Fixed some issued with scoping and globals

This commit is contained in:
Mattia Giambirtone 2022-07-09 13:36:21 +02:00
parent cc0aab850e
commit 3f5f514259
4 changed files with 20 additions and 26 deletions

View File

@ -27,7 +27,7 @@ when len(PEON_COMMIT_HASH) != 40:
const PEON_BRANCH* = "master" const PEON_BRANCH* = "master"
when len(PEON_BRANCH) > 255: when len(PEON_BRANCH) > 255:
{.fatal: "The git branch name's length must be less than or equal to 255 characters".} {.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_GC* = false # Traces the garbage collector (TODO)
const DEBUG_TRACE_ALLOCATION* = false # Traces memory allocation/deallocation const DEBUG_TRACE_ALLOCATION* = false # Traces memory allocation/deallocation
const DEBUG_TRACE_COMPILER* = false # Traces the compiler const DEBUG_TRACE_COMPILER* = false # Traces the compiler

View File

@ -385,8 +385,7 @@ proc getStackPos(self: Compiler, name: IdentExpr, depth: int = self.scopeDepth):
if name.name.lexeme == variable.name.name.lexeme: if name.name.lexeme == variable.name.name.lexeme:
if variable.isPrivate and variable.owner != self.currentModule: if variable.isPrivate and variable.owner != self.currentModule:
continue continue
elif variable.depth == depth or variable.depth == 0: elif variable.depth == depth:
# variable.depth == 0 for globals!
found = true found = true
dec(result) dec(result)
break break
@ -1317,6 +1316,7 @@ proc callExpr(self: Compiler, node: CallExpr) =
while node.kind == callExpr: while node.kind == callExpr:
self.callExpr(CallExpr(node)) self.callExpr(CallExpr(node))
node = CallExpr(node).callee node = CallExpr(node).callee
# funct = self.matchImpl(IdentExpr(node.callee).name.lexeme, Type(kind: Function, returnType: Type(kind: Any), args: args))
# TODO: Calling lambdas # TODO: Calling lambdas
else: else:
let typ = self.inferType(node) let typ = self.inferType(node)
@ -1472,23 +1472,19 @@ proc continueStmt(self: Compiler, node: ContinueStmt) =
proc breakStmt(self: Compiler, node: BreakStmt) = proc breakStmt(self: Compiler, node: BreakStmt) =
## Compiles break statements. A continue statement ## Compiles break statements. A continue statement
## jumps to the next iteration in a loop ## jumps to the next iteration in a loop
self.currentLoop.breakPos.add(self.emitJump(OpCode.JumpForwards))
# Emits dummy jump offset, this is
# patched later
self.currentLoop.breakPos.add(self.emitJump(OpCode.Jump))
if self.currentLoop.depth > self.scopeDepth: if self.currentLoop.depth > self.scopeDepth:
# Breaking out of a loop closes its scope # Breaking out of a loop closes its scope
self.endScope() self.endScope()
proc patchBreaks(self: Compiler) = proc patchBreaks(self: Compiler) =
## Patches "break" opcodes with ## Patches the jumps emitted by
## actual jumps. This is needed ## breakStmt. This is needed
## because the size of code ## because the size of code
## to skip is not known before ## to skip is not known before
## the loop is fully compiled ## the loop is fully compiled
for brk in self.currentLoop.breakPos: for brk in self.currentLoop.breakPos:
self.chunk.code[brk] = JumpForwards.uint8()
self.patchJump(brk) self.patchJump(brk)
@ -1512,7 +1508,7 @@ proc importStmt(self: Compiler, node: ImportStmt) =
var parser = newParser() var parser = newParser()
var compiler = newCompiler() var compiler = newCompiler()
# TODO: Find module # 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) = proc statement(self: Compiler, node: Statement) =
@ -1544,9 +1540,9 @@ proc statement(self: Compiler, node: Statement) =
self.returnStmt(ReturnStmt(node)) self.returnStmt(ReturnStmt(node))
of NodeKind.importStmt: of NodeKind.importStmt:
self.importStmt(ImportStmt(node)) self.importStmt(ImportStmt(node))
of NodeKind.whileStmt, NodeKind.forStmt: of NodeKind.whileStmt:
## Our parser already desugars for loops to # Note: Our parser already desugars
## while loops! # for loops to while loops!
let loop = self.currentLoop let loop = self.currentLoop
self.currentLoop = Loop(start: self.chunk.code.len(), self.currentLoop = Loop(start: self.chunk.code.len(),
depth: self.scopeDepth, breakPos: @[]) depth: self.scopeDepth, breakPos: @[])
@ -1604,7 +1600,7 @@ proc handleMagicPragma(self: Compiler, pragma: Pragma, node: ASTNode) =
if pragma.args.len() != 1: if pragma.args.len() != 1:
self.error("'magic' pragma: wrong number of arguments") self.error("'magic' pragma: wrong number of arguments")
elif pragma.args[0].kind != strExpr: 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: elif node.kind != NodeKind.funDecl:
self.error("'magic' pragma is not valid in this context") self.error("'magic' pragma is not valid in this context")
var node = FunDecl(node) var node = FunDecl(node)
@ -1623,7 +1619,7 @@ proc handlePurePragma(self: Compiler, pragma: Pragma, node: ASTNode) =
of lambdaExpr: of lambdaExpr:
LambdaExpr(node).isPure = true LambdaExpr(node).isPure = true
else: else:
self.error("'pure' pragma: invalid usage") self.error("'pure' pragma is not valid in this context")
proc dispatchPragmas(self: Compiler, node: ASTnode) = proc dispatchPragmas(self: Compiler, node: ASTnode) =
@ -1676,12 +1672,11 @@ proc funDecl(self: Compiler, node: FunDecl, fn: Name = nil, args: seq[Expression
else: else:
var function = self.currentFunction var function = self.currentFunction
var jmp: int var jmp: int
# Builtin functions map to a single # Builtin functions (usually) map to a single
# bytecode instruction to avoid # bytecode instruction to avoid unnecessary
# unnecessary overhead from peon's # overhead from peon's calling convention
# calling convention. This also means # This also means that peon's fast builtins
# that peon's fast builtins can only # can only be relatively simple
# be relatively simple
self.frames.add(self.names.high()) self.frames.add(self.names.high())
# A function's code is just compiled linearly # A function's code is just compiled linearly
# and then jumped over # and then jumped over
@ -1834,7 +1829,6 @@ proc compile*(self: Compiler, ast: seq[Declaration], file: string): Chunk =
self.names.add(main) self.names.add(main)
self.emitByte(LoadFunction) self.emitByte(LoadFunction)
self.emitBytes(main.codePos.toTriple()) self.emitBytes(main.codePos.toTriple())
self.emitByte(LoadReturnAddress) self.emitByte(LoadReturnAddress)
let pos = self.chunk.code.len() let pos = self.chunk.code.len()
self.emitBytes(0.toQuad()) self.emitBytes(0.toQuad())

View File

@ -34,7 +34,6 @@ type
funDecl, funDecl,
varDecl, varDecl,
# Statements # Statements
forStmt, # Unused for now (for loops are compiled to while loops)
ifStmt, ifStmt,
returnStmt, returnStmt,
breakStmt, breakStmt,
@ -62,7 +61,7 @@ type
sliceExpr, sliceExpr,
callExpr, callExpr,
getItemExpr, # Get expressions like a.b getItemExpr, # Get expressions like a.b
# Primary expressions # Primary expressions
groupingExpr, # Parenthesized expressions such as (true) and (3 + 4) groupingExpr, # Parenthesized expressions such as (true) and (3 + 4)
trueExpr, trueExpr,
falseExpr, falseExpr,

View File

@ -6,4 +6,5 @@ fn makeClosure(n: int): fn: int {
} }
makeClosure(1)(); var closure = makeClosure(1);
closure();