From: Brendan Hansen Date: Mon, 17 Dec 2018 08:14:41 +0000 (-0600) Subject: function parameters with scope; slight syntax change X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=4d2689c54e998341447997f64b7b7fcf61f535cb;p=light.git function parameters with scope; slight syntax change --- diff --git a/christmas_proj b/christmas_proj index f355762..b4796ba 100755 Binary files a/christmas_proj and b/christmas_proj differ diff --git a/data/progs/avg.lgt b/data/progs/avg.lgt index db38f06..3128585 100644 --- a/data/progs/avg.lgt +++ b/data/progs/avg.lgt @@ -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 diff --git a/data/progs/gol.lgt b/data/progs/gol.lgt index 933492c..40c1fbf 100644 --- a/data/progs/gol.lgt +++ b/data/progs/gol.lgt @@ -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 diff --git a/data/progs/maze.lgt b/data/progs/maze.lgt index 4cc1bbf..f450a50 100644 --- a/data/progs/maze.lgt +++ b/data/progs/maze.lgt @@ -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 index 0000000..48ff7a1 --- /dev/null +++ b/data/progs/new_syntax.light @@ -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) diff --git a/src/lang/executer.nim b/src/lang/executer.nim index b612f93..cb76310 100644 --- a/src/lang/executer.nim +++ b/src/lang/executer.nim @@ -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 diff --git a/src/lang/lexer.nim b/src/lang/lexer.nim index fe5bc86..9192dd8 100644 --- a/src/lang/lexer.nim +++ b/src/lang/lexer.nim @@ -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 "<=": diff --git a/src/lang/parser.nim b/src/lang/parser.nim index 5e4fca1..929e284 100644 --- a/src/lang/parser.nim +++ b/src/lang/parser.nim @@ -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 ) diff --git a/src/lang/types/ast.nim b/src/lang/types/ast.nim index 66a587f..11ffa94 100644 --- a/src/lang/types/ast.nim +++ b/src/lang/types/ast.nim @@ -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[]" ) diff --git a/src/lang/types/tokens.nim b/src/lang/types/tokens.nim index 306f235..2a9014a 100644 --- a/src/lang/types/tokens.nim +++ b/src/lang/types/tokens.nim @@ -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: diff --git a/src/lang/types/types.nim b/src/lang/types/types.nim index d17d6d8..487f478 100644 --- a/src/lang/types/types.nim +++ b/src/lang/types/types.nim @@ -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" diff --git a/src/lang/utils.nim b/src/lang/utils.nim index 86ee900..42dd643 100644 --- a/src/lang/utils.nim +++ b/src/lang/utils.nim @@ -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