From 87de3892cd063666c368b3fee3afa901624f4f3f Mon Sep 17 00:00:00 2001 From: Nirei Date: Thu, 2 Jan 2025 20:24:03 +0100 Subject: [PATCH] chore: stack-based arithmetics --- src/executor.py | 20 +++++++++----------- src/grammar.py | 17 +++++++---------- src/parser.py | 14 +++++++------- src/preprocessor.py | 8 +++++--- src/visitor.py | 16 +++++----------- tests/add.imp | 3 ++- tests/divide.imp | 3 ++- tests/multiply.imp | 3 ++- tests/negate.imp | 3 ++- tests/or.imp | 3 ++- tests/subtract.imp | 3 ++- tests/xor.imp | 3 ++- 12 files changed, 47 insertions(+), 49 deletions(-) diff --git a/src/executor.py b/src/executor.py index 017f981..db6634f 100644 --- a/src/executor.py +++ b/src/executor.py @@ -24,27 +24,27 @@ def execute_block(self, block, bindings: Bindings): return True def instruction_add(self, args, bindings): - value, (_, target) = args + ((_, target),) = args + current = self.stack.pop() old = bindings.resolve(target) - current = self.resolve_value(value, bindings) bindings.assign(target, old + current) def instruction_subtract(self, args, bindings): - value, (_, target) = args + ((_, target),) = args + current = self.stack.pop() old = bindings.resolve(target) - current = self.resolve_value(value, bindings) bindings.assign(target, old - current) def instruction_multiply(self, args, bindings): - value, (_, target) = args + ((_, target),) = args + current = self.stack.pop() old = bindings.resolve(target) - current = self.resolve_value(value, bindings) bindings.assign(target, old * current) def instruction_divide(self, args, bindings): - value, (_, target) = args + ((_, target),) = args + current = self.stack.pop() old = bindings.resolve(target) - current = self.resolve_value(value, bindings) bindings.assign(target, old // current) def instruction_and(self, args, bindings): @@ -139,9 +139,7 @@ def instruction_load(self): for pos in reversed(temp_positions): if pos < 0 or pos >= len(self.heap): - raise InvalidMemoryAddressException( - f"Invalid memory access at position: {pos}" - ) + raise InvalidMemoryAddressException(f"Invalid memory access at position: {pos}") value = self.heap[pos] self.stack.append(value) diff --git a/src/grammar.py b/src/grammar.py index 393a7ce..0f21e38 100644 --- a/src/grammar.py +++ b/src/grammar.py @@ -5,17 +5,15 @@ 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 = assignment / conditional / loop / stack_op - / arithmetic_op / boolean_op / io_op / stop / identifier - / halt / store / load + instruction = assignment / conditional / loop / stack / op / io / stop + / identifier / halt / store / load assignment = let sp_1n identifier 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_op = (push sp_1n value) / (pop sp_1n identifier) - arithmetic_op = (add / subtract / multiply / divide) sp_1n value sp_1n identifier - boolean_op = (and / or / xor / negate / not) sp_1n identifier - io_op = print sp_1n value + stack = (push sp_1n value) / (pop sp_1n identifier) + op = (add / subtract / multiply / divide / and / or / xor / negate / not) sp_1n identifier + io = print sp_1n value halt = exit sp_1n value value = identifier / literal @@ -37,9 +35,8 @@ sp_1n = ~r"[ \t]+" reserved = begin / end / stop / if / elif / else / while / push - / pop / let / add / subtract / multiply - / divide / and / or / xor / not / print / exit / store - / load + / pop / let / add / subtract / multiply / divide / and + / or / xor / not / print / exit / store / load begin = ~r"begin"i / ~r"do"i exit = ~r"exit"i end = ~r"end"i diff --git a/src/parser.py b/src/parser.py index 966adbc..74b756d 100755 --- a/src/parser.py +++ b/src/parser.py @@ -2,9 +2,9 @@ import argparse import pprint -import grammar as grammar -import visitor as visitor -from preprocessor import PipelinePreprocessor, CommentsPreprocessor +import grammar +import visitor +import preprocessor class ImperivmParser: @@ -12,13 +12,13 @@ def __init__( self, grammar=grammar.imperivm, visitor=visitor.ImperivmVisitor(), - preprocessor=None, + preprocessor=preprocessor.PipelinePreprocessor( + [preprocessor.CommentsPreprocessor()] + ), ): self.grammar = grammar self.visitor = visitor - self.preprocessor = preprocessor or PipelinePreprocessor( - [CommentsPreprocessor()] - ) + self.preprocessor = preprocessor def parse(self, program): program = self.preprocessor.process(program) diff --git a/src/preprocessor.py b/src/preprocessor.py index 56679c3..d74f943 100644 --- a/src/preprocessor.py +++ b/src/preprocessor.py @@ -5,14 +5,16 @@ class Preprocessor(ABC): @abstractmethod - def process(self, program: str) -> str: + def process(self, program: str): pass class CommentsPreprocessor(Preprocessor): @override def process(self, program: str): - cleaned_program = map(lambda line: re.sub(r"#.*$", "", line), program.splitlines()) + cleaned_program = map( + lambda line: re.sub(r"#.*$", "", line), program.splitlines() + ) return "\n".join(cleaned_program) @@ -24,4 +26,4 @@ def __init__(self, preprocessor_actions: List[Preprocessor]): def process(self, program: str): for action in self.preprocessor_actions: program = action.process(program) - return program \ No newline at end of file + return program diff --git a/src/visitor.py b/src/visitor.py index 40435d7..f298cce 100644 --- a/src/visitor.py +++ b/src/visitor.py @@ -38,9 +38,7 @@ def visit_assignment(self, _, visited_children): return instruction.text, target def visit_conditional(self, _, visited_children): - operation, _, condition, _, block, elif_operations, else_operations = ( - visited_children - ) + operation, _, condition, _, block, elif_operations, else_operations = visited_children elif_tree = [] if type(elif_operations) is list: @@ -59,20 +57,16 @@ def visit_loop(self, _, visited_children): operation, _, condition, _, block = visited_children return operation.text, condition, block - def visit_stack_op(self, _, visited_children): + def visit_stack(self, _, visited_children): [child] = visited_children operation, _, target = child return operation.text, target - def visit_arithmetic_op(self, _, visited_children): - [operation], _, value, _, target = visited_children - return operation.text, value, target - - def visit_boolean_op(self, _, visited_children): + def visit_op(self, _, visited_children): [operation], _, target = visited_children return operation.text, target - def visit_io_op(self, _, visited_children): + def visit_io(self, _, visited_children): operation, _, target = visited_children return operation.text, target @@ -103,5 +97,5 @@ def visit_identifier(self, node, _): return "id", node.text def generic_visit(self, node, visited_children): - """The generic visit method.""" + """the generic visit method""" return visited_children or node diff --git a/tests/add.imp b/tests/add.imp index c4bc64f..ab42c78 100644 --- a/tests/add.imp +++ b/tests/add.imp @@ -2,7 +2,8 @@ main begin push -5 let x - add 5 x + push 5 + add x exit x exit 1 end \ No newline at end of file diff --git a/tests/divide.imp b/tests/divide.imp index 07cb8ca..02fbe36 100644 --- a/tests/divide.imp +++ b/tests/divide.imp @@ -2,7 +2,8 @@ main begin push 0 let x - divide 14884 x + push 14884 + divide x exit x exit 1 end \ No newline at end of file diff --git a/tests/multiply.imp b/tests/multiply.imp index 8b869be..86bb711 100644 --- a/tests/multiply.imp +++ b/tests/multiply.imp @@ -2,7 +2,8 @@ main begin push 84781 let x - multiply 0 x + push 0 + multiply x exit x exit 1 end \ No newline at end of file diff --git a/tests/negate.imp b/tests/negate.imp index 64540e6..4ee4b9f 100644 --- a/tests/negate.imp +++ b/tests/negate.imp @@ -3,7 +3,8 @@ main begin let x negate x - add 2 x + push 2 + add x if x do exit 1 diff --git a/tests/or.imp b/tests/or.imp index 18758a0..e34578a 100644 --- a/tests/or.imp +++ b/tests/or.imp @@ -4,7 +4,8 @@ main begin push 2 or x - subtract 3 x + push 3 + subtract x if x do exit 1 diff --git a/tests/subtract.imp b/tests/subtract.imp index 85f88a1..d5fb219 100644 --- a/tests/subtract.imp +++ b/tests/subtract.imp @@ -2,7 +2,8 @@ main begin push 5 let x - subtract 5 x + push 5 + subtract x exit x exit 1 end \ No newline at end of file diff --git a/tests/xor.imp b/tests/xor.imp index 8d8a36d..f198b54 100644 --- a/tests/xor.imp +++ b/tests/xor.imp @@ -4,7 +4,8 @@ main begin push 3 xor x - subtract 2 x + push 2 + subtract x if x do exit 1