summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-11-20 16:13:03 +0100
committerAraq <rumpf_a@web.de>2011-11-20 16:13:03 +0100
commit72651de7103a85f68b6e86353960daf6e62b37df (patch)
tree7ec632d331ab39149fef59d8bcee66247a6556c7 /compiler
parenta274f3bf5be3fc35f1538e5aab0e32fb9ed2ff82 (diff)
downloadNim-72651de7103a85f68b6e86353960daf6e62b37df.tar.gz
bugfix: 'when' sections in generic objects now work, so TThread[void] compiles
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ast.nim2
-rwxr-xr-xcompiler/evals.nim4
-rwxr-xr-xcompiler/semdata.nim34
-rwxr-xr-xcompiler/semexprs.nim11
-rwxr-xr-xcompiler/semfold.nim4
-rwxr-xr-xcompiler/semstmts.nim4
-rwxr-xr-xcompiler/semtypes.nim69
-rwxr-xr-xcompiler/semtypinst.nim62
8 files changed, 117 insertions, 73 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 7f28d7b89..3fdf5f6e3 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1022,7 +1022,7 @@ proc getStr*(a: PNode): string =
 proc getStrOrChar*(a: PNode): string = 
   case a.kind
   of nkStrLit..nkTripleStrLit: result = a.strVal
-  of nkCharLit: result = chr(int(a.intVal)) & ""
+  of nkCharLit: result = $chr(int(a.intVal))
   else: 
     internalError(a.info, "getStrOrChar")
     result = ""
diff --git a/compiler/evals.nim b/compiler/evals.nim
index cc05267f4..9f677b705 100755
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -747,7 +747,7 @@ proc evalConStrStr(c: PEvalContext, n: PNode): PNode =
   for i in countup(1, sonsLen(n) - 1): 
     result = evalAux(c, n.sons[i], {})
     if isSpecial(result): return 
-    a.strVal.add(getStrValue(result))
+    a.strVal.add(getStrOrChar(result))
   result = a
 
 proc evalAppendStrStr(c: PEvalContext, n: PNode): PNode = 
@@ -758,7 +758,7 @@ proc evalAppendStrStr(c: PEvalContext, n: PNode): PNode =
   if isSpecial(result): return 
   var b = result
   case a.kind
-  of nkStrLit..nkTripleStrLit: a.strVal = a.strVal & getStrValue(b)
+  of nkStrLit..nkTripleStrLit: a.strVal = a.strVal & getStrOrChar(b)
   else: InternalError(n.info, "evalAppendStrStr")
   result = emptyNode
 
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 39e4892b2..1037d2914 100755
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -49,25 +49,26 @@ type
   PGenericsCache* = ref TGenericsCache
   PContext* = ref TContext
   TContext* = object of TPassContext # a context represents a module
-    module*: PSym             # the module sym belonging to the context
-    p*: PProcCon              # procedure context
-    generics*: PGenericsCache # may point to a global or module-local structure 
-    friendModule*: PSym       # current friend module; may access private data;
-                              # this is used so that generic instantiations can
-                              # access private object fields
-    InstCounter*: int         # to prevent endless instantiations
+    module*: PSym              # the module sym belonging to the context
+    p*: PProcCon               # procedure context
+    generics*: PGenericsCache  # may point to a global or module-local structure
+    friendModule*: PSym        # current friend module; may access private data;
+                               # this is used so that generic instantiations
+                               # can access private object fields
+    InstCounter*: int          # to prevent endless instantiations
    
-    threadEntries*: TSymSeq   # list of thread entries to check
-    tab*: TSymTab             # each module has its own symbol table
+    threadEntries*: TSymSeq    # list of thread entries to check
+    tab*: TSymTab              # each module has its own symbol table
     AmbiguousSymbols*: TIntSet # ids of all ambiguous symbols (cannot
                                # store this info in the syms themselves!)
-    converters*: TSymSeq      # sequence of converters
+    InGenericContext*: int     # > 0 if we are in a generic
+    converters*: TSymSeq       # sequence of converters
     optionStack*: TLinkedList
-    libs*: TLinkedList        # all libs used by this module
+    libs*: TLinkedList         # all libs used by this module
     semConstExpr*: proc (c: PContext, n: PNode): PNode # for the pragmas
     semExpr*: proc (c: PContext, n: PNode): PNode      # for the pragmas
-    includedFiles*: TIntSet   # used to detect recursive include files
-    filename*: string         # the module's filename
+    includedFiles*: TIntSet    # used to detect recursive include files
+    filename*: string          # the module's filename
     userPragmas*: TStrTable
     evalContext*: PEvalContext
     slurpedFiles*: seq[string]
@@ -91,8 +92,7 @@ proc makePtrType*(c: PContext, baseType: PType): PType
 proc makeVarType*(c: PContext, baseType: PType): PType
 proc newTypeS*(kind: TTypeKind, c: PContext): PType
 proc fillTypeS*(dest: PType, kind: TTypeKind, c: PContext)
-proc makeRangeType*(c: PContext, first, last: biggestInt, info: TLineInfo): PType
-  
+
 # owner handling:
 proc getCurrOwner*(): PSym
 proc PushOwner*(owner: PSym)
