mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-12 06:18:51 +00:00
* getType now works with tyInferred (concepts); refs #18220 * avoid cast * add more docs
This commit is contained in:
@@ -289,7 +289,7 @@ proc mapTypeToAstX(cache: IdentCache; t: PType; info: TLineInfo;
|
||||
of tyNot: result = mapTypeToBracket("not", mNot, t, info)
|
||||
of tyIterable: result = mapTypeToBracket("iterable", mIterableType, t, info)
|
||||
of tyAnything: result = atomicType("anything", mNone)
|
||||
of tyInferred: assert false
|
||||
of tyInferred: result = mapTypeToAstX(cache, t.lastSon, info, idgen, inst, allowRecursion)
|
||||
of tyStatic, tyFromExpr:
|
||||
if inst:
|
||||
if t.n != nil: result = t.n.copyTree
|
||||
|
||||
@@ -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")"""
|
||||
|
||||
Reference in New Issue
Block a user