fn build(
&self,
+ name: Atom,
structs_table: &HashMap<Atom, StructImpl>,
struct_args: &mut [Value],
) -> Result<FfiStruct, FfiError> {
- let args = ArgValue::build_args(struct_args, &self.fields, structs_table)?;
+ let args = ArgValue::build_args(
+ name,
+ ArgCountMismatchKind::Struct,
+ struct_args,
+ &self.fields,
+ structs_table,
+ )?;
let alloc = FfiStruct::new(self.layout()?, FfiAllocator::Rust)?;
return Err(FfiError::StructNotFound(*arg_type_name));
};
- Ok(Self::Struct(struct_type.build(structs_table, args)?))
+ Ok(Self::Struct(struct_type.build(
+ *arg_type_name,
+ structs_table,
+ args,
+ )?))
}
FfiType::Void => Err(FfiError::VoidArgumentType),
}
}
fn build_args(
+ name: Atom,
+ kind: ArgCountMismatchKind,
args: &'val mut [Value],
types: &[FfiType],
structs_table: &HashMap<Atom, StructImpl>,
) -> Result<Vec<Self>, FfiError> {
if types.len() != args.len() {
- return Err(FfiError::ArgCountMismatch);
+ return Err(FfiError::ArgCountMismatch {
+ name,
+ kind,
+ expected: types.len(),
+ got: args.len(),
+ });
}
args.iter_mut()
let fn_impl = self
.table
.get(&fn_name)
- .ok_or(FfiError::FunctionNotFound(fn_name))?;
+ .ok_or(FfiError::FunctionNotFound(fn_name, args.len()))?;
- let args = ArgValue::build_args(&mut args, &fn_impl.args, &self.structs)?;
+ let args = ArgValue::build_args(
+ fn_name,
+ ArgCountMismatchKind::Function,
+ &mut args,
+ &fn_impl.args,
+ &self.structs,
+ )?;
let args = PointerArgs::new(&args);
let (_, args) = args.as_struct()?;
- let ffi_struct = struct_impl.build(&self.structs, args)?;
+ let ffi_struct = struct_impl.build(kind, &self.structs, args)?;
let ptr = ManuallyDrop::new(ffi_struct).ptr;
ValueCast(Atom, Atom),
ValueOutOfRange(DomainErrorType, Value),
VoidArgumentType,
- FunctionNotFound(Atom),
+ FunctionNotFound(Atom, usize),
StructNotFound(Atom),
- ArgCountMismatch,
+ ArgCountMismatch {
+ name: Atom, // ffi function or struct
+ kind: ArgCountMismatchKind,
+ expected: usize,
+ got: usize,
+ },
AllocationFailed,
// LayoutError should never occour
LayoutError,
NullPtr,
}
+#[derive(Debug)]
+pub(crate) enum ArgCountMismatchKind {
+ Function,
+ Struct,
+}
+
impl std::fmt::Display for FfiError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Debug::fmt(self, f)
location: None,
}
}
- ExistenceError::FfiFunction(atom) => {
+ ExistenceError::FfiFunction(name, arity) => {
+ let culprit = functor!(atom!("/"), [atom_as_cell(name), fixnum(arity)]);
let stub = functor!(
atom!("existence_error"),
- [atom_as_cell((atom!("ffi_function"))), atom_as_cell(atom)]
+ [atom_as_cell((atom!("ffi_function"))), functor(culprit)]
+ );
+
+ MachineError {
+ stub,
+ location: None,
+ }
+ }
+ ExistenceError::FfiStructConstructor(name, arity) => {
+ let culprit = functor!(atom!("/"), [atom_as_cell(name), fixnum(arity)]);
+ let stub = functor!(
+ atom!("existence_error"),
+ [
+ atom_as_cell((atom!("ffi_struct_constructor"))),
+ functor(culprit)
+ ]
);
MachineError {
}
}
FfiError::ValueOutOfRange(domain, culprit) => self.domain_error(domain, culprit),
- FfiError::FunctionNotFound(name) => {
- self.existence_error(ExistenceError::FfiFunction(name))
+ FfiError::FunctionNotFound(name, arity) => {
+ self.existence_error(ExistenceError::FfiFunction(name, arity))
}
FfiError::StructNotFound(name) => {
self.existence_error(ExistenceError::FfiStructType(name))
}
- FfiError::ArgCountMismatch => self.unreachable_error(),
+ FfiError::ArgCountMismatch {
+ name,
+ kind,
+ expected: _,
+ got,
+ } => match kind {
+ ffi::ArgCountMismatchKind::Function => {
+ self.existence_error(ExistenceError::FfiFunction(name, got))
+ }
+ ffi::ArgCountMismatchKind::Struct => {
+ self.existence_error(ExistenceError::FfiStructConstructor(name, got))
+ }
+ },
FfiError::AllocationFailed => MachineError {
stub: functor!(atom!("resource_error"), [atom_as_cell((atom!("heap")))]),
location: None,
SourceSink(HeapCellValue),
Stream(HeapCellValue),
Process(HeapCellValue),
- FfiFunction(Atom),
+ FfiFunction(Atom, usize),
+ FfiStructConstructor(Atom, usize),
FfiStructType(Atom),
}