parameter passing works the same for macros and templates; use callsite magic to access the invokation AST
This commit is contained in:
parent
6bcdb9c8f4
commit
b4844a189d
16 changed files with 270 additions and 180 deletions
|
|
@ -441,7 +441,7 @@ type
|
|||
mNIntVal, mNFloatVal, mNSymbol, mNIdent, mNGetType, mNStrVal, mNSetIntVal,
|
||||
mNSetFloatVal, mNSetSymbol, mNSetIdent, mNSetType, mNSetStrVal, mNLineInfo,
|
||||
mNNewNimNode, mNCopyNimNode, mNCopyNimTree, mStrToIdent, mIdentToStr,
|
||||
mNBindSym,
|
||||
mNBindSym, mNCallSite,
|
||||
mEqIdent, mEqNimrodNode, mNHint, mNWarning, mNError,
|
||||
mInstantiationInfo, mGetTypeInfo
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ type
|
|||
module*: PSym
|
||||
tos*: PStackFrame # top of stack
|
||||
lastException*: PNode
|
||||
callsite: PNode # for 'callsite' magic
|
||||
mode*: TEvalMode
|
||||
globals*: TIdNodeTable # state of global vars
|
||||
|
||||
|
|
@ -74,7 +75,7 @@ proc popStackFrame*(c: PEvalContext) {.inline.} =
|
|||
if c.tos != nil: c.tos = c.tos.next
|
||||
else: InternalError("popStackFrame")
|
||||
|
||||
proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode
|
||||
proc evalMacroCall*(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode
|
||||
proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode
|
||||
|
||||
proc raiseCannotEval(c: PEvalContext, info: TLineInfo): PNode =
|
||||
|
|
@ -106,8 +107,11 @@ proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg = "") =
|
|||
proc isSpecial(n: PNode): bool {.inline.} =
|
||||
result = n.kind == nkExceptBranch
|
||||
|
||||
proc myreset(n: PNode) {.inline.} =
|
||||
when defined(system.reset): reset(n[])
|
||||
proc myreset(n: PNode) =
|
||||
when defined(system.reset):
|
||||
var oldInfo = n.info
|
||||
reset(n[])
|
||||
n.info = oldInfo
|
||||
|
||||
proc evalIf(c: PEvalContext, n: PNode): PNode =
|
||||
var i = 0
|
||||
|
|
@ -245,6 +249,11 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
|||
of tyObject:
|
||||
result = newNodeIT(nkPar, info, t)
|
||||
getNullValueAux(t.n, result)
|
||||
# initialize inherited fields:
|
||||
var base = t.sons[0]
|
||||
while base != nil:
|
||||
getNullValueAux(skipTypes(base, skipPtrs).n, result)
|
||||
base = base.sons[0]
|
||||
of tyArray, tyArrayConstr:
|
||||
result = newNodeIT(nkBracket, info, t)
|
||||
for i in countup(0, int(lengthOrd(t)) - 1):
|
||||
|
|
@ -925,7 +934,7 @@ proc evalExpandToAst(c: PEvalContext, original: PNode): PNode =
|
|||
# we want to replace it with nkIdent node featuring
|
||||
# the original unmangled macro name.
|
||||
macroCall.sons[0] = newIdentNode(expandedSym.name, expandedSym.info)
|
||||
result = evalMacroCall(c, macroCall, expandedSym)
|
||||
result = evalMacroCall(c, macroCall, original, expandedSym)
|
||||
else:
|
||||
InternalError(macroCall.info,
|
||||
"ExpandToAst: expanded symbol is no macro or template")
|
||||
|
|
@ -1166,10 +1175,13 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
|||
of mIdentToStr:
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
if result.kind != nkIdent: InternalError(n.info, "no ident node")
|
||||
var a = result
|
||||
result = newNodeIT(nkStrLit, n.info, n.typ)
|
||||
result.strVal = a.ident.s
|
||||
if a.kind == nkSym:
|
||||
result.strVal = a.sym.name.s
|
||||
else:
|
||||
if a.kind != nkIdent: InternalError(n.info, "no ident node")
|
||||
result.strVal = a.ident.s
|
||||
of mEqIdent:
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
|
|
@ -1226,6 +1238,9 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
|
|||
var a = result
|
||||
result = newNodeIT(nkStrLit, n.info, n.typ)
|
||||
result.strVal = newString(0)
|
||||
of mNCallSite:
|
||||
if c.callsite != nil: result = c.callsite
|
||||
else: stackTrace(c, n, errFieldXNotFound, "callsite")
|
||||
else:
|
||||
result = evalAux(c, n.sons[1], {})
|
||||
if isSpecial(result): return
|
||||
|
|
@ -1355,24 +1370,31 @@ proc evalConstExpr*(module: PSym, e: PNode): PNode =
|
|||
proc evalStaticExpr*(module: PSym, e: PNode): PNode =
|
||||
result = evalConstExprAux(module, e, emStatic)
|
||||
|
||||
proc evalMacroCall*(c: PEvalContext, n: PNode, sym: PSym): PNode =
|
||||
proc setupMacroParam(x: PNode): PNode =
|
||||
result = x
|
||||
if result.kind == nkHiddenStdConv: result = result.sons[1]
|
||||
|
||||
proc evalMacroCall(c: PEvalContext, n, nOrig: PNode, sym: PSym): PNode =
|
||||
# XXX GlobalError() is ugly here, but I don't know a better solution for now
|
||||
inc(evalTemplateCounter)
|
||||
if evalTemplateCounter > 100:
|
||||
if evalTemplateCounter > 100:
|
||||
GlobalError(n.info, errTemplateInstantiationTooNested)
|
||||
|
||||
#inc genSymBaseId
|
||||
c.callsite = nOrig
|
||||
var s = newStackFrame()
|
||||
s.call = n
|
||||
setlen(s.params, 2)
|
||||
setlen(s.params, n.len)
|
||||
# return value:
|
||||
s.params[0] = newNodeIT(nkNilLit, n.info, sym.typ.sons[0])
|
||||
s.params[1] = n
|
||||
# setup parameters:
|
||||
for i in 1 .. < n.len: s.params[i] = setupMacroParam(n.sons[i])
|
||||
pushStackFrame(c, s)
|
||||
discard eval(c, sym.getBody)
|
||||
result = s.params[0]
|
||||
popStackFrame(c)
|
||||
if cyclicTree(result): GlobalError(n.info, errCyclicTree)
|
||||
dec(evalTemplateCounter)
|
||||
c.callsite = nil
|
||||
|
||||
proc myOpen(module: PSym, filename: string): PPassContext =
|
||||
var c = newEvalContext(module, filename, emRepl)
|
||||
|
|
|
|||
|
|
@ -774,7 +774,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
|||
put(g, tkRStrLit, '\"' & replace(n[1].strVal, "\"", "\"\"") & '\"')
|
||||
else:
|
||||
gsub(g, n.sons[1])
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: gsub(g, n.sons[0])
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkHiddenCallConv: gsub(g, n.sons[1])
|
||||
of nkCast:
|
||||
put(g, tkCast, "cast")
|
||||
put(g, tkBracketLe, "[")
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ proc expectMacroOrTemplateCall(c: PContext, n: PNode): PSym
|
|||
|
||||
proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode
|
||||
|
||||
proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
|
||||
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||
semCheck: bool = true): PNode
|
||||
|
||||
proc semWhen(c: PContext, n: PNode, semCheck: bool = true): PNode
|
||||
|
|
@ -127,14 +127,14 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym): PNode =
|
|||
#GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
|
||||
dec(evalTemplateCounter)
|
||||
|
||||
proc semMacroExpr(c: PContext, n: PNode, sym: PSym,
|
||||
proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||
semCheck: bool = true): PNode =
|
||||
markUsed(n, sym)
|
||||
if sym == c.p.owner:
|
||||
GlobalError(n.info, errRecursiveDependencyX, sym.name.s)
|
||||
if c.evalContext == nil:
|
||||
c.evalContext = newEvalContext(c.module, "", emStatic)
|
||||
result = evalMacroCall(c.evalContext, n, sym)
|
||||
result = evalMacroCall(c.evalContext, n, nOrig, sym)
|
||||
if semCheck: result = semAfterMacroCall(c, result, sym)
|
||||
|
||||
proc forceBool(c: PContext, n: PNode): PNode =
|
||||
|
|
|
|||
|
|
@ -98,7 +98,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
|
|||
else: result = newSymNode(s, n.info)
|
||||
else:
|
||||
result = newSymNode(s, n.info)
|
||||
of skMacro: result = semMacroExpr(c, n, s)
|
||||
of skMacro: result = semMacroExpr(c, n, n, s)
|
||||
of skTemplate: result = semTemplateExpr(c, n, s)
|
||||
of skVar, skLet, skResult, skParam, skForVar:
|
||||
markUsed(n, s)
|
||||
|
|
@ -705,7 +705,7 @@ proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
|
|||
return errorNode(c, n)
|
||||
let callee = result.sons[0].sym
|
||||
case callee.kind
|
||||
of skMacro: result = semMacroExpr(c, nOrig, callee)
|
||||
of skMacro: result = semMacroExpr(c, result, nOrig, callee)
|
||||
of skTemplate: result = semTemplateExpr(c, nOrig, callee)
|
||||
else:
|
||||
fixAbstractType(c, result)
|
||||
|
|
@ -1398,7 +1398,8 @@ proc semBlockExpr(c: PContext, n: PNode): PNode =
|
|||
closeScope(c.tab)
|
||||
Dec(c.p.nestedBlockCounter)
|
||||
|
||||
proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
|
||||
# XXX why no overloading here?
|
||||
checkMinSonsLen(n, 2)
|
||||
var a: PNode
|
||||
if isCallExpr(n.sons[0]): a = n.sons[0].sons[0]
|
||||
|
|
@ -1407,7 +1408,7 @@ proc semMacroStmt(c: PContext, n: PNode, semCheck = true): PNode =
|
|||
if s != nil:
|
||||
case s.kind
|
||||
of skMacro:
|
||||
result = semMacroExpr(c, n, s, semCheck)
|
||||
result = semMacroExpr(c, n, n, s, semCheck)
|
||||
of skTemplate:
|
||||
# transform
|
||||
# nkMacroStmt(nkCall(a...), stmt, b...)
|
||||
|
|
@ -1499,16 +1500,16 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
|||
if s != nil:
|
||||
case s.kind
|
||||
of skMacro:
|
||||
if false and sfImmediate notin s.flags: # XXX not yet enabled
|
||||
if sfImmediate notin s.flags:
|
||||
result = semDirectOp(c, n, flags)
|
||||
else:
|
||||
result = semMacroExpr(c, n, s)
|
||||
result = semMacroExpr(c, n, n, s)
|
||||
of skTemplate:
|
||||
if sfImmediate notin s.flags:
|
||||
result = semDirectOp(c, n, flags)
|
||||
else:
|
||||
result = semTemplateExpr(c, n, s)
|
||||
of skType:
|
||||
of skType:
|
||||
# XXX think about this more (``set`` procs)
|
||||
if n.len == 2:
|
||||
result = semConv(c, n, s)
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
|
|||
of skTemplate:
|
||||
result = semTemplateExpr(c, n, s, false)
|
||||
of skMacro:
|
||||
result = semMacroExpr(c, n, s, false)
|
||||
result = semMacroExpr(c, n, n, s, false)
|
||||
of skGenericParam:
|
||||
result = newSymNode(s, n.info)
|
||||
of skParam:
|
||||
|
|
@ -97,7 +97,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
|||
incl(s.flags, sfUsed)
|
||||
case s.kind
|
||||
of skMacro:
|
||||
result = semMacroExpr(c, n, s, false)
|
||||
result = semMacroExpr(c, n, n, s, false)
|
||||
of skTemplate:
|
||||
result = semTemplateExpr(c, n, s, false)
|
||||
# BUGFIX: we must not return here, we need to do first phase of
|
||||
|
|
|
|||
|
|
@ -892,13 +892,10 @@ proc semConverterDef(c: PContext, n: PNode): PNode =
|
|||
|
||||
proc semMacroDef(c: PContext, n: PNode): PNode =
|
||||
checkSonsLen(n, bodyPos + 1)
|
||||
if n.sons[genericParamsPos].kind != nkEmpty:
|
||||
LocalError(n.info, errNoGenericParamsAllowedForX, "macro")
|
||||
result = semProcAux(c, n, skMacro, macroPragmas)
|
||||
var s = result.sons[namePos].sym
|
||||
var t = s.typ
|
||||
if t.sons[0] == nil: LocalError(n.info, errXNeedsReturnType, "macro")
|
||||
if sonsLen(t) != 2: LocalError(n.info, errXRequiresOneArgument, "macro")
|
||||
if n.sons[bodyPos].kind == nkEmpty:
|
||||
LocalError(n.info, errImplOfXexpected, s.name.s)
|
||||
|
||||
|
|
|
|||
|
|
@ -237,9 +237,11 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
|
|||
return errorSym(c, n)
|
||||
if result.typ.kind != tyGenericParam:
|
||||
# XXX get rid of this hack!
|
||||
var oldInfo = n.info
|
||||
reset(n[])
|
||||
n.kind = nkSym
|
||||
n.sym = result
|
||||
n.info = oldInfo
|
||||
else:
|
||||
LocalError(n.info, errIdentifierExpected)
|
||||
result = errorSym(c, n)
|
||||
|
|
@ -549,7 +551,9 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
|
|||
incl(result.flags, tfFinal)
|
||||
|
||||
proc addParamOrResult(c: PContext, param: PSym, kind: TSymKind) =
|
||||
if kind == skMacro and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
|
||||
if kind == skMacro:
|
||||
# within a macro, every param has the type PNimrodNode!
|
||||
# and param.typ.kind in {tyTypeDesc, tyExpr, tyStmt}:
|
||||
let nn = getSysSym"PNimrodNode"
|
||||
var a = copySym(param)
|
||||
a.typ = nn.typ
|
||||
|
|
@ -779,7 +783,7 @@ proc semTypeFromMacro(c: PContext, n: PNode): PType =
|
|||
markUsed(n, sym)
|
||||
case sym.kind
|
||||
of skMacro:
|
||||
result = semTypeNode(c, semMacroExpr(c, n, sym), nil)
|
||||
result = semTypeNode(c, semMacroExpr(c, n, n, sym), nil)
|
||||
of skTemplate:
|
||||
result = semTypeNode(c, semTemplateExpr(c, n, sym), nil)
|
||||
else:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue