summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/lambdalifting.nim28
-rw-r--r--compiler/semstmts.nim4
-rw-r--r--doc/tut2.txt6
-rw-r--r--lib/impure/db_sqlite.nim3
-rw-r--r--lib/wrappers/mysql.nim14
-rw-r--r--tests/generics/tconfusing_arrow.nim15
-rw-r--r--tests/iter/tshallowcopy_closures.nim31
7 files changed, 85 insertions, 16 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index b079ecdd6..6fa95fda2 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -187,6 +187,7 @@ proc addHiddenParam(routine: PSym, param: PSym) =
   param.position = params.len-1
   addSon(params, newSymNode(param))
   incl(routine.typ.flags, tfCapturesEnv)
+  assert sfFromGeneric in param.flags
   #echo "produced environment: ", param.id, " for ", routine.name.s
 
 proc getHiddenParam(routine: PSym): PSym =
@@ -194,12 +195,14 @@ proc getHiddenParam(routine: PSym): PSym =
   let hidden = lastSon(params)
   internalAssert hidden.kind == nkSym and hidden.sym.kind == skParam
   result = hidden.sym
+  assert sfFromGeneric in result.flags
 
 proc getEnvParam(routine: PSym): PSym =
   let params = routine.ast.sons[paramsPos]
   let hidden = lastSon(params)
   if hidden.kind == nkSym and hidden.sym.name.s == paramName:
     result = hidden.sym
+    assert sfFromGeneric in result.flags
 
 proc initIter(iter: PSym): TIter =
   result.fn = iter
@@ -716,15 +719,17 @@ proc outerProcSons(o: POuterContext, n: PNode, it: TIter) =
     let x = transformOuterProc(o, n.sons[i], it)
     if x != nil: n.sons[i] = x
 
-proc liftIterSym*(n: PNode): PNode =
-  # transforms  (iter)  to  (let env = newClosure[iter](); (iter, env)) 
+proc liftIterSym(n: PNode): PNode =
+  # transforms  (iter)  to  (let env = newClosure[iter](); (iter, env))
   let iter = n.sym
   assert iter.kind == skClosureIterator
 
   result = newNodeIT(nkStmtListExpr, n.info, n.typ)
   
-  var env = copySym(getHiddenParam(iter))
-  env.kind = skLet
+  let hp = getHiddenParam(iter)
+  let env = newSym(skLet, iter.name, iter.owner, iter.info)
+  env.typ = hp.typ
+  env.flags = hp.flags
   var v = newNodeI(nkVarSection, n.info)
   addVar(v, newSymNode(env))
   result.add(v)
@@ -853,7 +858,6 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode =
         addUniqueField(it.obj, local)
         return indirectAccess(newSymNode(it.closureParam), local, n.info)
 
-    var closure = PEnv(idTableGet(o.lambdasToEnv, local))
     if local.kind == skClosureIterator:
       # consider: [i1, i2, i1]  Since we merged the iterator's closure
       # with the captured owning variables, we need to generate the
@@ -861,13 +865,25 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode =
       if local == o.fn or local == it.fn:
         message(n.info, errRecursiveDependencyX, local.name.s)
       # XXX why doesn't this work?
+      var closure = PEnv(idTableGet(o.lambdasToEnv, local))
       if closure.isNil:
         return liftIterSym(n)
       else:
         let createdVar = generateIterClosureCreation(o, closure,
                                                      closure.attachedNode)
+        let lpt = getHiddenParam(local).typ
+        if lpt != createdVar.typ:
+          assert lpt.kind == tyRef and createdVar.typ.kind == tyRef
+          # fix bug 'tshallowcopy_closures' but report if this gets any weirder:
+          if createdVar.typ.sons[0].len == 1 and lpt.sons[0].len >= 1:
+            createdVar.typ = lpt
+            if createdVar.kind == nkSym: createdVar.sym.typ = lpt
+            closure.obj = lpt.sons[0]
+          else:
+            internalError(n.info, "environment computation failed")
         return makeClosure(local, createdVar, n.info)
 
+    var closure = PEnv(idTableGet(o.lambdasToEnv, local))
     if closure != nil:
       # we need to replace the lambda with '(lambda, env)':
       let a = closure.createdVar
@@ -935,7 +951,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
     # ignore forward declaration:
     result = body
   else:
-    #if fn.name.s == "cbOuter":
+    #if fn.name.s == "sort":
     #  echo rendertree(fn.ast, {renderIds})
     var o = newOuterContext(fn)
     let ex = closureCreationPoint(body)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 1396ef374..bdff15926 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -732,7 +732,7 @@ proc semBorrow(c: PContext, n: PNode, s: PSym) =
     localError(n.info, errNoSymbolToBorrowFromFound) 
   
 proc addResult(c: PContext, t: PType, info: TLineInfo, owner: TSymKind) = 
-  if t != nil: 
+  if t != nil:
     var s = newSym(skResult, getIdent"result", getCurrOwner(), info)
     s.typ = t
     incl(s.flags, sfUsed)
@@ -851,6 +851,7 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
   
   openScope(c)
   var s = n.sons[namePos].sym
