diff options
Diffstat (limited to 'awk/vm/compiler.py')
-rwxr-xr-x | awk/vm/compiler.py | 82 |
1 files changed, 65 insertions, 17 deletions
diff --git a/awk/vm/compiler.py b/awk/vm/compiler.py index 4cd7b83..a406779 100755 --- a/awk/vm/compiler.py +++ b/awk/vm/compiler.py @@ -38,21 +38,38 @@ class Compiler: def compile_assignment(self, line): """Compile assignment statements like 'x = 5' or 'x = y + z'""" + # Remove any comments from the line + line = line.split('#')[0].strip() + match = re.match(r'(\w+)\s*=\s*(.+)', line) if not match: return None - + var_name = match.group(1) expression = match.group(2) - # Allocate memory for the variable + print(f"# Compiling assignment: {var_name} = {expression}", file=sys.stderr) + + # First get the memory location mem_loc = self.allocate_variable(var_name) - # Compile the right-hand expression - vm_code = self.compile_expression(expression) + # Then compile the expression + expr_code = self.compile_expression(expression) + if not expr_code: + print(f"# Error: Failed to compile expression: {expression}", file=sys.stderr) + return None - # Store result in variable's memory location - vm_code.append(f"{mem_loc} !") + # Generate code that: + # 1. Evaluates the expression + # 2. Duplicates the result (for storing and leaving on stack) + # 3. Stores at memory location + vm_code = [] + vm_code.extend(expr_code) # Evaluate expression + vm_code.append("DUP") # Make a copy + vm_code.append(str(mem_loc)) # Push memory location + vm_code.append("@") # Read current value (for debugging) + vm_code.append("DROP") # Drop the old value + vm_code.append("!") # Store new value return vm_code @@ -60,6 +77,9 @@ class Compiler: """Compile expressions like '5', 'x + y', etc.""" vm_code = [] + # Remove any comments from the expression + expr = expr.split('#')[0].strip() + # Handle simple number if expr.isdigit(): vm_code.append(expr) @@ -74,39 +94,67 @@ class Compiler: # Handle binary operations ops = { '+': '+', - '*': '2*', # Note: This is a simplification - '-': 'NOT +', # This is a hack, proper subtraction would need more + '*': '*', + '-': 'NOT +', } + # Try each operator for op in ops: if op in expr: - left, right = expr.split(op) - vm_code.extend(self.compile_expression(left.strip())) - vm_code.extend(self.compile_expression(right.strip())) - vm_code.append(ops[op]) - return vm_code + parts = expr.split(op, 1) + if len(parts) == 2: + left = parts[0].strip() + right = parts[1].strip() + + print(f"# Debug: left={left}, right={right}", file=sys.stderr) + + # Generate code for left operand + left_code = self.compile_expression(left) + if not left_code: + continue + vm_code.extend(left_code) + + # Generate code for right operand + right_code = self.compile_expression(right) + if not right_code: + continue + vm_code.extend(right_code) + + # Add the operation + vm_code.append(ops[op]) + return vm_code return vm_code def compile(self, source): """Compile source code to VM instructions""" output = [] + debug_output = [] for line in source.split('\n'): - # Skip empty lines and comments line = line.strip() if not line or line.startswith('#'): continue - # Handle assignment + if line == "SHOW": + output.append("SHOW") + continue + if '=' in line: vm_code = self.compile_assignment(line) if vm_code: output.extend(vm_code) + debug_output.append(f"{' '.join(vm_code)} # {line}") + if not line.startswith('result ='): # If not final result + output.append("DROP") # Drop the duplicate we left on stack continue + + print("# Generated VM code:", file=sys.stderr) + for line in debug_output: + print(f"# {line}", file=sys.stderr) - # Other statement types can be added here - + # Add final SHOW to see the result + output.append("SHOW") return ' '.join(output) def main(): |