summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ast.nim2
-rwxr-xr-xcompiler/evals.nim44
-rwxr-xr-xcompiler/renderer.nim2
-rwxr-xr-xcompiler/sem.nim6
-rwxr-xr-xcompiler/semexprs.nim15
-rwxr-xr-xcompiler/semgnrc.nim4
-rwxr-xr-xcompiler/semstmts.nim3
-rwxr-xr-xcompiler/semtypes.nim8
8 files changed, 54 insertions, 30 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 79adafcf8..a8176501f 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -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
 
diff --git a/compiler/evals.nim b/compiler/evals.nim
index 4ec6cb4d7..bb0e5936d 100755
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -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)
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index c24a22fd5..b6b34287a 100755
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -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, "[")
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 34b6f1f78..d92c1657d 100755
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -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 = 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 06014bf6f..9219cacf6 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -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)
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index 849d04fb1..ea3eebc3a 100755
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -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
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index d12ad23cf..3a8424d9e 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -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)
   
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 5b6183005..8ec3c337c 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -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: