summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-08-26 02:47:17 +0200
committerAraq <rumpf_a@web.de>2012-08-26 02:47:17 +0200
commitb5b5e6e76df228f573ae86780c66889f4b426301 (patch)
tree10471ab5c2d742e6ea09974b1420002112459b3a /compiler
parent9a7f0cd8510a534a3f1e9d4275b8abd7825a94c6 (diff)
downloadNim-b5b5e6e76df228f573ae86780c66889f4b426301.tar.gz
distinguish properly between nkOpen and nkClosedSymChoice
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ast.nim8
-rwxr-xr-xcompiler/lookups.nim4
-rwxr-xr-xcompiler/renderer.nim5
-rwxr-xr-xcompiler/semcall.nim11
-rwxr-xr-xcompiler/semexprs.nim20
-rwxr-xr-xcompiler/semgnrc.nim13
-rw-r--r--compiler/semmagic.nim12
-rwxr-xr-xcompiler/semtempl.nim26
-rwxr-xr-xcompiler/sigmatch.nim2
-rwxr-xr-xcompiler/suggest.nim2
-rwxr-xr-xcompiler/trees.nim3
-rwxr-xr-xcompiler/types.nim2
12 files changed, 66 insertions, 42 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index a6f169384..79adafcf8 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -104,7 +104,8 @@ type
 
     nkTableConstr,        # a table constructor {expr: expr}
     nkBind,               # ``bind expr`` node
-    nkSymChoice,          # symbol choice node
+    nkClosedSymChoice,    # symbol choice node; a list of nkSyms (closed)
+    nkOpenSymChoice,      # symbol choice node; a list of nkSyms (open)
     nkHiddenStdConv,      # an implicit standard type conversion
     nkHiddenSubConv,      # an implicit type conversion from a subtype
                           # to a supertype
@@ -473,6 +474,11 @@ const
     mInRange, mInSet, mRepr,
     mRand, 
     mCopyStr, mCopyStrLast}
+  # magics that require special semantic checking and
+  # thus cannot be overloaded (also documented in the spec!):
+  SpecialSemMagics* = {
+    mDefined, mDefinedInScope, mCompiles, mLow, mHigh, mSizeOf, mIs, mOf, 
+    mEcho, mShallowCopy, mExpandToAst}
 
 type 
   PNode* = ref TNode
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index 9ab5d2c48..1717ab4fb 100755
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -230,7 +230,7 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
         LocalError(n.sons[1].info, errIdentifierExpected, 
                    renderTree(n.sons[1]))
         result = errorSym(c, n.sons[1])
-  of nkSymChoice: 
+  of nkClosedSymChoice, nkOpenSymChoice:
     o.mode = oimSymChoice
     result = n.sons[0].sym
     o.stackPtr = 1
@@ -269,7 +269,7 @@ proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym =
       result = n.sons[o.stackPtr].sym
       Incl(o.inSymChoice, result.id)
       inc(o.stackPtr)
-    else:
+    elif n.kind == nkOpenSymChoice:
       # try 'local' symbols too for Koenig's lookup:
       o.mode = oimSymChoiceLocalLookup
       o.stackPtr = c.tab.tos-1
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index a1a6de984..c24a22fd5 100755
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -379,7 +379,8 @@ proc lsub(n: PNode): int =
   of nkPar, nkCurly, nkBracket, nkClosure: result = lcomma(n) + 2
   of nkTableConstr:
     result = if n.len > 0: lcomma(n) + 2 else: len("{:}")
-  of nkSymChoice: result = lsons(n) + len("()") + sonsLen(n) - 1
+  of nkClosedSymChoice, nkOpenSymChoice: 
+    result = lsons(n) + len("()") + sonsLen(n) - 1
   of nkTupleTy: result = lcomma(n) + len("tuple[]")
   of nkDotExpr: result = lsons(n) + 1
   of nkBind: result = lsons(n) + len("bind_")
