1use crate::vval::*;
9use crate::compiler::*;
10use crate::nvec::NVec;
11use crate::str_int::*;
12use std::fmt;
13use std::fmt::{Debug};
14use std::rc::Rc;
15
16#[derive(Clone, Default)]
17pub struct Prog {
18 pub debug: std::vec::Vec<Option<SynPos>>,
19 pub data: std::vec::Vec<VVal>,
20 pub(crate) ops: std::vec::Vec<Op>,
21 pub nxt_debug: Option<SynPos>,
22}
23
24fn patch_respos_data(rp: &mut ResPos, idx: u16) {
25 match rp {
26 ResPos::Data(i) => { *i += idx; },
27 ResPos::Global(i) => { *i += idx; },
28 ResPos::GlobalRef(i) => { *i += idx; },
29 ResPos::Local(_)
30 | ResPos::LocalRef(_)
31 | ResPos::Up(_)
32 | ResPos::UpRef(_)
33 | ResPos::Arg(_)
34 | ResPos::Stack(_)
35 | ResPos::Value(_)
36 => (),
37 }
38}
39
40impl Prog {
41 pub(crate) fn append(&mut self, mut prog: Prog) {
42 let self_data_next_idx : u16 = self.data.len() as u16;
43
44 for o in prog.ops.iter_mut() {
45 match o {
46 Op::Add(p1, p2, p3) => {
47 patch_respos_data(p1, self_data_next_idx);
48 patch_respos_data(p2, self_data_next_idx);
49 patch_respos_data(p3, self_data_next_idx);
50 },
51 Op::Sub(p1, p2, p3) => {
52 patch_respos_data(p1, self_data_next_idx);
53 patch_respos_data(p2, self_data_next_idx);
54 patch_respos_data(p3, self_data_next_idx);
55 },
56 Op::Mul(p1, p2, p3) => {
57 patch_respos_data(p1, self_data_next_idx);
58 patch_respos_data(p2, self_data_next_idx);
59 patch_respos_data(p3, self_data_next_idx);
60 },
61 Op::Div(p1, p2, p3) => {
62 patch_respos_data(p1, self_data_next_idx);
63 patch_respos_data(p2, self_data_next_idx);
64 patch_respos_data(p3, self_data_next_idx);
65 },
66 Op::Mod(p1, p2, p3) => {
67 patch_respos_data(p1, self_data_next_idx);
68 patch_respos_data(p2, self_data_next_idx);
69 patch_respos_data(p3, self_data_next_idx);
70 },
71 Op::Le(p1, p2, p3) => {
72 patch_respos_data(p1, self_data_next_idx);
73 patch_respos_data(p2, self_data_next_idx);
74 patch_respos_data(p3, self_data_next_idx);
75 },
76 Op::Lt(p1, p2, p3) => {
77 patch_respos_data(p1, self_data_next_idx);
78 patch_respos_data(p2, self_data_next_idx);
79 patch_respos_data(p3, self_data_next_idx);
80 },
81 Op::Ge(p1, p2, p3) => {
82 patch_respos_data(p1, self_data_next_idx);
83 patch_respos_data(p2, self_data_next_idx);
84 patch_respos_data(p3, self_data_next_idx);
85 },
86 Op::Gt(p1, p2, p3) => {
87 patch_respos_data(p1, self_data_next_idx);
88 patch_respos_data(p2, self_data_next_idx);
89 patch_respos_data(p3, self_data_next_idx);
90 },
91 Op::Eq(p1, p2, p3) => {
92 patch_respos_data(p1, self_data_next_idx);
93 patch_respos_data(p2, self_data_next_idx);
94 patch_respos_data(p3, self_data_next_idx);
95 },
96 Op::NewPair(p1, p2, p3) => {
97 patch_respos_data(p1, self_data_next_idx);
98 patch_respos_data(p2, self_data_next_idx);
99 patch_respos_data(p3, self_data_next_idx);
100 },
101 Op::NewOpt(p1, p2) => {
102 patch_respos_data(p1, self_data_next_idx);
103 patch_respos_data(p2, self_data_next_idx);
104 },
105 Op::NewIter(p1, p2) => {
106 patch_respos_data(p1, self_data_next_idx);
107 patch_respos_data(p2, self_data_next_idx);
108 },
109 Op::NewNVec(vec, p1) => {
110 use std::borrow::BorrowMut;
111 match vec.borrow_mut() {
112 NVecPos::IVec2(a, b) => {
113 patch_respos_data(a, self_data_next_idx);
114 patch_respos_data(b, self_data_next_idx);
115 },
116 NVecPos::IVec3(a, b, c) => {
117 patch_respos_data(a, self_data_next_idx);
118 patch_respos_data(b, self_data_next_idx);
119 patch_respos_data(c, self_data_next_idx);
120 },
121 NVecPos::IVec4(a, b, c, d) => {
122 patch_respos_data(a, self_data_next_idx);
123 patch_respos_data(b, self_data_next_idx);
124 patch_respos_data(c, self_data_next_idx);
125 patch_respos_data(d, self_data_next_idx);
126 },
127 NVecPos::FVec2(a, b) => {
128 patch_respos_data(a, self_data_next_idx);
129 patch_respos_data(b, self_data_next_idx);
130 },
131 NVecPos::FVec3(a, b, c) => {
132 patch_respos_data(a, self_data_next_idx);
133 patch_respos_data(b, self_data_next_idx);
134 patch_respos_data(c, self_data_next_idx);
135 },
136 NVecPos::FVec4(a, b, c, d) => {
137 patch_respos_data(a, self_data_next_idx);
138 patch_respos_data(b, self_data_next_idx);
139 patch_respos_data(c, self_data_next_idx);
140 patch_respos_data(d, self_data_next_idx);
141 },
142 }
143 patch_respos_data(p1, self_data_next_idx);
144 },
145 Op::Mov(p1, p2) => {
146 patch_respos_data(p1, self_data_next_idx);
147 patch_respos_data(p2, self_data_next_idx);
148 },
149 Op::ToRef(p1, p2, _) => {
150 patch_respos_data(p1, self_data_next_idx);
151 patch_respos_data(p2, self_data_next_idx);
152 },
153 Op::NewErr(p1, p2) => {
154 patch_respos_data(p1, self_data_next_idx);
155 patch_respos_data(p2, self_data_next_idx);
156 },
157 Op::NewClos(p1, p2) => {
158 patch_respos_data(p1, self_data_next_idx);
159 patch_respos_data(p2, self_data_next_idx);
160 },
161 Op::ListPush(p1, p2, p3) => {
162 patch_respos_data(p1, self_data_next_idx);
163 patch_respos_data(p2, self_data_next_idx);
164 patch_respos_data(p3, self_data_next_idx);
165 },
166 Op::ListSplice(p1, p2, p3) => {
167 patch_respos_data(p1, self_data_next_idx);
168 patch_respos_data(p2, self_data_next_idx);
169 patch_respos_data(p3, self_data_next_idx);
170 },
171 Op::MapSetKey(p1, p2, p3, p4) => {
172 patch_respos_data(p1, self_data_next_idx);
173 patch_respos_data(p2, self_data_next_idx);
174 patch_respos_data(p3, self_data_next_idx);
175 patch_respos_data(p4, self_data_next_idx);
176 },
177 Op::MapSplice(p1, p2, p3) => {
178 patch_respos_data(p1, self_data_next_idx);
179 patch_respos_data(p2, self_data_next_idx);
180 patch_respos_data(p3, self_data_next_idx);
181 },
182 Op::JmpIfN(p1, _) => {
183 patch_respos_data(p1, self_data_next_idx);
184 },
185 Op::OrJmp(p1, _, p2, _) => {
186 patch_respos_data(p1, self_data_next_idx);
187 patch_respos_data(p2, self_data_next_idx);
188 },
189 Op::AndJmp(p1, _, p2) => {
190 patch_respos_data(p1, self_data_next_idx);
191 patch_respos_data(p2, self_data_next_idx);
192 },
193 Op::JmpTbl(p1, _) => {
194 patch_respos_data(p1, self_data_next_idx);
195 },
196 Op::GetIdx(p1, _, _) => {
197 patch_respos_data(p1, self_data_next_idx);
198 },
199 Op::GetIdx2(p1, _, _) => {
200 patch_respos_data(p1, self_data_next_idx);
201 },
202 Op::GetIdx3(p1, _, _) => {
203 patch_respos_data(p1, self_data_next_idx);
204 },
205 Op::GetSym(p1, _, _) => {
206 patch_respos_data(p1, self_data_next_idx);
207 },
208 Op::GetSym2(p1, _, _) => {
209 patch_respos_data(p1, self_data_next_idx);
210 },
211 Op::GetSym3(p1, _, _) => {
212 patch_respos_data(p1, self_data_next_idx);
213 },
214 Op::GetKey(p1, p2, _) => {
215 patch_respos_data(p1, self_data_next_idx);
216 patch_respos_data(p2, self_data_next_idx);
217 },
218 Op::Destr(p1, _) => {
219 patch_respos_data(p1, self_data_next_idx);
220 },
221 Op::Call(_, p1) => {
222 patch_respos_data(p1, self_data_next_idx);
223 },
224 Op::CallDirect(fun) => {
225 patch_respos_data(
226 &mut Rc::get_mut(fun).expect("only rc").arg,
227 self_data_next_idx);
228 patch_respos_data(
229 &mut Rc::get_mut(fun).expect("only rc").res,
230 self_data_next_idx);
231 },
232 Op::CallMethodKey(p1, p2, _, p3) => {
233 patch_respos_data(p1, self_data_next_idx);
234 patch_respos_data(p2, self_data_next_idx);
235 patch_respos_data(p3, self_data_next_idx);
236 },
237 Op::CallMethodSym(p1, _, p2) => {
238 patch_respos_data(p1, self_data_next_idx);
239 patch_respos_data(p2, self_data_next_idx);
240 },
241 Op::Apply(p1, p2, p3) => {
242 patch_respos_data(p1, self_data_next_idx);
243 patch_respos_data(p2, self_data_next_idx);
244 patch_respos_data(p3, self_data_next_idx);
245 },
246 Op::Builtin(Builtin::Export(_, p1)) => {
247 patch_respos_data(p1, self_data_next_idx);
248 },
249 Op::CtrlFlow(CtrlFlow::Break(p1)) => {
250 patch_respos_data(p1, self_data_next_idx);
251 },
252 Op::IterInit(p1, _) => {
253 patch_respos_data(p1, self_data_next_idx);
254 },
255 Op::IterNext(p1) => {
256 patch_respos_data(p1, self_data_next_idx);
257 },
258Op::NewMap(p1) => { patch_respos_data(p1, self_data_next_idx); },
263 Op::NewList(p1) => { patch_respos_data(p1, self_data_next_idx); },
264 Op::Argv(p1) => { patch_respos_data(p1, self_data_next_idx); },
265 Op::End
266 | Op::Builtin(Builtin::DumpStack(_))
267 | Op::Builtin(Builtin::DumpVM(_))
268 | Op::CtrlFlow(CtrlFlow::Next)
269 | Op::Unwind
270 | Op::Accumulator(_)
271 | Op::PushLoopInfo(_)
272 | Op::Jmp(_)
273 | Op::ClearLocals(_, _)
274 => (),
275 }
276 }
277
278 self.debug.append(&mut prog.debug);
279 self.data.append(&mut prog.data);
280 self.ops.append(&mut prog.ops);
281 }
282
283 pub(crate) fn op_count(&self) -> usize { self.ops.len() }
284
285 pub(crate) fn new() -> Self {
286 Self {
287 data: vec![],
288 ops: vec![],
289 debug: vec![],
290 nxt_debug: None,
291 }
292 }
293
294 pub(crate) fn global_ref_pos(&mut self, data: VVal) -> ResPos {
295 self.data.push(data);
296 ResPos::GlobalRef((self.data.len() - 1) as u16)
297 }
298
299 pub(crate) fn global_pos(&mut self, data: VVal) -> ResPos {
300 self.data.push(data);
301 ResPos::Global((self.data.len() - 1) as u16)
302 }
303
304 pub(crate) fn data_pos(&mut self, data: VVal) -> ResPos {
305 self.data.push(data);
306 ResPos::Data((self.data.len() - 1) as u16)
307 }
308
309pub(crate) fn push_op(&mut self, o: Op) -> &mut Self {
316 self.ops.push(o);
317 self.debug.push(std::mem::replace(&mut self.nxt_debug, None));
318 self
319 }
320
321 pub(crate) fn set_dbg(&mut self, sp: SynPos) -> &mut Self {
322 self.nxt_debug = Some(sp);
323 self
324 }
325
326 pub(crate) fn op_end(&mut self) -> &mut Self {
327 self.push_op(Op::End);
328 self
329 }
330
331 pub(crate) fn op_mov(&mut self, sp: &SynPos, a: ResPos, r: ResPos) {
332 self.set_dbg(sp.clone());
333 self.push_op(Op::Mov(a, r));
334 }
335
336 pub(crate) fn op_and_jmp(&mut self, sp: &SynPos, a: ResPos, jmp: i32, r: ResPos) {
337 self.set_dbg(sp.clone());
338 self.push_op(Op::AndJmp(a, jmp, r));
339 }
340
341 pub(crate) fn op_or_jmp_mode(&mut self, sp: &SynPos, a: ResPos, jmp: i32, r: ResPos, mode: OrMode) {
342 self.set_dbg(sp.clone());
343 self.push_op(Op::OrJmp(a, jmp, r, mode));
344 }
345
346 pub(crate) fn op_jmp_tbl(&mut self, sp: &SynPos, a: ResPos, tbl: Vec<i32>) {
347 self.set_dbg(sp.clone());
348 self.push_op(Op::JmpTbl(a, Box::new(tbl)));
349 }
350
351 pub(crate) fn op_destr(&mut self, sp: &SynPos, a: ResPos, destr_info: DestructureInfo) {
352 self.set_dbg(sp.clone());
353 self.push_op(Op::Destr(a, Box::new(destr_info)));
354 }
355
356 pub(crate) fn op_to_ref(&mut self, sp: &SynPos, a: ResPos, r: ResPos, typ: ToRefType) {
357 self.set_dbg(sp.clone());
358 self.push_op(Op::ToRef(a, r, typ));
359 }
360
361 pub(crate) fn op_new_list(&mut self, sp: &SynPos, r: ResPos) {
362 self.set_dbg(sp.clone());
363 self.push_op(Op::NewList(r));
364 }
365
366 pub(crate) fn op_list_splice(&mut self, sp: &SynPos, a: ResPos, b: ResPos, r: ResPos) {
367 self.set_dbg(sp.clone());
368 self.push_op(Op::ListSplice(a, b, r));
369 }
370
371 pub(crate) fn op_list_push(&mut self, sp: &SynPos, a: ResPos, b: ResPos, r: ResPos) {
372 self.set_dbg(sp.clone());
373 self.push_op(Op::ListPush(a, b, r));
374 }
375
376 pub(crate) fn op_new_map(&mut self, sp: &SynPos, r: ResPos) {
377 self.set_dbg(sp.clone());
378 self.push_op(Op::NewMap(r));
379 }
380
381 pub(crate) fn op_map_set_key(&mut self, sp: &SynPos, a: ResPos, b: ResPos, c: ResPos, r: ResPos) {
382 self.set_dbg(sp.clone());
383 self.push_op(Op::MapSetKey(a, b, c, r));
384 }
385
386 pub(crate) fn op_map_splice(&mut self, sp: &SynPos, a: ResPos, b: ResPos, r: ResPos) {
387 self.set_dbg(sp.clone());
388 self.push_op(Op::MapSplice(a, b, r));
389 }
390
391 pub(crate) fn op_get_key(&mut self, sp: &SynPos, a: ResPos, b: ResPos, r: ResPos) {
392 self.set_dbg(sp.clone());
393 self.push_op(Op::GetKey(a, b, r));
394 }
395
396 pub(crate) fn op_get_idx(&mut self, sp: &SynPos, a: ResPos, i: u32, r: ResPos) {
397 self.set_dbg(sp.clone());
398 self.push_op(Op::GetIdx(a, i, r));
399 }
400
401 pub(crate) fn op_get_idx2(&mut self, sp: &SynPos, a: ResPos, i: u32, i2: u32, r: ResPos) {
402 self.set_dbg(sp.clone());
403 self.push_op(Op::GetIdx2(a, Box::new((i, i2)), r));
404 }
405
406 pub(crate) fn op_get_idx3(&mut self, sp: &SynPos, a: ResPos, i: u32, i2: u32, i3: u32, r: ResPos) {
407 self.set_dbg(sp.clone());
408 self.push_op(Op::GetIdx3(a, Box::new((i, i2, i3)), r));
409 }
410
411 pub(crate) fn op_get_sym(&mut self, sp: &SynPos, a: ResPos, s: Symbol, r: ResPos) {
412 self.set_dbg(sp.clone());
413 self.push_op(Op::GetSym(a, Box::new(s), r));
414 }
415
416 pub(crate) fn op_get_sym2(&mut self, sp: &SynPos, a: ResPos, s: Symbol, s2: Symbol, r: ResPos) {
417 self.set_dbg(sp.clone());
418 self.push_op(Op::GetSym2(a, Box::new((s, s2)), r));
419 }
420
421 pub(crate) fn op_get_sym3(&mut self, sp: &SynPos, a: ResPos, s: Symbol, s2: Symbol, s3: Symbol, r: ResPos) {
422 self.set_dbg(sp.clone());
423 self.push_op(Op::GetSym3(a, Box::new((s, s2, s3)), r));
424 }
425
426 pub(crate) fn op_new_err(&mut self, sp: &SynPos, a: ResPos, r: ResPos) {
427 self.set_dbg(sp.clone());
428 self.push_op(Op::NewErr(a, r));
429 }
430
431 pub(crate) fn op_argv(&mut self, sp: &SynPos, r: ResPos) {
432 self.set_dbg(sp.clone());
433 self.push_op(Op::Argv(r));
434 }
435
436 pub(crate) fn op_unwind(&mut self, sp: &SynPos) {
437 self.set_dbg(sp.clone());
438 self.push_op(Op::Unwind);
439 }
440
441 pub(crate) fn op_binop(&mut self, sp: &SynPos, op: BinOp, a: ResPos, b: ResPos, r: ResPos) {
442 self.set_dbg(sp.clone());
443 self.push_op(op.to_op(a, b, r));
444 }
445
446 pub(crate) fn op_new_opt(&mut self, sp: &SynPos, a: ResPos, r: ResPos) {
447 self.set_dbg(sp.clone());
448 self.push_op(Op::NewOpt(a, r));
449 }
450
451 pub(crate) fn op_new_iter(&mut self, sp: &SynPos, a: ResPos, r: ResPos) {
452 self.set_dbg(sp.clone());
453 self.push_op(Op::NewIter(a, r));
454 }
455
456 pub(crate) fn op_new_clos(&mut self, sp: &SynPos, a: ResPos, r: ResPos) {
457 self.set_dbg(sp.clone());
458 self.push_op(Op::NewClos(a, r));
459 }
460
461 pub(crate) fn op_call_method_key(&mut self, sp: &SynPos, a: ResPos, b: ResPos, argc: u16, r: ResPos) {
462 self.set_dbg(sp.clone());
463 self.push_op(Op::CallMethodKey(a, b, argc, r));
464 }
465
466 pub(crate) fn op_call_method_sym(&mut self, sp: &SynPos, a: ResPos, sym: String, argc: u16, r: ResPos) {
467 self.set_dbg(sp.clone());
468 self.push_op(Op::CallMethodSym(a, Box::new((sym, argc)), r));
469 }
470
471 pub(crate) fn op_call_direct(&mut self, sp: &SynPos, a: ResPos, mut fun: DirectFun, r: ResPos) {
472 self.set_dbg(sp.clone());
473 fun.arg = a;
474 fun.res = r;
475 self.push_op(Op::CallDirect(Rc::new(fun)));
476 }
477
478 pub(crate) fn op_call(&mut self, sp: &SynPos, argc: u16, r: ResPos) {
479 self.set_dbg(sp.clone());
480 self.push_op(Op::Call(argc, r));
481 }
482
483 pub(crate) fn op_new_ivec2(&mut self, sp: &SynPos, a: ResPos, b: ResPos, r: ResPos) {
484 self.set_dbg(sp.clone());
485 self.push_op(Op::NewNVec(Box::new(NVecPos::IVec2(a, b)), r));
486 }
487
488 pub(crate) fn op_new_ivec3(&mut self, sp: &SynPos, a: ResPos, b: ResPos, c: ResPos, r: ResPos) {
489 self.set_dbg(sp.clone());
490 self.push_op(Op::NewNVec(Box::new(NVecPos::IVec3(a, b, c)), r));
491 }
492
493 #[allow(clippy::many_single_char_names)]
494 pub(crate) fn op_new_ivec4(&mut self, sp: &SynPos, a: ResPos, b: ResPos, c: ResPos, d: ResPos, r: ResPos) {
495 self.set_dbg(sp.clone());
496 self.push_op(Op::NewNVec(Box::new(NVecPos::IVec4(a, b, c, d)), r));
497 }
498
499 pub(crate) fn op_new_fvec2(&mut self, sp: &SynPos, a: ResPos, b: ResPos, r: ResPos) {
500 self.set_dbg(sp.clone());
501 self.push_op(Op::NewNVec(Box::new(NVecPos::FVec2(a, b)), r));
502 }
503
504 pub(crate) fn op_new_fvec3(&mut self, sp: &SynPos, a: ResPos, b: ResPos, c: ResPos, r: ResPos) {
505 self.set_dbg(sp.clone());
506 self.push_op(Op::NewNVec(Box::new(NVecPos::FVec3(a, b, c)), r));
507 }
508
509 #[allow(clippy::many_single_char_names)]
510 pub(crate) fn op_new_fvec4(&mut self, sp: &SynPos, a: ResPos, b: ResPos, c: ResPos, d: ResPos, r: ResPos) {
511 self.set_dbg(sp.clone());
512 self.push_op(Op::NewNVec(Box::new(NVecPos::FVec4(a, b, c, d)), r));
513 }
514
515 pub(crate) fn op_clear_locals(&mut self, sp: &SynPos, from: u16, to: u16) {
516 self.set_dbg(sp.clone());
517 self.push_op(Op::ClearLocals(from, to));
518 }
519
520 pub(crate) fn op_ctrl_flow_break(&mut self, sp: &SynPos, a: ResPos) {
521 self.set_dbg(sp.clone());
522 self.push_op(Op::CtrlFlow(CtrlFlow::Break(a)));
523 }
524
525 pub(crate) fn op_ctrl_flow_next(&mut self, sp: &SynPos) {
526 self.set_dbg(sp.clone());
527 self.push_op(Op::CtrlFlow(CtrlFlow::Next));
528 }
529
530 pub(crate) fn op_jmp(&mut self, sp: &SynPos, offs: i32) {
531 self.set_dbg(sp.clone());
532 self.push_op(Op::Jmp(offs));
533 }
534
535 pub(crate) fn op_jmp_ifn(&mut self, sp: &SynPos, a: ResPos, offs: i32) {
536 self.set_dbg(sp.clone());
537 self.push_op(Op::JmpIfN(a, offs));
538 }
539
540 pub(crate) fn op_push_loop_info(&mut self, sp: &SynPos, break_offs: u16) {
541 self.set_dbg(sp.clone());
542 self.push_op(Op::PushLoopInfo(break_offs));
543 }
544
545 pub(crate) fn op_iter_init(&mut self, sp: &SynPos, a: ResPos, end_offs: i32) {
546 self.set_dbg(sp.clone());
547 self.push_op(Op::IterInit(a, end_offs));
548 }
549
550 pub(crate) fn op_iter_next(&mut self, sp: &SynPos, r: ResPos) {
551 self.set_dbg(sp.clone());
552 self.push_op(Op::IterNext(r));
553 }
554
555 pub(crate) fn op_apply(&mut self, sp: &SynPos, a: ResPos, b: ResPos, r: ResPos) {
556 self.set_dbg(sp.clone());
557 self.push_op(Op::Apply(a, b, r));
558 }
559
560 pub(crate) fn op_dump_vm(&mut self, sp: &SynPos) {
561 self.set_dbg(sp.clone());
562 self.push_op(Op::Builtin(Builtin::DumpVM(Box::new(sp.clone()))));
563 }
564
565 pub(crate) fn op_dump_stack(&mut self, sp: &SynPos) {
566 self.set_dbg(sp.clone());
567 self.push_op(Op::Builtin(Builtin::DumpStack(Box::new(sp.clone()))));
568 }
569
570 pub(crate) fn op_export(&mut self, sp: &SynPos, a: ResPos, name: String) {
571 self.set_dbg(sp.clone());
572 self.push_op(Op::Builtin(Builtin::Export(Box::new(name), a)));
573 }
574
575 pub(crate) fn op_new_pair(&mut self, sp: &SynPos, a: ResPos, b: ResPos, r: ResPos) {
576 self.set_dbg(sp.clone());
577 self.push_op(Op::NewPair(a, b, r));
578 }
579
580 pub(crate) fn op_accumulator(&mut self, sp: &SynPos, at: AccumType) {
581 self.set_dbg(sp.clone());
582 self.push_op(Op::Accumulator(at));
583 }
584
585 pub fn dump(&self) {
586 println!("PROG:");
587 for (i, o) in self.ops.iter().enumerate() {
588 println!(" [{:>3}] {:?}", i, o);
589 }
590 println!(" DATA:");
591 for (i, o) in self.data.iter().enumerate() {
592 println!(" [{:>3}] {:?}", i, o);
593 }
594 }
595}
596
597impl Debug for Prog {
598 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
599 writeln!(f, "PROG:")?;
600 for (i, o) in self.ops.iter().enumerate() {
601 writeln!(f, " [{:>3}] {:?}", i, o)?;
602 }
603 writeln!(f, " DATA:")?;
604 for (i, o) in self.data.iter().enumerate() {
605 writeln!(f, " [{:>3}] {:?}", i, o)?;
606 }
607 Ok(())
608 }
609}
610
611#[derive(Debug, Clone)]
612pub(crate) struct DestructureInfo {
613 pub vars: VVal,
614 pub poses: std::vec::Vec<VarPos>,
615 pub is_ref: bool,
616}
617
618fn set_env_at_varpos(e: &mut Env, pos: &VarPos, v: &VVal) {
619 match pos {
620 VarPos::UpValue(d) => e.set_up(*d, v.clone()),
621 VarPos::Local(d) => e.set_consume(*d, v.clone()),
622 VarPos::Global(VVal::Ref(r)) => { r.replace(v.clone()); },
623 VarPos::Global(_)
624 | VarPos::Const(_)
625 | VarPos::NoPos
626 => panic!(
627 "Fatal error in WLambda, can't destructure to {:?}", pos),
628 }
629}
630
631fn set_ref_at_varpos(e: &mut Env, pos: &VarPos, rv: &VVal) {
632 let v = rv.clone();
633 match pos {
634 VarPos::UpValue(d) => e.assign_ref_up(*d, v),
635 VarPos::Local(d) => e.assign_ref_local(*d, v),
636 VarPos::Global(VVal::Ref(r)) => { r.borrow().set_ref(v); },
637 VarPos::Global(_)
638 | VarPos::Const(_)
639 | VarPos::NoPos
640 => panic!(
641 "Fatal error in WLambda, can't ref destructure to {:?}", pos),
642 }
643}
644
645macro_rules! set_at_varpos {
646 ($self: ident, $env: ident, $pos: ident, $v: expr) => {
647 if $self.is_ref {
648 set_ref_at_varpos($env, $pos, $v);
649 } else {
650 set_env_at_varpos($env, $pos, $v);
651 }
652 }
653}
654
655impl DestructureInfo {
656 #[allow(clippy::cognitive_complexity)]
657 pub fn destructure(&self, env: &mut Env, val: VVal) {
658 match val {
659 VVal::Lst(l) => {
660 let nul = VVal::None;
661 for (i, pos) in self.poses.iter().enumerate() {
662 set_at_varpos!(
663 self, env, pos, l.borrow().get(i).unwrap_or(&nul));
664 }
665 },
666 VVal::Map(m) => {
667 for (i, pos) in self.poses.iter().enumerate() {
668 let sym = self.vars.at(i).unwrap().to_sym();
669 let val = m.borrow().get(&sym).cloned().unwrap_or(VVal::None);
670
671 set_at_varpos!(self, env, pos, &val);
672 }
673 },
674 VVal::Pair(p) => {
675 let (lv, rv) = &*p;
676
677 if let Some(pos) = self.poses.get(0) {
678 set_at_varpos!(self, env, pos, lv);
679 }
680
681 if let Some(pos) = self.poses.get(1) {
682 set_at_varpos!(self, env, pos, rv);
683 }
684 },
685 VVal::IVec(vb) => {
686 match vb.as_ref() {
687 NVec::Vec2(a, b) => {
688 if let Some(pos) = self.poses.get(0) {
689 set_at_varpos!(self, env, pos, &VVal::Int(*a));
690 }
691
692 if let Some(pos) = self.poses.get(1) {
693 set_at_varpos!(self, env, pos, &VVal::Int(*b));
694 }
695 },
696 NVec::Vec3(a, b, c) => {
697 if let Some(pos) = self.poses.get(0) {
698 set_at_varpos!(self, env, pos, &VVal::Int(*a));
699 }
700
701 if let Some(pos) = self.poses.get(1) {
702 set_at_varpos!(self, env, pos, &VVal::Int(*b));
703 }
704
705 if let Some(pos) = self.poses.get(2) {
706 set_at_varpos!(self, env, pos, &VVal::Int(*c));
707 }
708 },
709 NVec::Vec4(a, b, c, d) => {
710 if let Some(pos) = self.poses.get(0) {
711 set_at_varpos!(self, env, pos, &VVal::Int(*a));
712 }
713
714 if let Some(pos) = self.poses.get(1) {
715 set_at_varpos!(self, env, pos, &VVal::Int(*b));
716 }
717
718 if let Some(pos) = self.poses.get(2) {
719 set_at_varpos!(self, env, pos, &VVal::Int(*c));
720 }
721
722 if let Some(pos) = self.poses.get(3) {
723 set_at_varpos!(self, env, pos, &VVal::Int(*d));
724 }
725 },
726 }
727 },
728 VVal::FVec(vb) => {
729 match vb.as_ref() {
730 NVec::Vec2(a, b) => {
731 if let Some(pos) = self.poses.get(0) {
732 set_at_varpos!(self, env, pos, &VVal::Flt(*a));
733 }
734
735 if let Some(pos) = self.poses.get(1) {
736 set_at_varpos!(self, env, pos, &VVal::Flt(*b));
737 }
738 },
739 NVec::Vec3(a, b, c) => {
740 if let Some(pos) = self.poses.get(0) {
741 set_at_varpos!(self, env, pos, &VVal::Flt(*a));
742 }
743
744 if let Some(pos) = self.poses.get(1) {
745 set_at_varpos!(self, env, pos, &VVal::Flt(*b));
746 }
747
748 if let Some(pos) = self.poses.get(2) {
749 set_at_varpos!(self, env, pos, &VVal::Flt(*c));
750 }
751 },
752 NVec::Vec4(a, b, c, d) => {
753 if let Some(pos) = self.poses.get(0) {
754 set_at_varpos!(self, env, pos, &VVal::Flt(*a));
755 }
756
757 if let Some(pos) = self.poses.get(1) {
758 set_at_varpos!(self, env, pos, &VVal::Flt(*b));
759 }
760
761 if let Some(pos) = self.poses.get(2) {
762 set_at_varpos!(self, env, pos, &VVal::Flt(*c));
763 }
764
765 if let Some(pos) = self.poses.get(3) {
766 set_at_varpos!(self, env, pos, &VVal::Flt(*d));
767 }
768 },
769 }
770 },
771 _ => {
772 for pos in self.poses.iter() {
773 set_at_varpos!(self, env, pos, &val);
774 }
775 }
776 }
777 }
778}
779
780#[derive(Debug, Clone, Copy)]
781pub(crate) enum BinOp {
782 Add,
783 Sub,
784 Mul,
785 Div,
786 Mod,
787 Le,
788 Lt,
789 Ge,
790 Gt,
791 Eq,
792}
793
794impl BinOp {
795 pub(crate) fn to_op(self, a: ResPos, b: ResPos, out: ResPos) -> Op {
796 match self {
797 BinOp::Add => Op::Add(a, b, out),
798 BinOp::Sub => Op::Sub(a, b, out),
799 BinOp::Mul => Op::Mul(a, b, out),
800 BinOp::Div => Op::Div(a, b, out),
801 BinOp::Mod => Op::Mod(a, b, out),
802 BinOp::Le => Op::Le(a, b, out),
803 BinOp::Lt => Op::Lt(a, b, out),
804 BinOp::Ge => Op::Ge(a, b, out),
805 BinOp::Gt => Op::Gt(a, b, out),
806 BinOp::Eq => Op::Eq(a, b, out),
807 }
808 }
809}
810
811#[derive(Debug,Clone,Copy)]
812pub(crate) enum AccumType {
813 String,
814 Bytes,
815 Float,
816 Int,
817 Map,
818 Vec,
819}
820
821#[derive(Debug,Clone)]
822pub(crate) enum ToRefType {
823 CaptureRef,
824 ToRef,
825 Deref,
826 Hidden,
827 Weak,
828}
829
830#[derive(Debug,Clone)]
831#[allow(clippy::box_collection)]
832pub(crate) enum Builtin {
833 Export(Box<String>, ResPos),
834 DumpStack(Box<SynPos>),
835 DumpVM(Box<SynPos>),
836}
837
838#[derive(Debug,Clone)]
839pub(crate) enum CtrlFlow {
840 Next,
841 Break(ResPos),
842}
843
844#[derive(Debug,Clone)]
845pub(crate) enum NVecPos {
846 IVec2(ResPos, ResPos),
847 IVec3(ResPos, ResPos, ResPos),
848 IVec4(ResPos, ResPos, ResPos, ResPos),
849 FVec2(ResPos, ResPos),
850 FVec3(ResPos, ResPos, ResPos),
851 FVec4(ResPos, ResPos, ResPos, ResPos),
852}
853
854#[derive(Clone)]
855pub(crate) struct DirectFun {
856 pub arg: ResPos,
857 pub res: ResPos,
858 pub fun: Rc<dyn Fn(VVal, &mut Env) -> VVal>,
859}
860
861impl DirectFun {
862 pub fn new(fun: Rc<dyn Fn(VVal, &mut Env) -> VVal>) -> Self {
863 Self {
864 arg: ResPos::Stack(0),
865 res: ResPos::Stack(0),
866 fun,
867 }
868 }
869}
870
871impl Debug for DirectFun {
872 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
873 write!(f, "Box<DirectFun:?;arg={:?},res={:?}>", self.arg, self.res)
874 }
875}
876
877#[derive(Debug,Clone,Copy)]
878#[repr(u8)]
879pub(crate) enum OrMode {
880 Bool,
881 SomeOp,
882 ExtSomeOp,
883 NoneOp,
884 ErrOp,
885 OptOp,
886}
887
888#[allow(clippy::box_collection)]
889#[derive(Debug,Clone)]
890pub(crate) enum Op {
891 Mov(ResPos, ResPos),
892 NewOpt(ResPos, ResPos),
893 NewIter(ResPos, ResPos),
894 NewPair(ResPos, ResPos, ResPos),
895 NewNVec(Box<NVecPos>, ResPos),
896 Argv(ResPos),
897 ToRef(ResPos, ResPos, ToRefType),
898 ClearLocals(u16, u16),
899 Accumulator(AccumType),
900 PushLoopInfo(u16),
901 Add(ResPos, ResPos, ResPos),
902 Sub(ResPos, ResPos, ResPos),
903 Mul(ResPos, ResPos, ResPos),
904 Div(ResPos, ResPos, ResPos),
905 Mod(ResPos, ResPos, ResPos),
906 Le(ResPos, ResPos, ResPos),
907 Lt(ResPos, ResPos, ResPos),
908 Ge(ResPos, ResPos, ResPos),
909 Gt(ResPos, ResPos, ResPos),
910 Eq(ResPos, ResPos, ResPos),
911 NewErr(ResPos, ResPos),
912 NewList(ResPos),
913 ListPush(ResPos, ResPos, ResPos),
914 ListSplice(ResPos, ResPos, ResPos),
915 NewMap(ResPos),
916 MapSetKey(ResPos, ResPos, ResPos, ResPos),
917 MapSplice(ResPos, ResPos, ResPos),
918 NewClos(ResPos, ResPos),
919 GetIdx(ResPos, u32, ResPos),
920 GetIdx2(ResPos, Box<(u32, u32)>, ResPos),
921 GetIdx3(ResPos, Box<(u32, u32, u32)>, ResPos),
922 GetSym(ResPos, Box<Symbol>, ResPos),
923 GetSym2(ResPos, Box<(Symbol, Symbol)>, ResPos),
924 GetSym3(ResPos, Box<(Symbol, Symbol, Symbol)>, ResPos),
925 GetKey(ResPos, ResPos, ResPos),
926 Destr(ResPos, Box<DestructureInfo>),
927 Call(u16, ResPos),
928 CallDirect(Rc<DirectFun>),
929 CallMethodKey(ResPos, ResPos, u16, ResPos),
930 CallMethodSym(ResPos, Box<(String, u16)>, ResPos),
931 Apply(ResPos, ResPos, ResPos),
932 Jmp(i32),
933 JmpIfN(ResPos, i32),
934 OrJmp(ResPos, i32, ResPos, OrMode),
935 AndJmp(ResPos, i32, ResPos),
936 JmpTbl(ResPos, Box<Vec<i32>>),
937 CtrlFlow(CtrlFlow),
938 Builtin(Builtin),
939 IterInit(ResPos, i32),
940 IterNext(ResPos),
941Unwind,
943 End,
944}