summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-03-08 01:59:15 +0100
committerAraq <rumpf_a@web.de>2011-03-08 01:59:15 +0100
commitfa332b729835f70c71ee235626490697779fee87 (patch)
treee6e7039e25fdd73f22bde845e1b02e8b0ded2a5a
parentf9c6cec90c1a67e885b6172a8bccfb014175f60b (diff)
downloadNim-fa332b729835f70c71ee235626490697779fee87.tar.gz
fixes #13; fixes #18
-rwxr-xr-xrod/evals.nim61
-rwxr-xr-xrod/nimrod.nim4
-rw-r--r--tests/accept/run/tmacro2.nim27
-rw-r--r--tests/accept/run/tmacro3.nim31
4 files changed, 102 insertions, 21 deletions
diff --git a/rod/evals.nim b/rod/evals.nim
index 9feb6875f..2dca9896f 100755
--- a/rod/evals.nim
+++ b/rod/evals.nim
@@ -42,7 +42,8 @@ type
 proc newStackFrame*(): PStackFrame
 proc pushStackFrame*(c: PEvalContext, t: PStackFrame)
 proc popStackFrame*(c: PEvalContext)
-proc newEvalContext*(module: PSym, filename: string, optEval: bool): PEvalContext
+proc newEvalContext*(module: PSym, filename: string, 
+                     optEval: bool): PEvalContext
 proc eval*(c: PEvalContext, n: PNode): PNode
   # eval never returns nil! This simplifies the code a lot and
   # makes it faster too.
@@ -50,9 +51,12 @@ proc evalConstExpr*(module: PSym, e: PNode): PNode
 proc evalPass*(): TPass
 # implementation
 
-const 
-  evalMaxIterations = 10000000 # max iterations of all loops
-  evalMaxRecDepth = 100000    # max recursion depth for evaluation
+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
+# the compiler runs on then! Bad idea!
 
 proc newStackFrame(): PStackFrame = 
   new(result)
@@ -87,7 +91,7 @@ proc stackTrace(c: PEvalContext, n: PNode, msg: TMsgKind, arg: string = "") =
   stackTraceAux(c.tos)
   Fatal(n.info, msg, arg)
 
-proc isSpecial(n: PNode): bool = 
+proc isSpecial(n: PNode): bool {.inline.} = 
   result = (n.kind == nkExceptBranch) 
   # or (n.kind == nkEmpty)
   # XXX this does not work yet! Better to compile too much than to compile to
@@ -137,11 +141,10 @@ proc evalWhile(c: PEvalContext, n: PNode): PNode =
     of nkBreakStmt: 
       if result.sons[0].kind == nkEmpty: 
         result = emptyNode    # consume ``break`` token
-        break 
-    of nkExceptBranch, nkReturnToken: 
+      # Bugfix (see tmacro2): but break in any case!
       break 
-    else: 
-      nil
+    of nkExceptBranch, nkReturnToken: break 
+    else: nil
     dec(gWhileCounter)
     if gWhileCounter <= 0: 
       stackTrace(c, n, errTooManyIterations)
@@ -152,7 +155,7 @@ proc evalBlock(c: PEvalContext, n: PNode): PNode =
   if result.kind == nkBreakStmt: 
     if result.sons[0] != nil: 
       assert(result.sons[0].kind == nkSym)
-      if n.sons[0].kind != nkempty: 
+      if n.sons[0].kind != nkEmpty: 
         assert(n.sons[0].kind == nkSym)
         if result.sons[0].sym.id == n.sons[0].sym.id: result = emptyNode
     else: 
@@ -250,6 +253,7 @@ proc evalVar(c: PEvalContext, n: PNode): PNode =
     assert(a.sons[0].kind == nkSym)
     var v = a.sons[0].sym
     if a.sons[2].kind != nkEmpty: 
+      #if a.sons[2].kind == nkNone: echo "Yep"
       result = evalAux(c, a.sons[2], {})
       if isSpecial(result): return 
     else: 
@@ -309,7 +313,9 @@ proc evalArrayAccess(c: PEvalContext, n: PNode, flags: TEvalFlags): PNode =
   result = emptyNode
   case x.kind
   of nkPar: 
-    if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)].sons[1]
+    if (idx >= 0) and (idx < sonsLen(x)): 
+      result = x.sons[int(idx)]
+      if result.kind == nkExprColonExpr: result = result.sons[1]
     else: stackTrace(c, n, errIndexOutOfBounds)
     if not aliasNeeded(result, flags): result = copyTree(result)
   of nkBracket, nkMetaNode: 
@@ -458,12 +464,25 @@ proc evalAnd(c: PEvalContext, n: PNode): PNode =
   
 proc evalNoOpt(c: PEvalContext, n: PNode): PNode = 
   result = newNodeI(nkExceptBranch, n.info) 
-  # creating a nkExceptBranch without sons means that it could not be evaluated
+  # creating a nkExceptBranch without sons 
+  # means that it could not be evaluated
   
 proc evalNew(c: PEvalContext, n: PNode): PNode = 
