# Dependencies
requires "nim >= 0.19.0"
+requires "docopt >= 0.6.8"
requires "opengl >= 1.2.0"
requires "glfw"
--- /dev/null
+
+#FLOOD_WITH_RANDOM {
+ $m6 = -1 + 256 * 256 * 256
+ $m7 = !GET_WIDTH()
+ $m8 = !GET_HEIGHT()
+
+ $y = 0
+ while $y < $m8 {
+ $x = 0
+ while $x < $m7 {
+ !SET_COL(!RANDOM($m6))
+ $x = $x + 1
+ }
+ $y = $y + 1
+ }
+}
+
+//change 1, 2, 3 4, 7, 8
+#TAKE_AVERAGE {
+ //Red, Green and Blue Sum
+ $m1 = 0
+ $m2 = 0
+ $m3 = 0
+ //Count
+ $m4 = 0
+
+ $m7 = $x + 1
+ $m8 = $y + 1
+
+ $y = $y - 1
+ while $y <= $m8 {
+ $x = $m7 - 2
+ while $x <= $m7 {
+ if !IN_BOUNDS($x, $y) {
+ $m1 = $m1 + !GET_R()
+ $m2 = $m2 + !GET_G()
+ $m3 = $m3 + !GET_B()
+
+ $m4 = $m4 + 1
+ }
+
+ $x = $x + 1
+ }
+ $y = $y + 1
+ }
+ $x = $x - 2
+ $y = $y - 2
+
+ if $m4 > 0 {
+ $m1 = $m1 / $m4
+ $m2 = $m2 / $m4
+ $m3 = $m3 / $m4
+ $m1 = $m1 * 256 * 256
+ $m2 = $m2 * 256
+ !SET_COL($m1 + $m2 + $m3)
+ }
+}
+
+!FLOOD_WITH_RANDOM()
+
+!SAY(!GET_WIDTH())
+!SAY(!GET_HEIGHT())
+
+$m5 = 30
+while 1 {
+ !RENDER()
+ $m5 = $m5 - 1
+ if $m5 <= 0 {
+ $m5 = 30
+
+ $y = 0
+ while $y < !GET_HEIGHT() {
+ $x = 0
+ while $x < !GET_WIDTH() {
+ !TAKE_AVERAGE()
+ $x = $x + 1
+ }
+ $y = $y + 1
+ }
+ }
+}
+++ /dev/null
-$mem_2 = 0
-$mem_3 = 10000
-
-while 1 {
- $pos_x = 0
- $pos_y = 0
- while $pos_y < 256 {
- $mem_1 = 20 * $pos_x + $mem_2 / 4
- $mem_1 = $mem_1 + $pos_y * $pos_x * 5
- !set_col($mem_1)
- !step_linear(1)
- }
- $mem_2 = $mem_2 + 1
- !render()
-
- $mem_3 = $mem_3 - 1
- if $mem_3 <= 0 {
- !halt()
- }
-}
-
-$pos_x = 0
-$pos_y = 10
-$mem_8 = 1
+$x = 0
+$y = 10
+$m8 = 1
#move_diag {
- $pos_x = $pos_x + $mem_8
- $pos_y = $pos_y + $mem_8
+ $x = $x + $m8
+ $y = $y + $m8
}
#swap_xy {
- $mem_1 = $pos_x
- $pos_x = $pos_y
- $pos_y = $mem_1
+ $m1 = $x
+ $x = $y
+ $y = $m1
}
-$mem_3 = 100
-while $pos_x <= 255 {
- $mem_3 = $mem_3 + 4
- if $mem_3 >= 256 {
- $mem_3 = $mem_3 - 156
+$m3 = 100
+while $x <= !GET_WIDTH() {
+ $m3 = $m3 + 4
+ if $m3 >= 256 {
+ $m3 = $m3 - 156
}
- !set_col($pos_x, $pos_y, $mem_3)
+ !set_col($m3)
!move_diag()
!swap_xy()
!render()
}
-$pos_x = 240
-$pos_y = 255
-$mem_8 = 0 - 1
+$x = !GET_WIDTH() - 15
+$y = !GET_HEIGHT() - 1
+$m8 = 0 - 1
-while $pos_x >= 0 {
- !set_col($pos_x, $pos_y, 255)
+while $x >= 0 {
+ !set_col(255)
!move_diag()
!render()
}
-!say($pos_x)
-$mem_2 = if $pos_x < 0 {
+!say($x)
+$m2 = if $x < 0 {
1000
}
-!say($mem_2)
+!say($m2)
--- /dev/null
+//Assumes 128 by 128 board
+#BOARD_WIDTH { 128 }
+#BOARD_HEIGHT { 128 }
+
+#CELL_ALIVE { 255 }
+#CELL_DEAD { 0 }
+
+// Set up initial board
+$y = 0
+while $y < !BOARD_HEIGHT() {
+ $x = 0
+ while $x < !BOARD_WIDTH() {
+ if !random(100) >= 50 {
+ !set_r(!CELL_ALIVE())
+ } else {
+ !set_r(!CELL_DEAD())
+ }
+ $x = $x + 1
+ }
+ $y = $y + 1
+}
+
+#UPDATE_CURRENT {
+ //Neighbor count
+ $m1 = 0
+
+ $x = $x - 1
+ $y = $y - 1
+
+ $m1 = $m1 + !get_a() == !CELL_ALIVE()
+ $x = $x + 1
+ $m1 = $m1 + !get_a() == !CELL_ALIVE()
+ $x = $x + 1
+ $m1 = $m1 + !get_a() == !CELL_ALIVE()
+ $x = $x - 2
+ $y = $y + 1
+ $m1 = $m1 + !get_a() == !CELL_ALIVE()
+ $x = $x + 2
+ $m1 = $m1 + !get_a() == !CELL_ALIVE()
+ $x = $x - 2
+ $y = $y + 1
+ $m1 = $m1 + !get_a() == !CELL_ALIVE()
+ $x = $x + 1
+ $m1 = $m1 + !get_a() == !CELL_ALIVE()
+ $x = $x + 1
+ $m1 = $m1 + !get_a() == !CELL_ALIVE()
+
+ $x = $x - 1
+ $y = $y - 1
+
+ $m2 = !get_a() == !CELL_ALIVE()
+ if $m2 {
+ $m3 = $m1 < 2
+ $m3 = $m3 + $m1 > 3
+ if $m3 {
+ !set_r(!CELL_DEAD())
+ }
+ } else {
+ if $m1 == 3 {
+ !set_r(!CELL_ALIVE())
+ }
+ }
+}
+
+#COPY_BOARD {
+ $y = 0
+ while $y < !BOARD_HEIGHT() {
+ $x = 0
+ while $x < !BOARD_WIDTH() {
+ !set_a(!get_r())
+
+ $x = $x + 1
+ }
+ $y = $y + 1
+ }
+}
+
+//Big render / update loop
+$m7 = 30
+while 1 {
+ //Draw the board
+ !render()
+
+ $m7 = $m7 - 1
+ if $m7 <= 0 {
+ $m7 = 30
+
+ $y = 0
+ while $y < !BOARD_HEIGHT() {
+ $x = 0
+ while $x < !BOARD_WIDTH() {
+ !COPY_BOARD()
+ $x = $x + 1
+ }
+ $y = $y + 1
+ }
+
+ $y = 0
+ while $y < !BOARD_HEIGHT() {
+ $x = 0
+ while $x < !BOARD_WIDTH() {
+ !UPDATE_CURRENT()
+ $x = $x + 1
+ }
+ $y = $y + 1
+ }
+ }
+}
\ No newline at end of file
+++ /dev/null
-$mem_1 = 0
-$mem_2 = 1
-
-//Dummy function that doesn't do much
-#test {
- !say($mem_1 + $mem_2)
-}
-
-while $mem_2 < 100000 {
- $mem_3 = $mem_1 + $mem_2
- $mem_1 = $mem_2
- $mem_2 = $mem_3
- !say($mem_3, $mem_2, $mem_2 == $mem_3)
-}
-
-if !in_bounds($pos_x + 1, $pos_y) {
- !test()
-}
-
-!redraw()
\ No newline at end of file
type
LightBoard* = ref object
- width: int
- height: int
+ width*: int
+ height*: int
data: ref array[1024 * 1024, GLuint]
colors: ref array[1024 * 1024 * 4, GLfloat]
import os
+import times
import tables
+import random
+import parseutils
+
+import docopt
import opengl
import glfw3 as glfw
import gfx/window as gfx_window
import gfx/glutils as glutils
import lang/types/types
+import lang/types/ast
import lang/program
import lang/executer
if key == glfw.KEY_ESCAPE and action == glfw.PRESS:
glfw.SetWindowShouldClose(window, glfw.TRUE)
-proc main() =
- let window = gfxWindow.NewWindow(1200, 700, "ASDF")
- window.SetKeyCallback(key_down)
+proc CreateFuncs(window: gfx_window.Window, board: LightBoard): ExecFuncs =
+ newTable({
+ "say": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ echo $args
+ ),
- let program = LoadProgram("./data/progs/fibcol.lgt")
+ "get_width": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ board.width.int32
+ ),
- const board_width: int = 128
- const board_height: int = 128
- let board = CreateBoard(board_width, board_height)
- board.InitRendering()
+ "get_height": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ board.height.int32
+ ),
- var funcs = newTable({
- "say": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
- echo $args
+ "in_bounds": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ if args[0] < 0 or args[1] < 0 or args[0] >= board.width or args[1] >= board.height:
+ 0
+ else:
+ 1
),
+
"set_col": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
board.SetCol(ec.worker.pos_x.int, ec.worker.pos_y.int, args[0].GLuint)
),
+
+ "set_a": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ board.SetA(ec.worker.pos_x.int, ec.worker.pos_y.int, args[0].GLuint)
+ ),
+
+ "set_r": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ board.SetR(ec.worker.pos_x.int, ec.worker.pos_y.int, args[0].GLuint)
+ ),
+
+ "set_g": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ board.SetG(ec.worker.pos_x.int, ec.worker.pos_y.int, args[0].GLuint)
+ ),
+
+ "set_b": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ board.SetB(ec.worker.pos_x.int, ec.worker.pos_y.int, args[0].GLuint)
+ ),
+
+ "get_col": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ board.GetCol(ec.worker.pos_x.int, ec.worker.pos_y.int).int32
+ ),
+
+ "get_a": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ board.GetA(ec.worker.pos_x.int, ec.worker.pos_y.int).int32
+ ),
+
+ "get_r": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ board.GetR(ec.worker.pos_x.int, ec.worker.pos_y.int).int32
+ ),
+
+ "get_g": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ board.GetG(ec.worker.pos_x.int, ec.worker.pos_y.int).int32
+ ),
+
+ "get_b": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ board.GetB(ec.worker.pos_x.int, ec.worker.pos_y.int).int32
+ ),
+
+ "random": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ random.rand(args[0].int).int32
+ ),
+
"step_linear": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
ec.worker.pos_x += args[0]
- while ec.worker.pos_x >= board_width:
- ec.worker.pos_x -= board_width.LightInt
+ while ec.worker.pos_x >= board.width:
+ ec.worker.pos_x -= board.width.LightInt
ec.worker.pos_y += 1
while ec.worker.pos_x < 0:
- ec.worker.pos_x += board_width.LightInt
+ ec.worker.pos_x += board.width.LightInt
ec.worker.pos_y -= 1
),
+
+ "step_to_linear": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
+ ec.worker.pos_x = args[0] mod (board.width.int32)
+ ec.worker.pos_y = args[0] div (board.width.int32)
+ ),
+
"halt": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
ec.StopExecution()
),
+
"render": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
glClearColor(0, 0, 0, 1)
glClear(GL_COLOR_BUFFER_BIT)
)
})
- let ec = MakeExecutionContext(funcs)
+let docs = """
+Light Interpreter.
+
+Usage:
+ light run <file> [--width=<int>] [--height=<int>] [--win_width=<int>] [--win_height=<int>]
+ light ast <file>
+ light (-h | --help)
+ light --version
+
+Options:
+ -h --help Show this screen.
+ --width=<int> Width of board [default: 64].
+ --height=<int> Height of board [default: 64].
+ --win_width=<int> Width of window [default: 1200].
+ --win_height=<int> Height of window [default: 700].
+"""
+
+type
+ RunOptions = object
+ filename: string
+ board_width: int
+ board_height: int
+ window_width: int
+ window_height: int
+
+proc RunProgram(options: RunOptions) =
+ let window = gfx_window.NewWindow(options.window_width.cint, options.window_height.cint, "Light Visualizer")
+ window.SetKeyCallback(key_down)
+
+ var program = LoadProgram(options.filename)
+
+ let board = CreateBoard(options.board_width, options.board_height)
+ board.InitRendering()
+
+ let ec = MakeExecutionContext(CreateFuncs(window, board))
discard ExecuteProgram(ec, program)
while not window.ShouldClose():
glClearColor(0, 0, 0, 1)
glClear(GL_COLOR_BUFFER_BIT)
- board.RebufferColors()
board.Render()
os.sleep(1)
window.CloseWindow()
+proc PrintAst(filename: string) =
+ let program = LoadProgram(filename)
+
+ echo "\n" & filename & "'s Abstract Syntax Tree"
+ for line in program.code:
+ echo line
+ echo "\n"
+
+proc main() =
+ random.randomize(getTime().toUnix())
+ let args = docopt(docs, version = "Light programming language v0.1.0")
+
+ if args["run"]:
+ var
+ board_width: int
+ board_height: int
+ window_width: int
+ window_height: int
+ discard parseInt($args["--width"], board_width)
+ discard parseInt($args["--height"], board_height)
+ discard parseInt($args["--win_width"], window_width)
+ discard parseInt($args["--win_height"], window_height)
+ let options = RunOptions(
+ filename: $args["<file>"],
+ board_width: board_width,
+ board_height: board_height,
+ window_width: window_width,
+ window_height: window_height,
+ )
+ RunProgram(options)
+
+ if args["ast"]:
+ PrintAst($args["<file>"])
+
when isMainModule:
main()
var_5*, var_6*, var_7*, var_8*: LightInt
pos_x*, pos_y*: LightInt
- ExecFuncs = TableRef[string, proc(ec: ExecutionContext, args: openarray[LightInt]): LightInt]
+ ExecFuncs* = TableRef[string, proc(ec: ExecutionContext, args: openarray[LightInt]): LightInt]
ExecutionContext* = ref object
worker*: LightWorker
if cond != 0:
ExecuteLines(ec, exp.body)
else:
- 0
+ ExecuteLines(ec, exp.else_body)
of leWhile:
while ec.running:
ExecuteLines(ec, ec.defined_functions[exp.func_name])
else:
- raise newException(ValueError, "Cannot call undefined function")
+ raise newException(ValueError, "Cannot call undefined function: " & exp.func_name)
of leFuncDef:
if ec.defined_functions.hasKey(exp.def_func_name):
- raise newException(ValueError, "Cannot redefine function")
+ raise newException(ValueError, "Cannot redefine function: " & exp.def_func_name)
else:
ec.defined_functions[exp.def_func_name] = exp.func_body
- 1
+ 0
else:
0
if not ec.running:
return 0
- var last: LightInt
+ var last: LightInt = 0
for line in lines:
last = EvalExpr(ec, line)
if not ec.running: break
if line.strip.startsWith("//"):
continue
- for token, is_sep in strutils.tokenize(line, {' ', ';', '\t', ',', '(', ')'}):
+ for token, is_sep in strutils.tokenize(line, {' ', ';', '\t', ',', '(', ')', '{', '}'}):
if is_sep:
- if token.contains({','}):
- yield LightToken(kind: ltParamDelim)
- if token.contains({'('}):
- yield LightToken(kind: ltParamStart)
- if token.contains({')'}):
- yield LightToken(kind: ltParamEnd)
- if token.contains({';'}):
- yield LightToken(kind: ltExprDelim)
+ for ch in token.items:
+ if ch == ',':
+ yield LightToken(kind: ltParamDelim)
+ if ch == '{':
+ yield LightToken(kind: ltBlockStart)
+ if ch == '}':
+ yield LightToken(kind: ltBlockEnd)
+ if ch == '(':
+ yield LightToken(kind: ltParamStart)
+ if ch == ')':
+ yield LightToken(kind: ltParamEnd)
+ if ch == ';':
+ yield LightToken(kind: ltExprDelim)
continue
if token.startsWith('$'):
if varString == "":
raise newException(IOError, "Expected variable name")
else:
- if varString == "mem_1": varName = var1
- elif varString == "mem_2": varName = var2
- elif varString == "mem_3": varName = var3
- elif varString == "mem_4": varName = var4
- elif varString == "mem_5": varName = var5
- elif varString == "mem_6": varName = var6
- elif varString == "mem_7": varName = var7
- elif varString == "mem_8": varName = var8
- elif varString == "pos_x": varName = varX
- elif varString == "pos_y": varName = varY
+ if varString == "m1": varName = var1
+ elif varString == "m2": varName = var2
+ elif varString == "m3": varName = var3
+ elif varString == "m4": varName = var4
+ elif varString == "m5": varName = var5
+ elif varString == "m6": varName = var6
+ elif varString == "m7": varName = var7
+ elif varString == "m8": varName = var8
+ elif varString == "x": varName = varX
+ elif varString == "y": varName = varY
else:
raise newException(IOError, "Invalid variable name.")
elif token == "=":
yield LightToken(kind: ltEq)
+ elif token.startsWith("-") and token != "-":
+ var value: int
+ discard parseutils.parseInt(token, value)
+
+ yield LightToken(kind: ltNum, value: value.LightInt)
+
elif token.isDigit:
var value: int
discard parseutils.parseInt(token, value)
elif token.toLowerAscii == "if":
yield LightToken(kind: ltIf)
+ elif token.toLowerAscii == "else":
+ yield LightToken(kind: ltElse)
elif token.toLowerAscii == "while":
yield LightToken(kind: ltWhile)
elif token.toLowerAscii == "break":
yield LightToken(kind: ltBreak)
- elif token.toLowerAscii == "then" or token.toLowerAscii == "do" or token == "{":
+ elif token.toLowerAscii == "then" or token.toLowerAscii == "do":
yield LightToken(kind: ltBlockStart)
- elif token.toLowerAscii == "end" or token == "}":
+ elif token.toLowerAscii == "end":
yield LightToken(kind: ltBlockEnd)
- elif token.toLowerAscii == "goto":
- yield LightToken(kind: ltGoto)
- elif token.startsWith(':'):
- let labelName = token[1 .. ^1]
- yield LightToken(kind: ltLabel, label_name: labelName)
-
else:
case token:
of "+":
parser.tokens.Step()
- if curr.kind in {ltNum, ltVar} and prev.kind == leNull:
+ if curr.kind in {ltNum, ltVar, ltFunc} and prev.kind == leNull:
let prevExpr =
case curr.kind:
of ltNum: LightExpr(kind: leNumLit, value: curr.value)
of ltVar: LightExpr(kind: leVar, var_name: curr.var_name)
+ of ltFunc:
+ if parser.tokens.Current.kind != ltParamStart:
+ raise newException(ValueError, "Expected parameter list after function call")
+
+ parser.tokens.Step()
+ let params = Parse_block(parser.tokens, ltParamDelim, ltParamEnd)
+
+ LightExpr(
+ kind: leFuncCall,
+ func_name: curr.func_name,
+ params: params
+ )
else: LightExpr(kind: leNull)
return parser.NextExpr(prevExpr, stop_at)
expression: next
)
- elif curr.kind == ltLabel:
- return LightExpr(
- kind: leLabel,
- label: curr.label_name
- )
-
- elif curr.kind == ltGoto:
- let next = parser.tokens.Current
- if next.kind != ltLabel:
- raise newException(ValueError, "Expected label after goto")
-
- else:
- return LightExpr(
- kind: leGoto,
- label: next.label_name
- )
-
elif curr.kind == ltIf:
let condition = parser.NextExpr(LightExpr(kind: leNull), {ltBlockStart})
parser.tokens.Step()
let body = Parse_block(parser.tokens, ltExprDelim, ltBlockEnd)
+ let else_body =
+ if parser.tokens.Current.kind == ltElse:
+ parser.tokens.Step()
+ parser.tokens.Step()
+ Parse_block(parser.tokens, ltExprDelim, ltBlockEnd)
+ else:
+ @[]
+
+
return LightExpr(
kind: leIf,
condition: condition,
- body: body
+ body: body,
+ else_body: else_body
)
elif curr.kind == ltWhile:
return LightExpr(
kind: leBreak
)
-
- elif curr.kind == ltFunc:
- if parser.tokens.Current.kind != ltParamStart:
- raise newException(ValueError, "Expected parameter list after function call")
-
- parser.tokens.Step()
- let params = Parse_block(parser.tokens, ltParamDelim, ltParamEnd)
-
- return LightExpr(
- kind: leFuncCall,
- func_name: curr.func_name,
- params: params
- )
elif curr.kind == ltFuncDef:
if parser.tokens.Current.kind != ltBlockStart:
import sequtils
import tables
import ./types/ast
+import ./types/tokens
import ./lexer
import ./parser
+import sequtils
+import strutils
import ./types
import ./tokens
leNumLit = 2,
leOp = 3,
leAssign = 4,
- leLabel = 5,
- leGoto = 6,
- leIf = 7,
- leWhile = 8,
- leBreak = 9,
- leFuncCall = 10,
- leFuncDef = 11,
+ leIf = 5,
+ leWhile = 6,
+ leBreak = 7,
+ leFuncCall = 8,
+ leFuncDef = 9,
LightExpr* = ref object
case kind*: LightExprType
of leAssign:
variable*: LightVariable
expression*: LightExpr
- of leLabel, leGoto:
- label*: string
of leIf, leWhile:
condition*: LightExpr
body*: seq[LightExpr]
+ else_body*: seq[LightExpr]
of leFuncCall:
func_name*: string
params*: seq[LightExpr]
else:
discard
-proc `$`*(exp: LightExpr): string =
- case exp.kind:
- of leVar: "Var[" & $exp.var_name & "]"
- of leNumLit: "Num[" & $exp.value & "]"
- of leOp: "Operation[" & $exp.operation & ", " & $exp.left & ", " & $exp.right & "]"
- of leAssign: "Assignment[" & $exp.variable & ", " & $exp.expression & "]"
- of leLabel: "Label[" & $exp.label & "]"
- of leGoto: "Goto[" & $exp.label & "]"
- of leIf: "If[" & $exp.condition & " -> " & $exp.body & "]"
- of leWhile: "While[" & $exp.condition & " -> " & $exp.body & "]"
- of leBreak: "Break"
- of leFuncCall: "FuncCall[" & exp.func_name & ", " & $exp.params & "]"
- of leFuncDef: "FuncDef[" & exp.def_func_name & ", " & $exp.func_body & "]"
- else: ""
\ No newline at end of file
+func `$`*(exp: LightExpr): string
+func printExpr(exp: LightExpr, ind: int): string
+
+func multiline(things: seq[LightExpr], ind: int): string =
+ return things.foldl(a & printExpr(b, ind) & "\n", "")[0..^2]
+
+func printExpr(exp: LightExpr, ind: int): string =
+ let ts = strutils.repeat(" ", ind)
+ ts & (
+ case exp.kind:
+ of leVar: "var[" & $exp.var_name & "]"
+ of leNumLit: "num[" & $exp.value & "]"
+ of leOp: "op[" & $exp.operation & ", " & printExpr(exp.left, 0) & ", " & printExpr(exp.right, 0) & "]"
+ of leAssign: "assignment[" & $exp.variable & ", " & printExpr(exp.expression, 0) & "]"
+ of leIf: "if [" & printExpr(exp.condition, 0) & "] {\n" & multiline(exp.body, ind + 1) & "\n" & ts & "} else {\n" & multiline(exp.else_body, ind + 1) & "\n" & ts & "}"
+ of leWhile: "while [" & printExpr(exp.condition, 0) & "] {\n" & multiline(exp.body, ind + 1) & "\n" & ts & "}"
+ of leBreak: "break"
+ of leFuncCall: "funcCall[" & exp.func_name & ", " & $exp.params & "]"
+ of leFuncDef: "funcDef[" & exp.def_func_name & "] {\n" & multiline(exp.func_body, ind + 1) & "\n" & ts & "}"
+ of leNull: "NullExpr[]"
+ else: "UNDEFINED[]"
+ )
+
+func `$`*(exp: LightExpr): string =
+ printExpr(exp, 0)
ltNull,
ltVar, ltNum,
ltExprDelim,
- ltLabel, ltGoto,
- ltIf, ltWhile,
+ ltIf, ltElse, ltWhile,
ltBlockStart, ltBlockEnd,
ltBreak,
ltFunc,
var_name*: LightVariable
of ltNum:
value*: LightInt
- of ltLabel:
- label_name*: string
of ltFunc, ltFuncDef:
func_name*: string
of ltOp:
of ltEq: "EqualsToken"
of ltNum: "NumberToken[" & $token.value & "]"
of ltExprDelim: "ExprDelimToken"
- of ltLabel: "LabelToken[" & token.label_name & "]"
- of ltGoto: "GotoToken"
of ltIf: "IfToken"
of ltWhile: "WhileToken"
of ltBreak: "BreakToken"