mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 08:54:53 +00:00
progress
This commit is contained in:
@@ -20,6 +20,8 @@ import
|
||||
|
||||
from expanddefaults import caseObjDefaultBranch
|
||||
|
||||
import closureiters
|
||||
|
||||
import pipelineutils
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
@@ -1312,13 +1314,17 @@ proc genProcLvl3*(m: BModule, prc: PSym) =
|
||||
assert(prc.ast != nil)
|
||||
|
||||
var procBody: PNode = nil
|
||||
if isIterator(prc) and prc.closureBody != nil:
|
||||
if prc.closureBody != nil:
|
||||
procBody = prc.closureBody
|
||||
else:
|
||||
procBody = transformBody(m.g.graph, m.idgen, prc, {})
|
||||
if sfInjectDestructors in prc.flags:
|
||||
procBody = injectDestructorCalls(m.g.graph, m.idgen, prc, procBody)
|
||||
|
||||
if isIterator(prc):
|
||||
procBody = transformClosureIterator(m.g.graph, m.idgen, prc, procBody)
|
||||
prc.closureBody = procBody
|
||||
|
||||
let tmpInfo = prc.info
|
||||
discard freshLineInfo(p, prc.info)
|
||||
|
||||
|
||||
@@ -139,8 +139,9 @@
|
||||
|
||||
import
|
||||
ast, msgs, idents,
|
||||
renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos,
|
||||
options
|
||||
renderer, magicsys, lowerings, modulegraphs, lineinfos
|
||||
|
||||
import lambdautils
|
||||
|
||||
import std/tables
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ import
|
||||
idents, renderer, types, magicsys, lowerings, modulegraphs, lineinfos,
|
||||
transf, liftdestructors, typeallowed
|
||||
|
||||
import lambdautils, closureiters, injectdestructors
|
||||
|
||||
import std/[strutils, tables, intsets]
|
||||
|
||||
when defined(nimPreviewSlimSystem):
|
||||
@@ -119,79 +121,6 @@ discard """
|
||||
# local storage requirements for efficiency. This means closure iterators
|
||||
# have slightly different semantics from ordinary closures.
|
||||
|
||||
# ---------------- essential helpers -------------------------------------
|
||||
|
||||
const
|
||||
upName* = ":up" # field name for the 'up' reference
|
||||
paramName* = ":envP"
|
||||
envName* = ":env"
|
||||
|
||||
proc newCall(a: PSym, b: PNode): PNode =
|
||||
result = newNodeI(nkCall, a.info)
|
||||
result.add newSymNode(a)
|
||||
result.add b
|
||||
|
||||
proc createClosureIterStateType*(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PType =
|
||||
var n = newNodeI(nkRange, iter.info)
|
||||
n.add newIntNode(nkIntLit, -1)
|
||||
n.add newIntNode(nkIntLit, 0)
|
||||
result = newType(tyRange, idgen, iter)
|
||||
result.n = n
|
||||
var intType = nilOrSysInt(g)
|
||||
if intType.isNil: intType = newType(tyInt, idgen, iter)
|
||||
rawAddSon(result, intType)
|
||||
|
||||
proc createStateField(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym =
|
||||
result = newSym(skField, getIdent(g.cache, ":state"), idgen, iter, iter.info)
|
||||
result.typ = createClosureIterStateType(g, iter, idgen)
|
||||
|
||||
template isIterator*(owner: PSym): bool =
|
||||
owner.kind == skIterator and owner.typ.callConv == ccClosure
|
||||
|
||||
proc createEnvObj(g: ModuleGraph; idgen: IdGenerator; owner: PSym; info: TLineInfo): PType =
|
||||
result = createObj(g, idgen, owner, info, final=false)
|
||||
result.incl tfFinal
|
||||
if owner.isIterator:
|
||||
rawAddField(result, createStateField(g, owner, idgen))
|
||||
|
||||
proc getClosureIterResult*(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym =
|
||||
if resultPos < iter.ast.len:
|
||||
result = iter.ast[resultPos].sym
|
||||
else:
|
||||
# XXX a bit hacky:
|
||||
result = newSym(skResult, getIdent(g.cache, ":result"), idgen, iter, iter.info, {})
|
||||
result.typ = iter.typ.returnType
|
||||
incl(result.flagsImpl, sfUsed)
|
||||
iter.ast.add newSymNode(result)
|
||||
|
||||
proc addHiddenParam(routine: PSym, param: PSym) =
|
||||
assert param.kind == skParam
|
||||
var params = routine.ast[paramsPos]
|
||||
# -1 is correct here as param.position is 0 based but we have at position 0
|
||||
# some nkEffect node:
|
||||
param.position = routine.typ.n.len-1
|
||||
params.add newSymNode(param)
|
||||
#incl(routine.typ.flags, tfCapturesEnv)
|
||||
assert sfFromGeneric in param.flags
|
||||
#echo "produced environment: ", param.id, " for ", routine.id
|
||||
|
||||
proc getEnvParam*(routine: PSym): PSym =
|
||||
if routine.ast.isNil: return nil
|
||||
let params = routine.ast[paramsPos]
|
||||
let hidden = lastSon(params)
|
||||
if hidden.kind == nkSym and hidden.sym.kind == skParam and hidden.sym.name.s == paramName:
|
||||
result = hidden.sym
|
||||
assert sfFromGeneric in result.flags
|
||||
else:
|
||||
result = nil
|
||||
|
||||
proc getHiddenParam(g: ModuleGraph; routine: PSym): PSym =
|
||||
result = getEnvParam(routine)
|
||||
if result.isNil:
|
||||
# writeStackTrace()
|
||||
localError(g.config, routine.info, "internal error: could not find env param for " & routine.name.s)
|
||||
result = routine
|
||||
|
||||
proc interestingVar(s: PSym): bool {.inline.} =
|
||||
result = s.kind in {skVar, skLet, skTemp, skForVar, skParam, skResult} and
|
||||
sfGlobal notin s.flags and
|
||||
@@ -706,9 +635,6 @@ proc accessViaEnvVar(n: PNode; owner: PSym; d: var DetectionPass;
|
||||
localError(d.graph.config, n.info, "internal error: not part of closure object type")
|
||||
result = n
|
||||
|
||||
proc getStateField*(g: ModuleGraph; owner: PSym): PSym =
|
||||
getHiddenParam(g, owner).typ.skipTypes({tyOwned, tyRef, tyPtr}).n[0].sym
|
||||
|
||||
proc liftCapturedVars(n: PNode; owner: PSym; d: var DetectionPass;
|
||||
c: var LiftingPass): PNode
|
||||
|
||||
@@ -759,6 +685,11 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: var DetectionPass;
|
||||
else:
|
||||
s.transformedBody = newTree(nkStmtList, rawClosureCreation(s, d, c, n.info), body)
|
||||
finishClosureCreation(s, d, c, n.info, s.transformedBody)
|
||||
|
||||
if isIterator(s) and s.closureBody == nil:
|
||||
let injected = injectDestructorCalls(d.graph, d.idgen, s, body)
|
||||
let closureBody = transformClosureIterator(d.graph, d.idgen, s, injected)
|
||||
s.closureBody = closureBody
|
||||
c.inContainer = oldInContainer
|
||||
|
||||
if s.typ.callConv == ccClosure:
|
||||
|
||||
80
compiler/lambdautils.nim
Normal file
80
compiler/lambdautils.nim
Normal file
@@ -0,0 +1,80 @@
|
||||
import ast, modulegraphs, magicsys, idents, lowerings, msgs, lineinfos
|
||||
|
||||
import std/assertions
|
||||
|
||||
const
|
||||
upName* = ":up" # field name for the 'up' reference
|
||||
paramName* = ":envP"
|
||||
envName* = ":env"
|
||||
|
||||
# ---------------- essential helpers -------------------------------------
|
||||
|
||||
|
||||
proc newCall(a: PSym, b: PNode): PNode =
|
||||
result = newNodeI(nkCall, a.info)
|
||||
result.add newSymNode(a)
|
||||
result.add b
|
||||
|
||||
proc createClosureIterStateType*(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PType =
|
||||
var n = newNodeI(nkRange, iter.info)
|
||||
n.add newIntNode(nkIntLit, -1)
|
||||
n.add newIntNode(nkIntLit, 0)
|
||||
result = newType(tyRange, idgen, iter)
|
||||
result.n = n
|
||||
var intType = nilOrSysInt(g)
|
||||
if intType.isNil: intType = newType(tyInt, idgen, iter)
|
||||
rawAddSon(result, intType)
|
||||
|
||||
proc createStateField(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym =
|
||||
result = newSym(skField, getIdent(g.cache, ":state"), idgen, iter, iter.info)
|
||||
result.typ = createClosureIterStateType(g, iter, idgen)
|
||||
|
||||
template isIterator*(owner: PSym): bool =
|
||||
owner.kind == skIterator and owner.typ.callConv == ccClosure
|
||||
|
||||
proc createEnvObj*(g: ModuleGraph; idgen: IdGenerator; owner: PSym; info: TLineInfo): PType =
|
||||
result = createObj(g, idgen, owner, info, final=false)
|
||||
result.incl tfFinal
|
||||
if owner.isIterator:
|
||||
rawAddField(result, createStateField(g, owner, idgen))
|
||||
|
||||
proc getClosureIterResult*(g: ModuleGraph; iter: PSym; idgen: IdGenerator): PSym =
|
||||
if resultPos < iter.ast.len:
|
||||
result = iter.ast[resultPos].sym
|
||||
else:
|
||||
# XXX a bit hacky:
|
||||
result = newSym(skResult, getIdent(g.cache, ":result"), idgen, iter, iter.info, {})
|
||||
result.typ = iter.typ.returnType
|
||||
incl(result.flagsImpl, sfUsed)
|
||||
iter.ast.add newSymNode(result)
|
||||
|
||||
proc addHiddenParam*(routine: PSym, param: PSym) =
|
||||
assert param.kind == skParam
|
||||
var params = routine.ast[paramsPos]
|
||||
# -1 is correct here as param.position is 0 based but we have at position 0
|
||||
# some nkEffect node:
|
||||
param.position = routine.typ.n.len-1
|
||||
params.add newSymNode(param)
|
||||
#incl(routine.typ.flags, tfCapturesEnv)
|
||||
assert sfFromGeneric in param.flags
|
||||
#echo "produced environment: ", param.id, " for ", routine.id
|
||||
|
||||
proc getEnvParam*(routine: PSym): PSym =
|
||||
if routine.ast.isNil: return nil
|
||||
let params = routine.ast[paramsPos]
|
||||
let hidden = lastSon(params)
|
||||
if hidden.kind == nkSym and hidden.sym.kind == skParam and hidden.sym.name.s == paramName:
|
||||
result = hidden.sym
|
||||
assert sfFromGeneric in result.flags
|
||||
else:
|
||||
result = nil
|
||||
|
||||
proc getHiddenParam*(g: ModuleGraph; routine: PSym): PSym =
|
||||
result = getEnvParam(routine)
|
||||
if result.isNil:
|
||||
# writeStackTrace()
|
||||
localError(g.config, routine.info, "internal error: could not find env param for " & routine.name.s)
|
||||
result = routine
|
||||
|
||||
proc getStateField*(g: ModuleGraph; owner: PSym): PSym =
|
||||
getHiddenParam(g, owner).typ.skipTypes({tyOwned, tyRef, tyPtr}).n[0].sym
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
## Plugin to transform an inline iterator into a data structure.
|
||||
|
||||
import ".." / [ast, modulegraphs, lookups, semdata, lambdalifting, msgs]
|
||||
import ".." / [ast, modulegraphs, lookups, semdata, lambdautils, lambdalifting, msgs]
|
||||
|
||||
proc iterToProcImpl*(c: PContext, n: PNode): PNode =
|
||||
result = newNodeI(nkStmtList, n.info)
|
||||
|
||||
@@ -130,8 +130,8 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
|
||||
if c.tooEarly: return n
|
||||
else:
|
||||
if s.closureBody == nil:
|
||||
let transformedBody = injectDestructorCalls(c.graph, c.idgen, s, body)
|
||||
let closureBody = transformClosureIterator(c.graph, c.idgen, s, transformedBody)
|
||||
let injected = injectDestructorCalls(c.graph, c.idgen, s, body)
|
||||
let closureBody = transformClosureIterator(c.graph, c.idgen, s, injected)
|
||||
s.closureBody = closureBody
|
||||
return liftIterSym(c.graph, n, c.idgen, getCurrOwner(c))
|
||||
elif s.kind in {skProc, skFunc, skConverter, skMethod} and not c.tooEarly:
|
||||
|
||||
Reference in New Issue
Block a user