Fixed parsing code in funDecl for arguments, fixed funDecl in compiler
This commit is contained in:
parent
1da75aed5c
commit
ba9c8b4e56
|
@ -233,7 +233,7 @@ proc patchJump(self: Compiler, offset: int) =
|
||||||
## offset and changes the bytecode instruction if possible
|
## offset and changes the bytecode instruction if possible
|
||||||
## (i.e. jump is in 16 bit range), but the converse is also
|
## (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)
|
## 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:
|
if jump > 16777215:
|
||||||
self.error("cannot jump more than 16777215 bytecode instructions")
|
self.error("cannot jump more than 16777215 bytecode instructions")
|
||||||
if jump < uint16.high().int:
|
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)")
|
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) =
|
proc declareName(self: Compiler, node: ASTNode) =
|
||||||
## Compiles all name declarations (constants, static,
|
## Compiles all name declarations (constants, static,
|
||||||
## and dynamic)
|
## 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
|
# 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.error("cannot declare more than 16777215 static variables at a time")
|
||||||
self.names.add(Name(depth: self.scopeDepth, name: IdentExpr(node.name),
|
self.names.add(Name(depth: self.scopeDepth, name: IdentExpr(node.name),
|
||||||
isPrivate: node.isPrivate,
|
isPrivate: node.isPrivate,
|
||||||
owner: node.owner,
|
owner: node.owner,
|
||||||
isConst: node.isConst))
|
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:
|
else:
|
||||||
discard # TODO: Classes, functions
|
discard # TODO: Classes
|
||||||
|
|
||||||
|
|
||||||
proc varDecl(self: Compiler, node: VarDecl) =
|
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
|
# emit another batch of plain ol' Pop instructions for the rest
|
||||||
if popped <= uint16.high().int():
|
if popped <= uint16.high().int():
|
||||||
self.emitByte(PopN)
|
self.emitByte(PopN)
|
||||||
self.emitBytes(popped.toTriple())
|
self.emitBytes(popped.toDouble())
|
||||||
else:
|
else:
|
||||||
self.emitByte(PopN)
|
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()):
|
for i in countdown(self.names.high(), popped - uint16.high().int()):
|
||||||
if self.names[i].depth > self.scopeDepth:
|
if self.names[i].depth > self.scopeDepth:
|
||||||
self.emitByte(Pop)
|
self.emitByte(Pop)
|
||||||
|
@ -928,22 +943,11 @@ proc funDecl(self: Compiler, node: FunDecl) =
|
||||||
# We store the current function
|
# We store the current function
|
||||||
var function = self.currentFunction
|
var function = self.currentFunction
|
||||||
self.currentFunction = node
|
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
|
# A function's code is just compiled linearly
|
||||||
# and then jumped over
|
# and then jumped over
|
||||||
let jmp = self.emitJump(JumpForwards)
|
let jmp = self.emitJump(JumpForwards)
|
||||||
|
echo jmp
|
||||||
|
self.declareName(node)
|
||||||
|
|
||||||
# Since the deferred array is a linear
|
# Since the deferred array is a linear
|
||||||
# sequence of instructions and we want
|
# sequence of instructions and we want
|
||||||
|
@ -969,21 +973,24 @@ proc funDecl(self: Compiler, node: FunDecl) =
|
||||||
# that's about it
|
# that's about it
|
||||||
|
|
||||||
# All functions implicitly return nil. This code
|
# All functions implicitly return nil. This code
|
||||||
# will not execute if there's an explicit return
|
# will not be executed by the VM in all but the simplest
|
||||||
# and I cannot figure out an elegant and simple
|
# cases where there is an explicit return statement, but
|
||||||
# way to tell if a function already returns
|
# I cannot figure out an elegant and simple way to tell
|
||||||
# or not, so we just play it safe
|
# if a function already returned or not, so we play it safe
|
||||||
|
|
||||||
if not self.enableOptimizations:
|
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:
|
else:
|
||||||
self.emitByte(ImplicitReturn)
|
if OpCode(self.chunk.code[^1]) != OpCode.Return:
|
||||||
|
self.emitByte(ImplicitReturn)
|
||||||
|
|
||||||
# Currently defer is not functional so we
|
# Currently defer is not functional so we
|
||||||
# just pop the instructions
|
# just pop the instructions
|
||||||
for i in countup(deferStart, self.deferred.len(), 1):
|
for i in countup(deferStart, self.deferred.len(), 1):
|
||||||
self.deferred.delete(i)
|
self.deferred.delete(i)
|
||||||
|
|
||||||
|
echo self.chunk.code.len() - jmp
|
||||||
self.patchJump(jmp)
|
self.patchJump(jmp)
|
||||||
# This makes us compile nested functions correctly
|
# This makes us compile nested functions correctly
|
||||||
self.currentFunction = function
|
self.currentFunction = function
|
||||||
|
|
|
@ -925,8 +925,10 @@ proc funDecl(self: Parser, isAsync: bool = false, isStatic: bool = true, isPriva
|
||||||
self.expect(LeftBrace)
|
self.expect(LeftBrace)
|
||||||
if not isLambda:
|
if not isLambda:
|
||||||
FunDecl(self.currentFunction).body = self.blockStmt()
|
FunDecl(self.currentFunction).body = self.blockStmt()
|
||||||
|
FunDecl(self.currentFunction).arguments = arguments
|
||||||
else:
|
else:
|
||||||
LambdaExpr(self.currentFunction).body = self.blockStmt()
|
LambdaExpr(self.currentFunction).body = self.blockStmt()
|
||||||
|
LambdaExpr(self.currentFunction).arguments = arguments
|
||||||
result = self.currentFunction
|
result = self.currentFunction
|
||||||
self.currentFunction = enclosingFunction
|
self.currentFunction = enclosingFunction
|
||||||
|
|
||||||
|
|
31
src/main.nim
31
src/main.nim
|
@ -31,25 +31,26 @@ import jale/multiline
|
||||||
import config
|
import config
|
||||||
|
|
||||||
|
|
||||||
import strformat
|
|
||||||
import strutils
|
|
||||||
import sequtils
|
|
||||||
import times
|
|
||||||
import nimSHA2
|
|
||||||
|
|
||||||
const debugLexer = false
|
const debugLexer = false
|
||||||
const debugParser = false
|
const debugParser = true
|
||||||
const debugOptimizer = false
|
const debugOptimizer = false
|
||||||
const debugCompiler = true
|
const debugCompiler = true
|
||||||
const debugSerializer = true
|
const debugSerializer = false
|
||||||
|
|
||||||
|
import strformat
|
||||||
|
import strutils
|
||||||
|
when debugSerializer:
|
||||||
|
import sequtils
|
||||||
|
import times
|
||||||
|
import nimSHA2
|
||||||
|
|
||||||
|
|
||||||
proc getLineEditor: LineEditor =
|
proc getLineEditor: LineEditor =
|
||||||
result = newLineEditor()
|
result = newLineEditor()
|
||||||
result.prompt = "=> "
|
result.prompt = "=> "
|
||||||
result.populateDefaults() # setup default keybindings
|
result.populateDefaults() # Setup default keybindings
|
||||||
let hist = result.plugHistory() # create history object
|
let hist = result.plugHistory() # Create history object
|
||||||
result.bindHistory(hist) # set default history keybindings
|
result.bindHistory(hist) # Set default history keybindings
|
||||||
|
|
||||||
|
|
||||||
proc main =
|
proc main =
|
||||||
|
@ -59,15 +60,17 @@ proc main =
|
||||||
var tree: seq[ASTNode]
|
var tree: seq[ASTNode]
|
||||||
var optimized: tuple[tree: seq[ASTNode], warnings: seq[Warning]]
|
var optimized: tuple[tree: seq[ASTNode], warnings: seq[Warning]]
|
||||||
var compiled: Chunk
|
var compiled: Chunk
|
||||||
var serialized: Serialized
|
when debugSerializer:
|
||||||
var serializedRaw: seq[byte]
|
var serialized: Serialized
|
||||||
|
var serializedRaw: seq[byte]
|
||||||
var keep = true
|
var keep = true
|
||||||
|
|
||||||
var lexer = initLexer()
|
var lexer = initLexer()
|
||||||
var parser = initParser()
|
var parser = initParser()
|
||||||
var optimizer = initOptimizer(foldConstants=false)
|
var optimizer = initOptimizer(foldConstants=false)
|
||||||
var compiler = initCompiler()
|
var compiler = initCompiler()
|
||||||
var serializer = initSerializer()
|
when debugSerializer:
|
||||||
|
var serializer = initSerializer()
|
||||||
let lineEditor = getLineEditor()
|
let lineEditor = getLineEditor()
|
||||||
lineEditor.bindEvent(jeQuit):
|
lineEditor.bindEvent(jeQuit):
|
||||||
keep = false
|
keep = false
|
||||||
|
|
Loading…
Reference in New Issue