forked from nim-lang/Nim
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
getType now works with tyInferred (arising from concepts); refs nim-l…
…ang#18220 (nim-lang#18241) * getType now works with tyInferred (concepts); refs nim-lang#18220 * avoid cast * add more docs
- Loading branch information
1 parent
2ca6169
commit 897e50d
Showing
2 changed files
with
79 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,29 +1,85 @@ | ||
discard """ | ||
output: ''' | ||
(ObjectTy (Empty) (Sym "Model") (RecList (Sym "name") (Sym "password"))) | ||
(BracketExpr (Sym "typeDesc") (Sym "User")) | ||
''' | ||
""" | ||
import macros | ||
import std/macros | ||
import stdtest/testutils | ||
|
||
type | ||
Model = object of RootObj | ||
User = object of Model | ||
name : string | ||
password : string | ||
# getType | ||
|
||
macro testUser: string = | ||
result = newLit(User.getType.lispRepr) | ||
block: | ||
type | ||
Model = object of RootObj | ||
User = object of Model | ||
name : string | ||
password : string | ||
|
||
macro testGeneric(T: typedesc[Model]): string= | ||
result = newLit(T.getType.lispRepr) | ||
macro testUser: string = | ||
result = newLit(User.getType.lispRepr) | ||
|
||
echo testUser | ||
echo User.testGeneric | ||
macro testGeneric(T: typedesc[Model]): string= | ||
result = newLit(T.getType.lispRepr) | ||
|
||
macro assertVoid(e: typed): untyped = | ||
assert(getTypeInst(e).typeKind == ntyVoid) | ||
doAssert testUser == """(ObjectTy (Empty) (Sym "Model") (RecList (Sym "name") (Sym "password")))""" | ||
doAssert User.testGeneric == """(BracketExpr (Sym "typeDesc") (Sym "User"))""" | ||
|
||
proc voidProc() = discard | ||
macro assertVoid(e: typed): untyped = | ||
assert(getTypeInst(e).typeKind == ntyVoid) | ||
|
||
assertVoid voidProc() | ||
proc voidProc() = discard | ||
|
||
assertVoid voidProc() | ||
|
||
block: | ||
# refs #18220; not an actual solution (yet) but at least shows what's currently | ||
# possible | ||
|
||
type Callable1[R, T, U] = concept fn | ||
fn(default(T)) is R | ||
fn is U | ||
|
||
# note that typetraits.arity doesn't work | ||
macro arity(a: typed): int = | ||
# number of params | ||
# this is not production code! | ||
let a2 = a.getType[1] # this used to crash nim, with: `vmdeps.nim(292, 25) `false`` | ||
newLit a2.len - 1 | ||
|
||
type Callable2[R, T, U] = concept fn | ||
fn(default(T)) is R | ||
fn is U | ||
arity(U) == 2 | ||
|
||
proc map1[T, R, U](a: T, fn: Callable1[R, T, U]): R = | ||
let fn = U(fn) | ||
# `cast[U](fn)` would also work; | ||
# this is currently needed otherwise, sigmatch errors with: | ||
# Error: attempting to call routine: 'fn' | ||
# found 'fn' [param declared in tgettype.nim(53, 28)] | ||
# this can be fixed in future work | ||
fn(a) | ||
|
||
proc map2[T, R, U](a: T, fn: Callable2[R, T, U]): R = | ||
let fn = U(fn) | ||
fn(a) | ||
|
||
proc fn1(a: int, a2 = 'x'): string = $(a, a2, "fn1") | ||
proc fn2(a: int, a2 = "zoo"): string = $(a, a2, "fn2") | ||
proc fn3(a: int, a2 = "zoo2"): string = $(a, a2, "fn3") | ||
proc fn4(a: int): string {.inline.} = $(a, "fn4") | ||
proc fn5(a: int): string = $(a, "fn5") | ||
|
||
assertAll: | ||
# Callable1 | ||
1.map1(fn1) == """(1, 'x', "fn1")""" | ||
1.map1(fn2) == """(1, "zoo", "fn2")""" | ||
1.map1(fn3) == """(1, "zoo", "fn3")""" | ||
# fn3's optional param is not honored, because fn3 and fn2 yield same | ||
# generic instantiation; this is a caveat with this approach | ||
# There are several possible ways to improve things in future work. | ||
1.map1(fn4) == """(1, "fn4")""" | ||
1.map1(fn5) == """(1, "fn5")""" | ||
|
||
# Callable2; prevents passing procs with optional params to avoid above | ||
# mentioned caveat, but more restrictive | ||
not compiles(1.map2(fn1)) | ||
not compiles(1.map2(fn2)) | ||
not compiles(1.map2(fn3)) | ||
1.map2(fn4) == """(1, "fn4")""" | ||
1.map2(fn5) == """(1, "fn5")""" |