@@ -833,7 +834,7 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
     put(g, tkParLe, "(")
     gcomma(g, n, 1)
     put(g, tkParRi, ")")
-  of nkSymChoice: 
+  of nkClosedSymChoice, nkOpenSymChoice:
     put(g, tkParLe, "(")
     for i in countup(0, sonsLen(n) - 1): 
       if i > 0: put(g, tkOpr, "|")
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index e4655c5ba..a5107bf64 100755
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -10,7 +10,7 @@
 ## This module implements semantic checking for calls. 
 # included from sem.nim
 
-proc sameMethodDispatcher(a, b: PSym): bool = 
+proc sameMethodDispatcher(a, b: PSym): bool =
   result = false
   if a.kind == skMethod and b.kind == skMethod: 
     var aa = lastSon(a.ast)
@@ -132,11 +132,11 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
     if safeLen(s.ast.sons[genericParamsPos]) != n.len-1:
       return explicitGenericInstError(n)
     result = explicitGenericSym(c, n, s)
-  elif a.kind == nkSymChoice:
+  elif a.kind in {nkClosedSymChoice, nkOpenSymChoice}:
     # choose the generic proc with the proper number of type parameters.
     # XXX I think this could be improved by reusing sigmatch.ParamTypesMatch.
     # It's good enough for now.
-    result = newNodeI(nkSymChoice, n.info)
+    result = newNodeI(a.kind, n.info)
     for i in countup(0, len(a)-1): 
       var candidate = a.sons[i].sym
       if candidate.kind in {skProc, skMethod, skConverter, skIterator}: 
@@ -144,8 +144,9 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
         # type parameters:
         if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
           result.add(explicitGenericSym(c, n, candidate))
-    # get rid of nkSymChoice if not ambiguous:
-    if result.len == 1: result = result[0]
+    # get rid of nkClosedSymChoice if not ambiguous:
+    if result.len == 1 and a.kind == nkClosedSymChoice:
+      result = result[0]
     # candidateCount != 1: return explicitGenericInstError(n)
   else:
     result = explicitGenericInstError(n)
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index cd53d6501..06014bf6f 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -58,7 +58,7 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     result.typ = errorType(c)
 
 proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
-  result = symChoice(c, n, s)
+  result = symChoice(c, n, s, scClosed)
   
 proc inlineConst(n: PNode, s: PSym): PNode {.inline.} =
   result = copyTree(s.ast)
@@ -72,7 +72,7 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
     if sfProcVar notin s.flags and s.typ.callConv == ccDefault and
         smoduleId != c.module.id and smoduleId != c.friendModule.id: 
       LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
-    result = symChoice(c, n, s)
+    result = symChoice(c, n, s, scClosed)
     if result.kind == nkSym:
       markIndirect(c, result.sym)
       if isGenericRoutine(result.sym):
@@ -182,6 +182,9 @@ proc isCastable(dst, src: PType): bool =
         (skipTypes(dst, abstractInst).kind in IntegralTypes) or
         (skipTypes(src, abstractInst).kind in IntegralTypes)
   
+proc isSymChoice(n: PNode): bool {.inline.} =
+  result = n.kind in {nkClosedSymChoice, nkOpenSymChoice}
+
 proc semConv(c: PContext, n: PNode, s: PSym): PNode = 
   if sonsLen(n) != 2: 
     LocalError(n.info, errConvNeedsOneArg)
@@ -191,7 +194,7 @@ proc semConv(c: PContext, n: PNode, s: PSym): PNode =
   addSon(result, copyTree(n.sons[0]))
   addSon(result, semExprWithType(c, n.sons[1]))
   var op = result.sons[1]
-  if op.kind != nkSymChoice: 
+  if not isSymChoice(op):
     checkConvertible(result.info, result.typ, op.typ)
   else: 
     for i in countup(0, sonsLen(op) - 1):
@@ -830,7 +833,7 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   ## returns nil if it's not a built-in field access
   checkSonsLen(n, 2)
   # early exit for this; see tests/compile/tbindoverload.nim:
