intrinsics pr-03
This commit is contained in:
parent
8545c67939
commit
818e27eb31
@ -109,6 +109,11 @@ impl BuiltinTypeMeta {
|
||||
out
|
||||
}
|
||||
|
||||
pub fn validate_flat_values(&self, values: &[Value]) -> Result<(), BuiltinValueError> {
|
||||
let layout = self.flatten_layout();
|
||||
validate_values_against_layout(values, &layout)
|
||||
}
|
||||
|
||||
fn flatten_into(&self, out: &mut Vec<AbiType>) {
|
||||
match self.shape {
|
||||
BuiltinTypeShape::Scalar => out.extend_from_slice(self.flat_slot_layout),
|
||||
@ -153,6 +158,18 @@ impl BuiltinConstMeta {
|
||||
BuiltinConstMaterializer::Hook(_) => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn materialize(&self) -> Result<Vec<Value>, BuiltinValueError> {
|
||||
let values = match self.materializer {
|
||||
BuiltinConstMaterializer::Direct(slots) => {
|
||||
slots.iter().copied().map(BuiltinConstSlotValue::into_value).collect()
|
||||
}
|
||||
BuiltinConstMaterializer::Hook(hook) => hook(),
|
||||
};
|
||||
|
||||
validate_values_against_layout(&values, self.flat_slot_layout)?;
|
||||
Ok(values)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
@ -161,6 +178,12 @@ pub enum IntrinsicExecutionError {
|
||||
TypeMismatch { index: usize, expected: AbiType },
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub enum BuiltinValueError {
|
||||
ArityMismatch { expected: usize, got: usize },
|
||||
TypeMismatch { index: usize, expected: AbiType },
|
||||
}
|
||||
|
||||
pub type IntrinsicImplementation = fn(&[Value]) -> Result<Vec<Value>, IntrinsicExecutionError>;
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@ -207,6 +230,18 @@ impl IntrinsicMeta {
|
||||
}
|
||||
}
|
||||
|
||||
impl BuiltinConstSlotValue {
|
||||
pub fn into_value(self) -> Value {
|
||||
match self {
|
||||
BuiltinConstSlotValue::Int32(value) => Value::Int32(value),
|
||||
BuiltinConstSlotValue::Int64(value) => Value::Int64(value),
|
||||
BuiltinConstSlotValue::Float(value) => Value::Float(value),
|
||||
BuiltinConstSlotValue::Bool(value) => Value::Boolean(value),
|
||||
BuiltinConstSlotValue::NominalBuiltin { carrier, .. } => Value::Int32(carrier),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const COLOR: BuiltinTypeKey = BuiltinTypeKey::new("color", 1);
|
||||
const VEC2: BuiltinTypeKey = BuiltinTypeKey::new("vec2", 1);
|
||||
const PIXEL: BuiltinTypeKey = BuiltinTypeKey::new("pixel", 1);
|
||||
@ -345,6 +380,14 @@ pub fn lookup_builtin_constant(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn materialize_builtin_constant(
|
||||
target: &str,
|
||||
name: &str,
|
||||
version: u16,
|
||||
) -> Result<Option<Vec<Value>>, BuiltinValueError> {
|
||||
lookup_builtin_constant(target, name, version).map(BuiltinConstMeta::materialize).transpose()
|
||||
}
|
||||
|
||||
pub fn lookup_intrinsic(owner: &str, name: &str, version: u16) -> Option<&'static IntrinsicMeta> {
|
||||
INTRINSICS
|
||||
.iter()
|
||||
@ -386,6 +429,23 @@ fn value_matches_abi_type(value: &Value, expected: AbiType) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_values_against_layout(
|
||||
values: &[Value],
|
||||
layout: &[AbiType],
|
||||
) -> Result<(), BuiltinValueError> {
|
||||
if values.len() != layout.len() {
|
||||
return Err(BuiltinValueError::ArityMismatch { expected: layout.len(), got: values.len() });
|
||||
}
|
||||
|
||||
for (index, (value, expected)) in values.iter().zip(layout.iter()).enumerate() {
|
||||
if !value_matches_abi_type(value, *expected) {
|
||||
return Err(BuiltinValueError::TypeMismatch { index, expected: *expected });
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vec2_dot(args: &[Value]) -> Result<Vec<Value>, IntrinsicExecutionError> {
|
||||
if args.len() != 4 {
|
||||
return Err(IntrinsicExecutionError::ArityMismatch { expected: 4, got: args.len() });
|
||||
@ -462,6 +522,18 @@ mod tests {
|
||||
assert!(lookup_intrinsic("vec2", "zero", 1).is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builtin_constant_materializes_vec2_zero() {
|
||||
let zero = lookup_builtin_constant("vec2", "zero", 1).expect("vec2.zero must exist");
|
||||
let materialized = zero.materialize().expect("vec2.zero must materialize");
|
||||
assert_eq!(materialized, vec![Value::Float(0.0), Value::Float(0.0)]);
|
||||
|
||||
let looked_up = materialize_builtin_constant("vec2", "zero", 1)
|
||||
.expect("materialization lookup must succeed")
|
||||
.expect("constant must exist");
|
||||
assert_eq!(looked_up, materialized);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn intrinsic_metadata_exposes_arg_and_return_layouts() {
|
||||
let dot = lookup_intrinsic("vec2", "dot", 1).expect("vec2.dot must exist");
|
||||
@ -493,4 +565,13 @@ mod tests {
|
||||
.expect("length implementation must execute");
|
||||
assert_eq!(result, vec![Value::Float(5.0)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn pixel_flat_values_validate_with_color_carrier_slot() {
|
||||
let pixel = lookup_builtin_type("pixel", 1).expect("pixel builtin must exist");
|
||||
let values = vec![Value::Int32(1), Value::Int32(2), Value::Int32(0xF800)];
|
||||
pixel.validate_flat_values(&values).expect("pixel flat values must validate");
|
||||
assert_eq!(pixel.flat_slot_width, 3);
|
||||
assert_eq!(pixel.field("color").map(|field| field.start_slot), Some(2));
|
||||
}
|
||||
}
|
||||
|
||||
@ -17,9 +17,9 @@ mod vm_init_error;
|
||||
pub use builtins::{
|
||||
AbiType, BuiltinConstKey, BuiltinConstMaterializer, BuiltinConstMeta, BuiltinConstSlotValue,
|
||||
BuiltinFieldMeta, BuiltinLayoutType, BuiltinScalarType, BuiltinTypeKey, BuiltinTypeMeta,
|
||||
BuiltinTypeShape, IntrinsicExecutionError, IntrinsicImplementation, IntrinsicKey,
|
||||
IntrinsicMeta, lookup_builtin_constant, lookup_builtin_type, lookup_intrinsic,
|
||||
lookup_intrinsic_by_id,
|
||||
BuiltinTypeShape, BuiltinValueError, IntrinsicExecutionError, IntrinsicImplementation,
|
||||
IntrinsicKey, IntrinsicMeta, lookup_builtin_constant, lookup_builtin_type, lookup_intrinsic,
|
||||
lookup_intrinsic_by_id, materialize_builtin_constant,
|
||||
};
|
||||
pub use prometeu_hal::{HostContext, HostReturn, NativeInterface, SyscallId};
|
||||
pub use virtual_machine::{BudgetReport, LogicalFrameEndingReason, VirtualMachine};
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user