Definitive fix for closures
This commit is contained in:
parent
fc74bab529
commit
11c8c0a5ab
|
@ -31,7 +31,7 @@ when debugVM or debugMem or debugGC:
|
||||||
import std/terminal
|
import std/terminal
|
||||||
|
|
||||||
|
|
||||||
{.push checks:off.} # The VM is a critical point where checks are deleterious
|
{.push checks:on.} # The VM is a critical point where checks are deleterious
|
||||||
|
|
||||||
type
|
type
|
||||||
PeonVM* = ref object
|
PeonVM* = ref object
|
||||||
|
|
|
@ -188,7 +188,7 @@ type
|
||||||
# Stores the position of all jumps
|
# Stores the position of all jumps
|
||||||
jumps: seq[tuple[patched: bool, offset: int]]
|
jumps: seq[tuple[patched: bool, offset: int]]
|
||||||
# List of CFI start offsets into our CFI data
|
# List of CFI start offsets into our CFI data
|
||||||
cfiOffsets: seq[tuple[value, offset: int, fn: Name]]
|
cfiOffsets: seq[tuple[start, stop: int, fn: Name]]
|
||||||
CompileError* = ref object of PeonException
|
CompileError* = ref object of PeonException
|
||||||
compiler*: Compiler
|
compiler*: Compiler
|
||||||
node*: ASTNode
|
node*: ASTNode
|
||||||
|
@ -416,18 +416,20 @@ proc fixCFIOffsets(self: Compiler, oldLen: int, modifiedAt: int) =
|
||||||
let offset = self.chunk.code.len() - oldLen
|
let offset = self.chunk.code.len() - oldLen
|
||||||
var newCFI: array[3, uint8]
|
var newCFI: array[3, uint8]
|
||||||
var tmp: int
|
var tmp: int
|
||||||
for cfi in self.cfiOffsets:
|
for cfi in self.cfiOffsets.mitems():
|
||||||
if cfi.offset >= modifiedAt:
|
if cfi.start >= modifiedAt:
|
||||||
newCFI = (cfi.value + offset).toTriple()
|
newCFI = (cfi.start + offset).toTriple()
|
||||||
self.chunk.cfi[cfi.offset] = newCFI[0]
|
self.chunk.cfi[cfi.start] = newCFI[0]
|
||||||
self.chunk.cfi[cfi.offset + 1] = newCFI[1]
|
self.chunk.cfi[cfi.start + 1] = newCFI[1]
|
||||||
self.chunk.cfi[cfi.offset + 2] = newCFI[2]
|
self.chunk.cfi[cfi.start + 2] = newCFI[2]
|
||||||
tmp = [self.chunk.cfi[cfi.offset + 3], self.chunk.cfi[cfi.offset + 4], self.chunk.cfi[cfi.offset + 5]].fromTriple().int
|
tmp = [self.chunk.cfi[cfi.start + 3], self.chunk.cfi[cfi.start + 4], self.chunk.cfi[cfi.start + 5]].fromTriple().int
|
||||||
newCFI = (tmp + offset).toTriple()
|
newCFI = (tmp + offset).toTriple()
|
||||||
self.chunk.cfi[cfi.offset + 3] = newCFI[0]
|
self.chunk.cfi[cfi.start + 3] = newCFI[0]
|
||||||
self.chunk.cfi[cfi.offset + 4] = newCFI[1]
|
self.chunk.cfi[cfi.start + 4] = newCFI[1]
|
||||||
self.chunk.cfi[cfi.offset + 5] = newCFI[2]
|
self.chunk.cfi[cfi.start + 5] = newCFI[2]
|
||||||
cfi.fn.codePos += offset
|
cfi.fn.codePos += offset
|
||||||
|
cfi.start += offset
|
||||||
|
cfi.stop += offset
|
||||||
|
|
||||||
|
|
||||||
proc fixJumps(self: Compiler, oldLen: int, modifiedAt: int) =
|
proc fixJumps(self: Compiler, oldLen: int, modifiedAt: int) =
|
||||||
|
@ -444,8 +446,7 @@ proc fixJumps(self: Compiler, oldLen: int, modifiedAt: int) =
|
||||||
# list in cases where we shifted the jump
|
# list in cases where we shifted the jump
|
||||||
# instruction itself into the code!
|
# instruction itself into the code!
|
||||||
jump.offset += offset
|
jump.offset += offset
|
||||||
if jump.patched:
|
self.setJump(jump.offset, self.chunk.code[jump.offset + 1..jump.offset + 3])
|
||||||
self.setJump(jump.offset, self.chunk.code[jump.offset..<jump.offset + 3])
|
|
||||||
|
|
||||||
|
|
||||||
proc resolve(self: Compiler, name: IdentExpr,
|
proc resolve(self: Compiler, name: IdentExpr,
|
||||||
|
@ -1899,14 +1900,11 @@ proc typeDecl(self: Compiler, node: TypeDecl) =
|
||||||
|
|
||||||
proc funDecl(self: Compiler, node: FunDecl, fn: Name = nil, args: seq[Expression] = @[]) =
|
proc funDecl(self: Compiler, node: FunDecl, fn: Name = nil, args: seq[Expression] = @[]) =
|
||||||
## Compiles function declarations
|
## Compiles function declarations
|
||||||
# A function's code is just compiled linearly
|
|
||||||
# and then jumped over
|
|
||||||
if node.token.kind == Operator and node.token.lexeme in [".", ]:
|
if node.token.kind == Operator and node.token.lexeme in [".", ]:
|
||||||
self.error(&"The '{node.token.lexeme}' cannot be overridden", node)
|
self.error(&"The '{node.token.lexeme}' cannot be overridden", node)
|
||||||
var jmp: int
|
var jmp: int
|
||||||
self.declareName(node)
|
self.declareName(node)
|
||||||
self.dispatchPragmas(node)
|
self.dispatchPragmas(node)
|
||||||
# Function's code starts after the jump
|
|
||||||
var node = node
|
var node = node
|
||||||
var fn = if fn.isNil(): self.names[^(node.arguments.len() + 1)] else: fn
|
var fn = if fn.isNil(): self.names[^(node.arguments.len() + 1)] else: fn
|
||||||
# We store the current function
|
# We store the current function
|
||||||
|
@ -1915,7 +1913,6 @@ proc funDecl(self: Compiler, node: FunDecl, fn: Name = nil, args: seq[Expression
|
||||||
self.currentFunction.valueType.children.add(fn.valueType)
|
self.currentFunction.valueType.children.add(fn.valueType)
|
||||||
fn.valueType.parent = function.valueType
|
fn.valueType.parent = function.valueType
|
||||||
self.currentFunction = fn
|
self.currentFunction = fn
|
||||||
var names {.used.} = self.names[^(node.arguments.len())..^1]
|
|
||||||
if fn.valueType.isBuiltinFunction:
|
if fn.valueType.isBuiltinFunction:
|
||||||
fn.codePos = self.chunk.code.len()
|
fn.codePos = self.chunk.code.len()
|
||||||
# We take the arguments off of our name list
|
# We take the arguments off of our name list
|
||||||
|
@ -1927,11 +1924,13 @@ proc funDecl(self: Compiler, node: FunDecl, fn: Name = nil, args: seq[Expression
|
||||||
# can only be relatively simple
|
# can only be relatively simple
|
||||||
self.names = self.names[0..^node.arguments.len() + 1]
|
self.names = self.names[0..^node.arguments.len() + 1]
|
||||||
elif not node.body.isNil():
|
elif not node.body.isNil():
|
||||||
|
# A function's code is just compiled linearly
|
||||||
|
# and then jumped over
|
||||||
jmp = self.emitJump(JumpForwards, node.token.line)
|
jmp = self.emitJump(JumpForwards, node.token.line)
|
||||||
fn.codePos = self.chunk.code.len()
|
fn.codePos = self.chunk.code.len()
|
||||||
# We let our debugger know this function's boundaries
|
# We let our debugger know this function's boundaries
|
||||||
self.chunk.cfi.add(self.chunk.code.high().toTriple())
|
self.chunk.cfi.add(self.chunk.code.high().toTriple())
|
||||||
self.cfiOffsets.add((value: self.chunk.code.high(), offset: self.chunk.cfi.high() - 2, fn: fn))
|
self.cfiOffsets.add((start: self.chunk.code.high(), stop: 0, fn: fn))
|
||||||
let idx = self.chunk.cfi.len()
|
let idx = self.chunk.cfi.len()
|
||||||
self.chunk.cfi.add(0.toTriple()) # Patched it later
|
self.chunk.cfi.add(0.toTriple()) # Patched it later
|
||||||
self.chunk.cfi.add(uint8(node.arguments.len()))
|
self.chunk.cfi.add(uint8(node.arguments.len()))
|
||||||
|
@ -1985,6 +1984,7 @@ proc funDecl(self: Compiler, node: FunDecl, fn: Name = nil, args: seq[Expression
|
||||||
self.chunk.cfi[idx] = stop[0]
|
self.chunk.cfi[idx] = stop[0]
|
||||||
self.chunk.cfi[idx + 1] = stop[1]
|
self.chunk.cfi[idx + 1] = stop[1]
|
||||||
self.chunk.cfi[idx + 2] = stop[2]
|
self.chunk.cfi[idx + 2] = stop[2]
|
||||||
|
self.cfiOffsets[^1].stop = self.chunk.code.len()
|
||||||
# Currently defer is not functional, so we
|
# Currently defer is not functional, so we
|
||||||
# just pop the instructions
|
# just pop the instructions
|
||||||
for _ in deferStart..self.deferred.high():
|
for _ in deferStart..self.deferred.high():
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
import std;
|
import std;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn makeClosure(n: int): fn: fn: int {
|
fn makeClosure(n: int): fn: fn: int {
|
||||||
fn inner: fn: int {
|
fn inner: fn: int {
|
||||||
fn deep: int {
|
fn deep: int {
|
||||||
|
|
Loading…
Reference in New Issue