made closure iterators tests green, updated docs

This commit is contained in:
Andreas Rumpf 2015-12-31 00:16:38 +01:00
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) putLocIntoDest(p, d, sym.loc)
of skParam: of skParam:
if sym.loc.r == nil or sym.loc.t == nil: if sym.loc.r == nil or sym.loc.t == nil:
#echo "FAILED FOR PRCO ", p.prc.name.s # echo "FAILED FOR PRCO ", p.prc.name.s
#debug p.prc.typ.n # debug p.prc.typ.n
#echo renderTree(p.prc.ast, {renderIds}) # echo renderTree(p.prc.ast, {renderIds})
internalError(n.info, "expr: param not init " & sym.name.s & "_" & $sym.id) internalError(n.info, "expr: param not init " & sym.name.s & "_" & $sym.id)
putLocIntoDest(p, d, sym.loc) putLocIntoDest(p, d, sym.loc)
else: internalError(n.info, "expr(" & $sym.kind & "); unknown symbol") 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 assert sfFromGeneric in result.flags
else: else:
# writeStackTrace() # 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 result = routine
proc getEnvParam*(routine: PSym): PSym = proc getEnvParam*(routine: PSym): PSym =
@ -224,7 +224,7 @@ proc interestingIterVar(s: PSym): bool {.inline.} =
template isIterator(owner: PSym): bool = template isIterator(owner: PSym): bool =
owner.kind == skIterator and owner.typ.callConv == ccClosure 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)) # transforms (iter) to (let env = newClosure[iter](); (iter, env))
let iter = n.sym let iter = n.sym
assert iter.isIterator assert iter.isIterator
@ -326,12 +326,14 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
detectCapturedVars(s.getBody, s, c) detectCapturedVars(s.getBody, s, c)
let ow = s.skipGenericOwner let ow = s.skipGenericOwner
if ow == owner: if ow == owner:
if owner.isIterator and interestingIterVar(s): if owner.isIterator:
c.somethingToDo = true c.somethingToDo = true
if not c.capturedVars.containsOrIncl(s.id): addClosureParam(c, owner)
let obj = getHiddenParam(owner).typ.lastSon if interestingIterVar(s):
#let obj = c.getEnvTypeForOwner(s.owner).lastSon if not c.capturedVars.containsOrIncl(s.id):
addField(obj, s) 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 # but always return because the rest of the proc is only relevant when
# ow != owner: # ow != owner:
return return
@ -479,7 +481,7 @@ proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
result = n result = n
proc getStateField(owner: PSym): PSym = 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; proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode c: var LiftingPass): PNode
@ -684,6 +686,9 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
var d = initDetectionPass(fn) var d = initDetectionPass(fn)
var c = initLiftingPass(fn) var c = initLiftingPass(fn)
detectCapturedVars(body, fn, d) detectCapturedVars(body, fn, d)
if not d.somethingToDo and fn.isIterator:
addClosureParam(d, fn)
d.somethingToDo = true
if d.somethingToDo: if d.somethingToDo:
var newBody = liftCapturedVars(body, fn, d, c) var newBody = liftCapturedVars(body, fn, d, c)
if not c.envCreation.isNil: if not c.envCreation.isNil:
@ -692,7 +697,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
result = wrapIterBody(newBody, fn) result = wrapIterBody(newBody, fn)
else: else:
result = body result = body
#if fn.name.s == "outer": #if fn.name.s == "tokenize2":
# echo "had something to do ", d.somethingToDo # echo "had something to do ", d.somethingToDo
# echo renderTree(result, {renderIds}) # echo renderTree(result, {renderIds})
@ -705,7 +710,7 @@ proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
# ------------------- iterator transformation -------------------------------- # ------------------- iterator transformation --------------------------------
proc liftForLoop*(body: PNode): PNode = proc liftForLoop*(body: PNode; owner: PSym): PNode =
# problem ahead: the iterator could be invoked indirectly, but then # problem ahead: the iterator could be invoked indirectly, but then
# we don't know what environment to create here: # 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: if call[0].kind == nkSym and call[0].sym.isIterator:
# createClosure() # createClosure()
let iter = call[0].sym 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) var v = newNodeI(nkVarSection, body.info)
addVar(v, newSymNode(env)) addVar(v, newSymNode(env))

