summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-10-07 09:02:08 +0200
committerAraq <rumpf_a@web.de>2011-10-07 09:02:08 +0200
commit42516c0086faa41c0d8613759ebc263bd1e989e9 (patch)
treea858aebc4e2a786256b8b52457745ec8904d0c91 /compiler
parente9b7d5e68eeeb6d468d407437502fd1c178adc43 (diff)
downloadNim-42516c0086faa41c0d8613759ebc263bd1e989e9.tar.gz
code generator supports constant sequences; more consistent compile time evaluation
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ast.nim6
-rwxr-xr-xcompiler/ccgexprs.nim25
-rwxr-xr-xcompiler/ccgstmts.nim3
-rwxr-xr-xcompiler/ecmasgen.nim1
-rwxr-xr-xcompiler/evals.nim16
-rwxr-xr-xcompiler/sem.nim23
-rwxr-xr-xcompiler/semexprs.nim44
-rwxr-xr-xcompiler/semfold.nim20
-rwxr-xr-xcompiler/semstmts.nim41
-rwxr-xr-xcompiler/transf.nim24
-rwxr-xr-xcompiler/types.nim2
11 files changed, 123 insertions, 82 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 775f679df..b33d99554 100755
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -559,9 +559,11 @@ const
     tyBool, tyChar, tyEnum, tyArray, tyObject, 
     tySet, tyTuple, tyRange, tyPtr, tyRef, tyVar, tySequence, tyProc,
     tyPointer, 
-    tyOpenArray, tyString, tyCString, tyInt..tyInt64, tyFloat..tyFloat128} 
+    tyOpenArray, tyString, tyCString, tyInt..tyInt64, tyFloat..tyFloat128,
+    tyUInt..tyUInt64} 
   
-  ConstantDataTypes*: TTypeKinds = {tyArray, tySet, tyTuple}
+  ConstantDataTypes*: TTypeKinds = {tyArrayConstr, tyArray, tySet, 
+                                    tyTuple, tySequence}
   ExportableSymKinds* = {skVar, skConst, skProc, skMethod, skType, skIterator, 
     skMacro, skTemplate, skConverter, skStub}
   PersistentNodeFlags*: TNodeFlags = {nfBase2, nfBase8, nfBase16, nfAllConst}
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 409dd51c2..826832438 100755
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1831,6 +1831,7 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
     if sym.loc.r == nil or sym.loc.t == nil:
       InternalError(e.info, "expr: proc not init " & sym.name.s)
     putLocIntoDest(p, d, sym.loc)
+  of nkMetaNode: expr(p, e.sons[0], d)
   else: InternalError(e.info, "expr(" & $e.kind & "); unknown node kind")
 
 proc genNamedConstExpr(p: BProc, n: PNode): PRope =
@@ -1845,6 +1846,24 @@ proc genConstSimpleList(p: BProc, n: PNode): PRope =
   if length > 0: app(result, genNamedConstExpr(p, n.sons[length - 1]))
   appf(result, "}$n")
 
+proc genConstSeq(p: BProc, n: PNode, t: PType): PRope =
+  var data = ropef("{{$1, $1}", n.len.toRope)
+  for i in countup(0, n.len - 1):
+    appf(data, ",$1$n", [genConstExpr(p, n.sons[i])])
+  data.app("}")
+  
+  inc(p.labels)
+  result = con("CNSTSEQ", p.labels.toRope)
+  
+  appcg(p.module, cfsData,
+        "NIM_CONST struct {$n" & 
+        "  #TGenericSeq Sup;$n" &
+        "  $1 data[$2];$n" & 
+        "} $3 = $4;$n", [
+        getTypeDesc(p.module, t.sons[0]), n.len.toRope, result, data])
+
+  result = ropef("(($1)&$2)", [getTypeDesc(p.module, t), result])
+
 proc genConstExpr(p: BProc, n: PNode): PRope =
   case n.Kind
   of nkHiddenStdConv, nkHiddenSubConv:
