summary refs log tree commit diff stats
path: root/rod
diff options
context:
space:
mode:
Diffstat (limited to 'rod')
-rwxr-xr-xrod/cgen.nim19
-rwxr-xr-xrod/lexbase.nim4
-rwxr-xr-xrod/semstmts.nim45
-rwxr-xr-xrod/semtypes.nim57
-rwxr-xr-xrod/semtypinst.nim10
-rwxr-xr-xrod/transf.nim2
6 files changed, 74 insertions, 63 deletions
diff --git a/rod/cgen.nim b/rod/cgen.nim
index 51aee87ab..a15c4c4ca 100755
--- a/rod/cgen.nim
+++ b/rod/cgen.nim
@@ -267,7 +267,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
   of frHeader:
     var r = rdLoc(a)
     if not takeAddr: r = ropef("(*$1)", [r])
-    var s = t
+    var s = skipTypes(t, abstractInst)
     while (s.kind == tyObject) and (s.sons[0] != nil):
       app(r, ".Sup")
       s = skipTypes(s.sons[0], abstractInst)
@@ -373,7 +373,7 @@ proc cstringLit(m: BModule, r: var PRope, s: string): PRope =
   
 proc allocParam(p: BProc, s: PSym) = 
   assert(s.kind == skParam)
-  if not (lfParamCopy in s.loc.flags): 
+  if lfParamCopy notin s.loc.flags: 
     inc(p.labels)
     var tmp = con("%LOC", toRope(p.labels))
     incl(s.loc.flags, lfParamCopy)
@@ -383,7 +383,6 @@ proc allocParam(p: BProc, s: PSym) =
     s.loc.r = tmp
 
 proc localDebugInfo(p: BProc, s: PSym) = 
-  var name, a: PRope
   if {optStackTrace, optEndb} * p.options != {optStackTrace, optEndb}: return 
   # XXX work around a bug: No type information for open arrays possible:
   if skipTypes(s.typ, abstractVar).kind == tyOpenArray: return
@@ -391,7 +390,7 @@ proc localDebugInfo(p: BProc, s: PSym) =
     # "address" is the 0th field
     # "typ" is the 1rst field
     # "name" is the 2nd field
-    name = cstringLit(p, p.s[cpsInit], normalize(s.name.s))
+    var name = cstringLit(p, p.s[cpsInit], normalize(s.name.s))
     if (s.kind == skParam) and not ccgIntroducedPtr(s): allocParam(p, s)
     inc(p.labels, 3)
     appf(p.s[cpsInit], "%LOC$6 = getelementptr %TF* %F, %NI 0, $1, %NI 0$n" &
@@ -404,12 +403,12 @@ proc localDebugInfo(p: BProc, s: PSym) =
                                         toRope(p.labels), toRope(p.labels - 1), 
                                         toRope(p.labels - 2)])
   else: 
-    a = con("&", s.loc.r)
+    var a = con("&", s.loc.r)
     if (s.kind == skParam) and ccgIntroducedPtr(s): a = s.loc.r
     appf(p.s[cpsInit], 
-         "F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n", [
-        toRope(p.frameLen), makeCString(normalize(s.name.s)), a, 
-        genTypeInfo(p.module, s.loc.t)])
+         "F.s[$1].address = (void*)$3; F.s[$1].typ = $4; F.s[$1].name = $2;$n",
+         [toRope(p.frameLen), makeCString(normalize(s.name.s)), a, 
+          genTypeInfo(p.module, s.loc.t)])
   inc(p.frameLen)
 
 proc assignLocalVar(p: BProc, s: PSym) = 
@@ -461,7 +460,7 @@ proc iff(cond: bool, the, els: PRope): PRope =
   
 proc assignParam(p: BProc, s: PSym) = 
   assert(s.loc.r != nil)
-  if (sfAddrTaken in s.flags) and (gCmd == cmdCompileToLLVM): allocParam(p, s)
+  if sfAddrTaken in s.flags and gCmd == cmdCompileToLLVM: allocParam(p, s)
   localDebugInfo(p, s)
 
 proc fillProcLoc(sym: PSym) = 
@@ -574,7 +573,7 @@ proc generateHeaders(m: BModule) =
   app(m.s[cfsHeaders], "#include \"nimbase.h\"" & tnl & tnl)
   var it = PStrEntry(m.headerFiles.head)
   while it != nil: 
