nondescript/src/ndspkg/compv2/node.nim

154 lines
4.2 KiB
Nim

import ../types/value
import strformat
import strutils
import sequtils
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(", ")
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 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})"