@@ -1855,7 +1874,11 @@ proc genConstExpr(p: BProc, n: PNode): PRope =
     result = genRawSetData(cs, int(getSize(n.typ)))
   of nkBracket, nkPar:
     # XXX: tySequence!
-    result = genConstSimpleList(p, n)
+    var t = skipTypes(n.typ, abstractInst)
+    if t.kind == tySequence:
+      result = genConstSeq(p, n, t)
+    else:
+      result = genConstSimpleList(p, n)
   else:
     var d: TLoc
     initLocExpr(p, n, d)
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index f982f2c22..bf3d6aea1 100755
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -67,7 +67,8 @@ proc genConstStmt(p: BProc, t: PNode) =
     var c = it.sons[0].sym 
     if sfFakeConst in c.flags:
       genSingleVar(p, it)
-    elif c.typ.kind in ConstantDataTypes and not (lfNoDecl in c.loc.flags): 
+    elif c.typ.kind in ConstantDataTypes and not (lfNoDecl in c.loc.flags) and
+        c.ast.len != 0: 
       # generate the data:
       fillLoc(c.loc, locData, c.typ, mangleName(c), OnUnknown)
       if sfImportc in c.flags: 
diff --git a/compiler/ecmasgen.nim b/compiler/ecmasgen.nim
index 42643b39e..7ad4dbd8b 100755
--- a/compiler/ecmasgen.nim
+++ b/compiler/ecmasgen.nim
@@ -1426,6 +1426,7 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) =
   of nkCStringToString: convCStrToStr(p, n, r)
   of nkStmtListExpr: genStmtListExpr(p, n, r)
   of nkEmpty: nil
+  of nkMetaNode: gen(p, n.sons[0], r)
   else: InternalError(n.info, "gen: unknown node type: " & $n.kind)
   
 var globals: PGlobals
diff --git a/compiler/evals.nim b/compiler/evals.nim
index a61d687ef..1d443a404 100755
--- a/compiler/evals.nim
+++ b/compiler/evals.nim
@@ -43,7 +43,7 @@ const
   evalMaxIterations = 500_000 # max iterations of all loops
   evalMaxRecDepth = 10_000    # max recursion depth for evaluation
 
-# Much better: use a timeout! -> Wether code compiles depends on the machine
+# other idea: use a timeout! -> Wether code compiles depends on the machine
 # the compiler runs on then! Bad idea!
 
 proc newStackFrame*(): PStackFrame = 
@@ -754,17 +754,15 @@ proc evalRepr(c: PEvalContext, n: PNode): PNode =
   if isSpecial(result): return 
   result = newStrNodeT(renderTree(result, {renderNoComments}), n)
 
-proc isEmpty(n: PNode): bool = 
-  result = (n != nil) and (n.kind == nkEmpty)
+proc isEmpty(n: PNode): bool =
+  result = n != nil and n.kind == nkEmpty
 
 # The lexer marks multi-line strings as residing at the line where they 
 # are closed. This function returns the line where the string begins
 # Maybe the lexer should mark both the beginning and the end of expressions,
 # then this function could be removed.
 proc stringStartingLine(s: PNode): int =
-  var totalLines = 0
-  for ln in splitLines(s.strVal): inc totalLines
-  result = s.info.line - totalLines
+  result = s.info.line - countLines(s.strVal)
 
 proc evalParseExpr(c: PEvalContext, n: Pnode): Pnode =
   var code = evalAux(c, n.sons[1], {})
@@ -1069,9 +1067,6 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
   dec(gNestedEvals)
   if gNestedEvals <= 0: stackTrace(c, n, errTooManyIterations)
   case n.kind                 # atoms:
-  of nkMetaNode:
-    result = copyTree(n.sons[0])
-    result.typ = n.typ
   of nkEmpty: result = n
   of nkSym: result = evalSym(c, n, flags)
   of nkType..nkNilLit: result = copyNode(n) # end of atoms
