mirror of
https://github.com/nim-lang/Nim.git
synced 2026-07-19 23:41:29 +00:00
made closure iterators tests green, updated docs
This commit is contained in:
@@ -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")
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user