summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-10-19 01:59:51 +0200
committerAraq <rumpf_a@web.de>2012-10-19 01:59:51 +0200
commite6b52fe219f42d0483f467c3ad12b86949fe8eba (patch)
tree3557225c527837e436b657c155f85c9b00d2f428 /compiler
parent3f82352c2e53247650a66bff52f552517cff8121 (diff)
parent2efdf3df81fc1a451f4444e822a870c59e27e586 (diff)
downloadNim-e6b52fe219f42d0483f467c3ad12b86949fe8eba.tar.gz
Merge branch 'master' of github.com:Araq/Nimrod
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ast.nim1
-rw-r--r--compiler/ccgcalls.nim21
-rwxr-xr-xcompiler/ccgexprs.nim4
-rwxr-xr-xcompiler/cgen.nim2
-rwxr-xr-xcompiler/semexprs.nim98
-rwxr-xr-xcompiler/sigmatch.nim4
6 files changed, 76 insertions, 54 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 83bd360f2..870b2c016 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -715,6 +715,7 @@ const
                   nkCommand, nkCallStrLit}
 
   nkLambdaKinds* = {nkLambda, nkDo}
+  nkSymChoices* = {nkClosedSymChoice, nkOpenSymChoice}
 
   skLocalVars* = {skVar, skLet, skForVar, skParam}
 
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index 665d80e32..2673f98b8 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -18,13 +18,14 @@ proc leftAppearsOnRightSide(le, ri: PNode): bool =
 proc hasNoInit(call: PNode): bool {.inline.} =
   result = call.sons[0].kind == nkSym and sfNoInit in call.sons[0].sym.flags
 
-proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, pl: PRope) =
-  var pl = pl
+proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
+               callee, params: PRope) =
+  var pl = con(callee, "(".toRope, params)
   # getUniqueType() is too expensive here:
   var typ = skipTypes(ri.sons[0].typ, abstractInst)
   if typ.sons[0] != nil:
     if isInvalidReturnType(typ.sons[0]):
-      if sonsLen(ri) > 1: app(pl, ", ")
+      if params != nil: pl.app(", ")
       # beware of 'result = p(result)'. We may need to allocate a temporary:
       if d.k in {locTemp, locNone} or not leftAppearsOnRightSide(le, ri):
         # Great, we can use 'd':
@@ -125,9 +126,9 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
   # getUniqueType() is too expensive here:
   var typ = skipTypes(ri.sons[0].typ, abstractInst)
   assert(typ.kind == tyProc)
+  assert(sonsLen(typ) == sonsLen(typ.n))
   var length = sonsLen(ri)
   for i in countup(1, length - 1):
-    assert(sonsLen(typ) == sonsLen(typ.n))
     if ri.sons[i].typ.isCompileTimeOnly: continue
     if params != nil: app(params, ", ")
     if i < sonsLen(typ):
@@ -135,7 +136,7 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
       app(params, genArg(p, ri.sons[i], typ.n.sons[i].sym))
     else:
       app(params, genArgNoParam(p, ri.sons[i]))
-  fixupCall(p, le, ri, d, con(op.r, "(".toRope, params))
+  fixupCall(p, le, ri, d, op.r, params)
 
 proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
 
@@ -210,16 +211,16 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
   if skipTypes(param.typ, {tyGenericInst}).kind == tyPtr: app(pl, "->")
   else: app(pl, ".")
   app(pl, op.r)
-  app(pl, "(")
+  var params: PRope
   for i in countup(2, length - 1):
+    if params != nil: params.app(", ")
     assert(sonsLen(typ) == sonsLen(typ.n))
     if i < sonsLen(typ):
       assert(typ.n.sons[i].kind == nkSym)
-      app(pl, genArg(p, ri.sons[i], typ.n.sons[i].sym))
+      app(params, genArg(p, ri.sons[i], typ.n.sons[i].sym))
     else:
-      app(pl, genArgNoParam(p, ri.sons[i]))
-    if i < length - 1: app(pl, ", ")
-  fixupCall(p, le, ri, d, pl)
+      app(params, genArgNoParam(p, ri.sons[i]))
+  fixupCall(p, le, ri, d, pl, params)
 
 proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
   # generates a crappy ObjC call
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index d10b37432..d6666d88b 100755
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -223,7 +223,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
     # little HACK to support the new 'var T' as return type:
     lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
     return
-  var ty = skipTypes(dest.t, abstractVarRange)
+  var ty = skipTypes(dest.t, abstractRange)
   case ty.kind
   of tyRef:
     genRefAssign(p, dest, src, flags)
@@ -282,7 +282,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
     else:
       lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
   of tyPtr, tyPointer, tyChar, tyBool, tyEnum, tyCString,
