From 6f3f66c4076968c8065b219f409b5f8c681731b9 Mon Sep 17 00:00:00 2001 From: Skgland Date: Sun, 24 Aug 2025 21:08:52 +0200 Subject: [PATCH] fix builds without ffi feature --- src/machine/dispatch.rs | 12 -- src/machine/machine_errors.rs | 14 ++ src/machine/system_calls.rs | 393 ++++++++++++++++++++-------------- 3 files changed, 241 insertions(+), 178 deletions(-) diff --git a/src/machine/dispatch.rs b/src/machine/dispatch.rs index 9143f2e1..4d3c7666 100644 --- a/src/machine/dispatch.rs +++ b/src/machine/dispatch.rs @@ -4302,62 +4302,50 @@ impl Machine { step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallLoadForeignLib => { - #[cfg(feature = "ffi")] try_or_throw!(self.machine_st, self.load_foreign_lib()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteLoadForeignLib => { - #[cfg(feature = "ffi")] try_or_throw!(self.machine_st, self.load_foreign_lib()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallForeignCall => { - #[cfg(feature = "ffi")] try_or_throw!(self.machine_st, self.foreign_call()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteForeignCall => { - #[cfg(feature = "ffi")] try_or_throw!(self.machine_st, self.foreign_call()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallDefineForeignStruct => { - #[cfg(feature = "ffi")] try_or_throw!(self.machine_st, self.define_foreign_struct()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteDefineForeignStruct => { - #[cfg(feature = "ffi")] try_or_throw!(self.machine_st, self.define_foreign_struct()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallFfiAllocate => { - #[cfg(feature = "ffi")] try_or_throw!(self.machine_st, self.ffi_allocate()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteFfiAllocate => { - #[cfg(feature = "ffi")] try_or_throw!(self.machine_st, self.ffi_allocate()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallFfiReadPtr => { - #[cfg(feature = "ffi")] try_or_throw!(self.machine_st, self.ffi_read_ptr()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteFfiReadPtr => { - #[cfg(feature = "ffi")] try_or_throw!(self.machine_st, self.ffi_read_ptr()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } &Instruction::CallFfiDeallocate => { - #[cfg(feature = "ffi")] try_or_throw!(self.machine_st, self.ffi_deallocate()); step_or_fail!(self, self.machine_st.p += 1); } &Instruction::ExecuteFfiDeallocate => { - #[cfg(feature = "ffi")] try_or_throw!(self.machine_st, self.ffi_deallocate()); step_or_fail!(self, self.machine_st.p = self.machine_st.cp); } diff --git a/src/machine/machine_errors.rs b/src/machine/machine_errors.rs index b8e23981..db16d377 100644 --- a/src/machine/machine_errors.rs +++ b/src/machine/machine_errors.rs @@ -603,6 +603,20 @@ impl MachineState { } } + pub(super) fn missing_feature_error(&self, feature: Atom) -> MachineError { + let stub = functor!( + atom!("resource_error"), + [functor( + (functor!(atom!("feature"), [atom_as_cell((feature))])) + )] + ); + + MachineError { + stub, + location: None, + } + } + pub(super) fn unreachable_error(&self) -> MachineError { let stub = functor!(atom!("system_error")); diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index 3f6d12ea..6d98a0bb 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -4952,57 +4952,69 @@ impl Machine { Ok(()) } - #[cfg(feature = "ffi")] #[inline(always)] pub(crate) fn load_foreign_lib(&mut self) -> CallResult { - let library_name = self.deref_register(1); - let args_reg = self.deref_register(2); - if let Some(library_name) = self.machine_st.value_to_str_like(library_name) { - let stub_gen = || functor_stub(atom!("use_foreign_module"), 2); - match self.machine_st.try_from_list(args_reg, stub_gen) { - Ok(addrs) => { - let mut functions = Vec::new(); - for heap_cell in addrs { - read_heap_cell!(heap_cell, - (HeapCellValueTag::Str, s) => { - let name = cell_as_atom_cell!(self.machine_st.heap[s]).get_name(); - let args: Vec = match self.machine_st.try_from_list(self.machine_st.heap[s + 1], stub_gen) { - Ok(addrs) => { - let mut args = Vec::new(); - for heap_cell in addrs { - args.push(cell_as_atom_cell!(heap_cell).get_name()); - } - args - } - Err(e) => return Err(e) - }; - let return_value = cell_as_atom_cell!(self.machine_st.heap[s + 2]); - functions.push(FunctionDefinition { - name: name.as_str().to_string(), - args, - return_value: return_value.get_name(), - }); - } - _ => { - unreachable!() + fn stub_gen() -> MachineStub { + functor_stub(atom!("$load_foreign_lib"), 2) + } + + #[cfg(feature = "ffi")] + { + let library_name = self.deref_register(1); + let args_reg = self.deref_register(2); + if let Some(library_name) = self.machine_st.value_to_str_like(library_name) { + match self.machine_st.try_from_list(args_reg, stub_gen) { + Ok(addrs) => { + let mut functions = Vec::new(); + for heap_cell in addrs { + read_heap_cell!(heap_cell, + (HeapCellValueTag::Str, s) => { + let name = cell_as_atom_cell!(self.machine_st.heap[s]).get_name(); + let args: Vec = match self.machine_st.try_from_list(self.machine_st.heap[s + 1], stub_gen) { + Ok(addrs) => { + let mut args = Vec::new(); + for heap_cell in addrs { + args.push(cell_as_atom_cell!(heap_cell).get_name()); + } + args + } + Err(e) => return Err(e) + }; + let return_value = cell_as_atom_cell!(self.machine_st.heap[s + 2]); + functions.push(FunctionDefinition { + name: name.as_str().to_string(), + args, + return_value: return_value.get_name(), + }); } - ) - } - if self - .foreign_function_table - .load_library(&library_name.as_str(), &functions) - .is_ok() - { - return Ok(()); + _ => { + unreachable!() + } + ) + } + if self + .foreign_function_table + .load_library(&library_name.as_str(), &functions) + .is_ok() + { + return Ok(()); + } } - } - Err(e) => return Err(e), - }; + Err(e) => return Err(e), + }; + } + self.machine_st.fail = true; + Ok(()) + } + + #[cfg(not(feature = "ffi"))] + { + let err = self.machine_st.missing_feature_error(atom!("ffi")); + Err(self.machine_st.error_form(err, stub_gen())) } - self.machine_st.fail = true; - Ok(()) } + #[cfg(feature = "ffi")] fn map_ffi_arg( &mut self, source: HeapCellValue, @@ -5070,46 +5082,55 @@ impl Machine { } } - #[cfg(feature = "ffi")] #[inline(always)] pub(crate) fn foreign_call(&mut self) -> CallResult { fn stub_gen() -> Vec { - functor_stub(atom!("foreign_call"), 3) - } - - let function_name_arg = 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) { - match self.machine_st.try_from_list(args_reg, stub_gen) { - Ok(args) => { - let args = args - .into_iter() - .map(|x| self.map_ffi_arg(x, stub_gen)) - .collect::, _>>()?; - - match self.foreign_function_table.exec( - &function_name.as_str(), - args, - &mut self.machine_st.arena, - ) { - Ok(result) => { - return 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())); + functor_stub(atom!("$foreign_call"), 3) + } + + #[cfg(feature = "ffi")] + { + let function_name_arg = 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) { + match self.machine_st.try_from_list(args_reg, stub_gen) { + Ok(args) => { + let args = args + .into_iter() + .map(|x| self.map_ffi_arg(x, stub_gen)) + .collect::, _>>()?; + + match self.foreign_function_table.exec( + &function_name.as_str(), + args, + &mut self.machine_st.arena, + ) { + Ok(result) => { + return 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())); + } } } + Err(e) => return Err(e), } - Err(e) => return Err(e), } + + self.machine_st.fail = true; + Ok(()) } - self.machine_st.fail = true; - Ok(()) + #[cfg(not(feature = "ffi"))] + { + let err = self.machine_st.missing_feature_error(atom!("ffi")); + Err(self.machine_st.error_form(err, stub_gen())) + } } + #[cfg(feature = "ffi")] fn unify_ffi_result(&mut self, return_value: HeapCellValue, result: Value) -> CallResult { match result { Value::Number(n) => match n { @@ -5170,133 +5191,173 @@ impl Machine { sized_iter_to_heap_list(&mut self.machine_st.heap, cells.len(), cells.into_iter()) } - #[cfg(feature = "ffi")] #[inline(always)] pub(crate) fn define_foreign_struct(&mut self) -> CallResult { fn stub_gen() -> MachineStub { functor_stub(atom!("$define_foreign_struct"), 2) } - let struct_name_arg = 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) { - let fields: Vec = match self.machine_st.try_from_list(fields_reg, stub_gen) { - Ok(addrs) => { - let mut args = Vec::new(); - for heap_cell in addrs { - let arg_cell = self.machine_st.store(self.machine_st.deref(heap_cell)); - let Some(arg) = arg_cell.to_atom() else { - let err = if arg_cell.is_var() { - self.machine_st.instantiation_error() - } else { - self.machine_st.type_error(ValidType::Atom, heap_cell) - }; + #[cfg(feature = "ffi")] + { + let struct_name_arg = 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) { + let fields: Vec = match self.machine_st.try_from_list(fields_reg, stub_gen) { + Ok(addrs) => { + let mut args = Vec::new(); + for heap_cell in addrs { + let arg_cell = self.machine_st.store(self.machine_st.deref(heap_cell)); + let Some(arg) = arg_cell.to_atom() else { + let err = if arg_cell.is_var() { + self.machine_st.instantiation_error() + } else { + self.machine_st.type_error(ValidType::Atom, heap_cell) + }; - return Err(self.machine_st.error_form(err, stub_gen())); - }; + return Err(self.machine_st.error_form(err, stub_gen())); + }; - args.push(arg); + args.push(arg); + } + args } - args - } - Err(e) => return Err(e), - }; - self.foreign_function_table - .define_struct(&struct_name.as_str(), fields) - .map_err(|err| { - let ffi_error = self.machine_st.ffi_error(err, struct_name_arg); - self.machine_st.error_form(ffi_error, stub_gen()) - })?; - return Ok(()); + Err(e) => return Err(e), + }; + self.foreign_function_table + .define_struct(&struct_name.as_str(), fields) + .map_err(|err| { + let ffi_error = self.machine_st.ffi_error(err, struct_name_arg); + self.machine_st.error_form(ffi_error, stub_gen()) + })?; + return Ok(()); + } + self.machine_st.fail = true; + Ok(()) + } + + #[cfg(not(feature = "ffi"))] + { + let err = self.machine_st.missing_feature_error(atom!("ffi")); + Err(self.machine_st.error_form(err, stub_gen())) } - self.machine_st.fail = true; - Ok(()) } pub(crate) fn ffi_allocate(&mut self) -> CallResult { - let stub_gen = || functor_stub(atom!("$ffi_allocate"), 4); + fn stub_gen() -> MachineStub { + functor_stub(atom!("$ffi_allocate"), 4) + } - let allocator = self.deref_register(1); - let ffi_type_arg = self.deref_register(2); - let ffi_type = ffi_type_arg.to_atom().unwrap(); - let args = self.deref_register(3); - let return_value = self.deref_register(4); + #[cfg(feature = "ffi")] + { + let allocator = self.deref_register(1); + let ffi_type_arg = self.deref_register(2); + let ffi_type = ffi_type_arg.to_atom().unwrap(); + let args = self.deref_register(3); + let return_value = self.deref_register(4); + + let allocator = FfiAllocator::try_from(allocator.to_atom().unwrap()).map_err(|_| { + let machine_error = self + .machine_st + .domain_error(DomainErrorType::Allocator, allocator); + self.machine_st.error_form(machine_error, stub_gen()) + })?; - let allocator = FfiAllocator::try_from(allocator.to_atom().unwrap()).map_err(|_| { - let machine_error = self - .machine_st - .domain_error(DomainErrorType::Allocator, allocator); - self.machine_st.error_form(machine_error, stub_gen()) - })?; + let args = self.map_ffi_arg(args, stub_gen)?; - let args = self.map_ffi_arg(args, stub_gen)?; + let value = match self.foreign_function_table.allocate( + allocator, + ffi_type, + args, + &mut self.machine_st.arena, + ) { + Ok(value) => value, + Err(ffi_error) => { + let machine_error = self.machine_st.ffi_error(ffi_error, ffi_type_arg); + return Err(self.machine_st.error_form(machine_error, stub_gen())); + } + }; - let value = match self.foreign_function_table.allocate( - allocator, - ffi_type, - args, - &mut self.machine_st.arena, - ) { - Ok(value) => value, - Err(ffi_error) => { - let machine_error = self.machine_st.ffi_error(ffi_error, ffi_type_arg); - return Err(self.machine_st.error_form(machine_error, stub_gen())); - } - }; + self.unify_ffi_result(return_value, value) + } - self.unify_ffi_result(return_value, value) + #[cfg(not(feature = "ffi"))] + { + let err = self.machine_st.missing_feature_error(atom!("ffi")); + Err(self.machine_st.error_form(err, stub_gen())) + } } pub(crate) fn ffi_read_ptr(&mut self) -> CallResult { - let stub_gen = || functor_stub(atom!("$ffi_read_ptr"), 3); - - let ffi_type_arg = self.deref_register(1); - let ffi_type = ffi_type_arg.to_atom().unwrap(); - let ptr = self.deref_register(2); - let return_value = self.deref_register(3); + fn stub_gen() -> MachineStub { + functor_stub(atom!("$ffi_read_ptr"), 3) + } - let ptr = self.map_ffi_arg(ptr, stub_gen)?; + #[cfg(feature = "ffi")] + { + let ffi_type_arg = self.deref_register(1); + let ffi_type = ffi_type_arg.to_atom().unwrap(); + let ptr = self.deref_register(2); + let return_value = self.deref_register(3); + + let ptr = self.map_ffi_arg(ptr, stub_gen)?; + + let value = self + .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); + self.machine_st.error_form(machine_error, stub_gen()) + })?; - let value = self - .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); - self.machine_st.error_form(machine_error, stub_gen()) - })?; + self.unify_ffi_result(return_value, value) + } - self.unify_ffi_result(return_value, value) + #[cfg(not(feature = "ffi"))] + { + let err = self.machine_st.missing_feature_error(atom!("ffi")); + Err(self.machine_st.error_form(err, stub_gen())) + } } pub(crate) fn ffi_deallocate(&mut self) -> CallResult { - let stub_gen = || functor_stub(atom!("$ffi_deallocate"), 3); + fn stub_gen() -> MachineStub { + functor_stub(atom!("$ffi_deallocate"), 3) + } - let allocator = self.deref_register(1); - let ffi_type_arg = self.deref_register(2); - let ffi_type = ffi_type_arg.to_atom().unwrap(); - let ptr = self.deref_register(3); + #[cfg(feature = "ffi")] + { + let allocator = self.deref_register(1); + let ffi_type_arg = self.deref_register(2); + let ffi_type = ffi_type_arg.to_atom().unwrap(); + let ptr = self.deref_register(3); - let allocator = FfiAllocator::try_from(allocator.to_atom().unwrap()).map_err(|_| { - let machine_error = self - .machine_st - .domain_error(DomainErrorType::Allocator, allocator); - self.machine_st.error_form(machine_error, stub_gen()) - })?; + let allocator = FfiAllocator::try_from(allocator.to_atom().unwrap()).map_err(|_| { + let machine_error = self + .machine_st + .domain_error(DomainErrorType::Allocator, allocator); + self.machine_st.error_form(machine_error, stub_gen()) + })?; - let ptr = self.map_ffi_arg(ptr, stub_gen)?; + let ptr = self.map_ffi_arg(ptr, stub_gen)?; - match self - .foreign_function_table - .deallocate(allocator, ffi_type, ptr) - { - Ok(value) => value, - Err(ffi_error) => { - let machine_error = self.machine_st.ffi_error(ffi_error, ffi_type_arg); - return Err(self.machine_st.error_form(machine_error, stub_gen())); + match self + .foreign_function_table + .deallocate(allocator, ffi_type, ptr) + { + Ok(value) => value, + Err(ffi_error) => { + let machine_error = self.machine_st.ffi_error(ffi_error, ffi_type_arg); + return Err(self.machine_st.error_form(machine_error, stub_gen())); + } } + Ok(()) } - Ok(()) + #[cfg(not(feature = "ffi"))] + { + let err = self.machine_st.missing_feature_error(atom!("ffi")); + Err(self.machine_st.error_form(err, stub_gen())) + } } #[cfg(not(target_arch = "wasm32"))] -- 2.54.0