1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use arret_syntax::span::Span;

use arret_runtime::boxed;
use arret_runtime::boxed::prelude::*;

use crate::mir::builder::TryToBuilder;
use crate::mir::eval_hir::EvalHirCtx;
use crate::mir::value;
use crate::mir::value::Value;
use crate::ty::record;

pub fn load_record_field(
    ehx: &mut EvalHirCtx,
    b: &mut impl TryToBuilder,
    span: Span,
    record_cons: &record::ConsId,
    record_value: &Value,
    field_index: usize,
) -> Value {
    match record_value {
        Value::Record(_, fields) => fields[field_index].clone(),
        Value::Const(boxed_any) => {
            use boxed::FieldValue;

            let boxed_record = boxed_any
                .downcast_ref::<boxed::Record>()
                .expect("unexpected type when accessing record field");

            match boxed_record
                .field_values(ehx.as_heap())
                .nth(field_index)
                .unwrap()
            {
                FieldValue::Bool(bool_value) => boxed::Bool::singleton_ref(bool_value).into(),
                FieldValue::Int(int_value) => boxed::Int::new(ehx, int_value).into(),
                FieldValue::Float(float_value) => boxed::Float::new(ehx, float_value).into(),
                FieldValue::Char(char_value) => boxed::Char::new(ehx, char_value).into(),
                FieldValue::Boxed(boxed_any) => boxed_any.into(),
                FieldValue::InternedSym(interned) => {
                    boxed::Sym::from_interned_sym(ehx, interned).into()
                }
            }
        }
        other_value => {
            use crate::mir::ops::*;
            use crate::mir::value::build_reg::value_to_reg;

            let record_struct = ehx
                .evaled_record_class_for_cons(record_cons)
                .record_struct
                .clone();

            let b = if let Some(b) = b.try_to_builder() {
                b
            } else {
                panic!("need builder to access field of boxed record reg");
            };

            let record_reg =
                value_to_reg(ehx, b, span, other_value, &boxed::TypeTag::Record.into());

            let field_reg = b.push_reg(
                span,
                OpKind::LoadBoxedRecordField,
                LoadBoxedRecordFieldOp {
                    field_index,
                    record_reg: record_reg.into(),
                    record_struct: record_struct.clone(),
                },
            );

            let field_abi_type = record_struct.field_abi_types[field_index].clone();
            value::RegValue::new(field_reg, field_abi_type).into()
        }
    }
}