-     tyInt..tyUInt64, tyRange:
+     tyInt..tyUInt64, tyRange, tyVar:
     lineCg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
   else: InternalError("genAssignment(" & $ty.kind & ')')
 
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index ffd9babde..0e0962936 100755
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -271,7 +271,7 @@ proc resetLoc(p: BProc, loc: var TLoc) =
       genObjectInit(p, cpsStmts, loc.t, loc, true)
 
 proc constructLoc(p: BProc, loc: TLoc, section = cpsStmts) =
-  if not isComplexValueType(skipTypes(loc.t, abstractVarRange)):
+  if not isComplexValueType(skipTypes(loc.t, abstractRange)):
     lineF(p, section, "$1 = 0;$n", [rdLoc(loc)])
   else:
     lineF(p, section, "memset((void*)$1, 0, sizeof($2));$n",
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 2c98d9de6..2b39f6190 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -125,44 +125,48 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
   else:
     markUsed(n, s)
     result = newSymNode(s, n.info)
-  
-proc checkConversionBetweenObjects(info: TLineInfo, castDest, src: PType) =
-  var diff = inheritanceDiff(castDest, src)
-  if diff == high(int):
-    LocalError(info, errGenerated, MsgKindToString(errIllegalConvFromXtoY) % [
-        src.typeToString, castDest.typeToString])
+
+type
+  TConvStatus = enum
+    convOK,
+    convNotNeedeed,
+    convNotLegal
+
+proc checkConversionBetweenObjects(castDest, src: PType): TConvStatus =
+  return if inheritanceDiff(castDest, src) == high(int):
+      convNotLegal
+    else:
+      convOK
 
 const 
   IntegralTypes = {tyBool, tyEnum, tyChar, tyInt..tyUInt64}
 
-proc checkConvertible(info: TLineInfo, castDest, src: PType) = 
-  if sameType(castDest, src) and castDest.sym == src.sym: 
+proc checkConvertible(castDest, src: PType): TConvStatus =
+  result = convOK
+  if sameType(castDest, src) and castDest.sym == src.sym:
     # don't annoy conversions that may be needed on another processor:
     if castDest.kind notin IntegralTypes+{tyRange}:
-      Message(info, hintConvFromXtoItselfNotNeeded, typeToString(castDest))
+      result = convNotNeedeed
     return
   var d = skipTypes(castDest, abstractVar)
   var s = skipTypes(src, abstractVar)
-  while (d != nil) and (d.Kind in {tyPtr, tyRef}) and (d.Kind == s.Kind): 
+  while (d != nil) and (d.Kind in {tyPtr, tyRef}) and (d.Kind == s.Kind):
     d = base(d)
     s = base(s)
   if d == nil:
-    LocalError(info, errGenerated, msgKindToString(errIllegalConvFromXtoY) % [
-        src.typeToString, castDest.typeToString])
-  elif d.Kind == tyObject and s.Kind == tyObject: 
-    checkConversionBetweenObjects(info, d, s)
+    result = convNotLegal
+  elif d.Kind == tyObject and s.Kind == tyObject:
+    result = checkConversionBetweenObjects(d, s)
   elif (skipTypes(castDest, abstractVarRange).Kind in IntegralTypes) and
-      (skipTypes(src, abstractVarRange).Kind in IntegralTypes): 
+      (skipTypes(src, abstractVarRange).Kind in IntegralTypes):
     # accept conversion between integral types
-  else: 
+  else:
     # we use d, s here to speed up that operation a bit:
     case cmpTypes(d, s)
-    of isNone, isGeneric: 
+    of isNone, isGeneric:
       if not compareTypes(castDest, src, dcEqIgnoreDistinct):
-        LocalError(info, errGenerated, `%`(
-            MsgKindToString(errIllegalConvFromXtoY), 
-            [typeToString(src), typeToString(castDest)]))
-    else: 
+        result = convNotLegal
+    else:
       nil
 
 proc isCastable(dst, src: PType): bool = 
@@ -184,23 +188,32 @@ proc isCastable(dst, src: PType): bool =
         (skipTypes(src, abstractInst).kind in IntegralTypes)
   
 proc isSymChoice(n: PNode): bool {.inline.} =
-  result = n.kind in {nkClosedSymChoice, nkOpenSymChoice}
+  result = n.kind in nkSymChoices
 
-proc semConv(c: PContext, n: PNode, s: PSym): PNode = 
-  if sonsLen(n) != 2: 
+proc semConv(c: PContext, n: PNode, s: PSym): PNode =
+  if sonsLen(n) != 2:
     LocalError(n.info, errConvNeedsOneArg)
     return n
   result = newNodeI(nkConv, n.info)
-  result.typ = semTypeNode(c, n.sons[0], nil)
+  result.typ = semTypeNode(c, n.sons[0], nil).skipTypes({tyGenericInst})
   addSon(result, copyTree(n.sons[0]))
   addSon(result, semExprWithType(c, n.sons[1]))
   var op = result.sons[1]
+     
   if not isSymChoice(op):
-    checkConvertible(result.info, result.typ, op.typ)
-  else: 
+    let status = checkConvertible(result.typ, op.typ)
+    case status
+    of convOK: nil
+    of convNotNeedeed:
+      Message(n.info, hintConvFromXtoItselfNotNeeded, result.typ.typeToString)
+    of convNotLegal:
+      LocalError(n.info, errGenerated, MsgKindToString(errIllegalConvFromXtoY)%
+        [op.typ.typeToString, result.typ.typeToString])
+  else:
     for i in countup(0, sonsLen(op) - 1):
       let it = op.sons[i]
-      if sameType(result.typ, it.typ): 
+      let status = checkConvertible(result.typ, it.typ)
+      if status == convOK:
         markUsed(n, it.sym)
         markIndirect(c, it.sym)
         return it
@@ -492,12 +505,16 @@ proc analyseIfAddressTaken(c: PContext, n: PNode): PNode =
     result = newHiddenAddrTaken(c, n) # BUGFIX!
   
 proc analyseIfAddressTakenInCall(c: PContext, n: PNode) = 
+  checkMinSonsLen(n, 1)
   const 
     FakeVarParams = {mNew, mNewFinalize, mInc, ast.mDec, mIncl, mExcl, 
       mSetLengthStr, mSetLengthSeq, mAppendStrCh, mAppendStrStr, mSwap, 
       mAppendSeqElem, mNewSeq, mReset, mShallowCopy}
-  checkMinSonsLen(n, 1)
-  var t = n.sons[0].typ
+  
+  # get the real type of the callee
+  # it may be a proc var with a generic alias type, so we skip over them
+  var t = n.sons[0].typ.skipTypes({tyGenericInst})
+
   if n.sons[0].kind == nkSym and n.sons[0].sym.magic in FakeVarParams: 
     # BUGFIX: check for L-Value still needs to be done for the arguments!
     for i in countup(1, sonsLen(n) - 1): 
@@ -618,7 +635,8 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
   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): 
