propagate semExpr flags in macro/template expansion

This commit is contained in:
Zahary Karadjov 2014-04-06 16:55:16 +03:00
commit f6f5c9e9e6
5 changed files with 27 additions and 23 deletions

View file

@ -161,12 +161,13 @@ proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
localError(typ.n.info, errXisNoType, typeToString(typ)) localError(typ.n.info, errXisNoType, typeToString(typ))
proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode
proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
proc isOpImpl(c: PContext, n: PNode): PNode proc isOpImpl(c: PContext, n: PNode): PNode
proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
flags: TExprFlags = {}): PNode
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
semCheck: bool = true): PNode flags: TExprFlags = {}): PNode
proc symFromType(t: PType, info: TLineInfo): PSym = proc symFromType(t: PType, info: TLineInfo): PSym =
if t.sym != nil: return t.sym if t.sym != nil: return t.sym
@ -265,7 +266,8 @@ proc semConstExpr(c: PContext, n: PNode): PNode =
include hlo, seminst, semcall include hlo, seminst, semcall
proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode = proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
flags: TExprFlags): PNode =
inc(evalTemplateCounter) inc(evalTemplateCounter)
if evalTemplateCounter > 100: if evalTemplateCounter > 100:
globalError(s.info, errTemplateInstantiationTooNested) globalError(s.info, errTemplateInstantiationTooNested)
@ -281,7 +283,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
# BUGFIX: we cannot expect a type here, because module aliases would not # BUGFIX: we cannot expect a type here, because module aliases would not
# work then (see the ``tmodulealias`` test) # work then (see the ``tmodulealias`` test)
# semExprWithType(c, result) # semExprWithType(c, result)
result = semExpr(c, result) result = semExpr(c, result, flags)
of tyStmt: of tyStmt:
result = semStmt(c, result) result = semStmt(c, result)
of tyTypeDesc: of tyTypeDesc:
@ -290,14 +292,14 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
result.typ = makeTypeDesc(c, typ) result.typ = makeTypeDesc(c, typ)
#result = symNodeFromType(c, typ, n.info) #result = symNodeFromType(c, typ, n.info)
else: else:
result = semExpr(c, result) result = semExpr(c, result, flags)
result = fitNode(c, s.typ.sons[0], result) result = fitNode(c, s.typ.sons[0], result)
#GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0])) #GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
dec(evalTemplateCounter) dec(evalTemplateCounter)
c.friendModule = oldFriend c.friendModule = oldFriend
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym, proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
semCheck: bool = true): PNode = flags: TExprFlags = {}): PNode =
markUsed(n, sym) markUsed(n, sym)
if sym == c.p.owner: if sym == c.p.owner:
globalError(n.info, errRecursiveDependencyX, sym.name.s) globalError(n.info, errRecursiveDependencyX, sym.name.s)
@ -306,7 +308,8 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
# c.evalContext = c.createEvalContext(emStatic) # c.evalContext = c.createEvalContext(emStatic)
result = evalMacroCall(c.module, n, nOrig, sym) result = evalMacroCall(c.module, n, nOrig, sym)
if semCheck: result = semAfterMacroCall(c, result, sym) if efNoSemCheck notin flags:
result = semAfterMacroCall(c, result, sym, flags)
proc forceBool(c: PContext, n: PNode): PNode = proc forceBool(c: PContext, n: PNode): PNode =
result = fitNode(c, getSysType(tyBool), n) result = fitNode(c, getSysType(tyBool), n)

View file

@ -42,7 +42,7 @@ type
TExprFlag* = enum TExprFlag* = enum
efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType, efLValue, efWantIterator, efInTypeof, efWantStmt, efDetermineType,
efAllowDestructor, efWantValue, efOperand efAllowDestructor, efWantValue, efOperand, efNoSemCheck
TExprFlags* = set[TExprFlag] TExprFlags* = set[TExprFlag]
PContext* = ref TContext PContext* = ref TContext

View file

