use super::keys::{abs_decode, num_decode, CField, CHeap, CStore, CVal, CanonRef};
use super::{AggKind, CanonicalTypeId};
use crate::engine::Engine;
use crate::value::{
ArrayType, FieldType, FuncType, HeapType, Mutability, RefType, StorageType, StructType, ValType,
};
pub(crate) fn mat_val(engine: &Engine, v: &CVal) -> ValType {
match v {
CVal::Num(c) => num_decode(*c),
CVal::Ref(nullable, h) => ValType::Ref(RefType::new(*nullable, mat_heap(engine, h))),
}
}
fn mat_heap(engine: &Engine, h: &CHeap) -> HeapType {
match h {
CHeap::Abs(c) => abs_decode(*c),
CHeap::Concrete(kind, CanonRef::Canon(id)) => match kind {
AggKind::Func => HeapType::ConcreteFunc(FuncType::from_id(engine, *id)),
AggKind::Struct => HeapType::ConcreteStruct(StructType::from_id(engine, *id)),
AggKind::Array => HeapType::ConcreteArray(ArrayType::from_id(engine, *id)),
},
CHeap::Concrete(_, CanonRef::Rel(_)) => unreachable!("stored bodies use absolute ids"),
}
}
pub(crate) fn mat_field(engine: &Engine, f: &CField) -> FieldType {
let mutability = if f.mutable {
Mutability::Var
} else {
Mutability::Const
};
let storage = match &f.storage {
CStore::Packed(0) => StorageType::I8,
CStore::Packed(_) => StorageType::I16,
CStore::Val(v) => StorageType::ValType(mat_val(engine, v)),
};
FieldType::new(mutability, storage)
}
pub(crate) fn func_sig(engine: &Engine, id: CanonicalTypeId) -> (Vec<ValType>, Vec<ValType>) {
let (p, r) = engine
.types()
.read()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.func_body_raw(id);
(
p.iter().map(|v| mat_val(engine, v)).collect(),
r.iter().map(|v| mat_val(engine, v)).collect(),
)
}
pub(crate) fn struct_fields(engine: &Engine, id: CanonicalTypeId) -> Vec<FieldType> {
let fields = engine
.types()
.read()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.struct_fields_raw(id);
fields.iter().map(|f| mat_field(engine, f)).collect()
}
pub(crate) fn array_field(engine: &Engine, id: CanonicalTypeId) -> FieldType {
let field = engine
.types()
.read()
.unwrap_or_else(std::sync::PoisonError::into_inner)
.array_field_raw(id);
mat_field(engine, &field)
}