Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions source/loaders/rs_loader/rust/compiler/src/api/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ pub struct FunctionRegistration {
pub function_create: FunctionCreate,
pub ret: Option<String>,
pub input: Vec<FunctionInputSignature>,
pub template: Option<OpaqueType>,
}

pub fn register_function(function_registration: FunctionRegistration) {
Expand Down
176 changes: 176 additions & 0 deletions source/loaders/rs_loader/rust/compiler/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,17 @@ pub type OpaqueTypeList = *mut OpaqueType;
mod class;
mod function;
mod object;

#[repr(C)]
pub struct TemplateArgument {
pub name: *const c_char,
pub kind: c_int,
pub value: OpaqueType,
}

pub const TEMPLATE_ARGUMENT_TYPE: c_int = 0;
pub const TEMPLATE_ARGUMENT_TEMPLATE: c_int = 1;

pub use function::{
function_singleton, register_function, FunctionCreate, FunctionInputSignature,
FunctionRegistration,
Expand Down Expand Up @@ -62,6 +73,14 @@ extern "C" {

fn function_name(function: OpaqueType) -> *mut c_char;

fn value_create_int(i: c_int) -> OpaqueType;

fn function_call(func: OpaqueType, args: OpaqueTypeList, size: usize) -> OpaqueType;

fn value_create_double(d: f64) -> OpaqueType;

fn value_to_double(v: OpaqueType) -> f64;

fn function_signature(function: OpaqueType) -> OpaqueType;

fn value_create_function(function: OpaqueType) -> OpaqueType;
Expand Down Expand Up @@ -115,16 +134,173 @@ extern "C" {
singleton: OpaqueType,
class: OpaqueType,
) -> OpaqueType;
fn value_to_int(v: OpaqueType) -> i32;

fn metacall_loader(tag: *const c_char) -> OpaqueType;
fn loader_is_destroyed(loader_impl: OpaqueType) -> i32;

fn template_create(name: *const c_char, template_type: c_int) -> OpaqueType;

fn template_add_parameter(tpl: OpaqueType, parameter: *const c_char) -> c_int;

fn template_name(tpl: OpaqueType) -> *const c_char;

fn template_type(tpl: OpaqueType) -> c_int;

fn template_parameter_count(tpl: OpaqueType) -> usize;

fn template_parameter(tpl: OpaqueType, index: usize) -> *const c_char;

fn template_destroy(tpl: OpaqueType) -> ();

fn template_instantiate_function(
tpl: OpaqueType,
args: OpaqueType,
size: usize,
function_impl: OpaqueType,
singleton: OpaqueType,
) -> OpaqueType;
}

pub const TEMPLATE_TYPE_FUNCTION: c_int = 0;
pub const TEMPLATE_TYPE_CLASS: c_int = 1;

/// Creates a MetaCall function from an implementation and interface.
///
/// # Safety
/// `function_impl` and `singleton` must be valid MetaCall pointers.
pub unsafe fn create_function(
name: &str,
args_count: usize,
function_impl: OpaqueType,
singleton: OpaqueType,
) -> OpaqueType {
let name = CString::new(name).expect("function name contains NUL");

unsafe { function_create(name.as_ptr(), args_count, function_impl, singleton) }
}

/// # Safety
/// `name` must be a valid MetaCall template name.
pub unsafe fn create_template(name: &str, template_type: c_int) -> OpaqueType {
let name = CString::new(name).expect("template name contains NUL");

unsafe { template_create(name.as_ptr(), template_type) }
}

/// # Safety
/// `tpl` must be a valid reflect_template.
pub unsafe fn add_template_parameter(tpl: OpaqueType, parameter: &str) -> c_int {
let parameter = CString::new(parameter).expect("template parameter contains NUL");

unsafe { template_add_parameter(tpl, parameter.as_ptr()) }
}

/// # Safety
/// `tpl` must be a valid `reflect_template`.
pub unsafe fn get_template_name(tpl: OpaqueType) -> *const c_char {
unsafe { template_name(tpl) }
}

/// # Safety
/// `tpl` must be a valid `reflect_template`.
pub unsafe fn get_template_type(tpl: OpaqueType) -> c_int {
unsafe { template_type(tpl) }
}

/// # Safety
/// `tpl` must be a valid `reflect_template`.
pub unsafe fn get_template_parameter_count(tpl: OpaqueType) -> usize {
unsafe { template_parameter_count(tpl) }
}

/// # Safety
/// `tpl` must be a valid `reflect_template` and `index` must be within
/// the template's parameter range.
pub unsafe fn get_template_parameter(tpl: OpaqueType, index: usize) -> *const c_char {
unsafe { template_parameter(tpl, index) }
}

/// # Safety
/// `tpl` must be a valid `reflect_template` that is no longer in use.
pub unsafe fn destroy_template(tpl: OpaqueType) {
unsafe {
template_destroy(tpl);
}
}

/// # Safety
/// `tpl` must be a valid function template and `args` must point to a valid
/// array of template arguments with `size` elements.
pub unsafe fn instantiate_template_function(
tpl: OpaqueType,
args: &mut [TemplateArgument],
function_impl: OpaqueType,
singleton: OpaqueType,
) -> OpaqueType {
unsafe {
template_instantiate_function(
tpl,
args.as_mut_ptr() as OpaqueType,
args.len(),
function_impl,
singleton,
)
}
}

/// # Safety
/// `loader_impl` must be a valid loader implementation and `name` must
/// identify a valid MetaCall type.
pub unsafe fn get_loader_type(loader_impl: OpaqueType, name: &str) -> OpaqueType {
let name = CString::new(name).expect("type name contains NUL");

unsafe { loader_impl_type(loader_impl, name.as_ptr()) }
}

/// Creates a MetaCall integer value.
///
/// # Safety
/// The returned opaque pointer is owned by the caller and must be used
/// according to the MetaCall value API.
pub unsafe fn create_int_value(value: i32) -> OpaqueType {
unsafe { value_create_int(value as c_int) }
}

/// Calls a MetaCall function with the provided arguments.
///
/// # Safety
/// `function` must be a valid MetaCall function pointer, and every element
/// of `args` must be a valid MetaCall value pointer compatible with the
/// function signature.
pub unsafe fn call_function(function: OpaqueType, args: &mut [OpaqueType]) -> OpaqueType {
unsafe { function_call(function, args.as_mut_ptr(), args.len()) }
}

/// Converts a MetaCall value containing an Int into an `i32`.
///
/// # Safety
/// `v` must be a valid MetaCall value containing an integer.
pub unsafe fn int_from_value(v: OpaqueType) -> i32 {
unsafe { value_to_int(v) }
}

/// # Safety
/// `loader_impl` must be a valid initialized loader implementation pointer.
pub unsafe fn get_loader_lifecycle_state(loader_impl: OpaqueType) -> *mut LoaderLifecycleState {
(unsafe { loader_impl_get(loader_impl) }) as *mut LoaderLifecycleState
}
/// # Safety/// The returned opaque pointer is owned by MetaCall and must be used
/// according to the MetaCall value API.
pub unsafe fn create_double_value(value: f64) -> OpaqueType {
value_create_double(value)
}

/// # Safety
/// `v` must be a valid MetaCall value containing a double.
pub unsafe fn double_from_value(v: OpaqueType) -> f64 {
value_to_double(v)
}

static mut RS_LOADER_PTR: *mut c_void = std::ptr::null_mut();

Expand Down
30 changes: 23 additions & 7 deletions source/loaders/rs_loader/rust/compiler/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,26 @@ use super::rustc_ast::{
};
use super::{Function, FunctionParameter, FunctionType, Mutability, Reference};

pub fn handle_ty(ty: &rustc_ast::Ty) -> FunctionParameter {
pub fn handle_ty(ty: &rustc_ast::Ty, generics: &Vec<String>) -> FunctionParameter {
let mut result = FunctionParameter {
name: String::new(),
mutability: Mutability::No,
reference: Reference::No,
ty: FunctionType::Null,
generic: vec![],
generic_name: None,
};
match &ty.kind {
TyKind::Path(_, path) => {
let segment = &path.segments[0];
let symbol_string = segment.ident.name.to_string();

if generics.contains(&symbol_string) {
result.ty = FunctionType::Complex;
result.generic_name = Some(symbol_string.clone());
result.name = symbol_string;
return result;
}
match symbol_string.as_str() {
"i16" => result.ty = FunctionType::i16,
"i32" => result.ty = FunctionType::i32,
Expand All @@ -29,14 +37,15 @@ pub fn handle_ty(ty: &rustc_ast::Ty) -> FunctionParameter {
"bool" => result.ty = FunctionType::bool,
"i8" => result.ty = FunctionType::char,
"str" => result.ty = FunctionType::String,
"complex" => result.ty = FunctionType::Complex,
"Vec" => {
result.ty = FunctionType::Array;
if let Some(args) = &segment.args {
match &**args {
GenericArgs::AngleBracketed(AngleBracketedArgs { args, .. }) => {
for arg in args {
if let AngleBracketedArg::Arg(GenericArg::Type(ty)) = arg {
result.generic.push(handle_ty(ty))
result.generic.push(handle_ty(ty, generics))
}
}
}
Expand All @@ -52,7 +61,7 @@ pub fn handle_ty(ty: &rustc_ast::Ty) -> FunctionParameter {
GenericArgs::AngleBracketed(AngleBracketedArgs { args, .. }) => {
for arg in args {
if let AngleBracketedArg::Arg(GenericArg::Type(ty)) = arg {
result.generic.push(handle_ty(ty))
result.generic.push(handle_ty(ty, generics))
}
}
}
Expand All @@ -67,7 +76,7 @@ pub fn handle_ty(ty: &rustc_ast::Ty) -> FunctionParameter {
result.name = symbol_string;
}
TyKind::Ref(_, MutTy { ty, mutbl }) => {
let mut inner_ty = handle_ty(ty);
let mut inner_ty = handle_ty(ty, generics);
inner_ty.reference = Reference::Yes;
match mutbl {
rustc_ast::Mutability::Mut => inner_ty.mutability = Mutability::Yes,
Expand All @@ -91,15 +100,22 @@ fn handle_pat(pat: &Pat) -> Option<String> {
None
}

pub fn handle_fn(name: String, sig: &FnSig) -> Function {
pub fn handle_fn(name: String, sig: &FnSig, generics: &rustc_ast::Generics) -> Function {
let generics_params = generics
.params
.iter()
.map(|param| param.ident.name.to_string())
.collect::<Vec<String>>();

let mut function = Function {
name,
ret: None,
args: vec![],
generics: generics_params.clone(),
};
// parse input and output
for arg in &sig.decl.inputs {
let mut param = handle_ty(&arg.ty);
let mut param = handle_ty(&arg.ty, &generics_params);
// we need to extract the name from pat.
if let Some(name) = handle_pat(&arg.pat) {
param.name = name;
Expand All @@ -110,7 +126,7 @@ pub fn handle_fn(name: String, sig: &FnSig) -> Function {
match &sig.decl.output {
FnRetTy::Default(_) => function.ret = None,
FnRetTy::Ty(ty) => {
function.ret = Some(handle_ty(ty));
function.ret = Some(handle_ty(ty, &generics_params));
}
}
function
Expand Down
Loading