summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-07-31 22:39:17 +0200
committerAraq <rumpf_a@web.de>2011-07-31 22:39:17 +0200
commit3e806a374a1b42246e947965677c4a1520f3db57 (patch)
treebf2de9968a3288e5f6418eec65e4dbd6587bc07e
parent4f7fa0591112e70f7eacef051a215e3420f78da8 (diff)
downloadNim-3e806a374a1b42246e947965677c4a1520f3db57.tar.gz
'var T' for iterators
-rwxr-xr-xcompiler/ccgexprs.nim2
-rwxr-xr-xcompiler/semexprs.nim9
-rwxr-xr-xcompiler/semstmts.nim25
-rwxr-xr-xcompiler/transf.nim10
-rwxr-xr-xexamples/lazarus/backend.nim5
-rw-r--r--tests/accept/run/tmoditer.nim29
-rwxr-xr-xtodo.txt10
7 files changed, 79 insertions, 11 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 1e30df7ad..f6680d252 100755
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -207,7 +207,7 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   # This function replaces all other methods for generating
   # the assignment operation in C.
   if src.t != nil and src.t.kind == tyPtr:
-    # little HACK to suppor the new 'var T' as return type:
+    # little HACK to support the new 'var T' as return type:
     appcg(p, cpsStmts, "$1 = $2;$n", [rdLoc(dest), rdLoc(src)])
     return
   var ty = skipTypes(dest.t, abstractVarRange)
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index d403aeef1..3bbc0c71f 100755
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -36,6 +36,15 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     GlobalError(n.info, errExprXHasNoType, 
                 renderTree(result, {renderNoComments}))
 
+proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = 
+  result = semExpr(c, n, flags)
+  if result.kind == nkEmpty: 
+    # do not produce another redundant error message:
+    raiseRecoverableError()
+  if result.typ == nil:
+    GlobalError(n.info, errExprXHasNoType, 
+                renderTree(result, {renderNoComments}))
+
 proc semSymGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
   result = symChoice(c, n, s)
   
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 52fc2ea31..1c6c90c84 100755
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -167,6 +167,26 @@ proc SemReturn(c: PContext, n: PNode): PNode =
     if n[0][1].kind == nkSym and n[0][1].sym.kind == skResult: 
       n.sons[0] = ast.emptyNode
   
+proc SemYieldVarResult(c: PContext, n: PNode, restype: PType) =
+  var t = skipTypes(restype, {tyGenericInst})
+  case t.kind
+  of tyVar:
+    n.sons[0] = takeImplicitAddr(c, n.sons[0])
+  of tyTuple:
+    for i in 0.. <t.sonsLen:
+      var e = skipTypes(t.sons[i], {tyGenericInst})
+      if e.kind == tyVar:
+        if n.sons[0].kind == nkPar:
+          n.sons[0].sons[i] = takeImplicitAddr(c, n.sons[0].sons[i])
+        elif n.sons[0].kind == nkHiddenSubConv and 
+             n.sons[0].sons[1].kind == nkPar:
+          var a = n.sons[0].sons[1]
+          a.sons[i] = takeImplicitAddr(c, a.sons[i])
+        else:
+          debug n.sons[0]
+          localError(n.sons[0].info, errXExpected, "tuple constructor")
+  else: nil
+  
 proc SemYield(c: PContext, n: PNode): PNode = 
   result = n
   checkSonsLen(n, 1)
@@ -178,7 +198,8 @@ proc SemYield(c: PContext, n: PNode): PNode =
     if restype != nil: 
       n.sons[0] = fitNode(c, restype, n.sons[0])
       if n.sons[0].typ == nil: InternalError(n.info, "semYield")
-    else: 
+      SemYieldVarResult(c, n, restype)
+    else:
       localError(n.info, errCannotReturnExpr)
   
 proc fitRemoveHiddenConv(c: PContext, typ: Ptype, n: PNode): PNode = 
@@ -361,7 +382,7 @@ proc semFor(c: PContext, n: PNode): PNode =
   checkMinSonsLen(n, 3)
   var length = sonsLen(n)
   openScope(c.tab)
