diff --git a/src/config.nim b/src/config.nim index 218807b..12c2291 100644 --- a/src/config.nim +++ b/src/config.nim @@ -27,7 +27,7 @@ when len(PEON_COMMIT_HASH) != 40: const PEON_BRANCH* = "master" when len(PEON_BRANCH) > 255: {.fatal: "The git branch name's length must be less than or equal to 255 characters".} -const DEBUG_TRACE_VM* = true # Traces VM execution +const DEBUG_TRACE_VM* = false # Traces VM execution const DEBUG_TRACE_GC* = false # Traces the garbage collector (TODO) const DEBUG_TRACE_ALLOCATION* = false # Traces memory allocation/deallocation const DEBUG_TRACE_COMPILER* = false # Traces the compiler diff --git a/src/frontend/compiler.nim b/src/frontend/compiler.nim index b43d8e5..a7d668b 100644 --- a/src/frontend/compiler.nim +++ b/src/frontend/compiler.nim @@ -385,8 +385,7 @@ proc getStackPos(self: Compiler, name: IdentExpr, depth: int = self.scopeDepth): if name.name.lexeme == variable.name.name.lexeme: if variable.isPrivate and variable.owner != self.currentModule: continue - elif variable.depth == depth or variable.depth == 0: - # variable.depth == 0 for globals! + elif variable.depth == depth: found = true dec(result) break @@ -1317,6 +1316,7 @@ proc callExpr(self: Compiler, node: CallExpr) = while node.kind == callExpr: self.callExpr(CallExpr(node)) node = CallExpr(node).callee + # funct = self.matchImpl(IdentExpr(node.callee).name.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: args)) # TODO: Calling lambdas else: let typ = self.inferType(node) @@ -1472,23 +1472,19 @@ proc continueStmt(self: Compiler, node: ContinueStmt) = proc breakStmt(self: Compiler, node: BreakStmt) = ## Compiles break statements. A continue statement ## jumps to the next iteration in a loop - - # Emits dummy jump offset, this is - # patched later - self.currentLoop.breakPos.add(self.emitJump(OpCode.Jump)) + self.currentLoop.breakPos.add(self.emitJump(OpCode.JumpForwards)) if self.currentLoop.depth > self.scopeDepth: # Breaking out of a loop closes its scope self.endScope() proc patchBreaks(self: Compiler) = - ## Patches "break" opcodes with - ## actual jumps. This is needed + ## Patches the jumps emitted by + ## breakStmt. This is needed ## because the size of code ## to skip is not known before ## the loop is fully compiled for brk in self.currentLoop.breakPos: - self.chunk.code[brk] = JumpForwards.uint8() self.patchJump(brk) @@ -1512,7 +1508,7 @@ proc importStmt(self: Compiler, node: ImportStmt) = var parser = newParser() var compiler = newCompiler() # TODO: Find module - var result = compiler.compile(parser.parse(lexer.lex("", node.moduleName.name.lexeme), node.moduleName.name.lexeme), node.moduleName.name.lexeme) + var result {.used.} = compiler.compile(parser.parse(lexer.lex("", node.moduleName.name.lexeme), node.moduleName.name.lexeme), node.moduleName.name.lexeme) proc statement(self: Compiler, node: Statement) = @@ -1544,9 +1540,9 @@ proc statement(self: Compiler, node: Statement) = self.returnStmt(ReturnStmt(node)) of NodeKind.importStmt: self.importStmt(ImportStmt(node)) - of NodeKind.whileStmt, NodeKind.forStmt: - ## Our parser already desugars for loops to - ## while loops! + of NodeKind.whileStmt: + # Note: Our parser already desugars + # for loops to while loops! let loop = self.currentLoop self.currentLoop = Loop(start: self.chunk.code.len(), depth: self.scopeDepth, breakPos: @[]) @@ -1604,7 +1600,7 @@ proc handleMagicPragma(self: Compiler, pragma: Pragma, node: ASTNode) = if pragma.args.len() != 1: self.error("'magic' pragma: wrong number of arguments") elif pragma.args[0].kind != strExpr: - self.error("'magic' pragma: wrong type of argument (string expected)") + self.error("'magic' pragma: wrong type of argument (constant string expected)") elif node.kind != NodeKind.funDecl: self.error("'magic' pragma is not valid in this context") var node = FunDecl(node) @@ -1623,7 +1619,7 @@ proc handlePurePragma(self: Compiler, pragma: Pragma, node: ASTNode) = of lambdaExpr: LambdaExpr(node).isPure = true else: - self.error("'pure' pragma: invalid usage") + self.error("'pure' pragma is not valid in this context") proc dispatchPragmas(self: Compiler, node: ASTnode) = @@ -1676,12 +1672,11 @@ proc funDecl(self: Compiler, node: FunDecl, fn: Name = nil, args: seq[Expression else: var function = self.currentFunction var jmp: int - # Builtin functions map to a single - # bytecode instruction to avoid - # unnecessary overhead from peon's - # calling convention. This also means - # that peon's fast builtins can only - # be relatively simple + # Builtin functions (usually) map to a single + # bytecode instruction to avoid unnecessary + # overhead from peon's calling convention + # This also means that peon's fast builtins + # can only be relatively simple self.frames.add(self.names.high()) # A function's code is just compiled linearly # and then jumped over @@ -1834,7 +1829,6 @@ proc compile*(self: Compiler, ast: seq[Declaration], file: string): Chunk = self.names.add(main) self.emitByte(LoadFunction) self.emitBytes(main.codePos.toTriple()) - self.emitByte(LoadReturnAddress) let pos = self.chunk.code.len() self.emitBytes(0.toQuad()) diff --git a/src/frontend/meta/ast.nim b/src/frontend/meta/ast.nim index 2e22ba8..099786e 100644 --- a/src/frontend/meta/ast.nim +++ b/src/frontend/meta/ast.nim @@ -34,7 +34,6 @@ type funDecl, varDecl, # Statements - forStmt, # Unused for now (for loops are compiled to while loops) ifStmt, returnStmt, breakStmt, @@ -62,7 +61,7 @@ type sliceExpr, callExpr, getItemExpr, # Get expressions like a.b - # Primary expressions + # Primary expressions groupingExpr, # Parenthesized expressions such as (true) and (3 + 4) trueExpr, falseExpr, diff --git a/tests/closures.pn b/tests/closures.pn index 8a92f74..df8bd06 100644 --- a/tests/closures.pn +++ b/tests/closures.pn @@ -6,4 +6,5 @@ fn makeClosure(n: int): fn: int { } -makeClosure(1)(); +var closure = makeClosure(1); +closure();