-  if n.sons[1].kind == nkSymChoice: return
+  if isSymChoice(n.sons[1]): return
 
   var s = qualifiedLookup(c, n, {checkAmbiguity, checkUndeclared})
   if s != nil:
@@ -910,7 +913,7 @@ proc semFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   # in Nimrod. We first allow types in the semantic checking.
   result = builtinFieldAccess(c, n, flags)
   if result == nil:
-    if n.sons[1].kind == nkSymChoice: 
+    if isSymChoice(n.sons[1]):
       result = newNodeI(nkDotCall, n.info)
       addSon(result, n.sons[1])
       addSon(result, copyTree(n[0]))
@@ -1222,6 +1225,7 @@ proc semShallowCopy(c: PContext, n: PNode, flags: TExprFlags): PNode =
 
 proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = 
   # this is a hotspot in the compiler!
+  # DON'T forget to update ast.SpecialSemMagics if you add a magic here!
   result = n
   case s.magic # magics that need special treatment
   of mDefined: result = semDefined(c, setMs(n, s), false)
@@ -1518,8 +1522,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
       else:
         #liMessage(n.info, warnUser, renderTree(n));
         result = semIndirectOp(c, n, flags)
-    elif n.sons[0].kind == nkSymChoice or n[0].kind == nkBracketExpr and 
-        n[0][0].kind == nkSymChoice:
+    elif isSymChoice(n.sons[0]) or n[0].kind == nkBracketExpr and 
+        isSymChoice(n[0][0]):
       result = semDirectOp(c, n, flags)
     else:
       result = semIndirectOp(c, n, flags)
@@ -1576,7 +1580,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     checkMinSonsLen(n, 2)
   of nkTableConstr:
     result = semTableConstr(c, n)
-  of nkSymChoice:
+  of nkClosedSymChoice, nkOpenSymChoice:
     LocalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
     # error correction: Pick first element:
     result = n.sons[0]
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index 3a11f87ce..849d04fb1 100755
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -13,7 +13,7 @@
 # A problem is that it cannot be detected if the symbol is introduced
 # as in ``var x = ...`` or used because macros/templates can hide this!
 # So we have to eval templates/macros right here so that symbol
-# lookup can be accurate.
+# lookup can be accurate. XXX But this can only be done for immediate macros!
 
 # included from sem.nim
 
@@ -47,8 +47,8 @@ proc semGenericStmtSymbol(c: PContext, n: PNode, s: PSym): PNode =
     # Introduced in this pass! Leave it as an identifier.
     result = n
   of skProc, skMethod, skIterator, skConverter: 
-    result = symChoice(c, n, s)
-  of skTemplate: 
+    result = symChoice(c, n, s, scOpen)
+  of skTemplate:
     result = semTemplateExpr(c, n, s, false)
   of skMacro: 
     result = semMacroExpr(c, n, s, false)
