breaks work; refactor parser; operation tree reduction
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 16 Dec 2018 16:14:59 +0000 (10:14 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Sun, 16 Dec 2018 16:14:59 +0000 (10:14 -0600)
christmas_proj
data/progs/gol.lgt
data/progs/maze.lgt
src/lang/executer.nim
src/lang/parser.nim
src/lang/utils.nim [new file with mode: 0644]

index 9bafaa91535aad594ce6da3293b3b8c480304297..f355762d5182022497acbbdc3afd4131dd387c67 100755 (executable)
Binary files a/christmas_proj and b/christmas_proj differ
index f6dd1a46b3f159c8a8d40c4910704d2c7219c8fb..933492c71f3e6ca397fa61152badeec7ec0d807f 100644 (file)
@@ -1,6 +1,6 @@
 //Assumes 128 by 128 board
-#BOARD_WIDTH { 128 }
-#BOARD_HEIGHT { 128 }
+#BOARD_WIDTH { !GET_WIDTH() }
+#BOARD_HEIGHT { !GET_HEIGHT() }
 
 #CELL_ALIVE { 255 }
 #CELL_DEAD { 0 }
index 237f0c2523fedb7acac8a872605a0c60cce75e80..4cc1bbf223f1ecb574e3a049b00ea369e1455df6 100644 (file)
@@ -67,8 +67,7 @@ while !get_stack_height() > 0 {
        $y = $y - 2
 
        if $m1 {
-               $m8 = 1
-               while $m8 {
+               while 1 {
                        //Random direction
                        $m7 = !random(4)
 
@@ -103,7 +102,7 @@ while !get_stack_height() > 0 {
                                        $x = $x + $m5
                                        $y = $y + $m6
                                        !push_pos()
-                                       $m8 = 0
+                                       break
                                } else {
                                        !pop_pos()
                                        !pop_pos()
index 7be2cf17e683e78c44a02f8178c4c893327b3373..b612f93e891bac31196445f922ae4e5b57c06601 100644 (file)
@@ -2,6 +2,7 @@ import os
 import tables
 import ./types/types
 import ./types/ast
+import ./utils
 import ./program
 import ../board/board
 import ../gfx/window
@@ -19,6 +20,7 @@ type
     builtin_functions: ExecFuncs
     defined_functions: TableRef[string, seq[LightExpr]]
     running: bool
+    break_flag: bool
 
 proc MakeEmptyWorker(): LightWorker =
   LightWorker()
@@ -30,7 +32,8 @@ proc MakeExecutionContext*(funcs: ExecFuncs): ExecutionContext =
     worker: worker,
     builtin_functions: funcs,
     defined_functions: defined_functions,
-    running: false
+    running: false,
+    break_flag: false,
   )
 
 proc ExecuteLines(ec: ExecutionContext, lines: seq[LightExpr]): LightInt
@@ -79,30 +82,7 @@ proc EvalExpr(ec: ExecutionContext, exp: LightExpr): LightInt =
       left = EvalExpr(ec, exp.left)
       right = EvalExpr(ec, exp.right)
 
-    case exp.operation:
-    of loAdd: left + right
-    of loSub: left - right
-    of loMul: left * right
-    of loDiv: left div right
-    of loMod: left mod right
-    of loGt:
-      if left > right: 1
-      else: 0
-    of loGte:
-      if left >= right: 1
-      else: 0
-    of loLt:
-      if left < right: 1
-      else: 0
-    of loLte:
-      if left <= right: 1
-      else: 0
-    of loEq:
-      if left == right: 1
-      else: 0
-    of loNeq:
-      if left != right: 1
-      else: 0
+    EvalOperation(exp.operation, left, right)
 
   of leAssign:
     let value = EvalExpr(ec, exp.expression)
@@ -116,12 +96,20 @@ proc EvalExpr(ec: ExecutionContext, exp: LightExpr): LightInt =
       ExecuteLines(ec, exp.else_body)
 
   of leWhile:
+    var last: LightInt = 0
     while ec.running:
       let cond = EvalExpr(ec, exp.condition)
       if cond == 0:
         break
+      if ec.break_flag:
+        ec.break_flag = false
+        break
+
+      last = ExecuteLines(ec, exp.body)
+    last
 
-      discard ExecuteLines(ec, exp.body)
+  of leBreak:
+    ec.break_flag = true
     0
 
   of leFuncCall:
@@ -153,8 +141,12 @@ proc ExecuteLines(ec: ExecutionContext, lines: seq[LightExpr]): LightInt =
 
   var last: LightInt = 0
   for line in lines:
-    last = EvalExpr(ec, line)
-    if not ec.running: break
+    let next = EvalExpr(ec, line)
+    if ec.break_flag:
+      break
+    last = next
+    if not ec.running:
+      break
   last
 
 proc ExecuteProgram*(ec: ExecutionContext, prog: LightProgram): LightInt =
index 932e4b9afbe38ff579328ecac062779ee97a8053..5e4fca1922523744696cd8d9d9be8c3ae567d8fa 100644 (file)
@@ -2,21 +2,13 @@
 import ./types/types
 import ./types/tokens
 import ./types/ast
+import ./utils
 
 import ../utils/iter
 
-type
-  LightParser = object
-    tokens: Iter[LightToken]
-  
-func CreateParser(tokens: Iter[LightToken]): LightParser =
-  LightParser(tokens: tokens)
-func CreateParser(tokens: seq[LightToken]): LightParser =
-  CreateParser(CreateIter[LightToken](tokens, LightToken(kind: ltNull)))
-
-func NextExpr(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]): LightExpr
+func NextExpr(tokens: Iter[LightToken], prev: LightExpr, stop_at: set[LightTokenType]): LightExpr
 
-func Parse_block(tokens: Iter[LightToken], sep, endd: LightTokenType): seq[LightExpr] =
+func ParseBlock(tokens: Iter[LightToken], sep, endd: LightTokenType): seq[LightExpr] =
   result = @[]
 
   var last = tokens.Current
@@ -24,21 +16,20 @@ func Parse_block(tokens: Iter[LightToken], sep, endd: LightTokenType): seq[Light
     tokens.Step()
     return
 
-  var parser = CreateParser(tokens)
   while last.kind != endd:
-    let p = parser.NextExpr(LightExpr(kind: leNull), {sep, endd})
+    let p = tokens.NextExpr(LightExpr(kind: leNull), {sep, endd})
     if p.kind != leNull:
       result.add(p)
-    last = parser.tokens.Current
-    parser.tokens.Step()
+    last = tokens.Current
+    tokens.Step()
   
-func NextExpr(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]): LightExpr =
-  let curr = parser.tokens.Current
+func NextExpr(tokens: Iter[LightToken], prev: LightExpr, stop_at: set[LightTokenType]): LightExpr =
+  let curr = tokens.Current
 
   if curr.kind in stop_at:
     return prev
 
-  parser.tokens.Step()
+  tokens.Step()
 
   if curr.kind in {ltNum, ltVar, ltFunc} and prev.kind == leNull:
     let prevExpr =
@@ -46,11 +37,11 @@ func NextExpr(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]
       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 != ltLeftParen:
+        if tokens.Current.kind != ltLeftParen:
           raise newException(ValueError, "Expected parameter list after function call")
 
-        parser.tokens.Step()
-        let params = Parse_block(parser.tokens, ltParamDelim, ltRightParen)
+        tokens.Step()
+        let params = ParseBlock(tokens, ltParamDelim, ltRightParen)
 
         LightExpr(
           kind: leFuncCall,
@@ -59,28 +50,36 @@ func NextExpr(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]
         )
       else: LightExpr(kind: leNull)
 
-    return parser.NextExpr(prevExpr, stop_at)
+    return tokens.NextExpr(prevExpr, stop_at)
 
   elif curr.kind == ltOp:
-    let next = parser.NextExpr(LightExpr(kind: leNull), stop_at)
-    return LightExpr(
-      kind: leOp,
-      left: prev,
-      right: next,
-      operation: curr.operation
-    )
+    let next = tokens.NextExpr(LightExpr(kind: leNull), stop_at)
+
+    # Reduce if possible
+    if prev.kind == leNumLit and next.kind == leNumLit:
+      return LightExpr(
+        kind: leNumLit,
+        value: EvalOperation(curr.operation, prev.value, next.value)
+      )
+    else:
+      return LightExpr(
+        kind: leOp,
+        left: prev,
+        right: next,
+        operation: curr.operation
+      )
 
   elif curr.kind == ltLeftParen:
-    let next = parser.NextExpr(LightExpr(kind: leNull), {ltRightParen})
-    parser.tokens.Step()
-    return parser.NextExpr(next, stop_at)
+    let next = tokens.NextExpr(LightExpr(kind: leNull), {ltRightParen})
+    tokens.Step()
+    return tokens.NextExpr(next, stop_at)
   
   elif curr.kind == ltEq:
     if prev.kind != leVar:
       raise newException(ValueError, "Expected variable on the left of assignment operator")
 
     else:
-      let next = parser.NextExpr(LightExpr(kind: leNull), stop_at)
+      let next = tokens.NextExpr(LightExpr(kind: leNull), stop_at)
 
       return LightExpr(
         kind: leAssign,
@@ -89,15 +88,15 @@ func NextExpr(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]
       )
 
   elif curr.kind == ltIf:
-    let condition = parser.NextExpr(LightExpr(kind: leNull), {ltBlockStart})
-    parser.tokens.Step()
-    let body = Parse_block(parser.tokens, ltExprDelim, ltBlockEnd)
+    let condition = tokens.NextExpr(LightExpr(kind: leNull), {ltBlockStart})
+    tokens.Step()
+    let body = ParseBlock(tokens, ltExprDelim, ltBlockEnd)
 
     let else_body =
-      if parser.tokens.Current.kind == ltElse:
-        parser.tokens.Step()
-        parser.tokens.Step()
-        Parse_block(parser.tokens, ltExprDelim, ltBlockEnd)
+      if tokens.Current.kind == ltElse:
+        tokens.Step()
+        tokens.Step()
+        ParseBlock(tokens, ltExprDelim, ltBlockEnd)
       else:
         @[]
 
@@ -110,9 +109,9 @@ func NextExpr(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]
     )
 
   elif curr.kind == ltWhile:
-    let condition = parser.NextExpr(LightExpr(kind: leNull), {ltBlockStart})
-    parser.tokens.Step()
-    let body = Parse_block(parser.tokens, ltExprDelim, ltBlockEnd)
+    let condition = tokens.NextExpr(LightExpr(kind: leNull), {ltBlockStart})
+    tokens.Step()
+    let body = ParseBlock(tokens, ltExprDelim, ltBlockEnd)
 
     return LightExpr(
       kind: leWhile,
@@ -126,11 +125,11 @@ func NextExpr(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]
     )
   
   elif curr.kind == ltFuncDef:
-    if parser.tokens.Current.kind != ltBlockStart:
+    if tokens.Current.kind != ltBlockStart:
       raise newException(ValueError, "Expected block start after function definition")
     
-    parser.tokens.Step()
-    let body = Parse_block(parser.tokens, ltExprDelim, ltBlockEnd)
+    tokens.Step()
+    let body = ParseBlock(tokens, ltExprDelim, ltBlockEnd)
     
     return LightExpr(
       kind: leFuncDef,
@@ -143,10 +142,10 @@ func NextExpr(parser: LightParser, prev: LightExpr, stop_at: set[LightTokenType]
       kind: leNull
     )
   
-iterator Parse_tokens*(tokens: seq[LightToken]): LightExpr =
-  var parser = CreateParser(tokens)
-  while not parser.tokens.ReachedEnd:
-    let next = parser.NextExpr(LightExpr(kind: leNull), {ltExprDelim})
+iterator Parse_tokens*(tkns: seq[LightToken]): LightExpr =
+  var tokens = CreateIter[LightToken](tkns, LightToken(kind: ltNull))
+  while not tokens.ReachedEnd:
+    let next = tokens.NextExpr(LightExpr(kind: leNull), {ltExprDelim})
     if next.kind != leNull:
       yield next
-    parser.tokens.Step()
+    tokens.Step()
diff --git a/src/lang/utils.nim b/src/lang/utils.nim
new file mode 100644 (file)
index 0000000..86ee900
--- /dev/null
@@ -0,0 +1,27 @@
+import ./types/types
+
+proc EvalOperation*(operation: LightOperation, left, right: LightInt): LightInt =
+    case operation:
+    of loAdd: left + right
+    of loSub: left - right
+    of loMul: left * right
+    of loDiv: left div right
+    of loMod: left mod right
+    of loGt:
+      if left > right: 1
+      else: 0
+    of loGte:
+      if left >= right: 1
+      else: 0
+    of loLt:
+      if left < right: 1
+      else: 0
+    of loLte:
+      if left <= right: 1
+      else: 0
+    of loEq:
+      if left == right: 1
+      else: 0
+    of loNeq:
+      if left != right: 1
+      else: 0