+  if (t != nil) and (t.kind == tyProc):
+    # This is a proc variable, apply normal overload resolution
     var m: TCandidate
     initCandidate(m, t)
     matches(c, n, nOrig, m)
@@ -648,6 +666,10 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
     # we assume that a procedure that calls something indirectly 
     # has side-effects:
     if tfNoSideEffect notin t.flags: incl(c.p.owner.flags, sfSideEffect)
+  elif (t != nil) and t.kind == tyTypeDesc:
+    let destType = t.skipTypes({tyTypeDesc, tyGenericInst})
+    result = semConv(c, n, symFromType(destType, n.info))
+    return 
   else:
     result = overloadedCallOpr(c, n)
     # Now that nkSym does not imply an iteration over the proc/iterator space,
@@ -956,10 +978,10 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
       result.typ = elemType(arr)
     #GlobalError(n.info, errIndexTypesDoNotMatch)
   of tyTypeDesc:
-    result = n.sons[0] # The result so far is a tyTypeDesc bound to
-                       # a tyGenericBody. The line below will substitute
-                       # it with the instantiated type.
-    result.typ.sons[0] = semTypeNode(c, n, nil).linkTo(result.sym)
+    # The result so far is a tyTypeDesc bound 
+    # a tyGenericBody. The line below will substitute
+    # it with the instantiated type.
+    result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
   of tyTuple: 
     checkSonsLen(n, 2)
     n.sons[0] = makeDeref(n.sons[0])
@@ -1715,12 +1737,10 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkTableConstr:
     result = semTableConstr(c, n)
   of nkClosedSymChoice, nkOpenSymChoice:
-    LocalError(n.info, errExprXAmbiguous, renderTree(n, {renderNoComments}))
-    # error correction: Pick first element:
-    result = n.sons[0]
+    # handling of sym choices is context dependent
+    # the node is left intact for now
   of nkStaticExpr:
     result = semStaticExpr(c, n)
-
   of nkAsgn: result = semAsgn(c, n)
   of nkBlockStmt: result = semBlock(c, n)
   of nkStmtList: result = semStmtList(c, n)
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index f1920a255..a9753f97d 100755
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -685,8 +685,8 @@ proc ParamTypesMatchAux(c: PContext, m: var TCandidate, f, a: PType,
           result = userConvMatch(c, m, base(f), a, arg)
 
 proc ParamTypesMatch(c: PContext, m: var TCandidate, f, a: PType, 
-                     arg, argOrig: PNode): PNode = 
-  if arg == nil or arg.kind != nkClosedSymChoice:
+                     arg, argOrig: PNode): PNode =
+  if arg == nil or arg.kind notin nkSymChoices:
     result = ParamTypesMatchAux(c, m, f, a, arg, argOrig)
   else: 
     # CAUTION: The order depends on the used hashing scheme. Thus it is