Various fixes to closures and function objects

This commit is contained in:
Mattia Giambirtone 2022-10-06 09:57:19 +02:00
parent 9c878e5b9e
commit a4bccba6cd
6 changed files with 24 additions and 11 deletions

View File

@ -65,6 +65,7 @@ type
isClosure: bool isClosure: bool
envLen: int envLen: int
children: seq[Type] children: seq[Type]
parent: Type
of Reference, Pointer: of Reference, Pointer:
value: Type value: Type
of Generic: of Generic:
@ -475,7 +476,6 @@ proc getStackPos(self: Compiler, name: Name): int =
if name == variable: if name == variable:
found = true found = true
break break
inc(result)
if not found: if not found:
return -1 return -1
@ -944,12 +944,14 @@ proc emitFunction(self: Compiler, name: Name) =
# created by previous LoadFunction instructions # created by previous LoadFunction instructions
# that is now bound to some variable, so we just # that is now bound to some variable, so we just
# load it # load it
elif self.scopeDepth > 0 and name.depth != self.scopeDepth: elif self.scopeDepth > 0 and not self.currentFunction.isNil() and name.depth != self.scopeDepth:
self.emitByte(LoadClosure, name.line)
self.emitBytes(self.getClosurePos(name).toTriple(), name.line)
self.emitByte(LoadVar, name.line) self.emitByte(LoadVar, name.line)
self.emitBytes(self.getStackPos(name).toTriple(), name.line) self.emitBytes(self.getStackPos(name).toTriple(), name.line)
else: else:
self.emitByte(LoadClosure, name.line) self.emitByte(LoadVar, name.line)
self.emitBytes(self.getClosurePos(name).toTriple(), name.line) self.emitBytes(self.getStackPos(name).toTriple(), name.line)
proc generateCall(self: Compiler, fn: Name, args: seq[Expression], onStack: bool = false) = proc generateCall(self: Compiler, fn: Name, args: seq[Expression], onStack: bool = false) =
@ -1441,7 +1443,13 @@ proc identifier(self: Compiler, node: IdentExpr) =
# align its semantics with the call stack. This makes closures work as expected and is # align its semantics with the call stack. This makes closures work as expected and is
# not much slower than indexing our stack (since they're both dynamic arrays at runtime anyway) # not much slower than indexing our stack (since they're both dynamic arrays at runtime anyway)
if not s.isClosedOver: if not s.isClosedOver:
self.currentFunction.valueType.isClosure = true var fn = self.currentFunction.valueType
while true:
fn.isClosure = true
if fn.parent.isNil():
break
fn = fn.parent
s.isClosedOver = true
self.currentFunction.valueType.envLen += 1 self.currentFunction.valueType.envLen += 1
self.closedOver.add(s) self.closedOver.add(s)
let stackIdx = self.getStackPos(s).toTriple() let stackIdx = self.getStackPos(s).toTriple()
@ -1851,6 +1859,7 @@ proc funDecl(self: Compiler, node: FunDecl, fn: Name = nil, args: seq[Expression
var function = self.currentFunction var function = self.currentFunction
if not self.currentFunction.isNil(): if not self.currentFunction.isNil():
self.currentFunction.valueType.children.add(fn.valueType) self.currentFunction.valueType.children.add(fn.valueType)
fn.valueType.parent = function.valueType
self.currentFunction = fn self.currentFunction = fn
var names {.used.} = self.names[^(node.arguments.len())..^1] var names {.used.} = self.names[^(node.arguments.len())..^1]
if fn.valueType.isBuiltinFunction: if fn.valueType.isBuiltinFunction:

View File

@ -967,6 +967,8 @@ proc parseFunExpr(self: Parser): LambdaExpr =
result.returnType = self.parseFunExpr() result.returnType = self.parseFunExpr()
else: else:
result.returnType = self.expression() result.returnType = self.expression()
result.arguments = arguments
result.defaults = defaults
proc parseGenerics(self: Parser, decl: Declaration) = proc parseGenerics(self: Parser, decl: Declaration) =

View File

@ -6,12 +6,12 @@ fn first(a, b, c: int): int {
} }
fn second(a, b: int): int { fn second(a, b: int): int {
return b; return first(b, a, 0);
} }
fn last(a, b, c: int): int { fn last(a, b, c: int): int {
return c; return second(a, c);
} }

View File

@ -13,5 +13,7 @@ fn makeClosure(n: int): fn: fn: int {
} }
print(makeClosure(1)()()); # 1 var closure = makeClosure(38);
var inner = closure();
print(inner()); # 38!

View File

@ -12,7 +12,7 @@ fn outer: fn (n: int): int {
fn getAdder(a, b: int): fn: int64 { fn getAdder(a, b: int): fn (): int64 {
var x = a; var x = a;
var y = b; var y = b;
fn adder: int { fn adder: int {

View File

@ -18,5 +18,5 @@ fn outerTwo(n: int): int {
} }
print(outerTwo(5)); print(outerTwo(5)); # 5
print(outer()); print(outer()); # 69420