requires "nim >= 0.19.0"
requires "docopt >= 0.6.8"
requires "opengl >= 1.2.0"
-requires "glfw"
+requires "nimrod-glfw"
task run, "Run project":
exec("nimble build -d:release")
- exec("./christmas_proj")
\ No newline at end of file
+ exec("./christmas_proj")
+++ /dev/null
-
-@FLOOD_WITH_RANDOM() {
- $m6 = (256 * 256 * 256) - 1
- $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
-$x = 0
-$y = 10
-$m8 = 1
-
-#move_diag {
- $x = $x + $m8
- $y = $y + $m8
-}
-
-#swap_xy {
- $m1 = $x
- $x = $y
- $y = $m1
-}
-
-$m3 = 100
-while $x <= !GET_WIDTH() {
- $m3 = $m3 + 4
- if $m3 >= 256 {
- $m3 = $m3 - 156
- }
-
- !set_col($m3)
- !move_diag()
- !swap_xy()
- !render()
-}
-
-$x = !GET_WIDTH() - 15
-$y = !GET_HEIGHT() - 1
-$m8 = 0 - 1
-
-while $x >= 0 {
- !set_col(255)
- !move_diag()
- !render()
-}
-
-!say($x)
-$m2 = if $x < 0 {
- 1000
-}
-!say($m2)
+++ /dev/null
-//Assumes 128 by 128 board
-@BOARD_WIDTH() { !GET_WIDTH() }
-@BOARD_HEIGHT() { !GET_HEIGHT() }
-
-@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
-
- if !get_a() == !CELL_ALIVE() {
- if ($m1 < 2) | ($m1 > 3) {
- !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 = 1
-
- !COPY_BOARD()
-
- $y = 0
- while $y < !BOARD_HEIGHT() {
- $x = 0
- while $x < !BOARD_WIDTH() {
- !UPDATE_CURRENT()
- $x = $x + 1
- }
- $y = $y + 1
- }
- }
-}
-
-(5 > 4) & (7 > 10)
\ No newline at end of file
--- /dev/null
+//Assumes 128 by 128 board
+var $board_width = !get_width()
+var $board_height = !get_height()
+
+var $cell_alive = 255
+var $cell_dead = 0
+
+@create_board() {
+ var $x
+ var $y
+
+ // Set up initial board
+ $y = 0
+ while $y < $board_height {
+ $x = 0
+ while $x < $board_width {
+ if !random(100) >= 50 {
+ !set_r($x, $y, $cell_alive)
+ } else {
+ !set_r($x, $y, $cell_dead)
+ }
+ $x = $x + 1
+ }
+ $y = $y + 1
+ }
+}
+
+@update_cell($x, $y) {
+ var $neighbors = 0
+ var $x_off
+ var $y_off
+
+ $y_off = -1
+ while $y_off <= 1 {
+ $x_off = -1
+ while $x_off <= 1 {
+ if ($y_off ~= 0) | ($x_off ~= 0) {
+ if !get_a($x_off + $x, $y_off + $y) == $cell_alive {
+ $neighbors = $neighbors + 1
+ }
+ }
+ $x_off = $x_off + 1
+ }
+ $y_off = $y_off + 1
+ }
+
+ if !get_a($x, $y) == $cell_alive {
+ if ($neighbors < 2) | ($neighbors > 3) {
+ !set_r($x, $y, $cell_dead)
+ }
+ } else {
+ if $neighbors == 3 {
+ !set_r($x, $y, $cell_alive)
+ }
+ }
+}
+
+@copy_board() {
+ var $x
+ var $y
+
+ $y = 0
+ while $y < $board_height {
+ $x = 0
+ while $x < $board_width {
+ !set_a($x, $y, !get_r($x, $y))
+
+ $x = $x + 1
+ }
+ $y = $y + 1
+ }
+}
+
+!create_board()
+
+//Big render / update loop
+var $x
+var $y
+while 1 {
+ //Draw the board
+ !render()
+
+ !copy_board()
+
+ $y = 0
+ while $y < $board_height {
+ $x = 0
+ while $x < $board_width {
+ !update_cell($x, $y)
+ $x = $x + 1
+ }
+ $y = $y + 1
+ }
+}
+++ /dev/null
-@push_pos() {
- $m1 = ($y * 256 * 256) + $x
-
- !step_to_linear(0)
- !step_to_linear(!get_col() + 1)
-
- !set_col($m1)
-
- !step_to_linear(0)
- !set_col(!get_col() + 1)
-
- $x = $m1 % (256 * 256)
- $y = $m1 / (256 * 256)
-}
-
-@pop_pos() {
- !step_to_linear(0)
- !step_to_linear(!get_col())
- $m1 = !get_col()
- //!set_col(16777215)
-
- !step_to_linear(0)
- !set_col(!get_col() - 1)
- $x = $m1 % (256 * 256)
- $y = $m1 / (256 * 256)
-}
-
-@get_stack_height() {
- !push_pos()
- !step_to_linear(0)
- $m2 = !get_col() - 1
- !pop_pos()
- $m2
-}
-
-//Fills memory with defaults
-$y = 20
-while $y < !get_height() {
- $x = 0
- while $x < !get_width() {
- !set_col(255)
- $x = $x + 1
- }
- $y = $y + 1
-}
-
-
-$x = 1
-$y = 21
-!push_pos()
-!set_col(50)
-while !get_stack_height() > 0 {
- !pop_pos()
- !push_pos()
-
- $m1 = 0
- $y = $y - 2
- $m1 = $m1 + if !get_col() == 255 { 1 } else { 0 }
- $y = $y + 2
- $x = $x - 2
- $m1 = $m1 + if !get_col() == 255 { 1 } else { 0 }
- $x = $x + 4
- $m1 = $m1 + if !get_col() == 255 { 1 } else { 0 }
- $x = $x - 2
- $y = $y + 2
- $m1 = $m1 + if !get_col() == 255 { 1 } else { 0 }
- $y = $y - 2
-
- if $m1 {
- while 1 {
- //Random direction
- $m7 = !random(4)
-
- // dx and dy
- $m5 = $m6 = 0
-
- if $m7 == 0 { $m6 = -2 }
- if $m7 == 1 { $m5 = 2 }
- if $m7 == 2 { $m6 = 2 }
- if $m7 == 3 { $m5 = -2 }
-
- if !in_bounds($x + $m5, $y + $m6) {
- !push_pos()
- !push_pos()
- $x = $x + $m5
- $y = $y + $m6
- if !get_col() == 255 {
- !set_col(50)
- !pop_pos()
- $x = $x + $m5 / 2
- $y = $y + $m6 / 2
- !set_col(50)
- !pop_pos()
- $x = $x + $m5
- $y = $y + $m6
- !push_pos()
- break
- } else {
- !pop_pos()
- !pop_pos()
- }
- }
- }
- } else {
- !pop_pos()
- }
- !render()
-}
--- /dev/null
+@get_linear($pos) {
+ !get_col($pos % !get_width(), $pos / !get_width())
+}
+
+@set_linear($pos, $val) {
+ !set_col($pos % !get_width(), $pos / !get_width(), $val)
+}
+
+@push_pos($x, $y) {
+ var $color_enc = ($y * 256 * 256) + $x
+
+ var $off = !get_col(0, 0) + 1
+ !set_linear($off, $color_enc)
+
+ !set_col(0, 0, $off)
+}
+
+@top_pos() {
+ var $off = !get_col(0, 0)
+ !get_linear($off)
+}
+
+@pop_pos() {
+ var $off = !get_col(0, 0)
+ !set_linear($off, 0)
+ !set_col(0, 0, $off - 1)
+ 0
+}
+
+@get_stack_height() {
+ !get_col(0, 0)
+}
+
+//Fills memory with defaults
+@clear_board() {
+ var $x
+ var $y = 20
+ while $y < !get_height() {
+ $x = 0
+ while $x < !get_width() {
+ !set_col($x, $y, 255)
+ $x = $x + 1
+ }
+ $y = $y + 1
+ }
+}
+
+@generate_maze() {
+ var $x = 1
+ var $y = 21
+ var $loc
+ var $available_count
+ var $dir
+ var $dx
+ var $dy
+
+ !push_pos($x, $y)
+ !set_col($x, $y, 50)
+ while !get_stack_height() > 0 {
+ $loc = !top_pos()
+ $x = $loc % (256 * 256)
+ $y = $loc / (256 * 256)
+
+ $available_count = 0
+ $available_count = $available_count + !get_col($x, $y - 2) == 255
+ $available_count = $available_count + !get_col($x - 2, $y) == 255
+ $available_count = $available_count + !get_col($x + 2, $y) == 255
+ $available_count = $available_count + !get_col($x, $y + 2) == 255
+
+ if $available_count {
+ while 1 {
+ //Random direction
+ $dir = !random(4)
+
+ // dx and dy
+ $dx = $dy = 0
+
+ if $dir == 0 { $dx = -2 }
+ if $dir == 1 { $dx = 2 }
+ if $dir == 2 { $dy = 2 }
+ if $dir == 3 { $dy = -2 }
+
+ if !in_bounds($x + $dx, $y + $dy) {
+ if !get_col($x + $dx, $y + $dy) == 255 {
+ !set_col($x + $dx, $y + $dy, 50)
+ !set_col($x + $dx / 2, $y + $dy / 2, 50)
+ !push_pos($x + $dx, $y + $dy)
+ break
+ }
+ }
+ }
+ } else {
+ !pop_pos()
+ }
+ !render()
+ }
+}
+
+!clear_board()
+!generate_maze()
-@test_func($p1, $p2) {
- $p1 + $p2
-}
-@move_to($p1, $p2) {
- $x = $p1
- $y = $p2
-}
+var $param = 1000
-$p1 = 100
-$m1 = 0
-@rec($p1) {
- $m1 = $m1 + 1
- if $p1 <= 1 {
- 1
- } else {
- !test_func($p1, !rec($p1 - 1))
- }
+var $asdf = 10
+@test_func($param) {
+ !say($asdf)
+ var $asdf = 1234
+ !say($asdf)
+ !say($param + $test)
+ !set_col($param, $param + $test, ($param * $test) + 200)
}
-!say(!rec($p1), $m1)
-!say($p1)
+var $test = 4
+
+!test_func($asdf)
+!say($param)
+!render()
\ No newline at end of file
--- /dev/null
+var $width = !get_width()
+var $height = !get_height()
+
+//Util functions
+@get_linear($pos) {
+ !get_col($pos % $width, $pos / $width)
+}
+
+@set_linear($pos, $val) {
+ !set_col($pos % $width, $pos / $width, $val)
+}
+
+@swap_linear($p1, $p2) {
+ var $tmp = !get_col($p1 % $width, $p1 / $width)
+ !set_col($p1 % $width, $p1 / $width, !get_col($p2 % $width, $p2 / $width))
+ !set_col($p2 % $width, $p2 / $width, $tmp)
+}
+
+@fill_with_random() {
+ var $x = 0
+ var $y = 0
+ var $rgb
+
+ $y = 0
+ while $y < !get_height() {
+ $x = 0
+ while $x < !get_width() {
+ $rgb = !random(2)
+
+ !set_r($x, $y, if $rgb == 0 { !random(255) })
+ !set_g($x, $y, if $rgb == 1 { !random(255) })
+ !set_b($x, $y, if $rgb == 2 { !random(255) })
+ $x = $x + 1
+ }
+ $y = $y + 1
+ }
+}
+
+//Sorting functions
+
+@selection_sort($start, $end) {
+ var $tmp
+ var $small_val
+ var $small_ind
+ var $j
+ var $i = $start
+ while $i < $end {
+ $small_val = !get_linear($i)
+ $small_ind = $i
+ $j = $i + 1
+ while $j < $end {
+ if !get_linear($j) < $small_val {
+ $small_val = !get_linear($j)
+ $small_ind = $j
+ }
+
+ $j = $j + 1
+ }
+
+ !swap_linear($i, $small_ind)
+ !render()
+ $i = $i + 1
+ }
+}
+
+@bubble_sort($start, $end) {
+ var $i
+ var $j
+ var $tmp
+
+ $i = 0
+ while $i < ($end - 1) {
+ $j = 0
+ while $j < ($end - ($i + 1)) {
+ if !get_linear($j) > !get_linear($j + 1) {
+ !swap_linear($j, $j + 1)
+ }
+
+ $j = $j + 1
+ }
+ !render()
+ $i = $i + 1
+ }
+}
+
+@insertion_sort($start, $end) {
+ var $tmp
+ var $j = 0
+ var $i = $start + 1
+ while $i < $end {
+ $j = $i
+ while !get_linear($j) < !get_linear($j - 1) {
+ !swap_linear($j, $j - 1)
+ $j = $j - 1
+ }
+
+ $i = $i + 1
+ !render()
+ }
+}
+
+@shell_sort($start, $end) {
+ var $k
+ var $i
+ var $n
+
+ $k = $end / 2
+ while $k > 0 {
+ $i = $k
+ while $i < $end {
+ $n = $i - $k
+ while $n >= 0 {
+ if !get_linear($n + $k) >= !get_linear($n) {
+ break
+ } else {
+ !swap_linear($n, $n + $k)
+ }
+
+ $n = $n - $k
+ }
+
+ //Used to make it look cool
+ if ($i % 4) == 0 { !render() }
+ $i = $i + 1
+ }
+ $k = $k / 2
+ }
+}
+
+@quick_partition($low, $high) {
+ var $pivot = !get_linear($high)
+ var $i = $low
+ var $j = $low
+ while $j < $high {
+ if !get_linear($j) <= $pivot {
+ !swap_linear($i, $j)
+ $i = $i + 1
+ }
+
+ $j = $j + 1
+ }
+
+ !swap_linear($i, $high)
+ $i
+}
+
+@quick_sort($low, $high) {
+ if $low < $high {
+ var $pi = !quick_partition($low, $high)
+
+ !quick_sort($low, $pi - 1)
+ !render()
+ !quick_sort($pi + 1, $high)
+ !render()
+ }
+}
+
+
+!fill_with_random()
+!render()
+!bubble_sort(0, !get_width() * !get_height())
+
+!fill_with_random()
+!render()
+!selection_sort(0, !get_width() * !get_height())
+
+!fill_with_random()
+!render()
+!insertion_sort(0, !get_width() * !get_height())
+
+!fill_with_random()
+!render()
+!shell_sort(0, !get_width() * !get_height())
+
+!fill_with_random()
+!render()
+!quick_sort(0, (!get_width() * !get_height()) - 1)
glGenBuffers(1, board.colorBufferObject.addr)
glBindBuffer(GL_ARRAY_BUFFER, board.colorBufferObject)
- glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * board.width * board.height, board.colors.addr, GL_DYNAMIC_DRAW)
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * board.width * board.height, board.colors[].addr, GL_DYNAMIC_DRAW)
glEnableVertexAttribArray(1)
glVertexAttribDivisor(1, 1)
glVertexAttribPointer(1, 4, cGL_FLOAT, GL_FALSE, 16.GLsizei, nil)
),
"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)
+ board.SetCol(args[0].int, args[1].int, args[2].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)
+ board.SetA(args[0].int, args[1].int, args[2].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)
+ board.SetR(args[0].int, args[1].int, args[2].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)
+ board.SetG(args[0].int, args[1].int, args[2].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)
+ board.SetB(args[0].int, args[1].int, args[2].GLuint)
),
"get_col": (proc(ec: ExecutionContext, args: openarray[int32]): int32 {.closure.} =
- board.GetCol(ec.worker.pos_x.int, ec.worker.pos_y.int).int32
+ board.GetCol(args[0].int, args[1].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
+ board.GetA(args[0].int, args[1].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
+ board.GetR(args[0].int, args[1].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
+ board.GetG(args[0].int, args[1].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
+ board.GetB(args[0].int, args[1].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
- ec.worker.pos_y += 1
- while ec.worker.pos_x < 0:
- 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()
),
const MAX_STACK_HEIGHT = 400
type
- PContext = object
- p_1, p_2, p_3, p_4: LightInt
-
- PStack = ref object
- stack: ref array[MAX_STACK_HEIGHT, PContext]
- size: int
-
- LightWorker = ref object
- mem_1*, mem_2*, mem_3*, mem_4*: LightInt
- mem_5*, mem_6*, mem_7*, mem_8*: LightInt
- pos_x*, pos_y*: LightInt
- param_stack: PStack
+ Environment* = ref object
+ values: TableRef[LightVariable, LightInt]
+ parent: Environment
ExecFuncs* = TableRef[string, proc(ec: ExecutionContext, args: openarray[LightInt]): LightInt]
body: seq[LightExpr]
ExecutionContext* = ref object
- worker*: LightWorker
+ vars: Environment
builtin_functions: ExecFuncs
defined_functions: TableRef[string, DefFuncs]
running: bool
break_flag: bool
-proc Top(pstack: PStack): var PContext =
- pstack.stack[pstack.size - 1]
-
-proc Push(pstack: var PStack, ctx: PContext) =
- pstack.stack[pstack.size] = ctx
- pstack.size += 1
-
-proc Pop(pstack: var PStack): PContext =
- pstack.size -= 1
-
-proc MakeEmptyWorker(): LightWorker =
- let worker = LightWorker()
- let param_ctx = new(array[MAX_STACK_HEIGHT, PContext])
- worker.param_stack = PStack(
- stack: param_ctx,
- size: 1
+proc MakeEnvironment*(parent: Environment): Environment =
+ let values = newTable[LightVariable, LightInt]()
+ Environment(
+ values: values,
+ parent: parent
)
- worker
proc MakeExecutionContext*(funcs: ExecFuncs): ExecutionContext =
- let worker = MakeEmptyWorker()
+ let env = MakeEnvironment(nil)
let defined_functions = newTable[string, DefFuncs]()
ExecutionContext(
- worker: worker,
+ vars: env,
builtin_functions: funcs,
defined_functions: defined_functions,
running: false,
proc ExecuteLines(ec: ExecutionContext, lines: seq[LightExpr]): LightInt
-func GetVar(worker: LightWorker, variable: LightVariable): LightInt =
- case variable:
- of var_m1: worker.mem_1
- of var_m2: worker.mem_2
- of var_m3: worker.mem_3
- of var_m4: worker.mem_4
- of var_m5: worker.mem_5
- of var_m6: worker.mem_6
- of var_m7: worker.mem_7
- of var_m8: worker.mem_8
- of var_x: worker.pos_x
- of var_y: worker.pos_y
- of var_p1: worker.param_stack.Top().p_1
- of var_p2: worker.param_stack.Top().p_2
- of var_p3: worker.param_stack.Top().p_3
- of var_p4: worker.param_stack.Top().p_4
-
-func SetVar(worker: LightWorker, variable: LightVariable, value: LightInt): LightInt =
- case variable:
- of var_m1: worker.mem_1 = value
- of var_m2: worker.mem_2 = value
- of var_m3: worker.mem_3 = value
- of var_m4: worker.mem_4 = value
- of var_m5: worker.mem_5 = value
- of var_m6: worker.mem_6 = value
- of var_m7: worker.mem_7 = value
- of var_m8: worker.mem_8 = value
- of var_x: worker.pos_x = value
- of var_y: worker.pos_y = value
- of var_p1: worker.param_stack.Top().p_1 = value
- of var_p2: worker.param_stack.Top().p_2 = value
- of var_p3: worker.param_stack.Top().p_3 = value
- of var_p4: worker.param_stack.Top().p_4 = value
-
- value
+func GetVar(env: Environment, variable: LightVariable): LightInt =
+ if hasKey(env.values, variable):
+ return env.values[variable]
+
+ if env.parent == nil:
+ raise newException(ValueError, "Undefined variable: " & variable)
+
+ return env.parent.GetVar(variable)
+
+func SetVar(env: Environment, variable: LightVariable, value: LightInt): LightInt =
+ if hasKey(env.values, variable):
+ env.values[variable] = value
+ value
+
+ else:
+ if env.parent == nil:
+ raise newException(ValueError, "Undefined variable")
+
+ env.parent.SetVar(variable, value)
+
+func NewVar(env: Environment, variable: LightVariable) =
+ if hasKey(env.values, variable):
+ raise newException(ValueError, "Reclaration of variable: " & variable)
+
+ env.values[variable] = 0
proc EvalExpr(ec: ExecutionContext, exp: LightExpr): LightInt =
case exp.kind:
0
of leVar:
- GetVar(ec.worker, exp.var_name)
+ GetVar(ec.vars, exp.var_name)
+
+ of leVarDef:
+ NewVar(ec.vars, exp.var_name)
+ 0
of leNumLit:
exp.value
of leAssign:
let value = EvalExpr(ec, exp.expression)
- SetVar(ec.worker, exp.variable, value)
+ SetVar(ec.vars, exp.variable, value)
of leIf:
let cond = EvalExpr(ec, exp.condition)
for param in exp.params:
args.add(EvalExpr(ec, param))
- var ind: int = 0
- var params: PContext
+ var new_env = MakeEnvironment(ec.vars)
+ var ind: int = 0
for par in ec.defined_functions[exp.func_name].params:
if ind >= args.len:
raise newException(ValueError, "Too few parameters to function call")
-
- if par == var_p1: params.p_1 = args[ind]
- elif par == var_p2: params.p_2 = args[ind]
- elif par == var_p3: params.p_3 = args[ind]
- elif par == var_p4: params.p_4 = args[ind]
-
+
+ new_env.NewVar(par)
+ discard new_env.SetVar(par, args[ind])
ind += 1
- ec.worker.param_stack.Push(params)
+ ec.vars = new_env
let ret = ExecuteLines(ec, ec.defined_functions[exp.func_name].body)
- discard ec.worker.param_stack.Pop()
+ ec.vars = new_env.parent
ret
else:
continue
if token.startsWith('$'):
- let varString = token[1 .. ^1].toLowerAscii
- var varName: LightVariable
+ let varName = token[1 .. ^1].toLowerAscii
- if varString == "":
+ if varName == "":
raise newException(IOError, "Expected variable name")
- else:
- if varString == "m1": varName = var_m1
- elif varString == "m2": varName = var_m2
- elif varString == "m3": varName = var_m3
- elif varString == "m4": varName = var_m4
- elif varString == "m5": varName = var_m5
- elif varString == "m6": varName = var_m6
- elif varString == "m7": varName = var_m7
- elif varString == "m8": varName = var_m8
- elif varString == "p1": varName = var_p1
- elif varString == "p2": varName = var_p2
- elif varString == "p3": varName = var_p3
- elif varString == "p4": varName = var_p4
- elif varString == "x": varName = var_x
- elif varString == "y": varName = var_y
- else:
- raise newException(IOError, "Invalid variable name.")
-
+
yield LightToken(kind: ltVar, var_name: varName)
-
+
elif token.startsWith('!'):
let funcName = token[1..^1].toLowerAscii
yield LightToken(kind: ltFunc, func_name: funcName)
yield LightToken(kind: ltNum, value: value.LightInt)
+ elif token == "var":
+ yield LightToken(kind: ltVarDef)
elif token.toLowerAscii == "if":
yield LightToken(kind: ltIf)
elif token.toLowerAscii == "else":
let next = tokens.NextExpr(LightExpr(kind: leNull), {ltRightParen})
tokens.Step()
return tokens.NextExpr(next, stop_at)
+
+ elif curr.kind == ltVarDef:
+ if tokens.Current.kind != ltVar:
+ raise newException(ValueError, "Expected variable name for variable declaration")
+
+ let name = tokens.Current.var_name
+
+ return LightExpr(
+ kind: leVarDef,
+ var_name: name
+ )
elif curr.kind == ltEq:
+ var variable: string = ""
if prev.kind != leVar:
- raise newException(ValueError, "Expected variable on the left of assignment operator")
+ if tokens.Previous(2).kind == ltVar:
+ variable = tokens.Previous(2).var_name
+ else:
+ raise newException(ValueError, "Expected variable on the left of assignment operator")
+
+ let next = tokens.NextExpr(LightExpr(kind: leNull), stop_at)
- else:
- let next = tokens.NextExpr(LightExpr(kind: leNull), stop_at)
+ if variable == "":
+ variable = prev.var_name
- return LightExpr(
- kind: leAssign,
- variable: prev.var_name,
- expression: next
- )
+ return LightExpr(
+ kind: leAssign,
+ variable: variable,
+ expression: next
+ )
elif curr.kind == ltIf:
let condition = tokens.NextExpr(LightExpr(kind: leNull), {ltBlockStart})
for param in params:
if param.kind != leVar:
raise newException(ValueError, "Only parameter variables in function defintion parameter list")
- if (param.variable < var_p1) or (param.variable > var_p4):
- raise newException(ValueError, "Only parameter variables in function defintion parameter list")
else:
param_list.add(param.variable)
type
LightExprType* = enum
- leNull = 0,
- leVar = 1,
- leNumLit = 2,
- leOp = 3,
- leAssign = 4,
- leIf = 5,
- leWhile = 6,
- leBreak = 7,
- leFuncCall = 8,
- leFuncDef = 9,
+ leNull,
+ leVar,
+ leVarDef,
+ leNumLit,
+ leOp,
+ leAssign,
+ leIf,
+ leWhile,
+ leBreak,
+ leFuncCall,
+ leFuncDef,
LightExpr* = ref object
case kind*: LightExprType
- of leVar:
+ of leVar, leVarDef:
var_name*: LightVariable
of leNumLit:
value*: LightInt
let ts = strutils.repeat(" ", ind)
ts & (
case exp.kind:
+ of leVarDef: "varDef[" & $exp.var_name & "]"
of leVar: "var[" & $exp.var_name & "]"
of leNumLit: "num[" & $exp.value & "]"
of leOp: "op[" & $exp.operation & ", " & printExpr(exp.left, 0) & ", " & printExpr(exp.right, 0) & "]"
type
LightTokenType* = enum
ltNull,
- ltVar, ltNum,
+ ltVar, ltNum, ltVarDef,
ltExprDelim,
ltLeftParen, ltRightParen,
ltIf, ltElse, ltWhile,
case token.kind:
of ltNull: "NullToken"
of ltVar: "VarToken[" & $token.var_name & "]"
+ of ltVarDef: "VarDefToken"
of ltEq: "EqualsToken"
of ltNum: "NumberToken[" & $token.value & "]"
of ltExprDelim: "ExprDelimToken"
type
- LightVariable* = enum
- var_m1, var_m2, var_m3, var_m4,
- var_m5, var_m6, var_m7, var_m8,
- var_p1, var_p2, var_p3, var_p4,
- var_x, var_y
+ #LightVariable* = enum
+ # var_m1, var_m2, var_m3, var_m4,
+ # var_m5, var_m6, var_m7, var_m8,
+ # var_p1, var_p2, var_p3, var_p4,
+ # var_x, var_y
+ LightVariable* = string
LightOperation* = enum
loAdd, loSub, loMul, loDiv, loMod,
LightInt* = int32
-func `$`*(variable: LightVariable): string =
- case variable:
- of var_m1: "MEM_1"
- of var_m2: "MEM_2"
- of var_m3: "MEM_3"
- of var_m4: "MEM_4"
- of var_m5: "MEM_5"
- of var_m6: "MEM_6"
- of var_m7: "MEM_7"
- of var_m8: "MEM_8"
- of var_p1: "PRM_1"
- of var_p2: "PRM_2"
- of var_p3: "PRM_3"
- of var_p4: "PRM_4"
- of var_x: "POS_X"
- of var_y: "POS_Y"
+#func `$`*(variable: LightVariable): string =
+# case variable:
+# of var_m1: "MEM_1"
+# of var_m2: "MEM_2"
+# of var_m3: "MEM_3"
+# of var_m4: "MEM_4"
+# of var_m5: "MEM_5"
+# of var_m6: "MEM_6"
+# of var_m7: "MEM_7"
+# of var_m8: "MEM_8"
+# of var_p1: "PRM_1"
+# of var_p2: "PRM_2"
+# of var_p3: "PRM_3"
+# of var_p4: "PRM_4"
+# of var_x: "POS_X"
+# of var_y: "POS_Y"
proc CreateIter*[T](items: seq[T], empty: T): Iter[T] =
Iter[T](curr: 0, list: items, length: items.len, empty: empty)
-proc Step*[T](iter: Iter[T]) =
- iter.curr += 1
+proc Step*[T](iter: Iter[T], off: int = 1) =
+ iter.curr += off
func ReachedEnd*[T](iter: Iter[T]): bool =
iter.curr >= iter.length
return iter.list[iter.curr]
-proc Previous*[T](iter: Iter[T]): T =
- if iter.curr - 1 < 0 or iter.curr - 1 >= iter.length:
+proc Previous*[T](iter: Iter[T], off: int = 1): T =
+ if iter.curr - off < 0 or iter.curr - off >= iter.length:
return iter.empty
- return iter.list[iter.curr - 1]
+ return iter.list[iter.curr - off]
-proc Next*[T](iter: Iter[T]): T =
- if iter.curr + 1 < 0 or iter.curr + 1 >= iter.length:
+proc Next*[T](iter: Iter[T], off: int = 1): T =
+ if iter.curr + off < 0 or iter.curr + off >= iter.length:
return iter.empty
- return iter.list[iter.curr + 1]
+ return iter.list[iter.curr + off]