@@ -196,8 +196,8 @@ proc fillTypeS(dest: PType, kind: TTypeKind, c: PContext) =
   dest.owner = getCurrOwner()
   dest.size = - 1
 
-proc makeRangeType(c: PContext, first, last: biggestInt, 
-                   info: TLineInfo): PType = 
+proc makeRangeType*(c: PContext, first, last: biggestInt, 
+                    info: TLineInfo): PType = 
   var n = newNodeI(nkRange, info)
   addSon(n, newIntNode(nkIntLit, first))
   addSon(n, newIntNode(nkIntLit, last))
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index af3048586..d21f557d4 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -222,11 +222,12 @@ proc semOf(c: PContext, n: PNode): PNode =
 
 proc semIs(c: PContext, n: PNode): PNode = 
   if sonsLen(n) == 3:
-    var a = semExprWithType(c, n.sons[1], {efAllowType})
-    var b = semExprWithType(c, n.sons[2], {efAllowType})
-    result = newIntNode(nkIntLit, ord(sameType(a.typ, b.typ)))
-    result.typ = getSysType(tyBool)
-    result.info = n.info
+    var a = semTypeNode(c, n[1], nil)
+    var b = semTypeNode(c, n[2], nil)
+    n.typ = getSysType(tyBool)
+    n.sons[1] = newNodeIT(nkType, n[1].info, a)
+    n.sons[2] = newNodeIT(nkType, n[2].info, b)
+    result = n
   else:
     GlobalError(n.info, errXExpectsTwoArguments, "is")
 
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index f317340da..afa1090a7 100755
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -436,7 +436,9 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
           result = newIntNodeT(sonsLen(a), n)
         else:
           result = magicCall(m, n)
-      else: 
+      of mIs:
+        result = newIntNodeT(ord(sameType(n[1].typ, n[2].typ)), n)
+      else:
         result = magicCall(m, n)
     except EOverflow: 
       LocalError(n.info, errOverOrUnderflow)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 8412d4783..2818ecbd1 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -527,8 +527,10 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
       # like: mydata.seq
       addSon(s.typ, newTypeS(tyEmpty, c))
       s.ast = a
+      inc c.InGenericContext
       var body = semTypeNode(c, a.sons[2], nil)
-      if body != nil: 
+      dec c.InGenericContext
+      if body != nil:
         body.sym = s
         body.size = -1 # could not be computed properly
       s.typ.sons[sonsLen(s.typ) - 1] = body
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index e51e02f2d..ca7988aeb 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -351,31 +351,41 @@ proc semRecordCase(c: PContext, n: PNode, check: var TIntSet, pos: var int,
 
 proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int, 
                       father: PNode, rectype: PSym) = 
-  var 
-    length: int
-    f: PSym                   # new field
-    a, it, e, branch: PNode
-    typ: PType
-  if n == nil: 
-    return                    # BUGFIX: nil is possible
+  if n == nil: return
   case n.kind
-  of nkRecWhen: 
-    branch = nil              # the branch to take
-    for i in countup(0, sonsLen(n) - 1): 
-      it = n.sons[i]
+  of nkRecWhen:
+    var branch: PNode = nil   # the branch to take
+    for i in countup(0, sonsLen(n) - 1):
+      var it = n.sons[i]
       if it == nil: illFormedAst(n)
+      var idx = 1
       case it.kind
-      of nkElifBranch: 
+      of nkElifBranch:
         checkSonsLen(it, 2)
-        e = semConstBoolExpr(c, it.sons[0])
-        if (e.kind != nkIntLit): InternalError(e.info, "semRecordNodeAux")
-        if (e.intVal != 0) and (branch == nil): branch = it.sons[1]
-      of nkElse: 
+        if c.InGenericContext == 0:
+          var e = semConstBoolExpr(c, it.sons[0])
+          if e.kind != nkIntLit: InternalError(e.info, "semRecordNodeAux")
+          if e.intVal != 0 and branch == nil: branch = it.sons[1]
+        else:
+          it.sons[0] = forceBool(c, semExprWithType(c, it.sons[0]))
+      of nkElse:
         checkSonsLen(it, 1)
         if branch == nil: branch = it.sons[0]
+        idx = 0
       else: illFormedAst(n)
-    if branch != nil: semRecordNodeAux(c, branch, check, pos, father, rectype)
-  of nkRecCase: 
+      if c.InGenericContext > 0:
+        # use a new check intset here for each branch:
+        var newCheck: TIntSet
+        assign(newCheck, check)
+        var newPos = pos
+        var newf = newNodeI(nkRecList, n.info)
+        semRecordNodeAux(c, it.sons[idx], newcheck, newpos, newf, rectype)
+        it.sons[idx] = if newf.len == 1: newf[0] else: newf
+    if c.InGenericContext > 0:
+      addSon(father, n)
+    elif branch != nil:
+      semRecordNodeAux(c, branch, check, pos, father, rectype)
+  of nkRecCase:
     semRecordCase(c, n, check, pos, father, rectype)
   of nkNilLit: 
     if father.kind != nkRecList: addSon(father, newNodeI(nkRecList, n.info))
