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
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
mod arret_fun;
pub mod build_reg;
pub mod from_reg;
pub mod list;
pub mod plan_phi;
pub mod synthetic_fun;
pub mod to_const;
pub mod types;

use std::rc::Rc;
use std::sync::Arc;

use arret_runtime::abitype;
use arret_runtime::boxed;
use arret_runtime::boxed::refs::Gc;

use crate::mir::builder::BuiltReg;
use crate::mir::tagset::TypeTagSet;
use crate::rfi;
use crate::ty;
use crate::ty::record;

pub use arret_fun::{ArretFun, ArretFunId};

#[derive(Clone, Debug)]
pub struct RegValue {
    pub reg: BuiltReg,
    pub abi_type: abitype::AbiType,
    pub possible_type_tags: TypeTagSet,
    pub type_hint: types::TypeHint,
}

impl RegValue {
    pub fn new(reg: BuiltReg, abi_type: abitype::AbiType) -> RegValue {
        RegValue {
            reg,
            possible_type_tags: (&abi_type).into(),
            abi_type,
            type_hint: types::TypeHint::None,
        }
    }
}

#[derive(Clone, Debug)]
pub enum Value {
    Const(Gc<boxed::Any>),
    // This uses `Box<[]>` because we can't convert from a `Vec<>` to `Rc<[]>` without reallocating
    List(Box<[Value]>, Option<Box<Value>>),
    Record(record::ConsId, Box<[Value]>),
    ArretFun(ArretFun),
    RustFun(Arc<rfi::Fun>),
    Reg(Rc<RegValue>),

    TyPred(ty::pred::TestTy),
    EqPred,
    RecordCons(record::ConsId),
    FieldAccessor(record::ConsId, usize),
}

impl Value {
    pub fn unsized_list_iter(&self) -> list::UnsizedListIterator {
        self.clone().into_unsized_list_iter()
    }

    pub fn into_unsized_list_iter(self) -> list::UnsizedListIterator {
        list::UnsizedListIterator::new(self)
    }

    pub fn try_sized_list_iter(&self) -> Option<list::SizedListIterator> {
        list::SizedListIterator::try_new(self)
    }
}

impl<T: boxed::Boxed> From<Gc<T>> for Value {
    fn from(boxed_ref: Gc<T>) -> Self {
        Value::Const(boxed_ref.as_any_ref())
    }
}

impl From<RegValue> for Value {
    fn from(reg_value: RegValue) -> Self {
        Value::Reg(Rc::new(reg_value))
    }
}

pub fn visit_value_root(strong_pass: &mut boxed::collect::StrongPass, value: &mut Value) {
    match value {
        Value::Const(ref mut any_ref) => strong_pass.visit_box(any_ref),
        Value::List(ref mut fixed, ref mut rest) => {
            for any_ref in fixed.iter_mut() {
                visit_value_root(strong_pass, any_ref);
            }
            for any_ref in rest {
                visit_value_root(strong_pass, any_ref);
            }
        }
        Value::ArretFun(ref mut arret_fun) => {
            for (_, value) in arret_fun.env_values_mut().const_values.iter_mut() {
                visit_value_root(strong_pass, value);
            }
            for (_, value) in arret_fun.env_values_mut().free_values.iter_mut() {
                visit_value_root(strong_pass, value);
            }
        }
        _ => {}
    }
}