made closure iterators tests green, updated docs

This commit is contained in:
Andreas Rumpf
2015-12-31 00:16:38 +01:00
parent 2162a71c93
commit 307a6095fa
10 changed files with 42 additions and 35 deletions

View File

@@ -2004,9 +2004,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
putLocIntoDest(p, d, sym.loc)
of skParam:
if sym.loc.r == nil or sym.loc.t == nil:
#echo "FAILED FOR PRCO ", p.prc.name.s
#debug p.prc.typ.n
#echo renderTree(p.prc.ast, {renderIds})
# echo "FAILED FOR PRCO ", p.prc.name.s
# debug p.prc.typ.n
# echo renderTree(p.prc.ast, {renderIds})
internalError(n.info, "expr: param not init " & sym.name.s & "_" & $sym.id)
putLocIntoDest(p, d, sym.loc)
else: internalError(n.info, "expr(" & $sym.kind & "); unknown symbol")

View File

@@ -174,7 +174,7 @@ proc getHiddenParam(routine: PSym): PSym =
assert sfFromGeneric in result.flags
else:
# writeStackTrace()
localError(routine.info, "internal error: could not find env param " & routine.name.s)
localError(routine.info, "internal error: could not find env param for " & routine.name.s)
result = routine
proc getEnvParam*(routine: PSym): PSym =
@@ -224,7 +224,7 @@ proc interestingIterVar(s: PSym): bool {.inline.} =
template isIterator(owner: PSym): bool =
owner.kind == skIterator and owner.typ.callConv == ccClosure
proc liftIterSym(n: PNode; owner: PSym): PNode =
proc liftIterSym*(n: PNode; owner: PSym): PNode =
# transforms (iter) to (let env = newClosure[iter](); (iter, env))
let iter = n.sym
assert iter.isIterator
@@ -326,12 +326,14 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
detectCapturedVars(s.getBody, s, c)
let ow = s.skipGenericOwner
if ow == owner:
if owner.isIterator and interestingIterVar(s):
if owner.isIterator:
c.somethingToDo = true
if not c.capturedVars.containsOrIncl(s.id):
let obj = getHiddenParam(owner).typ.lastSon
#let obj = c.getEnvTypeForOwner(s.owner).lastSon
addField(obj, s)
addClosureParam(c, owner)
if interestingIterVar(s):
if not c.capturedVars.containsOrIncl(s.id):
let obj = getHiddenParam(owner).typ.lastSon
#let obj = c.getEnvTypeForOwner(s.owner).lastSon
addField(obj, s)
# but always return because the rest of the proc is only relevant when
# ow != owner:
return
@@ -479,7 +481,7 @@ proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
result = n
proc getStateField(owner: PSym): PSym =
getEnvParam(owner).typ.sons[0].n.sons[0].sym
getHiddenParam(owner).typ.sons[0].n.sons[0].sym
proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode
@@ -684,6 +686,9 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
var d = initDetectionPass(fn)
var c = initLiftingPass(fn)
detectCapturedVars(body, fn, d)
if not d.somethingToDo and fn.isIterator:
addClosureParam(d, fn)
d.somethingToDo = true
if d.somethingToDo:
var newBody = liftCapturedVars(body, fn, d, c)
if not c.envCreation.isNil:
@@ -692,7 +697,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
result = wrapIterBody(newBody, fn)
else:
result = body
#if fn.name.s == "outer":
#if fn.name.s == "tokenize2":
# echo "had something to do ", d.somethingToDo
# echo renderTree(result, {renderIds})
@@ -705,7 +710,7 @@ proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
# ------------------- iterator transformation --------------------------------
proc liftForLoop*(body: PNode): PNode =
proc liftForLoop*(body: PNode; owner: PSym): PNode =
# problem ahead: the iterator could be invoked indirectly, but then
# we don't know what environment to create here:
#
@@ -746,8 +751,11 @@ proc liftForLoop*(body: PNode): PNode =
if call[0].kind == nkSym and call[0].sym.isIterator:
# createClosure()
let iter = call[0].sym
assert iter.isIterator
env = copySym(getHiddenParam(iter))
let hp = getHiddenParam(iter)
env = newSym(skLet, iter.name, owner, body.info)
env.typ = hp.typ
env.flags = hp.flags
var v = newNodeI(nkVarSection, body.info)
addVar(v, newSymNode(env))

View File