-    if not (it.data[0] in {'\"', '<'}): 
+    if it.data[0] notin {'\"', '<'}: 
       appf(m.s[cfsHeaders], "#include \"$1\"$n", [toRope(it.data)])
     else: 
       appf(m.s[cfsHeaders], "#include $1$n", [toRope(it.data)])
diff --git a/rod/lexbase.nim b/rod/lexbase.nim
index 4f946b35f..f37fcc0a4 100755
--- a/rod/lexbase.nim
+++ b/rod/lexbase.nim
@@ -164,7 +164,7 @@ proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
   while not (L.buf[i] in {CR, LF, EndOfFile}): 
     add(result, L.buf[i])
     inc(i)
-  result = result & "\n"
+  result.add("\n")
   if marker: 
-    result = result & RepeatChar(getColNumber(L, L.bufpos)) & '^' & "\n"
+    result.add(RepeatChar(getColNumber(L, L.bufpos)) & '^' & "\n")
   
diff --git a/rod/semstmts.nim b/rod/semstmts.nim
index 8f0fc64b5..176fdad1b 100755
--- a/rod/semstmts.nim
+++ b/rod/semstmts.nim
@@ -472,11 +472,7 @@ proc addGenericParamListToScope(c: PContext, n: PNode) =
     if a.kind != nkSym: internalError(a.info, "addGenericParamListToScope")
     addDecl(c, a.sym)
 
-proc SemTypeSection(c: PContext, n: PNode): PNode = 
-  var 
-    s: PSym
-    t, body: PType
-  result = n 
+proc typeSectionLeftSidePass(c: PContext, n: PNode) = 
   # process the symbols on the left side for the whole type section, before
   # we even look at the type definitions on the right
   for i in countup(0, sonsLen(n) - 1): 
@@ -485,7 +481,8 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
     if a.kind == nkCommentStmt: continue 
     if a.kind != nkTypeDef: IllFormedAst(a)
     checkSonsLen(a, 3)
-    if (c.p.owner.kind == skModule): 
+    var s: PSym
+    if c.p.owner.kind == skModule: 
       s = semIdentWithPragma(c, skType, a.sons[0], {sfStar, sfMinus})
       incl(s.flags, sfGlobal)
     else: 
@@ -493,18 +490,20 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
     if s.flags * {sfStar, sfMinus} != {}: incl(s.flags, sfInInterface)
     s.typ = newTypeS(tyForward, c)
     s.typ.sym = s             # process pragmas:
-    if a.sons[0].kind == nkPragmaExpr: 
+    if a.sons[0].kind == nkPragmaExpr:
       pragma(c, s, a.sons[0].sons[1], typePragmas) 
     # add it here, so that recursive types are possible:
     addInterfaceDecl(c, s)
     a.sons[0] = newSymNode(s)
+
+proc typeSectionRightSidePass(c: PContext, n: PNode) =
   for i in countup(0, sonsLen(n) - 1): 
     var a = n.sons[i]
     if a.kind == nkCommentStmt: continue 
     if (a.kind != nkTypeDef): IllFormedAst(a)
     checkSonsLen(a, 3)
     if (a.sons[0].kind != nkSym): IllFormedAst(a)
-    s = a.sons[0].sym
+    var s = a.sons[0].sym
     if (s.magic == mNone) and (a.sons[2].kind == nkEmpty): 
       GlobalError(a.info, errImplOfXexpected, s.name.s)
     if s.magic != mNone: processMagicType(c, s)
@@ -518,13 +517,12 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
         InternalError(a.info, "semTypeSection: containerID")
       s.typ.containerID = getID()
       a.sons[1] = semGenericParamList(c, a.sons[1], s.typ)
-      
       # 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 
+      # like: mydata.seq
       addSon(s.typ, newTypeS(tyEmpty, c))
       s.ast = a
-      body = semTypeNode(c, a.sons[2], nil)
+      var body = semTypeNode(c, a.sons[2], nil)
       if body != nil: body.sym = s
       s.typ.sons[sonsLen(s.typ) - 1] = body
       popOwner()
@@ -532,28 +530,39 @@ proc SemTypeSection(c: PContext, n: PNode): PNode =
     elif a.sons[2].kind != nkEmpty: 
       # process the type's body:
       pushOwner(s)
-      t = semTypeNode(c, a.sons[2], s.typ)
-      if (t != s.typ) and (s.typ != nil): 
-        internalError(a.info, "semTypeSection()")
-      s.typ = t
+      var t = semTypeNode(c, a.sons[2], s.typ)
+      if s.typ == nil: 
+        s.typ = t
+      elif t != s.typ: 
+        # this can happen for e.g. tcan_alias_specialised_generic:
+        assignType(s.typ, t)
+        #debug s.typ
       s.ast = a
       popOwner()
