github-actions commited on
Commit
fb85cfd
·
1 Parent(s): 6d01cfb

Auto deploy from GitHub

Browse files
app.py ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import json
2
+ import logging
3
+ import traceback
4
+ from typing import Any, Dict, List
5
+
6
+ # OpenEnv SDK import
7
+ from openenv import MCPEnvironment
8
+
9
+ # ==============================================================================
10
+ # ROLE 1 & 3 IMPORTS
11
+ # TODO: Import the actual execution engine and generator from your teammates
12
+ # ==============================================================================
13
+ # from engine import execute_tac, verify_equivalence
14
+ # from curriculum import generate_level_code
15
+
16
+ logging.basicConfig(level=logging.INFO)
17
+ logger = logging.getLogger("CompilerEnvServer")
18
+
19
+ class CompilerEnv(MCPEnvironment):
20
+ """
21
+ The OpenEnv Server Wrapper for the Toy-IR Compiler Pass Optimizer.
22
+ Acts as the referee between the LLM client and Role 1's Execution Engine.
23
+ """
24
+
25
+ def __init__(self):
26
+ super().__init__()
27
+ # State variables
28
+ self.raw_json_code = None
29
+ self.current_state_string = ""
30
+ self.initial_cycles = 0
31
+ self.current_step = 0
32
+ self.max_steps = 10 # Set a max step limit per episode
33
+
34
+ # Cycle Weights (The Physics defined by Role 2)
35
+ self.cycle_weights = {
36
+ "ADD": 1,
37
+ "SUB": 1,
38
+ "MUL": 4,
39
+ "DIV": 10,
40
+ "MEM_LOAD": 20,
41
+ "STORE": 20
42
+ }
43
+
44
+ def reset(self) -> str:
45
+ """
46
+ Grabs unoptimized code, calculates baseline cycles, and translates the
47
+ state for the LLM.
48
+ """
49
+ self.current_step = 0
50
+
51
+ # 1. Grab new unoptimized code (Role 3 integration)
52
+ # TODO: Replace with real generator: self.raw_json_code = generate_level_code()
53
+ self.raw_json_code = self._mock_generator()
54
+
55
+ # 2. Get baseline cycles (Role 1 integration)
56
+ # TODO: Replace with real engine: self.initial_cycles, _ = execute_tac(self.raw_json_code, [])
57
+ self.initial_cycles = 100
58
+
59
+ # 3. Translate to Pseudo-Assembly to prevent Attention Dilution
60
+ self.current_state_string = self._translate_state(self.raw_json_code)
61
+
62
+ logger.info(f"Environment Reset. Baseline Cycles: {self.initial_cycles}")
63
+ return self.state()
64
+
65
+ def step(self, action: str) -> Dict[str, Any]:
66
+ """
67
+ Executes the LLM's chosen optimization pass, verifies math equivalence,
68
+ and calculates the reward.
69
+ """
70
+ self.current_step += 1
71
+
72
+ # 1. Parse LLM Action (Regex/JSON robustness)
73
+ try:
74
+ # Assuming the LLM outputs a single pass name or a list of passes
75
+ action_data = json.loads(action)
76
+ if isinstance(action_data, str):
77
+ action_array = [action_data]
78
+ else:
79
+ action_array = action_data
80
+ format_bonus = 0.1
81
+ except json.JSONDecodeError:
82
+ # Format Trap
83
+ return self._build_step_response(
84
+ reward=-2.5,
85
+ done=True,
86
+ error="Invalid JSON. You must output a valid JSON array of strings."
87
+ )
88
+
89
+ # 2. Execute Code & Verify Equivalence (Role 1 Integration)
90
+ # TODO: new_cycles, optimized_code = execute_tac(self.raw_json_code, action_array)
91
+ # TODO: is_valid = verify_equivalence(self.raw_json_code, optimized_code)
92
+ new_cycles = 80 # Mock Data
93
+ is_valid = True # Mock Data
94
+
95
+ # 3. Calculate Reward Physics
96
+ if not is_valid:
97
+ # Correctness Penalty + Micro-Variance for GRPO
98
+ penalty = -2.0 - (len(action_array) * 0.01)
99
+ return self._build_step_response(
100
+ reward=penalty,
101
+ done=True,
102
+ error=f"Code equivalence broken by passes: {action_array}"
103
+ )
104
+
105
+ # Calculate Improvement Ratio + Time Tax (-1.0)
106
+ cycle_improvement_ratio = (self.initial_cycles - new_cycles) / self.initial_cycles
107
+ time_tax = -0.05 * self.current_step # Small tax to prevent pass spamming
108
+ reward = cycle_improvement_ratio + format_bonus + time_tax
109
+
110
+ # Update state if sequential, or finish if one-shot
111
+ # NOTE: For hackathon speed, we treat this as a One-Shot episode
112
+ done = True
113
+
114
+ return self._build_step_response(
115
+ reward=reward,
116
+ done=done,
117
+ info={"status": "success", "optimized_cycles": new_cycles}
118
+ )
119
+
120
+ def state(self) -> str:
121
+ """
122
+ Returns the current observation to the LLM.
123
+ """
124
+ return f"Current Step: {self.current_step}/{self.max_steps}\n\n{self.current_state_string}"
125
+
126
+ def _translate_state(self, raw_json: List[Dict]) -> str:
127
+ """
128
+ Translates raw AST JSON into clean pseudo-assembly.
129
+ Strips all UUIDs and AST metadata.
130
+ """
131
+ pseudo_assembly = []
132
+ instruction_count = 1
133
+
134
+ for inst in raw_json:
135
+ op = inst.get("op", "UNKNOWN")
136
+ src1 = inst.get("src1", "")
137
+ src2 = inst.get("src2", "")
138
+ dest = inst.get("dest", "")
139
+
140
+ # Format arguments cleanly
141
+ args = f"{src1}" if src2 is None else f"{src1}, {src2}"
142
+
143
+ if dest:
144
+ line = f"{instruction_count}. {dest} = {op} {args}"
145
+ else:
146
+ line = f"{instruction_count}. {op} {args}"
147
+
148
+ pseudo_assembly.append(line)
149
+ instruction_count += 1
150
+
151
+ return "\n".join(pseudo_assembly)
152
+
153
+ def _build_step_response(self, reward: float, done: bool, error: str = None, info: dict = None) -> Dict[str, Any]:
154
+ """Helper to format the standard OpenEnv step return dictionary."""
155
+ response = {
156
+ "reward": reward,
157
+ "done": done,
158
+ "state": self.state()
159
+ }
160
+ if error:
161
+ response["error"] = error
162
+ if info:
163
+ response["info"] = info
164
+ return response
165
+
166
+ def _mock_generator(self):
167
+ """Mock data so the server runs before Role 1 integrates their engine."""
168
+ return [
169
+ {"op": "CONST", "dest": "a", "src1": 2, "src2": None},
170
+ {"op": "CONST", "dest": "b", "src1": 3, "src2": None},
171
+ {"op": "ADD", "dest": "c", "src1": "a", "src2": "b"}
172
+ ]
173
+
174
+ if __name__ == "__main__":
175
+ logger.info("Initializing CompilerEnv Server...")
176
+ try:
177
+ env = CompilerEnv()
178
+ # openenv.run() or start() depending on the specific MCP wrapper version
179
+ env.start()
180
+ except Exception as e:
181
+ logger.error(f"Failed to start environment server: {e}")
182
+ logger.error(traceback.format_exc())
space/compiler_tetris (1).ipynb ADDED
@@ -0,0 +1,651 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "cells": [
3
+ {
4
+ "cell_type": "code",
5
+ "execution_count": null,
6
+ "id": "b7fdb9ab",
7
+ "metadata": {},
8
+ "outputs": [],
9
+ "source": [
10
+ "# ==== CELL 1: Setup ====\n",
11
+ "!pip install -q pytest\n",
12
+ "import os, sys\n",
13
+ "\n",
14
+ "LOCAL_DIR = \"/content/toyir\"\n",
15
+ "DRIVE_DIR = \"/content/drive/MyDrive/env/toyir\"\n",
16
+ "\n",
17
+ "os.makedirs(LOCAL_DIR, exist_ok=True)\n",
18
+ "sys.path.insert(0, LOCAL_DIR)\n",
19
+ "print(\"Workspace ready at\", LOCAL_DIR)\n"
20
+ ]
21
+ },
22
+ {
23
+ "cell_type": "code",
24
+ "execution_count": null,
25
+ "id": "d0337367",
26
+ "metadata": {},
27
+ "outputs": [],
28
+ "source": [
29
+ "# ==== CELL 1b: Mount Drive + sync workspace ====\n",
30
+ "from google.colab import drive\n",
31
+ "drive.mount('/content/drive')\n",
32
+ "\n",
33
+ "import shutil\n",
34
+ "os.makedirs(DRIVE_DIR, exist_ok=True)\n",
35
+ "\n",
36
+ "# On fresh runtime: pull existing files from Drive -> local\n",
37
+ "for f in os.listdir(DRIVE_DIR):\n",
38
+ " src = os.path.join(DRIVE_DIR, f)\n",
39
+ " if os.path.isfile(src) and f.endswith(\".py\"):\n",
40
+ " shutil.copy2(src, os.path.join(LOCAL_DIR, f))\n",
41
+ "print(\"Synced from Drive:\", sorted(os.listdir(LOCAL_DIR)))\n"
42
+ ]
43
+ },
44
+ {
45
+ "cell_type": "code",
46
+ "execution_count": null,
47
+ "id": "2c83c529",
48
+ "metadata": {},
49
+ "outputs": [],
50
+ "source": [
51
+ "%%writefile /content/toyir/toy_vm.py\n",
52
+ "\"\"\"Toy-IR VM: deterministic, dependency-light execution engine for RLVR.\"\"\"\n",
53
+ "from __future__ import annotations\n",
54
+ "from copy import deepcopy\n",
55
+ "from typing import Any\n",
56
+ "\n",
57
+ "CYCLE_COST: dict[str, int] = {\n",
58
+ " \"CONST\": 1, \"ADD\": 1, \"SUB\": 1, \"MUL\": 3, \"DIV\": 5,\n",
59
+ " \"COPY\": 1, \"LOAD\": 4, \"STORE\": 4, \"NOP\": 0,\n",
60
+ "}\n",
61
+ "OP_ORDER = (\"CONST\", \"ADD\", \"SUB\", \"MUL\", \"DIV\", \"COPY\", \"LOAD\", \"STORE\", \"NOP\")\n",
62
+ "VALID_OPS = frozenset(CYCLE_COST)\n",
63
+ "REQUIRED_KEYS = (\"op\", \"dest\", \"src1\", \"src2\")\n",
64
+ "\n",
65
+ "\n",
66
+ "def _is_str_or_int_or_none(x: Any) -> bool:\n",
67
+ " return x is None or isinstance(x, str) or (isinstance(x, int) and not isinstance(x, bool))\n",
68
+ "\n",
69
+ "\n",
70
+ "def _is_str_or_none(x: Any) -> bool:\n",
71
+ " return x is None or isinstance(x, str)\n",
72
+ "\n",
73
+ "\n",
74
+ "def validate_ir(program: list[dict]) -> dict:\n",
75
+ " errors: list[str] = []\n",
76
+ " for i, ins in enumerate(program):\n",
77
+ " if not isinstance(ins, dict):\n",
78
+ " errors.append(f\"[{i}] not a dict\")\n",
79
+ " continue\n",
80
+ " for k in REQUIRED_KEYS:\n",
81
+ " if k not in ins:\n",
82
+ " errors.append(f\"[{i}] missing key '{k}'\")\n",
83
+ " if \"op\" not in ins:\n",
84
+ " continue\n",
85
+ " op = ins[\"op\"]\n",
86
+ " if op not in VALID_OPS:\n",
87
+ " errors.append(f\"[{i}] invalid op '{op}'\")\n",
88
+ " continue\n",
89
+ " if not _is_str_or_none(ins.get(\"dest\")):\n",
90
+ " errors.append(f\"[{i}] dest must be str|None\")\n",
91
+ " if not _is_str_or_int_or_none(ins.get(\"src1\")):\n",
92
+ " errors.append(f\"[{i}] src1 must be str|int|None\")\n",
93
+ " if not _is_str_or_int_or_none(ins.get(\"src2\")):\n",
94
+ " errors.append(f\"[{i}] src2 must be str|int|None\")\n",
95
+ "\n",
96
+ " # per-op contracts\n",
97
+ " if op in (\"CONST\", \"ADD\", \"SUB\", \"MUL\", \"DIV\", \"COPY\", \"LOAD\"):\n",
98
+ " if not isinstance(ins.get(\"dest\"), str):\n",
99
+ " errors.append(f\"[{i}] {op} requires str dest\")\n",
100
+ " if op in (\"ADD\", \"SUB\", \"MUL\", \"DIV\"):\n",
101
+ " if ins.get(\"src1\") is None or ins.get(\"src2\") is None:\n",
102
+ " errors.append(f\"[{i}] {op} requires src1 and src2\")\n",
103
+ " if op in (\"CONST\", \"COPY\"):\n",
104
+ " if ins.get(\"src1\") is None:\n",
105
+ " errors.append(f\"[{i}] {op} requires src1\")\n",
106
+ " if op in (\"CONST\", \"COPY\", \"LOAD\", \"STORE\"):\n",
107
+ " if ins.get(\"src2\") is not None:\n",
108
+ " errors.append(f\"[{i}] {op} requires src2=None\")\n",
109
+ " if op == \"LOAD\":\n",
110
+ " if not isinstance(ins.get(\"src1\"), str):\n",
111
+ " errors.append(f\"[{i}] LOAD src1 must be str (variable name)\")\n",
112
+ " if op == \"STORE\":\n",
113
+ " if not isinstance(ins.get(\"dest\"), str):\n",
114
+ " errors.append(f\"[{i}] STORE dest must be str (variable name)\")\n",
115
+ " if ins.get(\"src1\") is None:\n",
116
+ " errors.append(f\"[{i}] STORE requires src1\")\n",
117
+ " if op == \"NOP\":\n",
118
+ " if any(ins.get(k) is not None for k in (\"dest\", \"src1\", \"src2\")):\n",
119
+ " errors.append(f\"[{i}] NOP fields must all be None\")\n",
120
+ "\n",
121
+ " return {\"valid\": len(errors) == 0, \"errors\": errors}\n",
122
+ "\n",
123
+ "\n",
124
+ "def _resolve(operand: Any, variables: dict) -> int:\n",
125
+ " if isinstance(operand, str):\n",
126
+ " if operand not in variables:\n",
127
+ " raise KeyError(f\"undefined variable '{operand}'\")\n",
128
+ " return variables[operand]\n",
129
+ " if isinstance(operand, int) and not isinstance(operand, bool):\n",
130
+ " return operand\n",
131
+ " raise TypeError(f\"bad operand: {operand!r}\")\n",
132
+ "\n",
133
+ "\n",
134
+ "def _exec_one(ins: dict, variables: dict, memory: dict) -> int:\n",
135
+ " op = ins[\"op\"]\n",
136
+ " dest = ins[\"dest\"]\n",
137
+ " s1, s2 = ins[\"src1\"], ins[\"src2\"]\n",
138
+ "\n",
139
+ " if op == \"CONST\":\n",
140
+ " variables[dest] = _resolve(s1, variables)\n",
141
+ " elif op == \"ADD\":\n",
142
+ " variables[dest] = _resolve(s1, variables) + _resolve(s2, variables)\n",
143
+ " elif op == \"SUB\":\n",
144
+ " variables[dest] = _resolve(s1, variables) - _resolve(s2, variables)\n",
145
+ " elif op == \"MUL\":\n",
146
+ " variables[dest] = _resolve(s1, variables) * _resolve(s2, variables)\n",
147
+ " elif op == \"DIV\":\n",
148
+ " b = _resolve(s2, variables)\n",
149
+ " if b == 0:\n",
150
+ " raise ZeroDivisionError(\"DIV by zero\")\n",
151
+ " variables[dest] = _resolve(s1, variables) // b\n",
152
+ " elif op == \"COPY\":\n",
153
+ " variables[dest] = _resolve(s1, variables)\n",
154
+ " elif op == \"LOAD\":\n",
155
+ " if not isinstance(s1, str):\n",
156
+ " raise TypeError(\"LOAD src1 must be a variable name\")\n",
157
+ " addr = variables.get(s1)\n",
158
+ " if not (isinstance(addr, int) and not isinstance(addr, bool)):\n",
159
+ " raise TypeError(f\"LOAD address from '{s1}' is not int: {addr!r}\")\n",
160
+ " if addr not in memory:\n",
161
+ " raise KeyError(f\"LOAD from uninitialized addr {addr}\")\n",
162
+ " variables[dest] = memory[addr]\n",
163
+ " elif op == \"STORE\":\n",
164
+ " if not isinstance(dest, str):\n",
165
+ " raise TypeError(\"STORE dest must be a variable name\")\n",
166
+ " addr = variables.get(dest)\n",
167
+ " if not (isinstance(addr, int) and not isinstance(addr, bool)):\n",
168
+ " raise TypeError(f\"STORE address from '{dest}' is not int: {addr!r}\")\n",
169
+ " memory[addr] = _resolve(s1, variables)\n",
170
+ " elif op == \"NOP\":\n",
171
+ " pass\n",
172
+ " else:\n",
173
+ " raise ValueError(f\"non-executable op {op}\")\n",
174
+ " return CYCLE_COST[op]\n",
175
+ "\n",
176
+ "\n",
177
+ "def execute(program: list[dict], initial_state: dict) -> dict:\n",
178
+ " variables: dict = {}\n",
179
+ " memory: dict = {}\n",
180
+ " cycles = 0\n",
181
+ " try:\n",
182
+ " if not isinstance(initial_state, dict):\n",
183
+ " raise TypeError(\"initial_state must be a dict\")\n",
184
+ " state = deepcopy(initial_state)\n",
185
+ " variables = state.get(\"variables\", {})\n",
186
+ " memory = state.get(\"memory\", {})\n",
187
+ " if not isinstance(variables, dict):\n",
188
+ " raise TypeError(\"initial_state['variables'] must be a dict\")\n",
189
+ " if not isinstance(memory, dict):\n",
190
+ " raise TypeError(\"initial_state['memory'] must be a dict\")\n",
191
+ "\n",
192
+ " for ins in program:\n",
193
+ " cycles += _exec_one(ins, variables, memory)\n",
194
+ " except Exception as e:\n",
195
+ " return {\"memory\": memory, \"variables\": variables,\n",
196
+ " \"cycles\": None, \"success\": False, \"error\": str(e)}\n",
197
+ " return {\"memory\": memory, \"variables\": variables,\n",
198
+ " \"cycles\": cycles, \"success\": True, \"error\": None}\n",
199
+ "\n",
200
+ "\n",
201
+ "def count_cycles(program: list[dict]) -> int:\n",
202
+ " total = 0\n",
203
+ " for i, ins in enumerate(program):\n",
204
+ " op = ins.get(\"op\") if isinstance(ins, dict) else None\n",
205
+ " if op not in CYCLE_COST:\n",
206
+ " raise ValueError(f\"count_cycles: invalid or missing op at index {i}: {op!r}\")\n",
207
+ " total += CYCLE_COST[op]\n",
208
+ " return total\n",
209
+ "\n",
210
+ "\n",
211
+ "def profile(program: list[dict]) -> dict:\n",
212
+ " out: dict[str, int] = {\"n_instructions\": len(program)}\n",
213
+ " for op in OP_ORDER:\n",
214
+ " out[f\"n_{op.lower()}\"] = 0\n",
215
+ " for ins in program:\n",
216
+ " key = f\"n_{ins['op'].lower()}\"\n",
217
+ " if key in out:\n",
218
+ " out[key] += 1\n",
219
+ " return out\n",
220
+ "\n",
221
+ "\n",
222
+ "def _fmt_operand(x: Any) -> str:\n",
223
+ " if x is None:\n",
224
+ " return \"\"\n",
225
+ " return str(x)\n",
226
+ "\n",
227
+ "\n",
228
+ "def dump_ir(program: list[dict]) -> str:\n",
229
+ " stores = [ins[\"dest\"] for ins in program if ins[\"op\"] == \"STORE\"]\n",
230
+ " seen, ordered = set(), []\n",
231
+ " for s in stores:\n",
232
+ " if s not in seen:\n",
233
+ " seen.add(s); ordered.append(s)\n",
234
+ " header = \"// OBSERVABLE OUT: \" + (\", \".join(f\"mem[{s}]\" for s in ordered) if ordered else \"(none)\")\n",
235
+ " lines = [header]\n",
236
+ " for ins in program:\n",
237
+ " op = ins[\"op\"]\n",
238
+ " dest, s1, s2 = ins[\"dest\"], ins[\"src1\"], ins[\"src2\"]\n",
239
+ " if op == \"STORE\":\n",
240
+ " lines.append(f\"STORE [{dest}] {_fmt_operand(s1)}\")\n",
241
+ " elif op == \"LOAD\":\n",
242
+ " lines.append(f\"{dest} = LOAD [{_fmt_operand(s1)}]\")\n",
243
+ " elif op == \"NOP\":\n",
244
+ " lines.append(\"NOP\")\n",
245
+ " else:\n",
246
+ " parts = [op, _fmt_operand(s1)]\n",
247
+ " if s2 is not None:\n",
248
+ " parts.append(_fmt_operand(s2))\n",
249
+ " lines.append(f\"{dest} = {' '.join(p for p in parts if p)}\")\n",
250
+ " return \"\\n\".join(lines)\n",
251
+ "\n",
252
+ "\n",
253
+ "def clean_nops(program: list[dict]) -> list[dict]:\n",
254
+ " return [deepcopy(ins) for ins in program if ins[\"op\"] != \"NOP\"]\n"
255
+ ]
256
+ },
257
+ {
258
+ "cell_type": "code",
259
+ "execution_count": null,
260
+ "id": "3c85a58b",
261
+ "metadata": {},
262
+ "outputs": [],
263
+ "source": [
264
+ "%%writefile /content/toyir/verifier.py\n",
265
+ "\"\"\"Strict equivalence verifier - anti-cheat for RL reward hacking.\"\"\"\n",
266
+ "from __future__ import annotations\n",
267
+ "from toy_vm import execute\n",
268
+ "\n",
269
+ "\n",
270
+ "def verify(original_program: list[dict],\n",
271
+ " optimized_program: list[dict],\n",
272
+ " initial_states: list[dict]) -> dict:\n",
273
+ " if not initial_states:\n",
274
+ " raise ValueError(\"verify requires at least one initial_state\")\n",
275
+ "\n",
276
+ " results = []\n",
277
+ " all_match = True\n",
278
+ " for st in initial_states:\n",
279
+ " r_o = execute(original_program, st)\n",
280
+ " r_p = execute(optimized_program, st)\n",
281
+ " mem_o = r_o[\"memory\"] if r_o[\"success\"] else None\n",
282
+ " mem_p = r_p[\"memory\"] if r_p[\"success\"] else None\n",
283
+ "\n",
284
+ " execution_errors = {}\n",
285
+ " if not r_o[\"success\"]:\n",
286
+ " execution_errors[\"original_error\"] = r_o[\"error\"]\n",
287
+ " if not r_p[\"success\"]:\n",
288
+ " execution_errors[\"optimized_error\"] = r_p[\"error\"]\n",
289
+ "\n",
290
+ " if execution_errors:\n",
291
+ " match = False\n",
292
+ " mismatches = [\"__execution_error__\"]\n",
293
+ " else:\n",
294
+ " keys = set(mem_o.keys()) | set(mem_p.keys())\n",
295
+ " mismatches = [k for k in keys if mem_o.get(k) != mem_p.get(k)]\n",
296
+ " match = len(mismatches) == 0\n",
297
+ "\n",
298
+ " if not match:\n",
299
+ " all_match = False\n",
300
+ " results.append({\n",
301
+ " \"initial_state\": st,\n",
302
+ " \"original_memory\": mem_o,\n",
303
+ " \"optimized_memory\": mem_p,\n",
304
+ " \"match\": match,\n",
305
+ " \"mismatches\": sorted(mismatches, key=lambda x: (isinstance(x, str), x)),\n",
306
+ " \"execution_errors\": execution_errors or None,\n",
307
+ " })\n",
308
+ " return {\"equivalent\": all_match, \"results\": results}\n"
309
+ ]
310
+ },
311
+ {
312
+ "cell_type": "code",
313
+ "execution_count": null,
314
+ "id": "cd7f8fa2",
315
+ "metadata": {},
316
+ "outputs": [],
317
+ "source": [
318
+ "%%writefile /content/toyir/reward_utils.py\n",
319
+ "\"\"\"Reward signal: cycle-reduction metric for RL agent.\"\"\"\n",
320
+ "from __future__ import annotations\n",
321
+ "from toy_vm import execute\n",
322
+ "\n",
323
+ "\n",
324
+ "def compute_reduction(original_program: list[dict],\n",
325
+ " optimized_program: list[dict],\n",
326
+ " initial_state: dict) -> dict:\n",
327
+ " r_o = execute(original_program, initial_state)\n",
328
+ " r_p = execute(optimized_program, initial_state)\n",
329
+ "\n",
330
+ " if not (r_o[\"success\"] and r_p[\"success\"]):\n",
331
+ " return {\n",
332
+ " \"original_cycles\": r_o[\"cycles\"],\n",
333
+ " \"optimized_cycles\": r_p[\"cycles\"],\n",
334
+ " \"absolute_savings\": None,\n",
335
+ " \"relative_savings\": None,\n",
336
+ " \"success\": False,\n",
337
+ " \"error\": r_o[\"error\"] or r_p[\"error\"],\n",
338
+ " }\n",
339
+ "\n",
340
+ " oc, pc = r_o[\"cycles\"], r_p[\"cycles\"]\n",
341
+ " rel = 0.0 if oc == 0 else (oc - pc) / oc\n",
342
+ " rel = max(-1.0, min(1.0, rel))\n",
343
+ " return {\n",
344
+ " \"original_cycles\": oc,\n",
345
+ " \"optimized_cycles\": pc,\n",
346
+ " \"absolute_savings\": oc - pc,\n",
347
+ " \"relative_savings\": rel,\n",
348
+ " \"success\": True,\n",
349
+ " \"error\": None,\n",
350
+ " }\n"
351
+ ]
352
+ },
353
+ {
354
+ "cell_type": "code",
355
+ "execution_count": null,
356
+ "id": "4f2a941c",
357
+ "metadata": {},
358
+ "outputs": [],
359
+ "source": [
360
+ "%%writefile /content/toyir/test_vm.py\n",
361
+ "\"\"\"Pytest suite covering VM, verifier, reward, and RL exploit guardrails.\"\"\"\n",
362
+ "from __future__ import annotations\n",
363
+ "import random\n",
364
+ "import pytest\n",
365
+ "from toy_vm import (\n",
366
+ " validate_ir, execute, count_cycles, profile, dump_ir, clean_nops, OP_ORDER,\n",
367
+ ")\n",
368
+ "from verifier import verify\n",
369
+ "from reward_utils import compute_reduction\n",
370
+ "\n",
371
+ "\n",
372
+ "def I(op, dest=None, src1=None, src2=None):\n",
373
+ " return {\"op\": op, \"dest\": dest, \"src1\": src1, \"src2\": src2}\n",
374
+ "\n",
375
+ "\n",
376
+ "def test_const_fold_equivalence():\n",
377
+ " orig = [I(\"CONST\", \"t0\", 5), I(\"CONST\", \"t1\", 7), I(\"ADD\", \"t2\", \"t0\", \"t1\"),\n",
378
+ " I(\"CONST\", \"addr\", 0), I(\"STORE\", \"addr\", \"t2\")]\n",
379
+ " opt = [I(\"CONST\", \"t2\", 12), I(\"CONST\", \"addr\", 0), I(\"STORE\", \"addr\", \"t2\")]\n",
380
+ " res = verify(orig, opt, [{\"variables\": {}, \"memory\": {}}])\n",
381
+ " assert res[\"equivalent\"]\n",
382
+ " red = compute_reduction(orig, opt, {\"variables\": {}, \"memory\": {}})\n",
383
+ " assert red[\"absolute_savings\"] > 0\n",
384
+ "\n",
385
+ "\n",
386
+ "def test_dead_code_invisible():\n",
387
+ " orig = [I(\"CONST\", \"addr\", 0), I(\"CONST\", \"x\", 3),\n",
388
+ " I(\"MUL\", \"dead\", \"x\", 99), I(\"STORE\", \"addr\", \"x\")]\n",
389
+ " opt = [I(\"CONST\", \"addr\", 0), I(\"CONST\", \"x\", 3), I(\"STORE\", \"addr\", \"x\")]\n",
390
+ " res = verify(orig, opt, [{\"variables\": {}, \"memory\": {}}])\n",
391
+ " assert res[\"equivalent\"]\n",
392
+ "\n",
393
+ "\n",
394
+ "def test_fold_then_dce():\n",
395
+ " orig = [I(\"CONST\", \"a\", 2), I(\"CONST\", \"b\", 3), I(\"ADD\", \"c\", \"a\", \"b\"),\n",
396
+ " I(\"MUL\", \"d\", \"c\", 10), I(\"CONST\", \"addr\", 0), I(\"STORE\", \"addr\", \"d\")]\n",
397
+ " opt = [I(\"CONST\", \"d\", 50), I(\"CONST\", \"addr\", 0), I(\"STORE\", \"addr\", \"d\")]\n",
398
+ " res = verify(orig, opt, [{\"variables\": {}, \"memory\": {}}])\n",
399
+ " assert res[\"equivalent\"]\n",
400
+ " red = compute_reduction(orig, opt, {\"variables\": {}, \"memory\": {}})\n",
401
+ " assert red[\"original_cycles\"] > red[\"optimized_cycles\"]\n",
402
+ "\n",
403
+ "\n",
404
+ "def test_strength_reduction():\n",
405
+ " orig = [I(\"CONST\", \"addr\", 0), I(\"CONST\", \"x\", 7),\n",
406
+ " I(\"MUL\", \"y\", \"x\", 2), I(\"STORE\", \"addr\", \"y\")]\n",
407
+ " opt = [I(\"CONST\", \"addr\", 0), I(\"CONST\", \"x\", 7),\n",
408
+ " I(\"ADD\", \"y\", \"x\", \"x\"), I(\"STORE\", \"addr\", \"y\")]\n",
409
+ " res = verify(orig, opt, [{\"variables\": {}, \"memory\": {}}])\n",
410
+ " assert res[\"equivalent\"]\n",
411
+ " red = compute_reduction(orig, opt, {\"variables\": {}, \"memory\": {}})\n",
412
+ " assert red[\"absolute_savings\"] > 0\n",
413
+ "\n",
414
+ "\n",
415
+ "def test_already_optimal():\n",
416
+ " p = [I(\"CONST\", \"addr\", 0), I(\"CONST\", \"x\", 1), I(\"STORE\", \"addr\", \"x\")]\n",
417
+ " red = compute_reduction(p, p, {\"variables\": {}, \"memory\": {}})\n",
418
+ " assert red[\"absolute_savings\"] == 0\n",
419
+ " assert red[\"relative_savings\"] == 0.0\n",
420
+ "\n",
421
+ "\n",
422
+ "def test_div_by_zero():\n",
423
+ " p = [I(\"CONST\", \"a\", 10), I(\"CONST\", \"b\", 0), I(\"DIV\", \"c\", \"a\", \"b\")]\n",
424
+ " r = execute(p, {\"variables\": {}, \"memory\": {}})\n",
425
+ " assert r[\"success\"] is False\n",
426
+ " assert \"zero\" in r[\"error\"].lower()\n",
427
+ "\n",
428
+ "\n",
429
+ "def test_hardcoded_exploit_caught():\n",
430
+ " orig = [I(\"CONST\", \"addr\", 0), I(\"LOAD\", \"x\", \"in_addr\"),\n",
431
+ " I(\"MUL\", \"y\", \"x\", 3), I(\"STORE\", \"addr\", \"y\")]\n",
432
+ " opt = [I(\"CONST\", \"addr\", 0), I(\"CONST\", \"y\", 42), I(\"STORE\", \"addr\", \"y\")]\n",
433
+ " rng = random.Random(0)\n",
434
+ " states = [{\"variables\": {\"in_addr\": 1}, \"memory\": {1: rng.randint(0, 100)}} for _ in range(5)]\n",
435
+ " res = verify(orig, opt, states)\n",
436
+ " assert res[\"equivalent\"] is False\n",
437
+ " assert any(not r[\"match\"] for r in res[\"results\"])\n",
438
+ "\n",
439
+ "\n",
440
+ "def test_nop_zero_cost():\n",
441
+ " p = [I(\"NOP\"), I(\"CONST\", \"x\", 1), I(\"NOP\")]\n",
442
+ " assert count_cycles(p) == 1\n",
443
+ " r = execute(p, {\"variables\": {}, \"memory\": {}})\n",
444
+ " assert r[\"success\"] and r[\"cycles\"] == 1\n",
445
+ "\n",
446
+ "\n",
447
+ "def test_load_store_non_int_address():\n",
448
+ " p = [I(\"COPY\", \"addr\", \"bad\"), I(\"LOAD\", \"x\", \"addr\")]\n",
449
+ " r = execute(p, {\"variables\": {\"bad\": \"notint\"}, \"memory\": {}})\n",
450
+ " assert r[\"success\"] is False\n",
451
+ "\n",
452
+ "\n",
453
+ "def test_validate_ir_malformed():\n",
454
+ " assert not validate_ir([I(\"FOOBAR\", \"t\", 1, 2)])[\"valid\"]\n",
455
+ " assert not validate_ir([{\"op\": \"ADD\", \"dest\": \"x\"}])[\"valid\"]\n",
456
+ " assert not validate_ir([I(\"CONST\", 123, 1)])[\"valid\"]\n",
457
+ " assert not validate_ir([I(\"STORE\", None, \"x\")])[\"valid\"]\n",
458
+ " assert not validate_ir([I(\"LOAD\", \"x\", 42)])[\"valid\"]\n",
459
+ " assert not validate_ir([I(\"NOP\", \"x\", 1)])[\"valid\"]\n",
460
+ " assert not validate_ir([I(\"ADD\", \"x\", \"a\", None)])[\"valid\"]\n",
461
+ " assert not validate_ir([I(\"LOAD\", \"x\", \"addr\", 9)])[\"valid\"]\n",
462
+ " assert not validate_ir([I(\"STORE\", \"addr\", \"x\", 9)])[\"valid\"]\n",
463
+ " assert validate_ir([I(\"CONST\", \"x\", 1)])[\"valid\"]\n",
464
+ "\n",
465
+ "\n",
466
+ "def test_dump_ir_format():\n",
467
+ " p = [I(\"CONST\", \"t0\", 5), I(\"ADD\", \"t1\", \"t0\", \"a\"),\n",
468
+ " I(\"MUL\", \"t2\", \"t1\", 3), I(\"STORE\", \"addr0\", \"t2\")]\n",
469
+ " s = dump_ir(p)\n",
470
+ " lines = s.split(\"\\n\")\n",
471
+ " assert lines[0] == \"// OBSERVABLE OUT: mem[addr0]\"\n",
472
+ " assert lines[1] == \"t0 = CONST 5\"\n",
473
+ " assert lines[2] == \"t1 = ADD t0 a\"\n",
474
+ " assert lines[3] == \"t2 = MUL t1 3\"\n",
475
+ " assert lines[4] == \"STORE [addr0] t2\"\n",
476
+ " assert len(lines) == 5\n",
477
+ "\n",
478
+ "\n",
479
+ "def test_dump_ir_multi_store_header_order():\n",
480
+ " p = [I(\"CONST\", \"a\", 0), I(\"CONST\", \"b\", 1),\n",
481
+ " I(\"STORE\", \"a\", 5), I(\"STORE\", \"b\", 6), I(\"STORE\", \"a\", 7)]\n",
482
+ " s = dump_ir(p)\n",
483
+ " assert s.split(\"\\n\")[0] == \"// OBSERVABLE OUT: mem[a], mem[b]\"\n",
484
+ "\n",
485
+ "\n",
486
+ "def test_clean_nops():\n",
487
+ " p = [I(\"NOP\"), I(\"CONST\", \"x\", 1), I(\"NOP\"), I(\"CONST\", \"y\", 2), I(\"NOP\")]\n",
488
+ " out = clean_nops(p)\n",
489
+ " assert len(out) == 2\n",
490
+ " assert all(ins[\"op\"] != \"NOP\" for ins in out)\n",
491
+ "\n",
492
+ "\n",
493
+ "def test_verify_mismatches():\n",
494
+ " orig = [I(\"CONST\", \"a0\", 0), I(\"CONST\", \"a1\", 1),\n",
495
+ " I(\"CONST\", \"x\", 5), I(\"CONST\", \"y\", 9),\n",
496
+ " I(\"STORE\", \"a0\", \"x\"), I(\"STORE\", \"a1\", \"y\")]\n",
497
+ " opt = [I(\"CONST\", \"a0\", 0), I(\"CONST\", \"a1\", 1),\n",
498
+ " I(\"CONST\", \"x\", 5), I(\"CONST\", \"y\", 8),\n",
499
+ " I(\"STORE\", \"a0\", \"x\"), I(\"STORE\", \"a1\", \"y\")]\n",
500
+ " res = verify(orig, opt, [{\"variables\": {}, \"memory\": {}}])\n",
501
+ " assert res[\"equivalent\"] is False\n",
502
+ " assert res[\"results\"][0][\"mismatches\"] == [1]\n",
503
+ "\n",
504
+ "\n",
505
+ "def test_profile_counts_and_ordering():\n",
506
+ " p = [I(\"CONST\", \"x\", 1), I(\"ADD\", \"y\", \"x\", 2), I(\"MUL\", \"z\", \"y\", 3)]\n",
507
+ " pr = profile(p)\n",
508
+ " assert pr[\"n_instructions\"] == 3\n",
509
+ " assert pr[\"n_const\"] == 1 and pr[\"n_add\"] == 1 and pr[\"n_mul\"] == 1\n",
510
+ " expected = [\"n_instructions\"] + [f\"n_{op.lower()}\" for op in OP_ORDER]\n",
511
+ " assert list(pr.keys()) == expected\n",
512
+ "\n",
513
+ "\n",
514
+ "def test_no_input_mutation():\n",
515
+ " p = [I(\"CONST\", \"x\", 1), I(\"CONST\", \"addr\", 0), I(\"STORE\", \"addr\", \"x\")]\n",
516
+ " st = {\"variables\": {}, \"memory\": {}}\n",
517
+ " snap = {\"variables\": dict(st[\"variables\"]), \"memory\": dict(st[\"memory\"])}\n",
518
+ " execute(p, st)\n",
519
+ " assert st == snap\n",
520
+ "\n",
521
+ "\n",
522
+ "def test_clean_nops_no_aliasing():\n",
523
+ " p = [I(\"CONST\", \"x\", 1), I(\"NOP\")]\n",
524
+ " out = clean_nops(p)\n",
525
+ " out[0][\"op\"] = \"MUL\"\n",
526
+ " assert p[0][\"op\"] == \"CONST\"\n",
527
+ "\n",
528
+ "\n",
529
+ "def test_verify_rejects_empty_states():\n",
530
+ " with pytest.raises(ValueError):\n",
531
+ " verify([I(\"NOP\")], [I(\"NOP\")], [])\n",
532
+ "\n",
533
+ "\n",
534
+ "def test_verify_surfaces_execution_errors():\n",
535
+ " good = [I(\"CONST\", \"addr\", 0), I(\"CONST\", \"x\", 1), I(\"STORE\", \"addr\", \"x\")]\n",
536
+ " bad = [I(\"LOAD\", \"x\", \"missing_addr\")]\n",
537
+ " res = verify(good, bad, [{\"variables\": {}, \"memory\": {}}])\n",
538
+ " assert res[\"equivalent\"] is False\n",
539
+ " assert res[\"results\"][0][\"mismatches\"] == [\"__execution_error__\"]\n",
540
+ " assert res[\"results\"][0][\"execution_errors\"][\"optimized_error\"] is not None\n",
541
+ " assert \"original_error\" not in res[\"results\"][0][\"execution_errors\"]\n",
542
+ "\n",
543
+ "\n",
544
+ "def test_execute_rejects_bad_initial_state_shape():\n",
545
+ " r = execute([I(\"CONST\", \"x\", 1)], \"not-a-dict\")\n",
546
+ " assert r[\"success\"] is False\n",
547
+ " assert \"initial_state\" in r[\"error\"]\n",
548
+ "\n",
549
+ "\n",
550
+ "def test_compute_reduction_failure_path():\n",
551
+ " orig = [I(\"CONST\", \"addr\", 0), I(\"CONST\", \"x\", 1), I(\"STORE\", \"addr\", \"x\")]\n",
552
+ " bad = [I(\"CONST\", \"a\", 1), I(\"CONST\", \"b\", 0), I(\"DIV\", \"c\", \"a\", \"b\")]\n",
553
+ " red = compute_reduction(orig, bad, {\"variables\": {}, \"memory\": {}})\n",
554
+ " assert red[\"success\"] is False\n",
555
+ " assert red[\"relative_savings\"] is None\n",
556
+ " assert red[\"absolute_savings\"] is None\n",
557
+ " assert \"zero\" in red[\"error\"].lower()\n",
558
+ "\n",
559
+ "\n",
560
+ "def test_relative_savings_clamped_on_slowdown():\n",
561
+ " fast = [I(\"CONST\", \"addr\", 0), I(\"CONST\", \"x\", 1), I(\"STORE\", \"addr\", \"x\")]\n",
562
+ " # slower variant: extra dead MULs balloon the cycle count\n",
563
+ " slow = [I(\"CONST\", \"addr\", 0), I(\"CONST\", \"x\", 1)]\n",
564
+ " slow += [I(\"MUL\", \"junk\", \"x\", 2)] * 50\n",
565
+ " slow += [I(\"STORE\", \"addr\", \"x\")]\n",
566
+ " red = compute_reduction(fast, slow, {\"variables\": {}, \"memory\": {}})\n",
567
+ " assert red[\"absolute_savings\"] < 0\n",
568
+ " assert red[\"relative_savings\"] == -1.0 # clamped\n"
569
+ ]
570
+ },
571
+ {
572
+ "cell_type": "code",
573
+ "execution_count": null,
574
+ "id": "e6b83243",
575
+ "metadata": {},
576
+ "outputs": [],
577
+ "source": [
578
+ "# ==== CELL 6: Push to Drive ====\n",
579
+ "import shutil, os\n",
580
+ "for f in os.listdir(LOCAL_DIR):\n",
581
+ " if f.endswith(\".py\"):\n",
582
+ " shutil.copy2(os.path.join(LOCAL_DIR, f), os.path.join(DRIVE_DIR, f))\n",
583
+ "print(\"Saved to Drive:\", sorted(os.listdir(DRIVE_DIR)))\n"
584
+ ]
585
+ },
586
+ {
587
+ "cell_type": "code",
588
+ "execution_count": null,
589
+ "id": "5675f9a0",
590
+ "metadata": {},
591
+ "outputs": [],
592
+ "source": [
593
+ "# ==== CELL 7: Run tests ====\n",
594
+ "import subprocess\n",
595
+ "res = subprocess.run(\n",
596
+ " [\"python\", \"-m\", \"pytest\", \"-v\", \"test_vm.py\"],\n",
597
+ " cwd=LOCAL_DIR, capture_output=True, text=True,\n",
598
+ ")\n",
599
+ "print(res.stdout)\n",
600
+ "print(res.stderr)\n",
601
+ "assert res.returncode == 0, \"Tests failed\"\n"
602
+ ]
603
+ },
604
+ {
605
+ "cell_type": "code",
606
+ "execution_count": null,
607
+ "id": "1a500bb3",
608
+ "metadata": {},
609
+ "outputs": [],
610
+ "source": [
611
+ "# ==== CELL 8: Smoke demo ====\n",
612
+ "import importlib, toy_vm, verifier, reward_utils\n",
613
+ "importlib.reload(toy_vm); importlib.reload(verifier); importlib.reload(reward_utils)\n",
614
+ "from toy_vm import dump_ir\n",
615
+ "from reward_utils import compute_reduction\n",
616
+ "from verifier import verify\n",
617
+ "\n",
618
+ "orig = [\n",
619
+ " {\"op\":\"CONST\",\"dest\":\"addr\",\"src1\":0,\"src2\":None},\n",
620
+ " {\"op\":\"CONST\",\"dest\":\"a\",\"src1\":2,\"src2\":None},\n",
621
+ " {\"op\":\"CONST\",\"dest\":\"b\",\"src1\":3,\"src2\":None},\n",
622
+ " {\"op\":\"ADD\",\"dest\":\"c\",\"src1\":\"a\",\"src2\":\"b\"},\n",
623
+ " {\"op\":\"MUL\",\"dest\":\"d\",\"src1\":\"c\",\"src2\":2},\n",
624
+ " {\"op\":\"MUL\",\"dest\":\"dead\",\"src1\":\"d\",\"src2\":99},\n",
625
+ " {\"op\":\"STORE\",\"dest\":\"addr\",\"src1\":\"d\",\"src2\":None},\n",
626
+ "]\n",
627
+ "opt = [\n",
628
+ " {\"op\":\"CONST\",\"dest\":\"addr\",\"src1\":0,\"src2\":None},\n",
629
+ " {\"op\":\"CONST\",\"dest\":\"d\",\"src1\":10,\"src2\":None},\n",
630
+ " {\"op\":\"STORE\",\"dest\":\"addr\",\"src1\":\"d\",\"src2\":None},\n",
631
+ "]\n",
632
+ "\n",
633
+ "print(dump_ir(orig)); print(\"---\"); print(dump_ir(opt)); print(\"---\")\n",
634
+ "print(compute_reduction(orig, opt, {\"variables\":{},\"memory\":{}}))\n",
635
+ "print(\"equivalent:\", verify(orig, opt, [{\"variables\":{},\"memory\":{}}])[\"equivalent\"])\n"
636
+ ]
637
+ }
638
+ ],
639
+ "metadata": {
640
+ "kernelspec": {
641
+ "display_name": "Python 3",
642
+ "language": "python",
643
+ "name": "python3"
644
+ },
645
+ "language_info": {
646
+ "name": "python"
647
+ }
648
+ },
649
+ "nbformat": 4,
650
+ "nbformat_minor": 5
651
+ }
space/space/metahack1 (1).ipynb CHANGED
The diff for this file is too large to render. See raw diff
 