@@ -1131,6 +1126,9 @@ proc evalAux(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
      nkTypeSection, nkTemplateDef, nkConstSection, nkIteratorDef,
      nkConverterDef, nkIncludeStmt, nkImportStmt, nkFromStmt: 
     nil
+  of nkMetaNode:
+    result = copyTree(n.sons[0])
+    result.typ = n.typ
   of nkIdentDefs, nkCast, nkYieldStmt, nkAsmStmt, nkForStmt, nkPragmaExpr, 
      nkLambda, nkContinueStmt, nkIdent: 
     stackTrace(c, n, errCannotInterpretNodeX, $n.kind)
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 78a04f744..dcbdac157 100755
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -55,25 +55,26 @@ proc ParamsTypeCheck(c: PContext, typ: PType) {.inline.} =
     GlobalError(typ.n.info, errXisNoType, typeToString(typ))
 
 proc semConstExpr(c: PContext, n: PNode): PNode = 
-  result = semExprWithType(c, n)
-  if result == nil: 
-    GlobalError(n.info, errConstExprExpected)
-    return 
-  result = getConstExpr(c.module, result)
-  if result == nil: GlobalError(n.info, errConstExprExpected)
-  
-proc semAndEvalConstExpr(c: PContext, n: PNode): PNode = 
   var e = semExprWithType(c, n)
   if e == nil: 
     GlobalError(n.info, errConstExprExpected)
     return nil
   result = getConstExpr(c.module, e)
-  if result == nil: 
-    #writeln(output, renderTree(n));
+  if result == nil:
     result = evalConstExpr(c.module, e)
     if result == nil or result.kind == nkEmpty: 
       GlobalError(n.info, errConstExprExpected)
-
+  when false:
+    result = semExprWithType(c, n)
+    if result == nil: 
+      GlobalError(n.info, errConstExprExpected)
+      return 
+    result = getConstExpr(c.module, result)
+    if result == nil: GlobalError(n.info, errConstExprExpected)
+  
+proc semAndEvalConstExpr(c: PContext, n: PNode): PNode = 
+  result = semConstExpr(c, n)
+  
 include seminst, semcall
   
 proc typeMismatch(n: PNode, formal, actual: PType) = 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index e720cf055..356f1c196 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -9,10 +9,6 @@
 
 # this module does the semantic checking for expressions
 
-const 
-  ConstAbstractTypes = {tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, 
-    tyArrayConstr, tyTuple, tySet}
-
 proc semTemplateExpr(c: PContext, n: PNode, s: PSym, semCheck = true): PNode = 
   markUsed(n, s)
   pushInfoContext(n.info)
@@ -49,6 +45,11 @@ proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
 proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
   result = symChoice(c, n, s)
   
+proc inlineConst(n: PNode, s: PSym): PNode {.inline.} =
+  result = copyTree(s.ast)
+  result.typ = s.typ
+  result.info = n.info
+
 proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode = 
   case s.kind
   of skProc, skMethod, skIterator, skConverter: 
@@ -56,24 +57,25 @@ proc semSym(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
         getModule(s).id != c.module.id: 
       LocalError(n.info, errXCannotBePassedToProcVar, s.name.s)
     result = symChoice(c, n, s)
-  of skConst: 
-    #
-    # Consider::
-    #     const x = []
-    #     proc p(a: openarray[int])
-    #     proc q(a: openarray[char])
-    #     p(x)
-    #     q(x)
-    #
-    # It is clear that ``[]`` means two totally different things. Thus, we
-    # copy `x`'s AST into each context, so that the type fixup phase can
-    # deal with two different ``[]``.
-    #
+  of skConst:
     markUsed(n, s)
-    if s.typ.kind in ConstAbstractTypes:
-      result = copyTree(s.ast)
-      result.typ = s.typ
-      result.info = n.info
+    case skipTypes(s.typ, abstractInst).kind
+    of  tyNil, tyChar, tyInt..tyInt64, tyFloat..tyFloat128, 
+        tyTuple, tySet, tyUInt..tyUInt64:
+      result = inlineConst(n, s)
+    of tyArrayConstr, tySequence:
+      # Consider::
+      #     const x = []
+      #     proc p(a: openarray[int])
+      #     proc q(a: openarray[char])
+      #     p(x)
+      #     q(x)
+      #
+      # It is clear that ``[]`` means two totally different things. Thus, we
+      # copy `x`'s AST into each context, so that the type fixup phase can
+      # deal with two different ``[]``.
+      if s.ast.len == 0: result = inlineConst(n, s)
+      else: result = newSymNode(s, n.info)
     else:
       result = newSymNode(s, n.info)
   of skMacro: result = semMacroExpr(c, n, s)
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 570656a39..77d84b6f8 100755
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -181,10 +181,8 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
     result.info = n.info
   of mConStrStr: result = newStrNodeT(getStrOrChar(a) & getStrOrChar(b), n)
   of mInSet: result = newIntNodeT(Ord(inSet(a, b)), n)
-  of mRepr: 
-    # BUGFIX: we cannot eval mRepr here. But this means that it is not 
-    # available for interpretation. I don't know how to fix this.
-    #result := newStrNodeT(renderTree(a, {@set}[renderNoComments]), n);      
+  of mRepr:
+    # BUGFIX: we cannot eval mRepr here for reasons that I forgot.
   of mIntToStr, mInt64ToStr: result = newStrNodeT($(getOrdValue(a)), n)
   of mBoolToStr: 
     if getOrdValue(a) == 0: result = newStrNodeT("false", n)
@@ -324,7 +322,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
     var s = n.sym
     if s.kind == skEnumField: 
       result = newIntNodeT(s.position, n)
-    elif (s.kind == skConst): 
+    elif s.kind == skConst: 
       case s.magic
       of mIsMainModule: result = newIntNodeT(ord(sfMainModule in m.flags), n)
       of mCompileDate: result = newStrNodeT(times.getDateStr(), n)
@@ -370,10 +368,14 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
       of mLow: 
         result = newIntNodeT(firstOrd(n.sons[1].typ), n)
       of mHigh: 
-        if not (skipTypes(n.sons[1].typ, abstractVar).kind in
-            {tyOpenArray, tySequence, tyString}): 
-          result = newIntNodeT(lastOrd(skipTypes(n.sons[1].typ, abstractVar)),
-                               n)
+        if  skipTypes(n.sons[1].typ, abstractVar).kind notin
+            {tyOpenArray, tySequence, tyString}: 
+          result = newIntNodeT(lastOrd(skipTypes(n[1].typ, abstractVar)), n)
+        else:
+          var a = n.sons[1]
+          if a.kind == nkBracket:
+            # we can optimize it away: 
+            result = newIntNodeT(sonsLen(a)-1, n)
       of mLengthOpenArray:
         var a = n.sons[1]
         if a.kind == nkBracket: 
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index decc8a2d7..c00b68bb5 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -280,22 +280,33 @@ proc semConst(c: PContext, n: PNode): PNode =
     var typ: PType = nil
     if a.sons[1].kind != nkEmpty: typ = semTypeNode(c, a.sons[1], nil)
 
-    var e = semExprWithType(c, a.sons[2])
-    if e == nil: GlobalError(a.sons[2].info, errConstExprExpected)
-    var def = getConstExpr(c.module, e)
-    if def == nil: 
-      v.flags.incl(sfFakeConst)
-      def = evalConstExpr(c.module, e)
-      if def == nil or def.kind == nkEmpty: def = e
-    # check type compatibility between def.typ and typ:
-    if typ != nil:
-      def = fitRemoveHiddenConv(c, typ, def)
-    else:
-      typ = def.typ
-    if not typeAllowed(typ, skConst):
-      v.flags.incl(sfFakeConst)
-      if not typeAllowed(typ, skVar):
+    when true:
+      var def = semConstExpr(c, a.sons[2])
+      if def == nil: GlobalError(a.sons[2].info, errConstExprExpected)
+      # check type compatibility between def.typ and typ:
+      if typ != nil:
+        def = fitRemoveHiddenConv(c, typ, def)
+      else:
+        typ = def.typ
+      if not typeAllowed(typ, skConst):
         GlobalError(a.info, errXisNoType, typeToString(typ))
+    else:
+      var e = semExprWithType(c, a.sons[2])
+      if e == nil: GlobalError(a.sons[2].info, errConstExprExpected)
+      var def = getConstExpr(c.module, e)
+      if def == nil: 
+        v.flags.incl(sfFakeConst)
+        def = evalConstExpr(c.module, e)
+        if def == nil or def.kind == nkEmpty: def = e
+      # check type compatibility between def.typ and typ:
+      if typ != nil:
+        def = fitRemoveHiddenConv(c, typ, def)
+      else:
+        typ = def.typ
+      if not typeAllowed(typ, skConst):
+        v.flags.incl(sfFakeConst)
+        if not typeAllowed(typ, skVar):
+          GlobalError(a.info, errXisNoType, typeToString(typ))
     v.typ = typ
     v.ast = def               # no need to copy
     addInterfaceDecl(c, v)
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 482332f38..9c67165e3 100755
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -161,7 +161,6 @@ proc newAsgnStmt(c: PTransf, le: PNode, ri: PTransNode): PTransNode =
 
 proc transformSymAux(c: PTransf, n: PNode): PNode = 
   var b: PNode
-  if (n.kind != nkSym): internalError(n.info, "transformSym")
   var tc = c.transCon
   if sfBorrow in n.sym.flags: 
     # simply exchange the symbol:
@@ -176,14 +175,15 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
     if result != nil: return
     tc = tc.next
   result = b
-  case b.sym.kind
-  of skConst, skEnumField: 
-    if sfFakeConst notin b.sym.flags:
-      if skipTypes(b.sym.typ, abstractInst).kind notin ConstantDataTypes: 
-        result = getConstExpr(c.module, b)
-        if result == nil: InternalError(b.info, "transformSym: const")
-  else: 
-    nil
+  when false:
+    case b.sym.kind
+    of skConst, skEnumField: 
+      if sfFakeConst notin b.sym.flags:
+        if skipTypes(b.sym.typ, abstractInst).kind notin ConstantDataTypes: 
+          result = getConstExpr(c.module, b)
+          if result == nil: InternalError(b.info, "transformSym: const")
+    else: 
+      nil
 
 proc transformSym(c: PTransf, n: PNode): PTransNode = 
   result = PTransNode(transformSymAux(c, n))
@@ -360,7 +360,7 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
   var dest = skipTypes(n.typ, abstractVarRange)
   var source = skipTypes(n.sons[1].typ, abstractVarRange)
   case dest.kind
-  of tyInt..tyInt64, tyEnum, tyChar, tyBool: 
+  of tyInt..tyInt64, tyEnum, tyChar, tyBool, tyUInt..tyUInt64: 
     if not isOrdinalType(source):
       # XXX int64 -> float conversion?
       result = transformSons(c, n)
@@ -659,7 +659,7 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
 proc transform(c: PTransf, n: PNode): PTransNode = 
   case n.kind
   of nkSym: 
-    return transformSym(c, n)
+    result = transformSym(c, n)
   of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: 
     # nothing to be done for leaves:
     result = PTransNode(n)
@@ -719,7 +719,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
   else:
     result = transformSons(c, n)
   var cnst = getConstExpr(c.module, PNode(result))
-  if cnst != nil: 
+  if cnst != nil and (cnst.kind != nkBracket or cnst.len == 0): 
     result = PTransNode(cnst) # do not miss an optimization  
  
 proc processTransf(context: PPassContext, n: PNode): PNode = 
diff --git a/compiler/types.nim b/compiler/types.nim
index 144f4052e..cc1281b6e 100755
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -762,7 +762,7 @@ proc typeAllowedAux(marker: var TIntSet, typ: PType, kind: TSymKind): bool =
   of tyOpenArray, tyVarargs: 
     result = (kind == skParam) and typeAllowedAux(marker, t.sons[0], skVar)
   of tySequence: 
-    result = (kind != skConst) and typeAllowedAux(marker, t.sons[0], skVar) or
+    result = typeAllowedAux(marker, t.sons[0], skVar) or
         t.sons[0].kind == tyEmpty
   of tyArray:
     result = typeAllowedAux(marker, t.sons[1], skVar) or