Skip to content

Commit e3fdb8b

Browse files
authored
enable closures (#1185)
1 parent 8768299 commit e3fdb8b

File tree

8 files changed

+73
-78
lines changed

8 files changed

+73
-78
lines changed

src/hexer/constparams.nim

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -208,22 +208,25 @@ proc trCall(c: var Context; dest: var TokenBuf; n: var Cursor; targetExpectsTupl
208208
inc fnType
209209
while n.kind != ParRi:
210210
let previousFormalParam = fnType
211-
assert fnType.kind == ParLe
212-
let param = takeLocal(fnType, SkipFinalParRi)
213-
let pk = param.typ.typeKind
214-
if pk in {MutT, OutT, LentT}:
215-
tr c, dest, n
216-
elif pk == VarargsT:
217-
# do not advance formal parameter:
218-
fnType = previousFormalParam
219-
tr c, dest, n
220-
elif passByConstRef(c, param.typ, param.pragmas):
221-
trConstRef c, dest, n
222-
elif pk in {TypedescT, StaticT}:
223-
# do not produce any code for this as it's a compile-time value:
224-
skip n
211+
if fnType.kind == ParRi:
212+
tr c, dest, n # can happen for closure parameter
225213
else:
226-
tr c, dest, n
214+
assert fnType.kind == ParLe
215+
let param = takeLocal(fnType, SkipFinalParRi)
216+
let pk = param.typ.typeKind
217+
if pk in {MutT, OutT, LentT}:
218+
tr c, dest, n
219+
elif pk == VarargsT:
220+
# do not advance formal parameter:
221+
fnType = previousFormalParam
222+
tr c, dest, n
223+
elif passByConstRef(c, param.typ, param.pragmas):
224+
trConstRef c, dest, n
225+
elif pk in {TypedescT, StaticT}:
226+
# do not produce any code for this as it's a compile-time value:
227+
skip n
228+
else:
229+
tr c, dest, n
227230
takeParRi dest, n
228231
if needsTuple:
229232
dest.addParRi() # TupconstrX

src/hexer/duplifier.nim

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -613,14 +613,17 @@ proc trCall(c: var Context; n: var Cursor; e: Expects) =
613613
inc fnType
614614
while n.kind != ParRi:
615615
let previousFormalParam = fnType
616-
let param = takeLocal(fnType, SkipFinalParRi)
617-
let pk = param.typ.typeKind
618616
var e2 = WantNonOwner
619-
if pk == SinkT:
620-
e2 = WantOwner
621-
elif pk == VarargsT:
622-
# do not advance formal parameter:
623-
fnType = previousFormalParam
617+
if fnType.kind == ParRi:
618+
discard "this can happen for closure parameters"
619+
else:
620+
let param = takeLocal(fnType, SkipFinalParRi)
621+
let pk = param.typ.typeKind
622+
if pk == SinkT:
623+
e2 = WantOwner
624+
elif pk == VarargsT:
625+
# do not advance formal parameter:
626+
fnType = previousFormalParam
624627
tr c, n, e2
625628
takeParRi c.dest, n
626629
finishOwningTemp c.dest, ow

src/hexer/lambdalifting.nim

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,18 @@ proc trLocal(c: var Context; dest: var TokenBuf; n: var Cursor) =
8282
proc trProc(c: var Context; dest: var TokenBuf; n: var Cursor) =
8383
c.typeCache.openScope(ProcScope)
8484
copyInto dest, n:
85-
c.procStack.add(n.symId)
86-
let isConcrete = c.typeCache.takeRoutineHeader(dest, n)
85+
let symId = n.symId
86+
c.procStack.add(symId)
87+
var isConcrete = true # assume it is concrete
88+
for i in 0..<BodyPos:
89+
if i == ParamsPos:
90+
c.typeCache.registerParams(symId, n)
91+
elif i == TypeVarsPos:
92+
isConcrete = n.substructureKind != TypevarsU
93+
elif i == ProcPragmasPos:
94+
if hasPragma(n, ClosureP):
95+
c.closureProcs.incl symId
96+
takeTree dest, n
8797
if isConcrete:
8898
tr(c, dest, n)
8999
else:
@@ -314,6 +324,16 @@ proc treProcBody(c: var Context; dest, init: var TokenBuf; n: var Cursor; sym: S
314324
dest.copyIntoKind NewobjX, NoLineInfo:
315325
dest.copyIntoKind RefT, NoLineInfo:
316326
dest.addSymUse c.env.typ, NoLineInfo
327+
# init the environment via the `=wasMoved` hooks:
328+
for _, field in c.localToEnv:
329+
if field.objType == c.env.typ:
330+
dest.copyIntoKind WasmovedX, NoLineInfo:
331+
dest.copyIntoKind HaddrX, NoLineInfo:
332+
dest.copyIntoKind DotX, NoLineInfo:
333+
dest.copyIntoKind DerefX, NoLineInfo:
334+
dest.addSymUse c.env.s, NoLineInfo
335+
dest.addSymUse field.field, NoLineInfo
336+
317337
elif c.closureProcs.contains(sym):
318338
c.env = CurrentEnv(s: pool.syms.getOrIncl(EnvParamName), mode: EnvIsParam, typ: c.envTypeForProc(sym))
319339
else:
@@ -398,8 +418,13 @@ proc genCall(c: var Context; dest: var TokenBuf; n: var Cursor) =
398418
tre(c, dest, n)
399419
if wantsEnv:
400420
if isStatic:
401-
# use the current environment as the last parameter:
402-
untypedEnv dest, info, c.env
421+
if c.env.s != SymId(0):
422+
# use the current environment as the last parameter:
423+
untypedEnv dest, info, c.env
424+
else:
425+
# can happen for toplevel closures that have been declared .closure for interop
426+
# We have no environment here, so pass `nil` instead:
427+
dest.copyIntoKind NilX, info: discard
403428
else:
404429
# unpack the tuple:
405430
assert tmp != SymId(0)

src/nimony/derefs.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -714,7 +714,7 @@ proc trFor(c: var Context; n: var Cursor) =
714714
proc tr(c: var Context; n: var Cursor; e: Expects) =
715715
case n.kind
716716
of Symbol:
717-
when true:
717+
when false:
718718
# Closures are now implemented
719719
let localInfo = c.typeCache.getLocalInfo(n.symId)
720720
if localInfo.crossedProc > 0 and localInfo.kind in {VarY, LetY, ParamY, ResultY}:

src/nimony/sigmatch.nim

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -597,12 +597,12 @@ proc linearMatch(m: var Match; f, a: var Cursor; flags: set[LinearMatchFlag] = {
597597
skip a
598598

599599
type
600-
ProcProperties = object
601-
cc: CallConv
602-
usesRaises: bool
603-
usesClosure: bool
600+
ProcProperties* = object
601+
cc*: CallConv
602+
usesRaises*: bool
603+
usesClosure*: bool
604604

605-
proc extractCallConv(c: var Cursor): ProcProperties =
605+
proc extractProcProps*(c: var Cursor): ProcProperties =
606606
result = ProcProperties(cc: Fastcall, usesRaises: false, usesClosure: false)
607607
if c.substructureKind == PragmasU:
608608
inc c
@@ -672,8 +672,8 @@ proc procTypeMatch(m: var Match; f, a: var Cursor) =
672672
else:
673673
linearMatch m, f, a
674674
# match calling conventions:
675-
let fcc = extractCallConv(f)
676-
let acc = extractCallConv(a)
675+
let fcc = extractProcProps(f)
676+
let acc = extractProcProps(a)
677677
if fcc.cc != acc.cc:
678678
m.error CallConvMismatch, f, a
679679
elif fcc.usesRaises != acc.usesRaises:

src/nimony/vtables_frontend.nim

Lines changed: 8 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
include nifprelude
1414
import nifindexes, symparser, treemangler, typekeys
15-
import ".." / nimony / [nimony_model, decls, programs, typenav,
16-
renderer, typeprops]
15+
import nimony_model, decls, programs, typenav,
16+
renderer, typeprops, sigmatch
1717

1818
when false:
1919
# maybe we can use this later to provide better error messages
@@ -40,28 +40,6 @@ when false:
4040
else:
4141
return false
4242

43-
proc processPragmas(n: Cursor): (CallConv, string) =
44-
var n = n
45-
result = (NoCallConv, "0")
46-
if n.substructureKind == PragmasU:
47-
inc n
48-
while n.kind != ParRi:
49-
let pk = pragmaKind(n)
50-
case pk
51-
of NoPragma:
52-
let cc = callConvKind(n)
53-
if cc != NoCallConv:
54-
result[0] = cc
55-
skip n
56-
else:
57-
# it may be a `kv`
58-
skip n
59-
of RaisesP:
60-
result[1] = "1"
61-
skip n
62-
else:
63-
skip n
64-
6543
proc methodKey*(name: string; a: Cursor): string =
6644
# First parameter was the class type and has already been skipped here!
6745
var a = a
@@ -73,5 +51,9 @@ proc methodKey*(name: string; a: Cursor): string =
7351
# also add return type:
7452
mangle b, a, Frontend
7553
skip a
76-
let (callConv, hasRaises) = processPragmas(a)
77-
result = name & ":" & b.extract() & ":" & $callConv & ":" & hasRaises
54+
# handle pragmas:
55+
let props = extractProcProps(a)
56+
b.addKeyw $props.cc
57+
b.addKeyw $props.usesRaises
58+
b.addKeyw $props.usesClosure
59+
result = name & ":" & b.extract()

tests/nimony/errmsgs/tclosureunavail.msgs

Lines changed: 0 additions & 1 deletion
This file was deleted.

tests/nimony/errmsgs/tclosureunavail.nim

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)