Fix #4020; Better handling of templates within concepts
This commit is contained in:
parent
b199c5af4e
commit
8f4b374327
5 changed files with 65 additions and 2 deletions
|
|
@ -453,6 +453,7 @@ type
|
|||
nfIsRef # this node is a 'ref' node; used for the VM
|
||||
nfPreventCg # this node should be ignored by the codegen
|
||||
nfBlockArg # this a stmtlist appearing in a call (e.g. a do block)
|
||||
nfFromTemplate # a top-level node returned from a template
|
||||
|
||||
TNodeFlags* = set[TNodeFlag]
|
||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: beyond that)
|
||||
|
|
@ -956,7 +957,8 @@ const
|
|||
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias}
|
||||
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
|
||||
nfDotSetter, nfDotField,
|
||||
nfIsRef, nfPreventCg, nfLL}
|
||||
nfIsRef, nfPreventCg, nfLL,
|
||||
nfFromTemplate}
|
||||
namePos* = 0
|
||||
patternPos* = 1 # empty except for term rewriting macros
|
||||
genericParamsPos* = 2
|
||||
|
|
|
|||
|
|
@ -407,6 +407,8 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int;
|
|||
var istr = rspaces(indent + 2)
|
||||
result = "{$N$1\"kind\": $2" %
|
||||
[istr, makeYamlString($n.kind)]
|
||||
when defined(useNodeIds):
|
||||
addf(result, ",$N$1\"id\": $2", [istr, rope(n.id)])
|
||||
addf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
|
||||
if maxRecDepth != 0:
|
||||
addf(result, ",$N$1\"flags\": $2", [istr, rope($n.flags)])
|
||||
|
|
|
|||
|
|
@ -155,5 +155,7 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; fromHlo=false): PNode =
|
|||
#if ctx.instLines: result.info = n.info
|
||||
for i in countup(0, safeLen(body) - 1):
|
||||
evalTemplateAux(body.sons[i], args, ctx, result)
|
||||
result.flags.incl nfFromTemplate
|
||||
result = wrapInComesFrom(n.info, result)
|
||||
dec(evalTemplateCounter)
|
||||
|
||||
|
|
|
|||
|
|
@ -1761,7 +1761,8 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
else:
|
||||
var expr = semExpr(c, n.sons[i], flags)
|
||||
n.sons[i] = expr
|
||||
if c.matchedConcept != nil and expr.typ != nil:
|
||||
if c.matchedConcept != nil and expr.typ != nil and
|
||||
(nfFromTemplate notin n.flags or i != last):
|
||||
case expr.typ.kind
|
||||
of tyBool:
|
||||
if expr.kind == nkInfix and
|
||||
|
|
|
|||
56
tests/concepts/templatesinconcepts.nim
Normal file
56
tests/concepts/templatesinconcepts.nim
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import typetraits
|
||||
|
||||
template typeLen(x): int = x.type.name.len
|
||||
|
||||
template bunchOfChecks(x) =
|
||||
x.typeLen > 3
|
||||
x != 10 is bool
|
||||
|
||||
template stmtListExprTmpl(x: untyped): untyped =
|
||||
x is int
|
||||
x
|
||||
|
||||
type
|
||||
Obj = object
|
||||
x: int
|
||||
|
||||
Gen[T] = object
|
||||
x: T
|
||||
|
||||
Eq = concept x, y
|
||||
(x == y) is bool
|
||||
|
||||
NotEq = concept x, y
|
||||
(x != y) is bool
|
||||
|
||||
ConceptUsingTemplate1 = concept x
|
||||
echo x
|
||||
sizeof(x) is int
|
||||
bunchOfChecks x
|
||||
|
||||
ConceptUsingTemplate2 = concept x
|
||||
stmtListExprTmpl x
|
||||
|
||||
template ok(x) =
|
||||
static: assert(x)
|
||||
|
||||
template no(x) =
|
||||
static: assert(not(x))
|
||||
|
||||
ok int is Eq
|
||||
ok int is NotEq
|
||||
ok string is Eq
|
||||
ok string is NotEq
|
||||
ok Obj is Eq
|
||||
ok Obj is NotEq
|
||||
ok Gen[string] is Eq
|
||||
ok Gen[int] is NotEq
|
||||
|
||||
no int is ConceptUsingTemplate1
|
||||
ok float is ConceptUsingTemplate1
|
||||
no string is ConceptUsingTemplate1
|
||||
|
||||
ok int is ConceptUsingTemplate2
|
||||
no float is ConceptUsingTemplate2
|
||||
no string is ConceptUsingTemplate2
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue