fixes #2390
This commit is contained in:
parent
765f274629
commit
bba551fd1c
1 changed files with 59 additions and 53 deletions
|
|
@ -10,17 +10,17 @@
|
||||||
# included from sem.nim
|
# included from sem.nim
|
||||||
|
|
||||||
discard """
|
discard """
|
||||||
hygienic templates:
|
hygienic templates:
|
||||||
|
|
||||||
template `||` (a, b: expr): expr =
|
template `||` (a, b: expr): expr =
|
||||||
let aa = a
|
let aa = a
|
||||||
if aa: aa else: b
|
if aa: aa else: b
|
||||||
|
|
||||||
var
|
var
|
||||||
a, b: T
|
a, b: T
|
||||||
|
|
||||||
a || b || a
|
a || b || a
|
||||||
|
|
||||||
Each evaluation context has to be different and we need to perform
|
Each evaluation context has to be different and we need to perform
|
||||||
some form of preliminary symbol lookup in template definitions. Hygiene is
|
some form of preliminary symbol lookup in template definitions. Hygiene is
|
||||||
a way to achieve lexical scoping at compile time.
|
a way to achieve lexical scoping at compile time.
|
||||||
|
|
@ -50,7 +50,7 @@ proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode =
|
||||||
o: TOverloadIter
|
o: TOverloadIter
|
||||||
var i = 0
|
var i = 0
|
||||||
a = initOverloadIter(o, c, n)
|
a = initOverloadIter(o, c, n)
|
||||||
while a != nil:
|
while a != nil:
|
||||||
a = nextOverloadIter(o, c, n)
|
a = nextOverloadIter(o, c, n)
|
||||||
inc(i)
|
inc(i)
|
||||||
if i > 1: break
|
if i > 1: break
|
||||||
|
|
@ -96,7 +96,7 @@ proc semMixinStmt(c: PContext, n: PNode, toMixin: var IntSet): PNode =
|
||||||
for i in 0 .. < n.len:
|
for i in 0 .. < n.len:
|
||||||
toMixin.incl(considerQuotedIdent(n.sons[i]).id)
|
toMixin.incl(considerQuotedIdent(n.sons[i]).id)
|
||||||
result = newNodeI(nkEmpty, n.info)
|
result = newNodeI(nkEmpty, n.info)
|
||||||
|
|
||||||
proc replaceIdentBySym(n: var PNode, s: PNode) =
|
proc replaceIdentBySym(n: var PNode, s: PNode) =
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkPostfix: replaceIdentBySym(n.sons[1], s)
|
of nkPostfix: replaceIdentBySym(n.sons[1], s)
|
||||||
|
|
@ -135,7 +135,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode
|
||||||
proc openScope(c: var TemplCtx) = openScope(c.c)
|
proc openScope(c: var TemplCtx) = openScope(c.c)
|
||||||
proc closeScope(c: var TemplCtx) = closeScope(c.c)
|
proc closeScope(c: var TemplCtx) = closeScope(c.c)
|
||||||
|
|
||||||
proc semTemplBodyScope(c: var TemplCtx, n: PNode): PNode =
|
proc semTemplBodyScope(c: var TemplCtx, n: PNode): PNode =
|
||||||
openScope(c)
|
openScope(c)
|
||||||
result = semTemplBody(c, n)
|
result = semTemplBody(c, n)
|
||||||
closeScope(c)
|
closeScope(c)
|
||||||
|
|
@ -191,24 +191,24 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
|
||||||
else:
|
else:
|
||||||
replaceIdentBySym(n, ident)
|
replaceIdentBySym(n, ident)
|
||||||
|
|
||||||
proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode =
|
proc semTemplSymbol(c: PContext, n: PNode, s: PSym): PNode =
|
||||||
incl(s.flags, sfUsed)
|
incl(s.flags, sfUsed)
|
||||||
# we do not call styleCheckUse here, as the identifier is not really
|
# we do not call styleCheckUse here, as the identifier is not really
|
||||||
# resolved here. We will fixup the used identifiers later.
|
# resolved here. We will fixup the used identifiers later.
|
||||||
case s.kind
|
case s.kind
|
||||||
of skUnknown:
|
of skUnknown:
|
||||||
# Introduced in this pass! Leave it as an identifier.
|
# Introduced in this pass! Leave it as an identifier.
|
||||||
result = n
|
result = n
|
||||||
of OverloadableSyms:
|
of OverloadableSyms:
|
||||||
result = symChoice(c, n, s, scOpen)
|
result = symChoice(c, n, s, scOpen)
|
||||||
of skGenericParam:
|
of skGenericParam:
|
||||||
result = newSymNodeTypeDesc(s, n.info)
|
result = newSymNodeTypeDesc(s, n.info)
|
||||||
of skParam:
|
of skParam:
|
||||||
result = n
|
result = n
|
||||||
of skType:
|
of skType:
|
||||||
if (s.typ != nil) and (s.typ.kind != tyGenericParam):
|
if (s.typ != nil) and (s.typ.kind != tyGenericParam):
|
||||||
result = newSymNodeTypeDesc(s, n.info)
|
result = newSymNodeTypeDesc(s, n.info)
|
||||||
else:
|
else:
|
||||||
result = n
|
result = n
|
||||||
else:
|
else:
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
|
|
@ -305,21 +305,21 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
n.sons[i] = semTemplBodyScope(c, it)
|
n.sons[i] = semTemplBodyScope(c, it)
|
||||||
of nkWhileStmt:
|
of nkWhileStmt:
|
||||||
openScope(c)
|
openScope(c)
|
||||||
for i in countup(0, sonsLen(n)-1):
|
for i in countup(0, sonsLen(n)-1):
|
||||||
n.sons[i] = semTemplBody(c, n.sons[i])
|
n.sons[i] = semTemplBody(c, n.sons[i])
|
||||||
closeScope(c)
|
closeScope(c)
|
||||||
of nkCaseStmt:
|
of nkCaseStmt:
|
||||||
openScope(c)
|
openScope(c)
|
||||||
n.sons[0] = semTemplBody(c, n.sons[0])
|
n.sons[0] = semTemplBody(c, n.sons[0])
|
||||||
for i in countup(1, sonsLen(n)-1):
|
for i in countup(1, sonsLen(n)-1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
checkMinSonsLen(a, 1)
|
checkMinSonsLen(a, 1)
|
||||||
var L = sonsLen(a)
|
var L = sonsLen(a)
|
||||||
for j in countup(0, L-2):
|
for j in countup(0, L-2):
|
||||||
a.sons[j] = semTemplBody(c, a.sons[j])
|
a.sons[j] = semTemplBody(c, a.sons[j])
|
||||||
a.sons[L-1] = semTemplBodyScope(c, a.sons[L-1])
|
a.sons[L-1] = semTemplBodyScope(c, a.sons[L-1])
|
||||||
closeScope(c)
|
closeScope(c)
|
||||||
of nkForStmt, nkParForStmt:
|
of nkForStmt, nkParForStmt:
|
||||||
var L = sonsLen(n)
|
var L = sonsLen(n)
|
||||||
openScope(c)
|
openScope(c)
|
||||||
n.sons[L-2] = semTemplBody(c, n.sons[L-2])
|
n.sons[L-2] = semTemplBody(c, n.sons[L-2])
|
||||||
|
|
@ -338,14 +338,14 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
n.sons[0] = newSymNode(s, n.sons[0].info)
|
n.sons[0] = newSymNode(s, n.sons[0].info)
|
||||||
n.sons[1] = semTemplBody(c, n.sons[1])
|
n.sons[1] = semTemplBody(c, n.sons[1])
|
||||||
closeScope(c)
|
closeScope(c)
|
||||||
of nkTryStmt:
|
of nkTryStmt:
|
||||||
checkMinSonsLen(n, 2)
|
checkMinSonsLen(n, 2)
|
||||||
n.sons[0] = semTemplBodyScope(c, n.sons[0])
|
n.sons[0] = semTemplBodyScope(c, n.sons[0])
|
||||||
for i in countup(1, sonsLen(n)-1):
|
for i in countup(1, sonsLen(n)-1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
checkMinSonsLen(a, 1)
|
checkMinSonsLen(a, 1)
|
||||||
var L = sonsLen(a)
|
var L = sonsLen(a)
|
||||||
for j in countup(0, L-2):
|
for j in countup(0, L-2):
|
||||||
a.sons[j] = semTemplBody(c, a.sons[j])
|
a.sons[j] = semTemplBody(c, a.sons[j])
|
||||||
a.sons[L-1] = semTemplBodyScope(c, a.sons[L-1])
|
a.sons[L-1] = semTemplBodyScope(c, a.sons[L-1])
|
||||||
of nkVarSection: semTemplSomeDecl(c, n, skVar)
|
of nkVarSection: semTemplSomeDecl(c, n, skVar)
|
||||||
|
|
@ -355,32 +355,32 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
n.sons[0] = semTemplBody(c, n.sons[0])
|
n.sons[0] = semTemplBody(c, n.sons[0])
|
||||||
semTemplSomeDecl(c, n, skParam, 1)
|
semTemplSomeDecl(c, n, skParam, 1)
|
||||||
of nkConstSection:
|
of nkConstSection:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
if a.kind == nkCommentStmt: continue
|
if a.kind == nkCommentStmt: continue
|
||||||
if (a.kind != nkConstDef): illFormedAst(a)
|
if (a.kind != nkConstDef): illFormedAst(a)
|
||||||
checkSonsLen(a, 3)
|
checkSonsLen(a, 3)
|
||||||
addLocalDecl(c, a.sons[0], skConst)
|
addLocalDecl(c, a.sons[0], skConst)
|
||||||
a.sons[1] = semTemplBody(c, a.sons[1])
|
a.sons[1] = semTemplBody(c, a.sons[1])
|
||||||
a.sons[2] = semTemplBody(c, a.sons[2])
|
a.sons[2] = semTemplBody(c, a.sons[2])
|
||||||
of nkTypeSection:
|
of nkTypeSection:
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
if a.kind == nkCommentStmt: continue
|
if a.kind == nkCommentStmt: continue
|
||||||
if (a.kind != nkTypeDef): illFormedAst(a)
|
if (a.kind != nkTypeDef): illFormedAst(a)
|
||||||
checkSonsLen(a, 3)
|
checkSonsLen(a, 3)
|
||||||
addLocalDecl(c, a.sons[0], skType)
|
addLocalDecl(c, a.sons[0], skType)
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
var a = n.sons[i]
|
var a = n.sons[i]
|
||||||
if a.kind == nkCommentStmt: continue
|
if a.kind == nkCommentStmt: continue
|
||||||
if (a.kind != nkTypeDef): illFormedAst(a)
|
if (a.kind != nkTypeDef): illFormedAst(a)
|
||||||
checkSonsLen(a, 3)
|
checkSonsLen(a, 3)
|
||||||
if a.sons[1].kind != nkEmpty:
|
if a.sons[1].kind != nkEmpty:
|
||||||
openScope(c)
|
openScope(c)
|
||||||
a.sons[1] = semTemplBody(c, a.sons[1])
|
a.sons[1] = semTemplBody(c, a.sons[1])
|
||||||
a.sons[2] = semTemplBody(c, a.sons[2])
|
a.sons[2] = semTemplBody(c, a.sons[2])
|
||||||
closeScope(c)
|
closeScope(c)
|
||||||
else:
|
else:
|
||||||
a.sons[2] = semTemplBody(c, a.sons[2])
|
a.sons[2] = semTemplBody(c, a.sons[2])
|
||||||
of nkProcDef, nkLambdaKinds:
|
of nkProcDef, nkLambdaKinds:
|
||||||
result = semRoutineInTemplBody(c, n, skProc)
|
result = semRoutineInTemplBody(c, n, skProc)
|
||||||
|
|
@ -408,7 +408,13 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
if n.kind == nkDotExpr or n.kind == nkAccQuoted:
|
if n.kind == nkDotExpr or n.kind == nkAccQuoted:
|
||||||
let s = qualifiedLookUp(c.c, n, {})
|
let s = qualifiedLookUp(c.c, n, {})
|
||||||
if s != nil:
|
if s != nil:
|
||||||
if contains(c.toBind, s.id):
|
# do not symchoice a quoted template parameter (bug #2390):
|
||||||
|
if s.owner == c.owner and s.kind == skParam and
|
||||||
|
n.kind == nkAccQuoted and n.len == 1:
|
||||||
|
incl(s.flags, sfUsed)
|
||||||
|
styleCheckUse(n.info, s)
|
||||||
|
return newSymNode(s, n.info)
|
||||||
|
elif contains(c.toBind, s.id):
|
||||||
return symChoice(c.c, n, s, scClosed)
|
return symChoice(c.c, n, s, scClosed)
|
||||||
elif contains(c.toMixin, s.name.id):
|
elif contains(c.toMixin, s.name.id):
|
||||||
return symChoice(c.c, n, s, scForceOpen)
|
return symChoice(c.c, n, s, scForceOpen)
|
||||||
|
|
@ -445,31 +451,31 @@ proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
|
||||||
result = n
|
result = n
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
result.sons[i] = semTemplBodyDirty(c, n.sons[i])
|
result.sons[i] = semTemplBodyDirty(c, n.sons[i])
|
||||||
|
|
||||||
proc transformToExpr(n: PNode): PNode =
|
proc transformToExpr(n: PNode): PNode =
|
||||||
var realStmt: int
|
var realStmt: int
|
||||||
result = n
|
result = n
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkStmtList:
|
of nkStmtList:
|
||||||
realStmt = - 1
|
realStmt = - 1
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
case n.sons[i].kind
|
case n.sons[i].kind
|
||||||
of nkCommentStmt, nkEmpty, nkNilLit:
|
of nkCommentStmt, nkEmpty, nkNilLit:
|
||||||
discard
|
discard
|
||||||
else:
|
else:
|
||||||
if realStmt == - 1: realStmt = i
|
if realStmt == - 1: realStmt = i
|
||||||
else: realStmt = - 2
|
else: realStmt = - 2
|
||||||
if realStmt >= 0: result = transformToExpr(n.sons[realStmt])
|
if realStmt >= 0: result = transformToExpr(n.sons[realStmt])
|
||||||
else: n.kind = nkStmtListExpr
|
else: n.kind = nkStmtListExpr
|
||||||
of nkBlockStmt:
|
of nkBlockStmt:
|
||||||
n.kind = nkBlockExpr
|
n.kind = nkBlockExpr
|
||||||
#nkIfStmt: n.kind = nkIfExpr // this is not correct!
|
#nkIfStmt: n.kind = nkIfExpr // this is not correct!
|
||||||
else:
|
else:
|
||||||
discard
|
discard
|
||||||
|
|
||||||
proc semTemplateDef(c: PContext, n: PNode): PNode =
|
proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||||
var s: PSym
|
var s: PSym
|
||||||
if c.p.owner.kind == skModule:
|
if c.p.owner.kind == skModule:
|
||||||
s = semIdentVis(c, skTemplate, n.sons[0], {sfExported})
|
s = semIdentVis(c, skTemplate, n.sons[0], {sfExported})
|
||||||
incl(s.flags, sfGlobal)
|
incl(s.flags, sfGlobal)
|
||||||
else:
|
else:
|
||||||
|
|
@ -484,10 +490,10 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||||
pragma(c, s, n.sons[pragmasPos], templatePragmas)
|
pragma(c, s, n.sons[pragmasPos], templatePragmas)
|
||||||
|
|
||||||
var gp: PNode
|
var gp: PNode
|
||||||
if n.sons[genericParamsPos].kind != nkEmpty:
|
if n.sons[genericParamsPos].kind != nkEmpty:
|
||||||
n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos])
|
n.sons[genericParamsPos] = semGenericParamList(c, n.sons[genericParamsPos])
|
||||||
gp = n.sons[genericParamsPos]
|
gp = n.sons[genericParamsPos]
|
||||||
else:
|
else:
|
||||||
gp = newNodeI(nkGenericParams, n.info)
|
gp = newNodeI(nkGenericParams, n.info)
|
||||||
# process parameters:
|
# process parameters:
|
||||||
if n.sons[paramsPos].kind != nkEmpty:
|
if n.sons[paramsPos].kind != nkEmpty:
|
||||||
|
|
@ -525,14 +531,14 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
n.sons[bodyPos] = semTemplBody(ctx, n.sons[bodyPos])
|
n.sons[bodyPos] = semTemplBody(ctx, n.sons[bodyPos])
|
||||||
if s.typ.sons[0].kind notin {tyStmt, tyTypeDesc}:
|
if s.typ.sons[0].kind notin {tyStmt, tyTypeDesc}:
|
||||||
n.sons[bodyPos] = transformToExpr(n.sons[bodyPos])
|
n.sons[bodyPos] = transformToExpr(n.sons[bodyPos])
|
||||||
# only parameters are resolved, no type checking is performed
|
# only parameters are resolved, no type checking is performed
|
||||||
semIdeForTemplateOrGeneric(c, n.sons[bodyPos], ctx.cursorInBody)
|
semIdeForTemplateOrGeneric(c, n.sons[bodyPos], ctx.cursorInBody)
|
||||||
closeScope(c)
|
closeScope(c)
|
||||||
popOwner()
|
popOwner()
|
||||||
s.ast = n
|
s.ast = n
|
||||||
result = n
|
result = n
|
||||||
if n.sons[bodyPos].kind == nkEmpty:
|
if n.sons[bodyPos].kind == nkEmpty:
|
||||||
localError(n.info, errImplOfXexpected, s.name.s)
|
localError(n.info, errImplOfXexpected, s.name.s)
|
||||||
var proto = searchForProc(c, c.currentScope, s)
|
var proto = searchForProc(c, c.currentScope, s)
|
||||||
if proto == nil:
|
if proto == nil:
|
||||||
|
|
@ -545,7 +551,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||||
proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
template templToExpand(s: expr): expr =
|
template templToExpand(s: expr): expr =
|
||||||
s.kind == skTemplate and (s.typ.len == 1 or sfImmediate in s.flags)
|
s.kind == skTemplate and (s.typ.len == 1 or sfImmediate in s.flags)
|
||||||
|
|
||||||
proc newParam(c: var TemplCtx, n: PNode, s: PSym): PNode =
|
proc newParam(c: var TemplCtx, n: PNode, s: PSym): PNode =
|
||||||
# the param added in the current scope is actually wrong here for
|
# the param added in the current scope is actually wrong here for
|
||||||
# macros because they have a shadowed param of type 'PNimNode' (see
|
# macros because they have a shadowed param of type 'PNimNode' (see
|
||||||
|
|
@ -556,7 +562,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
let x = c.owner.typ.n.sons[s.position+1].sym
|
let x = c.owner.typ.n.sons[s.position+1].sym
|
||||||
assert x.name == s.name
|
assert x.name == s.name
|
||||||
result = newSymNode(x, n.info)
|
result = newSymNode(x, n.info)
|
||||||
|
|
||||||
proc handleSym(c: var TemplCtx, n: PNode, s: PSym): PNode =
|
proc handleSym(c: var TemplCtx, n: PNode, s: PSym): PNode =
|
||||||
result = n
|
result = n
|
||||||
if s != nil:
|
if s != nil:
|
||||||
|
|
@ -570,7 +576,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
discard
|
discard
|
||||||
# we keep the ident unbound for matching instantiated symbols and
|
# we keep the ident unbound for matching instantiated symbols and
|
||||||
# more flexibility
|
# more flexibility
|
||||||
|
|
||||||
proc expectParam(c: var TemplCtx, n: PNode): PNode =
|
proc expectParam(c: var TemplCtx, n: PNode): PNode =
|
||||||
let s = qualifiedLookUp(c.c, n, {})
|
let s = qualifiedLookUp(c.c, n, {})
|
||||||
if s != nil and s.owner == c.owner and s.kind == skParam:
|
if s != nil and s.owner == c.owner and s.kind == skParam:
|
||||||
|
|
@ -578,7 +584,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
localError(n.info, errInvalidExpression)
|
localError(n.info, errInvalidExpression)
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
result = n
|
result = n
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkIdent:
|
of nkIdent:
|
||||||
|
|
@ -588,7 +594,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
result = semBindStmt(c.c, n, c.toBind)
|
result = semBindStmt(c.c, n, c.toBind)
|
||||||
of nkEmpty, nkSym..nkNilLit: discard
|
of nkEmpty, nkSym..nkNilLit: discard
|
||||||
of nkCurlyExpr:
|
of nkCurlyExpr:
|
||||||
# we support '(pattern){x}' to bind a subpattern to a parameter 'x';
|
# we support '(pattern){x}' to bind a subpattern to a parameter 'x';
|
||||||
# '(pattern){|x}' does the same but the matches will be gathered in 'x'
|
# '(pattern){|x}' does the same but the matches will be gathered in 'x'
|
||||||
if n.len != 2:
|
if n.len != 2:
|
||||||
localError(n.info, errInvalidExpression)
|
localError(n.info, errInvalidExpression)
|
||||||
|
|
@ -611,7 +617,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
elif contains(c.toBind, s.id): discard
|
elif contains(c.toBind, s.id): discard
|
||||||
elif templToExpand(s):
|
elif templToExpand(s):
|
||||||
return semPatternBody(c, semTemplateExpr(c.c, n, s, {efNoSemCheck}))
|
return semPatternBody(c, semTemplateExpr(c.c, n, s, {efNoSemCheck}))
|
||||||
|
|
||||||
if n.kind == nkInfix and n.sons[0].kind == nkIdent:
|
if n.kind == nkInfix and n.sons[0].kind == nkIdent:
|
||||||
# we interpret `*` and `|` only as pattern operators if they occur in
|
# we interpret `*` and `|` only as pattern operators if they occur in
|
||||||
# infix notation, so that '`*`(a, b)' can be used for verbatim matching:
|
# infix notation, so that '`*`(a, b)' can be used for verbatim matching:
|
||||||
|
|
@ -628,7 +634,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
result.sons[1] = semPatternBody(c, n.sons[1])
|
result.sons[1] = semPatternBody(c, n.sons[1])
|
||||||
result.sons[2] = semPatternBody(c, n.sons[2])
|
result.sons[2] = semPatternBody(c, n.sons[2])
|
||||||
return
|
return
|
||||||
|
|
||||||
if n.kind == nkPrefix and n.sons[0].kind == nkIdent:
|
if n.kind == nkPrefix and n.sons[0].kind == nkIdent:
|
||||||
let opr = n.sons[0]
|
let opr = n.sons[0]
|
||||||
if opr.ident.s == "~":
|
if opr.ident.s == "~":
|
||||||
|
|
@ -636,13 +642,13 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
result.sons[0] = opr
|
result.sons[0] = opr
|
||||||
result.sons[1] = semPatternBody(c, n.sons[1])
|
result.sons[1] = semPatternBody(c, n.sons[1])
|
||||||
return
|
return
|
||||||
|
|
||||||
for i in countup(0, sonsLen(n) - 1):
|
for i in countup(0, sonsLen(n) - 1):
|
||||||
result.sons[i] = semPatternBody(c, n.sons[i])
|
result.sons[i] = semPatternBody(c, n.sons[i])
|
||||||
else:
|
else:
|
||||||
# dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
|
# dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
|
||||||
# so we use the generic code for nkDotExpr too
|
# so we use the generic code for nkDotExpr too
|
||||||
case n.kind
|
case n.kind
|
||||||
of nkDotExpr, nkAccQuoted:
|
of nkDotExpr, nkAccQuoted:
|
||||||
let s = qualifiedLookUp(c.c, n, {})
|
let s = qualifiedLookUp(c.c, n, {})
|
||||||
if s != nil:
|
if s != nil:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue