diff --git a/src/frontend/compiler.nim b/src/frontend/compiler.nim index 7876561..636f6c1 100644 --- a/src/frontend/compiler.nim +++ b/src/frontend/compiler.nim @@ -1379,11 +1379,9 @@ proc endScope(self: Compiler) = # Arguments to builtin functions become temporaries on the # stack and are popped automatically continue - if not name.belongsTo.resolved or not name.belongsTo.isReal: - # Function hasn't been compiled yet, - # so we can't get rid of its arguments - # (it may need them later) - names.delete(names.high()) + if name.belongsTo.valueType.isAuto: + # Automatic functions do not materialize + # at runtime, so their arguments don't either continue inc(popCount) if not name.resolved: @@ -2345,7 +2343,7 @@ proc getItemExpr(self: Compiler, node: GetItemExpr, compile: bool = true, matchi proc lambdaExpr(self: Compiler, node: LambdaExpr, compile: bool = true): Type {.discardable.} = ## Compiles lambda functions as expressions - result = Type(kind: Function, isLambda: true, fun: node, location: self.chunk.code.high()) + result = Type(kind: Function, isLambda: true, fun: node, location: self.chunk.code.high(), compiled: true) self.beginScope() var constraints: seq[tuple[match: bool, kind: Type]] = @[] for gen in node.generics: @@ -2362,11 +2360,12 @@ proc lambdaExpr(self: Compiler, node: LambdaExpr, compile: bool = true): Type {. file: self.file)) constraints = @[] var default: Expression + var name: Name var i = 0 for argument in node.arguments: if self.names.high() > 16777215: self.error("cannot declare more than 16777215 variables at a time") - self.names.add(Name(depth: self.depth, + name = Name(depth: self.depth, isPrivate: true, owner: self.currentModule, file: self.currentModule.file, @@ -2379,14 +2378,16 @@ proc lambdaExpr(self: Compiler, node: LambdaExpr, compile: bool = true): Type {. belongsTo: nil, # TODO kind: NameKind.Argument, node: argument.name - )) + ) + if compile: + self.names.add(name) if node.arguments.high() - node.defaults.high() <= node.arguments.high(): # There's a default argument! - result.args.add((self.names[^1].ident.token.lexeme, self.names[^1].valueType, node.defaults[i])) + result.args.add((name.ident.token.lexeme, name.valueType, node.defaults[i])) inc(i) else: # This argument has no default - result.args.add((self.names[^1].ident.token.lexeme, self.names[^1].valueType, default)) + result.args.add((name.ident.token.lexeme, name.valueType, default)) # The function needs a return type too! if not node.returnType.isNil(): result.returnType = self.inferOrError(node.returnType) diff --git a/tests/functionObj.pn b/tests/functionObj.pn index 302c9da..6d6bd11 100644 --- a/tests/functionObj.pn +++ b/tests/functionObj.pn @@ -1,5 +1,4 @@ # Tests first class functions - import std; @@ -11,6 +10,6 @@ fn outer: fn (n: int): int { } -var x = outer(); -print(x(50)); # 50 -print(outer()(1)); # 1 +var inner = outer(); +print(inner(20) == 20); +print(outer()(5) == 5); diff --git a/tests/varloop.pn b/tests/varloop.pn new file mode 100644 index 0000000..7face7e --- /dev/null +++ b/tests/varloop.pn @@ -0,0 +1,9 @@ +# Tests declaring a variable inside a loop +import std; + +var x = 0; +while x < 10 { + var _y = 10; + x = x + 1; +} +print(x == 10); \ No newline at end of file