parent
c2ba0ee144
commit
58bcf6cd46
6 changed files with 62 additions and 15 deletions
|
|
@ -228,7 +228,7 @@ type
|
||||||
TNodeKinds* = set[TNodeKind]
|
TNodeKinds* = set[TNodeKind]
|
||||||
|
|
||||||
type
|
type
|
||||||
TSymFlag* = enum # already 36 flags!
|
TSymFlag* = enum # already 38 flags!
|
||||||
sfUsed, # read access of sym (for warnings) or simply used
|
sfUsed, # read access of sym (for warnings) or simply used
|
||||||
sfExported, # symbol is exported from module
|
sfExported, # symbol is exported from module
|
||||||
sfFromGeneric, # symbol is instantiation of a generic; this is needed
|
sfFromGeneric, # symbol is instantiation of a generic; this is needed
|
||||||
|
|
@ -282,6 +282,7 @@ type
|
||||||
sfGeneratedOp # proc is a generated '='; do not inject destructors in it
|
sfGeneratedOp # proc is a generated '='; do not inject destructors in it
|
||||||
# variable is generated closure environment; requires early
|
# variable is generated closure environment; requires early
|
||||||
# destruction for --newruntime.
|
# destruction for --newruntime.
|
||||||
|
sfTemplateParam # symbol is a template parameter
|
||||||
|
|
||||||
|
|
||||||
TSymFlags* = set[TSymFlag]
|
TSymFlags* = set[TSymFlag]
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ proc evalTemplateAux(templ, actual: PNode, c: var TemplCtx, result: PNode) =
|
||||||
of nkSym:
|
of nkSym:
|
||||||
var s = templ.sym
|
var s = templ.sym
|
||||||
if (s.owner == nil and s.kind == skParam) or s.owner == c.owner:
|
if (s.owner == nil and s.kind == skParam) or s.owner == c.owner:
|
||||||
if s.kind == skParam and sfGenSym notin s.flags:
|
if s.kind == skParam and {sfGenSym, sfTemplateParam} * s.flags == {sfTemplateParam}:
|
||||||
handleParam actual.sons[s.position]
|
handleParam actual.sons[s.position]
|
||||||
elif (s.owner != nil) and (s.kind == skGenericParam or
|
elif (s.owner != nil) and (s.kind == skGenericParam or
|
||||||
s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam):
|
s.kind == skType and s.typ != nil and s.typ.kind == tyGenericParam):
|
||||||
|
|
|
||||||
|
|
@ -1896,7 +1896,6 @@ proc expectString(c: PContext, n: PNode): string =
|
||||||
|
|
||||||
proc newAnonSym(c: PContext; kind: TSymKind, info: TLineInfo): PSym =
|
proc newAnonSym(c: PContext; kind: TSymKind, info: TLineInfo): PSym =
|
||||||
result = newSym(kind, c.cache.idAnon, getCurrOwner(c), info)
|
result = newSym(kind, c.cache.idAnon, getCurrOwner(c), info)
|
||||||
result.flags = {sfGenSym}
|
|
||||||
|
|
||||||
proc semExpandToAst(c: PContext, n: PNode): PNode =
|
proc semExpandToAst(c: PContext, n: PNode): PNode =
|
||||||
let macroCall = n[1]
|
let macroCall = n[1]
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@ type
|
||||||
cursorInBody: bool # only for nimsuggest
|
cursorInBody: bool # only for nimsuggest
|
||||||
scopeN: int
|
scopeN: int
|
||||||
noGenSym: int
|
noGenSym: int
|
||||||
|
inTemplateHeader: int
|
||||||
|
|
||||||
template withBracketExpr(ctx, x, body: untyped) =
|
template withBracketExpr(ctx, x, body: untyped) =
|
||||||
body
|
body
|
||||||
|
|
@ -144,9 +145,12 @@ proc getIdentNode(c: var TemplCtx, n: PNode): PNode =
|
||||||
illFormedAst(n, c.c.config)
|
illFormedAst(n, c.c.config)
|
||||||
result = n
|
result = n
|
||||||
|
|
||||||
|
template oldCheck(cx: TemplCtx; cond: bool): bool =
|
||||||
|
(optNimV019 notin cx.c.config.globalOptions or cond)
|
||||||
|
|
||||||
proc isTemplParam(c: TemplCtx, n: PNode): bool {.inline.} =
|
proc isTemplParam(c: TemplCtx, n: PNode): bool {.inline.} =
|
||||||
result = n.kind == nkSym and n.sym.kind == skParam and
|
result = n.kind == nkSym and n.sym.kind == skParam and
|
||||||
n.sym.owner == c.owner and sfGenSym notin n.sym.flags
|
n.sym.owner == c.owner and sfTemplateParam in n.sym.flags
|
||||||
|
|
||||||
proc semTemplBody(c: var TemplCtx, n: PNode): PNode
|
proc semTemplBody(c: var TemplCtx, n: PNode): PNode
|
||||||
|
|
||||||
|
|
@ -231,6 +235,8 @@ proc addLocalDecl(c: var TemplCtx, n: var PNode, k: TSymKind) =
|
||||||
styleCheckDef(c.c.config, n.info, local)
|
styleCheckDef(c.c.config, n.info, local)
|
||||||
onDef(n.info, local)
|
onDef(n.info, local)
|
||||||
replaceIdentBySym(c.c, n, newSymNode(local, n.info))
|
replaceIdentBySym(c.c, n, newSymNode(local, n.info))
|
||||||
|
if k == skParam and c.inTemplateHeader > 0:
|
||||||
|
local.flags.incl sfTemplateParam
|
||||||
else:
|
else:
|
||||||
replaceIdentBySym(c.c, n, ident)
|
replaceIdentBySym(c.c, n, ident)
|
||||||
|
|
||||||
|
|
@ -288,7 +294,14 @@ proc semRoutineInTemplBody(c: var TemplCtx, n: PNode, k: TSymKind): PNode =
|
||||||
n.sons[namePos] = semRoutineInTemplName(c, n.sons[namePos])
|
n.sons[namePos] = semRoutineInTemplName(c, n.sons[namePos])
|
||||||
# open scope for parameters
|
# open scope for parameters
|
||||||
openScope(c)
|
openScope(c)
|
||||||
for i in patternPos..miscPos:
|
for i in patternPos..paramsPos-1:
|
||||||
|
n.sons[i] = semTemplBody(c, n.sons[i])
|
||||||
|
|
||||||
|
if k == skTemplate: inc(c.inTemplateHeader)
|
||||||
|
n.sons[paramsPos] = semTemplBody(c, n.sons[paramsPos])
|
||||||
|
if k == skTemplate: dec(c.inTemplateHeader)
|
||||||
|
|
||||||
|
for i in paramsPos+1..miscPos:
|
||||||
n.sons[i] = semTemplBody(c, n.sons[i])
|
n.sons[i] = semTemplBody(c, n.sons[i])
|
||||||
# open scope for locals
|
# open scope for locals
|
||||||
inc c.scopeN
|
inc c.scopeN
|
||||||
|
|
@ -331,8 +344,8 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
if n.ident.id in c.toInject: return n
|
if n.ident.id in c.toInject: return n
|
||||||
let s = qualifiedLookUp(c.c, n, {})
|
let s = qualifiedLookUp(c.c, n, {})
|
||||||
if s != nil:
|
if s != nil:
|
||||||
if s.owner == c.owner and s.kind == skParam and
|
if s.owner == c.owner and s.kind == skParam and sfTemplateParam in s.flags:
|
||||||
(sfGenSym notin s.flags or c.noGenSym == 0):
|
# oldCheck(c, sfGenSym notin s.flags or c.noGenSym == 0):
|
||||||
incl(s.flags, sfUsed)
|
incl(s.flags, sfUsed)
|
||||||
result = newSymNode(s, n.info)
|
result = newSymNode(s, n.info)
|
||||||
onUse(n.info, s)
|
onUse(n.info, s)
|
||||||
|
|
@ -542,16 +555,16 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||||
if n.kind == nkDotExpr:
|
if n.kind == nkDotExpr:
|
||||||
result = n
|
result = n
|
||||||
result.sons[0] = semTemplBody(c, n.sons[0])
|
result.sons[0] = semTemplBody(c, n.sons[0])
|
||||||
inc c.noGenSym
|
if optNimV019 notin c.c.config.globalOptions: inc c.noGenSym
|
||||||
result.sons[1] = semTemplBody(c, n.sons[1])
|
result.sons[1] = semTemplBody(c, n.sons[1])
|
||||||
dec c.noGenSym
|
if optNimV019 notin c.c.config.globalOptions: dec c.noGenSym
|
||||||
else:
|
else:
|
||||||
result = semTemplBodySons(c, n)
|
result = semTemplBodySons(c, n)
|
||||||
of nkExprColonExpr, nkExprEqExpr:
|
of nkExprColonExpr, nkExprEqExpr:
|
||||||
if n.len == 2:
|
if n.len == 2:
|
||||||
inc c.noGenSym
|
if optNimV019 notin c.c.config.globalOptions: inc c.noGenSym
|
||||||
result.sons[0] = semTemplBody(c, n.sons[0])
|
result.sons[0] = semTemplBody(c, n.sons[0])
|
||||||
dec c.noGenSym
|
if optNimV019 notin c.c.config.globalOptions: dec c.noGenSym
|
||||||
result.sons[1] = semTemplBody(c, n.sons[1])
|
result.sons[1] = semTemplBody(c, n.sons[1])
|
||||||
else:
|
else:
|
||||||
result = semTemplBodySons(c, n)
|
result = semTemplBodySons(c, n)
|
||||||
|
|
@ -625,6 +638,8 @@ proc semTemplateDef(c: PContext, n: PNode): PNode =
|
||||||
# body by the absence of the sfGenSym flag:
|
# body by the absence of the sfGenSym flag:
|
||||||
for i in 1 .. s.typ.n.len-1:
|
for i in 1 .. s.typ.n.len-1:
|
||||||
let param = s.typ.n.sons[i].sym
|
let param = s.typ.n.sons[i].sym
|
||||||
|
param.flags.incl sfTemplateParam
|
||||||
|
if optNimV019 in c.config.globalOptions:
|
||||||
param.flags.excl sfGenSym
|
param.flags.excl sfGenSym
|
||||||
if param.typ.kind != tyUntyped: allUntyped = false
|
if param.typ.kind != tyUntyped: allUntyped = false
|
||||||
if sonsLen(gp) > 0:
|
if sonsLen(gp) > 0:
|
||||||
|
|
|
||||||
|
|
@ -890,12 +890,13 @@ macro mkHandlerTplts(handlers: untyped): untyped =
|
||||||
# <handler code block>
|
# <handler code block>
|
||||||
# ...
|
# ...
|
||||||
proc mkEnter(hdName, body: NimNode): NimNode =
|
proc mkEnter(hdName, body: NimNode): NimNode =
|
||||||
quote do:
|
template helper(hdName, body) {.dirty.} =
|
||||||
template `hdName`(s, p, start) =
|
template hdName(s, p, start) =
|
||||||
let s {.inject.} = s
|
let s {.inject.} = s
|
||||||
let p {.inject.} = p
|
let p {.inject.} = p
|
||||||
let start {.inject.} = start
|
let start {.inject.} = start
|
||||||
`body`
|
body
|
||||||
|
result = getAst(helper(hdName, body))
|
||||||
|
|
||||||
template mkLeave(hdPostf, body) {.dirty.} =
|
template mkLeave(hdPostf, body) {.dirty.} =
|
||||||
# this has to be dirty to be able to capture *result* as *length* in
|
# this has to be dirty to be able to capture *result* as *length* in
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ wth
|
||||||
1
|
1
|
||||||
0
|
0
|
||||||
(total: 6)
|
(total: 6)
|
||||||
|
S1
|
||||||
'''
|
'''
|
||||||
"""
|
"""
|
||||||
# bug #1915
|
# bug #1915
|
||||||
|
|
@ -164,3 +165,33 @@ template baz(): untyped =
|
||||||
echo (total: bar2(3))
|
echo (total: bar2(3))
|
||||||
|
|
||||||
baz()
|
baz()
|
||||||
|
|
||||||
|
# bug #12121
|
||||||
|
macro state_machine_enum(states: varargs[untyped]) =
|
||||||
|
result = nnkTypeSection.newTree(
|
||||||
|
nnkTypeDef.newTree(
|
||||||
|
nnkPragmaExpr.newTree(ident("State"), nnkPragma.newTree(ident("pure"))),
|
||||||
|
newEmptyNode(),
|
||||||
|
nnkEnumTy.newTree(newEmptyNode())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
for s in states:
|
||||||
|
expectKind(s, nnkIdent)
|
||||||
|
result[0][2].add s
|
||||||
|
|
||||||
|
template mystate_machine(body: untyped) =
|
||||||
|
state_machine_enum(S1, S2, S3)
|
||||||
|
var state_stack: seq[State]
|
||||||
|
template state_current(): State {.inject, used.} =
|
||||||
|
state_stack[^1]
|
||||||
|
template state_push(state_name) {.inject, used.} =
|
||||||
|
state_stack.add State.state_name
|
||||||
|
template state_pop(n = 1) {.inject, used.} =
|
||||||
|
state_stack.setLen(state_stack.len - n)
|
||||||
|
body
|
||||||
|
|
||||||
|
mystate_machine:
|
||||||
|
state_push(S1)
|
||||||
|
echo state_current()
|
||||||
|
state_pop()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue