pub struct ExprSequence {
    pub insts: Vec<ExprInst>,
    pub pos: Pos,
}
Expand description

A linear sequence of instructions that produce a new value from the right-hand side of a rule, given bindings that come from a Pattern derived from the left-hand side.

Fields§

§insts: Vec<ExprInst>

Instruction sequence for expression.

InstId indexes into this sequence for Value::Expr values.

§pos: Pos

Position at which the rule producing this sequence was located.

Implementations§

Is this expression sequence producing a constant integer?

If so, return the integer type and the constant.

Examples found in repository?
src/codegen.rs (line 767)
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
    fn generate_pattern_inst(
        &self,
        code: &mut String,
        id: InstId,
        inst: &PatternInst,
        indent: &str,
        ctx: &mut BodyContext,
    ) -> (bool, usize) {
        match inst {
            &PatternInst::Arg { index, ty } => {
                let output = Value::Pattern {
                    inst: id,
                    output: 0,
                };
                let outputname = self.value_name(&output);
                let is_ref = match &self.typeenv.types[ty.index()] {
                    &Type::Primitive(..) => false,
                    _ => true,
                };
                writeln!(code, "{}let {} = arg{};", indent, outputname, index).unwrap();
                self.define_val(
                    &Value::Pattern {
                        inst: id,
                        output: 0,
                    },
                    ctx,
                    is_ref,
                    ty,
                );
                (true, 0)
            }
            &PatternInst::MatchEqual { ref a, ref b, .. } => {
                let a = self.value_by_ref(a, ctx);
                let b = self.value_by_ref(b, ctx);
                writeln!(code, "{}if {} == {} {{", indent, a, b).unwrap();
                (false, 1)
            }
            &PatternInst::MatchInt {
                ref input,
                int_val,
                ty,
                ..
            } => {
                let int_val = self.const_int(int_val, ty);
                let input = self.value_by_val(input, ctx);
                writeln!(code, "{}if {} == {}  {{", indent, input, int_val).unwrap();
                (false, 1)
            }
            &PatternInst::MatchPrim { ref input, val, .. } => {
                let input = self.value_by_val(input, ctx);
                let sym = &self.typeenv.syms[val.index()];
                writeln!(code, "{}if {} == {} {{", indent, input, sym).unwrap();
                (false, 1)
            }
            &PatternInst::MatchVariant {
                ref input,
                input_ty,
                variant,
                ref arg_tys,
            } => {
                let input = self.value_by_ref(input, ctx);
                let variants = match &self.typeenv.types[input_ty.index()] {
                    &Type::Primitive(..) => panic!("primitive type input to MatchVariant"),
                    &Type::Enum { ref variants, .. } => variants,
                };
                let ty_name = self.type_name(input_ty, /* is_ref = */ true);
                let variant = &variants[variant.index()];
                let variantname = &self.typeenv.syms[variant.name.index()];
                let args = self.match_variant_binders(variant, &arg_tys[..], id, ctx);
                let args = if args.is_empty() {
                    "".to_string()
                } else {
                    format!("{{ {} }}", args.join(", "))
                };
                writeln!(
                    code,
                    "{}if let {}::{} {} = {} {{",
                    indent, ty_name, variantname, args, input
                )
                .unwrap();
                (false, 1)
            }
            &PatternInst::Extract {
                ref inputs,
                ref output_tys,
                term,
                infallible,
                multi,
                ..
            } => {
                let termdata = &self.termenv.terms[term.index()];
                let sig = termdata.extractor_sig(self.typeenv).unwrap();

                let input_values = inputs
                    .iter()
                    .map(|input| self.value_by_ref(input, ctx))
                    .collect::<Vec<_>>();
                let output_binders = output_tys
                    .iter()
                    .enumerate()
                    .map(|(i, &ty)| {
                        let output_val = Value::Pattern {
                            inst: id,
                            output: i,
                        };
                        self.define_val(&output_val, ctx, /* is_ref = */ false, ty);
                        self.value_binder(&output_val, /* is_ref = */ false, ty)
                    })
                    .collect::<Vec<_>>();

                let bind_pattern = format!(
                    "{open_paren}{vars}{close_paren}",
                    open_paren = if output_binders.len() == 1 { "" } else { "(" },
                    vars = output_binders.join(", "),
                    close_paren = if output_binders.len() == 1 { "" } else { ")" }
                );
                let etor_call = format!(
                    "{name}(ctx, {args})",
                    name = sig.full_name,
                    args = input_values.join(", ")
                );

                match (infallible, multi) {
                    (_, true) => {
                        writeln!(
                            code,
                            "{indent}if let Some(mut iter) = {etor_call} {{",
                            indent = indent,
                            etor_call = etor_call,
                        )
                        .unwrap();
                        writeln!(
                            code,
                            "{indent}    while let Some({bind_pattern}) = iter.next(ctx) {{",
                            indent = indent,
                            bind_pattern = bind_pattern,
                        )
                        .unwrap();

                        (false, 2)
                    }
                    (false, false) => {
                        writeln!(
                            code,
                            "{indent}if let Some({bind_pattern}) = {etor_call} {{",
                            indent = indent,
                            bind_pattern = bind_pattern,
                            etor_call = etor_call,
                        )
                        .unwrap();

                        (false, 1)
                    }
                    (true, false) => {
                        writeln!(
                            code,
                            "{indent}let {bind_pattern} = {etor_call};",
                            indent = indent,
                            bind_pattern = bind_pattern,
                            etor_call = etor_call,
                        )
                        .unwrap();

                        (true, 0)
                    }
                }
            }
            &PatternInst::Expr {
                ref seq, output_ty, ..
            } if seq.is_const_int().is_some() => {
                let (ty, val) = seq.is_const_int().unwrap();
                assert_eq!(ty, output_ty);

                let output = Value::Pattern {
                    inst: id,
                    output: 0,
                };
                writeln!(
                    code,
                    "{}let {} = {};",
                    indent,
                    self.value_name(&output),
                    self.const_int(val, ty),
                )
                .unwrap();
                self.define_val(&output, ctx, /* is_ref = */ false, ty);
                (true, 0)
            }
            &PatternInst::Expr {
                ref seq, output_ty, ..
            } => {
                let closure_name = format!("closure{}", id.index());
                writeln!(code, "{}let mut {} = || {{", indent, closure_name).unwrap();
                let subindent = format!("{}    ", indent);
                let mut subctx = ctx.clone();
                let mut returns = vec![];
                for (id, inst) in seq.insts.iter().enumerate() {
                    let id = InstId(id);
                    let new_scope = self.generate_expr_inst(
                        code,
                        id,
                        inst,
                        &subindent,
                        &mut subctx,
                        &mut returns,
                    );
                    assert!(!new_scope);
                }
                assert_eq!(returns.len(), 1);
                writeln!(code, "{}return Some({});", subindent, returns[0].1).unwrap();
                writeln!(code, "{}}};", indent).unwrap();

                let output = Value::Pattern {
                    inst: id,
                    output: 0,
                };
                writeln!(
                    code,
                    "{}if let Some({}) = {}() {{",
                    indent,
                    self.value_binder(&output, /* is_ref = */ false, output_ty),
                    closure_name
                )
                .unwrap();
                self.define_val(&output, ctx, /* is_ref = */ false, output_ty);

                (false, 1)
            }
        }
    }

Trait Implementations§

Returns a copy of the value. Read more
Performs copy-assignment from source. Read more
Formats the value using the given formatter. Read more
Returns the “default value” for a type. Read more
The type of subexpression identifiers.
Construct a constant integer.
Construct a primitive constant.
Construct an enum variant with the given inputs assigned to the variant’s fields in order.
Call an external constructor with the given inputs as arguments.
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
This method returns an Ordering between self and other. Read more
Compares and returns the maximum of two values. Read more
Compares and returns the minimum of two values. Read more
Restrict a value to a certain interval. Read more
This method tests for self and other values to be equal, and is used by ==.
This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
This method returns an ordering between self and other values if one exists. Read more
This method tests less than (for self and other) and is used by the < operator. Read more
This method tests less than or equal to (for self and other) and is used by the <= operator. Read more
This method tests greater than (for self and other) and is used by the > operator. Read more
This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more

Auto Trait Implementations§

Blanket Implementations§

Gets the TypeId of self. Read more
Immutably borrows from an owned value. Read more
Mutably borrows from an owned value. Read more

Returns the argument unchanged.

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

The resulting type after obtaining ownership.
Creates owned data from borrowed data, usually by cloning. Read more
Uses borrowed data to replace owned data, usually by cloning. Read more
The type returned in the event of a conversion error.
Performs the conversion.
The type returned in the event of a conversion error.
Performs the conversion.