+
+proc typeSectionFinalPass(c: PContext, n: PNode) = 
   for i in countup(0, sonsLen(n) - 1): 
     var a = n.sons[i]
     if a.kind == nkCommentStmt: continue 
     if (a.sons[0].kind != nkSym): IllFormedAst(a)
-    s = a.sons[0].sym         
+    var s = a.sons[0].sym         
     # compute the type's size and check for illegal recursions:
     if a.sons[1].kind == nkEmpty: 
-      if (a.sons[2].kind in {nkSym, nkIdent, nkAccQuoted}): 
+      if a.sons[2].kind in {nkSym, nkIdent, nkAccQuoted}:
         # type aliases are hard:
         #MessageOut('for type ' + typeToString(s.typ));
-        t = semTypeNode(c, a.sons[2], nil)
+        var t = semTypeNode(c, a.sons[2], nil)
         if t.kind in {tyObject, tyEnum}: 
           assignType(s.typ, t)
           s.typ.id = t.id     # same id
       checkConstructedType(s.info, s.typ)
 
+proc SemTypeSection(c: PContext, n: PNode): PNode =
+  typeSectionLeftSidePass(c, n)
+  typeSectionRightSidePass(c, n)
+  typeSectionFinalPass(c, n)
+  result = n
+
 proc semParamList(c: PContext, n, genericParams: PNode, s: PSym) = 
   s.typ = semProcTypeNode(c, n, genericParams, nil)
 
diff --git a/rod/semtypes.nim b/rod/semtypes.nim
index ec5bb9e2f..90a774645 100755
--- a/rod/semtypes.nim
+++ b/rod/semtypes.nim
@@ -421,27 +421,34 @@ proc addInheritedFields(c: PContext, check: var TIntSet, pos: var int,
     addInheritedFields(c, check, pos, obj.sons[0])
   addInheritedFieldsAux(c, check, pos, obj.n)
 
+proc skipGenericInvokation(t: PType): PType {.inline.} = 
+  result = t
+  if result.kind == tyGenericInvokation:
+    result = result.sons[0]
+  if result.kind == tyGenericBody:
+    result = lastSon(result)
+
 proc semObjectNode(c: PContext, n: PNode, prev: PType): PType = 
-  var 
-    check: TIntSet
-    base: PType
-    pos: int
+  var check: TIntSet
   IntSetInit(check)
-  pos = 0 # n.sons[0] contains the pragmas (if any). We process these later...
+  var pos = 0 
+  var base: PType = nil
+  # n.sons[0] contains the pragmas (if any). We process these later...
   checkSonsLen(n, 3)
   if n.sons[1].kind != nkEmpty: 
     base = semTypeNode(c, n.sons[1].sons[0], nil)
-    if base.kind == tyObject: addInheritedFields(c, check, pos, base)
-    else: localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
-  else:
-    base = nil
+    var concreteBase = skipGenericInvokation(skipTypes(base, skipPtrs))
+    if concreteBase.kind == tyObject and tfFinal notin concreteBase.flags: 
+      addInheritedFields(c, check, pos, concreteBase)
+    else:
+      debug base
+      debug concreteBase
+      localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
   if n.kind != nkObjectTy: InternalError(n.info, "semObjectNode")
   result = newOrPrevType(tyObject, prev, c)
   addSon(result, base)
   result.n = newNodeI(nkRecList, n.info)
   semRecordNodeAux(c, n.sons[2], check, pos, result.n, result.sym)
-  if (base != nil) and (tfFinal in base.flags): 
-    localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
   
 proc addTypeVarsOfGenericBody(c: PContext, t: PType, genericParams: PNode, 
                               cl: var TIntSet): PType = 
@@ -559,9 +566,6 @@ proc semBlockType(c: PContext, n: PNode, prev: PType): PType =
   Dec(c.p.nestedBlockCounter)
 
 proc semTypeNode(c: PContext, n: PNode, prev: PType): PType = 
-  var 
-    s: PSym
-    t: PType
   result = nil
   if gCmd == cmdIdeTools: suggestExpr(c, n)
   case n.kind
@@ -576,7 +580,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     else: GlobalError(n.info, errTypeExpected)
   of nkBracketExpr: 
     checkMinSonsLen(n, 2)
-    s = semTypeIdent(c, n.sons[0])
+    var s = semTypeIdent(c, n.sons[0])
     case s.magic
     of mArray: result = semArray(c, n, prev)
     of mOpenArray: result = semContainer(c, n, tyOpenArray, "openarray", prev)
@@ -586,7 +590,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     of mSeq: result = semContainer(c, n, tySequence, "seq", prev)
     else: result = semGeneric(c, n, s, prev)
   of nkIdent, nkDotExpr, nkAccQuoted: 
-    s = semTypeIdent(c, n)
+    var s = semTypeIdent(c, n)
     if s.typ == nil: GlobalError(n.info, errTypeExpected)
     if prev == nil: 
       result = s.typ
@@ -596,7 +600,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
       result = prev
   of nkSym: 
     if (n.sym.kind == skType) and (n.sym.typ != nil): 
-      t = n.sym.typ
+      var t = n.sym.typ
       if prev == nil: 
         result = t
       else: 
@@ -615,20 +619,15 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     checkSonsLen(n, 2)
     result = semProcTypeNode(c, n.sons[0], nil, prev) 
     # dummy symbol for `pragma`:
-    s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c)
+    var s = newSymS(skProc, newIdentNode(getIdent("dummy"), n.info), c)
     s.typ = result
     pragma(c, s, n.sons[1], procTypePragmas)