space/space/space/.DS_Store ADDED
Binary file (6.15 kB). View file
 
space/space/space/metahack1 (1).ipynb ADDED
@@ -0,0 +1,1379 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "nbformat": 4,
3
+ "nbformat_minor": 0,
4
+ "metadata": {
5
+ "colab": {
6
+ "provenance": [],
7
+ "gpuType": "T4"
8
+ },
9
+ "kernelspec": {
10
+ "name": "python3",
11
+ "display_name": "Python 3"
12
+ },
13
+ "language_info": {
14
+ "name": "python"
15
+ },
16
+ "accelerator": "GPU"
17
+ },
18
+ "cells": [
19
+ {
20
+ "cell_type": "code",
21
+ "source": [
22
+ "## Design Assumptions (do not violate)\n",
23
+ "\n",
24
+ "# 1. **DCE never eliminates STOREs.** They define program output (final mem state).\n",
25
+ "# 2. **Addresses are distinct by construction.** Generator allocates each address variable to a unique integer; no aliasing.\n",
26
+ "# 3. **CF refuses to fold DIV by zero.** If src2 == 0 on a DIV op, leave instruction unchanged.\n",
27
+ "# 4. **Generator never emits DIV by literal zero.** When DIV is generated, src2 is always a non-zero constant or a variable known to be non-zero.\n",
28
+ "# # 5. **Integer arithmetic only.** No floats anywhere — avoids equivalence-check precision issues.\n",
29
+ "# 6. Generator declares `observable_addrs` per program — verifier compares only these mem entries.\n",
30
+ "# 7. State translator annotates observable outputs at top of dump.\n",
31
+ "# 8. Reward distinguishes broken (-1000) from valid-but-worse (small negative) — Harshal's formula.\n",
32
+ "# 9. Multi-input verification: 3-5 random initial states, all must match.\n",
33
+ "# 10. Integer division uses Python floor division (//). Aarush's VM must match."
34
+ ],
35
+ "metadata": {
36
+ "id": "_XI5jT2Ibvrf"
37
+ },
38
+ "execution_count": 2,
39
+ "outputs": []
40
+ },
41
+ {
42
+ "cell_type": "code",
43
+ "execution_count": 11,
44
+ "metadata": {
45
+ "id": "j6CQ327KWXwr"
46
+ },
47
+ "outputs": [],
48
+ "source": [
49
+ "# === TAC Schema v1.0 (LOCKED with Role 1 / Aarush) ===\n",
50
+ "# Reverse passes deferred to stretch goal — not in initial action space.\n",
51
+ "\n",
52
+ "OPS = [\"CONST\", \"ADD\", \"SUB\", \"MUL\", \"DIV\", \"LOAD\", \"STORE\", \"NOP\"]\n",
53
+ "\n",
54
+ "CYCLE_COSTS = {\n",
55
+ " \"CONST\": 1,\n",
56
+ " \"ADD\": 1,\n",
57
+ " \"SUB\": 1,\n",
58
+ " \"MUL\": 3,\n",
59
+ " \"DIV\": 5,\n",
60
+ " \"LOAD\": 4,\n",
61
+ " \"STORE\": 4,\n",
62
+ " \"NOP\": 0,\n",
63
+ "}\n",
64
+ "\n",
65
+ "# Instruction shape: {\"op\": str, \"dest\": str|None, \"src1\": Any, \"src2\": Any}\n",
66
+ "# Operands: str = variable name, int = literal constant, None = unused\n",
67
+ "#\n",
68
+ "# Op semantics:\n",
69
+ "# CONST: dest = src1 (src1 is int literal, src2 = None)\n",
70
+ "# ADD/SUB/MUL/DIV: dest = src1 OP src2 (src1, src2 are var names or int literals)\n",
71
+ "# LOAD: dest = mem[src1] (src1 is a var holding an address)\n",
72
+ "# STORE: mem[dest] = src1 (dest is a var holding an address)\n",
73
+ "# NOP: no-op (all fields None)\n",
74
+ "#\n",
75
+ "# Program output (for equivalence check) = final memory state (mem dict).\n",
76
+ "# Programs ship as: (initial_vars: dict, initial_mem: dict, instructions: list[dict])"
77
+ ]
78
+ },
79
+ {
80
+ "cell_type": "code",
81
+ "source": [
82
+ "import random\n",
83
+ "\n",
84
+ "def generate_level_1():\n",
85
+ " \"\"\"\n",
86
+ " Generate a Level 1 Toy-IR program.\n",
87
+ "\n",
88
+ " Characteristics:\n",
89
+ " - 4-6 instructions\n",
90
+ " - 2-3 CONST ops with literal values\n",
91
+ " - 1-2 arithmetic ops on those constants (foldable by CF)\n",
92
+ " - 0-1 dead variables (killable by DCE)\n",
93
+ " - Exactly 1 STORE at the end so the program has an observable output\n",
94
+ "\n",
95
+ " Returns:\n",
96
+ " dict with keys: initial_vars, initial_mem, instructions, observable_addrs\n",
97
+ " \"\"\"\n",
98
+ " instructions = []\n",
99
+ " var_counter = 0\n",
100
+ "\n",
101
+ " def new_var():\n",
102
+ " nonlocal var_counter\n",
103
+ " name = f\"v{var_counter}\"\n",
104
+ " var_counter += 1\n",
105
+ " return name\n",
106
+ "\n",
107
+ " # Step 1: Generate 2-3 constant assignments\n",
108
+ " num_consts = random.randint(2, 3)\n",
109
+ " const_vars = []\n",
110
+ " for _ in range(num_consts):\n",
111
+ " var = new_var()\n",
112
+ " value = random.randint(1, 10)\n",
113
+ " instructions.append({\"op\": \"CONST\", \"dest\": var, \"src1\": value, \"src2\": None})\n",
114
+ " const_vars.append(var)\n",
115
+ "\n",
116
+ " # Step 2: Generate 1-2 arithmetic ops using those constants\n",
117
+ " num_arith = random.randint(1, 2)\n",
118
+ " last_result = None\n",
119
+ " for _ in range(num_arith):\n",
120
+ " op = random.choice([\"ADD\", \"MUL\"])\n",
121
+ " src1 = random.choice(const_vars)\n",
122
+ " src2 = random.choice(const_vars)\n",
123
+ " dest = new_var()\n",
124
+ " instructions.append({\"op\": op, \"dest\": dest, \"src1\": src1, \"src2\": src2})\n",
125
+ " last_result = dest\n",
126
+ " const_vars.append(dest)\n",
127
+ "\n",
128
+ " # Step 3: Optionally add 1 dead variable (50% chance)\n",
129
+ " if random.random() < 0.5:\n",
130
+ " dead_var = new_var()\n",
131
+ " dead_value = random.randint(1, 10)\n",
132
+ " instructions.append({\"op\": \"CONST\", \"dest\": dead_var, \"src1\": dead_value, \"src2\": None})\n",
133
+ " # Note: dead_var is intentionally never used — DCE should catch it.\n",
134
+ "\n",
135
+ " # Step 4: Add a STORE at the end so the program has observable output\n",
136
+ " initial_vars = {\"addr0\": 0}\n",
137
+ " instructions.append({\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": last_result, \"src2\": None})\n",
138
+ "\n",
139
+ " initial_mem = {}\n",
140
+ "\n",
141
+ " return {\n",
142
+ " \"initial_vars\": initial_vars,\n",
143
+ " \"initial_mem\": initial_mem,\n",
144
+ " \"instructions\": instructions,\n",
145
+ " \"observable_addrs\": [0], # Aarush's verifier compares only these mem entries\n",
146
+ " }\n",
147
+ "\n",
148
+ "\n",
149
+ "# Sanity-check: generate a few programs and print them\n",
150
+ "for seed in [42, 1, 7, 99]:\n",
151
+ " random.seed(seed)\n",
152
+ " prog = generate_level_1()\n",
153
+ " print(f\"\\n=== seed={seed} ===\")\n",
154
+ " print(f\"initial_vars : {prog['initial_vars']}\")\n",
155
+ " print(f\"initial_mem : {prog['initial_mem']}\")\n",
156
+ " print(f\"observable_addrs : {prog['observable_addrs']}\")\n",
157
+ " print(f\"instructions ({len(prog['instructions'])}):\")\n",
158
+ " for i, instr in enumerate(prog['instructions']):\n",
159
+ " print(f\" {i}: {instr}\")"
160
+ ],
161
+ "metadata": {
162
+ "colab": {
163
+ "base_uri": "https://localhost:8080/"
164
+ },
165
+ "id": "a86vD1OyWcB9",
166
+ "outputId": "2d6d4604-6dc1-4c29-af64-e41cf5717c0d"
167
+ },
168
+ "execution_count": 4,
169
+ "outputs": [
170
+ {
171
+ "output_type": "stream",
172
+ "name": "stdout",
173
+ "text": [
174
+ "\n",
175
+ "=== seed=42 ===\n",
176
+ "initial_vars : {'addr0': 0}\n",
177
+ "initial_mem : {}\n",
178
+ "observable_addrs : [0]\n",
179
+ "instructions (4):\n",
180
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 1, 'src2': None}\n",
181
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 5, 'src2': None}\n",
182
+ " 2: {'op': 'ADD', 'dest': 'v2', 'src1': 'v0', 'src2': 'v0'}\n",
183
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v2', 'src2': None}\n",
184
+ "\n",
185
+ "=== seed=1 ===\n",
186
+ "initial_vars : {'addr0': 0}\n",
187
+ "initial_mem : {}\n",
188
+ "observable_addrs : [0]\n",
189
+ "instructions (5):\n",
190
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 10, 'src2': None}\n",
191
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 2, 'src2': None}\n",
192
+ " 2: {'op': 'ADD', 'dest': 'v2', 'src1': 'v1', 'src2': 'v1'}\n",
193
+ " 3: {'op': 'MUL', 'dest': 'v3', 'src1': 'v2', 'src2': 'v1'}\n",
194
+ " 4: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v3', 'src2': None}\n",
195
+ "\n",
196
+ "=== seed=7 ===\n",
197
+ "initial_vars : {'addr0': 0}\n",
198
+ "initial_mem : {}\n",
199
+ "observable_addrs : [0]\n",
200
+ "instructions (6):\n",
201
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 3, 'src2': None}\n",
202
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 7, 'src2': None}\n",
203
+ " 2: {'op': 'CONST', 'dest': 'v2', 'src1': 1, 'src2': None}\n",
204
+ " 3: {'op': 'ADD', 'dest': 'v3', 'src1': 'v1', 'src2': 'v2'}\n",
205
+ " 4: {'op': 'CONST', 'dest': 'v4', 'src1': 9, 'src2': None}\n",
206
+ " 5: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v3', 'src2': None}\n",
207
+ "\n",
208
+ "=== seed=99 ===\n",
209
+ "initial_vars : {'addr0': 0}\n",
210
+ "initial_mem : {}\n",
211
+ "observable_addrs : [0]\n",
212
+ "instructions (5):\n",
213
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 7, 'src2': None}\n",
214
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 4, 'src2': None}\n",
215
+ " 2: {'op': 'CONST', 'dest': 'v2', 'src1': 10, 'src2': None}\n",
216
+ " 3: {'op': 'ADD', 'dest': 'v3', 'src1': 'v0', 'src2': 'v0'}\n",
217
+ " 4: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v3', 'src2': None}\n"
218
+ ]
219
+ }
220
+ ]
221
+ },
222
+ {
223
+ "cell_type": "code",
224
+ "source": [
225
+ "def _resolve_operand(operand, known_constants):\n",
226
+ " \"\"\"\n",
227
+ " Given a TAC operand (string variable name or int literal),\n",
228
+ " return its concrete integer value if known, or None if unknown.\n",
229
+ " \"\"\"\n",
230
+ " if isinstance(operand, int):\n",
231
+ " return operand\n",
232
+ " if isinstance(operand, str) and operand in known_constants:\n",
233
+ " return known_constants[operand]\n",
234
+ " return None\n",
235
+ "\n",
236
+ "\n",
237
+ "def _compute(op, v1, v2):\n",
238
+ " \"\"\"Compute the result of a binary arithmetic op on two known integers.\"\"\"\n",
239
+ " if op == \"ADD\": return v1 + v2\n",
240
+ " if op == \"SUB\": return v1 - v2\n",
241
+ " if op == \"MUL\": return v1 * v2\n",
242
+ " if op == \"DIV\": return v1 // v2 # floor division (locked semantics)\n",
243
+ " raise ValueError(f\"_compute called with non-arithmetic op: {op}\")\n",
244
+ "\n",
245
+ "\n",
246
+ "def constant_folding(program):\n",
247
+ " \"\"\"\n",
248
+ " Forward pass that folds constant arithmetic into CONST ops, and\n",
249
+ " propagates known constants into instruction operands.\n",
250
+ "\n",
251
+ " Behavior:\n",
252
+ " - If both sources of an arithmetic op resolve to known integers,\n",
253
+ " replaces the instruction with a CONST holding the computed result.\n",
254
+ " - If only one source is known, still substitutes that known value\n",
255
+ " into the instruction (constant propagation), enabling downstream\n",
256
+ " passes (e.g., peephole) to recognize patterns like ADD-with-0 or MUL-by-1.\n",
257
+ " - Refuses to fold DIV by zero (Design Assumption #3).\n",
258
+ " - Always returns fresh dicts; never aliases input instructions.\n",
259
+ "\n",
260
+ " Args:\n",
261
+ " program: list of TAC instruction dicts (per locked schema).\n",
262
+ "\n",
263
+ " Returns:\n",
264
+ " new list of TAC instruction dicts. Always semantics-preserving.\n",
265
+ " Never raises, never returns None.\n",
266
+ " \"\"\"\n",
267
+ " known_constants = {}\n",
268
+ " new_program = []\n",
269
+ "\n",
270
+ " for instr in program:\n",
271
+ " # Always work on a copy — never alias input dicts\n",
272
+ " instr = instr.copy()\n",
273
+ " op = instr[\"op\"]\n",
274
+ " dest = instr[\"dest\"]\n",
275
+ "\n",
276
+ " if op == \"CONST\":\n",
277
+ " known_constants[dest] = instr[\"src1\"]\n",
278
+ " new_program.append(instr)\n",
279
+ "\n",
280
+ " elif op in (\"ADD\", \"SUB\", \"MUL\", \"DIV\"):\n",
281
+ " # === Constant propagation: substitute known constants into operands ===\n",
282
+ " if isinstance(instr[\"src1\"], str) and instr[\"src1\"] in known_constants:\n",
283
+ " instr[\"src1\"] = known_constants[instr[\"src1\"]]\n",
284
+ " if isinstance(instr[\"src2\"], str) and instr[\"src2\"] in known_constants:\n",
285
+ " instr[\"src2\"] = known_constants[instr[\"src2\"]]\n",
286
+ "\n",
287
+ " # === Try to fold ===\n",
288
+ " v1 = _resolve_operand(instr[\"src1\"], known_constants)\n",
289
+ " v2 = _resolve_operand(instr[\"src2\"], known_constants)\n",
290
+ "\n",
291
+ " if v1 is not None and v2 is not None:\n",
292
+ " # Both operands are known integers\n",
293
+ " if op == \"DIV\" and v2 == 0:\n",
294
+ " # Refuse to fold DIV by zero\n",
295
+ " new_program.append(instr)\n",
296
+ " known_constants.pop(dest, None)\n",
297
+ " else:\n",
298
+ " # Fold: replace with CONST\n",
299
+ " result = _compute(op, v1, v2)\n",
300
+ " new_program.append({\n",
301
+ " \"op\": \"CONST\",\n",
302
+ " \"dest\": dest,\n",
303
+ " \"src1\": result,\n",
304
+ " \"src2\": None,\n",
305
+ " })\n",
306
+ " known_constants[dest] = result\n",
307
+ " else:\n",
308
+ " # Can't fold (at least one operand unknown).\n",
309
+ " # Instruction may still have been mutated by propagation above.\n",
310
+ " new_program.append(instr)\n",
311
+ " known_constants.pop(dest, None)\n",
312
+ "\n",
313
+ " elif op == \"LOAD\":\n",
314
+ " # Memory reads aren't statically resolvable\n",
315
+ " new_program.append(instr)\n",
316
+ " known_constants.pop(dest, None)\n",
317
+ "\n",
318
+ " elif op in (\"STORE\", \"NOP\"):\n",
319
+ " # No dest tracking needed.\n",
320
+ " # Note: we COULD propagate src1 into a STORE for downstream readability,\n",
321
+ " # but the cycle cost is unchanged and the executor handles vars fine.\n",
322
+ " # Leave STORE alone — keeps the code minimal.\n",
323
+ " new_program.append(instr)\n",
324
+ "\n",
325
+ " else:\n",
326
+ " # Unknown op — defensive pass-through\n",
327
+ " new_program.append(instr)\n",
328
+ "\n",
329
+ " return new_program"
330
+ ],
331
+ "metadata": {
332
+ "id": "CGk8Fz4CZA3t"
333
+ },
334
+ "execution_count": 5,
335
+ "outputs": []
336
+ },
337
+ {
338
+ "cell_type": "code",
339
+ "source": [
340
+ "# === Sanity tests for constant_folding ===\n",
341
+ "\n",
342
+ "# Test 1: simple fold — ADD of two CONSTs\n",
343
+ "test1 = [\n",
344
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 3, \"src2\": None},\n",
345
+ " {\"op\": \"CONST\", \"dest\": \"b\", \"src1\": 5, \"src2\": None},\n",
346
+ " {\"op\": \"ADD\", \"dest\": \"c\", \"src1\": \"a\", \"src2\": \"b\"},\n",
347
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"c\", \"src2\": None},\n",
348
+ "]\n",
349
+ "result1 = constant_folding(test1)\n",
350
+ "print(\"Test 1 (simple ADD fold):\")\n",
351
+ "for i, instr in enumerate(result1): print(f\" {i}: {instr}\")\n",
352
+ "# Expected: instruction 2 becomes CONST c = 8\n",
353
+ "\n",
354
+ "# Test 2: chained fold — second op uses first op's folded result\n",
355
+ "test2 = [\n",
356
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 3, \"src2\": None},\n",
357
+ " {\"op\": \"CONST\", \"dest\": \"b\", \"src1\": 5, \"src2\": None},\n",
358
+ " {\"op\": \"ADD\", \"dest\": \"c\", \"src1\": \"a\", \"src2\": \"b\"}, # → 8\n",
359
+ " {\"op\": \"MUL\", \"dest\": \"d\", \"src1\": \"c\", \"src2\": \"b\"}, # → 8 * 5 = 40\n",
360
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"d\", \"src2\": None},\n",
361
+ "]\n",
362
+ "result2 = constant_folding(test2)\n",
363
+ "print(\"\\nTest 2 (chained fold):\")\n",
364
+ "for i, instr in enumerate(result2): print(f\" {i}: {instr}\")\n",
365
+ "# Expected: c becomes CONST 8, d becomes CONST 40\n",
366
+ "\n",
367
+ "# Test 3: DIV by zero refused\n",
368
+ "test3 = [\n",
369
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 10, \"src2\": None},\n",
370
+ " {\"op\": \"CONST\", \"dest\": \"b\", \"src1\": 0, \"src2\": None},\n",
371
+ " {\"op\": \"DIV\", \"dest\": \"c\", \"src1\": \"a\", \"src2\": \"b\"}, # 10/0 — must NOT fold\n",
372
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"c\", \"src2\": None},\n",
373
+ "]\n",
374
+ "result3 = constant_folding(test3)\n",
375
+ "print(\"\\nTest 3 (DIV by zero refused):\")\n",
376
+ "for i, instr in enumerate(result3): print(f\" {i}: {instr}\")\n",
377
+ "# Expected: instruction 2 unchanged (still DIV, not CONST)\n",
378
+ "\n",
379
+ "# Test 4: unknown source can't fold\n",
380
+ "test4 = [\n",
381
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 3, \"src2\": None},\n",
382
+ " {\"op\": \"LOAD\", \"dest\": \"b\", \"src1\": \"addr0\", \"src2\": None}, # b is unknown\n",
383
+ " {\"op\": \"ADD\", \"dest\": \"c\", \"src1\": \"a\", \"src2\": \"b\"}, # can't fold\n",
384
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"c\", \"src2\": None},\n",
385
+ "]\n",
386
+ "result4 = constant_folding(test4)\n",
387
+ "print(\"\\nTest 4 (LOAD makes b unknown, ADD not folded):\")\n",
388
+ "for i, instr in enumerate(result4): print(f\" {i}: {instr}\")\n",
389
+ "# Expected: instruction 2 unchanged (still ADD)\n",
390
+ "\n",
391
+ "# Test 5: idempotence — running CF on a generated program\n",
392
+ "random.seed(42)\n",
393
+ "prog = generate_level_1()\n",
394
+ "folded = constant_folding(prog[\"instructions\"])\n",
395
+ "print(\"\\nTest 5 (CF on generated Level 1 program, seed=42):\")\n",
396
+ "print(\"Before:\")\n",
397
+ "for i, instr in enumerate(prog[\"instructions\"]): print(f\" {i}: {instr}\")\n",
398
+ "print(\"After:\")\n",
399
+ "for i, instr in enumerate(folded): print(f\" {i}: {instr}\")\n",
400
+ "\n",
401
+ "# Test 6: constant propagation — only one source is known\n",
402
+ "test6 = [\n",
403
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 0, \"src2\": None},\n",
404
+ " {\"op\": \"LOAD\", \"dest\": \"b\", \"src1\": \"addr0\", \"src2\": None}, # b unknown\n",
405
+ " {\"op\": \"ADD\", \"dest\": \"c\", \"src1\": \"a\", \"src2\": \"b\"}, # a known (=0), b unknown\n",
406
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"c\", \"src2\": None},\n",
407
+ "]\n",
408
+ "result6 = constant_folding(test6)\n",
409
+ "print(\"\\nTest 6 (propagation: a=0 substituted into ADD even though b unknown):\")\n",
410
+ "for i, instr in enumerate(result6): print(f\" {i}: {instr}\")\n",
411
+ "# Expected: instruction 2 is still ADD (can't fold — b unknown), but src1 is now literal 0, not 'a'\n",
412
+ "# This sets up peephole to recognize \"ADD with 0\" later"
413
+ ],
414
+ "metadata": {
415
+ "colab": {
416
+ "base_uri": "https://localhost:8080/"
417
+ },
418
+ "id": "WLKSTVa8fRF8",
419
+ "outputId": "e9480e1e-5d59-4afe-a884-bae0fa4a2192"
420
+ },
421
+ "execution_count": 6,
422
+ "outputs": [
423
+ {
424
+ "output_type": "stream",
425
+ "name": "stdout",
426
+ "text": [
427
+ "Test 1 (simple ADD fold):\n",
428
+ " 0: {'op': 'CONST', 'dest': 'a', 'src1': 3, 'src2': None}\n",
429
+ " 1: {'op': 'CONST', 'dest': 'b', 'src1': 5, 'src2': None}\n",
430
+ " 2: {'op': 'CONST', 'dest': 'c', 'src1': 8, 'src2': None}\n",
431
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'c', 'src2': None}\n",
432
+ "\n",
433
+ "Test 2 (chained fold):\n",
434
+ " 0: {'op': 'CONST', 'dest': 'a', 'src1': 3, 'src2': None}\n",
435
+ " 1: {'op': 'CONST', 'dest': 'b', 'src1': 5, 'src2': None}\n",
436
+ " 2: {'op': 'CONST', 'dest': 'c', 'src1': 8, 'src2': None}\n",
437
+ " 3: {'op': 'CONST', 'dest': 'd', 'src1': 40, 'src2': None}\n",
438
+ " 4: {'op': 'STORE', 'dest': 'addr0', 'src1': 'd', 'src2': None}\n",
439
+ "\n",
440
+ "Test 3 (DIV by zero refused):\n",
441
+ " 0: {'op': 'CONST', 'dest': 'a', 'src1': 10, 'src2': None}\n",
442
+ " 1: {'op': 'CONST', 'dest': 'b', 'src1': 0, 'src2': None}\n",
443
+ " 2: {'op': 'DIV', 'dest': 'c', 'src1': 10, 'src2': 0}\n",
444
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'c', 'src2': None}\n",
445
+ "\n",
446
+ "Test 4 (LOAD makes b unknown, ADD not folded):\n",
447
+ " 0: {'op': 'CONST', 'dest': 'a', 'src1': 3, 'src2': None}\n",
448
+ " 1: {'op': 'LOAD', 'dest': 'b', 'src1': 'addr0', 'src2': None}\n",
449
+ " 2: {'op': 'ADD', 'dest': 'c', 'src1': 3, 'src2': 'b'}\n",
450
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'c', 'src2': None}\n",
451
+ "\n",
452
+ "Test 5 (CF on generated Level 1 program, seed=42):\n",
453
+ "Before:\n",
454
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 1, 'src2': None}\n",
455
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 5, 'src2': None}\n",
456
+ " 2: {'op': 'ADD', 'dest': 'v2', 'src1': 'v0', 'src2': 'v0'}\n",
457
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v2', 'src2': None}\n",
458
+ "After:\n",
459
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 1, 'src2': None}\n",
460
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 5, 'src2': None}\n",
461
+ " 2: {'op': 'CONST', 'dest': 'v2', 'src1': 2, 'src2': None}\n",
462
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v2', 'src2': None}\n",
463
+ "\n",
464
+ "Test 6 (propagation: a=0 substituted into ADD even though b unknown):\n",
465
+ " 0: {'op': 'CONST', 'dest': 'a', 'src1': 0, 'src2': None}\n",
466
+ " 1: {'op': 'LOAD', 'dest': 'b', 'src1': 'addr0', 'src2': None}\n",
467
+ " 2: {'op': 'ADD', 'dest': 'c', 'src1': 0, 'src2': 'b'}\n",
468
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'c', 'src2': None}\n"
469
+ ]
470
+ }
471
+ ]
472
+ },
473
+ {
474
+ "cell_type": "code",
475
+ "source": [
476
+ "def dead_code_elimination(program):\n",
477
+ " \"\"\"\n",
478
+ " Backward liveness analysis. Replace dead instructions with NOPs,\n",
479
+ " then strip NOPs.\n",
480
+ "\n",
481
+ " Rules:\n",
482
+ " - STOREs are always live (define program output).\n",
483
+ " - Address variables used in STORE/LOAD are always live.\n",
484
+ " - Any instruction whose dest is never read later is dead.\n",
485
+ "\n",
486
+ " Returns a fresh list of instruction dicts. Never raises, never returns None.\n",
487
+ " \"\"\"\n",
488
+ " # Walk backward, build new program in reverse, then re-reverse at the end\n",
489
+ " live = set()\n",
490
+ " new_program_reversed = []\n",
491
+ "\n",
492
+ " for instr in reversed(program):\n",
493
+ " instr = instr.copy() # never alias input\n",
494
+ " op = instr[\"op\"]\n",
495
+ " dest = instr[\"dest\"]\n",
496
+ " src1 = instr[\"src1\"]\n",
497
+ " src2 = instr[\"src2\"]\n",
498
+ "\n",
499
+ " if op == \"STORE\":\n",
500
+ " # STOREs are always kept; mark sources live\n",
501
+ " if isinstance(src1, str): live.add(src1)\n",
502
+ " if isinstance(dest, str): live.add(dest) # address variable\n",
503
+ " new_program_reversed.append(instr)\n",
504
+ "\n",
505
+ " elif op == \"NOP\":\n",
506
+ " # Pass through; will be stripped at the end\n",
507
+ " new_program_reversed.append(instr)\n",
508
+ "\n",
509
+ " elif op in (\"CONST\", \"ADD\", \"SUB\", \"MUL\", \"DIV\", \"LOAD\"):\n",
510
+ " if dest in live:\n",
511
+ " # Live instruction — keep it, mark its sources live\n",
512
+ " live.discard(dest)\n",
513
+ " if isinstance(src1, str): live.add(src1)\n",
514
+ " if isinstance(src2, str): live.add(src2)\n",
515
+ " new_program_reversed.append(instr)\n",
516
+ " else:\n",
517
+ " # Dead — replace with NOP\n",
518
+ " new_program_reversed.append({\n",
519
+ " \"op\": \"NOP\", \"dest\": None, \"src1\": None, \"src2\": None,\n",
520
+ " })\n",
521
+ "\n",
522
+ " else:\n",
523
+ " # Unknown op — defensive pass-through\n",
524
+ " new_program_reversed.append(instr)\n",
525
+ "\n",
526
+ " # Reverse back to forward order, then strip NOPs\n",
527
+ " new_program = list(reversed(new_program_reversed))\n",
528
+ " new_program = [instr for instr in new_program if instr[\"op\"] != \"NOP\"]\n",
529
+ "\n",
530
+ " return new_program"
531
+ ],
532
+ "metadata": {
533
+ "id": "5vo-KgaffTFR"
534
+ },
535
+ "execution_count": 12,
536
+ "outputs": []
537
+ },
538
+ {
539
+ "cell_type": "code",
540
+ "source": [
541
+ "# === Sanity tests for dead_code_elimination ===\n",
542
+ "\n",
543
+ "# Test 1: simple dead variable\n",
544
+ "test1 = [\n",
545
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 5, \"src2\": None},\n",
546
+ " {\"op\": \"CONST\", \"dest\": \"dead\", \"src1\": 99, \"src2\": None}, # never used\n",
547
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"a\", \"src2\": None},\n",
548
+ "]\n",
549
+ "result1 = dead_code_elimination(test1)\n",
550
+ "print(\"Test 1 (kill unused CONST):\")\n",
551
+ "for i, instr in enumerate(result1): print(f\" {i}: {instr}\")\n",
552
+ "# Expected: 'dead' instruction removed, 2 instructions remain\n",
553
+ "\n",
554
+ "# Test 2: chain of dead computation\n",
555
+ "test2 = [\n",
556
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 5, \"src2\": None},\n",
557
+ " {\"op\": \"CONST\", \"dest\": \"b\", \"src1\": 3, \"src2\": None},\n",
558
+ " {\"op\": \"ADD\", \"dest\": \"x\", \"src1\": \"a\", \"src2\": \"b\"}, # x never used → dead\n",
559
+ " {\"op\": \"CONST\", \"dest\": \"c\", \"src1\": 7, \"src2\": None},\n",
560
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"c\", \"src2\": None},\n",
561
+ "]\n",
562
+ "result2 = dead_code_elimination(test2)\n",
563
+ "print(\"\\nTest 2 (kill unused ADD and its feeders... but only if feeders are also unused):\")\n",
564
+ "for i, instr in enumerate(result2): print(f\" {i}: {instr}\")\n",
565
+ "# Expected: x's ADD killed. a and b also killed (only fed into x, which is dead).\n",
566
+ "# Final: just CONST c=7, STORE.\n",
567
+ "\n",
568
+ "# Test 3: STORE always preserved\n",
569
+ "test3 = [\n",
570
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 5, \"src2\": None},\n",
571
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"a\", \"src2\": None},\n",
572
+ "]\n",
573
+ "result3 = dead_code_elimination(test3)\n",
574
+ "print(\"\\nTest 3 (STORE preserved, feeder kept live):\")\n",
575
+ "for i, instr in enumerate(result3): print(f\" {i}: {instr}\")\n",
576
+ "# Expected: both instructions unchanged\n",
577
+ "\n",
578
+ "# Test 4: variable used by STORE is live, even if defined far above\n",
579
+ "test4 = [\n",
580
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 5, \"src2\": None}, # used by STORE → live\n",
581
+ " {\"op\": \"CONST\", \"dest\": \"b\", \"src1\": 9, \"src2\": None}, # never used → dead\n",
582
+ " {\"op\": \"CONST\", \"dest\": \"c\", \"src1\": 1, \"src2\": None}, # never used → dead\n",
583
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"a\", \"src2\": None},\n",
584
+ "]\n",
585
+ "result4 = dead_code_elimination(test4)\n",
586
+ "print(\"\\nTest 4 (only 'a' is live, b/c killed):\")\n",
587
+ "for i, instr in enumerate(result4): print(f\" {i}: {instr}\")\n",
588
+ "# Expected: a's CONST + STORE remain. b, c stripped.\n",
589
+ "\n",
590
+ "# Test 5: combine CF + DCE on a generated program\n",
591
+ "random.seed(42)\n",
592
+ "prog = generate_level_1()\n",
593
+ "print(\"\\nTest 5 (CF then DCE on seed=42):\")\n",
594
+ "print(\"Original:\")\n",
595
+ "for i, instr in enumerate(prog[\"instructions\"]): print(f\" {i}: {instr}\")\n",
596
+ "\n",
597
+ "after_cf = constant_folding(prog[\"instructions\"])\n",
598
+ "print(\"After CF:\")\n",
599
+ "for i, instr in enumerate(after_cf): print(f\" {i}: {instr}\")\n",
600
+ "\n",
601
+ "after_dce = dead_code_elimination(after_cf)\n",
602
+ "print(\"After CF + DCE:\")\n",
603
+ "for i, instr in enumerate(after_dce): print(f\" {i}: {instr}\")\n",
604
+ "# Expected: original 4 instructions become much shorter — dead 'v1' eliminated, v2 folded\n",
605
+ "\n",
606
+ "# Test 6: idempotence — running DCE twice gives same result\n",
607
+ "test6 = [\n",
608
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 5, \"src2\": None},\n",
609
+ " {\"op\": \"CONST\", \"dest\": \"dead\", \"src1\": 99, \"src2\": None},\n",
610
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"a\", \"src2\": None},\n",
611
+ "]\n",
612
+ "once = dead_code_elimination(test6)\n",
613
+ "twice = dead_code_elimination(once)\n",
614
+ "print(\"\\nTest 6 (idempotence):\", \"PASS\" if once == twice else \"FAIL\")"
615
+ ],
616
+ "metadata": {
617
+ "colab": {
618
+ "base_uri": "https://localhost:8080/"
619
+ },
620
+ "id": "vv8QRFRlvzdq",
621
+ "outputId": "e1d35874-ff1a-4dec-f43f-e22867dd3911"
622
+ },
623
+ "execution_count": 8,
624
+ "outputs": [
625
+ {
626
+ "output_type": "stream",
627
+ "name": "stdout",
628
+ "text": [
629
+ "Test 1 (kill unused CONST):\n",
630
+ " 0: {'op': 'CONST', 'dest': 'a', 'src1': 5, 'src2': None}\n",
631
+ " 1: {'op': 'STORE', 'dest': 'addr0', 'src1': 'a', 'src2': None}\n",
632
+ "\n",
633
+ "Test 2 (kill unused ADD and its feeders... but only if feeders are also unused):\n",
634
+ " 0: {'op': 'CONST', 'dest': 'c', 'src1': 7, 'src2': None}\n",
635
+ " 1: {'op': 'STORE', 'dest': 'addr0', 'src1': 'c', 'src2': None}\n",
636
+ "\n",
637
+ "Test 3 (STORE preserved, feeder kept live):\n",
638
+ " 0: {'op': 'CONST', 'dest': 'a', 'src1': 5, 'src2': None}\n",
639
+ " 1: {'op': 'STORE', 'dest': 'addr0', 'src1': 'a', 'src2': None}\n",
640
+ "\n",
641
+ "Test 4 (only 'a' is live, b/c killed):\n",
642
+ " 0: {'op': 'CONST', 'dest': 'a', 'src1': 5, 'src2': None}\n",
643
+ " 1: {'op': 'STORE', 'dest': 'addr0', 'src1': 'a', 'src2': None}\n",
644
+ "\n",
645
+ "Test 5 (CF then DCE on seed=42):\n",
646
+ "Original:\n",
647
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 1, 'src2': None}\n",
648
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 5, 'src2': None}\n",
649
+ " 2: {'op': 'ADD', 'dest': 'v2', 'src1': 'v0', 'src2': 'v0'}\n",
650
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v2', 'src2': None}\n",
651
+ "After CF:\n",
652
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 1, 'src2': None}\n",
653
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 5, 'src2': None}\n",
654
+ " 2: {'op': 'CONST', 'dest': 'v2', 'src1': 2, 'src2': None}\n",
655
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v2', 'src2': None}\n",
656
+ "After CF + DCE:\n",
657
+ " 0: {'op': 'CONST', 'dest': 'v2', 'src1': 2, 'src2': None}\n",
658
+ " 1: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v2', 'src2': None}\n",
659
+ "\n",
660
+ "Test 6 (idempotence): PASS\n"
661
+ ]
662
+ }
663
+ ]
664
+ },
665
+ {
666
+ "cell_type": "code",
667
+ "source": [
668
+ "def peephole_optimization(program):\n",
669
+ " \"\"\"\n",
670
+ " Single-instruction peephole rewrites. Replaces expensive ops with\n",
671
+ " cheaper equivalents when operands hit special values (0, 1, 2, self).\n",
672
+ "\n",
673
+ " Patterns (all preserve semantics):\n",
674
+ " MUL by 2 -> ADD x + x\n",
675
+ " MUL by 1 -> CONST (the other operand)\n",
676
+ " MUL by 0 -> CONST 0\n",
677
+ " ADD with 0 -> CONST (the other operand)\n",
678
+ " SUB x - x -> CONST 0\n",
679
+ " DIV by 1 -> CONST (the dividend)\n",
680
+ "\n",
681
+ " Notes:\n",
682
+ " - Operates on individual instructions; no cross-instruction state.\n",
683
+ " - Relies on constant_folding having propagated literal values into operands.\n",
684
+ " - Returns fresh instruction dicts; never aliases inputs.\n",
685
+ "\n",
686
+ " Returns a new list. Never raises, never returns None.\n",
687
+ " \"\"\"\n",
688
+ " new_program = []\n",
689
+ "\n",
690
+ " for instr in program:\n",
691
+ " instr = instr.copy()\n",
692
+ " op = instr[\"op\"]\n",
693
+ " dest = instr[\"dest\"]\n",
694
+ " src1 = instr[\"src1\"]\n",
695
+ " src2 = instr[\"src2\"]\n",
696
+ "\n",
697
+ " # === MUL patterns ===\n",
698
+ " if op == \"MUL\":\n",
699
+ " # MUL by 0 -> CONST 0\n",
700
+ " if src1 == 0 or src2 == 0:\n",
701
+ " new_program.append({\"op\": \"CONST\", \"dest\": dest, \"src1\": 0, \"src2\": None})\n",
702
+ " continue\n",
703
+ " # MUL by 1 -> CONST (other operand) if the other operand is a literal,\n",
704
+ " # otherwise leave alone (we don't want to introduce a useless\n",
705
+ " # \"CONST dest = some_var_name\" — that's not a valid CONST).\n",
706
+ " if src1 == 1 and isinstance(src2, int):\n",
707
+ " new_program.append({\"op\": \"CONST\", \"dest\": dest, \"src1\": src2, \"src2\": None})\n",
708
+ " continue\n",
709
+ " if src2 == 1 and isinstance(src1, int):\n",
710
+ " new_program.append({\"op\": \"CONST\", \"dest\": dest, \"src1\": src1, \"src2\": None})\n",
711
+ " continue\n",
712
+ " # MUL by 2 -> ADD x + x (when one operand is literal 2 and the other is a var)\n",
713
+ " if src1 == 2 and isinstance(src2, str):\n",
714
+ " new_program.append({\"op\": \"ADD\", \"dest\": dest, \"src1\": src2, \"src2\": src2})\n",
715
+ " continue\n",
716
+ " if src2 == 2 and isinstance(src1, str):\n",
717
+ " new_program.append({\"op\": \"ADD\", \"dest\": dest, \"src1\": src1, \"src2\": src1})\n",
718
+ " continue\n",
719
+ " # No pattern matched — keep as is\n",
720
+ " new_program.append(instr)\n",
721
+ "\n",
722
+ " # === ADD patterns ===\n",
723
+ " elif op == \"ADD\":\n",
724
+ " # ADD with 0 -> CONST (other operand) if the other operand is a literal\n",
725
+ " if src1 == 0 and isinstance(src2, int):\n",
726
+ " new_program.append({\"op\": \"CONST\", \"dest\": dest, \"src1\": src2, \"src2\": None})\n",
727
+ " continue\n",
728
+ " if src2 == 0 and isinstance(src1, int):\n",
729
+ " new_program.append({\"op\": \"CONST\", \"dest\": dest, \"src1\": src1, \"src2\": None})\n",
730
+ " continue\n",
731
+ " # If \"ADD x + 0\" where x is a variable, we'd want a copy — but our schema\n",
732
+ " # has no MOV/COPY op. Leave alone; CF + DCE handle the rest in practice.\n",
733
+ " new_program.append(instr)\n",
734
+ "\n",
735
+ " # === SUB patterns ===\n",
736
+ " elif op == \"SUB\":\n",
737
+ " # SUB x - x -> CONST 0 (only if both sources are the same string variable)\n",
738
+ " if isinstance(src1, str) and isinstance(src2, str) and src1 == src2:\n",
739
+ " new_program.append({\"op\": \"CONST\", \"dest\": dest, \"src1\": 0, \"src2\": None})\n",
740
+ " continue\n",
741
+ " # SUB x - 0 with literal 0 on src2 — we'd want a copy; skip (no COPY op)\n",
742
+ " new_program.append(instr)\n",
743
+ "\n",
744
+ " # === DIV patterns ===\n",
745
+ " elif op == \"DIV\":\n",
746
+ " # DIV by 1 -> CONST (dividend) if dividend is a literal\n",
747
+ " if src2 == 1 and isinstance(src1, int):\n",
748
+ " new_program.append({\"op\": \"CONST\", \"dest\": dest, \"src1\": src1, \"src2\": None})\n",
749
+ " continue\n",
750
+ " new_program.append(instr)\n",
751
+ "\n",
752
+ " else:\n",
753
+ " # CONST, LOAD, STORE, NOP — pass through\n",
754
+ " new_program.append(instr)\n",
755
+ "\n",
756
+ " return new_program"
757
+ ],
758
+ "metadata": {
759
+ "id": "IaczDNeLv5PW"
760
+ },
761
+ "execution_count": 9,
762
+ "outputs": []
763
+ },
764
+ {
765
+ "cell_type": "code",
766
+ "source": [
767
+ "# === Sanity tests for peephole_optimization ===\n",
768
+ "\n",
769
+ "# Test 1: MUL by 2 -> ADD x+x\n",
770
+ "test1 = [\n",
771
+ " {\"op\": \"LOAD\", \"dest\": \"y\", \"src1\": \"addr0\", \"src2\": None},\n",
772
+ " {\"op\": \"MUL\", \"dest\": \"x\", \"src1\": \"y\", \"src2\": 2},\n",
773
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"x\", \"src2\": None},\n",
774
+ "]\n",
775
+ "result1 = peephole_optimization(test1)\n",
776
+ "print(\"Test 1 (MUL by 2 -> ADD self):\")\n",
777
+ "for i, instr in enumerate(result1): print(f\" {i}: {instr}\")\n",
778
+ "# Expected: instruction 1 becomes ADD y+y\n",
779
+ "\n",
780
+ "# Test 2: MUL by 0 -> CONST 0\n",
781
+ "test2 = [\n",
782
+ " {\"op\": \"LOAD\", \"dest\": \"y\", \"src1\": \"addr0\", \"src2\": None},\n",
783
+ " {\"op\": \"MUL\", \"dest\": \"x\", \"src1\": \"y\", \"src2\": 0},\n",
784
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"x\", \"src2\": None},\n",
785
+ "]\n",
786
+ "result2 = peephole_optimization(test2)\n",
787
+ "print(\"\\nTest 2 (MUL by 0 -> CONST 0):\")\n",
788
+ "for i, instr in enumerate(result2): print(f\" {i}: {instr}\")\n",
789
+ "# Expected: instruction 1 becomes CONST x = 0\n",
790
+ "\n",
791
+ "# Test 3: MUL by 1 (both literals)\n",
792
+ "test3 = [\n",
793
+ " {\"op\": \"MUL\", \"dest\": \"x\", \"src1\": 7, \"src2\": 1},\n",
794
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"x\", \"src2\": None},\n",
795
+ "]\n",
796
+ "result3 = peephole_optimization(test3)\n",
797
+ "print(\"\\nTest 3 (MUL 7*1 -> CONST 7):\")\n",
798
+ "for i, instr in enumerate(result3): print(f\" {i}: {instr}\")\n",
799
+ "# Expected: instruction 0 becomes CONST x = 7\n",
800
+ "\n",
801
+ "# Test 4: SUB x - x -> CONST 0\n",
802
+ "test4 = [\n",
803
+ " {\"op\": \"LOAD\", \"dest\": \"y\", \"src1\": \"addr0\", \"src2\": None},\n",
804
+ " {\"op\": \"SUB\", \"dest\": \"x\", \"src1\": \"y\", \"src2\": \"y\"},\n",
805
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"x\", \"src2\": None},\n",
806
+ "]\n",
807
+ "result4 = peephole_optimization(test4)\n",
808
+ "print(\"\\nTest 4 (SUB y-y -> CONST 0):\")\n",
809
+ "for i, instr in enumerate(result4): print(f\" {i}: {instr}\")\n",
810
+ "# Expected: instruction 1 becomes CONST x = 0\n",
811
+ "\n",
812
+ "# Test 5: ADD with 0\n",
813
+ "test5 = [\n",
814
+ " {\"op\": \"ADD\", \"dest\": \"x\", \"src1\": 0, \"src2\": 5},\n",
815
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"x\", \"src2\": None},\n",
816
+ "]\n",
817
+ "result5 = peephole_optimization(test5)\n",
818
+ "print(\"\\nTest 5 (ADD 0+5 -> CONST 5):\")\n",
819
+ "for i, instr in enumerate(result5): print(f\" {i}: {instr}\")\n",
820
+ "# Expected: instruction 0 becomes CONST x = 5\n",
821
+ "\n",
822
+ "# Test 6: full pipeline — CF then peephole on a generated program\n",
823
+ "random.seed(7)\n",
824
+ "prog = generate_level_1()\n",
825
+ "print(\"\\nTest 6 (CF then peephole on seed=7):\")\n",
826
+ "print(\"Original:\")\n",
827
+ "for i, instr in enumerate(prog[\"instructions\"]): print(f\" {i}: {instr}\")\n",
828
+ "after_cf = constant_folding(prog[\"instructions\"])\n",
829
+ "print(\"After CF:\")\n",
830
+ "for i, instr in enumerate(after_cf): print(f\" {i}: {instr}\")\n",
831
+ "after_peep = peephole_optimization(after_cf)\n",
832
+ "print(\"After CF + peephole:\")\n",
833
+ "for i, instr in enumerate(after_peep): print(f\" {i}: {instr}\")\n",
834
+ "\n",
835
+ "# Test 7: idempotence\n",
836
+ "test7 = [\n",
837
+ " {\"op\": \"MUL\", \"dest\": \"x\", \"src1\": \"y\", \"src2\": 2},\n",
838
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"x\", \"src2\": None},\n",
839
+ "]\n",
840
+ "once = peephole_optimization(test7)\n",
841
+ "twice = peephole_optimization(once)\n",
842
+ "print(\"\\nTest 7 (idempotence):\", \"PASS\" if once == twice else \"FAIL\")\n",
843
+ "\n",
844
+ "# Test 8: no false fires — vanilla program shouldn't get rewritten\n",
845
+ "test8 = [\n",
846
+ " {\"op\": \"LOAD\", \"dest\": \"y\", \"src1\": \"addr0\", \"src2\": None},\n",
847
+ " {\"op\": \"MUL\", \"dest\": \"x\", \"src1\": \"y\", \"src2\": \"y\"}, # y*y, no peephole pattern\n",
848
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"x\", \"src2\": None},\n",
849
+ "]\n",
850
+ "result8 = peephole_optimization(test8)\n",
851
+ "print(\"\\nTest 8 (no false rewrite on y*y):\")\n",
852
+ "for i, instr in enumerate(result8): print(f\" {i}: {instr}\")\n",
853
+ "# Expected: instruction 1 unchanged (still MUL y*y)"
854
+ ],
855
+ "metadata": {
856
+ "colab": {
857
+ "base_uri": "https://localhost:8080/"
858
+ },
859
+ "id": "DWDUZUQvwXye",
860
+ "outputId": "1d1e327f-5f26-43e4-a6ac-f7a286da3781"
861
+ },
862
+ "execution_count": 10,
863
+ "outputs": [
864
+ {
865
+ "output_type": "stream",
866
+ "name": "stdout",
867
+ "text": [
868
+ "Test 1 (MUL by 2 -> ADD self):\n",
869
+ " 0: {'op': 'LOAD', 'dest': 'y', 'src1': 'addr0', 'src2': None}\n",
870
+ " 1: {'op': 'ADD', 'dest': 'x', 'src1': 'y', 'src2': 'y'}\n",
871
+ " 2: {'op': 'STORE', 'dest': 'addr0', 'src1': 'x', 'src2': None}\n",
872
+ "\n",
873
+ "Test 2 (MUL by 0 -> CONST 0):\n",
874
+ " 0: {'op': 'LOAD', 'dest': 'y', 'src1': 'addr0', 'src2': None}\n",
875
+ " 1: {'op': 'CONST', 'dest': 'x', 'src1': 0, 'src2': None}\n",
876
+ " 2: {'op': 'STORE', 'dest': 'addr0', 'src1': 'x', 'src2': None}\n",
877
+ "\n",
878
+ "Test 3 (MUL 7*1 -> CONST 7):\n",
879
+ " 0: {'op': 'CONST', 'dest': 'x', 'src1': 7, 'src2': None}\n",
880
+ " 1: {'op': 'STORE', 'dest': 'addr0', 'src1': 'x', 'src2': None}\n",
881
+ "\n",
882
+ "Test 4 (SUB y-y -> CONST 0):\n",
883
+ " 0: {'op': 'LOAD', 'dest': 'y', 'src1': 'addr0', 'src2': None}\n",
884
+ " 1: {'op': 'CONST', 'dest': 'x', 'src1': 0, 'src2': None}\n",
885
+ " 2: {'op': 'STORE', 'dest': 'addr0', 'src1': 'x', 'src2': None}\n",
886
+ "\n",
887
+ "Test 5 (ADD 0+5 -> CONST 5):\n",
888
+ " 0: {'op': 'CONST', 'dest': 'x', 'src1': 5, 'src2': None}\n",
889
+ " 1: {'op': 'STORE', 'dest': 'addr0', 'src1': 'x', 'src2': None}\n",
890
+ "\n",
891
+ "Test 6 (CF then peephole on seed=7):\n",
892
+ "Original:\n",
893
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 3, 'src2': None}\n",
894
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 7, 'src2': None}\n",
895
+ " 2: {'op': 'CONST', 'dest': 'v2', 'src1': 1, 'src2': None}\n",
896
+ " 3: {'op': 'ADD', 'dest': 'v3', 'src1': 'v1', 'src2': 'v2'}\n",
897
+ " 4: {'op': 'CONST', 'dest': 'v4', 'src1': 9, 'src2': None}\n",
898
+ " 5: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v3', 'src2': None}\n",
899
+ "After CF:\n",
900
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 3, 'src2': None}\n",
901
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 7, 'src2': None}\n",
902
+ " 2: {'op': 'CONST', 'dest': 'v2', 'src1': 1, 'src2': None}\n",
903
+ " 3: {'op': 'CONST', 'dest': 'v3', 'src1': 8, 'src2': None}\n",
904
+ " 4: {'op': 'CONST', 'dest': 'v4', 'src1': 9, 'src2': None}\n",
905
+ " 5: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v3', 'src2': None}\n",
906
+ "After CF + peephole:\n",
907
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 3, 'src2': None}\n",
908
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 7, 'src2': None}\n",
909
+ " 2: {'op': 'CONST', 'dest': 'v2', 'src1': 1, 'src2': None}\n",
910
+ " 3: {'op': 'CONST', 'dest': 'v3', 'src1': 8, 'src2': None}\n",
911
+ " 4: {'op': 'CONST', 'dest': 'v4', 'src1': 9, 'src2': None}\n",
912
+ " 5: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v3', 'src2': None}\n",
913
+ "\n",
914
+ "Test 7 (idempotence): PASS\n",
915
+ "\n",
916
+ "Test 8 (no false rewrite on y*y):\n",
917
+ " 0: {'op': 'LOAD', 'dest': 'y', 'src1': 'addr0', 'src2': None}\n",
918
+ " 1: {'op': 'MUL', 'dest': 'x', 'src1': 'y', 'src2': 'y'}\n",
919
+ " 2: {'op': 'STORE', 'dest': 'addr0', 'src1': 'x', 'src2': None}\n"
920
+ ]
921
+ }
922
+ ]
923
+ },
924
+ {
925
+ "cell_type": "code",
926
+ "source": [
927
+ "def dump_ir(program_data):\n",
928
+ " \"\"\"\n",
929
+ " Convert a TAC program into a readable string for the LLM observation.\n",
930
+ "\n",
931
+ " Format:\n",
932
+ " // OBSERVABLE OUT: mem[0], mem[1]\n",
933
+ " 0: v0 = 3 # CONST [1 cycle]\n",
934
+ " 1: v1 = 5 # CONST [1 cycle]\n",
935
+ " 2: v2 = v0 + v1 # ADD [1 cycle]\n",
936
+ " 3: mem[addr0] = v2 # STORE [4 cycles]\n",
937
+ " // TOTAL: 7 cycles\n",
938
+ "\n",
939
+ " Args:\n",
940
+ " program_data: dict with keys 'instructions' and 'observable_addrs',\n",
941
+ " OR a raw list of instructions (legacy).\n",
942
+ "\n",
943
+ " Returns:\n",
944
+ " A multi-line string suitable for inclusion in an LLM prompt.\n",
945
+ " \"\"\"\n",
946
+ " # Accept both forms — full program dict or raw instruction list\n",
947
+ " if isinstance(program_data, dict):\n",
948
+ " instructions = program_data[\"instructions\"]\n",
949
+ " observable_addrs = program_data.get(\"observable_addrs\", [])\n",
950
+ " else:\n",
951
+ " instructions = program_data\n",
952
+ " observable_addrs = []\n",
953
+ "\n",
954
+ " lines = []\n",
955
+ "\n",
956
+ " # Header: observable outputs\n",
957
+ " if observable_addrs:\n",
958
+ " addr_str = \", \".join(f\"mem[{a}]\" for a in observable_addrs)\n",
959
+ " lines.append(f\"// OBSERVABLE OUT: {addr_str}\")\n",
960
+ "\n",
961
+ " # Body: each instruction in human-readable form\n",
962
+ " total_cycles = 0\n",
963
+ " for i, instr in enumerate(instructions):\n",
964
+ " op = instr[\"op\"]\n",
965
+ " dest = instr[\"dest\"]\n",
966
+ " src1 = instr[\"src1\"]\n",
967
+ " src2 = instr[\"src2\"]\n",
968
+ " cost = CYCLE_COSTS.get(op, 0)\n",
969
+ " total_cycles += cost\n",
970
+ "\n",
971
+ " # Render the instruction body\n",
972
+ " if op == \"CONST\":\n",
973
+ " body = f\"{dest} = {src1}\"\n",
974
+ " elif op == \"ADD\":\n",
975
+ " body = f\"{dest} = {src1} + {src2}\"\n",
976
+ " elif op == \"SUB\":\n",
977
+ " body = f\"{dest} = {src1} - {src2}\"\n",
978
+ " elif op == \"MUL\":\n",
979
+ " body = f\"{dest} = {src1} * {src2}\"\n",
980
+ " elif op == \"DIV\":\n",
981
+ " body = f\"{dest} = {src1} // {src2}\"\n",
982
+ " elif op == \"LOAD\":\n",
983
+ " body = f\"{dest} = mem[{src1}]\"\n",
984
+ " elif op == \"STORE\":\n",
985
+ " body = f\"mem[{dest}] = {src1}\"\n",
986
+ " elif op == \"NOP\":\n",
987
+ " body = \"nop\"\n",
988
+ " else:\n",
989
+ " body = f\"<unknown op: {op}>\"\n",
990
+ "\n",
991
+ " cost_label = f\"{cost} cycle\" if cost == 1 else f\"{cost} cycles\"\n",
992
+ " lines.append(f\"{i}: {body:<35} # {op:<6} [{cost_label}]\")\n",
993
+ "\n",
994
+ " # Footer: total cycles\n",
995
+ " lines.append(f\"// TOTAL: {total_cycles} cycles\")\n",
996
+ "\n",
997
+ " return \"\\n\".join(lines)"
998
+ ],
999
+ "metadata": {
1000
+ "id": "yB_yMNOZwaPT"
1001
+ },
1002
+ "execution_count": 13,
1003
+ "outputs": []
1004
+ },
1005
+ {
1006
+ "cell_type": "code",
1007
+ "source": [
1008
+ "# === Sanity tests for state translator ===\n",
1009
+ "\n",
1010
+ "# Test 1: full generated program\n",
1011
+ "random.seed(1)\n",
1012
+ "prog = generate_level_1()\n",
1013
+ "print(\"Test 1 (raw seed=1 program):\")\n",
1014
+ "print(dump_ir(prog))\n",
1015
+ "\n",
1016
+ "# Test 2: after CF\n",
1017
+ "print(\"\\nTest 2 (after CF):\")\n",
1018
+ "folded = constant_folding(prog[\"instructions\"])\n",
1019
+ "prog_after_cf = {**prog, \"instructions\": folded}\n",
1020
+ "print(dump_ir(prog_after_cf))\n",
1021
+ "\n",
1022
+ "# Test 3: after CF + DCE — should show fewer instructions, lower total\n",
1023
+ "print(\"\\nTest 3 (after CF + DCE):\")\n",
1024
+ "optimized = dead_code_elimination(folded)\n",
1025
+ "prog_optimized = {**prog, \"instructions\": optimized}\n",
1026
+ "print(dump_ir(prog_optimized))\n",
1027
+ "\n",
1028
+ "# Test 4: every op type at least once\n",
1029
+ "test4_instructions = [\n",
1030
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 5, \"src2\": None},\n",
1031
+ " {\"op\": \"ADD\", \"dest\": \"b\", \"src1\": \"a\", \"src2\": 3},\n",
1032
+ " {\"op\": \"SUB\", \"dest\": \"c\", \"src1\": \"b\", \"src2\": \"a\"},\n",
1033
+ " {\"op\": \"MUL\", \"dest\": \"d\", \"src1\": \"c\", \"src2\": 2},\n",
1034
+ " {\"op\": \"DIV\", \"dest\": \"e\", \"src1\": \"d\", \"src2\": 4},\n",
1035
+ " {\"op\": \"LOAD\", \"dest\": \"f\", \"src1\": \"addr0\", \"src2\": None},\n",
1036
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"e\", \"src2\": None},\n",
1037
+ " {\"op\": \"NOP\", \"dest\": None, \"src1\": None, \"src2\": None},\n",
1038
+ "]\n",
1039
+ "test4_data = {\n",
1040
+ " \"instructions\": test4_instructions,\n",
1041
+ " \"observable_addrs\": [0, 1],\n",
1042
+ "}\n",
1043
+ "print(\"\\nTest 4 (every op type):\")\n",
1044
+ "print(dump_ir(test4_data))\n",
1045
+ "\n",
1046
+ "# Test 5: empty program shouldn't crash\n",
1047
+ "print(\"\\nTest 5 (empty program):\")\n",
1048
+ "print(dump_ir({\"instructions\": [], \"observable_addrs\": [0]}))"
1049
+ ],
1050
+ "metadata": {
1051
+ "colab": {
1052
+ "base_uri": "https://localhost:8080/"
1053
+ },
1054
+ "id": "SUqa7odp3wB_",
1055
+ "outputId": "c3f44089-213a-4a69-f29f-42b755ed142a"
1056
+ },
1057
+ "execution_count": 14,
1058
+ "outputs": [
1059
+ {
1060
+ "output_type": "stream",
1061
+ "name": "stdout",
1062
+ "text": [
1063
+ "Test 1 (raw seed=1 program):\n",
1064
+ "// OBSERVABLE OUT: mem[0]\n",
1065
+ "0: v0 = 10 # CONST [1 cycle]\n",
1066
+ "1: v1 = 2 # CONST [1 cycle]\n",
1067
+ "2: v2 = v1 + v1 # ADD [1 cycle]\n",
1068
+ "3: v3 = v2 * v1 # MUL [3 cycles]\n",
1069
+ "4: mem[addr0] = v3 # STORE [4 cycles]\n",
1070
+ "// TOTAL: 10 cycles\n",
1071
+ "\n",
1072
+ "Test 2 (after CF):\n",
1073
+ "// OBSERVABLE OUT: mem[0]\n",
1074
+ "0: v0 = 10 # CONST [1 cycle]\n",
1075
+ "1: v1 = 2 # CONST [1 cycle]\n",
1076
+ "2: v2 = 4 # CONST [1 cycle]\n",
1077
+ "3: v3 = 8 # CONST [1 cycle]\n",
1078
+ "4: mem[addr0] = v3 # STORE [4 cycles]\n",
1079
+ "// TOTAL: 8 cycles\n",
1080
+ "\n",
1081
+ "Test 3 (after CF + DCE):\n",
1082
+ "// OBSERVABLE OUT: mem[0]\n",
1083
+ "0: v3 = 8 # CONST [1 cycle]\n",
1084
+ "1: mem[addr0] = v3 # STORE [4 cycles]\n",
1085
+ "// TOTAL: 5 cycles\n",
1086
+ "\n",
1087
+ "Test 4 (every op type):\n",
1088
+ "// OBSERVABLE OUT: mem[0], mem[1]\n",
1089
+ "0: a = 5 # CONST [1 cycle]\n",
1090
+ "1: b = a + 3 # ADD [1 cycle]\n",
1091
+ "2: c = b - a # SUB [1 cycle]\n",
1092
+ "3: d = c * 2 # MUL [3 cycles]\n",
1093
+ "4: e = d // 4 # DIV [5 cycles]\n",
1094
+ "5: f = mem[addr0] # LOAD [4 cycles]\n",
1095
+ "6: mem[addr0] = e # STORE [4 cycles]\n",
1096
+ "7: nop # NOP [0 cycles]\n",
1097
+ "// TOTAL: 19 cycles\n",
1098
+ "\n",
1099
+ "Test 5 (empty program):\n",
1100
+ "// OBSERVABLE OUT: mem[0]\n",
1101
+ "// TOTAL: 0 cycles\n"
1102
+ ]
1103
+ }
1104
+ ]
1105
+ },
1106
+ {
1107
+ "cell_type": "code",
1108
+ "source": [
1109
+ "def generate_level_2():\n",
1110
+ " \"\"\"\n",
1111
+ " Generate a Level 2 Toy-IR program.\n",
1112
+ "\n",
1113
+ " Characteristics:\n",
1114
+ " - 8-12 instructions\n",
1115
+ " - 3-5 CONSTs (some literal, some used in arithmetic)\n",
1116
+ " - 3-5 arithmetic ops (ADD, SUB, MUL, DIV) with chaining\n",
1117
+ " - 1-3 dead variables (DCE opportunities)\n",
1118
+ " - 1 LOAD from initial memory (introduces non-constant variable)\n",
1119
+ " - 1 STORE at the end (observable output)\n",
1120
+ " - Mix of operands designed to hit peephole patterns occasionally:\n",
1121
+ " - MUL by literal 2 / 1 / 0 (not always — diversity matters)\n",
1122
+ " - DIV by non-zero divisor only (Design Assumption #4)\n",
1123
+ "\n",
1124
+ " Returns:\n",
1125
+ " dict with keys: initial_vars, initial_mem, instructions, observable_addrs\n",
1126
+ " \"\"\"\n",
1127
+ " instructions = []\n",
1128
+ " var_counter = 0\n",
1129
+ "\n",
1130
+ " def new_var():\n",
1131
+ " nonlocal var_counter\n",
1132
+ " name = f\"v{var_counter}\"\n",
1133
+ " var_counter += 1\n",
1134
+ " return name\n",
1135
+ "\n",
1136
+ " available_vars = [] # vars that exist and can be used as sources\n",
1137
+ "\n",
1138
+ " # Step 1: 3-5 CONSTs\n",
1139
+ " num_consts = random.randint(3, 5)\n",
1140
+ " for _ in range(num_consts):\n",
1141
+ " var = new_var()\n",
1142
+ " value = random.randint(1, 10)\n",
1143
+ " instructions.append({\"op\": \"CONST\", \"dest\": var, \"src1\": value, \"src2\": None})\n",
1144
+ " available_vars.append(var)\n",
1145
+ "\n",
1146
+ " # Step 2: 1 LOAD from initial memory\n",
1147
+ " # We'll seed initial_mem with something at a fresh address.\n",
1148
+ " load_addr_var = \"addr_in\"\n",
1149
+ " loaded_var = new_var()\n",
1150
+ " instructions.append({\n",
1151
+ " \"op\": \"LOAD\", \"dest\": loaded_var, \"src1\": load_addr_var, \"src2\": None,\n",
1152
+ " })\n",
1153
+ " available_vars.append(loaded_var)\n",
1154
+ "\n",
1155
+ " # Step 3: 3-5 arithmetic ops, chained\n",
1156
+ " num_arith = random.randint(3, 5)\n",
1157
+ " last_result = None\n",
1158
+ " for _ in range(num_arith):\n",
1159
+ " op = random.choice([\"ADD\", \"SUB\", \"MUL\", \"DIV\"])\n",
1160
+ "\n",
1161
+ " # 30% chance to use a literal as src2 to expose peephole opportunities\n",
1162
+ " # (MUL by 2/1/0, etc.)\n",
1163
+ " use_literal_src2 = random.random() < 0.3\n",
1164
+ "\n",
1165
+ " src1 = random.choice(available_vars)\n",
1166
+ " if use_literal_src2:\n",
1167
+ " # For DIV, never emit literal 0 (Design Assumption #4)\n",
1168
+ " if op == \"DIV\":\n",
1169
+ " src2 = random.choice([1, 2, 3, 4]) # safe non-zero divisors\n",
1170
+ " else:\n",
1171
+ " src2 = random.choice([0, 1, 2, 3]) # 0/1/2 hit peephole patterns\n",
1172
+ " else:\n",
1173
+ " src2 = random.choice(available_vars)\n",
1174
+ " # If we sampled a variable for DIV's src2, we can't be sure it's non-zero\n",
1175
+ " # at runtime. To stay safe per Assumption #4, restrict DIV to literal src2.\n",
1176
+ " if op == \"DIV\":\n",
1177
+ " src2 = random.choice([1, 2, 3, 4])\n",
1178
+ "\n",
1179
+ " dest = new_var()\n",
1180
+ " instructions.append({\"op\": op, \"dest\": dest, \"src1\": src1, \"src2\": src2})\n",
1181
+ " available_vars.append(dest)\n",
1182
+ " last_result = dest\n",
1183
+ "\n",
1184
+ " # Step 4: 1-3 extra dead CONSTs sprinkled in (DCE targets)\n",
1185
+ " num_dead = random.randint(1, 3)\n",
1186
+ " for _ in range(num_dead):\n",
1187
+ " dead_var = new_var()\n",
1188
+ " dead_value = random.randint(1, 20)\n",
1189
+ " # Insert at a random position before the (eventual) STORE\n",
1190
+ " insert_pos = random.randint(0, len(instructions))\n",
1191
+ " instructions.insert(insert_pos, {\n",
1192
+ " \"op\": \"CONST\", \"dest\": dead_var, \"src1\": dead_value, \"src2\": None,\n",
1193
+ " })\n",
1194
+ " # Note: dead_var intentionally never used afterward\n",
1195
+ "\n",
1196
+ " # Step 5: STORE the final result\n",
1197
+ " initial_vars = {\n",
1198
+ " \"addr0\": 0,\n",
1199
+ " \"addr_in\": 1, # address that the LOAD reads from\n",
1200
+ " }\n",
1201
+ " initial_mem = {1: random.randint(1, 20)} # seed mem[1] with a random value\n",
1202
+ "\n",
1203
+ " instructions.append({\n",
1204
+ " \"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": last_result, \"src2\": None,\n",
1205
+ " })\n",
1206
+ "\n",
1207
+ " return {\n",
1208
+ " \"initial_vars\": initial_vars,\n",
1209
+ " \"initial_mem\": initial_mem,\n",
1210
+ " \"instructions\": instructions,\n",
1211
+ " \"observable_addrs\": [0],\n",
1212
+ " }"
1213
+ ],
1214
+ "metadata": {
1215
+ "id": "OL6QbL0H3xuP"
1216
+ },
1217
+ "execution_count": 15,
1218
+ "outputs": []
1219
+ },
1220
+ {
1221
+ "cell_type": "code",
1222
+ "source": [
1223
+ "# === Sanity tests for Level 2 generator ===\n",
1224
+ "\n",
1225
+ "# Test 1: spot-check a few seeds\n",
1226
+ "for seed in [42, 1, 7]:\n",
1227
+ " random.seed(seed)\n",
1228
+ " prog = generate_level_2()\n",
1229
+ " print(f\"\\n=== Level 2, seed={seed} ===\")\n",
1230
+ " print(dump_ir(prog))\n",
1231
+ " print(f\"initial_vars: {prog['initial_vars']}\")\n",
1232
+ " print(f\"initial_mem : {prog['initial_mem']}\")\n",
1233
+ "\n",
1234
+ "# Test 2: full pipeline (CF + DCE + peephole) on a Level 2 program\n",
1235
+ "print(\"\\n=== Full optimization pipeline on Level 2 (seed=42) ===\")\n",
1236
+ "random.seed(42)\n",
1237
+ "prog = generate_level_2()\n",
1238
+ "print(\"ORIGINAL:\")\n",
1239
+ "print(dump_ir(prog))\n",
1240
+ "\n",
1241
+ "after_cf = constant_folding(prog[\"instructions\"])\n",
1242
+ "print(\"\\nAFTER CF:\")\n",
1243
+ "print(dump_ir({**prog, \"instructions\": after_cf}))\n",
1244
+ "\n",
1245
+ "after_dce = dead_code_elimination(after_cf)\n",
1246
+ "print(\"\\nAFTER CF + DCE:\")\n",
1247
+ "print(dump_ir({**prog, \"instructions\": after_dce}))\n",
1248
+ "\n",
1249
+ "after_peep = peephole_optimization(after_dce)\n",
1250
+ "print(\"\\nAFTER CF + DCE + PEEPHOLE:\")\n",
1251
+ "print(dump_ir({**prog, \"instructions\": after_peep}))"
1252
+ ],
1253
+ "metadata": {
1254
+ "colab": {
1255
+ "base_uri": "https://localhost:8080/"
1256
+ },
1257
+ "id": "D0XjNetU5gIo",
1258
+ "outputId": "1c35cdfc-a95d-48ff-c7ce-c4c236bbbbdb"
1259
+ },
1260
+ "execution_count": 16,
1261
+ "outputs": [
1262
+ {
1263
+ "output_type": "stream",
1264
+ "name": "stdout",
1265
+ "text": [
1266
+ "\n",
1267
+ "=== Level 2, seed=42 ===\n",
1268
+ "// OBSERVABLE OUT: mem[0]\n",
1269
+ "0: v0 = 2 # CONST [1 cycle]\n",
1270
+ "1: v1 = 1 # CONST [1 cycle]\n",
1271
+ "2: v2 = 5 # CONST [1 cycle]\n",
1272
+ "3: v3 = 4 # CONST [1 cycle]\n",
1273
+ "4: v11 = 19 # CONST [1 cycle]\n",
1274
+ "5: v4 = 4 # CONST [1 cycle]\n",
1275
+ "6: v5 = mem[addr_in] # LOAD [4 cycles]\n",
1276
+ "7: v9 = 18 # CONST [1 cycle]\n",
1277
+ "8: v10 = 8 # CONST [1 cycle]\n",
1278
+ "9: v6 = v4 + v0 # ADD [1 cycle]\n",
1279
+ "10: v7 = v0 // 2 # DIV [5 cycles]\n",
1280
+ "11: v8 = v0 - v3 # SUB [1 cycle]\n",
1281
+ "12: mem[addr0] = v8 # STORE [4 cycles]\n",
1282
+ "// TOTAL: 23 cycles\n",
1283
+ "initial_vars: {'addr0': 0, 'addr_in': 1}\n",
1284
+ "initial_mem : {1: 1}\n",
1285
+ "\n",
1286
+ "=== Level 2, seed=1 ===\n",
1287
+ "// OBSERVABLE OUT: mem[0]\n",
1288
+ "0: v0 = 10 # CONST [1 cycle]\n",
1289
+ "1: v7 = 19 # CONST [1 cycle]\n",
1290
+ "2: v1 = 2 # CONST [1 cycle]\n",
1291
+ "3: v2 = 5 # CONST [1 cycle]\n",
1292
+ "4: v3 = mem[addr_in] # LOAD [4 cycles]\n",
1293
+ "5: v4 = v3 // 2 # DIV [5 cycles]\n",
1294
+ "6: v5 = v3 + v3 # ADD [1 cycle]\n",
1295
+ "7: v6 = v2 + v5 # ADD [1 cycle]\n",
1296
+ "8: mem[addr0] = v6 # STORE [4 cycles]\n",
1297
+ "// TOTAL: 19 cycles\n",
1298
+ "initial_vars: {'addr0': 0, 'addr_in': 1}\n",
1299
+ "initial_mem : {1: 11}\n",
1300
+ "\n",
1301
+ "=== Level 2, seed=7 ===\n",
1302
+ "// OBSERVABLE OUT: mem[0]\n",
1303
+ "0: v0 = 3 # CONST [1 cycle]\n",
1304
+ "1: v1 = 7 # CONST [1 cycle]\n",
1305
+ "2: v2 = 1 # CONST [1 cycle]\n",
1306
+ "3: v3 = 2 # CONST [1 cycle]\n",
1307
+ "4: v4 = mem[addr_in] # LOAD [4 cycles]\n",
1308
+ "5: v5 = v0 + v4 # ADD [1 cycle]\n",
1309
+ "6: v6 = v3 - 3 # SUB [1 cycle]\n",
1310
+ "7: v7 = v4 + 3 # ADD [1 cycle]\n",
1311
+ "8: v10 = 2 # CONST [1 cycle]\n",
1312
+ "9: v8 = v1 + v3 # ADD [1 cycle]\n",
1313
+ "10: v9 = v6 + v0 # ADD [1 cycle]\n",
1314
+ "11: mem[addr0] = v9 # STORE [4 cycles]\n",
1315
+ "// TOTAL: 18 cycles\n",
1316
+ "initial_vars: {'addr0': 0, 'addr_in': 1}\n",
1317
+ "initial_mem : {1: 5}\n",
1318
+ "\n",
1319
+ "=== Full optimization pipeline on Level 2 (seed=42) ===\n",
1320
+ "ORIGINAL:\n",
1321
+ "// OBSERVABLE OUT: mem[0]\n",
1322
+ "0: v0 = 2 # CONST [1 cycle]\n",
1323
+ "1: v1 = 1 # CONST [1 cycle]\n",
1324
+ "2: v2 = 5 # CONST [1 cycle]\n",
1325
+ "3: v3 = 4 # CONST [1 cycle]\n",
1326
+ "4: v11 = 19 # CONST [1 cycle]\n",
1327
+ "5: v4 = 4 # CONST [1 cycle]\n",
1328
+ "6: v5 = mem[addr_in] # LOAD [4 cycles]\n",
1329
+ "7: v9 = 18 # CONST [1 cycle]\n",
1330
+ "8: v10 = 8 # CONST [1 cycle]\n",
1331
+ "9: v6 = v4 + v0 # ADD [1 cycle]\n",
1332
+ "10: v7 = v0 // 2 # DIV [5 cycles]\n",
1333
+ "11: v8 = v0 - v3 # SUB [1 cycle]\n",
1334
+ "12: mem[addr0] = v8 # STORE [4 cycles]\n",
1335
+ "// TOTAL: 23 cycles\n",
1336
+ "\n",
1337
+ "AFTER CF:\n",
1338
+ "// OBSERVABLE OUT: mem[0]\n",
1339
+ "0: v0 = 2 # CONST [1 cycle]\n",
1340
+ "1: v1 = 1 # CONST [1 cycle]\n",
1341
+ "2: v2 = 5 # CONST [1 cycle]\n",
1342
+ "3: v3 = 4 # CONST [1 cycle]\n",
1343
+ "4: v11 = 19 # CONST [1 cycle]\n",
1344
+ "5: v4 = 4 # CONST [1 cycle]\n",
1345
+ "6: v5 = mem[addr_in] # LOAD [4 cycles]\n",
1346
+ "7: v9 = 18 # CONST [1 cycle]\n",
1347
+ "8: v10 = 8 # CONST [1 cycle]\n",
1348
+ "9: v6 = 6 # CONST [1 cycle]\n",
1349
+ "10: v7 = 1 # CONST [1 cycle]\n",
1350
+ "11: v8 = -2 # CONST [1 cycle]\n",
1351
+ "12: mem[addr0] = v8 # STORE [4 cycles]\n",
1352
+ "// TOTAL: 19 cycles\n",
1353
+ "\n",
1354
+ "AFTER CF + DCE:\n",
1355
+ "// OBSERVABLE OUT: mem[0]\n",
1356
+ "0: v8 = -2 # CONST [1 cycle]\n",
1357
+ "1: mem[addr0] = v8 # STORE [4 cycles]\n",
1358
+ "// TOTAL: 5 cycles\n",
1359
+ "\n",
1360
+ "AFTER CF + DCE + PEEPHOLE:\n",
1361
+ "// OBSERVABLE OUT: mem[0]\n",
1362
+ "0: v8 = -2 # CONST [1 cycle]\n",
1363
+ "1: mem[addr0] = v8 # STORE [4 cycles]\n",
1364
+ "// TOTAL: 5 cycles\n"
1365
+ ]
1366
+ }
1367
+ ]
1368
+ },
1369
+ {
1370
+ "cell_type": "code",
1371
+ "source": [],
1372
+ "metadata": {
1373
+ "id": "Vo-9MitD5hwM"
1374
+ },
1375
+ "execution_count": null,
1376
+ "outputs": []
1377
+ }
1378
+ ]
1379
+ }
space/space/space/space/metahack1.ipynb ADDED
@@ -0,0 +1,484 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "nbformat": 4,
3
+ "nbformat_minor": 0,
4
+ "metadata": {
5
+ "colab": {
6
+ "provenance": [],
7
+ "gpuType": "T4"
8
+ },
9
+ "kernelspec": {
10
+ "name": "python3",
11
+ "display_name": "Python 3"
12
+ },
13
+ "language_info": {
14
+ "name": "python"
15
+ },
16
+ "accelerator": "GPU"
17
+ },
18
+ "cells": [
19
+ {
20
+ "cell_type": "code",
21
+ "source": [
22
+ "## Design Assumptions (do not violate)\n",
23
+ "\n",
24
+ "# 1. **DCE never eliminates STOREs.** They define program output (final mem state).\n",
25
+ "# 2. **Addresses are distinct by construction.** Generator allocates each address variable to a unique integer; no aliasing.\n",
26
+ "# 3. **CF refuses to fold DIV by zero.** If src2 == 0 on a DIV op, leave instruction unchanged.\n",
27
+ "# 4. **Generator never emits DIV by literal zero.** When DIV is generated, src2 is always a non-zero constant or a variable known to be non-zero.\n",
28
+ "# # 5. **Integer arithmetic only.** No floats anywhere — avoids equivalence-check precision issues.\n",
29
+ "# 6. Generator declares `observable_addrs` per program — verifier compares only these mem entries.\n",
30
+ "# 7. State translator annotates observable outputs at top of dump.\n",
31
+ "# 8. Reward distinguishes broken (-1000) from valid-but-worse (small negative) — Harshal's formula.\n",
32
+ "# 9. Multi-input verification: 3-5 random initial states, all must match.\n",
33
+ "# 10. Integer division uses Python floor division (//). Aarush's VM must match."
34
+ ],
35
+ "metadata": {
36
+ "id": "_XI5jT2Ibvrf"
37
+ },
38
+ "execution_count": 17,
39
+ "outputs": []
40
+ },
41
+ {
42
+ "cell_type": "code",
43
+ "execution_count": 13,
44
+ "metadata": {
45
+ "id": "j6CQ327KWXwr"
46
+ },
47
+ "outputs": [],
48
+ "source": [
49
+ "# === TAC Schema v1.0 (LOCKED with Role 1 / Aarush) ===\n",
50
+ "# Reverse passes deferred to stretch goal — not in initial action space.\n",
51
+ "\n",
52
+ "OPS = [\"CONST\", \"ADD\", \"SUB\", \"MUL\", \"DIV\", \"LOAD\", \"STORE\", \"NOP\"]\n",
53
+ "\n",
54
+ "CYCLE_COSTS = {\n",
55
+ " \"CONST\": 1,\n",
56
+ " \"ADD\": 1,\n",
57
+ " \"SUB\": 1,\n",
58
+ " \"MUL\": 3,\n",
59
+ " \"DIV\": 5,\n",
60
+ " \"LOAD\": 4,\n",
61
+ " \"STORE\": 4,\n",
62
+ " \"NOP\": 0,\n",
63
+ "}\n",
64
+ "\n",
65
+ "# Instruction shape: {\"op\": str, \"dest\": str|None, \"src1\": Any, \"src2\": Any}\n",
66
+ "# Operands: str = variable name, int = literal constant, None = unused\n",
67
+ "#\n",
68
+ "# Op semantics:\n",
69
+ "# CONST: dest = src1 (src1 is int literal, src2 = None)\n",
70
+ "# ADD/SUB/MUL/DIV: dest = src1 OP src2 (src1, src2 are var names or int literals)\n",
71
+ "# LOAD: dest = mem[src1] (src1 is a var holding an address)\n",
72
+ "# STORE: mem[dest] = src1 (dest is a var holding an address)\n",
73
+ "# NOP: no-op (all fields None)\n",
74
+ "#\n",
75
+ "# Program output (for equivalence check) = final memory state (mem dict).\n",
76
+ "# Programs ship as: (initial_vars: dict, initial_mem: dict, instructions: list[dict])\n",
77
+ "# 10. Integer division uses Python floor division (//). Aarush's VM must match."
78
+ ]
79
+ },
80
+ {
81
+ "cell_type": "code",
82
+ "source": [
83
+ "import random\n",
84
+ "\n",
85
+ "def generate_level_1():\n",
86
+ " \"\"\"\n",
87
+ " Generate a Level 1 Toy-IR program.\n",
88
+ "\n",
89
+ " Characteristics:\n",
90
+ " - 4-6 instructions\n",
91
+ " - 2-3 CONST ops with literal values\n",
92
+ " - 1-2 arithmetic ops on those constants (foldable by CF)\n",
93
+ " - 0-1 dead variables (killable by DCE)\n",
94
+ " - Exactly 1 STORE at the end so the program has an observable output\n",
95
+ "\n",
96
+ " Returns:\n",
97
+ " dict with keys: initial_vars, initial_mem, instructions, observable_addrs\n",
98
+ " \"\"\"\n",
99
+ " instructions = []\n",
100
+ " var_counter = 0\n",
101
+ "\n",
102
+ " def new_var():\n",
103
+ " nonlocal var_counter\n",
104
+ " name = f\"v{var_counter}\"\n",
105
+ " var_counter += 1\n",
106
+ " return name\n",
107
+ "\n",
108
+ " # Step 1: Generate 2-3 constant assignments\n",
109
+ " num_consts = random.randint(2, 3)\n",
110
+ " const_vars = []\n",
111
+ " for _ in range(num_consts):\n",
112
+ " var = new_var()\n",
113
+ " value = random.randint(1, 10)\n",
114
+ " instructions.append({\"op\": \"CONST\", \"dest\": var, \"src1\": value, \"src2\": None})\n",
115
+ " const_vars.append(var)\n",
116
+ "\n",
117
+ " # Step 2: Generate 1-2 arithmetic ops using those constants\n",
118
+ " num_arith = random.randint(1, 2)\n",
119
+ " last_result = None\n",
120
+ " for _ in range(num_arith):\n",
121
+ " op = random.choice([\"ADD\", \"MUL\"])\n",
122
+ " src1 = random.choice(const_vars)\n",
123
+ " src2 = random.choice(const_vars)\n",
124
+ " dest = new_var()\n",
125
+ " instructions.append({\"op\": op, \"dest\": dest, \"src1\": src1, \"src2\": src2})\n",
126
+ " last_result = dest\n",
127
+ " const_vars.append(dest)\n",
128
+ "\n",
129
+ " # Step 3: Optionally add 1 dead variable (50% chance)\n",
130
+ " if random.random() < 0.5:\n",
131
+ " dead_var = new_var()\n",
132
+ " dead_value = random.randint(1, 10)\n",
133
+ " instructions.append({\"op\": \"CONST\", \"dest\": dead_var, \"src1\": dead_value, \"src2\": None})\n",
134
+ " # Note: dead_var is intentionally never used — DCE should catch it.\n",
135
+ "\n",
136
+ " # Step 4: Add a STORE at the end so the program has observable output\n",
137
+ " initial_vars = {\"addr0\": 0}\n",
138
+ " instructions.append({\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": last_result, \"src2\": None})\n",
139
+ "\n",
140
+ " initial_mem = {}\n",
141
+ "\n",
142
+ " return {\n",
143
+ " \"initial_vars\": initial_vars,\n",
144
+ " \"initial_mem\": initial_mem,\n",
145
+ " \"instructions\": instructions,\n",
146
+ " \"observable_addrs\": [0], # Aarush's verifier compares only these mem entries\n",
147
+ " }\n",
148
+ "\n",
149
+ "\n",
150
+ "# Sanity-check: generate a few programs and print them\n",
151
+ "for seed in [42, 1, 7, 99]:\n",
152
+ " random.seed(seed)\n",
153
+ " prog = generate_level_1()\n",
154
+ " print(f\"\\n=== seed={seed} ===\")\n",
155
+ " print(f\"initial_vars : {prog['initial_vars']}\")\n",
156
+ " print(f\"initial_mem : {prog['initial_mem']}\")\n",
157
+ " print(f\"observable_addrs : {prog['observable_addrs']}\")\n",
158
+ " print(f\"instructions ({len(prog['instructions'])}):\")\n",
159
+ " for i, instr in enumerate(prog['instructions']):\n",
160
+ " print(f\" {i}: {instr}\")"
161
+ ],
162
+ "metadata": {
163
+ "colab": {
164
+ "base_uri": "https://localhost:8080/"
165
+ },
166
+ "id": "a86vD1OyWcB9",
167
+ "outputId": "de3d7093-eaea-420e-a0d7-2bd9451bcf6b"
168
+ },
169
+ "execution_count": 14,
170
+ "outputs": [
171
+ {
172
+ "output_type": "stream",
173
+ "name": "stdout",
174
+ "text": [
175
+ "\n",
176
+ "=== seed=42 ===\n",
177
+ "initial_vars : {'addr0': 0}\n",
178
+ "initial_mem : {}\n",
179
+ "observable_addrs : [0]\n",
180
+ "instructions (4):\n",
181
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 1, 'src2': None}\n",
182
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 5, 'src2': None}\n",
183
+ " 2: {'op': 'ADD', 'dest': 'v2', 'src1': 'v0', 'src2': 'v0'}\n",
184
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v2', 'src2': None}\n",
185
+ "\n",
186
+ "=== seed=1 ===\n",
187
+ "initial_vars : {'addr0': 0}\n",
188
+ "initial_mem : {}\n",
189
+ "observable_addrs : [0]\n",
190
+ "instructions (5):\n",
191
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 10, 'src2': None}\n",
192
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 2, 'src2': None}\n",
193
+ " 2: {'op': 'ADD', 'dest': 'v2', 'src1': 'v1', 'src2': 'v1'}\n",
194
+ " 3: {'op': 'MUL', 'dest': 'v3', 'src1': 'v2', 'src2': 'v1'}\n",
195
+ " 4: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v3', 'src2': None}\n",
196
+ "\n",
197
+ "=== seed=7 ===\n",
198
+ "initial_vars : {'addr0': 0}\n",
199
+ "initial_mem : {}\n",
200
+ "observable_addrs : [0]\n",
201
+ "instructions (6):\n",
202
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 3, 'src2': None}\n",
203
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 7, 'src2': None}\n",
204
+ " 2: {'op': 'CONST', 'dest': 'v2', 'src1': 1, 'src2': None}\n",
205
+ " 3: {'op': 'ADD', 'dest': 'v3', 'src1': 'v1', 'src2': 'v2'}\n",
206
+ " 4: {'op': 'CONST', 'dest': 'v4', 'src1': 9, 'src2': None}\n",
207
+ " 5: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v3', 'src2': None}\n",
208
+ "\n",
209
+ "=== seed=99 ===\n",
210
+ "initial_vars : {'addr0': 0}\n",
211
+ "initial_mem : {}\n",
212
+ "observable_addrs : [0]\n",
213
+ "instructions (5):\n",
214
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 7, 'src2': None}\n",
215
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 4, 'src2': None}\n",
216
+ " 2: {'op': 'CONST', 'dest': 'v2', 'src1': 10, 'src2': None}\n",
217
+ " 3: {'op': 'ADD', 'dest': 'v3', 'src1': 'v0', 'src2': 'v0'}\n",
218
+ " 4: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v3', 'src2': None}\n"
219
+ ]
220
+ }
221
+ ]
222
+ },
223
+ {
224
+ "cell_type": "code",
225
+ "source": [
226
+ "def _resolve_operand(operand, known_constants):\n",
227
+ " \"\"\"\n",
228
+ " Given a TAC operand (string variable name or int literal),\n",
229
+ " return its concrete integer value if known, or None if unknown.\n",
230
+ " \"\"\"\n",
231
+ " if isinstance(operand, int):\n",
232
+ " return operand\n",
233
+ " if isinstance(operand, str) and operand in known_constants:\n",
234
+ " return known_constants[operand]\n",
235
+ " return None\n",
236
+ "\n",
237
+ "\n",
238
+ "def _compute(op, v1, v2):\n",
239
+ " \"\"\"Compute the result of a binary arithmetic op on two known integers.\"\"\"\n",
240
+ " if op == \"ADD\": return v1 + v2\n",
241
+ " if op == \"SUB\": return v1 - v2\n",
242
+ " if op == \"MUL\": return v1 * v2\n",
243
+ " if op == \"DIV\": return v1 // v2 # floor division (locked semantics)\n",
244
+ " raise ValueError(f\"_compute called with non-arithmetic op: {op}\")\n",
245
+ "\n",
246
+ "\n",
247
+ "def constant_folding(program):\n",
248
+ " \"\"\"\n",
249
+ " Forward pass that folds constant arithmetic into CONST ops, and\n",
250
+ " propagates known constants into instruction operands.\n",
251
+ "\n",
252
+ " Behavior:\n",
253
+ " - If both sources of an arithmetic op resolve to known integers,\n",
254
+ " replaces the instruction with a CONST holding the computed result.\n",
255
+ " - If only one source is known, still substitutes that known value\n",
256
+ " into the instruction (constant propagation), enabling downstream\n",
257
+ " passes (e.g., peephole) to recognize patterns like ADD-with-0 or MUL-by-1.\n",
258
+ " - Refuses to fold DIV by zero (Design Assumption #3).\n",
259
+ " - Always returns fresh dicts; never aliases input instructions.\n",
260
+ "\n",
261
+ " Args:\n",
262
+ " program: list of TAC instruction dicts (per locked schema).\n",
263
+ "\n",
264
+ " Returns:\n",
265
+ " new list of TAC instruction dicts. Always semantics-preserving.\n",
266
+ " Never raises, never returns None.\n",
267
+ " \"\"\"\n",
268
+ " known_constants = {}\n",
269
+ " new_program = []\n",
270
+ "\n",
271
+ " for instr in program:\n",
272
+ " # Always work on a copy — never alias input dicts\n",
273
+ " instr = instr.copy()\n",
274
+ " op = instr[\"op\"]\n",
275
+ " dest = instr[\"dest\"]\n",
276
+ "\n",
277
+ " if op == \"CONST\":\n",
278
+ " known_constants[dest] = instr[\"src1\"]\n",
279
+ " new_program.append(instr)\n",
280
+ "\n",
281
+ " elif op in (\"ADD\", \"SUB\", \"MUL\", \"DIV\"):\n",
282
+ " # === Constant propagation: substitute known constants into operands ===\n",
283
+ " if isinstance(instr[\"src1\"], str) and instr[\"src1\"] in known_constants:\n",
284
+ " instr[\"src1\"] = known_constants[instr[\"src1\"]]\n",
285
+ " if isinstance(instr[\"src2\"], str) and instr[\"src2\"] in known_constants:\n",
286
+ " instr[\"src2\"] = known_constants[instr[\"src2\"]]\n",
287
+ "\n",
288
+ " # === Try to fold ===\n",
289
+ " v1 = _resolve_operand(instr[\"src1\"], known_constants)\n",
290
+ " v2 = _resolve_operand(instr[\"src2\"], known_constants)\n",
291
+ "\n",
292
+ " if v1 is not None and v2 is not None:\n",
293
+ " # Both operands are known integers\n",
294
+ " if op == \"DIV\" and v2 == 0:\n",
295
+ " # Refuse to fold DIV by zero\n",
296
+ " new_program.append(instr)\n",
297
+ " known_constants.pop(dest, None)\n",
298
+ " else:\n",
299
+ " # Fold: replace with CONST\n",
300
+ " result = _compute(op, v1, v2)\n",
301
+ " new_program.append({\n",
302
+ " \"op\": \"CONST\",\n",
303
+ " \"dest\": dest,\n",
304
+ " \"src1\": result,\n",
305
+ " \"src2\": None,\n",
306
+ " })\n",
307
+ " known_constants[dest] = result\n",
308
+ " else:\n",
309
+ " # Can't fold (at least one operand unknown).\n",
310
+ " # Instruction may still have been mutated by propagation above.\n",
311
+ " new_program.append(instr)\n",
312
+ " known_constants.pop(dest, None)\n",
313
+ "\n",
314
+ " elif op == \"LOAD\":\n",
315
+ " # Memory reads aren't statically resolvable\n",
316
+ " new_program.append(instr)\n",
317
+ " known_constants.pop(dest, None)\n",
318
+ "\n",
319
+ " elif op in (\"STORE\", \"NOP\"):\n",
320
+ " # No dest tracking needed.\n",
321
+ " # Note: we COULD propagate src1 into a STORE for downstream readability,\n",
322
+ " # but the cycle cost is unchanged and the executor handles vars fine.\n",
323
+ " # Leave STORE alone — keeps the code minimal.\n",
324
+ " new_program.append(instr)\n",
325
+ "\n",
326
+ " else:\n",
327
+ " # Unknown op — defensive pass-through\n",
328
+ " new_program.append(instr)\n",
329
+ "\n",
330
+ " return new_program"
331
+ ],
332
+ "metadata": {
333
+ "id": "CGk8Fz4CZA3t"
334
+ },
335
+ "execution_count": 18,
336
+ "outputs": []
337
+ },
338
+ {
339
+ "cell_type": "code",
340
+ "source": [
341
+ "# === Sanity tests for constant_folding ===\n",
342
+ "\n",
343
+ "# Test 1: simple fold — ADD of two CONSTs\n",
344
+ "test1 = [\n",
345
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 3, \"src2\": None},\n",
346
+ " {\"op\": \"CONST\", \"dest\": \"b\", \"src1\": 5, \"src2\": None},\n",
347
+ " {\"op\": \"ADD\", \"dest\": \"c\", \"src1\": \"a\", \"src2\": \"b\"},\n",
348
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"c\", \"src2\": None},\n",
349
+ "]\n",
350
+ "result1 = constant_folding(test1)\n",
351
+ "print(\"Test 1 (simple ADD fold):\")\n",
352
+ "for i, instr in enumerate(result1): print(f\" {i}: {instr}\")\n",
353
+ "# Expected: instruction 2 becomes CONST c = 8\n",
354
+ "\n",
355
+ "# Test 2: chained fold — second op uses first op's folded result\n",
356
+ "test2 = [\n",
357
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 3, \"src2\": None},\n",
358
+ " {\"op\": \"CONST\", \"dest\": \"b\", \"src1\": 5, \"src2\": None},\n",
359
+ " {\"op\": \"ADD\", \"dest\": \"c\", \"src1\": \"a\", \"src2\": \"b\"}, # → 8\n",
360
+ " {\"op\": \"MUL\", \"dest\": \"d\", \"src1\": \"c\", \"src2\": \"b\"}, # → 8 * 5 = 40\n",
361
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"d\", \"src2\": None},\n",
362
+ "]\n",
363
+ "result2 = constant_folding(test2)\n",
364
+ "print(\"\\nTest 2 (chained fold):\")\n",
365
+ "for i, instr in enumerate(result2): print(f\" {i}: {instr}\")\n",
366
+ "# Expected: c becomes CONST 8, d becomes CONST 40\n",
367
+ "\n",
368
+ "# Test 3: DIV by zero refused\n",
369
+ "test3 = [\n",
370
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 10, \"src2\": None},\n",
371
+ " {\"op\": \"CONST\", \"dest\": \"b\", \"src1\": 0, \"src2\": None},\n",
372
+ " {\"op\": \"DIV\", \"dest\": \"c\", \"src1\": \"a\", \"src2\": \"b\"}, # 10/0 — must NOT fold\n",
373
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"c\", \"src2\": None},\n",
374
+ "]\n",
375
+ "result3 = constant_folding(test3)\n",
376
+ "print(\"\\nTest 3 (DIV by zero refused):\")\n",
377
+ "for i, instr in enumerate(result3): print(f\" {i}: {instr}\")\n",
378
+ "# Expected: instruction 2 unchanged (still DIV, not CONST)\n",
379
+ "\n",
380
+ "# Test 4: unknown source can't fold\n",
381
+ "test4 = [\n",
382
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 3, \"src2\": None},\n",
383
+ " {\"op\": \"LOAD\", \"dest\": \"b\", \"src1\": \"addr0\", \"src2\": None}, # b is unknown\n",
384
+ " {\"op\": \"ADD\", \"dest\": \"c\", \"src1\": \"a\", \"src2\": \"b\"}, # can't fold\n",
385
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"c\", \"src2\": None},\n",
386
+ "]\n",
387
+ "result4 = constant_folding(test4)\n",
388
+ "print(\"\\nTest 4 (LOAD makes b unknown, ADD not folded):\")\n",
389
+ "for i, instr in enumerate(result4): print(f\" {i}: {instr}\")\n",
390
+ "# Expected: instruction 2 unchanged (still ADD)\n",
391
+ "\n",
392
+ "# Test 5: idempotence — running CF on a generated program\n",
393
+ "random.seed(42)\n",
394
+ "prog = generate_level_1()\n",
395
+ "folded = constant_folding(prog[\"instructions\"])\n",
396
+ "print(\"\\nTest 5 (CF on generated Level 1 program, seed=42):\")\n",
397
+ "print(\"Before:\")\n",
398
+ "for i, instr in enumerate(prog[\"instructions\"]): print(f\" {i}: {instr}\")\n",
399
+ "print(\"After:\")\n",
400
+ "for i, instr in enumerate(folded): print(f\" {i}: {instr}\")\n",
401
+ "\n",
402
+ "# Test 6: constant propagation — only one source is known\n",
403
+ "test6 = [\n",
404
+ " {\"op\": \"CONST\", \"dest\": \"a\", \"src1\": 0, \"src2\": None},\n",
405
+ " {\"op\": \"LOAD\", \"dest\": \"b\", \"src1\": \"addr0\", \"src2\": None}, # b unknown\n",
406
+ " {\"op\": \"ADD\", \"dest\": \"c\", \"src1\": \"a\", \"src2\": \"b\"}, # a known (=0), b unknown\n",
407
+ " {\"op\": \"STORE\", \"dest\": \"addr0\", \"src1\": \"c\", \"src2\": None},\n",
408
+ "]\n",
409
+ "result6 = constant_folding(test6)\n",
410
+ "print(\"\\nTest 6 (propagation: a=0 substituted into ADD even though b unknown):\")\n",
411
+ "for i, instr in enumerate(result6): print(f\" {i}: {instr}\")\n",
412
+ "# Expected: instruction 2 is still ADD (can't fold — b unknown), but src1 is now literal 0, not 'a'\n",
413
+ "# This sets up peephole to recognize \"ADD with 0\" later"
414
+ ],
415
+ "metadata": {
416
+ "colab": {
417
+ "base_uri": "https://localhost:8080/"
418
+ },
419
+ "id": "WLKSTVa8fRF8",
420
+ "outputId": "27042d38-0044-4814-bbfa-8a2c2d87ee06"
421
+ },
422
+ "execution_count": 20,
423
+ "outputs": [
424
+ {
425
+ "output_type": "stream",
426
+ "name": "stdout",
427
+ "text": [
428
+ "Test 1 (simple ADD fold):\n",
429
+ " 0: {'op': 'CONST', 'dest': 'a', 'src1': 3, 'src2': None}\n",
430
+ " 1: {'op': 'CONST', 'dest': 'b', 'src1': 5, 'src2': None}\n",
431
+ " 2: {'op': 'CONST', 'dest': 'c', 'src1': 8, 'src2': None}\n",
432
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'c', 'src2': None}\n",
433
+ "\n",
434
+ "Test 2 (chained fold):\n",
435
+ " 0: {'op': 'CONST', 'dest': 'a', 'src1': 3, 'src2': None}\n",
436
+ " 1: {'op': 'CONST', 'dest': 'b', 'src1': 5, 'src2': None}\n",
437
+ " 2: {'op': 'CONST', 'dest': 'c', 'src1': 8, 'src2': None}\n",
438
+ " 3: {'op': 'CONST', 'dest': 'd', 'src1': 40, 'src2': None}\n",
439
+ " 4: {'op': 'STORE', 'dest': 'addr0', 'src1': 'd', 'src2': None}\n",
440
+ "\n",
441
+ "Test 3 (DIV by zero refused):\n",
442
+ " 0: {'op': 'CONST', 'dest': 'a', 'src1': 10, 'src2': None}\n",
443
+ " 1: {'op': 'CONST', 'dest': 'b', 'src1': 0, 'src2': None}\n",
444
+ " 2: {'op': 'DIV', 'dest': 'c', 'src1': 10, 'src2': 0}\n",
445
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'c', 'src2': None}\n",
446
+ "\n",
447
+ "Test 4 (LOAD makes b unknown, ADD not folded):\n",
448
+ " 0: {'op': 'CONST', 'dest': 'a', 'src1': 3, 'src2': None}\n",
449
+ " 1: {'op': 'LOAD', 'dest': 'b', 'src1': 'addr0', 'src2': None}\n",
450
+ " 2: {'op': 'ADD', 'dest': 'c', 'src1': 3, 'src2': 'b'}\n",
451
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'c', 'src2': None}\n",
452
+ "\n",
453
+ "Test 5 (CF on generated Level 1 program, seed=42):\n",
454
+ "Before:\n",
455
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 1, 'src2': None}\n",
456
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 5, 'src2': None}\n",
457
+ " 2: {'op': 'ADD', 'dest': 'v2', 'src1': 'v0', 'src2': 'v0'}\n",
458
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v2', 'src2': None}\n",
459
+ "After:\n",
460
+ " 0: {'op': 'CONST', 'dest': 'v0', 'src1': 1, 'src2': None}\n",
461
+ " 1: {'op': 'CONST', 'dest': 'v1', 'src1': 5, 'src2': None}\n",
462
+ " 2: {'op': 'CONST', 'dest': 'v2', 'src1': 2, 'src2': None}\n",
463
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'v2', 'src2': None}\n",
464
+ "\n",
465
+ "Test 6 (propagation: a=0 substituted into ADD even though b unknown):\n",
466
+ " 0: {'op': 'CONST', 'dest': 'a', 'src1': 0, 'src2': None}\n",
467
+ " 1: {'op': 'LOAD', 'dest': 'b', 'src1': 'addr0', 'src2': None}\n",
468
+ " 2: {'op': 'ADD', 'dest': 'c', 'src1': 0, 'src2': 'b'}\n",
469
+ " 3: {'op': 'STORE', 'dest': 'addr0', 'src1': 'c', 'src2': None}\n"
470
+ ]
471
+ }
472
+ ]
473
+ },
474
+ {
475
+ "cell_type": "code",
476
+ "source": [],
477
+ "metadata": {
478
+ "id": "5vo-KgaffTFR"
479
+ },
480
+ "execution_count": null,
481
+ "outputs": []
482
+ }
483
+ ]
484
+ }
space/space/space/space/space/.github/workflows/deploy.yml ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ name: Deploy to Hugging Face Space
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ deploy:
10
+ runs-on: ubuntu-latest
11
+
12
+ steps:
13
+ - name: Checkout Repo
14
+ uses: actions/checkout@v4
15
+
16
+ - name: Push to Hugging Face
17
+ env:
18
+ HF_TOKEN: ${{ secrets.HF_TOKEN }}
19
+ run: |
20
+ git config --global user.email "github-actions@github.com"
21
+ git config --global user.name "github-actions"
22
+
23
+ git clone https://user:$HF_TOKEN@huggingface.co/spaces/greedybeserk95/Compilertetris space
24
+
25
+ rsync -av --exclude ".git" ./ space/
26
+
27
+ cd space
28
+ git add .
29
+ git commit -m "Auto deploy from GitHub" || echo "No changes"
30
+ git push
space/space/space/space/space/README.md CHANGED
@@ -1,11 +1 @@
1
- ---
2
- title: Compilertetris
3
- emoji: ⚡
4
- colorFrom: red
5
- colorTo: gray
6
- sdk: docker
7
- pinned: false
8
- short_description: an RL environment which optimizes IR code
9
- ---
10
-
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
+ # MetaHackathon2026Finals
 
 
 
 
 
 
 
 
 
 
space/space/space/space/space/space/.gitattributes ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ *.7z filter=lfs diff=lfs merge=lfs -text
2
+ *.arrow filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
4
+ *.bz2 filter=lfs diff=lfs merge=lfs -text
5
+ *.ckpt filter=lfs diff=lfs merge=lfs -text
6
+ *.ftz filter=lfs diff=lfs merge=lfs -text
7
+ *.gz filter=lfs diff=lfs merge=lfs -text
8
+ *.h5 filter=lfs diff=lfs merge=lfs -text
9
+ *.joblib filter=lfs diff=lfs merge=lfs -text
10
+ *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
+ *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
+ *.model filter=lfs diff=lfs merge=lfs -text
13
+ *.msgpack filter=lfs diff=lfs merge=lfs -text
14
+ *.npy filter=lfs diff=lfs merge=lfs -text
15
+ *.npz filter=lfs diff=lfs merge=lfs -text
16
+ *.onnx filter=lfs diff=lfs merge=lfs -text
17
+ *.ot filter=lfs diff=lfs merge=lfs -text
18
+ *.parquet filter=lfs diff=lfs merge=lfs -text
19
+ *.pb filter=lfs diff=lfs merge=lfs -text
20
+ *.pickle filter=lfs diff=lfs merge=lfs -text
21
+ *.pkl filter=lfs diff=lfs merge=lfs -text
22
+ *.pt filter=lfs diff=lfs merge=lfs -text
23
+ *.pth filter=lfs diff=lfs merge=lfs -text
24
+ *.rar filter=lfs diff=lfs merge=lfs -text
25
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
26
+ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
+ *.tar.* filter=lfs diff=lfs merge=lfs -text
28
+ *.tar filter=lfs diff=lfs merge=lfs -text
29
+ *.tflite filter=lfs diff=lfs merge=lfs -text
30
+ *.tgz filter=lfs diff=lfs merge=lfs -text
31
+ *.wasm filter=lfs diff=lfs merge=lfs -text
32
+ *.xz filter=lfs diff=lfs merge=lfs -text
33
+ *.zip filter=lfs diff=lfs merge=lfs -text
34
+ *.zst filter=lfs diff=lfs merge=lfs -text
35
+ *tfevents* filter=lfs diff=lfs merge=lfs -text
space/space/space/space/space/space/README.md ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ title: Compilertetris
3
+ emoji: ⚡
4
+ colorFrom: red
5
+ colorTo: gray
6
+ sdk: docker
7
+ pinned: false
8
+ short_description: an RL environment which optimizes IR code
9
+ ---
10
+
11
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference