summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim6
-rw-r--r--compiler/sem.nim4
-rw-r--r--compiler/semdata.nim1
-rw-r--r--compiler/semstmts.nim4
-rw-r--r--compiler/semtypes.nim35
-rw-r--r--compiler/semtypinst.nim2
-rw-r--r--compiler/sigmatch.nim19
-rw-r--r--compiler/types.nim4
-rw-r--r--compiler/vmgen.nim23
-rw-r--r--tests/macros/tdebugstmt.nim29
-rw-r--r--todo.txt2
11 files changed, 87 insertions, 42 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 7138b5f52..cd002eef1 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1129,7 +1129,7 @@ proc newType(kind: TTypeKind, owner: PSym): PType =
   result.align = 2            # default alignment
   result.id = getID()
   when debugIds:
-    RegisterId(result)
+    registerId(result)
   #if result.id < 2000 then
   #  MessageOut(typeKindToStr[kind] & ' has id: ' & toString(result.id))
   
@@ -1166,7 +1166,7 @@ proc copyType(t: PType, owner: PSym, keepId: bool): PType =
   if keepId: 
     result.id = t.id
   else: 
-    when debugIds: RegisterId(result)
+    when debugIds: registerId(result)
   result.sym = t.sym          # backend-info should not be copied
   
 proc copySym(s: PSym, keepId: bool = false): PSym = 
@@ -1177,7 +1177,7 @@ proc copySym(s: PSym, keepId: bool = false): PSym =
     result.id = s.id
   else: 
     result.id = getID()
-    when debugIds: RegisterId(result)
+    when debugIds: registerId(result)
   result.flags = s.flags
   result.magic = s.magic
   if s.kind == skModule:
diff --git a/compiler/sem.nim b/compiler/sem.nim
index e89e32f4e..00ac79716 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -83,7 +83,9 @@ proc commonType*(x, y: PType): PType =
   elif a.kind == tyTypeDesc:
     # turn any concrete typedesc into the abstract typedesc type
     if a.sons == nil: result = a
-    else: result = newType(tyTypeDesc, a.owner)
+    else:
+      result = newType(tyTypeDesc, a.owner)
+      rawAddSon(result, newType(tyNone, a.owner))
   elif b.kind in {tyArray, tyArrayConstr, tySet, tySequence} and 
       a.kind == b.kind:
     # check for seq[empty] vs. seq[int]
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 8b97f3685..c9d95e1bf 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -211,6 +211,7 @@ proc makeTypeDesc*(c: PContext, typ: PType): PType =
 
 proc makeTypeSymNode*(c: PContext, typ: PType, info: TLineInfo): PNode =
   let typedesc = makeTypeDesc(c, typ)
+  rawAddSon(typedesc, newTypeS(tyNone, c))
   let sym = newSym(skType, idAnon, getCurrOwner(), info).linkTo(typedesc)
   return newSymNode(sym, info)
 
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index d3cc1a12e..0871b7fb7 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -740,7 +740,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
       # we fill it out later. For magic generics like 'seq', it won't be filled
       # so we use tyEmpty instead of nil to not crash for strange conversions
       # like: mydata.seq
-      rawAddSon(s.typ, newTypeS(tyEmpty, c))
+      rawAddSon(s.typ, newTypeS(tyNone, c))
       s.ast = a
       inc c.inGenericContext
       var body = semTypeNode(c, a.sons[2], nil)
@@ -748,7 +748,7 @@ proc typeSectionRightSidePass(c: PContext, n: PNode) =
       if body != nil:
         body.sym = s
         body.size = -1 # could not be computed properly
-      s.typ.sons[sonsLen(s.typ) - 1] = body
+        s.typ.sons[sonsLen(s.typ) - 1] = body
       popOwner()
       closeScope(c)
     elif a.sons[2].kind != nkEmpty: 
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 408b1b62e..6f2d9ece9 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -681,12 +681,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
   of tySequence, tySet, tyArray, tyOpenArray,
      tyVar, tyPtr, tyRef, tyProc:
     # XXX: this is a bit strange, but proc(s: seq)
-    # produces tySequence(tyGenericParam, null).
+    # produces tySequence(tyGenericParam, tyNone).
     # This also seems to be true when creating aliases
     # like: type myseq = distinct seq.
     # Maybe there is another better place to associate
     # the seq type class with the seq identifier.
-    if paramType.kind == tySequence and paramType.lastSon == nil:
+    if paramType.kind == tySequence and paramType.lastSon.kind == tyNone:
       let typ = c.newTypeWithSons(tyBuiltInTypeClass,
                                   @[newTypeS(paramType.kind, c)])
       result = addImplicitGeneric(typ)
@@ -1133,15 +1133,26 @@ proc processMagicType(c: PContext, m: PSym) =
   of mNil: setMagicType(m, tyNil, ptrSize)
   of mExpr: setMagicType(m, tyExpr, 0)
   of mStmt: setMagicType(m, tyStmt, 0)
-  of mTypeDesc: setMagicType(m, tyTypeDesc, 0)
+  of mTypeDesc: 
+    setMagicType(m, tyTypeDesc, 0)
+    rawAddSon(m.typ, newTypeS(tyNone, c))
   of mVoidType: setMagicType(m, tyEmpty, 0)
-  of mArray: setMagicType(m, tyArray, 0)
-  of mOpenArray: setMagicType(m, tyOpenArray, 0)
-  of mVarargs: setMagicType(m, tyVarargs, 0)
-  of mRange: setMagicType(m, tyRange, 0)
-  of mSet: setMagicType(m, tySet, 0) 
-  of mSeq: setMagicType(m, tySequence, 0)
-  of mOrdinal: setMagicType(m, tyOrdinal, 0)
+  of mArray:
+    setMagicType(m, tyArray, 0)
+  of mOpenArray:
+    setMagicType(m, tyOpenArray, 0)
+  of mVarargs:
+    setMagicType(m, tyVarargs, 0)
+  of mRange:
+    setMagicType(m, tyRange, 0)
+    rawAddSon(m.typ, newTypeS(tyNone, c))
+  of mSet:
+    setMagicType(m, tySet, 0) 
+  of mSeq: 
+    setMagicType(m, tySequence, 0)
+  of mOrdinal:
+    setMagicType(m, tyOrdinal, 0)
+    rawAddSon(m.typ, newTypeS(tyNone, c))
   of mPNimrodNode: discard
   else: localError(m.info, errTypeExpected)
   
@@ -1165,8 +1176,8 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
       typ = semTypeNode(c, constraint, nil)
       if typ.kind != tyStatic or typ.len == 0:
         if typ.kind == tyTypeDesc:
-          if typ.len == 0:
-            typ = newTypeS(tyTypeDesc, c)
+          if typ.sons[0].kind == tyNone:
+            typ = newTypeWithSons(c, tyTypeDesc, @[newTypeS(tyNone, c)])
         else:
           typ = semGenericConstraints(c, typ)
     
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index 1158335a8..a07d91241 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -358,7 +358,7 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
     if lookup != nil:
       result = lookup
       if tfUnresolved in t.flags: result = result.base
-    elif t.sonsLen > 0:
+    elif t.sons[0].kind != tyNone:
       result = makeTypeDesc(cl.c, replaceTypeVarsT(cl, t.sons[0]))
  
   of tyUserTypeClass:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index d269e9e69..f9200ea0c 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -562,10 +562,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       #if result < isGeneric: result = isNone
       if result notin {isNone, isGeneric}:
         result = typeRangeRel(f, a)
-    elif skipTypes(f, {tyRange}).kind == a.kind:
-      result = isIntConv
-    elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
-      result = isConvertible  # a convertible to f
+    else:
+      if skipTypes(f, {tyRange}).kind == a.kind:
+        result = isIntConv
+      elif isConvertibleToRange(skipTypes(f, {tyRange}), a):
+        result = isConvertible  # a convertible to f
   of tyInt:      result = handleRange(f, a, tyInt8, tyInt32)
   of tyInt8:     result = handleRange(f, a, tyInt8, tyInt8)
   of tyInt16:    result = handleRange(f, a, tyInt8, tyInt16)
@@ -636,7 +637,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   of tyOrdinal:
     if isOrdinalType(a):
       var x = if a.kind == tyOrdinal: a.sons[0] else: a
-      if f.sonsLen == 0:
+      if f.sons[0].kind == tyNone:
         result = isGeneric
       else:
         result = typeRel(c, f.sons[0], x)
@@ -736,7 +737,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   of tyGenericInst:
     let roota = a.skipGenericAlias
     let rootf = f.skipGenericAlias
-    if a.kind == tyGenericInst and roota.base == rootf.base :
+    if a.kind == tyGenericInst and roota.base == rootf.base:
       for i in 1 .. rootf.sonsLen-2:
         let ff = rootf.sons[i]
         let aa = roota.sons[i]
@@ -845,7 +846,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         # by a tyTypeDesc params. Unfortunately, this requires more substantial
         # changes in semtypinst and elsewhere.
         if a.kind == tyTypeDesc:
-          if f.sons == nil or f.sons.len == 0:
+          if f.sonsLen == 0:
             result = isGeneric
           else:
             internalAssert a.sons != nil and a.sons.len > 0
@@ -854,7 +855,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         else:
           result = isNone
       else:
-        if f.sonsLen > 0:
+        if f.sonsLen > 0 and f.sons[0].kind != tyNone:
           result = typeRel(c, f.lastSon, a)
         else:
           result = isGeneric
@@ -883,7 +884,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     var prev = PType(idTableGet(c.bindings, f))
     if prev == nil:
       if a.kind == tyTypeDesc:
-        if f.sonsLen == 0:
+        if f.sons[0].kind == tyNone:
           result = isGeneric
         else:
           result = typeRel(c, f.sons[0], a.sons[0])
