Browse Source

Updated Makefile

master
Mattia Giambirtone 3 months ago
parent
commit
e38610fdbd
  1. 4
      Makefile
  2. 2
      src/config.nim
  3. 20
      src/frontend/compiler.nim
  4. 9
      tests/closures.pn

4
Makefile

@ -1,5 +1,5 @@
run:
nim --hints:off --warnings:off r src/test.nim
repl:
nim --hints:off --warnings:off r src/main.nim
pretty:
nimpretty src/*.nim src/backend/*.nim src/frontend/*.nim src/frontend/meta/*.nim src/memory/*.nim src/util/*.nim

2
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* = false # Traces VM execution
const DEBUG_TRACE_VM* = true # 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

20
src/frontend/compiler.nim

@ -429,7 +429,7 @@ proc resolve(self: Compiler, name: string,
return nil
proc detectClosureVariable(self: Compiler, name: var Name, depth: int = self.scopeDepth, decl: bool = false) =
proc detectClosureVariable(self: Compiler, name: var Name, depth: int = self.scopeDepth) =
## Detects if the given name is used in a local scope deeper
## than the given one and modifies the code emitted for it
## to store it as a closure variable if it is. Does nothing if the name
@ -438,7 +438,7 @@ proc detectClosureVariable(self: Compiler, name: var Name, depth: int = self.sco
## each time a name is referenced in order for closed-over variables
## to be emitted properly, otherwise the runtime may behave
## unpredictably or crash
if name.isNil() or name.depth == 0:
if name.isNil() or name.depth == 0 or name.isClosedOver:
return
elif name.depth < depth:
# Ding! The given name is closed over: we need to
@ -446,14 +446,13 @@ proc detectClosureVariable(self: Compiler, name: var Name, depth: int = self.sco
# put in place for us into a StoreClosure. We also update
# the name's isClosedOver field so that self.identifier()
# can emit a LoadClosure instruction instead of a LoadVar
if not name.isClosedOver:
self.closedOver.add(name)
self.closedOver.add(name)
if self.closedOver.len() >= 16777216:
self.error("too many consecutive closed-over variables (max is 16777215)")
name.isClosedOver = true
if decl:
self.emitByte(StoreClosure)
self.emitBytes(self.closedOver.high().toTriple())
self.chunk.code[name.codePos] = StoreClosure.uint8()
for i, b in self.closedOver.high().toTriple():
self.chunk.code[name.codePos + i + 1] = b
proc compareTypes(self: Compiler, a, b: Type): bool =
@ -1129,6 +1128,8 @@ proc identifier(self: Compiler, node: IdentExpr) =
# no matter the scope depth
self.emitConstant(node, self.inferType(node))
else:
self.emitByte(JumpForwards)
self.emitBytes(0.toTriple())
self.detectClosureVariable(s)
if s.valueType.kind == Function:
# Functions have no runtime
@ -1149,7 +1150,6 @@ proc identifier(self: Compiler, node: IdentExpr) =
self.emitBytes(self.getClosurePos(s.name).toTriple())
proc assignment(self: Compiler, node: ASTNode) =
## Compiles assignment expressions
case node.kind:
@ -1583,10 +1583,8 @@ proc varDecl(self: Compiler, node: VarDecl) =
self.error(&"expected value of type '{self.typeToStr(expected)}', but '{node.name.token.lexeme}' is of type '{self.typeToStr(actual)}'")
self.expression(node.value)
self.declareName(node, mutable=node.token.kind == TokenType.Var)
var r = self.names[^1]
self.detectClosureVariable(r, decl=true)
self.emitByte(StoreVar)
self.emitBytes((self.getStackPos(r.name) + 1).toTriple())
self.emitBytes((self.getStackPos(self.names[^1].name) + 1).toTriple())
proc typeDecl(self: Compiler, node: TypeDecl) =

9
tests/closures.pn

@ -1,8 +1,9 @@
fn makeClosure(n: int): fn: int {
fn inner: int {
return n;
}
return inner;
var n = n;
fn inner: int {
return n;
}
return inner;
}

Loading…
Cancel
Save