make ffi support full {i,u}64 range
This commit is contained in:
105
src/ffi.rs
105
src/ffi.rs
@@ -19,12 +19,16 @@ and for each field: we add to the pointer until we're aligned to the next data t
|
|||||||
and finally we add the pointer the size of what we've written.
|
and finally we add the pointer the size of what we've written.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use crate::arena::Arena;
|
||||||
use crate::atom_table::Atom;
|
use crate::atom_table::Atom;
|
||||||
|
use crate::forms::Number;
|
||||||
|
use crate::parser::ast::Fixnum;
|
||||||
|
|
||||||
|
use dashu::Integer;
|
||||||
|
use ordered_float::OrderedFloat;
|
||||||
use std::alloc::{self, Layout};
|
use std::alloc::{self, Layout};
|
||||||
use std::any::Any;
|
use std::any::Any;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::convert::TryFrom;
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::ffi::{c_void, CString};
|
use std::ffi::{c_void, CString};
|
||||||
use std::ptr::addr_of_mut;
|
use std::ptr::addr_of_mut;
|
||||||
@@ -189,8 +193,7 @@ impl ForeignFunctionTable {
|
|||||||
unsafe {
|
unsafe {
|
||||||
macro_rules! push_int {
|
macro_rules! push_int {
|
||||||
($type:ty) => {{
|
($type:ty) => {{
|
||||||
let n: $type = <$type>::try_from(args[i].as_int()?)
|
let n: $type = args[i].as_int()?;
|
||||||
.map_err(|_| FFIError::ValueDontFit)?;
|
|
||||||
let mut box_value = Box::new(n) as Box<dyn Any>;
|
let mut box_value = Box::new(n) as Box<dyn Any>;
|
||||||
pointers.push(&mut *box_value as *mut _ as *mut c_void);
|
pointers.push(&mut *box_value as *mut _ as *mut c_void);
|
||||||
_memory.push(box_value);
|
_memory.push(box_value);
|
||||||
@@ -263,8 +266,7 @@ impl ForeignFunctionTable {
|
|||||||
($type:ty) => {{
|
($type:ty) => {{
|
||||||
field_ptr = field_ptr
|
field_ptr = field_ptr
|
||||||
.add(field_ptr.align_offset(std::mem::align_of::<$type>()));
|
.add(field_ptr.align_offset(std::mem::align_of::<$type>()));
|
||||||
let n: $type = <$type>::try_from(struct_args[i].as_int()?)
|
let n: $type = struct_args[i].as_int()?;
|
||||||
.map_err(|_| FFIError::ValueDontFit)?;
|
|
||||||
std::ptr::write(field_ptr as *mut $type, n);
|
std::ptr::write(field_ptr as *mut $type, n);
|
||||||
field_ptr = field_ptr.add(std::mem::size_of::<$type>());
|
field_ptr = field_ptr.add(std::mem::size_of::<$type>());
|
||||||
}};
|
}};
|
||||||
@@ -327,7 +329,12 @@ impl ForeignFunctionTable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn exec(&mut self, name: &str, mut args: Vec<Value>) -> Result<Value, FFIError> {
|
pub fn exec(
|
||||||
|
&mut self,
|
||||||
|
name: &str,
|
||||||
|
mut args: Vec<Value>,
|
||||||
|
arena: &mut Arena,
|
||||||
|
) -> Result<Value, FFIError> {
|
||||||
let function_impl = self.table.get_mut(name).ok_or(FFIError::FunctionNotFound)?;
|
let function_impl = self.table.get_mut(name).ok_or(FFIError::FunctionNotFound)?;
|
||||||
let mut pointer_args =
|
let mut pointer_args =
|
||||||
Self::build_pointer_args(&mut args, &function_impl.args, &mut self.structs)?;
|
Self::build_pointer_args(&mut args, &function_impl.args, &mut self.structs)?;
|
||||||
@@ -335,14 +342,14 @@ impl ForeignFunctionTable {
|
|||||||
unsafe {
|
unsafe {
|
||||||
macro_rules! call_and_return {
|
macro_rules! call_and_return {
|
||||||
($type:ty) => {{
|
($type:ty) => {{
|
||||||
let mut n: Box<$type> = Box::new(0);
|
let mut n: $type = 0;
|
||||||
libffi::raw::ffi_call(
|
libffi::raw::ffi_call(
|
||||||
&mut function_impl.cif,
|
&mut function_impl.cif,
|
||||||
Some(*function_impl.code_ptr.as_safe_fun()),
|
Some(*function_impl.code_ptr.as_safe_fun()),
|
||||||
&mut *n as *mut _ as *mut c_void,
|
&mut n as *mut _ as *mut c_void,
|
||||||
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void,
|
pointer_args.pointers.as_mut_ptr() as *mut *mut c_void,
|
||||||
);
|
);
|
||||||
Ok(Value::Int(i64::from(*n)))
|
Ok(Value::Number(fixnum!(Number, n, arena)))
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -354,50 +361,37 @@ impl ForeignFunctionTable {
|
|||||||
libffi::raw::FFI_TYPE_SINT16 => call_and_return!(i16),
|
libffi::raw::FFI_TYPE_SINT16 => call_and_return!(i16),
|
||||||
libffi::raw::FFI_TYPE_UINT32 => call_and_return!(u32),
|
libffi::raw::FFI_TYPE_UINT32 => call_and_return!(u32),
|
||||||
libffi::raw::FFI_TYPE_SINT32 => call_and_return!(i32),
|
libffi::raw::FFI_TYPE_SINT32 => call_and_return!(i32),
|
||||||
libffi::raw::FFI_TYPE_UINT64 => {
|
libffi::raw::FFI_TYPE_UINT64 => call_and_return!(u64),
|
||||||
let mut n: Box<u64> = Box::new(0);
|
|
||||||
libffi::raw::ffi_call(
|
|
||||||
&mut function_impl.cif,
|
|
||||||
Some(*function_impl.code_ptr.as_safe_fun()),
|
|
||||||
&mut *n as *mut _ as *mut c_void,
|
|
||||||
pointer_args.pointers.as_mut_ptr(),
|
|
||||||
);
|
|
||||||
Ok(Value::Int(
|
|
||||||
i64::try_from(*n).map_err(|_| FFIError::ValueDontFit)?,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
libffi::raw::FFI_TYPE_SINT64 => call_and_return!(i64),
|
libffi::raw::FFI_TYPE_SINT64 => call_and_return!(i64),
|
||||||
libffi::raw::FFI_TYPE_POINTER => {
|
libffi::raw::FFI_TYPE_POINTER => {
|
||||||
let mut n: Box<*mut c_void> = Box::new(std::ptr::null_mut());
|
let mut n: *mut c_void = std::ptr::null_mut();
|
||||||
libffi::raw::ffi_call(
|
libffi::raw::ffi_call(
|
||||||
&mut function_impl.cif,
|
&mut function_impl.cif,
|
||||||
Some(*function_impl.code_ptr.as_safe_fun()),
|
Some(*function_impl.code_ptr.as_safe_fun()),
|
||||||
&mut *n as *mut _ as *mut c_void,
|
&mut n as *mut *mut c_void as *mut c_void,
|
||||||
pointer_args.pointers.as_mut_ptr(),
|
pointer_args.pointers.as_mut_ptr(),
|
||||||
);
|
);
|
||||||
Ok(Value::Int(
|
Ok(Value::Number(fixnum!(Number, n as isize, arena)))
|
||||||
i64::try_from(*n as isize).map_err(|_| FFIError::ValueDontFit)?,
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
libffi::raw::FFI_TYPE_FLOAT => {
|
libffi::raw::FFI_TYPE_FLOAT => {
|
||||||
let mut n: Box<f32> = Box::new(0.0);
|
let mut n: f32 = 0.0;
|
||||||
libffi::raw::ffi_call(
|
libffi::raw::ffi_call(
|
||||||
&mut function_impl.cif,
|
&mut function_impl.cif,
|
||||||
Some(*function_impl.code_ptr.as_safe_fun()),
|
Some(*function_impl.code_ptr.as_safe_fun()),
|
||||||
&mut *n as *mut _ as *mut c_void,
|
&mut n as *mut _ as *mut c_void,
|
||||||
pointer_args.pointers.as_mut_ptr(),
|
pointer_args.pointers.as_mut_ptr(),
|
||||||
);
|
);
|
||||||
Ok(Value::Float((*n).into()))
|
Ok(Value::Number(Number::Float(OrderedFloat(n.into()))))
|
||||||
}
|
}
|
||||||
libffi::raw::FFI_TYPE_DOUBLE => {
|
libffi::raw::FFI_TYPE_DOUBLE => {
|
||||||
let mut n: Box<f64> = Box::new(0.0);
|
let mut n: f64 = 0.0;
|
||||||
libffi::raw::ffi_call(
|
libffi::raw::ffi_call(
|
||||||
&mut function_impl.cif,
|
&mut function_impl.cif,
|
||||||
Some(*function_impl.code_ptr.as_safe_fun()),
|
Some(*function_impl.code_ptr.as_safe_fun()),
|
||||||
&mut *n as *mut _ as *mut c_void,
|
&mut n as *mut _ as *mut c_void,
|
||||||
pointer_args.pointers.as_mut_ptr(),
|
pointer_args.pointers.as_mut_ptr(),
|
||||||
);
|
);
|
||||||
Ok(Value::Float(*n))
|
Ok(Value::Number(Number::Float(OrderedFloat(n))))
|
||||||
}
|
}
|
||||||
libffi::raw::FFI_TYPE_STRUCT => {
|
libffi::raw::FFI_TYPE_STRUCT => {
|
||||||
let name = &function_impl
|
let name = &function_impl
|
||||||
@@ -422,7 +416,7 @@ impl ForeignFunctionTable {
|
|||||||
&mut *ptr as *mut _,
|
&mut *ptr as *mut _,
|
||||||
pointer_args.pointers.as_mut_ptr(),
|
pointer_args.pointers.as_mut_ptr(),
|
||||||
);
|
);
|
||||||
let struct_val = self.read_struct(ptr, name, struct_type);
|
let struct_val = self.read_struct(ptr, name, struct_type, arena);
|
||||||
#[allow(clippy::from_raw_with_void_ptr)]
|
#[allow(clippy::from_raw_with_void_ptr)]
|
||||||
drop(Box::from_raw(ptr));
|
drop(Box::from_raw(ptr));
|
||||||
struct_val
|
struct_val
|
||||||
@@ -437,6 +431,7 @@ impl ForeignFunctionTable {
|
|||||||
ptr: *mut c_void,
|
ptr: *mut c_void,
|
||||||
name: &str,
|
name: &str,
|
||||||
struct_type: &StructImpl,
|
struct_type: &StructImpl,
|
||||||
|
arena: &mut Arena,
|
||||||
) -> Result<Value, FFIError> {
|
) -> Result<Value, FFIError> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut returns = Vec::new();
|
let mut returns = Vec::new();
|
||||||
@@ -450,7 +445,7 @@ impl ForeignFunctionTable {
|
|||||||
field_ptr =
|
field_ptr =
|
||||||
field_ptr.add(field_ptr.align_offset(std::mem::align_of::<$type>()));
|
field_ptr.add(field_ptr.align_offset(std::mem::align_of::<$type>()));
|
||||||
let n = std::ptr::read(field_ptr as *mut $type);
|
let n = std::ptr::read(field_ptr as *mut $type);
|
||||||
returns.push(Value::Int(i64::from(n)));
|
returns.push(Value::Number(fixnum!(Number, n, arena)));
|
||||||
field_ptr = field_ptr.add(std::mem::size_of::<$type>());
|
field_ptr = field_ptr.add(std::mem::size_of::<$type>());
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
@@ -462,29 +457,21 @@ impl ForeignFunctionTable {
|
|||||||
libffi::raw::FFI_TYPE_SINT16 => read_and_push_int!(i16),
|
libffi::raw::FFI_TYPE_SINT16 => read_and_push_int!(i16),
|
||||||
libffi::raw::FFI_TYPE_UINT32 => read_and_push_int!(u32),
|
libffi::raw::FFI_TYPE_UINT32 => read_and_push_int!(u32),
|
||||||
libffi::raw::FFI_TYPE_SINT32 => read_and_push_int!(i32),
|
libffi::raw::FFI_TYPE_SINT32 => read_and_push_int!(i32),
|
||||||
libffi::raw::FFI_TYPE_UINT64 => {
|
libffi::raw::FFI_TYPE_UINT64 => read_and_push_int!(u64),
|
||||||
field_ptr =
|
|
||||||
field_ptr.add(field_ptr.align_offset(std::mem::align_of::<u64>()));
|
|
||||||
let n = std::ptr::read(field_ptr as *mut u64);
|
|
||||||
returns.push(Value::Int(
|
|
||||||
i64::try_from(n).map_err(|_| FFIError::ValueDontFit)?,
|
|
||||||
));
|
|
||||||
field_ptr = field_ptr.add(std::mem::size_of::<u64>());
|
|
||||||
}
|
|
||||||
libffi::raw::FFI_TYPE_SINT64 => read_and_push_int!(i64),
|
libffi::raw::FFI_TYPE_SINT64 => read_and_push_int!(i64),
|
||||||
libffi::raw::FFI_TYPE_POINTER => read_and_push_int!(i64),
|
libffi::raw::FFI_TYPE_POINTER => read_and_push_int!(i64),
|
||||||
libffi::raw::FFI_TYPE_FLOAT => {
|
libffi::raw::FFI_TYPE_FLOAT => {
|
||||||
field_ptr =
|
field_ptr =
|
||||||
field_ptr.add(field_ptr.align_offset(std::mem::align_of::<f32>()));
|
field_ptr.add(field_ptr.align_offset(std::mem::align_of::<f32>()));
|
||||||
let n: f32 = std::ptr::read(field_ptr as *mut f32);
|
let n: f32 = std::ptr::read(field_ptr as *mut f32);
|
||||||
returns.push(Value::Float(n.into()));
|
returns.push(Value::Number(Number::Float(OrderedFloat(n.into()))));
|
||||||
field_ptr = field_ptr.add(std::mem::size_of::<f32>());
|
field_ptr = field_ptr.add(std::mem::size_of::<f32>());
|
||||||
}
|
}
|
||||||
libffi::raw::FFI_TYPE_DOUBLE => {
|
libffi::raw::FFI_TYPE_DOUBLE => {
|
||||||
field_ptr =
|
field_ptr =
|
||||||
field_ptr.add(field_ptr.align_offset(std::mem::align_of::<f64>()));
|
field_ptr.add(field_ptr.align_offset(std::mem::align_of::<f64>()));
|
||||||
let n: f64 = std::ptr::read(field_ptr as *mut f64);
|
let n: f64 = std::ptr::read(field_ptr as *mut f64);
|
||||||
returns.push(Value::Float(n));
|
returns.push(Value::Number(Number::Float(OrderedFloat(n))));
|
||||||
field_ptr = field_ptr.add(std::mem::size_of::<f64>());
|
field_ptr = field_ptr.add(std::mem::size_of::<f64>());
|
||||||
}
|
}
|
||||||
libffi::raw::FFI_TYPE_STRUCT => {
|
libffi::raw::FFI_TYPE_STRUCT => {
|
||||||
@@ -495,7 +482,8 @@ impl ForeignFunctionTable {
|
|||||||
.ok_or(FFIError::StructNotFound)?;
|
.ok_or(FFIError::StructNotFound)?;
|
||||||
field_ptr = field_ptr
|
field_ptr = field_ptr
|
||||||
.add(field_ptr.align_offset(struct_type.ffi_type.alignment as usize));
|
.add(field_ptr.align_offset(struct_type.ffi_type.alignment as usize));
|
||||||
let struct_val = self.read_struct(field_ptr, &substruct, struct_type);
|
let struct_val =
|
||||||
|
self.read_struct(field_ptr, &substruct, struct_type, arena);
|
||||||
returns.push(struct_val?);
|
returns.push(struct_val?);
|
||||||
field_ptr = field_ptr.add(struct_type.ffi_type.size);
|
field_ptr = field_ptr.add(struct_type.ffi_type.size);
|
||||||
}
|
}
|
||||||
@@ -511,24 +499,33 @@ impl ForeignFunctionTable {
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Int(i64),
|
Number(Number),
|
||||||
Float(f64),
|
|
||||||
CString(CString),
|
CString(CString),
|
||||||
Struct(String, Vec<Value>),
|
Struct(String, Vec<Value>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Value {
|
impl Value {
|
||||||
fn as_int(&self) -> Result<i64, FFIError> {
|
fn as_int<I>(&self) -> Result<I, FFIError>
|
||||||
|
where
|
||||||
|
Integer: TryInto<I>,
|
||||||
|
i64: TryInto<I>,
|
||||||
|
{
|
||||||
match self {
|
match self {
|
||||||
Value::Int(n) => Ok(*n),
|
Value::Number(Number::Integer(ibig_ptr)) => {
|
||||||
|
let ibig: &Integer = ibig_ptr;
|
||||||
|
ibig.clone().try_into().map_err(|_| FFIError::ValueDontFit)
|
||||||
|
}
|
||||||
|
Value::Number(Number::Fixnum(fixnum)) => fixnum
|
||||||
|
.get_num()
|
||||||
|
.try_into()
|
||||||
|
.map_err(|_| FFIError::ValueDontFit),
|
||||||
_ => Err(FFIError::ValueCast),
|
_ => Err(FFIError::ValueCast),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn as_float(&self) -> Result<f64, FFIError> {
|
fn as_float(&self) -> Result<f64, FFIError> {
|
||||||
match self {
|
match self {
|
||||||
Value::Float(n) => Ok(*n),
|
&Value::Number(Number::Float(OrderedFloat(f))) => Ok(f),
|
||||||
Value::Int(n) => Ok(*n as f64),
|
|
||||||
_ => Err(FFIError::ValueCast),
|
_ => Err(FFIError::ValueCast),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -536,7 +533,9 @@ impl Value {
|
|||||||
fn as_ptr(&mut self) -> Result<*mut c_void, FFIError> {
|
fn as_ptr(&mut self) -> Result<*mut c_void, FFIError> {
|
||||||
match self {
|
match self {
|
||||||
Value::CString(ref mut cstr) => Ok(&mut *cstr as *mut _ as *mut c_void),
|
Value::CString(ref mut cstr) => Ok(&mut *cstr as *mut _ as *mut c_void),
|
||||||
Value::Int(n) => Ok(std::ptr::with_exposed_provenance_mut(*n as usize)),
|
Value::Number(Number::Fixnum(fixnum)) => Ok(std::ptr::with_exposed_provenance_mut(
|
||||||
|
fixnum.get_num() as usize,
|
||||||
|
)),
|
||||||
_ => Err(FFIError::ValueCast),
|
_ => Err(FFIError::ValueCast),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5002,8 +5002,6 @@ impl Machine {
|
|||||||
#[cfg(feature = "ffi")]
|
#[cfg(feature = "ffi")]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub(crate) fn foreign_call(&mut self) -> CallResult {
|
pub(crate) fn foreign_call(&mut self) -> CallResult {
|
||||||
use dashu::integer::IBig;
|
|
||||||
|
|
||||||
let function_name = self.deref_register(1);
|
let function_name = self.deref_register(1);
|
||||||
let args_reg = self.deref_register(2);
|
let args_reg = self.deref_register(2);
|
||||||
let return_value = self.deref_register(3);
|
let return_value = self.deref_register(3);
|
||||||
@@ -5011,8 +5009,7 @@ impl Machine {
|
|||||||
let stub_gen = || functor_stub(atom!("foreign_call"), 3);
|
let stub_gen = || functor_stub(atom!("foreign_call"), 3);
|
||||||
fn map_arg(machine_st: &mut MachineState, source: HeapCellValue) -> crate::ffi::Value {
|
fn map_arg(machine_st: &mut MachineState, source: HeapCellValue) -> crate::ffi::Value {
|
||||||
match Number::try_from((source, &machine_st.arena.f64_tbl)) {
|
match Number::try_from((source, &machine_st.arena.f64_tbl)) {
|
||||||
Ok(Number::Fixnum(n)) => Value::Int(n.get_num()),
|
Ok(number) => Value::Number(number),
|
||||||
Ok(Number::Float(n)) => Value::Float(n.into_inner()),
|
|
||||||
_ => {
|
_ => {
|
||||||
let stub_gen = || functor_stub(atom!("foreign_call"), 3);
|
let stub_gen = || functor_stub(atom!("foreign_call"), 3);
|
||||||
if let Some(string) = machine_st.value_to_str_like(source) {
|
if let Some(string) = machine_st.value_to_str_like(source) {
|
||||||
@@ -5047,28 +5044,29 @@ impl Machine {
|
|||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|x| map_arg(&mut self.machine_st, x))
|
.map(|x| map_arg(&mut self.machine_st, x))
|
||||||
.collect();
|
.collect();
|
||||||
match self
|
match self.foreign_function_table.exec(
|
||||||
.foreign_function_table
|
&function_name.as_str(),
|
||||||
.exec(&function_name.as_str(), args)
|
args,
|
||||||
{
|
&mut self.machine_st.arena,
|
||||||
|
) {
|
||||||
Ok(result) => {
|
Ok(result) => {
|
||||||
match result {
|
match result {
|
||||||
Value::Int(n) => {
|
Value::Number(n) => match n {
|
||||||
if let Ok(fixnum) = Fixnum::build_with_checked(n) {
|
Number::Float(OrderedFloat(n)) => {
|
||||||
self.machine_st.unify_fixnum(fixnum, return_value)
|
|
||||||
} else {
|
|
||||||
let bigint = IBig::from(n);
|
|
||||||
let bigint = arena_alloc!(
|
|
||||||
bigint.clone(),
|
|
||||||
&mut self.machine_st.arena
|
|
||||||
);
|
|
||||||
self.machine_st.unify_big_int(bigint, return_value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Value::Float(n) => {
|
|
||||||
let n = float_alloc!(n, self.machine_st.arena);
|
let n = float_alloc!(n, self.machine_st.arena);
|
||||||
self.machine_st.unify_f64(n, return_value)
|
self.machine_st.unify_f64(n, return_value)
|
||||||
}
|
}
|
||||||
|
Number::Integer(typed_arena_ptr) => {
|
||||||
|
self.machine_st.unify_big_int(typed_arena_ptr, return_value)
|
||||||
|
}
|
||||||
|
Number::Rational(typed_arena_ptr) => {
|
||||||
|
self.machine_st
|
||||||
|
.unify_rational(typed_arena_ptr, return_value);
|
||||||
|
}
|
||||||
|
Number::Fixnum(fixnum) => {
|
||||||
|
self.machine_st.unify_fixnum(fixnum, return_value)
|
||||||
|
}
|
||||||
|
},
|
||||||
Value::Struct(name, args) => {
|
Value::Struct(name, args) => {
|
||||||
let struct_value = resource_error_call_result!(
|
let struct_value = resource_error_call_result!(
|
||||||
self.machine_st,
|
self.machine_st,
|
||||||
@@ -5108,34 +5106,26 @@ impl Machine {
|
|||||||
fn build_struct(&mut self, name: &str, mut args: Vec<Value>) -> Result<HeapCellValue, usize> {
|
fn build_struct(&mut self, name: &str, mut args: Vec<Value>) -> Result<HeapCellValue, usize> {
|
||||||
args.insert(0, Value::CString(CString::new(name).unwrap()));
|
args.insert(0, Value::CString(CString::new(name).unwrap()));
|
||||||
|
|
||||||
let mut expanded_args = Vec::with_capacity(args.len());
|
let cells: Vec<_> = args
|
||||||
|
.into_iter()
|
||||||
for val in args {
|
.map(|val| {
|
||||||
expanded_args.push(match val {
|
Ok(match val {
|
||||||
Value::Int(n) => {
|
Value::Number(n) => match n {
|
||||||
if let Ok(fixnum) = Fixnum::build_with_checked(n) {
|
Number::Float(OrderedFloat(f)) => {
|
||||||
fixnum_as_cell!(fixnum)
|
HeapCellValue::from(float_alloc!(f, self.machine_st.arena))
|
||||||
} else {
|
|
||||||
integer_as_cell!(Number::Integer(arena_alloc!(
|
|
||||||
Integer::from(n),
|
|
||||||
&mut self.machine_st.arena
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
}
|
_ => integer_as_cell!(n),
|
||||||
Value::Float(n) => HeapCellValue::from(float_alloc!(n, self.machine_st.arena)),
|
},
|
||||||
Value::CString(cstr) => atom_as_cell!(AtomTable::build_with(
|
Value::CString(cstr) => atom_as_cell!(AtomTable::build_with(
|
||||||
&self.machine_st.atom_tbl,
|
&self.machine_st.atom_tbl,
|
||||||
&cstr.into_string().unwrap()
|
&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::<Result<_, usize>>()?;
|
||||||
|
|
||||||
sized_iter_to_heap_list(
|
sized_iter_to_heap_list(&mut self.machine_st.heap, cells.len(), cells.into_iter())
|
||||||
&mut self.machine_st.heap,
|
|
||||||
expanded_args.len(),
|
|
||||||
expanded_args.into_iter(),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "ffi")]
|
#[cfg(feature = "ffi")]
|
||||||
|
|||||||
@@ -583,10 +583,13 @@ mod private {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: FitsInFixnumSeal> MightNotFitInFixnumSeal for T {}
|
||||||
impl MightNotFitInFixnumSeal for i64 {}
|
impl MightNotFitInFixnumSeal for i64 {}
|
||||||
|
impl MightNotFitInFixnumSeal for u64 {}
|
||||||
impl MightNotFitInFixnumSeal for &Integer {}
|
impl MightNotFitInFixnumSeal for &Integer {}
|
||||||
impl MightNotFitInFixnumSeal for Integer {}
|
impl MightNotFitInFixnumSeal for Integer {}
|
||||||
impl MightNotFitInFixnumSeal for usize {}
|
impl MightNotFitInFixnumSeal for usize {}
|
||||||
|
impl MightNotFitInFixnumSeal for isize {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(private_bounds)]
|
#[allow(private_bounds)]
|
||||||
|
|||||||
@@ -143,8 +143,7 @@ fn ffi_return_values() {
|
|||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn ffi_return_values_u64() -> u64 {
|
extern "C" fn ffi_return_values_u64() -> u64 {
|
||||||
// 0xFEDCBA9876543210 // too large for i64
|
0xFEDCBA9876543210
|
||||||
0xBEEFBEE5C0DEB00
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
@@ -172,7 +171,7 @@ fn ffi_return_values() {
|
|||||||
-0xBEEFBEE,
|
-0xBEEFBEE,
|
||||||
0xC0DEB000u32,
|
0xC0DEB000u32,
|
||||||
-0xBEEFBEE5C0DEB00i64,
|
-0xBEEFBEE5C0DEB00i64,
|
||||||
0xBEEFBEE5C0DEB00u64,
|
0xFEDCBA9876543210u64,
|
||||||
std::f32::consts::PI as f64,
|
std::f32::consts::PI as f64,
|
||||||
std::f64::consts::TAU
|
std::f64::consts::TAU
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user