@ -10,11 +10,12 @@
# this module does the semantic checking for expressions # this module does the semantic checking for expressions
# included from sem.nim # included from sem.nim
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode = proc semTemplateExpr(c: PContext, n: PNode, s: PSym,
flags: TExprFlags = {}): PNode =
markUsed(n, s) markUsed(n, s)
pushInfoContext(n.info) pushInfoContext(n.info)
result = evalTemplate(n, s, getCurrOwner()) result = evalTemplate(n, s, getCurrOwner())
if semCheck: result = semAfterMacroCall(c, result, s) if efNoSemCheck notin flags: result = semAfterMacroCall(c, result, s, flags)
popInfoContext() popInfoContext()
proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
@ -95,8 +96,8 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
else: result = newSymNode(s, n.info) else: result = newSymNode(s, n.info)
else: else:
result = newSymNode(s, n.info) result = newSymNode(s, n.info)
of skMacro: result = semMacroExpr(c, n, n, s) of skMacro: result = semMacroExpr(c, n, n, s, flags)
of skTemplate: result = semTemplateExpr(c, n, s) of skTemplate: result = semTemplateExpr(c, n, s, flags)
of skVar, skLet, skResult, skParam, skForVar: of skVar, skLet, skResult, skParam, skForVar:
markUsed(n, s) markUsed(n, s)
# if a proc accesses a global variable, it is not side effect free: # if a proc accesses a global variable, it is not side effect free:
@ -793,8 +794,8 @@ proc afterCallActions(c: PContext; n, orig: PNode, flags: TExprFlags): PNode =
result = n result = n
let callee = result.sons[0].sym let callee = result.sons[0].sym
case callee.kind case callee.kind
of skMacro: result = semMacroExpr(c, result, orig, callee) of skMacro: result = semMacroExpr(c, result, orig, callee, flags)
of skTemplate: result = semTemplateExpr(c, result, callee) of skTemplate: result = semTemplateExpr(c, result, callee, flags)
else: else:
semFinishOperands(c, result) semFinishOperands(c, result)
activate(c, result) activate(c, result)
@ -1966,13 +1967,13 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
result = semDirectOp(c, n, flags) result = semDirectOp(c, n, flags)
else: else:
var p = fixImmediateParams(n) var p = fixImmediateParams(n)
result = semMacroExpr(c, p, p, s) result = semMacroExpr(c, p, p, s, flags)
of skTemplate: of skTemplate:
if sfImmediate notin s.flags: if sfImmediate notin s.flags:
result = semDirectOp(c, n, flags) result = semDirectOp(c, n, flags)
else: else:
var p = fixImmediateParams(n) var p = fixImmediateParams(n)
result = semTemplateExpr(c, p, s) result = semTemplateExpr(c, p, s, flags)
of skType: of skType:
# XXX think about this more (``set`` procs) # XXX think about this more (``set`` procs)
if n.len == 2: if n.len == 2:

View file

@ -47,12 +47,12 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
of skTemplate: of skTemplate:
if macroToExpand(s): if macroToExpand(s):
let n = fixImmediateParams(n) let n = fixImmediateParams(n)
result = semTemplateExpr(c, n, s, false) result = semTemplateExpr(c, n, s, {efNoSemCheck})
else: else:
result = symChoice(c, n, s, scOpen) result = symChoice(c, n, s, scOpen)
of skMacro: of skMacro:
if macroToExpand(s): if macroToExpand(s):
result = semMacroExpr(c, n, n, s, false) result = semMacroExpr(c, n, n, s, {efNoSemCheck})
else: else:
result = symChoice(c, n, s, scOpen) result = symChoice(c, n, s, scOpen)
of skGenericParam: of skGenericParam:
@ -126,14 +126,14 @@ proc semGenericStmt(c: PContext, n: PNode,
case s.kind case s.kind
of skMacro: of skMacro:
if macroToExpand(s): if macroToExpand(s):
result = semMacroExpr(c, n, n, s, false) result = semMacroExpr(c, n, n, s, {efNoSemCheck})
else: else:
n.sons[0] = symChoice(c, n.sons[0], s, scOption) n.sons[0] = symChoice(c, n.sons[0], s, scOption)
result = n result = n
of skTemplate: of skTemplate:
if macroToExpand(s): if macroToExpand(s):
let n = fixImmediateParams(n) let n = fixImmediateParams(n)
result = semTemplateExpr(c, n, s, false) result = semTemplateExpr(c, n, s, {efNoSemCheck})
else: else:
n.sons[0] = symChoice(c, n.sons[0], s, scOption) n.sons[0] = symChoice(c, n.sons[0], s, scOption)
result = n result = n

View file

@ -539,7 +539,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
elif contains(c.toBind, s.id): elif contains(c.toBind, s.id):
result = symChoice(c.c, n, s, scClosed) result = symChoice(c.c, n, s, scClosed)
elif templToExpand(s): elif templToExpand(s):
result = semPatternBody(c, semTemplateExpr(c.c, n, s, false)) result = semPatternBody(c, semTemplateExpr(c.c, n, s, {efNoSemCheck}))
else: else:
discard discard
# we keep the ident unbound for matching instantiated symbols and # we keep the ident unbound for matching instantiated symbols and
@ -584,7 +584,7 @@ proc semPatternBody(c: var TemplCtx, n: PNode): PNode =
if s.owner == c.owner and s.kind == skParam: discard if s.owner == c.owner and s.kind == skParam: discard
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, false)) 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