+  pushOwner(s)
   addParams(c, n.typ.n, skProc)
   pushProcCon(c, s)
   addResult(c, n.typ.sons[0], n.info, skProc)
@@ -858,6 +859,7 @@ proc semInferredLambda(c: PContext, pt: TIdTable, n: PNode): PNode =
   n.sons[bodyPos] = transformBody(c.module, semBody, n.sons[namePos].sym)
   addResultNode(c, n)
   popProcCon(c)
+  popOwner()
   closeScope(c)
   
   s.ast = result
diff --git a/doc/tut2.txt b/doc/tut2.txt
index 2ae0f18f6..b9fff93b9 100644
--- a/doc/tut2.txt
+++ b/doc/tut2.txt
@@ -304,8 +304,8 @@ Procedures always use static dispatch. For dynamic dispatch replace the
   echo eval(newPlus(newPlus(newLit(1), newLit(2)), newLit(4)))
 
 Note that in the example the constructors ``newLit`` and ``newPlus`` are procs
-because they should use static binding, but ``eval`` is a method because it
-requires dynamic binding.
+because it makes more sense for them to use static binding, but ``eval`` is a
+method because it requires dynamic binding.
 
 In a multi-method all parameters that have an object type are used for the
 dispatching:
@@ -640,7 +640,7 @@ Macros
 Macros enable advanced compile-time code transformations, but they cannot
 change Nim's syntax. However, this is no real restriction because Nim's
 syntax is flexible enough anyway. Macros have to be implemented in pure Nim
-code if `foreign function interface (FFI)
+code if the `foreign function interface (FFI)
 <manual.html#foreign-function-interface>`_ is not enabled in the compiler, but
 other than that restriction (which at some point in the future will go away)
 you can write any kind of Nim code and the compiler will run it at compile
diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim
index bc9e0b591..bf1ce75ef 100644
--- a/lib/impure/db_sqlite.nim
+++ b/lib/impure/db_sqlite.nim
@@ -48,6 +48,7 @@ proc dbError*(msg: string) {.noreturn.} =
   raise e
 
 proc dbQuote(s: string): string =
+  if s.isNil: return "NULL"
   result = "'"
   for c in items(s):
     if c == '\'': add(result, "''")
@@ -61,7 +62,7 @@ proc dbFormat(formatstr: TSqlQuery, args: varargs[string]): string =
     if c == '?':
       add(result, dbQuote(args[a]))
       inc(a)
-    else: 
+    else:
       add(result, c)
   
 proc tryExec*(db: TDbConn, query: TSqlQuery, 
diff --git a/lib/wrappers/mysql.nim b/lib/wrappers/mysql.nim
index 5deceb6e2..9161f5672 100644
--- a/lib/wrappers/mysql.nim
+++ b/lib/wrappers/mysql.nim
@@ -10,11 +10,15 @@
 {.deadCodeElim: on.}
 {.push, callconv: cdecl.}
 
-when defined(Unix): 
-  const 
-    lib = "libmysqlclient.so.(15|16|17|18)"
-when defined(Windows): 
-  const 
+when defined(Unix):
+  when defined(macosx):
+    const
+      lib = "libmysqlclient.(15|16|17[18).dylib"
+  else:
+    const
+      lib = "libmysqlclient.so.(15|16|17|18)"
+when defined(Windows):
+  const
     lib = "libmysql.dll"
 type 
   my_bool* = bool
diff --git a/tests/generics/tconfusing_arrow.nim b/tests/generics/tconfusing_arrow.nim
new file mode 100644
index 000000000..6a5a9d682
--- /dev/null
+++ b/tests/generics/tconfusing_arrow.nim
@@ -0,0 +1,15 @@
+import algorithm, future
+
+type Deck = object
+  value: int
+
+proc sort(h: var seq[Deck]) =
+  # works:
+  h.sort(proc (x, y: Deck): auto = 
+    cmp(x.value, y.value))
+  # fails:
+  h.sort((x, y: Deck) => cmp(ord(x.value), ord(y.value)))
+
+var player: seq[Deck] = @[]
+
+player.sort()
diff --git a/tests/iter/tshallowcopy_closures.nim b/tests/iter/tshallowcopy_closures.nim
new file mode 100644
index 000000000..2f024ee7e
--- /dev/null
+++ b/tests/iter/tshallowcopy_closures.nim
@@ -0,0 +1,31 @@
+discard """
+  ccodecheck: "!@('{' \\s* 'NI HEX3Astate;' \\s* '}')"
+"""
+
+# bug #1803
+type TaskFn = iterator (): float
+
+iterator a1(): float {.closure.} =
+    var k = 10
+    while k > 0:
+        echo "a1 ", k
+        dec k
+        yield 1.0
+
+
+iterator a2(): float {.closure.} =
+    var k = 15
+    while k > 0:
+        echo "a2 ", k
+        dec k
+        yield 2.0
+
+var
+  x = a1
+  y = a2
+  z: TaskFn
+
+discard x()
+z = x #shallowCopy(z, x)
+z = y #shallowCopy(z, y)
+discard x()