polished version
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 16 Dec 2018 03:30:14 +0000 (21:30 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 16 Dec 2018 03:30:14 +0000 (21:30 -0600)
15 files changed:
christmas_proj
christmas_proj.nimble
data/progs/avg.lgt [new file with mode: 0644]
data/progs/fibcol.lgt [deleted file]
data/progs/first.lgt
data/progs/gol.lgt [new file with mode: 0644]
data/progs/test.lgt [deleted file]
src/board/board.nim
src/christmas_proj.nim
src/lang/executer.nim
src/lang/lexer.nim
src/lang/parser.nim
src/lang/program.nim
src/lang/types/ast.nim
src/lang/types/tokens.nim

index 94824293d7132f8befb22591f48e87cbb66a8d47..98bedaa7edbf2d80f1a83f6d0d5b28112d2c9391 100755 (executable)
Binary files a/christmas_proj and b/christmas_proj differ
index 182ef92fa663232d62b8e299f379f155f537178a..c147fcdcaa247908cbcbe3b54bfd769f45f62103 100644 (file)
@@ -11,6 +11,7 @@ bin           = @["christmas_proj"]
 # Dependencies
 
 requires "nim >= 0.19.0"
+requires "docopt >= 0.6.8"
 requires "opengl >= 1.2.0"
 requires "glfw"
 
diff --git a/data/progs/avg.lgt b/data/progs/avg.lgt
new file mode 100644 (file)
index 0000000..e6ee493
--- /dev/null
@@ -0,0 +1,81 @@
+
+#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
+               }
+       }
+}
diff --git a/data/progs/fibcol.lgt b/data/progs/fibcol.lgt
deleted file mode 100644 (file)
index 11e416d..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-$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()
-       }
-}
-
index 61b8e9ee2be2e6c6f650fc850006c498aa64e5f7..748ee796a500a0318349c4069839b467644c951d 100644 (file)
@@ -1,43 +1,43 @@
-$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)
diff --git a/data/progs/gol.lgt b/data/progs/gol.lgt
new file mode 100644 (file)
index 0000000..39e70ba
--- /dev/null
@@ -0,0 +1,108 @@
+//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
diff --git a/data/progs/test.lgt b/data/progs/test.lgt
deleted file mode 100644 (file)
index a719715..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-$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
index aecfcdfc0b0721fdffec9eb28adf13b93c82aa9c..3f481446d1758bf36749c72c938eab43dbc1e3e5 100644 (file)
@@ -3,8 +3,8 @@ import ../gfx/glutils
 
 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]
 
index 229b07b126e994cc685c453b4e6cfa759b3d8415..f4783b89312ebec62b0720535de0f0b50ffaed54 100644 (file)
@@ -1,11 +1,17 @@
 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
 
@@ -15,36 +21,90 @@ proc key_down(window: glfw.Window, key, scancode, action, modifier: cint) {.cdec
   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)
@@ -59,14 +119,47 @@ proc main() =
     )
   })
 
-  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)
@@ -74,5 +167,39 @@ proc main() =
 
   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()
index 4988ee22bf0a0d8d8ff8a7fa86f2948017f272eb..7be2cf17e683e78c44a02f8178c4c893327b3373 100644 (file)
@@ -12,7 +12,7 @@ type
     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
@@ -113,7 +113,7 @@ proc EvalExpr(ec: ExecutionContext, exp: LightExpr): LightInt =
     if cond != 0:
       ExecuteLines(ec, exp.body)
     else:
-      0
+      ExecuteLines(ec, exp.else_body)
 
   of leWhile:
     while ec.running:
@@ -135,15 +135,15 @@ proc EvalExpr(ec: ExecutionContext, exp: LightExpr): LightInt =
       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
 
@@ -151,7 +151,7 @@ proc ExecuteLines(ec: ExecutionContext, lines: seq[LightExpr]): LightInt =
   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
index 6e754c86ee27f9a17f2d878bd623347d3a22587a..aa277092edfda88a06b535fefda5a62303a26af6 100644 (file)
@@ -10,16 +10,21 @@ iterator Generate_tokens*(source: string): LightToken =
     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('$'):
@@ -29,16 +34,16 @@ iterator Generate_tokens*(source: string): LightToken =
         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.")
 
@@ -55,6 +60,12 @@ iterator Generate_tokens*(source: string): LightToken =
       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)
@@ -63,21 +74,17 @@ iterator Generate_tokens*(source: string): LightToken =
 
       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 "+":
index 1019884438d3eed7406aad0a264552cfb72c1921..c28d4e14c6141ba9b183fe277f1f9c4d4f712ea8 100644 (file)
@@ -40,11 +40,23 @@ func NextExpr(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]
 
   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)
@@ -71,32 +83,25 @@ func NextExpr(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]
         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:
@@ -114,19 +119,6 @@ func NextExpr(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]
     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:
index 1dbfce08a22ff7c66bf9ab29ad6af1ce967430ff..0a72c1421ec76440ec3a18a4b175c16c64fb6ed7 100644 (file)
@@ -1,6 +1,7 @@
 import sequtils
 import tables
 import ./types/ast
+import ./types/tokens
 import ./lexer
 import ./parser
 
index 1cd98b636438af0a2b42c23315a96969fe776828..66a587f3918f09502651e62e4447f1f89166c2b4 100644 (file)
@@ -1,3 +1,5 @@
+import sequtils
+import strutils
 import ./types
 import ./tokens
 
@@ -8,13 +10,11 @@ type
     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
@@ -29,11 +29,10 @@ type
     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]
@@ -43,17 +42,28 @@ type
     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)
index b9ceaec668b4a6a66aa5742802150ca6f271f03a..8247db8a037449ef62aa9cbbe0bc9d7e6cec9b34 100644 (file)
@@ -5,8 +5,7 @@ type
     ltNull,
     ltVar, ltNum,
     ltExprDelim,
-    ltLabel, ltGoto,
-    ltIf, ltWhile,
+    ltIf, ltElse, ltWhile,
     ltBlockStart, ltBlockEnd,
     ltBreak,
     ltFunc,
@@ -21,8 +20,6 @@ type
       var_name*: LightVariable
     of ltNum:
       value*: LightInt
-    of ltLabel:
-      label_name*: string
     of ltFunc, ltFuncDef:
       func_name*: string
     of ltOp:
@@ -51,8 +48,6 @@ proc `$`*(token: LightToken): string =
     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"