-  n.sons[length-2] = semExprWithType(c, n.sons[length-2], {efWantIterator})
+  n.sons[length-2] = semExprNoDeref(c, n.sons[length-2], {efWantIterator})
   var call = n.sons[length-2]
   if call.kind != nkCall or call.sons[0].kind != nkSym or
       call.sons[0].sym.kind != skIterator: 
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 78814edd8..caa73da25 100755
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -502,9 +502,15 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
       addVar(v, newSymNode(temp))
       add(result, newAsgnStmt(c, newSymNode(temp), arg.ptransNode))
       IdNodeTablePut(newC.mapping, formal, newSymNode(temp))
-    of paVarAsgn: 
+    of paVarAsgn:
       assert(skipTypes(formal.typ, abstractInst).kind == tyVar)
-      InternalError(arg.info, "not implemented: pass to var parameter")
+      # XXX why is this even necessary?
+      var b = newNodeIT(nkHiddenAddr, arg.info, formal.typ)
+      b.add(arg)
+      arg = b
+      IdNodeTablePut(newC.mapping, formal, arg)
+      # XXX BUG still not correct if the arg has a side effect!
+      #InternalError(arg.info, "not implemented: pass to var parameter")
   var body = newC.owner.ast.sons[codePos]
   pushInfoContext(n.info)
   inc(c.inlining)
diff --git a/examples/lazarus/backend.nim b/examples/lazarus/backend.nim
new file mode 100755
index 000000000..64f0c5bf7
--- /dev/null
+++ b/examples/lazarus/backend.nim
@@ -0,0 +1,5 @@
+# Backend for the Lazarus GUI

+

+proc myAdd*(x, y: int): int {.cdecl, exportc.} = 

+  result = x + y

+

diff --git a/tests/accept/run/tmoditer.nim b/tests/accept/run/tmoditer.nim
new file mode 100644
index 000000000..1e6be37e4
--- /dev/null
+++ b/tests/accept/run/tmoditer.nim
@@ -0,0 +1,29 @@
+discard """
+  output: "XXXXX01234"
+"""
+
+iterator modPairs(a: var array[0..4,string]): tuple[key: int, val: var string] =
+  for i in 0..a.high:
+    yield (i, a[i])
+
+iterator modItems*[T](a: var array[0..4,T]): var T =
+  for i in 0..a.high:
+    yield a[i]
+
+var
+  arr = ["a", "b", "c", "d", "e"]
+
+for a in modItems(arr):
+  a = "X"
+
+for a in items(arr):
+  stdout.write(a)
+
+for i, a in modPairs(arr):
+  a = $i
+
+for a in items(arr):
+  stdout.write(a)
+
+echo ""
+
diff --git a/todo.txt b/todo.txt
index 2c5f15b54..e781e772a 100755
--- a/todo.txt
+++ b/todo.txt
@@ -1,11 +1,10 @@
 Version 0.8.14
 ==============
 
+- fix serious bug that keeps teventemitter from compiling
 - ``var T`` as a return type:
-  * for iterators
   * add ``modGet`` for generics
   * documentation
-  * provide ``mod`` as an alternative syntax for ``var``
 - optional indentation for 'case' statement
 - make threadvar efficient again on linux after testing
 - test the sort implementation again
@@ -19,8 +18,7 @@ version 0.9.0
 - add --deadlock_prevention:on|off switch? timeout for locks?
 - warning for implicit openArray -> varargs convention
 - implement explicit varargs
-- tests: run modules that contain "#RUN_ME", compile the other
-  modules; run the GC tests
+- tests: run the GC tests
 - change overloading resolution
 - implement closures; implement proper coroutines
 
@@ -40,8 +38,6 @@ version 0.9.XX
 - implicit ref/ptr->var conversion; the compiler may store an object
   implicitly on the heap for write barrier efficiency; better: 
   proc specialization in the code gen
-- resizing of strings/sequences could take into account the memory that
-  is allocated
 - find a way to reintroduce the cleanup() pass for C code generation: this
   is hard because of partial evaluation --> symbol files will fix this as
   a side effect
@@ -81,6 +77,8 @@ Low priority
 - find a way for easy constructors and destructors; (destructors are much more
   important than constructors)
 - code generated for type information is wasteful
+- resizing of strings/sequences could take into account the memory that
+  is allocated
 
 
 Version 2