91 lines
2.8 KiB
Nim
91 lines
2.8 KiB
Nim
import sugar
|
|
|
|
import ../scanner
|
|
import ../chunk
|
|
|
|
type
|
|
Local* = ref object
|
|
name*: string # name of this local
|
|
index*: int # what is its index in the stack (0 is the stack bottom - nil in the main function)
|
|
depth*: int # depth of this local
|
|
# if depth is -1, the variable cannot be referenced yet
|
|
# its depth will be set once its first ever value is determined
|
|
scope*: Scope # the innermost scope of this local
|
|
captured*: bool
|
|
|
|
Upvalue* = ref object
|
|
index*: int
|
|
isLocal*: bool
|
|
|
|
Scope* = ref object
|
|
labels*: seq[string]
|
|
goalStackIndex*: int # the stack count it started with plus 1
|
|
jumps*: seq[int] # jumps to be patched that jump to the end
|
|
function*: bool # if true, it is a function
|
|
parentFunction*: Scope # if not a function, which scope is the innermost function it's in (if it's a function this points to itself)
|
|
# if parentFunction is nil, the scope is not inside a function
|
|
upvalues*: seq[Upvalue] # only needed for functions
|
|
|
|
Compiler* = ref object
|
|
#
|
|
# input
|
|
#
|
|
scanner*: Scanner
|
|
source*: string
|
|
#
|
|
# state
|
|
#
|
|
previous*: Token
|
|
current*: Token
|
|
canAssign*: bool
|
|
locals*: seq[Local]
|
|
scopes*: seq[Scope]
|
|
stackIndex*: int # how large the stack is
|
|
# when there's an error both are set
|
|
# panic mode can be turned off e.g. at block boundaries
|
|
panicMode*: bool
|
|
#
|
|
# output
|
|
#
|
|
chunk*: Chunk
|
|
hadError*: bool
|
|
|
|
Precedence* = enum
|
|
pcNone, pcExprTop, pcAmpersand, pcAssignment, pcNonAssignTop, pcOr, pcAnd, pcEquality, pcComparison,
|
|
pcTerm, pcFactor, pcUnary, pcCall, pcIndex, pcPrimary
|
|
# pcUnary applies to all prefix operators regardless of this enum's value
|
|
# changing pcUnary's position can change the priority of all unary ops
|
|
#
|
|
# Note: unary only rules should have precedence pcNone!!!
|
|
# pcExprTop, pcNonAssignTop are special placeholders!
|
|
|
|
ParseRule* = object
|
|
name*: string # debug purposes only
|
|
prefix*: (Compiler) -> void
|
|
infix*: (Compiler) -> void
|
|
prec*: Precedence # only relevant to infix, prefix always has pcUnary
|
|
|
|
|
|
proc newScope*(comp: Compiler, function: bool): Scope =
|
|
result.new()
|
|
#result.depth = comp.scopes.len + 1
|
|
result.function = function
|
|
result.goalStackIndex = comp.stackIndex + 1
|
|
if function:
|
|
result.parentFunction = result
|
|
elif comp.scopes.len() > 0 and comp.scopes[comp.scopes.high()].parentFunction != nil:
|
|
result.parentFunction = comp.scopes[comp.scopes.high()].parentFunction
|
|
|
|
comp.scopes.add(result)
|
|
|
|
# HELPERS FOR THE COMPILER TYPE
|
|
|
|
proc newCompiler*(name: string, source: string): Compiler =
|
|
result = new(Compiler)
|
|
result.chunk = initChunk(name)
|
|
result.source = source
|
|
result.hadError = false
|
|
result.panicMode = false
|
|
result.canAssign = true
|
|
result.locals = @[]
|
|
result.scopes = @[] |