function parameters with scope; slight syntax change
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 17 Dec 2018 08:14:41 +0000 (02:14 -0600)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Mon, 17 Dec 2018 08:14:41 +0000 (02:14 -0600)
12 files changed:
christmas_proj
data/progs/avg.lgt
data/progs/gol.lgt
data/progs/maze.lgt
data/progs/new_syntax.light [new file with mode: 0644]
src/lang/executer.nim
src/lang/lexer.nim
src/lang/parser.nim
src/lang/types/ast.nim
src/lang/types/tokens.nim
src/lang/types/types.nim
src/lang/utils.nim

index f355762d5182022497acbbdc3afd4131dd387c67..b4796ba8496bdea29c8e7fe1c05f35c0ddce77f4 100755 (executable)
Binary files a/christmas_proj and b/christmas_proj differ
index db38f0601e220ce73c4d4341df0e9669e38fda25..312858550589bbcf89e6914c45c905539b513e72 100644 (file)
@@ -1,5 +1,5 @@
 
-#FLOOD_WITH_RANDOM {
+@FLOOD_WITH_RANDOM() {
        $m6 = (256 * 256 * 256) - 1
        $m7 = !GET_WIDTH()
        $m8 = !GET_HEIGHT()
@@ -16,7 +16,7 @@
 }
 
 //change 1, 2, 3 4, 7, 8
