diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 378951d9db..8796dd729e 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -164,11 +164,11 @@ proc genBreakState(p: BProc, n: PNode) = if n.sons[0].kind == nkClosure: # XXX this produces quite inefficient code! initLocExpr(p, n.sons[0].sons[1], a) - lineF(p, cpsStmts, "if (((NI*) $1)[0] < 0) break;$n", [rdLoc(a)]) + lineF(p, cpsStmts, "if (((NI*) $1)[1] < 0) break;$n", [rdLoc(a)]) else: initLocExpr(p, n.sons[0], a) - # the environment is guaranteed to contain the 'state' field at offset 0: - lineF(p, cpsStmts, "if ((((NI*) $1.ClE_0)[0]) < 0) break;$n", [rdLoc(a)]) + # the environment is guaranteed to contain the 'state' field at offset 1: + lineF(p, cpsStmts, "if ((((NI*) $1.ClE_0)[1]) < 0) break;$n", [rdLoc(a)]) # lineF(p, cpsStmts, "if (($1) < 0) break;$n", [rdLoc(a)]) proc genVarPrototypeAux(m: BModule, sym: PSym) diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index aba9c53429..3220212873 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -12,6 +12,7 @@ # ------------------------- Name Mangling -------------------------------- import sighashes +from lowerings import createObj proc isKeyword(w: PIdent): bool = # Nim and C++ share some keywords @@ -1092,7 +1093,8 @@ proc fakeClosureType(owner: PSym): PType = result = newType(tyTuple, owner) result.rawAddSon(newType(tyPointer, owner)) var r = newType(tyRef, owner) - r.rawAddSon(newType(tyTuple, owner)) + let obj = createObj(owner, owner.info, final=false) + r.rawAddSon(obj) result.rawAddSon(r) type diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index cd2ccfe53c..986d8c716f 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -142,7 +142,7 @@ proc createStateField(iter: PSym): PSym = proc createEnvObj(owner: PSym; info: TLineInfo): PType = # YYY meh, just add the state field for every closure for now, it's too # hard to figure out if it comes from a closure iterator: - result = createObj(owner, info) + result = createObj(owner, info, final=false) rawAddField(result, createStateField(owner)) proc getIterResult(iter: PSym): PSym = diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim index 4bd54603d8..ce76b63a41 100644 --- a/compiler/lowerings.nim +++ b/compiler/lowerings.nim @@ -109,17 +109,19 @@ proc lowerSwap*(n: PNode; owner: PSym): PNode = result.add newFastAsgnStmt(n[1], n[2]) result.add newFastAsgnStmt(n[2], tempAsNode) -proc createObj*(owner: PSym, info: TLineInfo): PType = +proc createObj*(owner: PSym, info: TLineInfo; final=true): PType = result = newType(tyObject, owner) - rawAddSon(result, nil) - incl result.flags, tfFinal + if final: + rawAddSon(result, nil) + incl result.flags, tfFinal + else: + rawAddSon(result, getCompilerProc("RootObj").typ) result.n = newNodeI(nkRecList, info) - when true: - let s = newSym(skType, getIdent("Env_" & info.toFilename), - owner, info) - incl s.flags, sfAnon - s.typ = result - result.sym = s + let s = newSym(skType, getIdent("Env_" & info.toFilename), + owner, info) + incl s.flags, sfAnon + s.typ = result + result.sym = s proc rawAddField*(obj: PType; field: PSym) = assert field.kind == skField diff --git a/lib/system.nim b/lib/system.nim index 8f653c1e01..d62c0424eb 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -413,7 +413,7 @@ type ## is an int type ranging from one to the maximum value ## of an int. This type is often useful for documentation and debugging. - RootObj* {.exportc: "TNimObject", inheritable.} = + RootObj* {.compilerProc, inheritable.} = object ## the root of Nim's object hierarchy. Objects should ## inherit from RootObj or one of its descendants. However, ## objects that have no ancestor are allowed. @@ -3269,7 +3269,7 @@ when not defined(JS): #and not defined(nimscript): proc finished*[T: proc](x: T): bool {.noSideEffect, inline.} = ## can be used to determine if a first class iterator has finished. {.emit: """ - `result` = *((NI*) `x`.ClE_0) < 0; + `result` = ((NI*) `x`.ClE_0)[1] < 0; """.} elif defined(JS): diff --git a/lib/system/deepcopy.nim b/lib/system/deepcopy.nim index e12f08842d..65ba2278c8 100644 --- a/lib/system/deepcopy.nim +++ b/lib/system/deepcopy.nim @@ -148,11 +148,11 @@ proc genericDeepCopyAux(dest, src: pointer, mt: PNimType; tab: var PtrTable) = let realType = x.typ sysAssert realType == mt, " types do differ" # this version should work for any possible GC: - let size = if mt.base.kind == tyObject: cast[ptr PNimType](s2)[].size else: mt.base.size - let z = newObj(mt, size) + let typ = if mt.base.kind == tyObject: cast[ptr PNimType](s2)[] else: mt.base + let z = newObj(mt, typ.size) unsureAsgnRef(cast[PPointer](dest), z) tab.put(s2, z) - genericDeepCopyAux(z, s2, mt.base, tab) + genericDeepCopyAux(z, s2, typ, tab) else: unsureAsgnRef(cast[PPointer](dest), z) of tyPtr: diff --git a/tests/closure/tboehmdeepcopy.nim b/tests/closure/tboehmdeepcopy.nim new file mode 100644 index 0000000000..79ac5797aa --- /dev/null +++ b/tests/closure/tboehmdeepcopy.nim @@ -0,0 +1,17 @@ +discard """ + cmd: "nim c --gc:boehm $options $file" + output: '''meep''' +""" + +proc callit(it: proc ()) = + it() + +proc main = + var outer = "meep" + proc x = + echo outer + var y: proc() + deepCopy(y, x) + callit(y) + +main()