diff --git a/src/executor.py b/src/executor.py index 32ed2bd..c1ed52c 100644 --- a/src/executor.py +++ b/src/executor.py @@ -29,6 +29,9 @@ def __init__(self, ast): "xor": self.instruction_xor, "negate": self.instruction_negate, "not": self.instruction_not, + "equal": self.instruction_equal, + "greater": self.instruction_greater, + "lesser": self.instruction_lesser, "if": self.instruction_if, "while": self.instruction_while, "exit": lambda args, bindings: exit(self.resolve_value(args[0], bindings)), @@ -112,7 +115,25 @@ def instruction_negate(self, args, bindings): def instruction_not(self, args, bindings): ((_, target),) = args old = bindings.resolve(target) - bindings.assign(target, 0 if old else 1) + bindings.assign(target, not old) + + def instruction_equal(self, args, bindings): + ((_, target),) = args + argument = self.stack.pop() + old = bindings.resolve(target) + bindings.assign(target, old == argument) + + def instruction_greater(self, args, bindings): + ((_, target),) = args + argument = self.stack.pop() + old = bindings.resolve(target) + bindings.assign(target, old > argument) + + def instruction_lesser(self, args, bindings): + ((_, target),) = args + argument = self.stack.pop() + old = bindings.resolve(target) + bindings.assign(target, old < argument) def instruction_if(self, args, bindings): for index in range(0, len(args) - 1, 2): @@ -183,6 +204,9 @@ def resolve_value(self, value, bindings: Bindings): if kind == "id": return bindings.resolve(content) + if kind == "boolean": + return content == "true" + return content def invoke_subroutine(self, name, bindings: Bindings): diff --git a/src/grammar.py b/src/grammar.py index bcf48e0..cff9122 100644 --- a/src/grammar.py +++ b/src/grammar.py @@ -5,24 +5,28 @@ program = ws_0n subroutine (sp_0n br ws_0n subroutine)* ws_0n subroutine = identifier ws_1n block block = begin ws_1n (instruction (sp_0n br ws_0n instruction)*)? ws_1n end - instruction = conditional / loop / stack / op / io / stop - / identifier / halt / store / load + instruction = conditional / loop / stack / op / io / stop / identifier + / halt / store / load - conditional = if sp_1n value ws_1n block (ws_1n elif sp_1n value ws_1n block)* (ws_1n else ws_1n block)? + conditional = if sp_1n value ws_1n + block (ws_1n elif sp_1n value ws_1n block)* + (ws_1n else ws_1n block)? loop = while sp_1n value ws_1n block stack = (push sp_1n value) / (pop sp_1n identifier) - op = (add / subtract / multiply / divide / and / or / xor / negate / not) sp_1n identifier + op = (add / subtract / multiply / divide / and / or / xor + / negate / not / equal / greater / lesser) sp_1n identifier io = print sp_1n value halt = exit sp_1n value value = identifier / literal - literal = integer / float / string + literal = integer / float / string / boolean identifier = !reserved ~r"[a-z][a-z0-9_]*"i integer = ~r"-?(0|([1-9][0-9]*))" float = ~r"-?(0|([1-9][0-9]*))\.[0-9]+" string = quote string_text quote + boolean = true / false quote = "\"" string_text = ~r"([^\"\\]|\\.)*" @@ -35,7 +39,8 @@ reserved = begin / end / stop / if / elif / else / while / push / pop / add / subtract / multiply / divide / and - / or / xor / not / print / exit / store / load + / or / xor / not / print / exit / store / load / true + / false / equal / greater / lesser begin = ~r"begin"i / ~r"do"i exit = ~r"exit"i end = ~r"end"i @@ -58,5 +63,10 @@ print = ~r"print"i store = ~r"store"i load = ~r"load"i + true = ~r"true"i + false = ~r"false"i + equal = ~r"equal"i + greater = ~r"greater"i + lesser = ~r"lesser"i """ ) diff --git a/src/visitor.py b/src/visitor.py index ad0e7ad..8920c4d 100644 --- a/src/visitor.py +++ b/src/visitor.py @@ -69,7 +69,7 @@ def visit_io(self, _, visited_children): def visit_stop(self, _, __): return ("stop",) - def visit_halt(self, node, visited_children): + def visit_halt(self, _, visited_children): operation, _, status_code = visited_children return operation.text, status_code @@ -89,6 +89,9 @@ def visit_integer(self, node, _): def visit_float(self, node, _): return "float", float(node.text) + def visit_boolean(self, node, _): + return "boolean", node.text + def visit_identifier(self, node, _): return "id", node.text diff --git a/tests/add.imp b/tests/add.imp index 3851832..aa984a5 100644 --- a/tests/add.imp +++ b/tests/add.imp @@ -1,9 +1,15 @@ -main - begin - push -5 - pop x - push 5 - add x - exit x - exit 1 - end \ No newline at end of file +main begin + push 37 + pop x + + push 5 + add x + + push 42 + equal x + + if x do + exit 0 + end + exit 1 +end \ No newline at end of file diff --git a/tests/not.imp b/tests/not.imp index c37798e..1355c0c 100644 --- a/tests/not.imp +++ b/tests/not.imp @@ -1,5 +1,5 @@ main begin - push 1 + push true pop x not x @@ -7,7 +7,7 @@ main begin exit 1 end - push 0 + push false pop x not x