Skip to content

Commit f724096

Browse files
authored
closures (#1178)
1 parent 53c0cd5 commit f724096

File tree

3 files changed

+35
-15
lines changed

3 files changed

+35
-15
lines changed

src/hexer/lambdalifting.nim

Lines changed: 24 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ proc treProcBody(c: var Context; dest, init: var TokenBuf; n: var Cursor; sym: S
311311
dest.addDotToken() # no pragmas
312312
dest.copyIntoKind RefT, NoLineInfo:
313313
dest.addSymUse c.env.typ, NoLineInfo
314-
dest.copyIntoKind NewrefX, NoLineInfo:
314+
dest.copyIntoKind NewobjX, NoLineInfo:
315315
dest.copyIntoKind RefT, NoLineInfo:
316316
dest.addSymUse c.env.typ, NoLineInfo
317317
elif c.closureProcs.contains(sym):
@@ -321,20 +321,18 @@ proc treProcBody(c: var Context; dest, init: var TokenBuf; n: var Cursor; sym: S
321321
dest.add init
322322
while n.kind != ParRi:
323323
tre(c, dest, n)
324-
inc n # ParRi
325324
c.env = oldEnv
326325
else:
327326
tre(c, dest, n)
328327

329328
proc treProc(c: var Context; dest: var TokenBuf; n: var Cursor) =
330-
c.typeCache.openScope(ProcScope)
331329
var init = createTokenBuf(10)
332330
copyInto dest, n:
333331
var isConcrete = true # assume it is concrete
334332
let sym = n.symId
335333
for i in 0..<BodyPos:
336334
if i == ParamsPos:
337-
c.typeCache.registerLocal(sym, ProcY, n)
335+
c.typeCache.openProcScope(sym, n)
338336
treParams c, dest, init, n, c.closureProcs.contains(sym)
339337
else:
340338
if i == TypeVarsPos:
@@ -368,7 +366,7 @@ proc genCall(c: var Context; dest: var TokenBuf; n: var Cursor) =
368366
inc n
369367
var fn = n
370368
let typ = c.typeCache.getType(n, {SkipAliases})
371-
let wantsEnv = isClosure(typ)
369+
let wantsEnv = isClosure(typ) or (n.kind == Symbol and c.closureProcs.contains(n.symId))
372370
var isStatic = false
373371
var tmp = SymId(0)
374372
if wantsEnv:
@@ -408,6 +406,7 @@ proc genCall(c: var Context; dest: var TokenBuf; n: var Cursor) =
408406
copyIntoKind dest, TupatX, info:
409407
dest.addSymUse tmp, info
410408
dest.addIntLit 1, info
409+
dest.addParRi()
411410
skipParRi n
412411

413412
proc treProcType(c: var Context; dest: var TokenBuf; n: var Cursor) =
@@ -493,8 +492,10 @@ proc tre(c: var Context; dest: var TokenBuf; n: var Cursor) =
493492
inc n
494493
dest.copyIntoKind DotX, info:
495494
dest.copyIntoKind DerefX, info:
496-
dest.typedEnv info, c.env
497-
skip n # type not needed...
495+
dest.copyIntoKind CastX, info:
496+
dest.copyIntoKind RefT, info:
497+
dest.takeTree n # type
498+
dest.addSymUse c.env.s, info
498499
assert n.kind == Symbol
499500
dest.takeTree n # the symbol
500501
skipParRi n
@@ -513,6 +514,7 @@ proc genObjectTypes(c: var Context; dest: var TokenBuf) =
513514
for local, field in c.localToEnv:
514515
objectTypes.mgetOrPut(field.objType, @[]).add(field)
515516
for objType, fields in objectTypes:
517+
let beforeType = dest.len
516518
dest.copyIntoKind TypeS, NoLineInfo:
517519
dest.addSymDef objType, NoLineInfo
518520
dest.addDotToken() # no export marker
@@ -521,14 +523,17 @@ proc genObjectTypes(c: var Context; dest: var TokenBuf) =
521523
dest.copyIntoKind ObjectT, NoLineInfo:
522524
# inherits from RootObj:
523525
dest.addSymUse pool.syms.getOrIncl(RootObjName), NoLineInfo
524-
for field in items fields:
525-
dest.copyIntoKind FldY, NoLineInfo:
526-
dest.addSymDef field.field, NoLineInfo
527-
dest.addDotToken() # no export marker
528-
dest.addDotToken() # no pragmas
529-
var n = field.typ
530-
tre(c, dest, n) # type might need an environment parameter
531-
dest.addDotToken() # no default value
526+
for field in items fields:
527+
let beforeField = dest.len
528+
dest.copyIntoKind FldY, NoLineInfo:
529+
dest.addSymDef field.field, NoLineInfo
530+
dest.addDotToken() # no export marker
531+
dest.addDotToken() # no pragmas
532+
var n = field.typ
533+
tre(c, dest, n) # type might need an environment parameter
534+
dest.addDotToken() # no default value
535+
programs.publish(field.field, dest, beforeField)
536+
programs.publish(objType, dest, beforeType)
532537

533538
proc elimLambdas*(n: Cursor; moduleSuffix: string): TokenBuf =
534539
var c = Context(counter: 0, typeCache: createTypeCache(), thisModuleSuffix: moduleSuffix)
@@ -541,6 +546,7 @@ proc elimLambdas*(n: Cursor; moduleSuffix: string): TokenBuf =
541546
# second pass: generate environments
542547
if c.localToEnv.len > 0:
543548
# some closure usage has been found, so we need to generate environments
549+
c.typeCache.openScope()
544550
let cap = result.len
545551
var oldResult = move result
546552
result = createTokenBuf(cap)
@@ -553,5 +559,8 @@ proc elimLambdas*(n: Cursor; moduleSuffix: string): TokenBuf =
553559
tre(c, result, n)
554560
result.takeParRi n
555561
endRead(oldResult)
562+
c.typeCache.closeScope()
563+
564+
#echo "PRODUCED ", toString(result, false)
556565

557566
# TODO: `nil` must be patched to be `(nil, nil)`.

src/nimony/programs.nim

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,13 @@ proc knowsSym*(s: SymId): bool {.inline.} = prog.mem.hasKey(s)
255255
proc publish*(s: SymId; buf: sink TokenBuf) =
256256
prog.mem[s] = buf
257257

258+
proc publish*(s: SymId; dest: TokenBuf; start: int) =
259+
# XXX We really need to find an elegant way to use Cursor here instead of Tokenbuf copies
260+
var buf = createTokenBuf(dest.len - start + 1)
261+
for i in start..<dest.len:
262+
buf.add dest[i]
263+
publish s, buf
264+
258265
proc splitModulePath*(s: string): (string, string, string) =
259266
var (dir, main, ext) = splitFile(s)
260267
let dotPos = find(main, '.')

src/nimony/typenav.nim

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,10 @@ proc registerParams*(c: var TypeCache; routine: SymId; params: Cursor) =
6666
registerLocal(c, r.name.symId, ParamY, r.typ)
6767
c.current.locals[routine] = LocalInfo(kind: ProcY, typ: params)
6868

69+
proc openProcScope*(c: var TypeCache; routine: SymId; params: Cursor) =
70+
registerLocal(c, routine, ProcY, params)
71+
c.current = TypeScope(locals: initTable[SymId, LocalInfo](), parent: c.current, kind: ProcScope)
72+
6973
proc firstSon(n: Cursor): Cursor {.inline.} =
7074
result = n
7175
inc result

0 commit comments

Comments
 (0)