-#TAKE_AVERAGE {
+@TAKE_AVERAGE() {
        //Red, Green and Blue Sum
        $m1 = 0
        $m2 = 0
index 933492c71f3e6ca397fa61152badeec7ec0d807f..40c1fbf8326a84faa514002e6686b0dc5c786aac 100644 (file)
@@ -1,9 +1,9 @@
 //Assumes 128 by 128 board
-#BOARD_WIDTH { !GET_WIDTH() }
-#BOARD_HEIGHT { !GET_HEIGHT() }
+@BOARD_WIDTH() { !GET_WIDTH() }
+@BOARD_HEIGHT() { !GET_HEIGHT() }
 
-#CELL_ALIVE { 255 }
-#CELL_DEAD { 0 }
+@CELL_ALIVE() { 255 }
+@CELL_DEAD() { 0 }
 
 // Set up initial board
 $y = 0
@@ -20,7 +20,7 @@ while $y < !BOARD_HEIGHT() {
        $y = $y + 1
 }
 
-#UPDATE_CURRENT {
+@UPDATE_CURRENT() {
        //Neighbor count
        $m1 = 0
 
@@ -48,9 +48,8 @@ while $y < !BOARD_HEIGHT() {
        $x = $x - 1
        $y = $y - 1
 
-       $m2 = !get_a() == !CELL_ALIVE()
-       if $m2 {
-               if ($m1 < 2) + ($m1 > 3) {
+       if !get_a() == !CELL_ALIVE() {
+               if ($m1 < 2) | ($m1 > 3) {
                        !set_r(!CELL_DEAD())
                }
        } else {
@@ -60,7 +59,7 @@ while $y < !BOARD_HEIGHT() {
        }
 }
 
-#COPY_BOARD {
+@COPY_BOARD() {
        $y = 0
        while $y < !BOARD_HEIGHT() {
                $x = 0
@@ -83,15 +82,7 @@ while 1 {
        if $m7 <= 0 {
                $m7 = 1
 
-               $y = 0
-               while $y < !BOARD_HEIGHT() {
-                       $x = 0
-                       while $x < !BOARD_WIDTH() {
-                               !COPY_BOARD()
-                               $x = $x + 1
-                       }
-                       $y = $y + 1
-               }
+               !COPY_BOARD()
 
                $y = 0
                while $y < !BOARD_HEIGHT() {
@@ -103,4 +94,6 @@ while 1 {
                        $y = $y + 1
                }
        }
-}
\ No newline at end of file
+}
+
+(5 > 4) & (7 > 10)
\ No newline at end of file
index 4cc1bbf223f1ecb574e3a049b00ea369e1455df6..f450a50e15db7cffa6287c7f0536f78130df49cf 100644 (file)
@@ -1,4 +1,4 @@
-#push_pos {
+@push_pos() {
        $m1 = ($y * 256 * 256) + $x
 
        !step_to_linear(0)
@@ -13,7 +13,7 @@
        $y = $m1 / (256 * 256)
 }
 
-#pop_pos {
+@pop_pos() {
        !step_to_linear(0)
        !step_to_linear(!get_col())
        $m1 = !get_col()
@@ -25,7 +25,7 @@
        $y = $m1 / (256 * 256)
 }
 
-#get_stack_height {
+@get_stack_height() {
        !push_pos()
        !step_to_linear(0)
        $m2 = !get_col() - 1
@@ -38,7 +38,7 @@ $y = 20
 while $y < !get_height() {
        $x = 0
        while $x < !get_width() {
-               !set_col(50)
+               !set_col(255)
                $x = $x + 1
        }
        $y = $y + 1
@@ -48,22 +48,22 @@ while $y < !get_height() {
 $x = 1
 $y = 21
 !push_pos()
-!set_col(255)
+!set_col(50)
 while !get_stack_height() > 0 {
        !pop_pos()
        !push_pos()
 
        $m1 = 0
        $y = $y - 2     
-       $m1 = $m1 + if !get_col() == 50 { 1 } else { 0 }
+       $m1 = $m1 + if !get_col() == 255 { 1 } else { 0 }
        $y = $y + 2
        $x = $x - 2
-       $m1 = $m1 + if !get_col() == 50 { 1 } else { 0 }
+       $m1 = $m1 + if !get_col() == 255 { 1 } else { 0 }
        $x = $x + 4
-       $m1 = $m1 + if !get_col() == 50 { 1 } else { 0 }
+       $m1 = $m1 + if !get_col() == 255 { 1 } else { 0 }
        $x = $x - 2
        $y = $y + 2
-       $m1 = $m1 + if !get_col() == 50 { 1 } else { 0 }
+       $m1 = $m1 + if !get_col() == 255 { 1 } else { 0 }
        $y = $y - 2
 
        if $m1 {
@@ -74,30 +74,22 @@ while !get_stack_height() > 0 {
                        // 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 $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() == 50 {
-                                       !set_col(255)
+                               if !get_col() == 255 {
+                                       !set_col(50)
                                        !pop_pos()
                                        $x = $x + $m5 / 2
                                        $y = $y + $m6 / 2
-                                       !set_col(255)
+                                       !set_col(50)
                                        !pop_pos()
                                        $x = $x + $m5
                                        $y = $y + $m6
diff --git a/data/progs/new_syntax.light b/data/progs/new_syntax.light
new file mode 100644 (file)
index 0000000..48ff7a1
--- /dev/null
@@ -0,0 +1,23 @@
+@test_func($p1, $p2) {
+       $p1 + $p2
+}
+
+@move_to($p1, $p2) {
+       $x = $p1
+       $y = $p2
+}
+
+$p1 = 100
+
+$m1 = 0
+@rec($p1) {
+       $m1 = $m1 + 1
+       if $p1 <= 1 {
+               1
+       } else {
+               !test_func($p1, !rec($p1 - 1))
+       }
+}
+
+!say(!rec($p1), $m1)
+!say($p1)
index b612f93e891bac31196445f922ae4e5b57c06601..cb76310557e5d80ff4acc7f111f92f9e63603373 100644 (file)
@@ -7,27 +7,57 @@ import ./program
 import ../board/board
 import ../gfx/window
 
+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
-    var_1*, var_2*, var_3*, var_4*: LightInt
-    var_5*, var_6*, var_7*, var_8*: LightInt
+    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
 
   ExecFuncs* = TableRef[string, proc(ec: ExecutionContext, args: openarray[LightInt]): LightInt]
 
+  DefFuncs = ref object
+    params: seq[LightVariable]
+    body: seq[LightExpr]
+
   ExecutionContext* = ref object
     worker*: LightWorker
     builtin_functions: ExecFuncs
-    defined_functions: TableRef[string, seq[LightExpr]]
+    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 =
-  LightWorker()
+  let worker = LightWorker()
+  let param_ctx = new(array[MAX_STACK_HEIGHT, PContext])
+  worker.param_stack = PStack(
+    stack: param_ctx,
+    size: 1
+  )
+  worker
 
 proc MakeExecutionContext*(funcs: ExecFuncs): ExecutionContext =
   let worker = MakeEmptyWorker()
-  let defined_functions = newTable[string, seq[LightExpr]]()
+  let defined_functions = newTable[string, DefFuncs]()
   ExecutionContext(
     worker: worker,
     builtin_functions: funcs,
@@ -40,29 +70,37 @@ proc ExecuteLines(ec: ExecutionContext, lines: seq[LightExpr]): LightInt
 
 func GetVar(worker: LightWorker, variable: LightVariable): LightInt =
   case variable:
-  of var1: worker.var_1
-  of var2: worker.var_2
-  of var3: worker.var_3
-  of var4: worker.var_4
-  of var5: worker.var_5
-  of var6: worker.var_6
-  of var7: worker.var_7
-  of var8: worker.var_8
-  of varX: worker.pos_x
-  of varY: worker.pos_y
+  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 var1: worker.var_1 = value
-  of var2: worker.var_2 = value
-  of var3: worker.var_3 = value
-  of var4: worker.var_4 = value
-  of var5: worker.var_5 = value
-  of var6: worker.var_6 = value
-  of var7: worker.var_7 = value
-  of var8: worker.var_8 = value
-  of varX: worker.pos_X = value
-  of varY: worker.pos_Y = value
+  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
 
@@ -120,7 +158,28 @@ proc EvalExpr(ec: ExecutionContext, exp: LightExpr): LightInt =
       ec.builtin_functions[exp.func_name](ec, args)
 
     elif ec.defined_functions.hasKey(exp.func_name):
-      ExecuteLines(ec, ec.defined_functions[exp.func_name])
+      var args = newSeq[LightInt]()
+      for param in exp.params:
+        args.add(EvalExpr(ec, param))
+
+      var ind: int = 0
+      var params: PContext
+
+      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]
+
+        ind += 1
+
+      ec.worker.param_stack.Push(params)
+      let ret = ExecuteLines(ec, ec.defined_functions[exp.func_name].body)
+      discard ec.worker.param_stack.Pop()
+      ret
 
     else:
       raise newException(ValueError, "Cannot call undefined function: " & exp.func_name)
@@ -130,7 +189,10 @@ proc EvalExpr(ec: ExecutionContext, exp: LightExpr): LightInt =
       raise newException(ValueError, "Cannot redefine function: " & exp.def_func_name)
 
     else:
-      ec.defined_functions[exp.def_func_name] = exp.func_body
+      ec.defined_functions[exp.def_func_name] = DefFuncs(
+        params: exp.param_vars,
+        body: exp.func_body
+      )
       0
   else:
     0
index fe5bc86646216231230299b88e1299e85b6c4ee4..9192dd8e9d7f098b58d2712d0663044a10d07e3f 100644 (file)
@@ -34,16 +34,20 @@ iterator Generate_tokens*(source: string): LightToken =
         if varString == "":
           raise newException(IOError, "Expected variable name")
         else:
-          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
+          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.")
 
@@ -53,20 +57,14 @@ iterator Generate_tokens*(source: string): LightToken =
         let funcName = token[1..^1].toLowerAscii
         yield LightToken(kind: ltFunc, func_name: funcName)
 
-      elif token.startsWith('#'):
+      elif token.startsWith('@'):
         let funcName = token[1..^1].toLowerAscii
         yield LightToken(kind: ltFuncDef, func_name: funcName)
 
       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:
+      elif (token.startsWith("-") and token != "-") or token.isDigit:
         var value: int
         discard parseutils.parseInt(token, value)
 
@@ -97,6 +95,12 @@ iterator Generate_tokens*(source: string): LightToken =
           yield LightToken(kind: ltOp, operation: loDiv)
         of "%":
           yield LightToken(kind: ltOp, operation: loMod)
+        of "&":
+          yield LightToken(kind: ltOp, operation: loBitAnd)
+        of "|":
+          yield LightToken(kind: ltOp, operation: loBitOr)
+        of "^":
+          yield LightToken(kind: ltOp, operation: loBitXor)
         of "<":
           yield LightToken(kind: ltOp, operation: loLt)
         of "<=":
index 5e4fca1922523744696cd8d9d9be8c3ae567d8fa..929e2844d62c46b0061d3eda747905f8578e040e 100644 (file)
@@ -125,15 +125,34 @@ func NextExpr(tokens: Iter[LightToken], prev: LightExpr, stop_at: set[LightToken
     )
   
   elif curr.kind == ltFuncDef:
+    if tokens.Current.kind != ltLeftParen:
+      raise newException(ValueError, "Expected parameter list before function definition")
+
+    tokens.Step()
+    let params = ParseBlock(tokens, ltParamDelim, ltRightParen)
+    var param_list = newSeq[LightVariable]()
+    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)
+
+    # Allows for next line function body
+    if tokens.Current.kind == ltExprDelim:
+      tokens.Step()
+
     if tokens.Current.kind != ltBlockStart:
-      raise newException(ValueError, "Expected block start after function definition")
-    
+      raise newException(ValueError, "Expected function body")
+
     tokens.Step()
     let body = ParseBlock(tokens, ltExprDelim, ltBlockEnd)
     
     return LightExpr(
       kind: leFuncDef,
       def_func_name: curr.func_name,
+      param_vars: param_list,
       func_body: body
     )
 
index 66a587f3918f09502651e62e4447f1f89166c2b4..11ffa946dd0873a523be85b14f041e7cddb801e2 100644 (file)
@@ -38,6 +38,7 @@ type
       params*: seq[LightExpr]
     of leFuncDef:
       def_func_name*: string
+      param_vars*: seq[LightVariable]
       func_body*: seq[LightExpr]
     else: 
       discard
@@ -60,7 +61,7 @@ func printExpr(exp: LightExpr, ind: int): string =
       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 leFuncDef: "funcDef[" & exp.def_func_name & "] (" & $exp.param_vars & ") {\n" & multiline(exp.func_body, ind + 1) & "\n" & ts & "}"
       of leNull: "NullExpr[]"
       else: "UNDEFINED[]"
   )
index 306f2350d461fd9c1f2b300033dec2a8c077f580..2a9014a71a19e885485005a2dee6099680d1befb 100644 (file)
@@ -27,19 +27,6 @@ type
     else:
       discard
 
-func `$`*(variable: LightVariable): string =
-  case variable:
-  of var1: "MEM_1"
-  of var2: "MEM_2"
-  of var3: "MEM_3"
-  of var4: "MEM_4"
-  of var5: "MEM_5"
-  of var6: "MEM_6"
-  of var7: "MEM_7"
-  of var8: "MEM_8"
-  of varX: "POS_X"
-  of varY: "POS_Y"
-
 proc `$`*(token: LightToken): string =
   return
     case token.kind:
index d17d6d84d1ea57f6d542adfedf8e3e7db95d806f..487f478309b2d285dfc95ebffb0c97a1c91af074 100644 (file)
@@ -1,11 +1,30 @@
 type
   LightVariable* = enum
-    var1 = 0, var2 = 1, var3 = 2, var4 = 3,
-    var5 = 4, var6 = 5, var7 = 6, var8 = 7,
-    varX = 8, varY = 9
+    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
     
   LightOperation* = enum
     loAdd, loSub, loMul, loDiv, loMod,
+    loBitAnd, loBitOr, loBitXor,
     loGt, loGte, loLt, loLte, loEq, loNeq
 
   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"
index 86ee900f9ab713b6b0febbcb3c9c3c409156d376..42dd643cbc6c85dc327b96e7afba6fc19e929c45 100644 (file)
@@ -7,6 +7,9 @@ proc EvalOperation*(operation: LightOperation, left, right: LightInt): LightInt
     of loMul: left * right
     of loDiv: left div right
     of loMod: left mod right
+    of loBitAnd: left and right
+    of loBitOr: left or right
+    of loBitXor: left xor right
     of loGt:
       if left > right: 1
       else: 0