From: Brendan Hansen Date: Sun, 16 Dec 2018 16:14:59 +0000 (-0600) Subject: breaks work; refactor parser; operation tree reduction X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=145e7ceafce5ca20df064d1f0e811550632dac16;p=light.git breaks work; refactor parser; operation tree reduction --- diff --git a/christmas_proj b/christmas_proj index 9bafaa9..f355762 100755 Binary files a/christmas_proj and b/christmas_proj differ diff --git a/data/progs/gol.lgt b/data/progs/gol.lgt index f6dd1a4..933492c 100644 --- a/data/progs/gol.lgt +++ b/data/progs/gol.lgt @@ -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 } diff --git a/data/progs/maze.lgt b/data/progs/maze.lgt index 237f0c2..4cc1bbf 100644 --- a/data/progs/maze.lgt +++ b/data/progs/maze.lgt @@ -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() diff --git a/src/lang/executer.nim b/src/lang/executer.nim index 7be2cf1..b612f93 100644 --- a/src/lang/executer.nim +++ b/src/lang/executer.nim @@ -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 = diff --git a/src/lang/parser.nim b/src/lang/parser.nim index 932e4b9..5e4fca1 100644 --- a/src/lang/parser.nim +++ b/src/lang/parser.nim @@ -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 index 0000000..86ee900 --- /dev/null +++ b/src/lang/utils.nim @@ -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