forked from M-Labs/nac3
nac3core: function codegen callback changes
Added code generator argument to the callback, so it would be easier to write complicated codegen with that callback. To prepare for RPC codegen.
This commit is contained in:
parent
ffe89eec86
commit
050c862c1a
@ -371,13 +371,7 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
|
|||||||
..
|
..
|
||||||
} => {
|
} => {
|
||||||
if let Some(callback) = codegen_callback {
|
if let Some(callback) = codegen_callback {
|
||||||
// TODO: Change signature
|
return callback.run(ctx, obj, fun, params, generator);
|
||||||
let obj = obj.map(|(t, v)| (t, v.to_basic_value_enum(ctx, generator)));
|
|
||||||
let params = params
|
|
||||||
.into_iter()
|
|
||||||
.map(|(name, val)| (name, val.to_basic_value_enum(ctx, generator)))
|
|
||||||
.collect();
|
|
||||||
return callback.run(ctx, obj, fun, params);
|
|
||||||
}
|
}
|
||||||
let old_key = ctx.get_subst_key(obj.as_ref().map(|a| a.0), fun.0, None);
|
let old_key = ctx.get_subst_key(obj.as_ref().map(|a| a.0), fun.0, None);
|
||||||
let mut keys = fun.0.args.clone();
|
let mut keys = fun.0.args.clone();
|
||||||
@ -431,7 +425,7 @@ pub fn gen_call<'ctx, 'a, G: CodeGenerator>(
|
|||||||
};
|
};
|
||||||
param_vals = real_params
|
param_vals = real_params
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|p| p.to_basic_value_enum(ctx, generator).into())
|
.map(|p| p.to_basic_value_enum(ctx, generator))
|
||||||
.collect_vec();
|
.collect_vec();
|
||||||
instance_to_symbol.get(&key).cloned()
|
instance_to_symbol.get(&key).cloned()
|
||||||
}
|
}
|
||||||
|
@ -62,13 +62,13 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
instance_to_stmt: Default::default(),
|
instance_to_stmt: Default::default(),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||||
|ctx, _, fun, args| {
|
|ctx, _, fun, args, generator| {
|
||||||
let int32 = ctx.primitives.int32;
|
let int32 = ctx.primitives.int32;
|
||||||
let int64 = ctx.primitives.int64;
|
let int64 = ctx.primitives.int64;
|
||||||
let float = ctx.primitives.float;
|
let float = ctx.primitives.float;
|
||||||
let boolean = ctx.primitives.bool;
|
let boolean = ctx.primitives.bool;
|
||||||
let arg_ty = fun.0.args[0].ty;
|
let arg_ty = fun.0.args[0].ty;
|
||||||
let arg = args[0].1;
|
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
|
||||||
if ctx.unifier.unioned(arg_ty, boolean) {
|
if ctx.unifier.unioned(arg_ty, boolean) {
|
||||||
Some(
|
Some(
|
||||||
ctx.builder
|
ctx.builder
|
||||||
@ -120,13 +120,13 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
instance_to_stmt: Default::default(),
|
instance_to_stmt: Default::default(),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||||
|ctx, _, fun, args| {
|
|ctx, _, fun, args, generator| {
|
||||||
let int32 = ctx.primitives.int32;
|
let int32 = ctx.primitives.int32;
|
||||||
let int64 = ctx.primitives.int64;
|
let int64 = ctx.primitives.int64;
|
||||||
let float = ctx.primitives.float;
|
let float = ctx.primitives.float;
|
||||||
let boolean = ctx.primitives.bool;
|
let boolean = ctx.primitives.bool;
|
||||||
let arg_ty = fun.0.args[0].ty;
|
let arg_ty = fun.0.args[0].ty;
|
||||||
let arg = args[0].1;
|
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
|
||||||
if ctx.unifier.unioned(arg_ty, boolean)
|
if ctx.unifier.unioned(arg_ty, boolean)
|
||||||
|| ctx.unifier.unioned(arg_ty, int32)
|
|| ctx.unifier.unioned(arg_ty, int32)
|
||||||
{
|
{
|
||||||
@ -170,18 +170,18 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
instance_to_stmt: Default::default(),
|
instance_to_stmt: Default::default(),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||||
|ctx, _, fun, args| {
|
|ctx, _, fun, args, generator| {
|
||||||
let int32 = ctx.primitives.int32;
|
let int32 = ctx.primitives.int32;
|
||||||
let int64 = ctx.primitives.int64;
|
let int64 = ctx.primitives.int64;
|
||||||
let boolean = ctx.primitives.bool;
|
let boolean = ctx.primitives.bool;
|
||||||
let float = ctx.primitives.float;
|
let float = ctx.primitives.float;
|
||||||
let arg_ty = fun.0.args[0].ty;
|
let arg_ty = fun.0.args[0].ty;
|
||||||
let arg = args[0].1;
|
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
|
||||||
if ctx.unifier.unioned(arg_ty, boolean)
|
if ctx.unifier.unioned(arg_ty, boolean)
|
||||||
|| ctx.unifier.unioned(arg_ty, int32)
|
|| ctx.unifier.unioned(arg_ty, int32)
|
||||||
|| ctx.unifier.unioned(arg_ty, int64)
|
|| ctx.unifier.unioned(arg_ty, int64)
|
||||||
{
|
{
|
||||||
let arg = args[0].1.into_int_value();
|
let arg = arg.into_int_value();
|
||||||
let val = ctx
|
let val = ctx
|
||||||
.builder
|
.builder
|
||||||
.build_signed_int_to_float(arg, ctx.ctx.f64_type(), "sitofp")
|
.build_signed_int_to_float(arg, ctx.ctx.f64_type(), "sitofp")
|
||||||
@ -207,8 +207,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
instance_to_symbol: Default::default(),
|
instance_to_symbol: Default::default(),
|
||||||
instance_to_stmt: Default::default(),
|
instance_to_stmt: Default::default(),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
|
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
|
||||||
let arg = args[0].1;
|
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
|
||||||
let round_intrinsic =
|
let round_intrinsic =
|
||||||
ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| {
|
ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| {
|
||||||
let float = ctx.ctx.f64_type();
|
let float = ctx.ctx.f64_type();
|
||||||
@ -244,8 +244,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
instance_to_symbol: Default::default(),
|
instance_to_symbol: Default::default(),
|
||||||
instance_to_stmt: Default::default(),
|
instance_to_stmt: Default::default(),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
|
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
|
||||||
let arg = args[0].1;
|
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
|
||||||
let round_intrinsic =
|
let round_intrinsic =
|
||||||
ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| {
|
ctx.module.get_function("llvm.round.f64").unwrap_or_else(|| {
|
||||||
let float = ctx.ctx.f64_type();
|
let float = ctx.ctx.f64_type();
|
||||||
@ -294,7 +294,7 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
instance_to_symbol: Default::default(),
|
instance_to_symbol: Default::default(),
|
||||||
instance_to_stmt: Default::default(),
|
instance_to_stmt: Default::default(),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
|
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
|
||||||
let mut start = None;
|
let mut start = None;
|
||||||
let mut stop = None;
|
let mut stop = None;
|
||||||
let mut step = None;
|
let mut step = None;
|
||||||
@ -302,17 +302,17 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
let zero = int32.const_zero();
|
let zero = int32.const_zero();
|
||||||
for (i, arg) in args.iter().enumerate() {
|
for (i, arg) in args.iter().enumerate() {
|
||||||
if arg.0 == Some("start".into()) {
|
if arg.0 == Some("start".into()) {
|
||||||
start = Some(arg.1);
|
start = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
|
||||||
} else if arg.0 == Some("stop".into()) {
|
} else if arg.0 == Some("stop".into()) {
|
||||||
stop = Some(arg.1);
|
stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
|
||||||
} else if arg.0 == Some("step".into()) {
|
} else if arg.0 == Some("step".into()) {
|
||||||
step = Some(arg.1);
|
step = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
|
||||||
} else if i == 0 {
|
} else if i == 0 {
|
||||||
start = Some(arg.1);
|
start = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
|
||||||
} else if i == 1 {
|
} else if i == 1 {
|
||||||
stop = Some(arg.1);
|
stop = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
|
||||||
} else if i == 2 {
|
} else if i == 2 {
|
||||||
step = Some(arg.1);
|
step = Some(arg.1.clone().to_basic_value_enum(ctx, generator));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// TODO: error when step == 0
|
// TODO: error when step == 0
|
||||||
@ -356,8 +356,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
instance_to_symbol: Default::default(),
|
instance_to_symbol: Default::default(),
|
||||||
instance_to_stmt: Default::default(),
|
instance_to_stmt: Default::default(),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|_, _, _, args| {
|
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
|
||||||
Some(args[0].1)
|
Some(args[0].1.clone().to_basic_value_enum(ctx, generator))
|
||||||
})))),
|
})))),
|
||||||
})),
|
})),
|
||||||
Arc::new(RwLock::new(TopLevelDef::Function {
|
Arc::new(RwLock::new(TopLevelDef::Function {
|
||||||
@ -373,13 +373,13 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
instance_to_stmt: Default::default(),
|
instance_to_stmt: Default::default(),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||||
|ctx, _, fun, args| {
|
|ctx, _, fun, args, generator| {
|
||||||
let int32 = ctx.primitives.int32;
|
let int32 = ctx.primitives.int32;
|
||||||
let int64 = ctx.primitives.int64;
|
let int64 = ctx.primitives.int64;
|
||||||
let float = ctx.primitives.float;
|
let float = ctx.primitives.float;
|
||||||
let boolean = ctx.primitives.bool;
|
let boolean = ctx.primitives.bool;
|
||||||
let arg_ty = fun.0.args[0].ty;
|
let arg_ty = fun.0.args[0].ty;
|
||||||
let arg = args[0].1;
|
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
|
||||||
if ctx.unifier.unioned(arg_ty, boolean) {
|
if ctx.unifier.unioned(arg_ty, boolean) {
|
||||||
Some(arg)
|
Some(arg)
|
||||||
} else if ctx.unifier.unioned(arg_ty, int32) {
|
} else if ctx.unifier.unioned(arg_ty, int32) {
|
||||||
@ -424,8 +424,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
instance_to_symbol: Default::default(),
|
instance_to_symbol: Default::default(),
|
||||||
instance_to_stmt: Default::default(),
|
instance_to_stmt: Default::default(),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
|
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
|
||||||
let arg = args[0].1;
|
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
|
||||||
let floor_intrinsic =
|
let floor_intrinsic =
|
||||||
ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
|
ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
|
||||||
let float = ctx.ctx.f64_type();
|
let float = ctx.ctx.f64_type();
|
||||||
@ -461,8 +461,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
instance_to_symbol: Default::default(),
|
instance_to_symbol: Default::default(),
|
||||||
instance_to_stmt: Default::default(),
|
instance_to_stmt: Default::default(),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
|
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
|
||||||
let arg = args[0].1;
|
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
|
||||||
let floor_intrinsic =
|
let floor_intrinsic =
|
||||||
ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
|
ctx.module.get_function("llvm.floor.f64").unwrap_or_else(|| {
|
||||||
let float = ctx.ctx.f64_type();
|
let float = ctx.ctx.f64_type();
|
||||||
@ -498,8 +498,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
instance_to_symbol: Default::default(),
|
instance_to_symbol: Default::default(),
|
||||||
instance_to_stmt: Default::default(),
|
instance_to_stmt: Default::default(),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
|
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
|
||||||
let arg = args[0].1;
|
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
|
||||||
let ceil_intrinsic =
|
let ceil_intrinsic =
|
||||||
ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| {
|
ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| {
|
||||||
let float = ctx.ctx.f64_type();
|
let float = ctx.ctx.f64_type();
|
||||||
@ -535,8 +535,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
instance_to_symbol: Default::default(),
|
instance_to_symbol: Default::default(),
|
||||||
instance_to_stmt: Default::default(),
|
instance_to_stmt: Default::default(),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args| {
|
codegen_callback: Some(Arc::new(GenCall::new(Box::new(|ctx, _, _, args, generator| {
|
||||||
let arg = args[0].1;
|
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
|
||||||
let ceil_intrinsic =
|
let ceil_intrinsic =
|
||||||
ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| {
|
ctx.module.get_function("llvm.ceil.f64").unwrap_or_else(|| {
|
||||||
let float = ctx.ctx.f64_type();
|
let float = ctx.ctx.f64_type();
|
||||||
@ -581,10 +581,10 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
|||||||
instance_to_stmt: Default::default(),
|
instance_to_stmt: Default::default(),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
codegen_callback: Some(Arc::new(GenCall::new(Box::new(
|
||||||
|ctx, _, fun, args| {
|
|ctx, _, fun, args, generator| {
|
||||||
let range_ty = ctx.primitives.range;
|
let range_ty = ctx.primitives.range;
|
||||||
let arg_ty = fun.0.args[0].ty;
|
let arg_ty = fun.0.args[0].ty;
|
||||||
let arg = args[0].1;
|
let arg = args[0].1.clone().to_basic_value_enum(ctx, generator);
|
||||||
if ctx.unifier.unioned(arg_ty, range_ty) {
|
if ctx.unifier.unioned(arg_ty, range_ty) {
|
||||||
let arg = arg.into_pointer_value();
|
let arg = arg.into_pointer_value();
|
||||||
let (start, end, step) = destructure_range(ctx, arg);
|
let (start, end, step) = destructure_range(ctx, arg);
|
||||||
|
@ -11,20 +11,21 @@ use super::codegen::CodeGenContext;
|
|||||||
use super::typecheck::type_inferencer::PrimitiveStore;
|
use super::typecheck::type_inferencer::PrimitiveStore;
|
||||||
use super::typecheck::typedef::{FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier};
|
use super::typecheck::typedef::{FunSignature, FuncArg, SharedUnifier, Type, TypeEnum, Unifier};
|
||||||
use crate::{
|
use crate::{
|
||||||
symbol_resolver::SymbolResolver,
|
codegen::CodeGenerator,
|
||||||
|
symbol_resolver::{SymbolResolver, ValueEnum},
|
||||||
typecheck::{type_inferencer::CodeLocation, typedef::CallId},
|
typecheck::{type_inferencer::CodeLocation, typedef::CallId},
|
||||||
};
|
};
|
||||||
use itertools::{izip, Itertools};
|
|
||||||
use parking_lot::RwLock;
|
|
||||||
use nac3parser::ast::{self, Stmt, StrRef};
|
|
||||||
use inkwell::values::BasicValueEnum;
|
use inkwell::values::BasicValueEnum;
|
||||||
|
use itertools::{izip, Itertools};
|
||||||
|
use nac3parser::ast::{self, Stmt, StrRef};
|
||||||
|
use parking_lot::RwLock;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Debug)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Debug)]
|
||||||
pub struct DefinitionId(pub usize);
|
pub struct DefinitionId(pub usize);
|
||||||
|
|
||||||
|
pub mod builtins;
|
||||||
pub mod composer;
|
pub mod composer;
|
||||||
pub mod helper;
|
pub mod helper;
|
||||||
pub mod builtins;
|
|
||||||
pub mod type_annotation;
|
pub mod type_annotation;
|
||||||
use composer::*;
|
use composer::*;
|
||||||
use type_annotation::*;
|
use type_annotation::*;
|
||||||
@ -34,9 +35,10 @@ mod test;
|
|||||||
type GenCallCallback = Box<
|
type GenCallCallback = Box<
|
||||||
dyn for<'ctx, 'a> Fn(
|
dyn for<'ctx, 'a> Fn(
|
||||||
&mut CodeGenContext<'ctx, 'a>,
|
&mut CodeGenContext<'ctx, 'a>,
|
||||||
Option<(Type, BasicValueEnum)>,
|
Option<(Type, ValueEnum<'ctx>)>,
|
||||||
(&FunSignature, DefinitionId),
|
(&FunSignature, DefinitionId),
|
||||||
Vec<(Option<StrRef>, BasicValueEnum<'ctx>)>,
|
Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
|
||||||
|
&mut dyn CodeGenerator,
|
||||||
) -> Option<BasicValueEnum<'ctx>>
|
) -> Option<BasicValueEnum<'ctx>>
|
||||||
+ Send
|
+ Send
|
||||||
+ Sync,
|
+ Sync,
|
||||||
@ -54,11 +56,12 @@ impl GenCall {
|
|||||||
pub fn run<'ctx, 'a>(
|
pub fn run<'ctx, 'a>(
|
||||||
&self,
|
&self,
|
||||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||||
obj: Option<(Type, BasicValueEnum<'ctx>)>,
|
obj: Option<(Type, ValueEnum<'ctx>)>,
|
||||||
fun: (&FunSignature, DefinitionId),
|
fun: (&FunSignature, DefinitionId),
|
||||||
args: Vec<(Option<StrRef>, BasicValueEnum<'ctx>)>,
|
args: Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
|
||||||
|
generator: &mut dyn CodeGenerator,
|
||||||
) -> Option<BasicValueEnum<'ctx>> {
|
) -> Option<BasicValueEnum<'ctx>> {
|
||||||
(self.fp)(ctx, obj, fun, args)
|
(self.fp)(ctx, obj, fun, args, generator)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +123,7 @@ pub enum TopLevelDef {
|
|||||||
// symbol resolver of the module defined the class
|
// symbol resolver of the module defined the class
|
||||||
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
||||||
// custom codegen callback
|
// custom codegen callback
|
||||||
codegen_callback: Option<Arc<GenCall>>
|
codegen_callback: Option<Arc<GenCall>>,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user