summary refs log tree commit diff stats
path: root/compiler/semexprs.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/semexprs.nim')
-rwxr-xr-xcompiler/semexprs.nim100
1 files changed, 63 insertions, 37 deletions
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index d423acc17..d3b30e24b 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -8,6 +8,7 @@
 #
 
 # this module does the semantic checking for expressions
+# included from sem.nim
 
 proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode = 
   markUsed(n, s)
@@ -103,7 +104,8 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
     if s.ast == nil: InternalError(n.info, "no default for")
     result = semExpr(c, s.ast)
   of skType:
-    if efAllowType notin flags: GlobalError(n.info, errATypeHasNoValue)
+    if efAllowType notin flags:
+      GlobalError(n.info, errATypeHasNoValue)
     markUsed(n, s)
     result = newSymNode(s, n.info)
   else:
@@ -245,17 +247,17 @@ proc semIs(c: PContext, n: PNode): PNode =
   else:
     GlobalError(n.info, errXExpectsTwoArguments, "is")
 
-proc semOpAux(c: PContext, n: PNode) = 
-  for i in countup(1, sonsLen(n) - 1): 
+proc semOpAux(c: PContext, n: PNode) =
+  for i in countup(1, sonsLen(n) - 1):
     var a = n.sons[i]
     if a.kind == nkExprEqExpr and sonsLen(a) == 2: 
       var info = a.sons[0].info
       a.sons[0] = newIdentNode(considerAcc(a.sons[0]), info)
-      a.sons[1] = semExprWithType(c, a.sons[1])
+      a.sons[1] = semExprWithType(c, a.sons[1], {efAllowType})
       a.typ = a.sons[1].typ
-    else: 
-      n.sons[i] = semExprWithType(c, a)
-  
+    else:
+      n.sons[i] = semExprWithType(c, a, {efAllowType})
+    
 proc overloadedCallOpr(c: PContext, n: PNode): PNode = 
   # quick check if there is *any* () operator overloaded:
   var par = getIdent("()")
@@ -514,25 +516,32 @@ proc semStaticExpr(c: PContext, n: PNode): PNode =
   if result.isNil:
     LocalError(n.info, errCannotInterpretNodeX, renderTree(n))
 
-proc semDirectCallAnalyseEffects(c: PContext, n: PNode,
-                                 flags: TExprFlags): PNode =
+proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
+                                     flags: TExprFlags): PNode =
   if efWantIterator in flags:
-    result = semDirectCall(c, n, {skIterator})
+    result = semOverloadedCall(c, n, nOrig, {skIterator})
   elif efInTypeOf in flags:
     # for ``type(countup(1,3))``, see ``tests/ttoseq``.
-    result = semDirectCall(c, n, {skIterator, skProc, skMethod, skConverter})
+    result = semOverloadedCall(c, n, nOrig, {skIterator, skProc, skMethod, skConverter, skMacro, skTemplate})
   else:
-    result = semDirectCall(c, n, {skProc, skMethod, skConverter})
+    result = semOverloadedCall(c, n, nOrig, {skProc, skMethod, skConverter, skMacro, skTemplate})
   if result != nil:
     if result.sons[0].kind != nkSym: 
       InternalError("semDirectCallAnalyseEffects")
-    var callee = result.sons[0].sym
-    if (callee.kind == skIterator) and (callee.id == c.p.owner.id): 
-      GlobalError(n.info, errRecursiveDependencyX, callee.name.s)
-    if sfNoSideEffect notin callee.flags:
-      if {sfImportc, sfSideEffect} * callee.flags != {}:
-        incl(c.p.owner.flags, sfSideEffect)
-  
+    let callee = result.sons[0].sym
+    case callee.kind
+    of skMacro, skTemplate: nil
+    else:
+      if (callee.kind == skIterator) and (callee.id == c.p.owner.id): 
+        GlobalError(n.info, errRecursiveDependencyX, callee.name.s)
+      if sfNoSideEffect notin callee.flags: 
+        if {sfImportc, sfSideEffect} * callee.flags != {}:
+          incl(c.p.owner.flags, sfSideEffect)
+
+proc semDirectCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode,
+                                 flags: TExprFlags): PNode =
+  result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
+
 proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = 
   result = nil
   var prc = n.sons[0]
@@ -548,13 +557,14 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
       return semExpr(c, result, flags)
   else: 
     n.sons[0] = semExpr(c, n.sons[0])
+  let nOrig = n.copyTree
   semOpAux(c, n)
   var t: PType = nil
   if (n.sons[0].typ != nil): t = skipTypes(n.sons[0].typ, abstractInst)
   if (t != nil) and (t.kind == tyProc): 
     var m: TCandidate
     initCandidate(m, t)
