From 64061d8b798ef9bb715f3dd1f42f5931abfcb18b Mon Sep 17 00:00:00 2001 From: Jan-Niclas Loosen Date: Sat, 18 Oct 2025 13:16:52 +0200 Subject: [PATCH] Clean up codes --- Uebung-01/MaMa.py | 63 ++++++++++++++++++++++++-------------------- Uebung-01/MaMaGUI.py | 6 ++--- Uebung-01/MaMaMa.py | 27 ++++++++++++------- 3 files changed, 55 insertions(+), 41 deletions(-) diff --git a/Uebung-01/MaMa.py b/Uebung-01/MaMa.py index e5b068e..930b497 100644 --- a/Uebung-01/MaMa.py +++ b/Uebung-01/MaMa.py @@ -1,14 +1,22 @@ from typing import Dict, Optional, Tuple, List, Any class MaMa: - def __init__(self, prog: Dict[int, str] | List[str], - stack: Dict[int, int] | List[int] | None = None) -> None: - self.steps = 0 - self.prog = {i: instr for i, instr in enumerate(prog)} if isinstance(prog, list) else prog - self.p_prog = 0 - self.stack: Dict[int, int] = {} - self.p_stack = -1 + def __init__(self, prog: Dict[int, str] | List[str], stack: Dict[int, int] | List[int] | None = None) -> None: + self.step_counter = 0 self.halted = False + + # Init prog from list or dict + self.p_prog = 0 + if isinstance(prog, list): + self.prog = {i: micro for i, micro in enumerate(prog)} + else: + self.prog = prog + + # Default stack + self.p_stack = -1 + self.stack: Dict[int, int] = {} + + # Init custom stack from list or dict if stack is not None: if isinstance(stack, list): self.stack = {i: v for i, v in enumerate(stack)} @@ -17,8 +25,7 @@ class MaMa: self.p_stack = max(self.stack.keys(), default=-1) self.initial_stack = dict(self.stack) - # ------------------------------------------------------------- - + # Runs the machine and returns execution journal def run(self, max_steps: int = 1000) -> List[Dict[str, int | str | dict | list]]: steps = 0 # always insert init configuration as step 0 @@ -28,48 +35,48 @@ class MaMa: steps += 1 return journal - # ------------------------------------------------------------- - + # Returns the full program def structure(self) -> Dict[int, Dict[str, Any]]: - return {i: {"call": call, "macros": []} for i, call in sorted(self.prog.items())} + return {i: {"micro": micro, "macros": []} for i, micro in sorted(self.prog.items())} + # Decodes string MaMa instructions to function callables @staticmethod - def decode(call: str) -> Tuple[str, Optional[List[int]]]: - if "(" in call: - name, rest = call.split("(", 1) + def decode(micro: str) -> Tuple[str, Optional[List[int]]]: + if "(" in micro: + name, rest = micro.split("(", 1) args_str = rest[:-1] if args_str.strip() == "": return name, [] args = [int(a.strip()) for a in args_str.split(",")] return name, args - return call, None + return micro, None - # ------------------------------------------------------------- - - def config(self, call: str) -> Dict[str, int | str | dict | list]: + # Generates journal entry for a step + def config(self, micro: str) -> Dict[str, int | str | dict | list]: return { - "step": self.steps, - "call": call, + "step": self.step_counter, + "micro": micro, "p_prog": self.p_prog, "p_stack": self.p_stack, "stack": dict(self.stack), } - # ------------------------------------------------------------- - + # Executes one step of the machine def __step(self) -> Dict[str, int | str | dict | list]: if self.halted or self.p_prog not in self.prog: self.halted = True return self.config("halted") - call = self.prog[self.p_prog] - name, args = MaMa.decode(call) + micro = self.prog[self.p_prog] + name, args = MaMa.decode(micro) method = getattr(self, f"_{name}", None) if method is None: - raise ValueError(f"Unknown instruction: {call}") + raise ValueError(f"Unknown instruction: {micro}") method(args) - self.steps += 1 - return self.config(call) + self.step_counter += 1 + return self.config(micro) + + # DEFINE MaMa Micros # Stop execution def _stop(self, _: Optional[int]) -> None: diff --git a/Uebung-01/MaMaGUI.py b/Uebung-01/MaMaGUI.py index 6fc6713..fefd492 100644 --- a/Uebung-01/MaMaGUI.py +++ b/Uebung-01/MaMaGUI.py @@ -74,7 +74,7 @@ class MaMaGUI: state = self.journal[self.journal_index] stack = dict(state["stack"]) p_prog, p_stack = int(state["p_prog"]), int(state["p_stack"]) - step, call = int(state["step"]), str(state["call"]) + step, micro = int(state["step"]), str(state["micro"]) # Load code structure structure = self.machine.structure() @@ -96,7 +96,7 @@ class MaMaGUI: instr_indent = " " * depth prefix = ">> " if addr == p_prog else " " - line = f"{prefix}{instr_indent}{addr:>3}: {info['call']}" + line = f"{prefix}{instr_indent}{addr:>3}: {info['micro']}" self.prog_list.insert(tk.END, line) opened_macros = macros @@ -118,7 +118,7 @@ class MaMaGUI: # Update configuration and global stack self.conf_label.config(text=f"({p_stack}, {p_prog}, {list(stack.values())})") - self.status.config(text=f"Step {step}/{len(self.journal)-1} | PC={p_prog} | SP={p_stack} | Call: {call}") + self.status.config(text=f"Step {step}/{len(self.journal)-1} | PC={p_prog} | SP={p_stack} | Micro: {micro}") # Configure auto step speed def __update_speed(self, value: str) -> None: diff --git a/Uebung-01/MaMaMa.py b/Uebung-01/MaMaMa.py index 1219c13..7a9c818 100644 --- a/Uebung-01/MaMaMa.py +++ b/Uebung-01/MaMaMa.py @@ -1,42 +1,49 @@ -from typing import Dict, Optional, List, Any, Tuple +from typing import Dict, Optional, List, Any, Tuple, override from MaMa import MaMa class MaMaMa(MaMa): def __init__(self, prog, stack=None) -> None: + # Store macros self.macros: Dict[str, Dict[str, Any]] = {} self.initial_macros: Dict[str, Dict[str, Any]] = {} + + # Trace nested macros self._macro_trace: Dict[int, List[str]] = {} super().__init__(prog, stack) + # Register a new macro, which is a name and a sequence of micros def add_macro(self, name: str, prog: List[str] | Dict[int, str], args: List[str] = None) -> None: if isinstance(prog, list): prog = {i: instr for i, instr in enumerate(prog)} self.macros[name] = {"prog": prog, "args": args} self.initial_macros[name] = dict(self.macros[name]) + # Automatically flatten macros and then execute + @override def run(self, max_steps: int = 1000): - # automatically flatten macros before execution - self._expand_macros_into_prog() + self.__flatten_macro() return super().run(max_steps) - # --- flatten macros recursively before execution --- - def _expand_macros_into_prog(self) -> None: + # Flatten macros recursively + def __flatten_macro(self) -> None: def expand(prog: Dict[int, str], stack: List[str]) -> List[Tuple[str, List[str]]]: out: List[Tuple[str, List[str]]] = [] - for _, call in sorted(prog.items()): - name, args = self.decode(call) + for _, micro in sorted(prog.items()): + name, args = self.decode(micro) if name in self.macros: out.extend(expand(self.macros[name]["prog"], stack + [name])) else: - out.append((call, list(stack))) + out.append((micro, list(stack))) return out expanded = expand(self.prog, []) self.prog = {i: call for i, (call, _) in enumerate(expanded)} self._macro_trace = {i: macros for i, (_, macros) in enumerate(expanded)} + # Add macros to structure + @override def structure(self) -> Dict[int, Dict[str, Any]]: return { - i: {"call": call, "macros": self._macro_trace.get(i, []), "p_prog": self.p_prog} - for i, call in sorted(self.prog.items()) + i: {"micro": micro, "macros": self._macro_trace.get(i, []), "p_prog": self.p_prog} + for i, micro in sorted(self.prog.items()) }