158 lines
4.3 KiB
Nim
158 lines
4.3 KiB
Nim
|
|
import ../types/value
|
|
|
|
import strformat
|
|
import strutils
|
|
import sequtils
|
|
|
|
type
|
|
NodeKind* = enum
|
|
nkBlockExpr, nkExprStmt, nkProgram, nkBreak, nkExpr,
|
|
nkConst, nkList, nkTable, nkGetIndex, nkSetIndex, nkLen,
|
|
nkIf, nkWhile, nkOr, nkAnd, nkNegate, nkNot,
|
|
nkPlus, nkMinus, nkMult, nkDiv, nkEq, nkNeq, nkLess, nkGreater,
|
|
nkGe, nkLe,
|
|
nkCall, nkColonCall, nkVarDecl, nkProc,
|
|
nkVarGet, nkVarSet,
|
|
nkFalse, nkTrue, nkNil
|
|
|
|
Node* = ref object
|
|
line*: int
|
|
case kind*: NodeKind:
|
|
of nkBlockExpr:
|
|
children*: seq[Node]
|
|
labels*: seq[string]
|
|
of nkProgram:
|
|
pChildren*: seq[Node]
|
|
of nkExprStmt, nkExpr: # only when there is a ; does it compile to expr stmt; expr used for parentheses, &
|
|
expression*: Node
|
|
of nkBreak:
|
|
label*: string
|
|
of nkConst:
|
|
constant*: NdValue
|
|
of nkList:
|
|
elems*: seq[Node]
|
|
of nkTable:
|
|
keys*: seq[Node]
|
|
values*: seq[Node]
|
|
of nkGetIndex:
|
|
gCollection*: Node
|
|
gIndex*: Node
|
|
of nkSetIndex:
|
|
sCollection*: Node
|
|
sIndex*: Node
|
|
sValue*: Node
|
|
of nkLen, nkNegate, nkNot: # unary ops
|
|
argument*: Node
|
|
of nkIf:
|
|
ifCondition*: Node
|
|
ifBody*: Node
|
|
elseBody*: Node
|
|
of nkWhile:
|
|
whileCondition*: Node
|
|
whileBody*: Node
|
|
of nkAnd, nkOr, nkPlus, nkMinus, nkMult, nkDiv, nkEq, nkNeq, nkLess, nkGreater, nkGe, nkLe: # binary ops
|
|
left*: Node
|
|
right*: Node
|
|
of nkCall, nkColonCall:
|
|
function*: Node
|
|
arguments*: seq[Node]
|
|
of nkVarDecl:
|
|
name*: string
|
|
value*: Node # can be nil
|
|
of nkProc:
|
|
parameters*: seq[string]
|
|
procBody*: Node
|
|
of nkVarGet:
|
|
gVarName*: string
|
|
of nkVarSet:
|
|
sVarName*: string
|
|
newVal*: Node
|
|
of nkFalse, nkTrue, nkNil:
|
|
discard
|
|
|
|
proc `$`*(node: Node): string =
|
|
if node == nil:
|
|
return "<nil>"
|
|
case node.kind:
|
|
of nkAnd:
|
|
result = &"(and {node.left} {node.right})"
|
|
of nkBlockExpr:
|
|
let labels = node.labels.join(", ")
|
|
let elements = node.children.map(`$`).join(", ")
|
|
result = &"(block labels: {labels} elements: {elements})"
|
|
of nkBreak:
|
|
result = &"(break {node.label})"
|
|
of nkCall:
|
|
let args = node.arguments.map(`$`).join(", ")
|
|
result = &"(call {node.function}({args}))"
|
|
of nkColonCall:
|
|
let args = node.arguments.map(`$`).join(", ")
|
|
result = &"(:call {node.function} ({args}))"
|
|
of nkConst:
|
|
result = &"(const {node.constant})"
|
|
of nkDiv:
|
|
result = &"(/ {node.left} {node.right})"
|
|
of nkEq:
|
|
result = &"(== {node.left} {node.right})"
|
|
of nkExpr:
|
|
result = &"(grouping {node.expression})"
|
|
of nkExprStmt:
|
|
result = &"(exprStmt {node.expression})"
|
|
of nkFalse:
|
|
result = "(false)"
|
|
of nkGe:
|
|
result = &"(ge {node.left} {node.right})"
|
|
of nkGetIndex:
|
|
result = &"({node.gCollection}[{node.gIndex}])"
|
|
of nkGreater:
|
|
result = &"(greater {node.left} {node.right})"
|
|
of nkIf:
|
|
result = &"(if {node.ifCondition}: {node.ifBody} else: {node.elseBody})"
|
|
of nkLe:
|
|
result = &"(le {node.left} {node.right})"
|
|
of nkLen:
|
|
result = &"(# {node.argument})"
|
|
of nkLess:
|
|
result = &"(less {node.left} {node.right})"
|
|
of nkList:
|
|
let elems = node.elems.map(`$`).join(", ")
|
|
result = &"(list {elems})"
|
|
of nkMinus:
|
|
result = &"(- {node.left} {node.right})"
|
|
of nkMult:
|
|
result = &"(* {node.left} {node.right})"
|
|
of nkNegate:
|
|
result = &"(neg {node.argument})"
|
|
of nkNeq:
|
|
result = &"(!= {node.left} {node.right})"
|
|
of nkNil:
|
|
result = "(nil)"
|
|
of nkNot:
|
|
result = &"(! {node.argument})"
|
|
of nkOr:
|
|
result = &"(or {node.left} {node.right})"
|
|
of nkPlus:
|
|
result = &"(+ {node.left} {node.right})"
|
|
of nkProc:
|
|
let params = node.parameters.join(", ")
|
|
result = &"(proc params: {params} body: {node.procBody})"
|
|
of nkProgram:
|
|
result = node.pChildren.map(`$`).join(";\n")
|
|
of nkSetIndex:
|
|
result = &"({node.sCollection}[{node.sIndex}] = {node.sValue})"
|
|
of nkTable:
|
|
let keys = node.keys.map(`$`).join(", ")
|
|
let values = node.values.map(`$`).join(", ")
|
|
result = &"(table keys: {keys}, values: {values})"
|
|
of nkTrue:
|
|
result = "(true)"
|
|
of nkVarDecl:
|
|
result = &"(varDecl {node.name} = {node.value})"
|
|
of nkVarGet:
|
|
result = &"(varGet {node.gVarName})"
|
|
of nkVarSet:
|
|
result = &"(varSet {node.sVarName} = {node.newVal})"
|
|
of nkWhile:
|
|
result = &"(while {node.whileCondition}: {node.whileBody})"
|