interpretergen.icl 111 KB
Newer Older
1 2 3 4
implementation module interpretergen

import StdEnv
import StdMaybe
5
import ArgEnv
6 7 8
import target

Start w
9
# args = getCommandLine
10 11 12 13 14 15 16 17 18 19
# opts = parse_opts args 1 default_opts
# (opts,w) = case opts.instructions_order of
	Nothing
		-> (opts,w)
	Just [fp]
		# (ok,f,w) = fopen fp FReadText w
		| not ok -> abort ("Failed to read '"+++fp+++"'\n")
		# (instrs,f) = fetch_instructions [] f
		# (_,w) = fclose f w
		-> ({opts & instructions_order=Just instrs},w)
20

21
# (io,w) = stdio w
22
# io = foldl (\io e -> io <<< e <<< "\n") io (all_instructions opts start)
23 24
# (_,w) = fclose io w
= w
25
where
26 27 28 29 30 31 32 33 34 35 36 37 38 39
	parse_opts :: !{String} !Int !Options -> Options
	parse_opts args i opts
	| i>=size args
		= opts
		= case args.[i] of
			"-i" -> parse_opts args (i+2) {opts & instructions_order=Just [args.[i+1]]}
			"-d" -> parse_opts args (i+1) {opts & debug_instructions=True}
			a -> abort ("unknown argument '"+++a+++"'\n")

	default_opts =
		{ instructions_order = Nothing
		, debug_instructions = False
		}

40 41 42 43 44 45 46 47 48 49
	fetch_instructions :: ![String] !*File -> *(![String], !*File)
	fetch_instructions is f
	# (e,f) = fend f
	| e = (reverse is,f)
	# (l,f) = freadline f
	| l%(0,12) <> "\tINSTRUCTION(" = fetch_instructions is f
	# i = l%(13,find_closing_paren 13 l-1)
	= fetch_instructions [i:is] f
	where
		find_closing_paren i s = if (s.[i]==')') i (find_closing_paren (i+1) s)
50 51 52 53

($) infixr 0
($) f :== f

54
all_instructions opts t = bootstrap $ collect_instructions opts $ map (\i -> i t) $
Camil Staps's avatar
Camil Staps committed
55
	[ instr "absR" (Just 0) $
56 57
		new_local TReal (absR (to_real (B @ 0))) \r ->
		B @ 0 .= to_word r
Camil Staps's avatar
Camil Staps committed
58
	, instr "acosR" (Just 0) $
59 60
		new_local TReal (acosR (to_real (B @ 0))) \r ->
		B @ 0 .= to_word r
Camil Staps's avatar
Camil Staps committed
61
	, instr "addI" (Just 0) $
62
		B @ 1 .= to_word (to_int (B @ 0) + to_int (B @ 1)) :.
63
		shrink_b 1
Camil Staps's avatar
Camil Staps committed
64
	, instr "addIo" (Just 0) $
65 66
		B @ 1 .= to_int (B @ 0) + to_int (B @ 1) :.
		B @ 0 .= to_int (B @ 1) <. to_int (B @ 0)
Camil Staps's avatar
Camil Staps committed
67
	, instr "addLU" (Just 0) $
68 69
		B @ 2 .= to_int (B @ 1) + to_int (B @ 2) :.
		B @ 1 .= B @ 0 + if_expr (B @ 2 <. B @ 1) (lit_word 1) (lit_word 0) :.
70
		shrink_b 1
Camil Staps's avatar
Camil Staps committed
71
	, instr "addR" (Just 0) $
72 73
		new_local TReal (to_real (B @ 0) + to_real (B @ 1)) \r ->
		B @ 1 .= to_word r :.
74 75
		shrink_b 1
	] ++
Camil Staps's avatar
Camil Staps committed
76
	[ instr ("add_empty_node"+++toString n) Nothing $
77
		ensure_hp 3 :.
78 79 80 81
		Pc .= to_word_ptr (Pc @ 1) :.
		Hp @ 0 .= cycle_ptr :.
		for [0..n-1] (\i -> A @ (1-i) .= A @ (0-i)) :.
		A @ (1-n) .= to_word Hp :.
82
		grow_a 1 :.
83
		advance_ptr Hp 3
84 85
	\\ n <- [2..32]
	] ++