-  of nkEnumTy: 
-    result = semEnum(c, n, prev)
-  of nkType: 
-    result = n.typ
-  of nkStmtListType: 
-    result = semStmtListType(c, n, prev)
-  of nkBlockType: 
-    result = semBlockType(c, n, prev)
-  else: 
-    GlobalError(n.info, errTypeExpected) 
-    #internalError(n.info, 'semTypeNode(' +{&} nodeKindToStr[n.kind] +{&} ')');
+  of nkEnumTy: result = semEnum(c, n, prev)
+  of nkType: result = n.typ
+  of nkStmtListType: result = semStmtListType(c, n, prev)
+  of nkBlockType: result = semBlockType(c, n, prev)
+  else: GlobalError(n.info, errTypeExpected) 
+  #internalError(n.info, 'semTypeNode(' +{&} nodeKindToStr[n.kind] +{&} ')');
   
 proc setMagicType(m: PSym, kind: TTypeKind, size: int) = 
   m.typ.kind = kind
diff --git a/rod/semtypinst.nim b/rod/semtypinst.nim
index 6427d7858..b6126e285 100755
--- a/rod/semtypinst.nim
+++ b/rod/semtypinst.nim
@@ -12,13 +12,17 @@
 import ast, astalgo, msgs, types, semdata
 
 proc checkConstructedType*(info: TLineInfo, t: PType) = 
-  if (tfAcyclic in t.flags) and (skipTypes(t, abstractInst).kind != tyObject): 
+  if tfAcyclic in t.flags and skipTypes(t, abstractInst).kind != tyObject: 
     LocalError(info, errInvalidPragmaX, "acyclic")
   elif computeSize(t) < 0: 
     LocalError(info, errIllegalRecursionInTypeX, typeToString(t))
-  elif (t.kind == tyVar) and (t.sons[0].kind == tyVar): 
+  elif t.kind == tyVar and t.sons[0].kind == tyVar: 
     LocalError(info, errVarVarTypeNotAllowed)
-
+  when false:
+    if t.kind == tyObject and t.sons[0] != nil:
+      if t.sons[0].kind != tyObject or tfFinal in t.sons[0].flags: 
+        localError(info, errInheritanceOnlyWithNonFinalObjects)
+    
 proc containsGenericTypeIter(t: PType, closure: PObject): bool = 
   result = t.kind in GenericTypes
 
diff --git a/rod/transf.nim b/rod/transf.nim
index c7c4e3db8..d2e6f8c69 100755
--- a/rod/transf.nim
+++ b/rod/transf.nim
@@ -669,7 +669,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
     result = transformFor(c, n)
   of nkCaseStmt: 
     result = transformCase(c, n)
-  of nkProcDef, nkMethodDef, nkIteratorDef, nkMacroDef: 
+  of nkProcDef, nkMethodDef, nkIteratorDef, nkMacroDef, nkConverterDef: 
     if n.sons[genericParamsPos].kind == nkEmpty: 
       n.sons[codePos] = PNode(transform(c, n.sons[codePos]))
       if n.kind == nkMethodDef: methodDef(n.sons[namePos].sym)