Fixed parsing code in funDecl for arguments, fixed funDecl in compiler

This commit is contained in:
Nocturn9x 2022-03-21 15:40:13 +01:00
parent 1da75aed5c
commit ba9c8b4e56
3 changed files with 51 additions and 39 deletions

View File

@ -233,7 +233,7 @@ proc patchJump(self: Compiler, offset: int) =
## offset and changes the bytecode instruction if possible
## (i.e. jump is in 16 bit range), but the converse is also
## true (i.e. it might change a regular jump into a long one)
let jump: int = self.chunk.code.len() - offset - 4
let jump: int = self.chunk.code.len() - offset
if jump > 16777215:
self.error("cannot jump more than 16777215 bytecode instructions")
if jump < uint16.high().int:
@ -473,6 +473,9 @@ proc binary(self: Compiler, node: BinaryExpr) =
self.error(&"invalid AST node of kind {node.kind} at binary(): {node} (This is an internal error and most likely a bug)")
proc identifier(self: Compiler, node: IdentExpr)
proc declareName(self: Compiler, node: ASTNode) =
## Compiles all name declarations (constants, static,
## and dynamic)
@ -491,11 +494,23 @@ proc declareName(self: Compiler, node: ASTNode) =
# slap myself 100 times with a sign saying "I'm dumb". Mark my words
self.error("cannot declare more than 16777215 static variables at a time")
self.names.add(Name(depth: self.scopeDepth, name: IdentExpr(node.name),
isPrivate: node.isPrivate,
isPrivate: node.isPrivate,
owner: node.owner,
isConst: node.isConst))
of funDecl:
var node = FunDecl(node)
# Declares the function's name in the
# current (outer) scope...
self.declareName(node.name)
# ... but its arguments in an inner one!
# (this ugly part is needed because
# self.blockStmt() already increments
# and decrements the scope depth)
for argument in node.arguments:
self.names.add(Name(depth: self.scopeDepth + 1, isPrivate: true, owner: "", isConst: false, name: IdentExpr(argument)))
# TODO: Default arguments and unpacking
else:
discard # TODO: Classes, functions
discard # TODO: Classes
proc varDecl(self: Compiler, node: VarDecl) =
@ -660,10 +675,10 @@ proc endScope(self: Compiler) =
# emit another batch of plain ol' Pop instructions for the rest
if popped <= uint16.high().int():
self.emitByte(PopN)
self.emitBytes(popped.toTriple())
self.emitBytes(popped.toDouble())
else:
self.emitByte(PopN)
self.emitBytes(uint16.high().int.toTriple())
self.emitBytes(uint16.high().int.toDouble())
for i in countdown(self.names.high(), popped - uint16.high().int()):
if self.names[i].depth > self.scopeDepth:
self.emitByte(Pop)
@ -928,22 +943,11 @@ proc funDecl(self: Compiler, node: FunDecl) =
# We store the current function
var function = self.currentFunction
self.currentFunction = node
# Declares the function's name in the
# outer scope...
self.declareName(node.name)
self.scopeDepth += 1
# ... but its arguments in an inner one!
# (this ugly part is needed because
# self.blockStmt() already increments
# and decrements the scope depth)
for argument in node.arguments:
self.declareName(IdentExpr(argument))
self.scopeDepth -= 1
# TODO: Default arguments
# A function's code is just compiled linearly
# and then jumped over
let jmp = self.emitJump(JumpForwards)
echo jmp
self.declareName(node)
# Since the deferred array is a linear
# sequence of instructions and we want
@ -969,21 +973,24 @@ proc funDecl(self: Compiler, node: FunDecl) =
# that's about it
# All functions implicitly return nil. This code
# will not execute if there's an explicit return
# and I cannot figure out an elegant and simple
# way to tell if a function already returns
# or not, so we just play it safe
# will not be executed by the VM in all but the simplest
# cases where there is an explicit return statement, but
# I cannot figure out an elegant and simple way to tell
# if a function already returned or not, so we play it safe
if not self.enableOptimizations:
self.emitBytes(OpCode.Nil, OpCode.Return)
if OpCode(self.chunk.code[^1]) != OpCode.Return:
self.emitBytes(OpCode.Nil, OpCode.Return)
else:
self.emitByte(ImplicitReturn)
if OpCode(self.chunk.code[^1]) != OpCode.Return:
self.emitByte(ImplicitReturn)
# Currently defer is not functional so we
# just pop the instructions
for i in countup(deferStart, self.deferred.len(), 1):
self.deferred.delete(i)
echo self.chunk.code.len() - jmp
self.patchJump(jmp)
# This makes us compile nested functions correctly
self.currentFunction = function

View File

@ -925,8 +925,10 @@ proc funDecl(self: Parser, isAsync: bool = false, isStatic: bool = true, isPriva
self.expect(LeftBrace)
if not isLambda:
FunDecl(self.currentFunction).body = self.blockStmt()
FunDecl(self.currentFunction).arguments = arguments
else:
LambdaExpr(self.currentFunction).body = self.blockStmt()
LambdaExpr(self.currentFunction).arguments = arguments
result = self.currentFunction
self.currentFunction = enclosingFunction

View File

@ -31,25 +31,26 @@ import jale/multiline
import config
import strformat
import strutils
import sequtils
import times
import nimSHA2
const debugLexer = false
const debugParser = false
const debugParser = true
const debugOptimizer = false
const debugCompiler = true
const debugSerializer = true
const debugSerializer = false
import strformat
import strutils
when debugSerializer:
import sequtils
import times
import nimSHA2
proc getLineEditor: LineEditor =
result = newLineEditor()
result.prompt = "=> "
result.populateDefaults() # setup default keybindings
let hist = result.plugHistory() # create history object
result.bindHistory(hist) # set default history keybindings
result.populateDefaults() # Setup default keybindings
let hist = result.plugHistory() # Create history object
result.bindHistory(hist) # Set default history keybindings
proc main =
@ -59,15 +60,17 @@ proc main =
var tree: seq[ASTNode]
var optimized: tuple[tree: seq[ASTNode], warnings: seq[Warning]]
var compiled: Chunk
var serialized: Serialized
var serializedRaw: seq[byte]
when debugSerializer:
var serialized: Serialized
var serializedRaw: seq[byte]
var keep = true
var lexer = initLexer()
var parser = initParser()
var optimizer = initOptimizer(foldConstants=false)
var compiler = initCompiler()
var serializer = initSerializer()
when debugSerializer:
var serializer = initSerializer()
let lineEditor = getLineEditor()
lineEditor.bindEvent(jeQuit):
keep = false