intrinsics pr-03

This commit is contained in:
bQUARKz 2026-03-03 04:59:06 +00:00
parent 8545c67939
commit 818e27eb31
Signed by: bquarkz
SSH Key Fingerprint: SHA256:Z7dgqoglWwoK6j6u4QC87OveEq74WOhFN+gitsxtkf8
2 changed files with 84 additions and 3 deletions

View File

@ -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));
}
}

View File

@ -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};