-  if c.optEval: 
-    result = evalNoOpt(c, n)
-  else: 
+  if c.optEval: return evalNoOpt(c, n)
+  # we ignore the finalizer for now and most likely forever :-)
+  result = evalAux(c, n.sons[1], {efLValue})
+  if isSpecial(result): return 
+  var a = result
+  var t = skipTypes(n.sons[1].typ, abstractVar)
+  if a.kind == nkEmpty: InternalError(n.info, "first parameter is empty")
+  # changing the node kind is ugly and suggests deep problems:
+  a.kind = nkRefTy
+  a.info = n.info
+  a.typ = t
+  a.sons = nil
+  addSon(a, getNullValue(t.sons[0], n.info))
+  result = emptyNode
+  when false:
     var t = skipTypes(n.sons[1].typ, abstractVar)
     result = newNodeIT(nkRefTy, n.info, t)
     addSon(result, getNullValue(t.sons[0], n.info))
@@ -522,8 +541,8 @@ proc evalRangeChck(c: PEvalContext, n: PNode): PNode =
     result = x                # a <= x and x <= b
     result.typ = n.typ
   else: 
-    stackTrace(c, n, errGenerated, `%`(msgKindToString(errIllegalConvFromXtoY), [
-        typeToString(n.sons[0].typ), typeToString(n.typ)]))
+    stackTrace(c, n, errGenerated, msgKindToString(errIllegalConvFromXtoY) % [
+        typeToString(n.sons[0].typ), typeToString(n.typ)])
   
 proc evalConvStrToCStr(c: PEvalContext, n: PNode): PNode = 
   result = evalAux(c, n.sons[0], {})
@@ -623,11 +642,15 @@ proc evalNewSeq(c: PEvalContext, n: PNode): PNode =
   var b = result
   var t = skipTypes(n.sons[1].typ, abstractVar)
   if a.kind == nkEmpty: InternalError(n.info, "first parameter is empty")
+  # changing the node kind is ugly and suggests deep problems:
   a.kind = nkBracket
   a.info = n.info
   a.typ = t
-  for i in countup(0, int(getOrdValue(b)) - 1): 
-    addSon(a, getNullValue(t.sons[0], n.info))
+  a.sons = nil
+  var L = int(getOrdValue(b))
+  newSeq(a.sons, L)
+  for i in countup(0, L-1): 
+    a.sons[i] = getNullValue(t.sons[0], n.info)
   result = emptyNode
 
 proc evalAssert(c: PEvalContext, n: PNode): PNode = 
diff --git a/rod/nimrod.nim b/rod/nimrod.nim
index 4548a0186..a1751da7f 100755
--- a/rod/nimrod.nim
+++ b/rod/nimrod.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2010 Andreas Rumpf
+#        (c) Copyright 2011 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -81,7 +81,7 @@ proc HandleCmdLine() =
           var prog = quoteIfContainsWhite(changeFileExt(filename, ""))
         execExternalProgram(prog & ' ' & arguments)
 
-cmdLineInfo = newLineInfo("command line", - 1, - 1)
+cmdLineInfo = newLineInfo("command line", -1, -1)
 condsyms.InitDefines()
 HandleCmdLine()
 quit(options.gExitcode)
diff --git a/tests/accept/run/tmacro2.nim b/tests/accept/run/tmacro2.nim
new file mode 100644
index 000000000..6aa9bb57d
--- /dev/null
+++ b/tests/accept/run/tmacro2.nim
@@ -0,0 +1,27 @@
+discard """
+  output: "ta-da Your value sir: 'HE!!!!o Wor!!d'"
+"""
+
+import macros, strutils
+
+proc testBlock(): string {.compileTime.} = 
+  block myBlock:
+    while true:
+      echo "inner block"
+      break myBlock
+    echo "outer block"
+  result = "ta-da"
+
+macro mac(n: expr): expr =
+  expectKind(n, nnkCall)
+  expectLen(n, 2)
+  expectKind(n[1], nnkStrLit)
+  var s: string = n[1].strVal
+  s = s.replace("l", "!!")
+  result = newStrLitNode("Your value sir: '$#'" % [s])
+
+const s = testBlock() 
+const t = mac("HEllo World")
+echo s, " ", t
+
+
diff --git a/tests/accept/run/tmacro3.nim b/tests/accept/run/tmacro3.nim
new file mode 100644
index 000000000..fa2040e92
--- /dev/null
+++ b/tests/accept/run/tmacro3.nim
@@ -0,0 +1,31 @@
+discard """
+  output: ""
+"""
+
+import  macros
+
+type 
+    TA = tuple[a: int]
+    PA = ref TA
+
+macro test*(a: stmt): stmt =
+  var val: PA
+  new(val)
+  val.a = 4
+
+test:
+  "hi"
+
+macro test2*(a: stmt): stmt =
+  proc testproc(recurse: int) =
+    echo "Thats weird"
+    var o : PNimrodNode = nil
+    echo "  no its not!"
+    o = newNimNode(nnkNone)
+    if recurse > 0:
+      testproc(recurse - 1)
+  testproc(5)
+
+test2:
+  "hi"
+