@@ -1330,6 +1330,8 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
initContext c
putWithSpace g, tkSymbol, if n.kind == nkState: "state" else: "goto"
gsons(g, n, c)
of nkBreakState:
put(g, tkTuple, "breakstate")
of nkTypeClassTy:
gTypeClassTy(g, n)
else:

View File

@@ -1235,7 +1235,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if isAnon: result.typ = s.typ
if isTopLevel(c) and s.kind != skIterator and
s.typ.callConv == ccClosure:
message(s.info, warnDeprecated, "top level '.closure' calling convention")
localError(s.info, "'.closure' calling convention for top level routines is invalid")
proc determineType(c: PContext, s: PSym) =
if s.typ != nil: return

View File

@@ -960,10 +960,6 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
var r: PType
if n.sons[0].kind != nkEmpty:
r = semTypeNode(c, n.sons[0], nil)
elif kind == skIterator:
# XXX This is special magic we should likely get rid of
r = newTypeS(tyExpr, c)
message(n.info, warnDeprecated, "implicit return type for 'iterator'")
if r != nil:
# turn explicit 'void' return type into 'nil' because the rest of the

View File

@@ -111,8 +111,8 @@ proc newAsgnStmt(c: PTransf, le: PNode, ri: PTransNode): PTransNode =
result[1] = ri
proc transformSymAux(c: PTransf, n: PNode): PNode =
#if n.sym.kind == skClosureIterator:
# return liftIterSym(n)
if n.sym.kind == skIterator and n.sym.typ.callConv == ccClosure:
return liftIterSym(n, getCurrOwner(c))
var b: PNode
var tc = c.transCon
if sfBorrow in n.sym.flags and n.sym.kind in routineKinds:
@@ -497,9 +497,9 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
return result
c.breakSyms.add(labl)
if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or
call.sons[0].sym.kind != skIterator:
call.sons[0].typ.callConv == ccClosure:
n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode
result[1] = lambdalifting.liftForLoop(n).PTransNode
result[1] = lambdalifting.liftForLoop(n, getCurrOwner(c)).PTransNode
discard c.breakSyms.pop
return result
@@ -904,6 +904,8 @@ proc transformStmt*(module: PSym, n: PNode): PNode =
#result = liftLambdasForTopLevel(module, result)
incl(result.flags, nfTransf)
when useEffectSystem: trackTopLevelStmt(module, result)
#if n.info ?? "temp.nim":
# echo renderTree(result, {renderIds})
proc transformExpr*(module: PSym, n: PNode): PNode =
if nfTransf in n.flags:

View File

@@ -7,7 +7,7 @@ type
data: T
callback: proc () {.closure.}
proc cbOuter(response: string) {.closure, discardable.} =
proc cbOuter(response: string) {.discardable.} =
iterator cbIter(): Future[int] {.closure.} =
for i in 0..7:
proc foo(): int =

View File

@@ -9,7 +9,7 @@ proc univ(x, y: int): State = Tree
var w, h = 30
iterator fields(a = (0,0), b = (h-1,w-1)) =
iterator fields(a = (0,0), b = (h-1,w-1)): auto =
for y in max(a[0], 0) .. min(b[0], h-1):
for x in max(a[1], 0) .. min(b[1], w-1):
yield (y,x)

View File

@@ -14,11 +14,7 @@ discard """
49
64
81
--- squares of evens, only
4
16
36
64'''
'''
"""
iterator `/`[T](sequence: seq[T],
@@ -40,10 +36,10 @@ iterator `/>>`[I,O](sequence: seq[I],
if (filtermap.f(element)):
yield filtermap.m(element)
proc isEven(x:int): bool {.closure.} = result =
proc isEven(x:int): bool =
(x and 1) == 0
proc square(x:int): int {.closure.} = result =
proc square(x:int): int =
x * x
let list = @[1,2,3,4,5,6,7,8,9]
@@ -52,6 +48,6 @@ echo ("--- evens")
for item in list / isEven : echo(item)
echo ("--- squares")
for item in list >> square : echo(item)
echo ("--- squares of evens, only")
#echo ("--- squares of evens, only")
# next line doesn't compile. Generic types are not inferred
for item in list />> (isEven, square) : echo(item)
#for item in list />> (isEven, square) : echo(item)

View File

@@ -19,6 +19,9 @@ News
- The check ``x is iterator`` (used for instance in concepts) was always a
weird special case (you could not use ``x is proc``) and was removed from
the language.
- Implicit return type for iterators have been removed from the language.
- Top level routines cannot have the calling convention ``closure``
anymore.
2015-10-27 Version 0.12.0 released