From: Skgland Date: Mon, 25 Aug 2025 21:54:18 +0000 (+0200) Subject: cleanup ffi error handling and use Atom instead of &str in appropriate places X-Git-Tag: v0.10.0~11^2~3 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=78c08b87b63d5c016b62f1bf59ca69aeb2d10ba5;p=scryer-prolog.git cleanup ffi error handling and use Atom instead of &str in appropriate places --- diff --git a/src/ffi.rs b/src/ffi.rs index 3bd27557..b780e7b3 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -22,6 +22,7 @@ and finally we add the pointer the size of what we've written. use crate::arena::Arena; use crate::atom_table::Atom; use crate::forms::Number; +use crate::machine::machine_errors::DomainErrorType; use crate::parser::ast::{Fixnum, MightNotFitInFixnum}; use dashu::Integer; @@ -39,7 +40,7 @@ use std::ops::Deref; use std::ptr::NonNull; pub struct FunctionDefinition { - pub name: String, + pub name: Atom, pub return_value: Atom, pub args: Vec, } @@ -100,10 +101,10 @@ impl FunctionImpl { return_type_name: Atom, args: &[Arg], arena: &mut Arena, - structs_table: &HashMap, + structs_table: &HashMap, ) -> Result { let struct_type = structs_table - .get(&*return_type_name.as_str()) + .get(&return_type_name) .ok_or(FfiError::StructNotFound(return_type_name))?; let ffi_type = unsafe { *struct_type.ffi_type.as_raw_ptr() }; @@ -121,12 +122,8 @@ impl FunctionImpl { ) }; - let struct_val = struct_type.read( - alloc.ptr.as_ptr(), - &return_type_name.as_str(), - structs_table, - arena, - ); + let struct_val = + struct_type.read(alloc.ptr.as_ptr(), return_type_name, structs_table, arena); drop(alloc); @@ -137,7 +134,7 @@ impl FunctionImpl { &self, args: &[Arg], arena: &mut Arena, - structs_table: &HashMap, + structs_table: &HashMap, ) -> Result { let call_fn: unsafe fn(&Self, &[Arg], &mut Arena) -> Result = match self.return_type { @@ -164,8 +161,8 @@ impl FunctionImpl { #[derive(Debug, Default)] pub struct ForeignFunctionTable { - table: HashMap, - structs: HashMap, + table: HashMap, + structs: HashMap, } #[derive(Clone, Debug)] @@ -183,7 +180,7 @@ impl StructImpl { fn build( &self, - structs_table: &HashMap, + structs_table: &HashMap, struct_args: &mut [Value], ) -> Result { let args = ArgValue::build_args(struct_args, &self.fields, structs_table)?; @@ -249,8 +246,8 @@ impl StructImpl { fn read( &self, ptr: *mut c_void, - struct_name: &str, - struct_table: &HashMap, + struct_name: Atom, + struct_table: &HashMap, arena: &mut Arena, ) -> Result { unsafe { @@ -315,7 +312,7 @@ impl StructImpl { FfiType::F32 => read_float::(ptr, &mut layout), FfiType::F64 => read_float::(ptr, &mut layout), FfiType::Struct(substruct) => { - let Some(substruct_type) = struct_table.get(&*substruct.as_str()) else { + let Some(substruct_type) = struct_table.get(substruct) else { return Err(FfiError::StructNotFound(*substruct)); }; @@ -328,19 +325,15 @@ impl StructImpl { .map_err(|_| FfiError::LayoutError)?; layout = new_layout; let field_ptr = ptr.byte_offset(offset as isize); - let struct_val = substruct_type.read( - field_ptr, - &substruct.as_str(), - struct_table, - arena, - )?; + let struct_val = + substruct_type.read(field_ptr, *substruct, struct_table, arena)?; Ok(struct_val) } - FfiType::Void => unreachable!("void is not a valid field type"), + FfiType::Void => return Err(FfiError::VoidArgumentType), }; returns.push(val?); } - Ok(Value::Struct(struct_name.to_string(), returns)) + Ok(Value::Struct(struct_name, returns)) } } } @@ -427,7 +420,7 @@ impl FfiType { } } - fn to_type(self, structs_table: &HashMap) -> Result { + fn to_type(self, structs_table: &HashMap) -> Result { Ok(match self { Self::I64 => libffi::middle::Type::i64(), Self::I32 => libffi::middle::Type::i32(), @@ -444,7 +437,7 @@ impl FfiType { Self::F32 => libffi::middle::Type::f32(), Self::F64 => libffi::middle::Type::f64(), Self::Struct(struct_name) => structs_table - .get(&*struct_name.as_str()) + .get(&struct_name) .ok_or(FfiError::StructNotFound(struct_name))? .ffi_type .clone(), @@ -471,7 +464,7 @@ impl<'val> ArgValue<'val> { fn new( val: &'val mut Value, arg_type: &FfiType, - structs_table: &HashMap, + structs_table: &HashMap, ) -> Result { match arg_type { FfiType::U8 => Ok(Self::U8(val.as_int()?)), @@ -486,27 +479,27 @@ impl<'val> ArgValue<'val> { FfiType::F64 => Ok(Self::F64(val.as_float()?)), FfiType::Ptr => Ok(Self::Ptr(val.as_ptr()?, PhantomData)), FfiType::CStr => Ok(Self::Ptr(val.as_ptr()?, PhantomData)), - FfiType::Struct(atom) => { - let (name, args) = val.as_struct()?; + FfiType::Struct(arg_type_name) => { + let (val_type_name, args) = val.as_struct()?; - if &*atom.as_str() != name { - return Err(FfiError::ValueCast); + if *arg_type_name != val_type_name { + return Err(FfiError::ValueCast(*arg_type_name, val_type_name)); } - let Some(struct_type) = structs_table.get(name) else { - return Err(FfiError::StructNotFound(*atom)); + let Some(struct_type) = structs_table.get(&val_type_name) else { + return Err(FfiError::StructNotFound(*arg_type_name)); }; Ok(Self::Struct(struct_type.build(structs_table, args)?)) } - FfiType::Void => Err(FfiError::InvalidArgumentType), + FfiType::Void => Err(FfiError::VoidArgumentType), } } fn build_args( args: &'val mut [Value], types: &[FfiType], - structs_table: &HashMap, + structs_table: &HashMap, ) -> Result, FfiError> { if types.len() != args.len() { return Err(FfiError::ArgCountMismatch); @@ -590,7 +583,7 @@ impl ForeignFunctionTable { self.table.extend(other.table); } - pub fn define_struct(&mut self, name: &str, atom_fields: Vec) -> Result<(), FfiError> { + pub fn define_struct(&mut self, name: Atom, atom_fields: Vec) -> Result<(), FfiError> { let fields: Vec<_> = atom_fields.iter().map(FfiType::from_atom).collect(); let struct_type = libffi::middle::Type::structure( fields @@ -612,7 +605,7 @@ impl ForeignFunctionTable { }; self.structs.insert( - name.to_string(), + name, StructImpl { ffi_type: struct_type, fields, @@ -629,7 +622,7 @@ impl ForeignFunctionTable { let mut ff_table: ForeignFunctionTable = Default::default(); let library = unsafe { Library::new(library_name) }?; for function in functions { - let symbol_name: CString = CString::new(function.name.clone())?; + let symbol_name: CString = CString::new(&*function.name.as_str())?; let code_ptr: Symbol<*mut c_void> = unsafe { library.get(symbol_name.as_bytes_with_nul()) }?; let args: Vec<_> = function.args.iter().map(FfiType::from_atom).collect(); @@ -643,7 +636,7 @@ impl ForeignFunctionTable { ); ff_table.table.insert( - function.name.clone(), + function.name, FunctionImpl { cif, args, @@ -659,11 +652,14 @@ impl ForeignFunctionTable { pub fn exec( &mut self, - fn_name: &str, + fn_name: Atom, mut args: Vec, arena: &mut Arena, ) -> Result { - let fn_impl = self.table.get(fn_name).ok_or(FfiError::FunctionNotFound)?; + let fn_impl = self + .table + .get(&fn_name) + .ok_or(FfiError::FunctionNotFound(fn_name))?; let args = ArgValue::build_args(&mut args, &fn_impl.args, &self.structs)?; @@ -695,13 +691,13 @@ impl ForeignFunctionTable { } match FfiType::from_atom(&kind) { - FfiType::Void => Err(FfiError::InvalidFfiType), + FfiType::Void => Err(FfiError::VoidArgumentType), FfiType::Bool => { let val = args.as_int::()?; let init = match val { 0 => false, 1 => true, - _ => return Err(FfiError::ValueOutOfRange), + _ => return Err(FfiError::ValueOutOfRange(DomainErrorType::ZeroOrOne, args)), }; allocate_primitive::(allocator, init, arena) } @@ -716,10 +712,10 @@ impl ForeignFunctionTable { FfiType::F32 => allocate_primitive::(allocator, args.as_float()? as f32, arena), FfiType::F64 => allocate_primitive::(allocator, args.as_float()?, arena), FfiType::Ptr => allocate_primitive::<*mut c_void>(allocator, args.as_ptr()?, arena), - FfiType::CStr => Err(FfiError::InvalidFfiType), + FfiType::CStr => Err(FfiError::CStrFieldType), FfiType::Struct(_) => { - let Some(struct_impl) = self.structs.get(&*kind.as_str()) else { - return Err(FfiError::InvalidStruct); + let Some(struct_impl) = self.structs.get(&kind) else { + return Err(FfiError::StructNotFound(kind)); }; let (_, args) = args.as_struct()?; @@ -755,11 +751,11 @@ impl ForeignFunctionTable { let ptr = ptr.as_ptr()?; let Some(ptr) = NonNull::new(ptr) else { - return Err(FfiError::ValueOutOfRange); + return Err(FfiError::NullPtr); }; match FfiType::from_atom(&kind) { - FfiType::Void => Err(FfiError::InvalidFfiType), + FfiType::Void => Err(FfiError::VoidArgumentType), FfiType::Bool | FfiType::U8 => Ok(unsafe { read_int::(ptr, arena) }), FfiType::I8 => Ok(unsafe { read_int::(ptr, arena) }), FfiType::U16 => Ok(unsafe { read_int::(ptr, arena) }), @@ -782,11 +778,11 @@ impl ForeignFunctionTable { unsafe { CStr::from_ptr(ptr.as_ptr().cast()) }.to_owned(), )), FfiType::Struct(_) => { - let Some(struct_impl) = self.structs.get(&*kind.as_str()) else { - return Err(FfiError::InvalidStruct); + let Some(struct_impl) = self.structs.get(&kind) else { + return Err(FfiError::StructNotFound(kind)); }; - struct_impl.read(ptr.as_ptr(), &kind.as_str(), &self.structs, arena) + struct_impl.read(ptr.as_ptr(), kind, &self.structs, arena) } } } @@ -805,11 +801,11 @@ impl ForeignFunctionTable { let ptr = ptr.as_ptr()?; let Some(ptr) = NonNull::new(ptr) else { - return Err(FfiError::ValueOutOfRange); + return Err(FfiError::NullPtr); }; match FfiType::from_atom(&kind) { - FfiType::Void => return Err(FfiError::InvalidFfiType), + FfiType::Void => return Err(FfiError::VoidArgumentType), FfiType::Bool => deallocate_primitive::(allocator, ptr), FfiType::U8 => deallocate_primitive::(allocator, ptr), FfiType::I8 => deallocate_primitive::(allocator, ptr), @@ -822,10 +818,10 @@ impl ForeignFunctionTable { FfiType::F32 => deallocate_primitive::(allocator, ptr), FfiType::F64 => deallocate_primitive::(allocator, ptr), FfiType::Ptr => deallocate_primitive::<*mut c_void>(allocator, ptr), - FfiType::CStr => return Err(FfiError::InvalidFfiType), + FfiType::CStr => return Err(FfiError::CStrFieldType), FfiType::Struct(_) => { - let Some(struct_impl) = self.structs.get(&*kind.as_str()) else { - return Err(FfiError::InvalidStruct); + let Some(struct_impl) = self.structs.get(&kind) else { + return Err(FfiError::StructNotFound(kind)); }; let layout = struct_impl.layout()?; @@ -845,7 +841,7 @@ impl ForeignFunctionTable { pub enum Value { Number(Number), CString(CString), - Struct(String, Vec), + Struct(Atom, Vec), } impl Value { @@ -857,22 +853,27 @@ impl Value { match self { Value::Number(Number::Integer(ibig_ptr)) => { let ibig: &Integer = ibig_ptr; - ibig.clone() - .try_into() - .map_err(|_| FfiError::ValueOutOfRange) + ibig.clone().try_into().map_err(|_| { + FfiError::ValueOutOfRange(DomainErrorType::FixedSizedInt, self.clone()) + }) } - Value::Number(Number::Fixnum(fixnum)) => fixnum - .get_num() - .try_into() - .map_err(|_| FfiError::ValueOutOfRange), - _ => Err(FfiError::ValueCast), + Value::Number(Number::Fixnum(fixnum)) => fixnum.get_num().try_into().map_err(|_| { + FfiError::ValueOutOfRange(DomainErrorType::FixedSizedInt, self.clone()) + }), + _ => Err(FfiError::ValueOutOfRange( + DomainErrorType::FixedSizedInt, + self.clone(), + )), } } fn as_float(&self) -> Result { match self { &Value::Number(Number::Float(OrderedFloat(f))) => Ok(f), - _ => Err(FfiError::ValueCast), + _ => Err(FfiError::ValueOutOfRange( + DomainErrorType::F64, + self.clone(), + )), } } @@ -882,33 +883,39 @@ impl Value { Value::Number(Number::Fixnum(fixnum)) => Ok(std::ptr::with_exposed_provenance_mut( fixnum.get_num() as usize, )), - _ => Err(FfiError::ValueCast), + _ => Err(FfiError::ValueOutOfRange( + DomainErrorType::PtrLike, + self.clone(), + )), } } - fn as_struct(&mut self) -> Result<(&str, &mut [Self]), FfiError> { + fn as_struct(&mut self) -> Result<(Atom, &mut [Self]), FfiError> { match self { - Value::Struct(name, values) => Ok((name, values)), - _ => Err(FfiError::ValueCast), + Value::Struct(name, values) => Ok((*name, values)), + _ => Err(FfiError::ValueOutOfRange( + DomainErrorType::FfiStruct, + self.clone(), + )), } } } #[derive(Debug)] pub enum FfiError { - ValueCast, - ValueOutOfRange, - InvalidArgumentType, - InvalidArgument, - InvalidFfiType, - InvalidStruct, - FunctionNotFound, + ValueCast(Atom, Atom), + ValueOutOfRange(DomainErrorType, Value), + VoidArgumentType, + FunctionNotFound(Atom), StructNotFound(Atom), ArgCountMismatch, AllocationFailed, // LayoutError should never occour LayoutError, + UnsupportedTypedef, UnsupportedAbi, + CStrFieldType, + NullPtr, } impl std::fmt::Display for FfiError { @@ -922,7 +929,7 @@ impl Error for FfiError {} impl From for FfiError { fn from(value: libffi::low::Error) -> Self { match value { - libffi::low::Error::Typedef => FfiError::InvalidFfiType, + libffi::low::Error::Typedef => FfiError::UnsupportedTypedef, libffi::low::Error::Abi => FfiError::UnsupportedAbi, } } diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index 22afc03a..1c28783c 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -3,7 +3,7 @@ use crate::atom_table::*; use crate::parser::ast::*; #[cfg(feature = "ffi")] -use crate::ffi::FfiError; +use crate::ffi::{self, FfiError}; use crate::forms::*; use crate::functor_macro::*; use crate::machine::heap::*; @@ -275,6 +275,30 @@ impl DomainError for MachineStub { } } +#[cfg(feature = "ffi")] +impl DomainError for ffi::Value { + fn domain_error(self, machine_st: &mut MachineState, error: DomainErrorType) -> MachineError { + use ffi::Value; + + match self { + Value::Number(number) => number.domain_error(machine_st, error), + Value::CString(cstring) => { + let str = cstring.to_string_lossy().into_owned(); + let stub = functor!( + atom!("domain_error"), + [atom_as_cell((error.as_atom())), string(str)] + ); + + MachineError { + stub, + location: None, + } + } + Value::Struct(atom, _values) => atom_as_cell!(atom).domain_error(machine_st, error), + } + } +} + #[inline(always)] pub(super) fn functor_stub(name: Atom, arity: usize) -> MachineStub { functor!(atom!("/"), [atom_as_cell(name), fixnum(arity)]) @@ -418,6 +442,28 @@ impl MachineState { [atom_as_cell((atom!("process"))), cell(culprit)] ); + MachineError { + stub, + location: None, + } + } + ExistenceError::FfiFunction(atom) => { + let stub = functor!( + atom!("existence_error"), + [atom_as_cell((atom!("ffi_function"))), atom_as_cell(atom)] + ); + + MachineError { + stub, + location: None, + } + } + ExistenceError::FfiStructType(atom) => { + let stub = functor!( + atom!("existence_error"), + [atom_as_cell((atom!("ffi_struct_type"))), atom_as_cell(atom)] + ); + MachineError { stub, location: None, @@ -628,42 +674,43 @@ impl MachineState { } #[cfg(feature = "ffi")] - pub(super) fn ffi_error(&self, err: FfiError, culprit: HeapCellValue) -> MachineError { - let error_atom = match err { - FfiError::ValueCast => atom!("value_cast"), - FfiError::ValueOutOfRange => atom!("value_out_of_range"), - FfiError::InvalidFfiType => atom!("invalid_ffi_type"), - FfiError::InvalidArgumentType => atom!("invalid_argument_type"), - FfiError::InvalidArgument => atom!("invalid_argument"), - FfiError::InvalidStruct => atom!("invalid_struct"), - FfiError::FunctionNotFound => atom!("function_not_found"), - FfiError::StructNotFound(culprit) => { + pub(super) fn ffi_error(&mut self, err: FfiError) -> MachineError { + match err { + FfiError::ValueCast(expected, actual) => { let stub = functor!( - atom!("ffi_error"), - [ - atom_as_cell((atom!("struct_not_found"))), - atom_as_cell(culprit) - ] + atom!("domain_error"), + [atom_as_cell(expected), atom_as_cell(actual)] ); - return MachineError { + MachineError { stub, location: None, - }; + } } - FfiError::ArgCountMismatch => atom!("mismatched_argument_count"), - FfiError::AllocationFailed => atom!("allocation_failed"), - FfiError::LayoutError => atom!("layout_error"), - FfiError::UnsupportedAbi => atom!("unsupported_abi"), - }; - let stub = functor!( - atom!("ffi_error"), - [atom_as_cell(error_atom), cell(culprit)] - ); - - MachineError { - stub, - location: None, + FfiError::ValueOutOfRange(domain, culprit) => self.domain_error(domain, culprit), + FfiError::FunctionNotFound(name) => { + self.existence_error(ExistenceError::FfiFunction(name)) + } + FfiError::StructNotFound(name) => { + self.existence_error(ExistenceError::FfiStructType(name)) + } + FfiError::ArgCountMismatch => self.unreachable_error(), + FfiError::AllocationFailed => MachineError { + stub: functor!(atom!("resource_error"), [atom_as_cell((atom!("heap")))]), + location: None, + }, + FfiError::LayoutError => self.representation_error(RepFlag::FfiLayout), + FfiError::UnsupportedTypedef => self.representation_error(RepFlag::FfiLayout), + FfiError::UnsupportedAbi => self.representation_error(RepFlag::FfiAbi), + FfiError::VoidArgumentType => self.domain_error( + DomainErrorType::FfiArgumentType, + atom_as_cell!(atom!("void")), + ), + FfiError::CStrFieldType => todo!(), + FfiError::NullPtr => self.domain_error( + DomainErrorType::NonNullPtr, + fixnum_as_cell!(Fixnum::build_with(0)), + ), } } @@ -845,6 +892,14 @@ pub(crate) enum DomainErrorType { OperatorPriority, Directive, Allocator, + FfiStruct, + ZeroOrOne, + NonNullPtr, + PtrLike, + F64, + FfiArgument, + FfiArgumentType, + FixedSizedInt, } impl DomainErrorType { @@ -860,6 +915,14 @@ impl DomainErrorType { DomainErrorType::OperatorPriority => atom!("operator_priority"), DomainErrorType::Directive => atom!("directive"), DomainErrorType::Allocator => atom!("allocator"), + DomainErrorType::ZeroOrOne => atom!("zero_or_one"), + DomainErrorType::FfiStruct => atom!("ffi_struct"), + DomainErrorType::NonNullPtr => atom!("non_null_pointer"), + DomainErrorType::PtrLike => atom!("pointer_like"), + DomainErrorType::F64 => atom!("f64"), + DomainErrorType::FfiArgument => atom!("ffi_argument"), + DomainErrorType::FfiArgumentType => atom!("ffi_argument_type"), + DomainErrorType::FixedSizedInt => atom!("fixed_sized_int"), } } } @@ -874,6 +937,8 @@ pub(crate) enum RepFlag { // MaxInteger, // MinInteger, Term, + FfiLayout, + FfiAbi, } impl RepFlag { @@ -885,7 +950,9 @@ impl RepFlag { RepFlag::MaxArity => atom!("max_arity"), RepFlag::Term => atom!("term"), // RepFlag::MaxInteger => atom!("max_integer"), - // RepFlag::MinInteger => atom!("min_integer") + // RepFlag::MinInteger => atom!("min_integer"), + RepFlag::FfiLayout => atom!("ffi_layout"), + RepFlag::FfiAbi => atom!("ffi_abi"), } } } @@ -1065,6 +1132,8 @@ pub enum ExistenceError { SourceSink(HeapCellValue), Stream(HeapCellValue), Process(HeapCellValue), + FfiFunction(Atom), + FfiStructType(Atom), } #[derive(Debug)] diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index c1de6bf8..148a9d8f 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -1,7 +1,6 @@ use crate::arena::*; use crate::atom_table::*; use crate::forms::*; -use crate::functor_macro::*; use crate::heap_iter::*; use crate::heap_print::*; use crate::machine::attributed_variables::*; @@ -184,7 +183,7 @@ impl IndexMut for MachineState { } } -pub type CallResult = Result>; +pub type CallResult = Result; // size may be an upper bound. // true_size is calculated to compute the exact offset. diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 6d98a0bb..3958bdbc 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -4982,29 +4982,35 @@ impl Machine { }; let return_value = cell_as_atom_cell!(self.machine_st.heap[s + 2]); functions.push(FunctionDefinition { - name: name.as_str().to_string(), + name, args, return_value: return_value.get_name(), }); } _ => { - unreachable!() - } + let err = self.machine_st.unreachable_error(); + return Err(self.machine_st.error_form(err, stub_gen())) + } ) } if self .foreign_function_table .load_library(&library_name.as_str(), &functions) - .is_ok() + .is_err() { - return Ok(()); + self.machine_st.fail = true; } + + Ok(()) } - Err(e) => return Err(e), - }; + Err(e) => Err(e), + } + } else { + let err = self + .machine_st + .type_error(ValidType::InCharacter, library_name); + Err(self.machine_st.error_form(err, stub_gen())) } - self.machine_st.fail = true; - Ok(()) } #[cfg(not(feature = "ffi"))] @@ -5034,9 +5040,9 @@ impl Machine { if let Some(head) = iter.next() { let head = self.machine_st.store(self.machine_st.deref(head)); - if let Some(struct_name) = self.machine_st.value_to_str_like(head) { + if let Some(struct_name) = head.to_atom() { Ok(Value::Struct( - struct_name.as_str().to_string(), + struct_name, iter.map(|x| self.map_ffi_arg(x, stub_gen)) .collect::>()?, )) @@ -5052,17 +5058,15 @@ impl Machine { Err(self.machine_st.error_form(err, src)) } else { // first element of a struct needs to be the type - Err(self.machine_st.error_form( - self.machine_st.ffi_error(FfiError::ValueOutOfRange, head), - stub_gen(), - )) + let err = self.machine_st.type_error(ValidType::Atom, head); + Err(self.machine_st.error_form(err, stub_gen())) } } else { // empty list is an invalid struct repr - Err(self.machine_st.error_form( - self.machine_st.ffi_error(FfiError::ValueOutOfRange, source), - stub_gen(), - )) + let err = self + .machine_st + .domain_error(DomainErrorType::FfiStruct, source); + Err(self.machine_st.error_form(err, stub_gen())) } } else if self.machine_st.deref(source).is_var() { let err = self.machine_st.instantiation_error(); @@ -5075,10 +5079,10 @@ impl Machine { Err(self.machine_st.error_form(err, src)) } else { - Err(self.machine_st.error_form( - self.machine_st.ffi_error(FfiError::InvalidArgument, source), - stub_gen(), - )) + let err = self + .machine_st + .domain_error(DomainErrorType::FfiArgument, source); + Err(self.machine_st.error_form(err, stub_gen())) } } @@ -5090,10 +5094,10 @@ impl Machine { #[cfg(feature = "ffi")] { - let function_name_arg = self.deref_register(1); + let function_name_arg = self.machine_st.store(self.deref_register(1)); let args_reg = self.deref_register(2); let return_value = self.deref_register(3); - if let Some(function_name) = self.machine_st.value_to_str_like(function_name_arg) { + if let Some(function_name) = function_name_arg.to_atom() { match self.machine_st.try_from_list(args_reg, stub_gen) { Ok(args) => { let args = args @@ -5102,25 +5106,25 @@ impl Machine { .collect::, _>>()?; match self.foreign_function_table.exec( - &function_name.as_str(), + function_name, args, &mut self.machine_st.arena, ) { - Ok(result) => { - return self.unify_ffi_result(return_value, result); - } + Ok(result) => self.unify_ffi_result(return_value, result), Err(e) => { - let err = self.machine_st.ffi_error(e, function_name_arg); - return Err(self.machine_st.error_form(err, stub_gen())); + let err = self.machine_st.ffi_error(e); + Err(self.machine_st.error_form(err, stub_gen())) } } } - Err(e) => return Err(e), + Err(e) => Err(e), } + } else { + let err = self + .machine_st + .type_error(ValidType::Atom, function_name_arg); + Err(self.machine_st.error_form(err, stub_gen())) } - - self.machine_st.fail = true; - Ok(()) } #[cfg(not(feature = "ffi"))] @@ -5149,7 +5153,7 @@ impl Machine { }, Value::Struct(name, args) => { let struct_value = - resource_error_call_result!(self.machine_st, self.build_struct(&name, args)); + resource_error_call_result!(self.machine_st, self.build_struct(name, args)); unify!(self.machine_st, return_value, struct_value); } @@ -5166,8 +5170,8 @@ impl Machine { } #[cfg(feature = "ffi")] - fn build_struct(&mut self, name: &str, mut args: Vec) -> Result { - args.insert(0, Value::CString(CString::new(name).unwrap())); + fn build_struct(&mut self, name: Atom, mut args: Vec) -> Result { + args.insert(0, Value::CString(CString::new(&*name.as_str()).unwrap())); let cells: Vec<_> = args .into_iter() @@ -5183,7 +5187,7 @@ impl Machine { &self.machine_st.atom_tbl, &cstr.into_string().unwrap() )), - Value::Struct(name, struct_args) => self.build_struct(&name, struct_args)?, + Value::Struct(name, struct_args) => self.build_struct(name, struct_args)?, }) }) .collect::>()?; @@ -5199,9 +5203,9 @@ impl Machine { #[cfg(feature = "ffi")] { - let struct_name_arg = self.deref_register(1); + let struct_name_arg = self.machine_st.store(self.deref_register(1)); let fields_reg = self.deref_register(2); - if let Some(struct_name) = self.machine_st.value_to_str_like(struct_name_arg) { + if let Some(struct_name) = struct_name_arg.to_atom() { let fields: Vec = match self.machine_st.try_from_list(fields_reg, stub_gen) { Ok(addrs) => { let mut args = Vec::new(); @@ -5224,15 +5228,16 @@ impl Machine { Err(e) => return Err(e), }; self.foreign_function_table - .define_struct(&struct_name.as_str(), fields) + .define_struct(struct_name, fields) .map_err(|err| { - let ffi_error = self.machine_st.ffi_error(err, struct_name_arg); + let ffi_error = self.machine_st.ffi_error(err); self.machine_st.error_form(ffi_error, stub_gen()) })?; - return Ok(()); + Ok(()) + } else { + let err = self.machine_st.type_error(ValidType::Atom, struct_name_arg); + Err(self.machine_st.error_form(err, stub_gen())) } - self.machine_st.fail = true; - Ok(()) } #[cfg(not(feature = "ffi"))] @@ -5272,7 +5277,7 @@ impl Machine { ) { Ok(value) => value, Err(ffi_error) => { - let machine_error = self.machine_st.ffi_error(ffi_error, ffi_type_arg); + let machine_error = self.machine_st.ffi_error(ffi_error); return Err(self.machine_st.error_form(machine_error, stub_gen())); } }; @@ -5305,7 +5310,7 @@ impl Machine { .foreign_function_table .read_ptr(ffi_type, ptr, &mut self.machine_st.arena) .map_err(|ffi_error| { - let machine_error = self.machine_st.ffi_error(ffi_error, ffi_type_arg); + let machine_error = self.machine_st.ffi_error(ffi_error); self.machine_st.error_form(machine_error, stub_gen()) })?; @@ -5346,7 +5351,7 @@ impl Machine { { Ok(value) => value, Err(ffi_error) => { - let machine_error = self.machine_st.ffi_error(ffi_error, ffi_type_arg); + let machine_error = self.machine_st.ffi_error(ffi_error); return Err(self.machine_st.error_form(machine_error, stub_gen())); } }