diff options
-rw-r--r-- | compiler/lambdalifting.nim | 28 | ||||
-rw-r--r-- | compiler/semstmts.nim | 4 | ||||
-rw-r--r-- | doc/tut2.txt | 6 | ||||
-rw-r--r-- | lib/impure/db_sqlite.nim | 3 | ||||
-rw-r--r-- | lib/wrappers/mysql.nim | 14 | ||||
-rw-r--r-- | tests/generics/tconfusing_arrow.nim | 15 | ||||
-rw-r--r-- | tests/iter/tshallowcopy_closures.nim | 31 |
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() |