View file

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

View file

@ -1235,7 +1235,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
if isAnon: result.typ = s.typ if isAnon: result.typ = s.typ
if isTopLevel(c) and s.kind != skIterator and if isTopLevel(c) and s.kind != skIterator and
s.typ.callConv == ccClosure: 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) = proc determineType(c: PContext, s: PSym) =
if s.typ != nil: return if s.typ != nil: return

View file

@ -960,10 +960,6 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
var r: PType var r: PType
if n.sons[0].kind != nkEmpty: if n.sons[0].kind != nkEmpty:
r = semTypeNode(c, n.sons[0], nil) 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: if r != nil:
# turn explicit 'void' return type into 'nil' because the rest of the # 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 result[1] = ri
proc transformSymAux(c: PTransf, n: PNode): PNode = proc transformSymAux(c: PTransf, n: PNode): PNode =
#if n.sym.kind == skClosureIterator: if n.sym.kind == skIterator and n.sym.typ.callConv == ccClosure:
# return liftIterSym(n) return liftIterSym(n, getCurrOwner(c))
var b: PNode var b: PNode
var tc = c.transCon var tc = c.transCon
if sfBorrow in n.sym.flags and n.sym.kind in routineKinds: 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 return result
c.breakSyms.add(labl) c.breakSyms.add(labl)
if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or 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 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 discard c.breakSyms.pop
return result return result
@ -904,6 +904,8 @@ proc transformStmt*(module: PSym, n: PNode): PNode =
#result = liftLambdasForTopLevel(module, result) #result = liftLambdasForTopLevel(module, result)
incl(result.flags, nfTransf) incl(result.flags, nfTransf)
when useEffectSystem: trackTopLevelStmt(module, result) when useEffectSystem: trackTopLevelStmt(module, result)
#if n.info ?? "temp.nim":
# echo renderTree(result, {renderIds})
proc transformExpr*(module: PSym, n: PNode): PNode = proc transformExpr*(module: PSym, n: PNode): PNode =
if nfTransf in n.flags: if nfTransf in n.flags:

View file

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

View file

@ -9,7 +9,7 @@ proc univ(x, y: int): State = Tree
var w, h = 30 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 y in max(a[0], 0) .. min(b[0], h-1):
for x in max(a[1], 0) .. min(b[1], w-1): for x in max(a[1], 0) .. min(b[1], w-1):
yield (y,x) yield (y,x)

View file

@ -14,11 +14,7 @@ discard """
49 49
64 64
81 81
--- squares of evens, only '''
4
16
36
64'''
""" """
iterator `/`[T](sequence: seq[T], iterator `/`[T](sequence: seq[T],
@ -40,10 +36,10 @@ iterator `/>>`[I,O](sequence: seq[I],
if (filtermap.f(element)): if (filtermap.f(element)):
yield filtermap.m(element) yield filtermap.m(element)
proc isEven(x:int): bool {.closure.} = result = proc isEven(x:int): bool =
(x and 1) == 0 (x and 1) == 0
proc square(x:int): int {.closure.} = result = proc square(x:int): int =
x * x x * x
let list = @[1,2,3,4,5,6,7,8,9] let list = @[1,2,3,4,5,6,7,8,9]
@ -52,6 +48,6 @@ echo ("--- evens")
for item in list / isEven : echo(item) for item in list / isEven : echo(item)
echo ("--- squares") echo ("--- squares")
for item in list >> square : echo(item) 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 # 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 - 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 weird special case (you could not use ``x is proc``) and was removed from
the language. 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 2015-10-27 Version 0.12.0 released