Fix #4020; Better handling of templates within concepts

This commit is contained in:
Zahary Karadjov 2017-06-19 20:07:26 +03:00 • committed by Andreas Rumpf
commit 8f4b374327
5 changed files with 65 additions and 2 deletions

View file

@ -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

View file

@ -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)])

View file

@ -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)

View file

@ -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

View 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