diff --git a/src/frontend/compiler.nim b/src/frontend/compiler.nim index da9e3b0..621d081 100644 --- a/src/frontend/compiler.nim +++ b/src/frontend/compiler.nim @@ -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: diff --git a/src/frontend/parser.nim b/src/frontend/parser.nim index e452dc0..fefafbb 100644 --- a/src/frontend/parser.nim +++ b/src/frontend/parser.nim @@ -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) = diff --git a/tests/chainedCalls.pn b/tests/chainedCalls.pn index dfbb50c..e8f5dd0 100644 --- a/tests/chainedCalls.pn +++ b/tests/chainedCalls.pn @@ -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); } diff --git a/tests/closures.pn b/tests/closures.pn index 95dd1a1..9318314 100644 --- a/tests/closures.pn +++ b/tests/closures.pn @@ -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! diff --git a/tests/functionObj.pn b/tests/functionObj.pn index b4922c4..40d4cca 100644 --- a/tests/functionObj.pn +++ b/tests/functionObj.pn @@ -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 { diff --git a/tests/nestedCalls.pn b/tests/nestedCalls.pn index bffe794..2577998 100644 --- a/tests/nestedCalls.pn +++ b/tests/nestedCalls.pn @@ -18,5 +18,5 @@ fn outerTwo(n: int): int { } -print(outerTwo(5)); -print(outer()); \ No newline at end of file +print(outerTwo(5)); # 5 +print(outer()); # 69420 \ No newline at end of file