Various fixes to closures and function objects
This commit is contained in:
parent
9c878e5b9e
commit
a4bccba6cd
|
@ -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:
|
||||||
|
|
|
@ -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) =
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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 x = a;
|
||||||
var y = b;
|
var y = b;
|
||||||
fn adder: int {
|
fn adder: int {
|
||||||
|
|
|
@ -18,5 +18,5 @@ fn outerTwo(n: int): int {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
print(outerTwo(5));
|
print(outerTwo(5)); # 5
|
||||||
print(outer());
|
print(outer()); # 69420
|
Loading…
Reference in New Issue