Async RPC support #540
|
@ -832,7 +832,6 @@ fn rpc_codegen_callback_fn<'ctx>(
|
||||||
let ptr_type = int8.ptr_type(AddressSpace::default());
|
let ptr_type = int8.ptr_type(AddressSpace::default());
|
||||||
let tag_ptr_type = ctx.ctx.struct_type(&[ptr_type.into(), size_type.into()], false);
|
let tag_ptr_type = ctx.ctx.struct_type(&[ptr_type.into(), size_type.into()], false);
|
||||||
|
|
||||||
|
|
||||||
let service_id = int32.const_int(fun.1 .0 as u64, false);
|
let service_id = int32.const_int(fun.1 .0 as u64, false);
|
||||||
// -- setup rpc tags
|
// -- setup rpc tags
|
||||||
let mut tag = Vec::new();
|
let mut tag = Vec::new();
|
||||||
|
@ -950,7 +949,11 @@ fn rpc_codegen_callback_fn<'ctx>(
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
ctx.builder
|
ctx.builder
|
||||||
.build_call(rpc_send_async, &[service_id.into(), tag_ptr.into(), args_ptr.into()], "rpc.send")
|
.build_call(
|
||||||
|
rpc_send_async,
|
||||||
|
&[service_id.into(), tag_ptr.into(), args_ptr.into()],
|
||||||
|
"rpc.send",
|
||||||
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
let rpc_send = ctx.module.get_function("rpc_send").unwrap_or_else(|| {
|
let rpc_send = ctx.module.get_function("rpc_send").unwrap_or_else(|| {
|
||||||
|
@ -980,12 +983,12 @@ fn rpc_codegen_callback_fn<'ctx>(
|
||||||
Ok(None)
|
Ok(None)
|
||||||
} else {
|
} else {
|
||||||
let result = format_rpc_ret(generator, ctx, fun.0.ret);
|
let result = format_rpc_ret(generator, ctx, fun.0.ret);
|
||||||
|
|
||||||
if !result.is_some_and(|res| res.get_type().is_pointer_type()) {
|
if !result.is_some_and(|res| res.get_type().is_pointer_type()) {
|
||||||
// An RPC returning an NDArray would not touch here.
|
// An RPC returning an NDArray would not touch here.
|
||||||
call_stackrestore(ctx, stackptr);
|
call_stackrestore(ctx, stackptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(result)
|
Ok(result)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,16 +34,12 @@ use nac3core::inkwell::{
|
||||||
targets::*,
|
targets::*,
|
||||||
OptimizationLevel,
|
OptimizationLevel,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
|
||||||
use nac3core::codegen::{gen_func_impl, CodeGenLLVMOptions, CodeGenTargetMachineOptions};
|
|
||||||
use nac3core::toplevel::builtins::get_exn_constructor;
|
use nac3core::toplevel::builtins::get_exn_constructor;
|
||||||
use nac3core::typecheck::typedef::{into_var_map, TypeEnum, Unifier, VarMap};
|
use nac3core::typecheck::typedef::{into_var_map, TypeEnum, Unifier, VarMap};
|
||||||
use nac3parser::{
|
use nac3core::nac3parser::{
|
||||||
ast::{Constant, ExprKind, Located, Stmt, StmtKind, StrRef},
|
ast::{Constant, ExprKind, Located, Stmt, StmtKind, StrRef},
|
||||||
parser::parse_program,
|
parser::parse_program,
|
||||||
};
|
};
|
||||||
use nac3core::toplevel::builtins::get_exn_constructor;
|
|
||||||
use nac3core::typecheck::typedef::{into_var_map, TypeEnum, Unifier, VarMap};
|
|
||||||
use pyo3::create_exception;
|
use pyo3::create_exception;
|
||||||
use pyo3::prelude::*;
|
use pyo3::prelude::*;
|
||||||
use pyo3::{exceptions, types::PyBytes, types::PyDict, types::PySet};
|
use pyo3::{exceptions, types::PyBytes, types::PyDict, types::PySet};
|
||||||
|
@ -139,7 +135,7 @@ struct Nac3 {
|
||||||
string_store: Arc<RwLock<HashMap<String, i32>>>,
|
string_store: Arc<RwLock<HashMap<String, i32>>>,
|
||||||
exception_ids: Arc<RwLock<HashMap<usize, usize>>>,
|
exception_ids: Arc<RwLock<HashMap<usize, usize>>>,
|
||||||
deferred_eval_store: DeferredEvaluationStore,
|
deferred_eval_store: DeferredEvaluationStore,
|
||||||
/// LLVM-related options for code generzation.
|
/// LLVM-related options for code generation.
|
||||||
llvm_options: CodeGenLLVMOptions,
|
llvm_options: CodeGenLLVMOptions,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -479,12 +475,24 @@ impl Nac3 {
|
||||||
|
|
||||||
match &stmt.node {
|
match &stmt.node {
|
||||||
StmtKind::FunctionDef { decorator_list, .. } => {
|
StmtKind::FunctionDef { decorator_list, .. } => {
|
||||||
if decorator_list.iter().any(|decorator| decorator_id_string(decorator) == Some("rpc".to_string())) {
|
if decorator_list
|
||||||
store_fun.call1(py, (def_id.0.into_py(py), module.getattr(py, name.to_string().as_str()).unwrap())).unwrap();
|
.iter()
|
||||||
let is_async = decorator_list.iter().any(
|
.any(|decorator| decorator_id_string(decorator) == Some("rpc".to_string()))
|
||||||
|decorator| decorator_get_flags(decorator).iter().any(
|
{
|
||||||
|constant| *constant == Constant::Str("async".into())
|
store_fun
|
||||||
));
|
.call1(
|
||||||
|
py,
|
||||||
|
(
|
||||||
|
def_id.0.into_py(py),
|
||||||
|
module.getattr(py, name.to_string().as_str()).unwrap(),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
let is_async = decorator_list.iter().any(|decorator| {
|
||||||
|
decorator_get_flags(decorator)
|
||||||
|
.iter()
|
||||||
|
.any(|constant| *constant == Constant::Str("async".into()))
|
||||||
|
});
|
||||||
rpc_ids.push((None, def_id, is_async));
|
rpc_ids.push((None, def_id, is_async));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -493,11 +501,14 @@ impl Nac3 {
|
||||||
let class_obj = module.getattr(py, class_name.as_str()).unwrap();
|
let class_obj = module.getattr(py, class_name.as_str()).unwrap();
|
||||||
for stmt in body {
|
for stmt in body {
|
||||||
if let StmtKind::FunctionDef { name, decorator_list, .. } = &stmt.node {
|
if let StmtKind::FunctionDef { name, decorator_list, .. } = &stmt.node {
|
||||||
if decorator_list.iter().any(|decorator| decorator_id_string(decorator) == Some("rpc".to_string())) {
|
if decorator_list.iter().any(|decorator| {
|
||||||
let is_async = decorator_list.iter().any(
|
decorator_id_string(decorator) == Some("rpc".to_string())
|
||||||
|decorator| decorator_get_flags(decorator).iter().any(
|
}) {
|
||||||
|constant| *constant == Constant::Str("async".into())
|
let is_async = decorator_list.iter().any(|decorator| {
|
||||||
));
|
decorator_get_flags(decorator)
|
||||||
|
.iter()
|
||||||
|
.any(|constant| *constant == Constant::Str("async".into()))
|
||||||
|
});
|
||||||
if name == &"__init__".into() {
|
if name == &"__init__".into() {
|
||||||
return Err(CompileError::new_err(format!(
|
return Err(CompileError::new_err(format!(
|
||||||
"compilation failed\n----------\nThe constructor of class {} should not be decorated with rpc decorator (at {})",
|
"compilation failed\n----------\nThe constructor of class {} should not be decorated with rpc decorator (at {})",
|
||||||
|
@ -509,7 +520,7 @@ impl Nac3 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => ()
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = *name_to_pyid.get(&name).unwrap();
|
let id = *name_to_pyid.get(&name).unwrap();
|
||||||
|
@ -852,8 +863,8 @@ impl Nac3 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves the Name.id from a decorator, supports decorators with arguments.
|
||||||
|
|||||||
fn decorator_id_string(decorator: &Located<ExprKind>) -> Option<String> {
|
fn decorator_id_string(decorator: &Located<ExprKind>) -> Option<String> {
|
||||||
/// Retrieves the Name.id from a decorator, supports decorators with arguments.
|
|
||||||
if let ExprKind::Name { id, .. } = decorator.node {
|
if let ExprKind::Name { id, .. } = decorator.node {
|
||||||
// Bare decorator
|
// Bare decorator
|
||||||
return Some(id.to_string());
|
return Some(id.to_string());
|
||||||
|
@ -867,11 +878,11 @@ fn decorator_id_string(decorator: &Located<ExprKind>) -> Option<String> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves flags from a decorator, if any.
|
||||||
fn decorator_get_flags(decorator: &Located<ExprKind>) -> Vec<Constant> {
|
fn decorator_get_flags(decorator: &Located<ExprKind>) -> Vec<Constant> {
|
||||||
/// Retrieves flags from a decorator, if any.
|
|
||||||
let mut flags = vec![];
|
let mut flags = vec![];
|
||||||
if let ExprKind::Call { keywords, .. } = &decorator.node {
|
if let ExprKind::Call { keywords, .. } = &decorator.node {
|
||||||
for keyword in keywords.iter() {
|
for keyword in keywords {
|
||||||
if keyword.node.arg != Some("flags".into()) {
|
if keyword.node.arg != Some("flags".into()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1673,7 +1673,7 @@ impl TopLevelComposer {
|
||||||
// they may be changed with our use of placeholders
|
// they may be changed with our use of placeholders
|
||||||
for (def, _) in definition_ast_list.iter().skip(self.builtin_num) {
|
for (def, _) in definition_ast_list.iter().skip(self.builtin_num) {
|
||||||
if let TopLevelDef::Function { signature, var_id, .. } = &mut *def.write() {
|
if let TopLevelDef::Function { signature, var_id, .. } = &mut *def.write() {
|
||||||
if let TypeEnum::TFunc(FunSignature { args, ret, vars}) =
|
if let TypeEnum::TFunc(FunSignature { args, ret, vars }) =
|
||||||
unifier.get_ty(*signature).as_ref()
|
unifier.get_ty(*signature).as_ref()
|
||||||
{
|
{
|
||||||
let new_var_ids = vars
|
let new_var_ids = vars
|
||||||
|
@ -1894,7 +1894,8 @@ impl TopLevelComposer {
|
||||||
} = &mut *function_def
|
} = &mut *function_def
|
||||||
{
|
{
|
||||||
let signature_ty_enum = unifier.get_ty(*signature);
|
let signature_ty_enum = unifier.get_ty(*signature);
|
||||||
let TypeEnum::TFunc(FunSignature { args, ret, vars, .. }) = signature_ty_enum.as_ref()
|
let TypeEnum::TFunc(FunSignature { args, ret, vars, .. }) =
|
||||||
|
signature_ty_enum.as_ref()
|
||||||
else {
|
else {
|
||||||
unreachable!("must be typeenum::tfunc")
|
unreachable!("must be typeenum::tfunc")
|
||||||
};
|
};
|
||||||
|
@ -2059,11 +2060,12 @@ impl TopLevelComposer {
|
||||||
}
|
}
|
||||||
if !decorator_list.is_empty() {
|
if !decorator_list.is_empty() {
|
||||||
if let ast::ExprKind::Call { func, .. } = &decorator_list[0].node {
|
if let ast::ExprKind::Call { func, .. } = &decorator_list[0].node {
|
||||||
if matches!(&func.node,
|
if matches!(&func.node,
|
||||||
ast::ExprKind::Name{ id, .. } if id == &"rpc".into()) {
|
ast::ExprKind::Name{ id, .. } if id == &"rpc".into())
|
||||||
instance_to_symbol.insert(String::new(), simple_name.to_string());
|
{
|
||||||
continue;
|
instance_to_symbol.insert(String::new(), simple_name.to_string());
|
||||||
derppening
commented
What exactly is this for? What exactly is this for?
mwojcik
commented
Mimics the check above it - for decorators with arguments the Name is behind a Call as I mentioned before. Without it, it wouldn't be considered an external function and compiler would try to compile it together with the kernel. Mimics the check above it - for decorators with arguments the Name is behind a Call as I mentioned before. Without it, it wouldn't be considered an external function and compiler would try to compile it together with the kernel.
|
|||||||
}
|
continue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Please add documentation for these two functions.