@@ -385,20 +395,19 @@ proc semRecordNodeAux(c: PContext, n: PNode, check: var TIntSet, pos: var int,
     for i in countup(0, sonsLen(n) - 1): 
       semRecordNodeAux(c, n.sons[i], check, pos, a, rectype)
     if a != father: addSon(father, a)
-  of nkIdentDefs: 
+  of nkIdentDefs:
     checkMinSonsLen(n, 3)
-    length = sonsLen(n)
-    if (father.kind != nkRecList) and (length >= 4): 
-      a = newNodeI(nkRecList, n.info)
-    else: 
-      a = ast.emptyNode
-    if n.sons[length - 1].kind != nkEmpty: 
-      localError(n.sons[length - 1].info, errInitHereNotAllowed)
-    if n.sons[length - 2].kind == nkEmpty: 
+    var length = sonsLen(n)
+    var a: PNode
+    if father.kind != nkRecList and length >= 4: a = newNodeI(nkRecList, n.info)
+    else: a = ast.emptyNode
+    if n.sons[length-1].kind != nkEmpty: 
+      localError(n.sons[length-1].info, errInitHereNotAllowed)
+    if n.sons[length-2].kind == nkEmpty: 
       GlobalError(n.info, errTypeExpected)
-    typ = semTypeNode(c, n.sons[length-2], nil)
-    for i in countup(0, sonsLen(n) - 3): 
-      f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
+    var typ = semTypeNode(c, n.sons[length-2], nil)
+    for i in countup(0, sonsLen(n)-3): 
+      var f = semIdentWithPragma(c, skField, n.sons[i], {sfExported})
       f.typ = typ
       f.position = pos
       if (rectype != nil) and ({sfImportc, sfExportc} * rectype.flags != {}) and
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 0473f2f74..55bf2dcc8 100755
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -9,7 +9,7 @@
 
 # This module does the instantiation of generic types.
 
-import ast, astalgo, msgs, types, semdata
+import ast, astalgo, msgs, types, semdata, renderer
 
 proc checkPartialConstructedType(info: TLineInfo, t: PType) =
   if tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject:
@@ -63,21 +63,51 @@ type
 
 proc ReplaceTypeVarsT*(cl: var TReplTypeVars, t: PType): PType
 proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym
-proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode = 
-  if n != nil: 
-    result = copyNode(n)
-    result.typ = ReplaceTypeVarsT(cl, n.typ)
-    case n.kind
-    of nkNone..pred(nkSym), succ(nkSym)..nkNilLit: 
-      nil
-    of nkSym: 
-      result.sym = ReplaceTypeVarsS(cl, n.sym)
-    else: 
-      var length = sonsLen(n)
-      if length > 0: 
-        newSons(result, length)
-        for i in countup(0, length - 1): 
-          result.sons[i] = ReplaceTypeVarsN(cl, n.sons[i])
+
+proc prepareNode(cl: var TReplTypeVars, n: PNode): PNode =
+  result = copyNode(n)
+  result.typ = ReplaceTypeVarsT(cl, n.typ)
+  for i in 0 .. safeLen(n)-1: 
+    # XXX HACK: ``f(a, b)``, avoid to instantiate `f` 
+    if i == 0: result.add(n[i])
+    else: result.add(prepareNode(cl, n[i]))
+
+proc ReplaceTypeVarsN(cl: var TReplTypeVars, n: PNode): PNode =
+  if n == nil: return
+  result = copyNode(n)
+  result.typ = ReplaceTypeVarsT(cl, n.typ)
+  case n.kind
+  of nkNone..pred(nkSym), succ(nkSym)..nkNilLit:
+    nil
+  of nkSym:
+    result.sym = ReplaceTypeVarsS(cl, n.sym)
+  of nkRecWhen:
+    var branch: PNode = nil              # the branch to take
+    for i in countup(0, sonsLen(n) - 1):
+      var it = n.sons[i]
+      if it == nil: illFormedAst(n)
+      case it.kind
+      of nkElifBranch:
+        checkSonsLen(it, 2)
+        var cond = prepareNode(cl, it.sons[0])
+        var e = cl.c.semConstExpr(cl.c, cond)
+        if e.kind != nkIntLit:
+          InternalError(e.info, "ReplaceTypeVarsN: when condition not a bool")
+        if e.intVal != 0 and branch == nil: branch = it.sons[1]
+      of nkElse:
+        checkSonsLen(it, 1)
+        if branch == nil: branch = it.sons[0]
+      else: illFormedAst(n)
+    if branch != nil:
+      result = ReplaceTypeVarsN(cl, branch)
+    else:
+      result = newNodeI(nkRecList, n.info)
+  else:
+    var length = sonsLen(n)
+    if length > 0:
+      newSons(result, length)
+      for i in countup(0, length - 1):
+        result.sons[i] = ReplaceTypeVarsN(cl, n.sons[i])
   
 proc ReplaceTypeVarsS(cl: var TReplTypeVars, s: PSym): PSym = 
   if s == nil: return nil