Spaces:
Runtime error
Runtime error
| import os | |
| from lexer import Lexer | |
| from parser_ast import Parser | |
| from semantic_analyzer import SemanticAnalyzer | |
| from optimizer import Optimizer | |
| from icg import ICG | |
| from code_gen import CodeGen | |
| class AssemblyVM: | |
| def __init__(self): | |
| self.memory = {} | |
| self.accumulator = 0 | |
| def _get_val(self, target): | |
| try: | |
| if '.' in target: return float(target) | |
| return int(target) | |
| except ValueError: | |
| return self.memory.get(target, 0) | |
| def execute(self, asm_instructions): | |
| print("\n--- RUNTIME LIVE EXECUTION OUTPUT ---") | |
| for line in asm_instructions: | |
| parts = line.split() | |
| if not parts: continue | |
| cmd = parts[0] | |
| if cmd == "LOAD": | |
| self.accumulator = self._get_val(parts[1]) | |
| elif cmd == "STORE": | |
| self.memory[parts[1]] = self.accumulator | |
| elif cmd == "ADD": | |
| self.accumulator += self._get_val(parts[1]) | |
| elif cmd == "SUB": | |
| self.accumulator -= self._get_val(parts[1]) | |
| elif cmd == "MUL": | |
| self.accumulator *= self._get_val(parts[1]) | |
| elif cmd == "DIV": | |
| divisor = self._get_val(parts[1]) | |
| self.accumulator = (self.accumulator // divisor) if divisor != 0 else 0 | |
| elif cmd == "OUT": | |
| print(f"[ASM OUT]: {self.accumulator}") | |
| print("-" * 37) | |
| # --- NEW HELPER: Scans the AST for any PRINT nodes --- | |
| def contains_print(ast_nodes): | |
| for node in ast_nodes: | |
| if node[0] == 'PRINT': | |
| return True | |
| if node[0] == 'BLOCK' and contains_print(node[1]): | |
| return True | |
| return False | |
| def compile_code(input_data): | |
| if os.path.exists(input_data) and input_data.endswith('.txt'): | |
| with open(input_data, "r") as f: | |
| source_code = f.read() | |
| else: | |
| source_code = input_data | |
| lexer = Lexer(source_code) | |
| parser = Parser(lexer.tokens) | |
| ast = parser.parse() | |
| semantic = SemanticAnalyzer() | |
| sem_errors = semantic.check(ast) | |
| all_errors = lexer.errors + parser.errors + sem_errors | |
| if all_errors: | |
| print("\n[!] COMPILATION ERRORS:") | |
| for err in all_errors: | |
| print(f" -> {err}") | |
| return | |
| optimizer = Optimizer() | |
| opt_ast = optimizer.optimize(ast) | |
| icg = ICG() | |
| tac = icg.generate(opt_ast) | |
| codegen = CodeGen() | |
| asm = codegen.generate_asm(tac) | |
| # --- FIXED: Only print output if a PRINT function exists in the code --- | |
| if contains_print(ast): | |
| print("\n" + "="*30) | |
| print(" COMPILATION SUCCESSFUL ") | |
| print("="*30) | |
| if tac: | |
| print("\n--- THREE ADDRESS CODE (TAC) ---") | |
| for line in tac: | |
| print(f" {line}") | |
| if asm: | |
| print("\n--- TARGET ASSEMBLY (Simple ASM) ---") | |
| for line in asm: | |
| print(f" {line}") | |
| print("="*30 + "\n") | |
| if asm: | |
| vm = AssemblyVM() | |
| vm.execute(asm) | |
| else: | |
| # No print function found -> Remain completely silent | |
| pass | |
| if __name__ == "__main__": | |
| # Test code with print | |
| test_code = "int x = 5 + 5; { print(x); }" | |
| compile_code(test_code) |