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
|
nfIsRef # this node is a 'ref' node; used for the VM
|
||||||
nfPreventCg # this node should be ignored by the codegen
|
nfPreventCg # this node should be ignored by the codegen
|
||||||
nfBlockArg # this a stmtlist appearing in a call (e.g. a do block)
|
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]
|
TNodeFlags* = set[TNodeFlag]
|
||||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: beyond that)
|
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: beyond that)
|
||||||
|
|
@ -956,7 +957,8 @@ const
|
||||||
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias}
|
skMacro, skTemplate, skConverter, skEnumField, skLet, skStub, skAlias}
|
||||||
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
|
PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16,
|
||||||
nfDotSetter, nfDotField,
|
nfDotSetter, nfDotField,
|
||||||
nfIsRef, nfPreventCg, nfLL}
|
nfIsRef, nfPreventCg, nfLL,
|
||||||
|
nfFromTemplate}
|
||||||
namePos* = 0
|
namePos* = 0
|
||||||
patternPos* = 1 # empty except for term rewriting macros
|
patternPos* = 1 # empty except for term rewriting macros
|
||||||
genericParamsPos* = 2
|
genericParamsPos* = 2
|
||||||
|
|
|
||||||
|
|
@ -407,6 +407,8 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int;
|
||||||
var istr = rspaces(indent + 2)
|
var istr = rspaces(indent + 2)
|
||||||
result = "{$N$1\"kind\": $2" %
|
result = "{$N$1\"kind\": $2" %
|
||||||
[istr, makeYamlString($n.kind)]
|
[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)])
|
addf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
|
||||||
if maxRecDepth != 0:
|
if maxRecDepth != 0:
|
||||||
addf(result, ",$N$1\"flags\": $2", [istr, rope($n.flags)])
|
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
|
#if ctx.instLines: result.info = n.info
|
||||||
for i in countup(0, safeLen(body) - 1):
|
for i in countup(0, safeLen(body) - 1):
|
||||||
evalTemplateAux(body.sons[i], args, ctx, result)
|
evalTemplateAux(body.sons[i], args, ctx, result)
|
||||||
|
result.flags.incl nfFromTemplate
|
||||||
result = wrapInComesFrom(n.info, result)
|
result = wrapInComesFrom(n.info, result)
|
||||||
dec(evalTemplateCounter)
|
dec(evalTemplateCounter)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1761,7 +1761,8 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
||||||
else:
|
else:
|
||||||
var expr = semExpr(c, n.sons[i], flags)
|
var expr = semExpr(c, n.sons[i], flags)
|
||||||
n.sons[i] = expr
|
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
|
case expr.typ.kind
|
||||||
of tyBool:
|
of tyBool:
|
||||||
if expr.kind == nkInfix and
|
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