made closure iterators tests green, updated docs
This commit is contained in:
parent
2162a71c93
commit
307a6095fa
10 changed files with 42 additions and 35 deletions
|
|
@ -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")
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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 =
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue