Various fixes to closures and function objects
This commit is contained in:
parent
9c878e5b9e
commit
a4bccba6cd
|
@ -65,6 +65,7 @@ type
|
|||
isClosure: bool
|
||||
envLen: int
|
||||
children: seq[Type]
|
||||
parent: Type
|
||||
of Reference, Pointer:
|
||||
value: Type
|
||||
of Generic:
|
||||
|
@ -475,7 +476,6 @@ proc getStackPos(self: Compiler, name: Name): int =
|
|||
if name == variable:
|
||||
found = true
|
||||
break
|
||||
inc(result)
|
||||
if not found:
|
||||
return -1
|
||||
|
||||
|
@ -944,12 +944,14 @@ proc emitFunction(self: Compiler, name: Name) =
|
|||
# created by previous LoadFunction instructions
|
||||
# that is now bound to some variable, so we just
|
||||
# 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.emitBytes(self.getStackPos(name).toTriple(), name.line)
|
||||
else:
|
||||
self.emitByte(LoadClosure, name.line)
|
||||
self.emitBytes(self.getClosurePos(name).toTriple(), name.line)
|
||||
self.emitByte(LoadVar, name.line)
|
||||
self.emitBytes(self.getStackPos(name).toTriple(), name.line)
|
||||
|
||||
|
||||
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
|
||||
# not much slower than indexing our stack (since they're both dynamic arrays at runtime anyway)
|
||||
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.closedOver.add(s)
|
||||
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
|
||||
if not self.currentFunction.isNil():
|
||||
self.currentFunction.valueType.children.add(fn.valueType)
|
||||
fn.valueType.parent = function.valueType
|
||||
self.currentFunction = fn
|
||||
var names {.used.} = self.names[^(node.arguments.len())..^1]
|
||||
if fn.valueType.isBuiltinFunction:
|
||||
|
|
|
@ -967,6 +967,8 @@ proc parseFunExpr(self: Parser): LambdaExpr =
|
|||
result.returnType = self.parseFunExpr()
|
||||
else:
|
||||
result.returnType = self.expression()
|
||||
result.arguments = arguments
|
||||
result.defaults = defaults
|
||||
|
||||
|
||||
proc parseGenerics(self: Parser, decl: Declaration) =
|
||||
|
|
|
@ -6,12 +6,12 @@ fn first(a, b, c: int): int {
|
|||
}
|
||||
|
||||
fn second(a, b: int): int {
|
||||
return b;
|
||||
return first(b, a, 0);
|
||||
}
|
||||
|
||||
|
||||
fn last(a, b, c: int): int {
|
||||
return c;
|
||||
return second(a, c);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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!
|
||||
|
||||
|
|
|
@ -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 y = b;
|
||||
fn adder: int {
|
||||
|
|
|
@ -18,5 +18,5 @@ fn outerTwo(n: int): int {
|
|||
}
|
||||
|
||||
|
||||
print(outerTwo(5));
|
||||
print(outer());
|
||||
print(outerTwo(5)); # 5
|
||||
print(outer()); # 69420
|
Loading…
Reference in New Issue