Fixed a bug where regular functions were mistaken for closures
This commit is contained in:
parent
ca5a1c1bc9
commit
3e6e9da475
|
@ -31,7 +31,7 @@ when debugVM or debugMem or debugGC:
|
|||
import std/terminal
|
||||
|
||||
|
||||
{.push checks:not disableVMChecks.} # The VM is a critical point where checks are deleterious
|
||||
{.push checks:enableVMChecks.} # The VM is a critical point where checks are deleterious
|
||||
|
||||
type
|
||||
PeonVM* = ref object
|
||||
|
@ -339,10 +339,10 @@ proc newPeonVM*: PeonVM =
|
|||
result.initCache()
|
||||
result.gc = newPeonGC()
|
||||
result.frames = @[]
|
||||
result.calls = @[]
|
||||
result.operands = @[]
|
||||
result.results = @[]
|
||||
result.envs = @[]
|
||||
result.calls = @[]
|
||||
result.gc.vm = result
|
||||
|
||||
|
||||
|
@ -625,7 +625,7 @@ when debugVM: # So nim shuts up
|
|||
stdout.styledWrite(fgGreen, "Call Stack: ", fgMagenta, "[")
|
||||
for i, e in self.calls:
|
||||
stdout.styledWrite(fgYellow, $e)
|
||||
if i < self.calls.high():
|
||||
if i < self.calls.len():
|
||||
stdout.styledWrite(fgYellow, ", ")
|
||||
styledEcho fgMagenta, "]"
|
||||
if self.operands.len() !> 0:
|
||||
|
@ -709,8 +709,6 @@ proc dispatch*(self: PeonVM) =
|
|||
of LoadUInt8:
|
||||
self.push(uint64(self.constReadUInt8(int(self.readLong()))))
|
||||
of LoadString:
|
||||
# TODO: Use constReadString with own memory manager
|
||||
# Strings are broken rn!!
|
||||
self.push(cast[uint64](self.constReadString(int(self.readLong()), int(self.readLong()))))
|
||||
# We cast instead of converting because, unlike with integers,
|
||||
# we don't want nim to touch any of the bits of the underlying
|
||||
|
|
|
@ -27,7 +27,7 @@ const debugStressGC* {.booldefine.} = false # Make the GC run a collection at
|
|||
const PeonBytecodeMarker* = "PEON_BYTECODE" # Magic value at the beginning of bytecode files
|
||||
const HeapGrowFactor* = 2 # The growth factor used by the GC to schedule the next collection
|
||||
const FirstGC* = 1024 * 1024; # How many bytes to allocate before running the first GC
|
||||
const disableVMChecks* {.booldefine.} = true; # Disables all types of compiler (nim-wise) checks in the VM
|
||||
const enableVMChecks* {.booldefine.} = true; # Enables all types of compiler (nim-wise) checks in the VM
|
||||
when HeapGrowFactor <= 1:
|
||||
{.fatal: "Heap growth factor must be > 1".}
|
||||
const PeonVersion* = (major: 0, minor: 1, patch: 0)
|
||||
|
@ -35,7 +35,7 @@ const PeonRelease* = "alpha"
|
|||
const PeonCommitHash* = "9884975fbd0bd2880f0969d21ee7b6ae44ecbafa"
|
||||
when len(PeonCommitHash) != 40:
|
||||
{.fatal: "The git commit hash must be exactly 40 characters long".}
|
||||
const PeonBranch* = "master"
|
||||
const PeonBranch* = "fixed-size-stack"
|
||||
when len(PeonBranch) > 255 or len(PeonBranch) == 0:
|
||||
{.fatal: "The git branch name's length must be within 1 and 255 characters".}
|
||||
const PeonVersionString* = &"Peon {PeonVersion.major}.{PeonVersion.minor}.{PeonVersion.patch} {PeonRelease} ({PeonBranch}, {CompileDate}, {CompileTime}, {PeonCommitHash[0..8]}) [Nim {NimVersion}] on {hostOS} ({hostCPU})"
|
||||
|
|
|
@ -146,6 +146,8 @@ type
|
|||
# The current scope depth. If > 0, we're
|
||||
# in a local scope, otherwise it's global
|
||||
scopeDepth: int
|
||||
# Scope ownership data
|
||||
scopeOwners: seq[tuple[owner: Name, depth: int]]
|
||||
# The current function being compiled
|
||||
currentFunction: Name
|
||||
# Are optimizations turned on?
|
||||
|
@ -237,6 +239,8 @@ proc newCompiler*(enableOptimizations: bool = true, replMode: bool = false): Com
|
|||
result.compilerProcs["magic"] = handleMagicPragma
|
||||
result.compilerProcs["pure"] = handlePurePragma
|
||||
result.source = ""
|
||||
result.scopeOwners = @[]
|
||||
|
||||
|
||||
## Public getters for nicer error formatting
|
||||
proc getCurrentNode*(self: Compiler): ASTNode = (if self.current >=
|
||||
|
@ -1031,6 +1035,7 @@ proc beginScope(self: Compiler) =
|
|||
## Begins a new local scope by incrementing the current
|
||||
## scope's depth
|
||||
inc(self.scopeDepth)
|
||||
self.scopeOwners.add((self.currentFunction, self.scopeDepth))
|
||||
|
||||
|
||||
proc `$`(self: Type): string = $self[]
|
||||
|
@ -1053,6 +1058,7 @@ proc endScope(self: Compiler) =
|
|||
if self.scopeDepth < 0:
|
||||
self.error("cannot call endScope with scopeDepth < 0 (This is an internal error and most likely a bug)")
|
||||
dec(self.scopeDepth)
|
||||
discard self.scopeOwners.pop()
|
||||
var names: seq[Name] = @[]
|
||||
var popCount = 0
|
||||
for name in self.names:
|
||||
|
@ -1346,6 +1352,7 @@ proc beginProgram(self: Compiler, incremental: bool = false): int =
|
|||
isFunDecl: true,
|
||||
line: -1)
|
||||
self.names.add(main)
|
||||
self.scopeOwners.add((main, 0))
|
||||
self.emitByte(LoadInt64, 1)
|
||||
self.emitBytes(self.chunk.writeConstant(main.codePos.toLong()), 1)
|
||||
self.emitByte(LoadUInt32, 1)
|
||||
|
@ -1485,7 +1492,7 @@ proc identifier(self: Compiler, node: IdentExpr) =
|
|||
# a location to jump to
|
||||
self.emitByte(LoadInt64, node.token.line)
|
||||
self.emitBytes(self.chunk.writeConstant(s.codePos.toLong()), node.token.line)
|
||||
elif self.scopeDepth > 0 and not self.currentFunction.isNil() and s.depth != self.scopeDepth:
|
||||
elif self.scopeDepth > 0 and not self.currentFunction.isNil() and s.depth != self.scopeDepth and self.scopeOwners[s.depth].owner != self.currentFunction:
|
||||
# Loads a closure variable. Stored in a separate "closure array" in the VM that does not
|
||||
# align its semantics with the call stack. This makes closures work as expected and is
|
||||
# not much slower than indexing our stack (since they're both dynamic arrays at runtime anyway)
|
||||
|
|
Loading…
Reference in New Issue