Camil Staps's avatar
Camil Staps committed
86
	[ instr "andI" (Just 0) $
87
		B @ 1 .= (B @ 0 &. B @ 1) :.
88
		shrink_b 1
Camil Staps's avatar
Camil Staps committed
89
	, instr "asinR" (Just 0) $
90 91
		new_local TReal (asinR (to_real (B @ 0))) \r ->
		B @ 0 .= to_word r
Camil Staps's avatar
Camil Staps committed
92
	, instr "atanR" (Just 0) $
93 94
		new_local TReal (atanR (to_real (B @ 0))) \r ->
		B @ 0 .= to_word r
Camil Staps's avatar
Camil Staps committed
95
	, instr "build0" (Just 1) $
96
		ensure_hp 3 :.
97 98 99
		Hp @ 0 .= Pc @ 1 :.
		A @ 1 .= to_word Hp :.
		advance_ptr Hp 3 :.
100
		grow_a 1
Camil Staps's avatar
Camil Staps committed
101
	, instr "build1" (Just 1) $
102
		ensure_hp 3 :.
103 104 105 106
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		A @ 0 .= to_word Hp :.
		advance_ptr Hp 3
107 108
	, alias "build2" $
	  alias "buildh2" $
Camil Staps's avatar
Camil Staps committed
109
	  instr "buildhr20" (Just 1) $
110
		ensure_hp 3 :.
111 112 113 114
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= A @ -1 :.
		A @ -1 .= to_word Hp :.
115
		shrink_a 1 :.
116
		advance_ptr Hp 3
Camil Staps's avatar
Camil Staps committed
117
	, instr "build3" (Just 1) $
118
		ensure_hp 4 :.
119 120 121
		Hp @ 0 .= Pc @ 1 :.
		for [1..3] (\i -> Hp @ i .= A @ (1-i)) :.
		A @ -2 .= to_word Hp :.
122
		shrink_a 2 :.
123
		advance_ptr Hp 4
Camil Staps's avatar
Camil Staps committed
124
	, instr "build4" (Just 1) $
125
		ensure_hp 5 :.
126 127 128
		Hp @ 0 .= Pc @ 1 :.
		for [1..4] (\i -> Hp @ i .= A @ (1-i)) :.
		A @ -3 .= to_word Hp :.
129
		shrink_a 3 :.
130
		advance_ptr Hp 5
Camil Staps's avatar
Camil Staps committed
131
	, instr "build" (Just 2) $
132 133 134 135 136 137 138 139
		new_local TWord (Pc @ 1) \s ->
		ensure_hp (s + lit_word 1) :.
		Hp @ 0 .= Pc @ 2 :.
		for [1..5] (\i -> Hp @ i .= A @ (1-i)) :.
		unrolled_loop [6..32] (\i -> s <. lit_word i) (\i -> Hp @ i .= A @ (1-i)) :.
		shrink_a (s - lit_word 1) :.
		A @ 0 .= to_word Hp :.
		advance_ptr Hp (s + lit_word 1)
140
	, alias "buildh0" $
Camil Staps's avatar
Camil Staps committed
141
	  instr "buildAC" (Just 1) $
142
		A @ 1 .= Pc @ 1 :.
143 144
		grow_a 1
	, alias "buildh1" $
Camil Staps's avatar
Camil Staps committed
145
	  instr "buildhr10" (Just 1) $
146
		ensure_hp 2 :.
147 148 149 150
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		A @ 0 .= to_word Hp :.
		advance_ptr Hp 2
151
	, alias "buildh3" $
Camil Staps's avatar
Camil Staps committed
152
	  instr "buildhr30" (Just 1) $
153
		ensure_hp 5 :.
154 155 156 157 158 159
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 3 .= A @ -1 :.
		Hp @ 4 .= A @ -2 :.
		A @ -2 .= to_word Hp :.
160
		shrink_a 2 :.
161
		advance_ptr Hp 5
162
	, alias "buildh4" $
Camil Staps's avatar
Camil Staps committed
163
	  instr "buildhr40" (Just 1) $
164
		ensure_hp 6 :.
165 166 167 168 169 170 171
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 3 .= A @ -1 :.
		Hp @ 4 .= A @ -2 :.
		Hp @ 5 .= A @ -3 :.
		A @ -3 .= to_word Hp :.
172
		shrink_a 3 :.
173
		advance_ptr Hp 6
174
	, alias "buildh" $
Camil Staps's avatar
Camil Staps committed
175
	  instr "buildhra0" (Just 2) $
176 177 178 179 180 181 182 183 184 185 186 187 188
		new_local TWord (Pc @ 1) \s_p_2 ->
		ensure_hp s_p_2 :.
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 3 .= A @ -1 :.
		Hp @ 4 .= A @ -2 :.
		Hp @ 5 .= A @ -3 :.
		Hp @ 6 .= A @ -4 :.
		unrolled_loop [8..34] (\i -> s_p_2 <. lit_word i) (\i -> Hp @ (i-1) .= A @ (3-i)) :.
		shrink_a (s_p_2 - lit_word 3) :.
		A @ 0 .= to_word Hp :.
		advance_ptr Hp s_p_2
Camil Staps's avatar
Camil Staps committed
189
	, instr "buildBFALSE" (Just 0) $
Camil Staps's avatar
Camil Staps committed
190 191
		A @ 1 .= static_boolean (lit_word 0) :.
		grow_a 1
Camil Staps's avatar
Camil Staps committed
192
	, instr "buildBTRUE" (Just 0) $
Camil Staps's avatar
Camil Staps committed
193 194
		A @ 1 .= static_boolean (lit_word 1) :.
		grow_a 1
Camil Staps's avatar
Camil Staps committed
195
	, instr "buildB_b" (Just 1) $
Camil Staps's avatar
Camil Staps committed
196 197
		A @ 1 .= static_boolean (B @ (Pc @ 1)) :.
		grow_a 1
Camil Staps's avatar
Camil Staps committed
198
	, instr "buildC" (Just 1) $
199 200
		A @ 1 .= static_character (to_char (Pc @ 1)) :.
		grow_a 1
Camil Staps's avatar
Camil Staps committed
201
	, instr "buildC_b" (Just 1) $
202 203
		A @ 1 .= static_character (to_char (B @ (Pc @ 1))) :.
		grow_a 1
Camil Staps's avatar
Camil Staps committed
204
	, instr "buildI" (Just 1) $
205
		new_local TInt (to_int (Pc @ 1)) \i ->
Camil Staps's avatar
Camil Staps committed
206 207 208 209
		if_then_else (lit_int 0 <=. i &&. i <=. lit_int 32)
			(A @ 1 .= small_integer i)
		[]
		(else (
210
			ensure_hp 2 :.
211 212 213 214
			Hp @ 0 .= INT_ptr + lit_word 2 :.
			Hp @ 1 .= to_word i :.
			A @ 1 .= to_word Hp :.
			advance_ptr Hp 2
Camil Staps's avatar
Camil Staps committed
215
		)) :.
216
		grow_a 1
Camil Staps's avatar
Camil Staps committed
217
	, instr "buildI_b" (Just 1) $
218
		new_local TInt (to_int (B @ to_int (Pc @ 1))) \i ->
Camil Staps's avatar
Camil Staps committed
219 220 221 222
		if_then_else (lit_int 0 <=. i &&. i <=. lit_int 32)
			(A @ 1 .= small_integer i)
		[]
		(else (
223
			ensure_hp 2 :.
224 225 226 227
			Hp @ 0 .= INT_ptr + lit_word 2 :.
			Hp @ 1 .= to_word i :.
			A @ 1 .= to_word Hp :.
			advance_ptr Hp 2
Camil Staps's avatar
Camil Staps committed
228
		)) :.
229
		grow_a 1
Camil Staps's avatar
Camil Staps committed
230
	, instr "buildR" (Just 1) $
231
		ensure_hp 2 :.
232 233 234
		Hp @ 0 .= REAL_ptr + lit_word 2 :.
		Hp @ 1 .= Pc @ 1 :.
		A @ 1 .= to_word Hp :.
235
		grow_a 1 :.
236
		advance_ptr Hp 2
Camil Staps's avatar
Camil Staps committed
237
	, instr "buildR_b" (Just 1) $
238
		ensure_hp 2 :.
239 240 241
		Hp @ 0 .= REAL_ptr + lit_word 2 :.
		Hp @ 1 .= B @ (Pc @ 1) :.
		A @ 1 .= to_word Hp :.
242
		grow_a 1 :.
243
		advance_ptr Hp 2
Camil Staps's avatar
Camil Staps committed
244
	, instr "buildhr01" (Just 1) $
245
		ensure_hp 2 :.
246 247 248
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= B @ 0 :.
		A @ 1 .= to_word Hp :.
249 250
		grow_a 1 :.
		shrink_b 1 :.
251
		advance_ptr Hp 2
Camil Staps's avatar
Camil Staps committed
252
	, instr "buildhr02" (Just 1) $
253
		ensure_hp 3 :.
254 255 256 257
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= B @ 0 :.
		Hp @ 2 .= B @ 1 :.
		A @ 1 .= to_word Hp :.
258 259
		grow_a 1 :.
		shrink_b 2 :.
260
		advance_ptr Hp 3
Camil Staps's avatar
Camil Staps committed
261
	, instr "buildhr03" Nothing $
262
		ensure_hp 5 :.
263 264 265 266 267 268 269
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= B @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		advance_ptr Pc 2 :.
		Hp @ 3 .= B @ 1 :.
		Hp @ 4 .= B @ 2 :.
		A @ 1 .= to_word Hp :.
270 271
		grow_a 1 :.
		shrink_b 3 :.
272
		advance_ptr Hp 5
Camil Staps's avatar
Camil Staps committed
273
	, instr "buildhr04" Nothing $
274
		ensure_hp 6 :.
275 276 277 278 279 280 281 282
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= B @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		advance_ptr Pc 2 :.
		Hp @ 3 .= B @ 1 :.
		Hp @ 4 .= B @ 2 :.
		Hp @ 5 .= B @ 3 :.
		A @ 1 .= to_word Hp :.
283 284
		grow_a 1 :.
		shrink_b 4 :.
285
		advance_ptr Hp 6
Camil Staps's avatar
Camil Staps committed
286
	, instr "buildhr11" (Just 1) $
287
		ensure_hp 3 :.
288 289 290 291
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= B @ 0 :.
		A @ 0 .= to_word Hp :.
292
		shrink_b 1 :.
293
		advance_ptr Hp 3
Camil Staps's avatar
Camil Staps committed
294
	, instr "buildhr12" Nothing $
295
		ensure_hp 5 :.
296 297 298 299 300 301 302
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		advance_ptr Pc 2 :.
		Hp @ 3 .= B @ 0 :.
		Hp @ 4 .= B @ 1 :.
		A @ 0 .= to_word Hp :.
303
		shrink_b 2 :.
304
		advance_ptr Hp 5
Camil Staps's avatar
Camil Staps committed
305
	, instr "buildhr13" Nothing $
306
		ensure_hp 6 :.
307 308 309 310 311 312 313 314
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		advance_ptr Pc 2 :.
		Hp @ 3 .= B @ 0 :.
		Hp @ 4 .= B @ 1 :.
		Hp @ 5 .= B @ 2 :.
		A @ 0 .= to_word Hp :.
315
		shrink_b 3 :.
316
		advance_ptr Hp 6
Camil Staps's avatar
Camil Staps committed
317
	, instr "buildhr21" Nothing $
318
		ensure_hp 5 :.
319 320 321 322 323 324 325
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		advance_ptr Pc 2 :.
		Hp @ 3 .= A @ -1 :.
		Hp @ 4 .= B @ 0 :.
		A @ -1 .= to_word Hp :.
326 327
		shrink_a 1 :.
		shrink_b 1 :.
328
		advance_ptr Hp 5
Camil Staps's avatar
Camil Staps committed
329
	, instr "buildhr22" Nothing $
330
		ensure_hp 6 :.
331 332 333 334 335 336 337 338
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		advance_ptr Pc 2 :.
		Hp @ 3 .= A @ -1 :.
		Hp @ 4 .= B @ 0 :.
		Hp @ 5 .= B @ 1 :.
		A @ -1 .= to_word Hp :.
339 340
		shrink_a 1 :.
		shrink_b 2 :.
341
		advance_ptr Hp 6
Camil Staps's avatar
Camil Staps committed
342
	, instr "buildhr31" Nothing $
343
		ensure_hp 6 :.
344 345 346 347 348 349 350 351
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		advance_ptr Pc 2 :.
		Hp @ 3 .= A @ -1 :.
		Hp @ 4 .= A @ -2 :.
		Hp @ 5 .= B @ 0 :.
		A @ -2 .= to_word Hp :.
352 353
		shrink_a 2 :.
		shrink_b 1 :.
354
		advance_ptr Hp 6
Camil Staps's avatar
Camil Staps committed
355
	, instr "buildhra1" Nothing $
356 357 358 359 360 361 362 363 364 365 366 367 368 369
		new_local TWord (Pc @ 1) \n_a ->
		ensure_hp (n_a + lit_word 3) :.
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		advance_ptr Pc 3 :.
		Hp @ 3 .= A @ -1 :.
		Hp @ 4 .= A @ -2 :.
		Hp @ 5 .= A @ -3 :.
		unrolled_loop [5..31] (\i -> n_a <. lit_word i) (\i -> Hp @ (i+1) .= A @ (1-i)) :.
		shrink_a (n_a - lit_word 1) :.
		A @ 0 .= to_word Hp :.
		advance_ptr Hp (n_a + lit_word 3) :.
		Hp @ -1 .= B @ 0 :.
370
		shrink_b 1
Camil Staps's avatar
Camil Staps committed
371
	, instr "buildhr0b" Nothing $
372 373 374 375 376 377 378 379 380 381 382 383 384
		new_local TWord (Pc @ 1) \n_b ->
		ensure_hp (n_b + lit_word 2) :.
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= B @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		advance_ptr Pc 3 :.
		Hp @ 3 .= B @ 1 :.
		Hp @ 4 .= B @ 2 :.
		Hp @ 5 .= B @ 3 :.
		Hp @ 6 .= B @ 4 :.
		unrolled_loop [6..32] (\i -> n_b <. lit_word i) (\i -> Hp @ (i+1) .= B @ (i-1)) :.
		shrink_b n_b :.
		A @ 1 .= to_word Hp :.
385
		grow_a 1 :.
386
		advance_ptr Hp (n_b + lit_word 2)
Camil Staps's avatar
Camil Staps committed
387
	, instr "buildhr1b" Nothing $
388 389 390 391 392 393 394 395 396 397 398 399 400 401
		new_local TWord (Pc @ 1) \n_b ->
		ensure_hp (n_b + lit_word 3) :.
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		advance_ptr Pc 3 :.
		Hp @ 3 .= B @ 0 :.
		Hp @ 4 .= B @ 1 :.
		Hp @ 5 .= B @ 2 :.
		Hp @ 6 .= B @ 3 :.
		unrolled_loop [5..31] (\i -> n_b <. lit_word i) (\i -> Hp @ (i+2) .= B @ (i-1)) :.
		shrink_b n_b :.
		A @ 0 .= to_word Hp :.
		advance_ptr Hp (n_b + lit_word 3)
Camil Staps's avatar
Camil Staps committed
402
	, instr "buildhr" (Just 3) $
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
		new_local TWord (Pc @ 1) \n_ab ->
		ensure_hp (n_ab + lit_word 2) :.
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		new_local TWord (Pc @ 3) \n_a ->
		new_local TWord (n_ab - n_a) \n_b ->
		Hp @ 3 .= A @ -1 :.
		unrolled_loop [3..30] (\i -> n_a <. lit_word i) (\i -> Hp @ (i+1) .= A @ (1-i)) :.
		shrink_a (n_a - lit_word 1) :.
		A @ 0 .= to_word Hp :.
		advance_ptr Hp (n_a + lit_word 2) :.
		Hp @ 0 .= B @ 0 :.
		Hp @ 1 .= B @ 1 :.
		unrolled_loop [3..30] (\i -> n_b <. lit_word i) (\i -> Hp @ (i-1) .= B @ (i-1)) :.
		shrink_b n_b :.
		advance_ptr Hp n_b
Camil Staps's avatar
Camil Staps committed
420
	, instr "build_r01" (Just 2) $
421
		ensure_hp 2 :.
422 423 424 425
		new_local TInt (to_int (Pc @ 1)) \bo ->
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= B @ bo :.
		A @ 1 .= to_word Hp :.
426
		grow_a 1 :.
427
		advance_ptr Hp 2
Camil Staps's avatar
Camil Staps committed
428
	, instr "build_r02" (Just 2) $
429
		ensure_hp 3 :.
430 431 432 433 434
		new_local TInt (to_int (Pc @ 1)) \bo ->
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= B @ bo :.
		Hp @ 2 .= B @ (bo + lit_int 1) :.
		A @ 1 .= to_word Hp :.
435
		grow_a 1 :.
436
		advance_ptr Hp 3
Camil Staps's avatar
Camil Staps committed
437
	, instr "build_r03" (Just 2) $
438
		ensure_hp 5 :.
439 440 441 442 443 444 445
		new_local TInt (to_int (Pc @ 1)) \bo ->
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= B @ bo :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 3 .= B @ (bo + lit_int 1) :.
		Hp @ 4 .= B @ (bo + lit_int 2) :.
		A @ 1 .= to_word Hp :.
446
		grow_a 1 :.
447
		advance_ptr Hp 5
Camil Staps's avatar
Camil Staps committed
448
	, instr "build_r04" (Just 2) $
449
		ensure_hp 6 :.
450 451 452 453 454 455 456 457
		new_local TInt (to_int (Pc @ 1)) \bo ->
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= B @ bo :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 3 .= B @ (bo + lit_int 1) :.
		Hp @ 4 .= B @ (bo + lit_int 2) :.
		Hp @ 5 .= B @ (bo + lit_int 3) :.
		A @ 1 .= to_word Hp :.
458
		grow_a 1 :.
459
		advance_ptr Hp 6
Camil Staps's avatar
Camil Staps committed
460
	, instr "build_r10" (Just 2) $
461
		ensure_hp 2 :.
462 463 464 465
		new_local TInt (to_int (Pc @ 1)) \ao ->
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= A @ ao :.
		A @ 1 .= to_word Hp :.
466
		grow_a 1 :.
467
		advance_ptr Hp 2
Camil Staps's avatar
Camil Staps committed
468
	, instr "build_r11" (Just 3) $
469
		ensure_hp 3 :.
470 471 472 473 474 475
		new_local TInt (to_int (Pc @ 1)) \ao ->
		new_local TInt (to_int (Pc @ 2)) \bo ->
		Hp @ 0 .= Pc @ 3 :.
		Hp @ 1 .= A @ ao :.
		Hp @ 2 .= B @ bo :.
		A @ 1 .= to_word Hp :.
476
		grow_a 1 :.
477
		advance_ptr Hp 3
Camil Staps's avatar
Camil Staps committed
478
	, instr "build_r12" (Just 3) $
479
		ensure_hp 5 :.
480 481 482 483 484 485 486 487
		new_local TInt (to_int (Pc @ 1)) \ao ->
		new_local TInt (to_int (Pc @ 2)) \bo ->
		Hp @ 0 .= Pc @ 3 :.
		Hp @ 1 .= A @ ao :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 3 .= B @ bo :.
		Hp @ 4 .= B @ (bo + lit_int 1) :.
		A @ 1 .= to_word Hp :.
488
		grow_a 1 :.
489
		advance_ptr Hp 5
Camil Staps's avatar
Camil Staps committed
490
	, instr "build_r13" (Just 3) $
491
		ensure_hp 6 :.
492 493 494 495 496 497 498 499 500
		new_local TInt (to_int (Pc @ 1)) \ao ->
		new_local TInt (to_int (Pc @ 2)) \bo ->
		Hp @ 0 .= Pc @ 3 :.
		Hp @ 1 .= A @ ao :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 3 .= B @ bo :.
		Hp @ 4 .= B @ (bo + lit_int 1) :.
		Hp @ 5 .= B @ (bo + lit_int 2) :.
		A @ 1 .= to_word Hp :.
501
		grow_a 1 :.
502
		advance_ptr Hp 6
Camil Staps's avatar
Camil Staps committed
503
	, instr "build_r20" (Just 2) $
504
		ensure_hp 3 :.
505 506 507 508 509
		new_local TInt (to_int (Pc @ 1)) \ao ->
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= A @ ao :.
		Hp @ 2 .= A @ (ao - lit_int 1) :.
		A @ 1 .= to_word Hp :.
510
		grow_a 1 :.
511
		advance_ptr Hp 3
Camil Staps's avatar
Camil Staps committed
512
	, instr "build_r21" (Just 3) $
513
		ensure_hp 5 :.
514 515 516 517 518 519 520 521
		new_local TInt (to_int (Pc @ 1)) \ao ->
		new_local TInt (to_int (Pc @ 2)) \bo ->
		Hp @ 0 .= Pc @ 3 :.
		Hp @ 1 .= A @ ao :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 3 .= A @ (ao - lit_int 1) :.
		Hp @ 4 .= B @ bo :.
		A @ 1 .= to_word Hp :.
522
		grow_a 1 :.
523
		advance_ptr Hp 5
Camil Staps's avatar
Camil Staps committed
524
	, instr "build_r30" (Just 2) $
525
		ensure_hp 5 :.
526 527 528 529 530 531 532
		new_local TInt (to_int (Pc @ 1)) \ao ->
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= A @ ao :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 3 .= A @ (ao - lit_int 1) :.
		Hp @ 4 .= A @ (ao - lit_int 2) :.
		A @ 1 .= to_word Hp :.
533
		grow_a 1 :.
534
		advance_ptr Hp 5
Camil Staps's avatar
Camil Staps committed
535
	, instr "build_r31" (Just 3) $
536
		ensure_hp 6 :.
537 538 539 540 541 542 543 544 545
		new_local TInt (to_int (Pc @ 1)) \ao ->
		new_local TInt (to_int (Pc @ 2)) \bo ->
		Hp @ 0 .= Pc @ 3 :.
		Hp @ 1 .= A @ ao :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 3 .= A @ (ao - lit_int 1) :.
		Hp @ 4 .= A @ (ao - lit_int 2) :.
		Hp @ 5 .= B @ bo :.
		A @ 1 .= to_word Hp :.
546
		grow_a 1 :.
547
		advance_ptr Hp 6
Camil Staps's avatar
Camil Staps committed
548
	, instr "build_r40" (Just 2) $
549
		ensure_hp 6 :.
550 551 552 553 554 555 556 557
		new_local TInt (to_int (Pc @ 1)) \ao ->
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= A @ ao :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 3 .= A @ (ao - lit_int 1) :.
		Hp @ 4 .= A @ (ao - lit_int 2) :.
		Hp @ 5 .= A @ (ao - lit_int 3) :.
		A @ 1 .= to_word Hp :.
558
		grow_a 1 :.
559
		advance_ptr Hp 6
Camil Staps's avatar
Camil Staps committed
560
	, instr "build_ra0" Nothing $
561 562 563 564 565 566 567 568 569 570
		new_local TWord (Pc @ 1) \n_a ->
		ensure_hp (n_a + lit_word 2) :.
		Hp @ 0 .= Pc @ 3 :.
		new_local (TPtr TWord) (A @? (Pc @ 2)) \ao_p ->
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 1 .= ao_p @ 0 :.
		for [3..6] (\i -> Hp @ i .= ao_p @ (2-i)) :.
		advance_ptr Pc 4 :.
		unrolled_loop [6..32] (\i -> n_a <. lit_word i) (\i -> Hp @ (i+1) .= ao_p @ (1-i)) :.
		A @ 1 .= to_word Hp :.
571
		grow_a 1 :.
572
		advance_ptr Hp (n_a + lit_word 2)
Camil Staps's avatar
Camil Staps committed
573
	, instr "build_ra1" Nothing $
574 575 576 577 578 579 580 581 582 583 584
		new_local TWord (Pc @ 1) \n_a ->
		ensure_hp (n_a + lit_word 3) :.
		Hp @ 0 .= Pc @ 3 :.
		new_local (TPtr TWord) (A @? (Pc @ 2)) \ao_p ->
		new_local TInt (to_int (Pc @ 4)) \bo ->
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 1 .= ao_p @ 0 :.
		for [3..5] (\i -> Hp @ i .= ao_p @ (2-i)) :.
		advance_ptr Pc 5 :.
		unrolled_loop [5..31] (\i -> n_a <. lit_word i) (\i -> Hp @ (i+1) .= ao_p @ (1-i)) :.
		A @ 1 .= to_word Hp :.
585
		grow_a 1 :.
586 587
		advance_ptr Hp (n_a + lit_word 3) :.
		Hp @ -1 .= B @ bo
Camil Staps's avatar
Camil Staps committed
588
	, instr "build_r0b" Nothing $
589 590 591 592 593 594 595 596 597 598
		new_local TWord (Pc @ 1) \n_b ->
		ensure_hp (n_b + lit_word 2) :.
		Hp @ 0 .= Pc @ 3 :.
		new_local (TPtr TWord) (B @? (Pc @ 2)) \bo_p ->
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 1 .= bo_p @ 0 :.
		for [3..6] (\i -> Hp @ i .= bo_p @ (i-2)) :.
		advance_ptr Pc 4 :.
		unrolled_loop [6..32] (\i -> n_b <. lit_word i) (\i -> Hp @ (i+1) .= bo_p @ (i-1)) :.
		A @ 1 .= to_word Hp :.
599
		grow_a 1 :.
600
		advance_ptr Hp (n_b + lit_word 2)
Camil Staps's avatar
Camil Staps committed
601
	, instr "build_r1b" Nothing $
602 603 604 605 606 607 608 609 610 611
		new_local TWord (Pc @ 1) \n_b ->
		ensure_hp (n_b + lit_word 3) :.
		Hp @ 0 .= Pc @ 3 :.
		Hp @ 1 .= A @ (Pc @ 2) :.
		new_local (TPtr TWord) (B @? (Pc @ 4)) \bo_p ->
		Hp @ 2 .= to_word (Hp @? 3) :.
		for [3..6] (\i -> Hp @ i .= bo_p @ (i-3)) :.
		advance_ptr Pc 5 :.
		unrolled_loop [5..31] (\i -> n_b <. lit_word i) (\i -> Hp @ (i+2) .= bo_p @ (i-1)) :.
		A @ 1 .= to_word Hp :.
612
		grow_a 1 :.
613
		advance_ptr Hp (n_b + lit_word 3)
Camil Staps's avatar
Camil Staps committed
614
	, instr "build_r" Nothing $
615 616 617 618 619 620 621 622 623 624 625 626 627
		new_local TWord (Pc @ 1) \n_ab ->
		ensure_hp (n_ab + lit_word 2) :.
		new_local (TPtr TWord) (A @? (Pc @ 2)) \ao_p ->
		Hp @ 0 .= Pc @ 3 :.
		Hp @ 2 .= to_word (Hp @? 3) :.
		Hp @ 1 .= ao_p @ 0 :.
		new_local TWord (Pc @ 4) \n_a ->
		Hp @ 3 .= ao_p @ -1 :.
		unrolled_loop [3..30] (\i -> n_a <. lit_word i) (\i -> Hp @ (i+1) .= ao_p @ (1-i)) :.
		new_local TWord (n_ab - n_a) \n_b ->
		new_local (TPtr TWord) (B @? (Pc @ 5)) \bo_p ->
		advance_ptr Pc 6 :.
		A @ 1 .= to_word Hp :.
628
		grow_a 1 :.
629 630 631 632 633
		advance_ptr Hp (n_a + lit_word 2) :.
		Hp @ 0 .= bo_p @ 0 :.
		Hp @ 1 .= bo_p @ 1 :.
		unrolled_loop [3..30] (\i -> n_b <. lit_word i) (\i -> Hp @ (i-1) .= bo_p @ (i-1)) :.
		advance_ptr Hp n_b
Camil Staps's avatar
Camil Staps committed
634
	, instr "build_u01" (Just 1) $
635
		ensure_hp 3 :.
636 637 638
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= B @ 0 :.
		A @ 1 .= to_word Hp :.
639 640
		grow_a 1 :.
		shrink_b 1 :.
641
		advance_ptr Hp 3
Camil Staps's avatar
Camil Staps committed
642
	, instr "build_u02" (Just 1) $
643
		ensure_hp 3 :.
644 645 646 647
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= B @ 0 :.
		Hp @ 2 .= B @ 1 :.
		A @ 1 .= to_word Hp :.
648 649
		grow_a 1 :.
		shrink_b 2 :.
650
		advance_ptr Hp 3
Camil Staps's avatar
Camil Staps committed
651
	, instr "build_u03" (Just 1) $
652
		ensure_hp 4 :.
653 654 655 656 657
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= B @ 0 :.
		Hp @ 2 .= B @ 1 :.
		Hp @ 3 .= B @ 2 :.
		A @ 1 .= to_word Hp :.
658 659
		grow_a 1 :.
		shrink_b 3 :.
660
		advance_ptr Hp 4
Camil Staps's avatar
Camil Staps committed
661
	, instr "build_u11" (Just 1) $
662
		ensure_hp 3 :.
663 664 665 666
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= B @ 0 :.
		A @ 0 .= to_word Hp :.
667
		shrink_b 1 :.
668
		advance_ptr Hp 3
Camil Staps's avatar
Camil Staps committed
669
	, instr "build_u12" (Just 1) $
670
		ensure_hp 4 :.
671 672 673 674 675
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= B @ 0 :.
		Hp @ 3 .= B @ 1 :.
		A @ 0 .= to_word Hp :.
676
		shrink_b 2 :.
677
		advance_ptr Hp 4
Camil Staps's avatar
Camil Staps committed
678
	, instr "build_u13" (Just 1) $
679
		ensure_hp 5 :.
680 681 682 683 684 685
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= B @ 0 :.
		Hp @ 3 .= B @ 1 :.
		Hp @ 4 .= B @ 2 :.
		A @ 0 .= to_word Hp :.
686
		shrink_b 3 :.
687
		advance_ptr Hp 5
Camil Staps's avatar
Camil Staps committed
688
	, instr "build_u21" (Just 1) $
689
		ensure_hp 4 :.
690 691 692 693 694
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= A @ -1 :.
		Hp @ 3 .= B @ 0 :.
		A @ -1 .= to_word Hp :.
695 696
		shrink_a 1 :.
		shrink_b 1 :.
697
		advance_ptr Hp 4
Camil Staps's avatar
Camil Staps committed
698
	, instr "build_u22" (Just 1) $
699
		ensure_hp 5 :.
700 701 702 703 704 705
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= A @ -1 :.
		Hp @ 3 .= B @ 0 :.
		Hp @ 4 .= B @ 1 :.
		A @ -1 .= to_word Hp :.
706 707
		shrink_a 1 :.
		shrink_b 2 :.
708
		advance_ptr Hp 5
Camil Staps's avatar
Camil Staps committed
709
	, instr "build_u31" (Just 1) $
710
		ensure_hp 5 :.
711 712 713 714 715 716
		Hp @ 0 .= Pc @ 1 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= A @ -1 :.
		Hp @ 3 .= A @ -2 :.
		Hp @ 4 .= B @ 0 :.
		A @ -2 .= to_word Hp :.
717 718
		shrink_a 2 :.
		shrink_b 1 :.
719
		advance_ptr Hp 5
Camil Staps's avatar
Camil Staps committed
720
	, instr "build_u0b" Nothing $
721 722 723 724 725 726 727
		new_local TWord (Pc @ 1) \n_b ->
		ensure_hp (n_b + lit_word 1) :.
		Hp @ 0 .= (Pc @ 2) :.
		for [1..4] (\i -> Hp @ i .= B @ (i-1)) :.
		advance_ptr Pc 3 :.
		unrolled_loop [5..32] (\i -> n_b <. lit_word i) (\i -> Hp @ i .= B @ (i-1)) :.
		A @ 1 .= to_word Hp :.
728
		grow_a 1 :.
729 730
		shrink_b n_b :.
		advance_ptr Hp (n_b + lit_word 1)
Camil Staps's avatar
Camil Staps committed
731
	, instr "build_u1b" Nothing $
732 733 734 735 736 737 738 739 740 741
		new_local TWord (Pc @ 1) \n_b ->
		ensure_hp (n_b + lit_word 2) :.
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= A @ 0 :.
		for [2..5] (\i -> Hp @ i .= B @ (i-2)) :.
		advance_ptr Pc 3 :.
		unrolled_loop [5..31] (\i -> n_b <. lit_word i) (\i -> Hp @ (i+1) .= B @ (i-1)) :.
		A @ 0 .= to_word Hp :.
		shrink_b n_b :.
		advance_ptr Hp (n_b + lit_word 2)
Camil Staps's avatar
Camil Staps committed
742
	, instr "build_u2b" Nothing $
743 744 745 746 747 748 749 750 751
		new_local TWord (Pc @ 1) \n_b ->
		ensure_hp (n_b + lit_word 3) :.
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= A @ 0 :.
		Hp @ 2 .= A @ -1 :.
		for [3..5] (\i -> Hp @ i .= B @ (i-3)) :.
		advance_ptr Pc 3 :.
		unrolled_loop [4..30] (\i -> n_b <. lit_word i) (\i -> Hp @ (i+2) .= B @ (i-1)) :.
		A @ -1 .= to_word Hp :.
752
		shrink_a 1 :.
753 754
		shrink_b n_b :.
		advance_ptr Hp (n_b + lit_word 3)
Camil Staps's avatar
Camil Staps committed
755
	, instr "build_ua1" Nothing $
756 757 758 759 760 761 762 763 764 765
		new_local TWord (Pc @ 1) \n_a ->
		ensure_hp (n_a + lit_word 2) :.
		Hp @ 0 .= Pc @ 2 :.
		for [1..4] (\i -> Hp @ i .= A @ (1-i)) :.
		advance_ptr Pc 3 :.
		unrolled_loop [5..31] (\i -> n_a <. lit_word i) (\i -> Hp @ i .= A @ (1-i)) :.
		shrink_a (n_a - lit_word 1) :.
		A @ 0 .= to_word Hp :.
		advance_ptr Hp (n_a + lit_word 2) :.
		Hp @ -1 .= B @ 0 :.
766
		shrink_b 1
Camil Staps's avatar
Camil Staps committed
767
	, instr "build_u" Nothing $
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
		new_local TWord (Pc @ 1) \n_ab ->
		ensure_hp (n_ab + lit_word 1) :.
		Hp @ 0 .= Pc @ 2 :.
		Hp @ 1 .= A @ 0 :.
		new_local TWord (Pc @ 3) \n_a ->
		new_local TWord (n_ab - n_a) \n_b ->
		Hp @ 2 .= A @ -1 :.
		unrolled_loop [3..30] (\i -> n_a <. lit_word i) (\i -> Hp @ i .= A @ (1-i)) :.
		shrink_a (n_a - lit_word 1) :.
		advance_ptr Pc 4 :.
		A @ 0 .= to_word Hp :.
		advance_ptr Hp (n_a + lit_word 1) :.
		Hp @ 0 .= B @ 0 :.
		Hp @ 1 .= B @ 1 :.
		unrolled_loop [3..30] (\i -> n_b <. lit_word i) (\i -> Hp @ (i-1) .= B @ (i-1)) :.
		shrink_b n_b :.
		advance_ptr Hp n_b