-    matches(c, n, m)
+    matches(c, n, nOrig, m)
     if m.state != csMatch: 
       var msg = msgKindToString(errTypeMismatch)
       for i in countup(1, sonsLen(n) - 1): 
@@ -575,7 +585,8 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
     # the old ``prc`` (which is likely an nkIdent) has to be restored:
     if result == nil: 
       n.sons[0] = prc
-      result = semDirectCallAnalyseEffects(c, n, flags)
+      nOrig.sons[0] = prc
+      result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
     if result == nil: 
       GlobalError(n.info, errExprXCannotBeCalled, 
                   renderTree(n, {renderNoComments}))
@@ -587,15 +598,21 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
 
 proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = 
   # this seems to be a hotspot in the compiler!
+  let nOrig = n.copyTree
   semOpAux(c, n)
-  result = semDirectCallAnalyseEffects(c, n, flags)
-  if result == nil: 
+  result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags)
+  if result == nil:
     result = overloadedCallOpr(c, n)
     if result == nil: GlobalError(n.Info, errGenerated, getNotFoundError(c, n))
-  fixAbstractType(c, result)
-  analyseIfAddressTakenInCall(c, result)
-  if result.sons[0].sym.magic != mNone:
-    result = magicsAfterOverloadResolution(c, result, flags)
+  let callee = result.sons[0].sym
+  case callee.kind
+  of skMacro: result = semMacroExpr(c, nOrig, callee)
+  of skTemplate: result = semTemplateExpr(c, nOrig, callee)
+  else:
+    fixAbstractType(c, result)
+    analyseIfAddressTakenInCall(c, result)
+    if callee.magic != mNone:
+      result = magicsAfterOverloadResolution(c, result, flags)
   result = evalAtCompileTime(c, result)
 
 proc buildStringify(c: PContext, arg: PNode): PNode = 
@@ -734,7 +751,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
         result.typ = ty
         markUsed(n, f)
         return 
-    elif efAllowType notin flags: 
+    elif efAllowType notin flags:
       GlobalError(n.sons[0].info, errATypeHasNoValue)
       return
     # reset to prevent 'nil' bug: see "tests/reject/tenumitems.nim":
@@ -852,16 +869,16 @@ proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
     # overloaded [] operator:
     result = semExpr(c, buildOverloadedSubscripts(n, getIdent"[]"))
 
-proc propertyWriteAccess(c: PContext, n, a: PNode): PNode = 
+proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
   var id = considerAcc(a[1])
-  result = newNodeI(nkCall, n.info)
-  addSon(result, newIdentNode(getIdent(id.s & '='), n.info))
+  let setterId = newIdentNode(getIdent(id.s & '='), n.info)
   # a[0] is already checked for semantics, that does ``builtinFieldAccess``
   # this is ugly. XXX Semantic checking should use the ``nfSem`` flag for
   # nodes?
-  addSon(result, a[0])
-  addSon(result, semExpr(c, n[1]))
-  result = semDirectCallAnalyseEffects(c, result, {})
+  let aOrig = nOrig[0]
+  result = newNode(nkCall, n.info, sons = @[setterId, a[0], semExpr(c, n[1])])
+  let orig = newNode(nkCall, n.info, sons = @[setterId, aOrig[0], nOrig[1]])
+  result = semDirectCallAnalyseEffects(c, result, orig, {})
   if result != nil:
     fixAbstractType(c, result)
     analyseIfAddressTakenInCall(c, result)
@@ -898,9 +915,10 @@ proc semAsgn(c: PContext, n: PNode): PNode =
   of nkDotExpr: 
     # r.f = x
     # --> `f=` (r, x)
+    let nOrig = n.copyTree
     a = builtinFieldAccess(c, a, {efLValue})
     if a == nil: 
-      return propertyWriteAccess(c, n, n[0])
+      return propertyWriteAccess(c, n, nOrig, a)
   of nkBracketExpr: 
     # a[i] = x
     # --> `[]=`(a, i, x)
@@ -1275,8 +1293,16 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     var s = qualifiedLookup(c, n.sons[0], {checkUndeclared})
     if s != nil: 
       case s.kind
-      of skMacro: result = semMacroExpr(c, n, s)
-      of skTemplate: result = semTemplateExpr(c, n, s)
+      of skMacro:
+        if false and sfImmediate notin s.flags: # XXX not yet enabled
+          result = semDirectOp(c, n, flags)
+        else:
+          result = semMacroExpr(c, n, s)
+      of skTemplate:
+        if sfImmediate notin s.flags:
+          result = semDirectOp(c, n, flags)
+        else:
+          result = semTemplateExpr(c, n, s)
       of skType: 
         # XXX think about this more (``set`` procs)
         if n.len == 2: