| 912 | } |
| 913 | |
| 914 | fn emit_expr<W: Write>(&self, ctx: &mut BodyContext<W>, result: BindingId) -> std::fmt::Result { |
| 915 | if ctx.is_bound.contains(&result) { |
| 916 | return write!(ctx.out, "v{}", result.index()); |
| 917 | } |
| 918 | |
| 919 | let binding = &ctx.ruleset.bindings[result.index()]; |
| 920 | |
| 921 | let call = |ctx: &mut BodyContext<W>, |
| 922 | term: TermId, |
| 923 | parameters: &[BindingId], |
| 924 | get_sig: fn(&Term, &TypeEnv) -> Option<ExternalSig>| { |
| 925 | let termdata = &self.termenv.terms[term.index()]; |
| 926 | let sig = get_sig(termdata, self.typeenv).unwrap(); |
| 927 | if let &[ret_ty] = &sig.ret_tys[..] { |
| 928 | let (is_ref, _) = self.ty(ret_ty); |
| 929 | if is_ref { |
| 930 | ctx.set_ref(result, true); |
| 931 | write!(ctx.out, "&")?; |
| 932 | } |
| 933 | } |
| 934 | write!(ctx.out, "{}(ctx", sig.full_name)?; |
| 935 | debug_assert_eq!(parameters.len(), sig.param_tys.len()); |
| 936 | for (¶meter, &arg_ty) in parameters.iter().zip(sig.param_tys.iter()) { |
| 937 | let (is_ref, _) = self.ty(arg_ty); |
| 938 | write!(ctx.out, ", ")?; |
| 939 | let (before, after) = match (is_ref, ctx.is_ref.contains(¶meter)) { |
| 940 | (false, true) => ("", ".clone()"), |
| 941 | (true, false) => ("&", ""), |
| 942 | _ => ("", ""), |
| 943 | }; |
| 944 | write!(ctx.out, "{before}")?; |
| 945 | self.emit_expr(ctx, parameter)?; |
| 946 | write!(ctx.out, "{after}")?; |
| 947 | } |
| 948 | if let ReturnKind::Iterator = sig.ret_kind { |
| 949 | write!(ctx.out, ", &mut v{}", result.index())?; |
| 950 | } |
| 951 | write!(ctx.out, ")") |
| 952 | }; |
| 953 | |
| 954 | let extract_fields = |ctx: &mut BodyContext<W>, |
| 955 | field_bindings: &[BindingId], |
| 956 | fields: &Fields| |
| 957 | -> std::fmt::Result { |
| 958 | if !field_bindings.is_empty() { |
| 959 | ctx.begin_block()?; |
| 960 | for (i, value) in field_bindings.iter().enumerate() { |
| 961 | let field_name = match fields { |
| 962 | Fields::Unit => panic!(), |
| 963 | Fields::Struct(fields) => { |
| 964 | Cow::Borrowed(&self.typeenv.syms[fields.fields[i].name.index()]) |
| 965 | } |
| 966 | Fields::Tuple(_) => Cow::Owned(format!("{i}")), |
| 967 | }; |
| 968 | write!(ctx.out, "{}{field_name}: ", &ctx.indent)?; |
| 969 | self.emit_expr(ctx, *value)?; |
| 970 | if ctx.is_ref.contains(value) { |
| 971 | write!(ctx.out, ".clone()")?; |