nondescript/src/ndspkg/compv2/node.nim

164 lines
4.3 KiB
Nim

import ../types/value
import strformat
import strutils
type
NodeKind* = enum
nkBlockExpr, nkExprStmt, 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 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(", ")
result = &"(block labels: {labels} elements: "
for ch in node.children:
result &= $ch & ", "
result[^1] = ')'
of nkBreak:
result = &"(break {node.label})"
of nkCall:
result = &"(call {node.function} "
for ch in node.arguments:
result &= $ch & ", "
result[^1] = ')'
of nkColonCall:
result = &"(:call {node.function} "
for ch in node.arguments:
result &= $ch & ", "
result[^1] = ')'
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:
result = &"(list "
for ch in node.elems:
result &= &"{ch}, "
result[^1] = ')'
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 nkSetIndex:
result = &"({node.sCollection}[{node.sIndex}] = {node.sValue})"
of nkTable:
var keys = ""
var values = ""
for i in 0..node.keys.high:
keys &= &"{node.keys[i]}, "
values &= &"{node.values[i]}, "
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})"