-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathexecution_engine.py
More file actions
235 lines (192 loc) · 8.61 KB
/
Copy pathexecution_engine.py
File metadata and controls
235 lines (192 loc) · 8.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
"""
Execution Engine for OverKill
Executes parsed instructions on the virtual machine
"""
from typing import Optional
import time
from language_parser import *
from virtual_machine import VirtualMachine, VMError
class ExecutionEngine:
"""Executes OverKill programs"""
def __init__(self, vm: VirtualMachine, program: Program):
self.vm = vm
self.program = program
self.step_mode = False
self.current_instruction = 0
self.current_section = None
def execute_instruction(self, instruction: Instruction) -> bool:
"""Execute a single instruction. Returns True to continue, False to stop."""
try:
if isinstance(instruction, ModeInstruction):
self.vm.mode = instruction.mode
self.vm.add_log(f"Mode set to: {instruction.mode}")
elif isinstance(instruction, SetRegInstruction):
x, y = self.vm.resolve_coordinate(instruction.coord)
self.vm.write_memory(x, y, instruction.value)
if instruction.name:
self.vm.config.named_registers[instruction.name] = (x, y, instruction.reg_type)
elif isinstance(instruction, ReadInstruction):
x, y = self.vm.resolve_coordinate(instruction.coord)
value = self.vm.read_memory(x, y)
self.vm.variables[instruction.variable] = value
self.vm.add_log(f"Read: {instruction.variable} = {value} from ({x}, {y})")
elif isinstance(instruction, WriteInstruction):
if instruction.variable not in self.vm.variables:
self.vm.add_warning(f"Variable '{instruction.variable}' not initialized")
value = 0
else:
value = self.vm.variables[instruction.variable]
x, y = self.vm.resolve_coordinate(instruction.coord)
self.vm.write_memory(x, y, value)
elif isinstance(instruction, WhenInstruction):
# Evaluate condition
result = self.evaluate_condition(instruction.condition)
if result:
for inst in instruction.then_block:
if not self.execute_instruction(inst):
return False
else:
for inst in instruction.else_block:
if not self.execute_instruction(inst):
return False
elif isinstance(instruction, WaitInstruction):
self.vm.add_log(f"Wait: {instruction.milliseconds}ms")
# For teaching purposes, we don't actually wait
# Just log it
elif isinstance(instruction, RepeatForeverInstruction):
self.vm.repeat_forever = True
self.vm.add_log("Repeat forever enabled")
elif isinstance(instruction, WatchInstruction):
x, y = self.vm.resolve_coordinate(instruction.coord)
self.vm.set_watchpoint(x, y, instruction.watch_type)
return True
except VMError as e:
# Error already logged by VM
return False
except Exception as e:
self.vm.add_error(f"Execution error: {str(e)}")
return False
def evaluate_condition(self, condition: str) -> bool:
"""Evaluate a condition string"""
condition = condition.strip()
# Handle logical operators
if ' and ' in condition:
parts = condition.split(' and ', 1)
return self.evaluate_condition(parts[0]) and self.evaluate_condition(parts[1])
if ' or ' in condition:
parts = condition.split(' or ', 1)
return self.evaluate_condition(parts[0]) or self.evaluate_condition(parts[1])
# Handle comparison operators
for op in ['==', '!=', '<=', '>=', '<', '>']:
if op in condition:
parts = condition.split(op, 1)
left = self.get_value(parts[0].strip())
right = self.get_value(parts[1].strip())
if op == '==':
return left == right
elif op == '!=':
return left != right
elif op == '<':
return left < right
elif op == '>':
return left > right
elif op == '<=':
return left <= right
elif op == '>=':
return left >= right
# Simple boolean value
return self.get_value(condition) != 0
def get_value(self, expr: str) -> Any:
"""Get value from expression (variable or literal)"""
expr = expr.strip()
# Check if it's a variable
if expr in self.vm.variables:
return self.vm.variables[expr]
# Try to parse as integer
try:
return int(expr)
except:
pass
# Try to parse as boolean
if expr.lower() == 'true':
return True
elif expr.lower() == 'false':
return False
return 0
def execute_section(self, section: List[Instruction]) -> bool:
"""Execute a section of instructions"""
for instruction in section:
if not self.vm.running or self.vm.paused:
return False
if not self.execute_instruction(instruction):
return False
if self.step_mode:
return True # Pause after each instruction in step mode
return True
def run(self):
"""Run the complete program"""
self.vm.running = True
self.vm.add_log("=== Starting execution ===")
# Execute First section
self.vm.add_log("=== Executing First section ===")
self.current_section = "First"
if not self.execute_section(self.program.first_section):
self.vm.running = False
return
# Execute Second section
self.vm.add_log("=== Executing Second section ===")
self.current_section = "Second"
# Check if repeat forever is in the Second section
has_repeat = any(isinstance(inst, RepeatForeverInstruction)
for inst in self.program.second_section)
if has_repeat:
# Execute Second section in a loop
iteration = 0
max_iterations = 10000 # Safety limit
while self.vm.running and not self.vm.paused and iteration < max_iterations:
if not self.execute_section(self.program.second_section):
break
iteration += 1
if self.step_mode:
break
if iteration >= max_iterations:
self.vm.add_warning("Maximum iterations reached (10000)")
else:
# Execute Second section once
self.execute_section(self.program.second_section)
self.vm.add_log("=== Execution completed ===")
self.vm.running = False
def step(self):
"""Execute one instruction (step mode)"""
self.step_mode = True
if not self.vm.running:
self.run()
else:
# Continue from where we left off
if self.current_section == "First":
if self.current_instruction < len(self.program.first_section):
inst = self.program.first_section[self.current_instruction]
self.execute_instruction(inst)
self.current_instruction += 1
elif self.current_section == "Second":
if self.current_instruction < len(self.program.second_section):
inst = self.program.second_section[self.current_instruction]
self.execute_instruction(inst)
self.current_instruction += 1
def pause(self):
"""Pause execution"""
self.vm.paused = True
def reset(self):
"""Reset execution state"""
self.vm.reset()
self.current_instruction = 0
self.current_section = None
self.step_mode = False
if __name__ == "__main__":
# Test execution engine
from machine_loader import MachineConfig, load_machine_config
config = MachineConfig()
vm = VirtualMachine(config)
prog = Program()
engine = ExecutionEngine(vm, prog)
print("Execution Engine Test")