diff --git a/compiler/types.nim b/compiler/types.nim
index 812cd4e93..db75cd3c0 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -47,7 +47,7 @@ proc equalParams*(a, b: PNode): TParamsEquality
   # returns whether the parameter lists of the procs a, b are exactly the same
 proc isOrdinalType*(t: PType): bool
 proc enumHasHoles*(t: PType): bool
-# XXX it is WRONG to include tyTypeDesc here as that might not have any child!
+
 const
   abstractPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyDistinct, tyOrdinal,
                    tyConst, tyMutable, tyTypeDesc}
@@ -1258,7 +1258,7 @@ proc containsGenericTypeIter(t: PType, closure: PObject): bool =
     return true
 
   if t.kind == tyTypeDesc:
-    if t.sonsLen == 0: return true
+    if t.sons[0].kind == tyNone: return true
     if containsGenericTypeIter(t.base, closure): return true
     return false
   
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim
index be32f990f..313c43dc4 100644
--- a/compiler/vmgen.nim
+++ b/compiler/vmgen.nim
@@ -946,6 +946,14 @@ proc genAsgn(c: PCtx; dest: TDest; ri: PNode; requiresCopy: bool) =
 
 template isGlobal(s: PSym): bool = sfGlobal in s.flags and s.kind != skForVar
 
+proc setSlot(c: PCtx; v: PSym) =
+  # XXX generate type initialization here?
+  if v.position == 0:
+    v.position = c.prc.maxSlots
+    c.prc.slots[v.position] = (inUse: true,
+        kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
+    inc c.prc.maxSlots
+
 proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
   case le.kind
   of nkBracketExpr:
@@ -973,8 +981,9 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
         gen(c, ri, tmp)
         c.gABx(le, whichAsgnOpc(le, opcWrGlobal), tmp, s.position)
     else:
+      if s.kind == skForVar and c.mode == emRepl: c.setSlot s
       internalAssert s.position > 0 or (s.position == 0 and
-                                        s.kind in {skParam,skResult,skForVar})
+                                        s.kind in {skParam,skResult})
       var dest: TRegister = s.position + ord(s.kind == skParam)
       gen(c, ri, dest)
   else:
@@ -1035,8 +1044,9 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
     else:
       c.gABx(n, opcLdGlobal, dest, s.position)
   else:
+    if s.kind == skForVar and c.mode == emRepl: c.setSlot s
     if s.position > 0 or (s.position == 0 and
-                          s.kind in {skParam,skResult,skForVar}):
+                          s.kind in {skParam,skResult}):
       if dest < 0:
         dest = s.position + ord(s.kind == skParam)
       else:
@@ -1045,7 +1055,6 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest) =
     else:
       # see tests/t99bott for an example that triggers it:
       cannotEval(n)
-      #InternalError(n.info, s.name.s & " " & $s.position)
 
 proc genAccess(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
                flags: TGenFlags) =
@@ -1123,14 +1132,6 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
     result = newNodeIT(nkCurly, info, t)
   else: internalError("getNullValue: " & $t.kind)
 
-proc setSlot(c: PCtx; v: PSym) =
-  # XXX generate type initialization here?
-  if v.position == 0:
-    v.position = c.prc.maxSlots
-    c.prc.slots[v.position] = (inUse: true,
-        kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
-    inc c.prc.maxSlots
-
 proc genVarSection(c: PCtx; n: PNode) =
   for a in n:
     if a.kind == nkCommentStmt: continue
diff --git a/tests/macros/tdebugstmt.nim b/tests/macros/tdebugstmt.nim
new file mode 100644
index 000000000..865dc436a
--- /dev/null
+++ b/tests/macros/tdebugstmt.nim
@@ -0,0 +1,29 @@
+discard """
+  output: '''a[0]: 42
+a[1]: 45
+x: some string'''
+"""
+
+import macros
+
+macro debug(n: varargs[expr]): stmt =
+  # `n` is a Nimrod AST that contains the whole macro invocation
+  # this macro returns a list of statements:
+  result = newNimNode(nnkStmtList, n)
+  # iterate over any argument that is passed to this macro:
+  for i in 0..n.len-1:
+    # add a call to the statement list that writes the expression;
+    # `toStrLit` converts an AST to its string representation:
+    add(result, newCall("write", newIdentNode("stdout"), toStrLit(n[i])))
+    # add a call to the statement list that writes ": "
+    add(result, newCall("write", newIdentNode("stdout"), newStrLitNode(": ")))
+    # add a call to the statement list that writes the expressions value:
+    add(result, newCall("writeln", newIdentNode("stdout"), n[i]))
+
+var
+  a: array [0..10, int]
+  x = "some string"
+a[0] = 42
+a[1] = 45
+
+debug(a[0], a[1], x)
diff --git a/todo.txt b/todo.txt
index 6f8726199..fef073f90 100644
--- a/todo.txt
+++ b/todo.txt
@@ -2,7 +2,7 @@ version 0.9.4
 =============
 
 - fix macros\tstringinterp.nim
-- test and fix showoff; add debug example to showoff
+- test and fix showoff
 - test and fix stdlib
 - test and fix misc
 - fix GC issues