@@ -75,7 +75,8 @@ proc semGenericStmt(c: PContext, n: PNode,
       if withinBind in flags:
         localError(n.info, errUndeclaredIdentifier, n.ident.s)
     else:
-      if withinBind in flags or s.id in toBind: result = symChoice(c, n, s)
+      if withinBind in flags or s.id in toBind:
+        result = symChoice(c, n, s, scClosed)
       else: result = semGenericStmtSymbol(c, n, s)
   of nkDotExpr:
     var s = QualifiedLookUp(c, n, {})
@@ -104,7 +105,7 @@ proc semGenericStmt(c: PContext, n: PNode,
       of skUnknown, skParam: 
         # Leave it as an identifier.
       of skProc, skMethod, skIterator, skConverter: 
-        result.sons[0] = symChoice(c, n.sons[0], s)
+        result.sons[0] = symChoice(c, n.sons[0], s, scOpen)
         first = 1
       of skGenericParam: 
         result.sons[0] = newSymNode(s, n.sons[0].info)
@@ -114,7 +115,7 @@ proc semGenericStmt(c: PContext, n: PNode,
         if (s.typ != nil) and (s.typ.kind != tyGenericParam): 
           result.sons[0] = newSymNode(s, n.sons[0].info)
           first = 1
-      else: 
+      else:
         result.sons[0] = newSymNode(s, n.sons[0].info)
         first = 1
     for i in countup(first, sonsLen(result) - 1): 
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index b4cc1727d..da179f0a7 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -49,16 +49,22 @@ proc semBindSym(c: PContext, n: PNode): PNode =
   result = copyNode(n)
   result.add(n.sons[0])
   
-  let sl = c.semConstExpr(c, n.sons[1])
+  let sl = semConstExpr(c, n.sons[1])
   if sl.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit}: 
-    LocalError(n.info, errStringLiteralExpected)
+    LocalError(n.sons[1].info, errStringLiteralExpected)
+    return errorNode(c, n)
+  
+  let isMixin = semConstExpr(c, n.sons[2])
+  if isMixin.kind != nkIntLit or isMixin.intVal < 0 or
+      isMixin.intVal > high(TSymChoiceRule).int:
+    LocalError(n.sons[2].info, errConstExprExpected)
     return errorNode(c, n)
   
   let id = newIdentNode(getIdent(sl.strVal), n.info)
   let s = QualifiedLookUp(c, id)
   if s != nil:
     # we need to mark all symbols:
-    let sc = symChoice(c, id, s)
+    var sc = symChoice(c, id, s, TSymChoiceRule(isMixin.intVal))
     result.add(sc)
   else:
     LocalError(n.sons[1].info, errUndeclaredIdentifier, sl.strVal)
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index 780dded82..c16f4ce09 100755
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -40,8 +40,12 @@ proc symBinding(n: PNode): TSymBinding =
       of wInject: return spInject
       else: nil
 
-proc symChoice(c: PContext, n: PNode, s: PSym): PNode = 
-  var 
+type
+  TSymChoiceRule = enum
+    scClosed, scOpen, scForceOpen
+
+proc symChoice(c: PContext, n: PNode, s: PSym, r: TSymChoiceRule): PNode =
+  var
     a: PSym
     o: TOverloadIter
   var i = 0
@@ -50,17 +54,17 @@ proc symChoice(c: PContext, n: PNode, s: PSym): PNode =
     a = nextOverloadIter(o, c, n)
     inc(i)
     if i > 1: break
-  if i <= 1:
+  if i <= 1 and r != scForceOpen:
     # XXX this makes more sense but breaks bootstrapping for now:
     # (s.kind notin routineKinds or s.magic != mNone):
-    # for some reason 'nextTry' is copied and considered as a candidate in
-    # tables.nim
+    # for instance 'nextTry' is both in tables.nim and astalgo.nim ...
     result = newSymNode(s, n.info)
     markUsed(n, s)
   else:
     # semantic checking requires a type; ``fitNode`` deals with it
     # appropriately
-    result = newNodeIT(nkSymChoice, n.info, newTypeS(tyNone, c))
+    let kind = if r == scClosed: nkClosedSymChoice else: nkOpenSymChoice
+    result = newNodeIT(kind, n.info, newTypeS(tyNone, c))
     a = initOverloadIter(o, c, n)
     while a != nil:
       incl(a.flags, sfUsed)
@@ -78,7 +82,7 @@ proc semBindStmt(c: PContext, n: PNode, toBind: var TIntSet): PNode =
     let s = QualifiedLookUp(c, a)
     if s != nil:
       # we need to mark all symbols:
-      let sc = symChoice(c, n, s)
+      let sc = symChoice(c, n, s, scClosed)
       if sc.kind == nkSym:
         toBind.incl(sc.sym.id)
       else:
@@ -178,7 +182,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
         incl(s.flags, sfUsed)
         result = newSymNode(s, n.info)
       elif Contains(c.toBind, s.id):
-        result = symChoice(c.c, n, s)
+        result = symChoice(c.c, n, s, scClosed)
       elif s.owner == c.owner:
         InternalAssert sfGenSym in s.flags
         incl(s.flags, sfUsed)
@@ -294,7 +298,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
     if n.kind == nkDotExpr or n.kind == nkAccQuoted:
       let s = QualifiedLookUp(c.c, n, {})
       if s != nil and Contains(c.toBind, s.id):
-        return symChoice(c.c, n, s)
+        return symChoice(c.c, n, s, scClosed)
     result = n
     for i in countup(0, sonsLen(n) - 1):
       result.sons[i] = semTemplBody(c, n.sons[i])
@@ -308,7 +312,7 @@ proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
       if s.owner == c.owner and s.kind == skParam:
         result = newSymNode(s, n.info)
       elif Contains(c.toBind, s.id):
-        result = symChoice(c.c, n, s)
+        result = symChoice(c.c, n, s, scClosed)
   of nkBind:
     result = semTemplBodyDirty(c, n.sons[0])
   of nkBindStmt:
@@ -321,7 +325,7 @@ proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
     if n.kind == nkDotExpr or n.kind == nkAccQuoted:
       let s = QualifiedLookUp(c.c, n, {})
       if s != nil and Contains(c.toBind, s.id):
-        return symChoice(c.c, n, s)
+        return symChoice(c.c, n, s, scClosed)
     result = n
     for i in countup(0, sonsLen(n) - 1):
       result.sons[i] = semTemplBodyDirty(c, n.sons[i])
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index aab847c94..5057883c7 100755
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -703,7 +703,7 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
 
 proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType, 
                      arg, argOrig: PNode): PNode = 
-  if arg == nil or arg.kind != nkSymChoice: 
+  if arg == nil or arg.kind != nkClosedSymChoice:
     result = ParamTypesMatchAux(c, m, f, a, arg, argOrig)
   else: 
     # CAUTION: The order depends on the used hashing scheme. Thus it is
diff --git a/compiler/suggest.nim b/compiler/suggest.nim
index 3b9c77336..daecf44b8 100755
--- a/compiler/suggest.nim
+++ b/compiler/suggest.nim
@@ -85,7 +85,7 @@ proc suggestObject(c: PContext, n: PNode, outputs: var int) =
 
 proc nameFits(c: PContext, s: PSym, n: PNode): bool = 
   var op = n.sons[0]
-  if op.kind == nkSymChoice: op = op.sons[0]
+  if op.kind in {nkOpenSymChoice, nkClosedSymChoice}: op = op.sons[0]
   var opr: PIdent
   case op.kind
   of nkSym: opr = op.sym.name
diff --git a/compiler/trees.nim b/compiler/trees.nim
index fb2e68548..e2c9b1b16 100755
--- a/compiler/trees.nim
+++ b/compiler/trees.nim
@@ -143,7 +143,8 @@ proc SwapOperands*(op: PNode) =
 proc IsRange*(n: PNode): bool {.inline.} = 
   if n.kind == nkInfix:
     if n[0].kind == nkIdent and n[0].ident.id == ord(wDotDot) or
-        n[0].kind == nkSymChoice and n[0][1].sym.name.id == ord(wDotDot):
+        n[0].kind in {nkClosedSymChoice, nkOpenSymChoice} and 
+        n[0][1].sym.name.id == ord(wDotDot):
       result = true
 
 proc whichPragma*(n: PNode): TSpecialWord = 
diff --git a/compiler/types.nim b/compiler/types.nim
index 8dae14924..aca168ba8 100755
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -117,7 +117,7 @@ proc isCompatibleToCString(a: PType): bool =
       result = true
   
 proc getProcHeader(sym: PSym): string = 
-  result = sym.name.s & '('
+  result = sym.owner.name.s & '.' & sym.name.s & '('
   var n = sym.typ.n
   for i in countup(1, sonsLen(n) - 1): 
     var p = n.sons[i]