summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorZahary Karadjov <zahary@gmail.com>2012-10-03 01:50:26 +0300
committerZahary Karadjov <zahary@gmail.com>2012-10-03 01:59:50 +0300
commit2e5265bef54ef260213a2ad6ec417f48571c2824 (patch)
treed15efa6aaa2d30f9484026a5ee7c238fd85fb32f /compiler
parent9c8bc3a244b4bbcdc56fdd255bb4e1a7ed30f781 (diff)
downloadNim-2e5265bef54ef260213a2ad6ec417f48571c2824.tar.gz
experimental support for querying the type of expressions within macros
normalised the line endings of macros.nim (minor edits otherwise)
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/evals.nim9
-rwxr-xr-xcompiler/sem.nim11
-rwxr-xr-xcompiler/semexprs.nim19
3 files changed, 29 insertions, 10 deletions
diff --git a/compiler/evals.nim b/compiler/evals.nim
index 0886b1ef5..226415815 100755
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -41,6 +41,7 @@ type
     callsite: PNode           # for 'callsite' magic
     mode*: TEvalMode
     globals*: TIdNodeTable    # state of global vars
+    getType*: proc(n: PNode): PNode
   
   PEvalContext* = ref TEvalContext
 
@@ -1091,7 +1092,10 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
     result = evalAux(c, n.sons[1], {})
     if isSpecial(result): return 
     if result.kind != nkIdent: stackTrace(c, n, errFieldXNotFound, "ident")
-  of mNGetType: result = evalAux(c, n.sons[1], {})
+  of mNGetType:
+    var ast = evalAux(c, n.sons[1], {})
+    InternalAssert c.getType != nil
+    result = c.getType(ast)
   of mNStrVal: 
     result = evalAux(c, n.sons[1], {})
     if isSpecial(result): return 
@@ -1152,7 +1156,8 @@ proc evalMagicOrCall(c: PEvalContext, n: PNode): PNode =
     var a = result
     result = evalAux(c, n.sons[2], {efLValue})
     if isSpecial(result): return 
-    a.typ = result.typ        # XXX: exception handling?
+    InternalAssert result.kind == nkSym and result.sym.kind == skType
+    a.typ = result.sym.typ
     result = emptyNode
   of mNSetStrVal:
     result = evalAux(c, n.sons[1], {efLValue})
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 397581f63..0a6159dfa 100755
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -43,6 +43,7 @@ proc addParams(c: PContext, n: PNode, kind: TSymKind)
 proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind)
 proc addResultNode(c: PContext, n: PNode)
 proc instGenericContainer(c: PContext, n: PNode, header: PType): PType
+proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
 
 proc typeMismatch(n: PNode, formal, actual: PType) = 
   if formal.kind != tyError and actual.kind != tyError: 
@@ -156,8 +157,18 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
   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)
+    c.evalContext.getType = proc (n: PNode): PNode =
+      var e = tryExpr(c, n)
+      if e == nil:
+        result = symNodeFromType(c, errorType(c), n.info)
+      elif e.typ == nil:
+        result = newSymNode(getSysSym"void")
+      else:
+        result = symNodeFromType(c, e.typ, n.info)
+
   result = evalMacroCall(c.evalContext, n, nOrig, sym)
   if semCheck: result = semAfterMacroCall(c, result, sym)
 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 51ede1614..e9dc5a8e9 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1237,12 +1237,7 @@ proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym,
   else:
     result = semDirectOp(c, n, flags)
 
-proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
-  # we replace this node by a 'true' or 'false' node:
-  if sonsLen(n) != 2: return semDirectOp(c, n, flags)
-  result = newIntNode(nkIntLit, 0)
-  result.info = n.info
-  result.typ = getSysType(tyBool)
+proc tryExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   # watch out, hacks ahead:
   let oldErrorCount = msgs.gErrorCounter
   let oldErrorMax = msgs.gErrorMax
@@ -1264,8 +1259,8 @@ proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
   let oldProcCon = c.p
   c.generics = newGenericsCache()
   try:
-    discard semExpr(c, n.sons[1])
-    result.intVal = ord(msgs.gErrorCounter == oldErrorCount)
+    result = semExpr(c, n, flags)
+    if msgs.gErrorCounter != oldErrorCount: result = nil
   except ERecoverableError:
     nil
   # undo symbol table changes (as far as it's possible):
@@ -1282,6 +1277,14 @@ proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
   msgs.gErrorCounter = oldErrorCount
   msgs.gErrorMax = oldErrorMax
 
+proc semCompiles(c: PContext, n: PNode, flags: TExprFlags): PNode =
+  # we replace this node by a 'true' or 'false' node:
+  if sonsLen(n) != 2: return semDirectOp(c, n, flags)
+  
+  result = newIntNode(nkIntLit, ord(tryExpr(c, n, flags) != nil))
+  result.info = n.info
+  result.typ = getSysType(tyBool)
+
 proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode =
   if sonsLen(n) == 3:
     # XXX ugh this is really a hack: shallowCopy() can be overloaded only