1 // Copyright (c) Facebook, Inc. and its affiliates.
3 // This source code is licensed under the MIT license found in the
4 // LICENSE file in the "hack" directory of this source tree.
8 Maybe::{self, Just, Nothing},
12 use iterator::Id as IterId;
15 use oxidized::ast_defs::Pos;
16 use runtime::TypedValue;
19 pub type Result<T> = std::result::Result<T, Error>;
21 #[derive(Error, Debug)]
23 #[error("IncludeTimeFatalException: FatalOp={0:?}, {1}")]
24 IncludeTimeFatalException(FatalOp, Pos, std::string::String),
26 #[error("Unrecoverable: {0}")]
27 Unrecoverable(std::string::String),
30 pub fn unrecoverable(msg: impl std::convert::Into<std::string::String>) -> Error {
31 Error::Unrecoverable(msg.into())
34 /// The various from_X functions below take some kind of AST
35 /// (expression, statement, etc.) and produce what is logically a
36 /// sequence of instructions. This could be represented by a list, but
37 /// we wish to avoid the quadratic complexity associated with repeated
38 /// appending. So, we build a tree of instructions which can be
39 /// flattened when complete.
42 pub enum InstrSeq<'a> {
43 List(BumpSliceMut<'a, Instruct<'a>>),
44 Concat(BumpSliceMut<'a, InstrSeq<'a>>),
46 // The slices are mutable because of `rewrite_user_labels`. This means
47 // we can't derive `Clone` (because you can't have multiple mutable
48 // references referring to the same resource). It is possible to implement
49 // deep copy functionality though: see `InstrSeq::clone()` below.
51 impl<'a> std::convert::From<(&'a bumpalo::Bump, (InstrSeq<'a>, InstrSeq<'a>))> for InstrSeq<'a> {
52 fn from((alloc, (i1, i2)): (&'a bumpalo::Bump, (InstrSeq<'a>, InstrSeq<'a>))) -> InstrSeq<'a> {
53 InstrSeq::gather(alloc, vec![i1, i2])
58 pub struct CompactIter<'i, 'a, I>
60 I: Iterator<Item = &'i Instruct<'a>>,
63 next: Option<&'i Instruct<'a>>,
66 impl<'i, 'a, I> CompactIter<'i, 'a, I>
68 I: Iterator<Item = &'i Instruct<'a>>,
70 pub fn new(i: I) -> Self {
78 impl<'i, 'a, I> Iterator for CompactIter<'i, 'a, I>
80 I: Iterator<Item = &'i Instruct<'a>>,
82 type Item = &'i Instruct<'a>;
83 fn next(&mut self) -> Option<Self::Item> {
84 if self.next.is_some() {
85 std::mem::replace(&mut self.next, None)
87 let mut cur = self.iter.next();
89 Some(i) if InstrSeq::is_srcloc(i) => {
90 self.next = self.iter.next();
91 while self.next.map_or(false, InstrSeq::is_srcloc) {
93 self.next = self.iter.next();
104 pub struct InstrIter<'i, 'a> {
105 instr_seq: &'i InstrSeq<'a>,
107 concat_stack: std::vec::Vec<
109 (&'i BumpSliceMut<'a, Instruct<'a>>, usize),
110 (&'i BumpSliceMut<'a, InstrSeq<'a>>, usize),
115 impl<'i, 'a> InstrIter<'i, 'a> {
116 pub fn new(instr_seq: &'i InstrSeq<'a>) -> Self {
120 concat_stack: std::vec::Vec::new(),
125 impl<'i, 'a> Iterator for InstrIter<'i, 'a> {
126 type Item = &'i Instruct<'a>;
127 fn next(&mut self) -> Option<Self::Item> {
128 //self: & mut InstrIter<'i, 'a>
129 //self.instr_seq: &'i InstrSeq<'a>
130 match self.instr_seq {
131 InstrSeq::List(s) if s.is_empty() => None,
132 InstrSeq::List(s) if s.len() == 1 && self.index > 0 => None,
133 InstrSeq::List(s) if s.len() == 1 => {
137 InstrSeq::List(s) if s.len() > 1 && self.index >= s.len() => None,
138 InstrSeq::List(s) => {
139 let r = s.get(self.index);
143 InstrSeq::Concat(s) => {
144 if self.concat_stack.is_empty() {
147 self.concat_stack.push(itertools::Either::Right((s, 0)));
153 while !self.concat_stack.is_empty() {
154 let top: &mut itertools::Either<_, _> = self.concat_stack.last_mut().unwrap();
156 itertools::Either::Left((list, size)) if *size >= list.len() => {
157 self.concat_stack.pop();
159 itertools::Either::Left((list, size)) => {
160 let r: Option<&'i Instruct<'a>> = list.get(*size);
164 itertools::Either::Right((concat, size)) if *size >= concat.len() => {
165 self.concat_stack.pop();
167 itertools::Either::Right((concat, size)) => {
168 let i: &'i InstrSeq<'a> = &(concat[*size]);
171 InstrSeq::List(s) if s.is_empty() => {}
172 InstrSeq::List(s) if s.len() == 1 => {
175 InstrSeq::List(s) => {
176 self.concat_stack.push(itertools::Either::Left((s, 0)));
178 InstrSeq::Concat(s) => {
179 self.concat_stack.push(itertools::Either::Right((s, 0)));
191 #[allow(clippy::needless_lifetimes)]
195 pub fn empty<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
196 InstrSeq::new_empty(alloc)
199 pub fn instr<'a>(alloc: &'a bumpalo::Bump, i: Instruct<'a>) -> InstrSeq<'a> {
200 InstrSeq::new_singleton(alloc, i)
203 pub fn instrs<'a>(alloc: &'a bumpalo::Bump, is: &'a mut [Instruct<'a>]) -> InstrSeq<'a> {
204 InstrSeq::new_list(alloc, is)
207 pub fn lit_const<'a>(alloc: &'a bumpalo::Bump, l: InstructLitConst<'a>) -> InstrSeq<'a> {
208 instr(alloc, Instruct::ILitConst(l))
212 alloc: &'a bumpalo::Bump,
218 Instruct::IIterator(InstructIterator::IterInit(args, label)),
223 alloc: &'a bumpalo::Bump,
229 Instruct::IIterator(InstructIterator::IterNext(args, label)),
233 pub fn iternextk<'a>(
234 alloc: &'a bumpalo::Bump,
240 let args = IterArgs {
247 Instruct::IIterator(InstructIterator::IterNext(args, label)),
251 pub fn iterfree<'a>(alloc: &'a bumpalo::Bump, id: IterId) -> InstrSeq<'a> {
252 instr(alloc, Instruct::IIterator(InstructIterator::IterFree(id)))
255 pub fn whresult<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
256 instr(alloc, Instruct::IAsync(AsyncFunctions::WHResult))
259 pub fn jmp<'a>(alloc: &'a bumpalo::Bump, label: Label) -> InstrSeq<'a> {
260 instr(alloc, Instruct::IContFlow(InstructControlFlow::Jmp(label)))
263 pub fn jmpz<'a>(alloc: &'a bumpalo::Bump, label: Label) -> InstrSeq<'a> {
264 instr(alloc, Instruct::IContFlow(InstructControlFlow::JmpZ(label)))
267 pub fn jmpnz<'a>(alloc: &'a bumpalo::Bump, label: Label) -> InstrSeq<'a> {
270 Instruct::IContFlow(InstructControlFlow::JmpNZ(label)),
274 pub fn jmpns<'a>(alloc: &'a bumpalo::Bump, label: Label) -> InstrSeq<'a> {
277 Instruct::IContFlow(InstructControlFlow::JmpNS(label)),
281 pub fn continue_<'a>(alloc: &'a bumpalo::Bump, level: isize) -> InstrSeq<'a> {
284 Instruct::ISpecialFlow(InstructSpecialFlow::Continue(level)),
288 pub fn break_<'a>(alloc: &'a bumpalo::Bump, level: isize) -> InstrSeq<'a> {
291 Instruct::ISpecialFlow(InstructSpecialFlow::Break(level)),
295 pub fn goto<'a>(alloc: &'a bumpalo::Bump, label: std::string::String) -> InstrSeq<'_> {
298 Instruct::ISpecialFlow(InstructSpecialFlow::Goto(Str::new_str(alloc, &label))),
302 pub fn iter_break<'a>(
303 alloc: &'a bumpalo::Bump,
305 itrs: std::vec::Vec<IterId>,
307 let mut vec = bumpalo::collections::Vec::from_iter_in(
309 .map(|id| Instruct::IIterator(InstructIterator::IterFree(id))),
312 vec.push(Instruct::IContFlow(InstructControlFlow::Jmp(label)));
313 instrs(alloc, vec.into_bump_slice_mut())
316 pub fn false_<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
317 instr(alloc, Instruct::ILitConst(InstructLitConst::False))
320 pub fn true_<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
321 instr(alloc, Instruct::ILitConst(InstructLitConst::True))
325 alloc: &'a bumpalo::Bump,
326 const_id: ConstId<'a>,
331 Instruct::ILitConst(InstructLitConst::ClsCnsD(const_id, cid)),
335 pub fn clscns<'a>(alloc: &'a bumpalo::Bump, const_id: ConstId<'a>) -> InstrSeq<'a> {
338 Instruct::ILitConst(InstructLitConst::ClsCns(const_id)),
342 pub fn clscnsl<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>) -> InstrSeq<'a> {
343 instr(alloc, Instruct::ILitConst(InstructLitConst::ClsCnsL(local)))
346 pub fn eq<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
347 instr(alloc, Instruct::IOp(InstructOperator::Eq))
350 pub fn neq<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
351 instr(alloc, Instruct::IOp(InstructOperator::Neq))
354 pub fn gt<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
355 instr(alloc, Instruct::IOp(InstructOperator::Gt))
358 pub fn gte<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
359 instr(alloc, Instruct::IOp(InstructOperator::Gte))
362 pub fn lt<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
363 instr(alloc, Instruct::IOp(InstructOperator::Lt))
366 pub fn lte<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
367 instr(alloc, Instruct::IOp(InstructOperator::Lte))
370 pub fn concat<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
371 instr(alloc, Instruct::IOp(InstructOperator::Concat))
374 pub fn concatn<'a>(alloc: &'a bumpalo::Bump, n: isize) -> InstrSeq<'a> {
375 instr(alloc, Instruct::IOp(InstructOperator::ConcatN(n)))
378 pub fn print<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
379 instr(alloc, Instruct::IOp(InstructOperator::Print))
382 pub fn cast_dict<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
383 instr(alloc, Instruct::IOp(InstructOperator::CastDict))
386 pub fn cast_string<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
387 instr(alloc, Instruct::IOp(InstructOperator::CastString))
390 pub fn cast_int<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
391 instr(alloc, Instruct::IOp(InstructOperator::CastInt))
394 pub fn cast_bool<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
395 instr(alloc, Instruct::IOp(InstructOperator::CastBool))
398 pub fn cast_double<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
399 instr(alloc, Instruct::IOp(InstructOperator::CastDouble))
402 pub fn retc<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
403 instr(alloc, Instruct::IContFlow(InstructControlFlow::RetC))
406 pub fn retc_suspended<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
409 Instruct::IContFlow(InstructControlFlow::RetCSuspended),
413 pub fn retm<'a>(alloc: &'a bumpalo::Bump, p: NumParams) -> InstrSeq<'a> {
414 instr(alloc, Instruct::IContFlow(InstructControlFlow::RetM(p)))
417 pub fn null<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
418 instr(alloc, Instruct::ILitConst(InstructLitConst::Null))
421 pub fn nulluninit<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
422 instr(alloc, Instruct::ILitConst(InstructLitConst::NullUninit))
425 pub fn chain_faults<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
426 instr(alloc, Instruct::IMisc(InstructMisc::ChainFaults))
429 pub fn dup<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
430 instr(alloc, Instruct::IBasic(InstructBasic::Dup))
433 pub fn nop<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
434 instr(alloc, Instruct::IBasic(InstructBasic::Nop))
437 pub fn instanceofd<'a>(alloc: &'a bumpalo::Bump, s: ClassId<'a>) -> InstrSeq<'a> {
438 instr(alloc, Instruct::IOp(InstructOperator::InstanceOfD(s)))
441 pub fn instanceof<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
442 instr(alloc, Instruct::IOp(InstructOperator::InstanceOf))
445 pub fn islateboundcls<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
446 instr(alloc, Instruct::IOp(InstructOperator::IsLateBoundCls))
449 pub fn istypestructc<'a>(alloc: &'a bumpalo::Bump, mode: TypestructResolveOp) -> InstrSeq<'a> {
450 instr(alloc, Instruct::IOp(InstructOperator::IsTypeStructC(mode)))
453 pub fn throwastypestructexception<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
456 Instruct::IOp(InstructOperator::ThrowAsTypeStructException),
460 pub fn throw_non_exhaustive_switch<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
463 Instruct::IMisc(InstructMisc::ThrowNonExhaustiveSwitch),
467 pub fn raise_class_string_conversion_warning<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
470 Instruct::IMisc(InstructMisc::RaiseClassStringConversionWarning),
474 pub fn combine_and_resolve_type_struct<'a>(alloc: &'a bumpalo::Bump, i: isize) -> InstrSeq<'a> {
477 Instruct::IOp(InstructOperator::CombineAndResolveTypeStruct(i)),
481 pub fn record_reified_generic<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
482 instr(alloc, Instruct::IMisc(InstructMisc::RecordReifiedGeneric))
485 pub fn check_reified_generic_mismatch<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
488 Instruct::IMisc(InstructMisc::CheckReifiedGenericMismatch),
492 pub fn int<'a>(alloc: &'a bumpalo::Bump, i: isize) -> InstrSeq<'a> {
495 Instruct::ILitConst(InstructLitConst::Int(i.try_into().unwrap())),
499 pub fn int64<'a>(alloc: &'a bumpalo::Bump, i: i64) -> InstrSeq<'a> {
500 instr(alloc, Instruct::ILitConst(InstructLitConst::Int(i)))
503 pub fn int_of_string<'a>(alloc: &'a bumpalo::Bump, litstr: &str) -> InstrSeq<'a> {
506 Instruct::ILitConst(InstructLitConst::Int(litstr.parse::<i64>().unwrap())),
510 pub fn double<'a>(alloc: &'a bumpalo::Bump, litstr: &str) -> InstrSeq<'a> {
513 Instruct::ILitConst(InstructLitConst::Double(Str::from(
514 bumpalo::collections::String::from_str_in(litstr, alloc).into_bump_str(),
519 pub fn string<'a>(alloc: &'a bumpalo::Bump, litstr: impl Into<String>) -> InstrSeq<'a> {
522 Instruct::ILitConst(InstructLitConst::String(Str::from(
523 bumpalo::collections::String::from_str_in(litstr.into().as_str(), alloc)
529 pub fn this<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
530 instr(alloc, Instruct::IMisc(InstructMisc::This))
533 pub fn istypec<'a>(alloc: &'a bumpalo::Bump, op: IstypeOp) -> InstrSeq<'a> {
534 instr(alloc, Instruct::IIsset(InstructIsset::IsTypeC(op)))
537 pub fn istypel<'a>(alloc: &'a bumpalo::Bump, id: Local<'a>, op: IstypeOp) -> InstrSeq<'a> {
538 instr(alloc, Instruct::IIsset(InstructIsset::IsTypeL(id, op)))
541 pub fn add<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
542 instr(alloc, Instruct::IOp(InstructOperator::Add))
545 pub fn addo<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
546 instr(alloc, Instruct::IOp(InstructOperator::AddO))
549 pub fn sub<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
550 instr(alloc, Instruct::IOp(InstructOperator::Sub))
553 pub fn subo<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
554 instr(alloc, Instruct::IOp(InstructOperator::SubO))
557 pub fn mul<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
558 instr(alloc, Instruct::IOp(InstructOperator::Mul))
561 pub fn mulo<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
562 instr(alloc, Instruct::IOp(InstructOperator::MulO))
565 pub fn shl<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
566 instr(alloc, Instruct::IOp(InstructOperator::Shl))
569 pub fn shr<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
570 instr(alloc, Instruct::IOp(InstructOperator::Shr))
573 pub fn cmp<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
574 instr(alloc, Instruct::IOp(InstructOperator::Cmp))
577 pub fn mod_<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
578 instr(alloc, Instruct::IOp(InstructOperator::Mod))
581 pub fn div<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
582 instr(alloc, Instruct::IOp(InstructOperator::Div))
585 pub fn same<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
586 instr(alloc, Instruct::IOp(InstructOperator::Same))
589 pub fn pow<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
590 instr(alloc, Instruct::IOp(InstructOperator::Pow))
593 pub fn nsame<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
594 instr(alloc, Instruct::IOp(InstructOperator::NSame))
597 pub fn not<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
598 instr(alloc, Instruct::IOp(InstructOperator::Not))
601 pub fn bitnot<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
602 instr(alloc, Instruct::IOp(InstructOperator::BitNot))
605 pub fn bitand<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
606 instr(alloc, Instruct::IOp(InstructOperator::BitAnd))
609 pub fn bitor<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
610 instr(alloc, Instruct::IOp(InstructOperator::BitOr))
613 pub fn bitxor<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
614 instr(alloc, Instruct::IOp(InstructOperator::BitXor))
617 pub fn sets<'a>(alloc: &'a bumpalo::Bump, readonly_op: ReadonlyOp) -> InstrSeq<'a> {
620 Instruct::IMutator(InstructMutator::SetS(readonly_op)),
624 pub fn setl<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>) -> InstrSeq<'a> {
625 instr(alloc, Instruct::IMutator(InstructMutator::SetL(local)))
628 pub fn setg<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
629 instr(alloc, Instruct::IMutator(InstructMutator::SetG))
632 pub fn unsetl<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>) -> InstrSeq<'a> {
633 instr(alloc, Instruct::IMutator(InstructMutator::UnsetL(local)))
636 pub fn unsetg<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
637 instr(alloc, Instruct::IMutator(InstructMutator::UnsetG))
640 pub fn incdecl<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>, op: IncdecOp) -> InstrSeq<'a> {
643 Instruct::IMutator(InstructMutator::IncDecL(local, op)),
647 pub fn incdecg<'a>(alloc: &'a bumpalo::Bump, op: IncdecOp) -> InstrSeq<'a> {
648 instr(alloc, Instruct::IMutator(InstructMutator::IncDecG(op)))
651 pub fn incdecs<'a>(alloc: &'a bumpalo::Bump, op: IncdecOp) -> InstrSeq<'a> {
652 instr(alloc, Instruct::IMutator(InstructMutator::IncDecS(op)))
655 pub fn setopg<'a>(alloc: &'a bumpalo::Bump, op: EqOp) -> InstrSeq<'a> {
656 instr(alloc, Instruct::IMutator(InstructMutator::SetOpG(op)))
659 pub fn setopl<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>, op: EqOp) -> InstrSeq<'a> {
662 Instruct::IMutator(InstructMutator::SetOpL(local, op)),
666 pub fn setops<'a>(alloc: &'a bumpalo::Bump, op: EqOp) -> InstrSeq<'a> {
667 instr(alloc, Instruct::IMutator(InstructMutator::SetOpS(op)))
670 pub fn issetl<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>) -> InstrSeq<'a> {
671 instr(alloc, Instruct::IIsset(InstructIsset::IssetL(local)))
674 pub fn issetg<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
675 instr(alloc, Instruct::IIsset(InstructIsset::IssetG))
678 pub fn issets<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
679 instr(alloc, Instruct::IIsset(InstructIsset::IssetS))
682 pub fn isunsetl<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>) -> InstrSeq<'a> {
683 instr(alloc, Instruct::IIsset(InstructIsset::IsUnsetL(local)))
686 pub fn cgets<'a>(alloc: &'a bumpalo::Bump, readonly_op: ReadonlyOp) -> InstrSeq<'a> {
687 instr(alloc, Instruct::IGet(InstructGet::CGetS(readonly_op)))
690 pub fn cgetg<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
691 instr(alloc, Instruct::IGet(InstructGet::CGetG))
694 pub fn cgetl<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>) -> InstrSeq<'a> {
695 instr(alloc, Instruct::IGet(InstructGet::CGetL(local)))
698 pub fn cugetl<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>) -> InstrSeq<'a> {
699 instr(alloc, Instruct::IGet(InstructGet::CUGetL(local)))
702 pub fn cgetl2<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>) -> InstrSeq<'a> {
703 instr(alloc, Instruct::IGet(InstructGet::CGetL2(local)))
706 pub fn cgetquietl<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>) -> InstrSeq<'a> {
707 instr(alloc, Instruct::IGet(InstructGet::CGetQuietL(local)))
710 pub fn classgetc<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
711 instr(alloc, Instruct::IGet(InstructGet::ClassGetC))
714 pub fn classgetts<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
715 instr(alloc, Instruct::IGet(InstructGet::ClassGetTS))
718 pub fn classname<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
719 instr(alloc, Instruct::IMisc(InstructMisc::ClassName))
722 pub fn lazyclassfromclass<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
723 instr(alloc, Instruct::IMisc(InstructMisc::LazyClassFromClass))
726 pub fn self_<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
727 instr(alloc, Instruct::IMisc(InstructMisc::Self_))
730 pub fn lateboundcls<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
731 instr(alloc, Instruct::IMisc(InstructMisc::LateBoundCls))
734 pub fn parent<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
735 instr(alloc, Instruct::IMisc(InstructMisc::Parent))
738 pub fn popu<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
739 instr(alloc, Instruct::IBasic(InstructBasic::PopU))
742 pub fn popc<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
743 instr(alloc, Instruct::IBasic(InstructBasic::PopC))
746 pub fn popl<'a>(alloc: &'a bumpalo::Bump, l: Local<'a>) -> InstrSeq<'a> {
747 instr(alloc, Instruct::IMutator(InstructMutator::PopL(l)))
750 pub fn initprop<'a>(alloc: &'a bumpalo::Bump, pid: PropId<'a>, op: InitpropOp) -> InstrSeq<'a> {
753 Instruct::IMutator(InstructMutator::InitProp(pid, op)),
757 pub fn checkprop<'a>(alloc: &'a bumpalo::Bump, pid: PropId<'a>) -> InstrSeq<'a> {
758 instr(alloc, Instruct::IMutator(InstructMutator::CheckProp(pid)))
761 pub fn pushl<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>) -> InstrSeq<'a> {
762 instr(alloc, Instruct::IGet(InstructGet::PushL(local)))
765 pub fn throw<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
766 instr(alloc, Instruct::IContFlow(InstructControlFlow::Throw))
769 pub fn new_vec_array<'a>(alloc: &'a bumpalo::Bump, i: isize) -> InstrSeq<'a> {
770 instr(alloc, Instruct::ILitConst(InstructLitConst::NewVec(i)))
773 pub fn new_pair<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
774 instr(alloc, Instruct::ILitConst(InstructLitConst::NewPair))
777 pub fn add_elemc<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
778 instr(alloc, Instruct::ILitConst(InstructLitConst::AddElemC))
781 pub fn add_new_elemc<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
782 instr(alloc, Instruct::ILitConst(InstructLitConst::AddNewElemC))
786 alloc: &'a bumpalo::Bump,
787 labels: bumpalo::collections::Vec<'a, Label>,
791 Instruct::IContFlow(InstructControlFlow::Switch(
792 Switchkind::Unbounded,
794 BumpSliceMut::new(alloc, labels.into_bump_slice_mut()),
799 pub fn newobj<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
800 instr(alloc, Instruct::ICall(InstructCall::NewObj))
804 alloc: &'a bumpalo::Bump,
805 cases: bumpalo::collections::Vec<'a, (&'a str, Label)>,
807 let cases_ = BumpSliceMut::new(
809 alloc.alloc_slice_fill_iter(cases.into_iter().map(|p| Pair(Str::from(p.0), p.1))),
813 Instruct::IContFlow(InstructControlFlow::SSwitch(cases_)),
817 pub fn newobjr<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
818 instr(alloc, Instruct::ICall(InstructCall::NewObjR))
821 pub fn newobjd<'a>(alloc: &'a bumpalo::Bump, id: ClassId<'a>) -> InstrSeq<'a> {
822 instr(alloc, Instruct::ICall(InstructCall::NewObjD(id)))
825 pub fn newobjrd<'a>(alloc: &'a bumpalo::Bump, id: ClassId<'a>) -> InstrSeq<'a> {
826 instr(alloc, Instruct::ICall(InstructCall::NewObjRD(id)))
829 pub fn newobjs<'a>(alloc: &'a bumpalo::Bump, scref: SpecialClsRef) -> InstrSeq<'a> {
830 instr(alloc, Instruct::ICall(InstructCall::NewObjS(scref)))
833 pub fn lockobj<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
834 instr(alloc, Instruct::IMisc(InstructMisc::LockObj))
837 pub fn clone<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
838 instr(alloc, Instruct::IOp(InstructOperator::Clone))
841 pub fn new_record<'a>(
842 alloc: &'a bumpalo::Bump,
847 Slice::new(alloc.alloc_slice_fill_iter(keys.into_iter().map(|s| Str::from(*s))));
850 Instruct::ILitConst(InstructLitConst::NewRecord(id, keys_)),
854 pub fn newstructdict<'a>(alloc: &'a bumpalo::Bump, keys: &'a [&'a str]) -> InstrSeq<'a> {
856 Slice::new(alloc.alloc_slice_fill_iter(keys.into_iter().map(|s| Str::from(*s))));
859 Instruct::ILitConst(InstructLitConst::NewStructDict(keys_)),
863 pub fn newcol<'a>(alloc: &'a bumpalo::Bump, collection_type: CollectionType) -> InstrSeq<'a> {
866 Instruct::ILitConst(InstructLitConst::NewCol(collection_type)),
870 pub fn colfromarray<'a>(
871 alloc: &'a bumpalo::Bump,
872 collection_type: CollectionType,
876 Instruct::ILitConst(InstructLitConst::ColFromArray(collection_type)),
880 pub fn entrynop<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
881 instr(alloc, Instruct::IBasic(InstructBasic::EntryNop))
884 pub fn typedvalue<'a>(alloc: &'a bumpalo::Bump, xs: TypedValue<'a>) -> InstrSeq<'a> {
885 instr(alloc, Instruct::ILitConst(InstructLitConst::TypedValue(xs)))
889 alloc: &'a bumpalo::Bump,
892 readonly_op: ReadonlyOp,
896 Instruct::IBase(InstructBase::BaseL(local, mode, readonly_op)),
901 alloc: &'a bumpalo::Bump,
902 stack_index: StackIndex,
907 Instruct::IBase(InstructBase::BaseC(stack_index, mode)),
912 alloc: &'a bumpalo::Bump,
913 stack_index: StackIndex,
918 Instruct::IBase(InstructBase::BaseGC(stack_index, mode)),
923 alloc: &'a bumpalo::Bump,
927 instr(alloc, Instruct::IBase(InstructBase::BaseGL(local, mode)))
931 alloc: &'a bumpalo::Bump,
935 readonly_op: ReadonlyOp,
939 Instruct::IBase(InstructBase::BaseSC(y, z, mode, readonly_op)),
943 pub fn baseh<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
944 instr(alloc, Instruct::IBase(InstructBase::BaseH))
947 pub fn cgetcunop<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
948 instr(alloc, Instruct::IMisc(InstructMisc::CGetCUNop))
951 pub fn ugetcunop<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
952 instr(alloc, Instruct::IMisc(InstructMisc::UGetCUNop))
956 alloc: &'a bumpalo::Bump,
958 range: Option<(Local<'a>, isize)>,
962 Instruct::IMisc(InstructMisc::MemoGet(
965 Some((fst, snd)) => Just(Pair(fst, snd)),
972 // Factored out to reduce verbosity.
973 fn range_opt_to_maybe<'a>(range: Option<(Local<'a>, isize)>) -> Maybe<Pair<Local<'a>, isize>> {
975 Some((fst, snd)) => Just(Pair(fst, snd)),
980 pub fn memoget_eager<'a>(
981 alloc: &'a bumpalo::Bump,
984 range: Option<(Local<'a>, isize)>,
988 Instruct::IMisc(InstructMisc::MemoGetEager(
991 range_opt_to_maybe(range),
997 alloc: &'a bumpalo::Bump,
998 range: Option<(Local<'a>, isize)>,
1002 Instruct::IMisc(InstructMisc::MemoSet(range_opt_to_maybe(range))),
1006 pub fn memoset_eager<'a>(
1007 alloc: &'a bumpalo::Bump,
1008 range: Option<(Local<'a>, isize)>,
1012 Instruct::IMisc(InstructMisc::MemoSetEager(range_opt_to_maybe(range))),
1016 pub fn getmemokeyl<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>) -> InstrSeq<'a> {
1017 instr(alloc, Instruct::IMisc(InstructMisc::GetMemoKeyL(local)))
1020 pub fn barethis<'a>(alloc: &'a bumpalo::Bump, notice: BareThisOp) -> InstrSeq<'a> {
1021 instr(alloc, Instruct::IMisc(InstructMisc::BareThis(notice)))
1024 pub fn checkthis<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1025 instr(alloc, Instruct::IMisc(InstructMisc::CheckThis))
1028 pub fn verify_ret_type_c<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1029 instr(alloc, Instruct::IMisc(InstructMisc::VerifyRetTypeC))
1032 pub fn verify_ret_type_ts<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1033 instr(alloc, Instruct::IMisc(InstructMisc::VerifyRetTypeTS))
1036 pub fn verify_out_type<'a>(alloc: &'a bumpalo::Bump, i: ParamId<'a>) -> InstrSeq<'a> {
1037 instr(alloc, Instruct::IMisc(InstructMisc::VerifyOutType(i)))
1040 pub fn verify_param_type<'a>(alloc: &'a bumpalo::Bump, i: ParamId<'a>) -> InstrSeq<'a> {
1041 instr(alloc, Instruct::IMisc(InstructMisc::VerifyParamType(i)))
1044 pub fn verify_param_type_ts<'a>(alloc: &'a bumpalo::Bump, i: ParamId<'a>) -> InstrSeq<'a> {
1045 instr(alloc, Instruct::IMisc(InstructMisc::VerifyParamTypeTS(i)))
1048 pub fn dim<'a>(alloc: &'a bumpalo::Bump, op: MemberOpMode, key: MemberKey<'a>) -> InstrSeq<'a> {
1049 instr(alloc, Instruct::IBase(InstructBase::Dim(op, key)))
1052 pub fn dim_warn_pt<'a>(
1053 alloc: &'a bumpalo::Bump,
1055 readonly_op: ReadonlyOp,
1057 dim(alloc, MemberOpMode::Warn, MemberKey::PT(key, readonly_op))
1060 pub fn dim_define_pt<'a>(
1061 alloc: &'a bumpalo::Bump,
1063 readonly_op: ReadonlyOp,
1065 dim(alloc, MemberOpMode::Define, MemberKey::PT(key, readonly_op))
1068 pub fn fcallclsmethod<'a>(
1069 alloc: &'a bumpalo::Bump,
1070 is_log_as_dynamic_call: IsLogAsDynamicCallOp,
1071 fcall_args: FcallArgs<'a>,
1075 Instruct::ICall(InstructCall::FCallClsMethod(
1077 is_log_as_dynamic_call,
1082 pub fn fcallclsmethodd<'a>(
1083 alloc: &'a bumpalo::Bump,
1084 fcall_args: FcallArgs<'a>,
1085 method_name: MethodId<'a>,
1086 class_name: ClassId<'a>,
1090 Instruct::ICall(InstructCall::FCallClsMethodD(
1098 pub fn fcallclsmethods<'a>(
1099 alloc: &'a bumpalo::Bump,
1100 fcall_args: FcallArgs<'a>,
1101 scref: SpecialClsRef,
1105 Instruct::ICall(InstructCall::FCallClsMethodS(fcall_args, scref)),
1109 pub fn fcallclsmethodsd<'a>(
1110 alloc: &'a bumpalo::Bump,
1111 fcall_args: FcallArgs<'a>,
1112 scref: SpecialClsRef,
1113 method_name: MethodId<'a>,
1117 Instruct::ICall(InstructCall::FCallClsMethodSD(
1125 pub fn fcallctor<'a>(alloc: &'a bumpalo::Bump, fcall_args: FcallArgs<'a>) -> InstrSeq<'a> {
1126 instr(alloc, Instruct::ICall(InstructCall::FCallCtor(fcall_args)))
1129 pub fn fcallfunc<'a>(alloc: &'a bumpalo::Bump, fcall_args: FcallArgs<'a>) -> InstrSeq<'a> {
1130 instr(alloc, Instruct::ICall(InstructCall::FCallFunc(fcall_args)))
1133 pub fn fcallfuncd<'a>(
1134 alloc: &'a bumpalo::Bump,
1135 fcall_args: FcallArgs<'a>,
1140 Instruct::ICall(InstructCall::FCallFuncD(fcall_args, id)),
1144 pub fn fcallobjmethod<'a>(
1145 alloc: &'a bumpalo::Bump,
1146 fcall_args: FcallArgs<'a>,
1147 flavor: ObjNullFlavor,
1151 Instruct::ICall(InstructCall::FCallObjMethod(fcall_args, flavor)),
1155 pub fn fcallobjmethodd<'a>(
1156 alloc: &'a bumpalo::Bump,
1157 fcall_args: FcallArgs<'a>,
1158 method: MethodId<'a>,
1159 flavor: ObjNullFlavor,
1163 Instruct::ICall(InstructCall::FCallObjMethodD(fcall_args, flavor, method)),
1167 pub fn fcallobjmethodd_nullthrows<'a>(
1168 alloc: &'a bumpalo::Bump,
1169 fcall_args: FcallArgs<'a>,
1170 method: MethodId<'a>,
1172 fcallobjmethodd(alloc, fcall_args, method, ObjNullFlavor::NullThrows)
1176 alloc: &'a bumpalo::Bump,
1177 num_params: NumParams,
1183 Instruct::IFinal(InstructFinal::QueryM(num_params, op, key)),
1187 pub fn querym_cget_pt<'a>(
1188 alloc: &'a bumpalo::Bump,
1189 num_params: NumParams,
1191 readonly_op: ReadonlyOp,
1197 MemberKey::PT(key, readonly_op),
1202 alloc: &'a bumpalo::Bump,
1203 num_params: NumParams,
1208 Instruct::IFinal(InstructFinal::SetM(num_params, key)),
1213 alloc: &'a bumpalo::Bump,
1214 num_params: NumParams,
1219 Instruct::IFinal(InstructFinal::UnsetM(num_params, key)),
1224 alloc: &'a bumpalo::Bump,
1225 num_params: NumParams,
1231 Instruct::IFinal(InstructFinal::SetOpM(num_params, op, key)),
1236 alloc: &'a bumpalo::Bump,
1237 num_params: NumParams,
1243 Instruct::IFinal(InstructFinal::IncDecM(num_params, op, key)),
1248 alloc: &'a bumpalo::Bump,
1249 num_params: NumParams,
1251 readonly_op: ReadonlyOp,
1253 setm(alloc, num_params, MemberKey::PT(key, readonly_op))
1256 pub fn resolve_func<'a>(alloc: &'a bumpalo::Bump, func_id: FunctionId<'a>) -> InstrSeq<'a> {
1257 instr(alloc, Instruct::IOp(InstructOperator::ResolveFunc(func_id)))
1260 pub fn resolve_rfunc<'a>(alloc: &'a bumpalo::Bump, func_id: FunctionId<'a>) -> InstrSeq<'a> {
1263 Instruct::IOp(InstructOperator::ResolveRFunc(func_id)),
1267 pub fn resolveclsmethod<'a>(alloc: &'a bumpalo::Bump, method_id: MethodId<'a>) -> InstrSeq<'a> {
1270 Instruct::IOp(InstructOperator::ResolveClsMethod(method_id)),
1274 pub fn resolveclsmethodd<'a>(
1275 alloc: &'a bumpalo::Bump,
1276 class_id: ClassId<'a>,
1277 method_id: MethodId<'a>,
1281 Instruct::IOp(InstructOperator::ResolveClsMethodD(class_id, method_id)),
1285 pub fn resolveclsmethods<'a>(
1286 alloc: &'a bumpalo::Bump,
1287 scref: SpecialClsRef,
1288 method_id: MethodId<'a>,
1292 Instruct::IOp(InstructOperator::ResolveClsMethodS(scref, method_id)),
1296 pub fn resolverclsmethod<'a>(
1297 alloc: &'a bumpalo::Bump,
1298 method_id: MethodId<'a>,
1302 Instruct::IOp(InstructOperator::ResolveRClsMethod(method_id)),
1306 pub fn resolverclsmethodd<'a>(
1307 alloc: &'a bumpalo::Bump,
1308 class_id: ClassId<'a>,
1309 method_id: MethodId<'a>,
1313 Instruct::IOp(InstructOperator::ResolveRClsMethodD(class_id, method_id)),
1317 pub fn resolverclsmethods<'a>(
1318 alloc: &'a bumpalo::Bump,
1319 scref: SpecialClsRef,
1320 method_id: MethodId<'a>,
1324 Instruct::IOp(InstructOperator::ResolveRClsMethodS(scref, method_id)),
1328 pub fn resolve_meth_caller<'a>(
1329 alloc: &'a bumpalo::Bump,
1330 fun_id: FunctionId<'a>,
1334 Instruct::IOp(InstructOperator::ResolveMethCaller(fun_id)),
1338 pub fn resolveclass<'a>(alloc: &'a bumpalo::Bump, class_id: ClassId<'a>) -> InstrSeq<'a> {
1341 Instruct::IOp(InstructOperator::ResolveClass(class_id)),
1345 pub fn lazyclass<'a>(alloc: &'a bumpalo::Bump, class_id: ClassId<'a>) -> InstrSeq<'a> {
1348 Instruct::ILitConst(InstructLitConst::LazyClass(class_id)),
1352 pub fn oodeclexists<'a>(alloc: &'a bumpalo::Bump, class_kind: ClassishKind) -> InstrSeq<'a> {
1355 Instruct::IMisc(InstructMisc::OODeclExists(class_kind)),
1359 pub fn fatal<'a>(alloc: &'a bumpalo::Bump, op: FatalOp) -> InstrSeq<'a> {
1360 instr(alloc, Instruct::IOp(InstructOperator::Fatal(op)))
1363 pub fn await_<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1364 instr(alloc, Instruct::IAsync(AsyncFunctions::Await))
1367 pub fn yield_<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1368 instr(alloc, Instruct::IGenerator(GenCreationExecution::Yield))
1371 pub fn yieldk<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1372 instr(alloc, Instruct::IGenerator(GenCreationExecution::YieldK))
1375 pub fn createcont<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1378 Instruct::IGenerator(GenCreationExecution::CreateCont),
1382 pub fn awaitall<'a>(
1383 alloc: &'a bumpalo::Bump,
1384 range: Option<(Local<'a>, isize)>,
1388 Instruct::IAsync(AsyncFunctions::AwaitAll(range_opt_to_maybe(range))),
1392 pub fn label<'a>(alloc: &'a bumpalo::Bump, label: Label) -> InstrSeq<'a> {
1393 instr(alloc, Instruct::ILabel(label))
1396 pub fn awaitall_list<'a>(
1397 alloc: &'a bumpalo::Bump,
1398 unnamed_locals: std::vec::Vec<Local<'a>>,
1401 match unnamed_locals.split_first() {
1402 None => panic!("Expected at least one await"),
1404 if let Unnamed(hd_id) = hd {
1405 let mut prev_id = hd_id;
1406 for unnamed_local in tl.iter() {
1407 match unnamed_local {
1409 assert_eq!(*prev_id + 1, *id);
1412 _ => panic!("Expected unnamed local"),
1417 Some((Unnamed(*hd_id), unnamed_locals.len().try_into().unwrap())),
1420 panic!("Expected unnamed local")
1426 pub fn exit<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1427 instr(alloc, Instruct::IOp(InstructOperator::Exit))
1430 pub fn idx<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1431 instr(alloc, Instruct::IMisc(InstructMisc::Idx))
1434 pub fn array_idx<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1435 instr(alloc, Instruct::IMisc(InstructMisc::ArrayIdx))
1438 pub fn createcl<'a>(
1439 alloc: &'a bumpalo::Bump,
1440 param_num: NumParams,
1445 Instruct::IMisc(InstructMisc::CreateCl(param_num, cls_num)),
1449 pub fn eval<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1452 Instruct::IIncludeEvalDefine(InstructIncludeEvalDefine::Eval),
1456 pub fn incl<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1459 Instruct::IIncludeEvalDefine(InstructIncludeEvalDefine::Incl),
1463 pub fn inclonce<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1466 Instruct::IIncludeEvalDefine(InstructIncludeEvalDefine::InclOnce),
1470 pub fn req<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1473 Instruct::IIncludeEvalDefine(InstructIncludeEvalDefine::Req),
1477 pub fn reqdoc<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1480 Instruct::IIncludeEvalDefine(InstructIncludeEvalDefine::ReqDoc),
1484 pub fn reqonce<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1487 Instruct::IIncludeEvalDefine(InstructIncludeEvalDefine::ReqOnce),
1491 pub fn silence_start<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>) -> InstrSeq<'a> {
1494 Instruct::IMisc(InstructMisc::Silence(local, OpSilence::Start)),
1498 pub fn silence_end<'a>(alloc: &'a bumpalo::Bump, local: Local<'a>) -> InstrSeq<'a> {
1501 Instruct::IMisc(InstructMisc::Silence(local, OpSilence::End)),
1505 pub fn contcheck_check<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1508 Instruct::IGenerator(GenCreationExecution::ContCheck(CheckStarted::CheckStarted)),
1512 pub fn contcheck_ignore<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1515 Instruct::IGenerator(GenCreationExecution::ContCheck(CheckStarted::IgnoreStarted)),
1519 pub fn contenter<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1520 instr(alloc, Instruct::IGenerator(GenCreationExecution::ContEnter))
1523 pub fn contraise<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1524 instr(alloc, Instruct::IGenerator(GenCreationExecution::ContRaise))
1527 pub fn contvalid<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1528 instr(alloc, Instruct::IGenerator(GenCreationExecution::ContValid))
1531 pub fn contcurrent<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1534 Instruct::IGenerator(GenCreationExecution::ContCurrent),
1538 pub fn contkey<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1539 instr(alloc, Instruct::IGenerator(GenCreationExecution::ContKey))
1542 pub fn contgetreturn<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1545 Instruct::IGenerator(GenCreationExecution::ContGetReturn),
1549 pub fn nativeimpl<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1550 instr(alloc, Instruct::IMisc(InstructMisc::NativeImpl))
1554 alloc: &'a bumpalo::Bump,
1562 Instruct::ISrcLoc(Srcloc {
1571 pub fn is_type_structc_resolve<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1574 Instruct::IOp(InstructOperator::IsTypeStructC(
1575 TypestructResolveOp::Resolve,
1580 pub fn is_type_structc_dontresolve<'a>(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1583 Instruct::IOp(InstructOperator::IsTypeStructC(
1584 TypestructResolveOp::DontResolve,
1590 impl<'a> InstrSeq<'a> {
1591 /// We can't implement `std::Clone`` because of the need for an
1592 /// allocator. Instead, use this associated function.
1593 pub fn clone(alloc: &'a bumpalo::Bump, s: &InstrSeq<'a>) -> InstrSeq<'a> {
1594 InstrSeq::from_iter_in(alloc, InstrIter::new(s).cloned())
1597 /// We can't implement `std::Default` because of the need
1598 /// for an allocator. Instead, use this associated function
1599 /// to produce an empty instruction sequence.
1600 pub fn new_empty(alloc: &'a bumpalo::Bump) -> InstrSeq<'a> {
1601 InstrSeq::List(BumpSliceMut::new(
1603 bumpalo::vec![in &alloc; ].into_bump_slice_mut(),
1607 /// An instruction sequence of a single instruction.
1608 pub fn new_singleton(alloc: &'a bumpalo::Bump, i: Instruct<'a>) -> InstrSeq<'a> {
1609 InstrSeq::List(BumpSliceMut::new(
1611 bumpalo::vec![in &alloc; i].into_bump_slice_mut(),
1615 /// An instruction sequence of a sequence of instructions.
1616 pub fn new_list(alloc: &'a bumpalo::Bump, is: &'a mut [Instruct<'a>]) -> InstrSeq<'a> {
1617 InstrSeq::List(BumpSliceMut::new(alloc, is))
1620 /// An instruction sequence of a concatenation of instruction sequences.
1621 pub fn new_concat(alloc: &'a bumpalo::Bump, iss: &'a mut [InstrSeq<'a>]) -> InstrSeq<'a> {
1622 InstrSeq::Concat(BumpSliceMut::new(alloc, iss))
1625 /// Move instructions out of a container.
1626 pub fn from_iter_in<T: IntoIterator<Item = Instruct<'a>>>(
1627 alloc: &'a bumpalo::Bump,
1632 bumpalo::collections::Vec::from_iter_in(it, alloc).into_bump_slice_mut(),
1636 /// Transitional version. We mean to write a `gather!` in the future.
1637 pub fn gather(alloc: &'a bumpalo::Bump, iss: std::vec::Vec<InstrSeq<'a>>) -> InstrSeq<'a> {
1638 fn prd<'a>(is: &InstrSeq<'a>) -> bool {
1640 InstrSeq::List(s) if s.is_empty() => false,
1645 let non_empty = bumpalo::collections::Vec::from_iter_in(iss.into_iter().filter(prd), alloc);
1646 if non_empty.is_empty() {
1647 InstrSeq::new_empty(alloc)
1649 InstrSeq::new_concat(alloc, non_empty.into_bump_slice_mut())
1653 pub fn iter<'i>(&'i self) -> InstrIter<'i, 'a> {
1654 InstrIter::new(self)
1657 pub fn compact_iter<'i>(&'i self) -> impl Iterator<Item = &Instruct<'a>> {
1658 CompactIter::new(self.iter())
1661 pub fn create_try_catch(
1662 alloc: &'a bumpalo::Bump,
1663 label_gen: &mut label::Gen,
1664 opt_done_label: Option<Label>,
1669 let done_label = match opt_done_label {
1671 None => label_gen.next_regular(),
1676 instr::instr(alloc, Instruct::ITry(InstructTry::TryCatchBegin)),
1678 instr::jmp(alloc, done_label),
1679 instr::instr(alloc, Instruct::ITry(InstructTry::TryCatchMiddle)),
1684 instr::instr(alloc, Instruct::IContFlow(InstructControlFlow::Throw))
1686 instr::instr(alloc, Instruct::ITry(InstructTry::TryCatchEnd)),
1687 instr::label(alloc, done_label),
1692 /// Test whether `i` is of case `Instruct::ISrcLoc`.
1693 fn is_srcloc(instruction: &Instruct<'a>) -> bool {
1695 Instruct::ISrcLoc(_) => true,
1700 pub fn first(&self) -> Option<&Instruct<'a>> {
1701 // self: &InstrSeq<'a>
1703 InstrSeq::List(s) if s.is_empty() => None,
1704 InstrSeq::List(s) if s.len() == 1 => {
1706 if InstrSeq::is_srcloc(i) {
1712 InstrSeq::List(s) => match s.iter().find(|&i| !InstrSeq::is_srcloc(i)) {
1716 InstrSeq::Concat(s) => s.iter().find_map(InstrSeq::first),
1720 /// Test for the empty instruction sequence.
1721 pub fn is_empty(&self) -> bool {
1722 // self:&InstrSeq<'a>
1724 InstrSeq::List(s) if s.is_empty() => true,
1725 InstrSeq::List(s) if s.len() == 1 => InstrSeq::is_srcloc(&s[0]),
1726 InstrSeq::List(s) => s.is_empty() || s.iter().all(InstrSeq::is_srcloc),
1727 InstrSeq::Concat(s) => s.iter().all(InstrSeq::is_empty),
1731 pub fn flat_map_seq<F>(&self, alloc: &'a bumpalo::Bump, f: &mut F) -> Self
1733 F: FnMut(&Instruct<'a>) -> Self,
1735 // self: &InstrSeq<'a>
1737 InstrSeq::List(s) if s.is_empty() => InstrSeq::new_empty(alloc),
1738 InstrSeq::List(s) if s.len() == 1 => f(&s[0]),
1739 InstrSeq::List(s) => InstrSeq::Concat(BumpSliceMut::new(
1741 bumpalo::collections::vec::Vec::from_iter_in(s.iter().map(|x| f(x)), alloc)
1742 .into_bump_slice_mut(),
1744 InstrSeq::Concat(s) => InstrSeq::Concat(BumpSliceMut::new(
1746 bumpalo::collections::vec::Vec::from_iter_in(
1747 s.iter().map(|x| x.flat_map_seq(alloc, f)),
1750 .into_bump_slice_mut(),
1755 pub fn fold_left<'i, F, A>(&'i self, f: &mut F, init: A) -> A
1757 F: FnMut(A, &'i Instruct<'a>) -> A,
1759 // self:& InstrSeq<'a>
1761 InstrSeq::List(s) if s.is_empty() => init,
1762 InstrSeq::List(s) if s.len() == 1 => f(init, &s[0]),
1763 InstrSeq::List(s) => s.iter().fold(init, f),
1764 InstrSeq::Concat(s) => s.iter().fold(init, |acc, x| x.fold_left(f, acc)),
1768 pub fn filter_map<F>(&self, alloc: &'a bumpalo::Bump, f: &mut F) -> Self
1770 F: FnMut(&Instruct<'a>) -> Option<Instruct<'a>>,
1772 //self: &InstrSeq<'a>
1774 InstrSeq::List(s) if s.is_empty() => InstrSeq::new_empty(alloc),
1775 InstrSeq::List(s) if s.len() == 1 => {
1776 let x: &Instruct<'a> = &s[0];
1778 Some(x) => instr::instr(alloc, x),
1779 None => InstrSeq::new_empty(alloc),
1782 InstrSeq::List(s) => InstrSeq::List(BumpSliceMut::new(
1784 bumpalo::collections::vec::Vec::from_iter_in(s.iter().filter_map(f), alloc)
1785 .into_bump_slice_mut(),
1787 InstrSeq::Concat(s) => InstrSeq::Concat(BumpSliceMut::new(
1789 bumpalo::collections::vec::Vec::from_iter_in(
1790 s.iter().map(|x| x.filter_map(alloc, f)),
1793 .into_bump_slice_mut(),
1798 pub fn filter_map_mut<F>(&mut self, alloc: &'a bumpalo::Bump, f: &mut F)
1800 F: FnMut(&mut Instruct<'a>) -> bool,
1802 //self: &mut InstrSeq<'a>
1804 InstrSeq::List(s) if s.is_empty() => {}
1805 InstrSeq::List(s) if s.len() == 1 => {
1806 let x: &mut Instruct<'a> = &mut s[0];
1808 *self = instr::empty(alloc)
1811 InstrSeq::List(s) => {
1812 let mut new_lst = bumpalo::vec![in alloc;];
1813 for mut i in s.iter_mut() {
1815 new_lst.push(i.clone())
1818 *self = instr::instrs(alloc, new_lst.into_bump_slice_mut())
1820 InstrSeq::Concat(s) => s.iter_mut().for_each(|x| x.filter_map_mut(alloc, f)),
1824 pub fn map_mut<F>(&mut self, f: &mut F)
1826 F: FnMut(&mut Instruct<'a>),
1828 //self: &mut InstrSeq<'a>
1830 InstrSeq::List(s) if s.is_empty() => {}
1831 InstrSeq::List(s) if s.len() == 1 => f(&mut s[0]),
1832 InstrSeq::List(s) => s.iter_mut().for_each(f),
1833 InstrSeq::Concat(s) => s.iter_mut().for_each(|x| x.map_mut(f)),
1837 #[allow(clippy::result_unit_err)]
1838 pub fn map_result_mut<F>(&mut self, f: &mut F) -> Result<()>
1840 F: FnMut(&mut Instruct<'a>) -> Result<()>,
1842 //self: &mut InstrSeq<'a>
1844 InstrSeq::List(s) if s.is_empty() => Ok(()),
1845 InstrSeq::List(s) if s.len() == 1 => f(&mut s[0]),
1846 InstrSeq::List(s) => s.iter_mut().try_for_each(|x| f(x)),
1847 InstrSeq::Concat(s) => s.iter_mut().try_for_each(|x| x.map_result_mut(f)),
1855 use crate::instr::{instr, instrs};
1856 use pretty_assertions::assert_eq;
1860 let a = bumpalo::Bump::new();
1861 let alloc: &bumpalo::Bump = &a;
1862 let mk_i = || Instruct::IComment(Str::from(""));
1863 let empty = || InstrSeq::new_empty(alloc);
1865 let one = || instr(alloc, mk_i());
1866 let list0 = || instrs(alloc, bumpalo::vec![in alloc;].into_bump_slice_mut());
1867 let list1 = || instrs(alloc, bumpalo::vec![in alloc; mk_i()].into_bump_slice_mut());
1871 bumpalo::vec![in alloc; mk_i(), mk_i()].into_bump_slice_mut(),
1875 InstrSeq::Concat(BumpSliceMut::new(
1877 bumpalo::vec![in alloc;].into_bump_slice_mut(),
1881 InstrSeq::Concat(BumpSliceMut::new(
1883 bumpalo::vec![in alloc; one()].into_bump_slice_mut(),
1887 assert_eq!(empty().iter().count(), 0);
1888 assert_eq!(one().iter().count(), 1);
1889 assert_eq!(list0().iter().count(), 0);
1890 assert_eq!(list1().iter().count(), 1);
1891 assert_eq!(list2().iter().count(), 2);
1892 assert_eq!(concat0().iter().count(), 0);
1893 assert_eq!(concat1().iter().count(), 1);
1895 let concat = InstrSeq::Concat(BumpSliceMut::new(
1897 bumpalo::vec![in alloc; empty()].into_bump_slice_mut(),
1899 assert_eq!(concat.iter().count(), 0);
1901 let concat = InstrSeq::Concat(BumpSliceMut::new(
1903 bumpalo::vec![in alloc; empty(), one()].into_bump_slice_mut(),
1905 assert_eq!(concat.iter().count(), 1);
1907 let concat = InstrSeq::Concat(BumpSliceMut::new(
1909 bumpalo::vec![in alloc; one(), empty()].into_bump_slice_mut(),
1911 assert_eq!(concat.iter().count(), 1);
1913 let concat = InstrSeq::Concat(BumpSliceMut::new(
1915 bumpalo::vec![in alloc; one(), list1()].into_bump_slice_mut(),
1917 assert_eq!(concat.iter().count(), 2);
1919 let concat = InstrSeq::Concat(BumpSliceMut::new(
1921 bumpalo::vec![in alloc; list2(), list1()].into_bump_slice_mut(),
1923 assert_eq!(concat.iter().count(), 3);
1925 let concat = InstrSeq::Concat(BumpSliceMut::new(
1927 bumpalo::vec![in alloc; concat0(), list2(), list1()].into_bump_slice_mut(),
1929 assert_eq!(concat.iter().count(), 3);
1931 let concat = InstrSeq::Concat(BumpSliceMut::new(
1933 bumpalo::vec![in alloc; concat1(), concat1()].into_bump_slice_mut(),
1935 assert_eq!(concat.iter().count(), 2);
1937 let concat = InstrSeq::Concat(BumpSliceMut::new(
1939 bumpalo::vec![in alloc; concat0(), concat1()].into_bump_slice_mut(),
1941 assert_eq!(concat.iter().count(), 1);
1943 let concat = InstrSeq::Concat(BumpSliceMut::new(
1945 bumpalo::vec![in alloc; list2(), concat1()].into_bump_slice_mut(),
1947 assert_eq!(concat.iter().count(), 3);
1949 let concat = InstrSeq::Concat(BumpSliceMut::new(
1951 bumpalo::vec![in alloc; list2(), concat0()].into_bump_slice_mut(),
1953 assert_eq!(concat.iter().count(), 2);
1955 let concat = InstrSeq::Concat(BumpSliceMut::new(
1957 bumpalo::vec![in alloc; one(), concat0()].into_bump_slice_mut(),
1959 assert_eq!(concat.iter().count(), 1);
1961 let concat = InstrSeq::Concat(BumpSliceMut::new(
1963 bumpalo::vec![in alloc; empty(), concat0()].into_bump_slice_mut(),
1965 assert_eq!(concat.iter().count(), 0);
1970 pub unsafe extern "C" fn no_call_compile_only_USED_TYPES_instruction_sequence<'a, 'arena>(
1971 _: InstrSeq<'arena>,