forked from M-Labs/nac3
Compare commits
1 Commits
master
...
use_static
Author | SHA1 | Date | |
---|---|---|---|
237a44c477 |
@ -65,7 +65,7 @@ enum ParallelMode {
|
||||
Deep,
|
||||
}
|
||||
|
||||
pub struct ArtiqCodeGenerator<'a> {
|
||||
pub struct ArtiqCodeGenerator<'a, T: TimeFns + Sync> {
|
||||
name: String,
|
||||
|
||||
/// The size of a `size_t` variable in bits.
|
||||
@ -79,7 +79,7 @@ pub struct ArtiqCodeGenerator<'a> {
|
||||
|
||||
/// Variable for tracking the end of a `with parallel` block.
|
||||
end: Option<Expr<Option<Type>>>,
|
||||
timeline: &'a (dyn TimeFns + Sync),
|
||||
timeline: &'a T,
|
||||
|
||||
/// The [`ParallelMode`] of the current parallel context.
|
||||
///
|
||||
@ -91,13 +91,13 @@ pub struct ArtiqCodeGenerator<'a> {
|
||||
special_ids: SpecialPythonId,
|
||||
}
|
||||
|
||||
impl<'a> ArtiqCodeGenerator<'a> {
|
||||
impl<'a, T: TimeFns + Sync> ArtiqCodeGenerator<'a, T> {
|
||||
pub fn new(
|
||||
name: String,
|
||||
size_t: IntType<'_>,
|
||||
timeline: &'a (dyn TimeFns + Sync),
|
||||
timeline: &'a T,
|
||||
special_ids: SpecialPythonId,
|
||||
) -> ArtiqCodeGenerator<'a> {
|
||||
) -> ArtiqCodeGenerator<'a, T> {
|
||||
assert!(matches!(size_t.get_bit_width(), 32 | 64));
|
||||
ArtiqCodeGenerator {
|
||||
name,
|
||||
@ -116,9 +116,9 @@ impl<'a> ArtiqCodeGenerator<'a> {
|
||||
name: String,
|
||||
ctx: &Context,
|
||||
target_machine: &TargetMachine,
|
||||
timeline: &'a (dyn TimeFns + Sync),
|
||||
timeline: &'a T,
|
||||
special_ids: SpecialPythonId,
|
||||
) -> ArtiqCodeGenerator<'a> {
|
||||
) -> ArtiqCodeGenerator<'a, T> {
|
||||
let llvm_usize = ctx.ptr_sized_int_type(&target_machine.get_target_data(), None);
|
||||
Self::new(name, llvm_usize, timeline, special_ids)
|
||||
}
|
||||
@ -183,7 +183,7 @@ impl<'a> ArtiqCodeGenerator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
impl CodeGenerator for ArtiqCodeGenerator<'_> {
|
||||
impl<T: TimeFns + Sync> CodeGenerator for ArtiqCodeGenerator<'_, T> {
|
||||
fn get_name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
@ -479,8 +479,8 @@ fn gen_rpc_tag(
|
||||
/// Formats an RPC argument to conform to the expected format required by `send_value`.
|
||||
///
|
||||
/// See `artiq/firmware/libproto_artiq/rpc_proto.rs` for the expected format.
|
||||
fn format_rpc_arg<'ctx>(
|
||||
generator: &mut dyn CodeGenerator,
|
||||
fn format_rpc_arg<'ctx, T: CodeGenerator>(
|
||||
generator: &mut T,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
(arg, arg_ty, arg_idx): (BasicValueEnum<'ctx>, Type, usize),
|
||||
) -> PointerValue<'ctx> {
|
||||
@ -558,8 +558,8 @@ fn format_rpc_arg<'ctx>(
|
||||
}
|
||||
|
||||
/// Formats an RPC return value to conform to the expected format required by NAC3.
|
||||
fn format_rpc_ret<'ctx>(
|
||||
generator: &mut dyn CodeGenerator,
|
||||
fn format_rpc_ret<'ctx, T: CodeGenerator>(
|
||||
generator: &mut T,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
ret_ty: Type,
|
||||
) -> Option<BasicValueEnum<'ctx>> {
|
||||
@ -820,12 +820,12 @@ fn format_rpc_ret<'ctx>(
|
||||
Some(result)
|
||||
}
|
||||
|
||||
fn rpc_codegen_callback_fn<'ctx>(
|
||||
fn rpc_codegen_callback_fn<'ctx, T: CodeGenerator>(
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: Option<(Type, ValueEnum<'ctx>)>,
|
||||
fun: (&FunSignature, DefinitionId),
|
||||
args: Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut T,
|
||||
is_async: bool,
|
||||
) -> Result<Option<BasicValueEnum<'ctx>>, String> {
|
||||
let int8 = ctx.ctx.i8_type();
|
||||
@ -962,9 +962,9 @@ fn rpc_codegen_callback_fn<'ctx>(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn attributes_writeback<'ctx>(
|
||||
pub fn attributes_writeback<'ctx, T: CodeGenerator>(
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut T,
|
||||
inner_resolver: &InnerResolver,
|
||||
host_attributes: &PyObject,
|
||||
return_obj: Option<(Type, ValueEnum<'ctx>)>,
|
||||
@ -1140,9 +1140,9 @@ fn get_fprintf_format_constant<'ctx>(
|
||||
/// * `suffix` - String to terminate the printed string, if any.
|
||||
/// * `as_repr` - Whether the `repr()` output of values instead of `str()`.
|
||||
/// * `as_rtio` - Whether to print to `rtio_log` instead of `core_log`.
|
||||
fn polymorphic_print<'ctx>(
|
||||
fn polymorphic_print<'ctx, T: CodeGenerator>(
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut T,
|
||||
values: &[(Type, ValueEnum<'ctx>)],
|
||||
separator: &str,
|
||||
suffix: Option<&str>,
|
||||
@ -1150,7 +1150,7 @@ fn polymorphic_print<'ctx>(
|
||||
as_rtio: bool,
|
||||
) -> Result<(), String> {
|
||||
let printf = |ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut T,
|
||||
fmt: String,
|
||||
args: Vec<BasicValueEnum<'ctx>>| {
|
||||
debug_assert!(!fmt.is_empty());
|
||||
@ -1184,7 +1184,7 @@ fn polymorphic_print<'ctx>(
|
||||
let mut args = Vec::new();
|
||||
|
||||
let flush = |ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut T,
|
||||
fmt: &mut String,
|
||||
args: &mut Vec<BasicValueEnum<'ctx>>| {
|
||||
if !fmt.is_empty() {
|
||||
@ -1488,9 +1488,9 @@ fn polymorphic_print<'ctx>(
|
||||
}
|
||||
|
||||
/// Invokes the `core_log` intrinsic function.
|
||||
pub fn call_core_log_impl<'ctx>(
|
||||
pub fn call_core_log_impl<'ctx, T: CodeGenerator>(
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut T,
|
||||
arg: (Type, BasicValueEnum<'ctx>),
|
||||
) -> Result<(), String> {
|
||||
let (arg_ty, arg_val) = arg;
|
||||
@ -1501,9 +1501,9 @@ pub fn call_core_log_impl<'ctx>(
|
||||
}
|
||||
|
||||
/// Invokes the `rtio_log` intrinsic function.
|
||||
pub fn call_rtio_log_impl<'ctx>(
|
||||
pub fn call_rtio_log_impl<'ctx, T: CodeGenerator>(
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut T,
|
||||
channel: StructValue<'ctx>,
|
||||
arg: (Type, BasicValueEnum<'ctx>),
|
||||
) -> Result<(), String> {
|
||||
@ -1524,12 +1524,12 @@ pub fn call_rtio_log_impl<'ctx>(
|
||||
}
|
||||
|
||||
/// Generates a call to `core_log`.
|
||||
pub fn gen_core_log<'ctx>(
|
||||
pub fn gen_core_log<'ctx, G: CodeGenerator + ?Sized>(
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: Option<&(Type, ValueEnum<'ctx>)>,
|
||||
fun: (&FunSignature, DefinitionId),
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut G,
|
||||
) -> Result<(), String> {
|
||||
assert!(obj.is_none());
|
||||
assert_eq!(args.len(), 1);
|
||||
@ -1541,12 +1541,12 @@ pub fn gen_core_log<'ctx>(
|
||||
}
|
||||
|
||||
/// Generates a call to `rtio_log`.
|
||||
pub fn gen_rtio_log<'ctx>(
|
||||
pub fn gen_rtio_log<'ctx, T: CodeGenerator>(
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: Option<&(Type, ValueEnum<'ctx>)>,
|
||||
fun: (&FunSignature, DefinitionId),
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut T,
|
||||
) -> Result<(), String> {
|
||||
assert!(obj.is_none());
|
||||
assert_eq!(args.len(), 2);
|
||||
|
@ -303,8 +303,8 @@ impl Nac3 {
|
||||
fn report_modinit(
|
||||
arg_names: &[String],
|
||||
method_name: &str,
|
||||
resolver: &Arc<dyn SymbolResolver + Send + Sync>,
|
||||
top_level_defs: &[Arc<RwLock<TopLevelDef>>],
|
||||
resolver: &Arc<R>,
|
||||
top_level_defs: &[Arc<RwLock<TopLevelDef<R, G, S>>>],
|
||||
unifier: &mut Unifier,
|
||||
primitives: &PrimitiveStore,
|
||||
) -> Option<String> {
|
||||
@ -531,8 +531,7 @@ impl Nac3 {
|
||||
string_store: self.string_store.clone(),
|
||||
exception_ids: self.exception_ids.clone(),
|
||||
deferred_eval_store: self.deferred_eval_store.clone(),
|
||||
})))
|
||||
as Arc<dyn SymbolResolver + Send + Sync>;
|
||||
})));
|
||||
let name_to_pyid = Rc::new(name_to_pyid);
|
||||
let module_location = ast::Location::new(1, 1, stmt.location.file);
|
||||
module_to_resolver_cache.insert(
|
||||
@ -695,7 +694,7 @@ impl Nac3 {
|
||||
deferred_eval_store: self.deferred_eval_store.clone(),
|
||||
});
|
||||
let resolver =
|
||||
Arc::new(Resolver(inner_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>;
|
||||
Arc::new(Resolver(inner_resolver.clone()));
|
||||
let (_, def_id, _) = composer
|
||||
.register_top_level(synthesized.pop().unwrap(), Some(resolver.clone()), "", false)
|
||||
.unwrap();
|
||||
|
@ -119,10 +119,10 @@ impl StaticValue for PythonValue {
|
||||
self.id
|
||||
}
|
||||
|
||||
fn get_const_obj<'ctx>(
|
||||
fn get_const_obj<'ctx, G: CodeGenerator>(
|
||||
&self,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
_: &mut dyn CodeGenerator,
|
||||
_: &mut G,
|
||||
) -> BasicValueEnum<'ctx> {
|
||||
ctx.module.get_global(format!("{}_const", self.id).as_str()).map_or_else(
|
||||
|| {
|
||||
@ -149,10 +149,10 @@ impl StaticValue for PythonValue {
|
||||
)
|
||||
}
|
||||
|
||||
fn to_basic_value_enum<'ctx, 'a>(
|
||||
fn to_basic_value_enum<'ctx, 'a, G: CodeGenerator>(
|
||||
&self,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut G,
|
||||
expected_ty: Type,
|
||||
) -> Result<BasicValueEnum<'ctx>, String> {
|
||||
if let Some(val) = self.resolver.id_to_primitive.read().get(&self.id) {
|
||||
@ -992,12 +992,12 @@ impl InnerResolver {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_obj_value<'ctx>(
|
||||
pub fn get_obj_value<'ctx, G: CodeGenerator>(
|
||||
&self,
|
||||
py: Python,
|
||||
obj: &PyAny,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut G,
|
||||
expected_ty: Type,
|
||||
) -> PyResult<Option<BasicValueEnum<'ctx>>> {
|
||||
let ty_id: u64 =
|
||||
@ -1661,11 +1661,11 @@ impl SymbolResolver for Resolver {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_symbol_value<'ctx>(
|
||||
fn get_symbol_value<'ctx, G: CodeGenerator>(
|
||||
&self,
|
||||
id: StrRef,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut G,
|
||||
) -> Option<ValueEnum<'ctx>> {
|
||||
if let Some(def_id) = self.0.id_to_def.read().get(&id) {
|
||||
let top_levels = ctx.top_level.definitions.read();
|
||||
|
@ -27,7 +27,7 @@ mod slice;
|
||||
mod string;
|
||||
|
||||
#[must_use]
|
||||
pub fn load_irrt<'ctx>(ctx: &'ctx Context, symbol_resolver: &dyn SymbolResolver) -> Module<'ctx> {
|
||||
pub fn load_irrt<'ctx, S: SymbolResolver>(ctx: &'ctx Context, symbol_resolver: &S) -> Module<'ctx> {
|
||||
let bitcode_buf = MemoryBuffer::create_from_memory_range(
|
||||
include_bytes!(concat!(env!("OUT_DIR"), "/irrt.bc")),
|
||||
"irrt_bitcode_buffer",
|
||||
|
@ -80,12 +80,12 @@ mod macros {
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct StaticValueStore {
|
||||
pub struct StaticValueStore<S: StaticValue> {
|
||||
pub lookup: HashMap<Vec<(usize, u64)>, usize>,
|
||||
pub store: Vec<HashMap<usize, Arc<dyn StaticValue + Send + Sync>>>,
|
||||
pub store: Vec<HashMap<usize, Arc<S>>>,
|
||||
}
|
||||
|
||||
pub type VarValue<'ctx> = (PointerValue<'ctx>, Option<Arc<dyn StaticValue + Send + Sync>>, i64);
|
||||
pub type VarValue<'ctx, S> = (PointerValue<'ctx>, Option<Arc<S>>, i64);
|
||||
|
||||
/// Additional options for LLVM during codegen.
|
||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||
@ -168,7 +168,7 @@ impl CodeGenTargetMachineOptions {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CodeGenContext<'ctx, 'a> {
|
||||
pub struct CodeGenContext<'ctx, 'a, R: SymbolResolver, S: StaticValue, G: CodeGenerator> {
|
||||
/// The LLVM context associated with [this context][CodeGenContext].
|
||||
pub ctx: &'ctx Context,
|
||||
|
||||
@ -182,19 +182,19 @@ pub struct CodeGenContext<'ctx, 'a> {
|
||||
pub module: Module<'ctx>,
|
||||
|
||||
/// The [`TopLevelContext`] associated with [this context][CodeGenContext].
|
||||
pub top_level: &'a TopLevelContext,
|
||||
pub top_level: &'a TopLevelContext<R, G>,
|
||||
pub unifier: Unifier,
|
||||
pub resolver: Arc<dyn SymbolResolver + Send + Sync>,
|
||||
pub static_value_store: Arc<Mutex<StaticValueStore>>,
|
||||
pub resolver: Arc<R>,
|
||||
pub static_value_store: Arc<Mutex<StaticValueStore<S>>>,
|
||||
|
||||
/// A [`HashMap`] containing the mapping between the names of variables currently in-scope and
|
||||
/// its value information.
|
||||
pub var_assignment: HashMap<StrRef, VarValue<'ctx>>,
|
||||
pub var_assignment: HashMap<StrRef, VarValue<'ctx, S>>,
|
||||
|
||||
pub type_cache: HashMap<Type, BasicTypeEnum<'ctx>>,
|
||||
pub primitives: PrimitiveStore,
|
||||
pub calls: Arc<HashMap<CodeLocation, CallId>>,
|
||||
pub registry: &'a WorkerRegistry,
|
||||
pub registry: &'a WorkerRegistry<R, G, S>,
|
||||
|
||||
/// Cache for constant strings.
|
||||
pub const_strings: HashMap<String, BasicValueEnum<'ctx>>,
|
||||
@ -235,7 +235,7 @@ pub struct CodeGenContext<'ctx, 'a> {
|
||||
llvm_usize: OnceCell<IntType<'ctx>>,
|
||||
}
|
||||
|
||||
impl<'ctx> CodeGenContext<'ctx, '_> {
|
||||
impl<'ctx, R: SymbolResolver, S: StaticValue, G: CodeGenerator> CodeGenContext<'ctx, '_, R, S, G> {
|
||||
/// Whether the [current basic block][Builder::get_insert_block] referenced by `builder`
|
||||
/// contains a [terminator statement][BasicBlock::get_terminator].
|
||||
pub fn is_terminated(&self) -> bool {
|
||||
@ -276,9 +276,9 @@ impl WithCall {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct WorkerRegistry {
|
||||
sender: Arc<Sender<Option<CodeGenTask>>>,
|
||||
receiver: Arc<Receiver<Option<CodeGenTask>>>,
|
||||
pub struct WorkerRegistry<R: SymbolResolver, G: CodeGenerator, S: StaticValue> {
|
||||
sender: Arc<Sender<Option<CodeGenTask<R>>>>,
|
||||
receiver: Arc<Receiver<Option<CodeGenTask<R>>>>,
|
||||
|
||||
/// Whether any thread in this registry has panicked.
|
||||
panicked: AtomicBool,
|
||||
@ -289,22 +289,22 @@ pub struct WorkerRegistry {
|
||||
/// The number of threads available for this registry.
|
||||
thread_count: usize,
|
||||
wait_condvar: Condvar,
|
||||
top_level_ctx: Arc<TopLevelContext>,
|
||||
static_value_store: Arc<Mutex<StaticValueStore>>,
|
||||
top_level_ctx: Arc<TopLevelContext<R, G>>,
|
||||
static_value_store: Arc<Mutex<StaticValueStore<S>>>,
|
||||
|
||||
/// LLVM-related options for code generation.
|
||||
pub llvm_options: CodeGenLLVMOptions,
|
||||
}
|
||||
|
||||
impl WorkerRegistry {
|
||||
impl<R: SymbolResolver, G: CodeGenerator, S: StaticValue> WorkerRegistry<R, G, S> {
|
||||
/// Creates workers for this registry.
|
||||
#[must_use]
|
||||
pub fn create_workers<G: CodeGenerator + Send + 'static>(
|
||||
pub fn create_workers(
|
||||
generators: Vec<Box<G>>,
|
||||
top_level_ctx: Arc<TopLevelContext>,
|
||||
top_level_ctx: Arc<TopLevelContext<R, G>>,
|
||||
llvm_options: &CodeGenLLVMOptions,
|
||||
f: &Arc<WithCall>,
|
||||
) -> (Arc<WorkerRegistry>, Vec<thread::JoinHandle<()>>) {
|
||||
) -> (Arc<Self>, Vec<thread::JoinHandle<()>>) {
|
||||
let (sender, receiver) = unbounded();
|
||||
let task_count = Mutex::new(0);
|
||||
let wait_condvar = Condvar::new();
|
||||
@ -385,13 +385,13 @@ impl WorkerRegistry {
|
||||
}
|
||||
|
||||
/// Adds a task to this [`WorkerRegistry`].
|
||||
pub fn add_task(&self, task: CodeGenTask) {
|
||||
pub fn add_task(&self, task: CodeGenTask<R>) {
|
||||
*self.task_count.lock() += 1;
|
||||
self.sender.send(Some(task)).unwrap();
|
||||
}
|
||||
|
||||
/// Function executed by worker thread for generating IR for each function.
|
||||
fn worker_thread<G: CodeGenerator>(&self, generator: &mut G, f: &Arc<WithCall>) {
|
||||
fn worker_thread(&self, generator: &mut G, f: &Arc<WithCall>) {
|
||||
let context = Context::create();
|
||||
let mut builder = context.create_builder();
|
||||
let mut module = context.create_module(generator.get_name());
|
||||
@ -472,7 +472,7 @@ impl WorkerRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CodeGenTask {
|
||||
pub struct CodeGenTask<R: SymbolResolver> {
|
||||
pub subst: Vec<(Type, ConcreteType)>,
|
||||
pub store: ConcreteTypeStore,
|
||||
pub symbol_name: String,
|
||||
@ -480,7 +480,7 @@ pub struct CodeGenTask {
|
||||
pub body: Arc<Vec<Stmt<Option<Type>>>>,
|
||||
pub calls: Arc<HashMap<CodeLocation, CallId>>,
|
||||
pub unifier_index: usize,
|
||||
pub resolver: Arc<dyn SymbolResolver + Send + Sync>,
|
||||
pub resolver: Arc<R>,
|
||||
pub id: usize,
|
||||
}
|
||||
|
||||
@ -489,12 +489,12 @@ pub struct CodeGenTask {
|
||||
/// This function is used to obtain the in-memory representation of `ty`, e.g. a `bool` variable
|
||||
/// would be represented by an `i8`.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn get_llvm_type<'ctx, G: CodeGenerator + ?Sized>(
|
||||
fn get_llvm_type<'ctx, R: SymbolResolver, G: CodeGenerator>(
|
||||
ctx: &'ctx Context,
|
||||
module: &Module<'ctx>,
|
||||
generator: &G,
|
||||
unifier: &mut Unifier,
|
||||
top_level: &TopLevelContext,
|
||||
top_level: &TopLevelContext<R, G>,
|
||||
type_cache: &mut HashMap<Type, BasicTypeEnum<'ctx>>,
|
||||
ty: Type,
|
||||
) -> BasicTypeEnum<'ctx> {
|
||||
@ -649,12 +649,12 @@ fn get_llvm_type<'ctx, G: CodeGenerator + ?Sized>(
|
||||
/// be byte-aligned for the variable to be addressable in memory, whereas there is no such
|
||||
/// restriction for ABI representations.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn get_llvm_abi_type<'ctx, G: CodeGenerator + ?Sized>(
|
||||
fn get_llvm_abi_type<'ctx, R: SymbolResolver, G: CodeGenerator>(
|
||||
ctx: &'ctx Context,
|
||||
module: &Module<'ctx>,
|
||||
generator: &G,
|
||||
unifier: &mut Unifier,
|
||||
top_level: &TopLevelContext,
|
||||
top_level: &TopLevelContext<R, G>,
|
||||
type_cache: &mut HashMap<Type, BasicTypeEnum<'ctx>>,
|
||||
primitives: &PrimitiveStore,
|
||||
ty: Type,
|
||||
@ -728,14 +728,16 @@ fn get_llvm_valist_type<'ctx>(ctx: &'ctx Context, triple: &TargetTriple) -> Basi
|
||||
pub fn gen_func_impl<
|
||||
'ctx,
|
||||
G: CodeGenerator,
|
||||
F: FnOnce(&mut G, &mut CodeGenContext) -> Result<(), String>,
|
||||
R: SymbolResolver,
|
||||
S: StaticValue,
|
||||
F: FnOnce(&mut G, &mut CodeGenContext<R, S, G>) -> Result<(), String>,
|
||||
>(
|
||||
context: &'ctx Context,
|
||||
generator: &mut G,
|
||||
registry: &WorkerRegistry,
|
||||
registry: &WorkerRegistry<R, G, S>,
|
||||
builder: Builder<'ctx>,
|
||||
module: Module<'ctx>,
|
||||
task: CodeGenTask,
|
||||
task: CodeGenTask<R>,
|
||||
codegen_function: F,
|
||||
) -> Result<(Builder<'ctx>, Module<'ctx>, FunctionValue<'ctx>), (Builder<'ctx>, String)> {
|
||||
let top_level_ctx = registry.top_level_ctx.clone();
|
||||
@ -1069,13 +1071,13 @@ pub fn gen_func_impl<
|
||||
/// * `module` - The [`Module`] of which the generated LLVM function will be inserted into.
|
||||
/// * `task` - The [`CodeGenTask`] associated with this function generation task.
|
||||
///
|
||||
pub fn gen_func<'ctx, G: CodeGenerator>(
|
||||
pub fn gen_func<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
context: &'ctx Context,
|
||||
generator: &mut G,
|
||||
registry: &WorkerRegistry,
|
||||
registry: &WorkerRegistry<R, G, S>,
|
||||
builder: Builder<'ctx>,
|
||||
module: Module<'ctx>,
|
||||
task: CodeGenTask,
|
||||
task: CodeGenTask<R>,
|
||||
) -> Result<(Builder<'ctx>, Module<'ctx>, FunctionValue<'ctx>), (Builder<'ctx>, String)> {
|
||||
let body = task.body.clone();
|
||||
gen_func_impl(context, generator, registry, builder, module, task, |generator, ctx| {
|
||||
@ -1125,8 +1127,8 @@ fn bool_to_int_type<'ctx>(
|
||||
/// ```
|
||||
///
|
||||
/// Returns an `i1` [`IntValue`] representing the result of whether the `value` is in the range.
|
||||
fn gen_in_range_check<'ctx>(
|
||||
ctx: &CodeGenContext<'ctx, '_>,
|
||||
fn gen_in_range_check<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
ctx: &CodeGenContext<'ctx, '_, R, S, G>,
|
||||
value: IntValue<'ctx>,
|
||||
stop: IntValue<'ctx>,
|
||||
step: IntValue<'ctx>,
|
||||
@ -1174,16 +1176,16 @@ pub fn get_type_alignment<'ctx>(ty: impl Into<BasicTypeEnum<'ctx>>) -> IntValue<
|
||||
///
|
||||
/// The returned [`PointerValue`] will have a type of `i8*`, a size of at least `size`, and will be
|
||||
/// aligned with the alignment of `align_ty`.
|
||||
pub fn type_aligned_alloca<'ctx, G: CodeGenerator + ?Sized>(
|
||||
pub fn type_aligned_alloca<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
ctx: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
align_ty: impl Into<BasicTypeEnum<'ctx>>,
|
||||
size: IntValue<'ctx>,
|
||||
name: Option<&str>,
|
||||
) -> PointerValue<'ctx> {
|
||||
/// Round `val` up to its modulo `power_of_two`.
|
||||
fn round_up<'ctx>(
|
||||
ctx: &CodeGenContext<'ctx, '_>,
|
||||
fn round_up<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
ctx: &CodeGenContext<'ctx, '_, R, S, G>,
|
||||
val: IntValue<'ctx>,
|
||||
power_of_two: IntValue<'ctx>,
|
||||
) -> IntValue<'ctx> {
|
||||
|
@ -13,7 +13,7 @@ use super::{
|
||||
CodeGenContext, CodeGenerator,
|
||||
};
|
||||
use crate::{
|
||||
symbol_resolver::ValueEnum,
|
||||
symbol_resolver::{StaticValue, SymbolResolver, ValueEnum},
|
||||
toplevel::{
|
||||
helper::{arraylike_flatten_element_type, extract_ndims},
|
||||
numpy::unpack_ndarray_var_tys,
|
||||
@ -23,12 +23,12 @@ use crate::{
|
||||
};
|
||||
|
||||
/// Generates LLVM IR for `ndarray.empty`.
|
||||
pub fn gen_ndarray_empty<'ctx>(
|
||||
context: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx>)>,
|
||||
pub fn gen_ndarray_empty<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
context: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx, S>)>,
|
||||
fun: (&FunSignature, DefinitionId),
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||
generator: &mut dyn CodeGenerator,
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx, S>)],
|
||||
generator: &mut G,
|
||||
) -> Result<PointerValue<'ctx>, String> {
|
||||
assert!(obj.is_none());
|
||||
assert_eq!(args.len(), 1);
|
||||
@ -48,12 +48,12 @@ pub fn gen_ndarray_empty<'ctx>(
|
||||
}
|
||||
|
||||
/// Generates LLVM IR for `ndarray.zeros`.
|
||||
pub fn gen_ndarray_zeros<'ctx>(
|
||||
context: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx>)>,
|
||||
pub fn gen_ndarray_zeros<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
context: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx, S>)>,
|
||||
fun: (&FunSignature, DefinitionId),
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||
generator: &mut dyn CodeGenerator,
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx, S>)],
|
||||
generator: &mut G,
|
||||
) -> Result<PointerValue<'ctx>, String> {
|
||||
assert!(obj.is_none());
|
||||
assert_eq!(args.len(), 1);
|
||||
@ -73,12 +73,12 @@ pub fn gen_ndarray_zeros<'ctx>(
|
||||
}
|
||||
|
||||
/// Generates LLVM IR for `ndarray.ones`.
|
||||
pub fn gen_ndarray_ones<'ctx>(
|
||||
context: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx>)>,
|
||||
pub fn gen_ndarray_ones<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
context: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx, S>)>,
|
||||
fun: (&FunSignature, DefinitionId),
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||
generator: &mut dyn CodeGenerator,
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx, S>)],
|
||||
generator: &mut G,
|
||||
) -> Result<PointerValue<'ctx>, String> {
|
||||
assert!(obj.is_none());
|
||||
assert_eq!(args.len(), 1);
|
||||
@ -98,12 +98,12 @@ pub fn gen_ndarray_ones<'ctx>(
|
||||
}
|
||||
|
||||
/// Generates LLVM IR for `ndarray.full`.
|
||||
pub fn gen_ndarray_full<'ctx>(
|
||||
context: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx>)>,
|
||||
pub fn gen_ndarray_full<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
context: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx, S>)>,
|
||||
fun: (&FunSignature, DefinitionId),
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||
generator: &mut dyn CodeGenerator,
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx, S>)],
|
||||
generator: &mut G,
|
||||
) -> Result<PointerValue<'ctx>, String> {
|
||||
assert!(obj.is_none());
|
||||
assert_eq!(args.len(), 2);
|
||||
@ -130,12 +130,12 @@ pub fn gen_ndarray_full<'ctx>(
|
||||
Ok(ndarray.as_abi_value(context))
|
||||
}
|
||||
|
||||
pub fn gen_ndarray_array<'ctx>(
|
||||
context: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx>)>,
|
||||
pub fn gen_ndarray_array<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
context: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx, S>)>,
|
||||
fun: (&FunSignature, DefinitionId),
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||
generator: &mut dyn CodeGenerator,
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx, S>)],
|
||||
generator: &mut G,
|
||||
) -> Result<PointerValue<'ctx>, String> {
|
||||
assert!(obj.is_none());
|
||||
assert!(matches!(args.len(), 1..=3));
|
||||
@ -170,12 +170,12 @@ pub fn gen_ndarray_array<'ctx>(
|
||||
}
|
||||
|
||||
/// Generates LLVM IR for `ndarray.eye`.
|
||||
pub fn gen_ndarray_eye<'ctx>(
|
||||
context: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx>)>,
|
||||
pub fn gen_ndarray_eye<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
context: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx, S>)>,
|
||||
fun: (&FunSignature, DefinitionId),
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||
generator: &mut dyn CodeGenerator,
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx, S>)],
|
||||
generator: &mut G,
|
||||
) -> Result<PointerValue<'ctx>, String> {
|
||||
assert!(obj.is_none());
|
||||
assert!(matches!(args.len(), 1..=3));
|
||||
@ -229,12 +229,12 @@ pub fn gen_ndarray_eye<'ctx>(
|
||||
}
|
||||
|
||||
/// Generates LLVM IR for `ndarray.identity`.
|
||||
pub fn gen_ndarray_identity<'ctx>(
|
||||
context: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx>)>,
|
||||
pub fn gen_ndarray_identity<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
context: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx, S>)>,
|
||||
fun: (&FunSignature, DefinitionId),
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||
generator: &mut dyn CodeGenerator,
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx, S>)],
|
||||
generator: &mut G,
|
||||
) -> Result<PointerValue<'ctx>, String> {
|
||||
assert!(obj.is_none());
|
||||
assert_eq!(args.len(), 1);
|
||||
@ -257,12 +257,12 @@ pub fn gen_ndarray_identity<'ctx>(
|
||||
}
|
||||
|
||||
/// Generates LLVM IR for `ndarray.copy`.
|
||||
pub fn gen_ndarray_copy<'ctx>(
|
||||
context: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx>)>,
|
||||
pub fn gen_ndarray_copy<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
context: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx, S>)>,
|
||||
_fun: (&FunSignature, DefinitionId),
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||
generator: &mut dyn CodeGenerator,
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx, S>)],
|
||||
generator: &mut G,
|
||||
) -> Result<PointerValue<'ctx>, String> {
|
||||
assert!(obj.is_some());
|
||||
assert!(args.is_empty());
|
||||
@ -278,12 +278,12 @@ pub fn gen_ndarray_copy<'ctx>(
|
||||
}
|
||||
|
||||
/// Generates LLVM IR for `ndarray.fill`.
|
||||
pub fn gen_ndarray_fill<'ctx>(
|
||||
context: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx>)>,
|
||||
pub fn gen_ndarray_fill<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
context: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
obj: &Option<(Type, ValueEnum<'ctx, S>)>,
|
||||
fun: (&FunSignature, DefinitionId),
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx>)],
|
||||
generator: &mut dyn CodeGenerator,
|
||||
args: &[(Option<StrRef>, ValueEnum<'ctx, S>)],
|
||||
generator: &mut G,
|
||||
) -> Result<(), String> {
|
||||
assert!(obj.is_some());
|
||||
assert_eq!(args.len(), 1);
|
||||
@ -306,9 +306,9 @@ pub fn gen_ndarray_fill<'ctx>(
|
||||
///
|
||||
/// The input `NDArray` are flattened and treated as 1D
|
||||
/// The operation is equivalent to `np.dot(arr1.ravel(), arr2.ravel())`
|
||||
pub fn ndarray_dot<'ctx, G: CodeGenerator + ?Sized>(
|
||||
pub fn ndarray_dot<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
generator: &mut G,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
ctx: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
(x1_ty, x1): (Type, BasicValueEnum<'ctx>),
|
||||
(x2_ty, x2): (Type, BasicValueEnum<'ctx>),
|
||||
) -> Result<BasicValueEnum<'ctx>, String> {
|
||||
|
@ -1262,12 +1262,12 @@ pub fn get_builtins<'ctx, G: CodeGenerator + ?Sized>(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn exn_constructor<'ctx>(
|
||||
pub fn exn_constructor<'ctx, G: CodeGenerator>(
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: Option<(Type, ValueEnum<'ctx>)>,
|
||||
_fun: (&FunSignature, DefinitionId),
|
||||
mut args: Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut G,
|
||||
) -> Result<Option<BasicValueEnum<'ctx>>, String> {
|
||||
let (zelf_ty, zelf) = obj.unwrap();
|
||||
let zelf = zelf.to_basic_value_enum(ctx, generator, zelf_ty)?.into_pointer_value();
|
||||
|
@ -23,7 +23,7 @@ use super::{
|
||||
DefaultCodeGenerator, WithCall, WorkerRegistry,
|
||||
};
|
||||
use crate::{
|
||||
symbol_resolver::{SymbolResolver, ValueEnum},
|
||||
symbol_resolver::{StaticValue, SymbolResolver, ValueEnum},
|
||||
toplevel::{
|
||||
composer::{ComposerConfig, TopLevelComposer},
|
||||
DefinitionId, FunInstance, TopLevelContext, TopLevelDef,
|
||||
@ -53,22 +53,22 @@ impl SymbolResolver for Resolver {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_symbol_type(
|
||||
fn get_symbol_type<R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
&self,
|
||||
_: &mut Unifier,
|
||||
_: &[Arc<RwLock<TopLevelDef>>],
|
||||
_: &mut Unifier<R, G, S>,
|
||||
_: &[Arc<RwLock<TopLevelDef<R, G, S>>>],
|
||||
_: &PrimitiveStore,
|
||||
str: StrRef,
|
||||
) -> Result<Type, String> {
|
||||
self.id_to_type.get(&str).copied().ok_or_else(|| format!("cannot find symbol `{str}`"))
|
||||
}
|
||||
|
||||
fn get_symbol_value<'ctx>(
|
||||
fn get_symbol_value<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
&self,
|
||||
_: StrRef,
|
||||
_: &mut CodeGenContext<'ctx, '_>,
|
||||
_: &mut dyn CodeGenerator,
|
||||
) -> Option<ValueEnum<'ctx>> {
|
||||
_: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
_: &mut G,
|
||||
) -> Option<ValueEnum<'ctx, S>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@ -107,8 +107,7 @@ fn test_primitives() {
|
||||
unifier.top_level = Some(top_level.clone());
|
||||
|
||||
let resolver =
|
||||
Arc::new(Resolver { id_to_type: HashMap::new(), id_to_def: RwLock::new(HashMap::new()) })
|
||||
as Arc<dyn SymbolResolver + Send + Sync>;
|
||||
Arc::new(Resolver { id_to_type: HashMap::new(), id_to_def: RwLock::new(HashMap::new()) });
|
||||
|
||||
let threads = vec![DefaultCodeGenerator::new("test".into(), context.i64_type()).into()];
|
||||
let signature = FunSignature {
|
||||
@ -252,7 +251,7 @@ fn test_simple_call() {
|
||||
|
||||
let resolver = Resolver { id_to_type: HashMap::new(), id_to_def: RwLock::new(HashMap::new()) };
|
||||
resolver.add_id_def("foo".into(), DefinitionId(foo_id));
|
||||
let resolver = Arc::new(resolver) as Arc<dyn SymbolResolver + Send + Sync>;
|
||||
let resolver = Arc::new(resolver);
|
||||
|
||||
if let TopLevelDef::Function { resolver: r, .. } =
|
||||
&mut *top_level.definitions.read()[foo_id].write()
|
||||
|
@ -39,11 +39,11 @@ impl SymbolValue {
|
||||
///
|
||||
/// * `constant` - The constant to create the value from.
|
||||
/// * `expected_ty` - The expected type of the [`SymbolValue`].
|
||||
pub fn from_constant(
|
||||
pub fn from_constant<R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
constant: &Constant,
|
||||
expected_ty: Type,
|
||||
primitives: &PrimitiveStore,
|
||||
unifier: &mut Unifier,
|
||||
unifier: &mut Unifier<R, G, S>,
|
||||
) -> Result<Self, String> {
|
||||
match constant {
|
||||
Constant::None => {
|
||||
@ -148,7 +148,7 @@ impl SymbolValue {
|
||||
}
|
||||
|
||||
/// Returns the [`Type`] representing the data type of this value.
|
||||
pub fn get_type(&self, primitives: &PrimitiveStore, unifier: &mut Unifier) -> Type {
|
||||
pub fn get_type<R: SymbolResolver, G: CodeGenerator, S: StaticValue>(&self, primitives: &PrimitiveStore, unifier: &mut Unifier<R, G, S>) -> Type {
|
||||
match self {
|
||||
SymbolValue::I32(_) => primitives.int32,
|
||||
SymbolValue::I64(_) => primitives.int64,
|
||||
@ -166,10 +166,10 @@ impl SymbolValue {
|
||||
}
|
||||
|
||||
/// Returns the [`TypeAnnotation`] representing the data type of this value.
|
||||
pub fn get_type_annotation(
|
||||
pub fn get_type_annotation<R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
&self,
|
||||
primitives: &PrimitiveStore,
|
||||
unifier: &mut Unifier,
|
||||
unifier: &mut Unifier<R, G, S>,
|
||||
) -> TypeAnnotation {
|
||||
match self {
|
||||
SymbolValue::Bool(..)
|
||||
@ -201,10 +201,10 @@ impl SymbolValue {
|
||||
}
|
||||
|
||||
/// Returns the [`TypeEnum`] representing the data type of this value.
|
||||
pub fn get_type_enum(
|
||||
pub fn get_type_enum<R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
&self,
|
||||
primitives: &PrimitiveStore,
|
||||
unifier: &mut Unifier,
|
||||
unifier: &mut Unifier<R, G, S>,
|
||||
) -> Rc<TypeEnum> {
|
||||
let ty = self.get_type(primitives, unifier);
|
||||
unifier.get_ty(ty)
|
||||
@ -273,76 +273,76 @@ pub trait StaticValue {
|
||||
fn get_unique_identifier(&self) -> u64;
|
||||
|
||||
/// Returns the constant object represented by this unique identifier.
|
||||
fn get_const_obj<'ctx>(
|
||||
fn get_const_obj<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
&self,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
ctx: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
generator: &mut G,
|
||||
) -> BasicValueEnum<'ctx>;
|
||||
|
||||
/// Converts this value to a LLVM [`BasicValueEnum`].
|
||||
fn to_basic_value_enum<'ctx>(
|
||||
fn to_basic_value_enum<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
&self,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
ctx: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
generator: &mut G,
|
||||
expected_ty: Type,
|
||||
) -> Result<BasicValueEnum<'ctx>, String>;
|
||||
|
||||
/// Returns a field within this value.
|
||||
fn get_field<'ctx>(
|
||||
fn get_field<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
&self,
|
||||
name: StrRef,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
) -> Option<ValueEnum<'ctx>>;
|
||||
ctx: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
) -> Option<ValueEnum<'ctx, S>>;
|
||||
|
||||
/// Returns a single element of this tuple.
|
||||
fn get_tuple_element<'ctx>(&self, index: u32) -> Option<ValueEnum<'ctx>>;
|
||||
fn get_tuple_element<'ctx, S: StaticValue>(&self, index: u32) -> Option<ValueEnum<'ctx, S>>;
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum ValueEnum<'ctx> {
|
||||
pub enum ValueEnum<'ctx, S: StaticValue> {
|
||||
/// [`ValueEnum`] representing a static value.
|
||||
Static(Arc<dyn StaticValue + Send + Sync>),
|
||||
Static(Arc<S>),
|
||||
|
||||
/// [`ValueEnum`] representing a dynamic value.
|
||||
Dynamic(BasicValueEnum<'ctx>),
|
||||
}
|
||||
|
||||
impl<'ctx> From<BasicValueEnum<'ctx>> for ValueEnum<'ctx> {
|
||||
impl<'ctx, S: StaticValue> From<BasicValueEnum<'ctx>> for ValueEnum<'ctx, S> {
|
||||
fn from(v: BasicValueEnum<'ctx>) -> Self {
|
||||
ValueEnum::Dynamic(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> From<PointerValue<'ctx>> for ValueEnum<'ctx> {
|
||||
impl<'ctx, S: StaticValue> From<PointerValue<'ctx>> for ValueEnum<'ctx, S> {
|
||||
fn from(v: PointerValue<'ctx>) -> Self {
|
||||
ValueEnum::Dynamic(v.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> From<IntValue<'ctx>> for ValueEnum<'ctx> {
|
||||
impl<'ctx, S: StaticValue> From<IntValue<'ctx>> for ValueEnum<'ctx, S> {
|
||||
fn from(v: IntValue<'ctx>) -> Self {
|
||||
ValueEnum::Dynamic(v.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> From<FloatValue<'ctx>> for ValueEnum<'ctx> {
|
||||
impl<'ctx, S: StaticValue> From<FloatValue<'ctx>> for ValueEnum<'ctx, S> {
|
||||
fn from(v: FloatValue<'ctx>) -> Self {
|
||||
ValueEnum::Dynamic(v.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> From<StructValue<'ctx>> for ValueEnum<'ctx> {
|
||||
impl<'ctx, S: StaticValue> From<StructValue<'ctx>> for ValueEnum<'ctx, S> {
|
||||
fn from(v: StructValue<'ctx>) -> Self {
|
||||
ValueEnum::Dynamic(v.into())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ctx> ValueEnum<'ctx> {
|
||||
impl<'ctx, S: StaticValue> ValueEnum<'ctx, S> {
|
||||
/// Converts this [`ValueEnum`] to a [`BasicValueEnum`].
|
||||
pub fn to_basic_value_enum<'a>(
|
||||
pub fn to_basic_value_enum<'a, R: SymbolResolver, G: CodeGenerator>(
|
||||
self,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
ctx: &mut CodeGenContext<'ctx, 'a, R, S, G>,
|
||||
generator: &mut G,
|
||||
expected_ty: Type,
|
||||
) -> Result<BasicValueEnum<'ctx>, String> {
|
||||
match self {
|
||||
@ -354,10 +354,10 @@ impl<'ctx> ValueEnum<'ctx> {
|
||||
|
||||
pub trait SymbolResolver {
|
||||
/// Get type of type variable identifier or top-level function type,
|
||||
fn get_symbol_type(
|
||||
fn get_symbol_type<R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
&self,
|
||||
unifier: &mut Unifier,
|
||||
top_level_defs: &[Arc<RwLock<TopLevelDef>>],
|
||||
unifier: &mut Unifier<R, G, S>,
|
||||
top_level_defs: &[Arc<RwLock<TopLevelDef<R, G, S>>>],
|
||||
primitives: &PrimitiveStore,
|
||||
str: StrRef,
|
||||
) -> Result<Type, String>;
|
||||
@ -365,21 +365,21 @@ pub trait SymbolResolver {
|
||||
/// Get the top-level definition of identifiers.
|
||||
fn get_identifier_def(&self, str: StrRef) -> Result<DefinitionId, HashSet<String>>;
|
||||
|
||||
fn get_symbol_value<'ctx>(
|
||||
fn get_symbol_value<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
&self,
|
||||
str: StrRef,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
) -> Option<ValueEnum<'ctx>>;
|
||||
ctx: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
generator: &mut G,
|
||||
) -> Option<ValueEnum<'ctx, S>>;
|
||||
|
||||
fn get_default_param_value(&self, expr: &Expr) -> Option<SymbolValue>;
|
||||
fn get_string_id(&self, s: &str) -> i32;
|
||||
fn get_exception_id(&self, tyid: usize) -> usize;
|
||||
|
||||
fn handle_deferred_eval(
|
||||
fn handle_deferred_eval<R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
&self,
|
||||
_unifier: &mut Unifier,
|
||||
_top_level_defs: &[Arc<RwLock<TopLevelDef>>],
|
||||
_unifier: &mut Unifier<R, G, S>,
|
||||
_top_level_defs: &[Arc<RwLock<TopLevelDef<R, G, S>>>],
|
||||
_primitives: &PrimitiveStore,
|
||||
) -> Result<(), String> {
|
||||
Ok(())
|
||||
@ -403,10 +403,10 @@ thread_local! {
|
||||
}
|
||||
|
||||
/// Converts a type annotation into a [Type].
|
||||
pub fn parse_type_annotation<T>(
|
||||
resolver: &dyn SymbolResolver,
|
||||
top_level_defs: &[Arc<RwLock<TopLevelDef>>],
|
||||
unifier: &mut Unifier,
|
||||
pub fn parse_type_annotation<T, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
resolver: &R,
|
||||
top_level_defs: &[Arc<RwLock<TopLevelDef<R, G, S>>>],
|
||||
unifier: &mut Unifier<R, G, S>,
|
||||
primitives: &PrimitiveStore,
|
||||
expr: &Expr<T>,
|
||||
) -> Result<Type, HashSet<String>> {
|
||||
@ -424,7 +424,7 @@ pub fn parse_type_annotation<T>(
|
||||
let uint64_id = ids[9];
|
||||
let literal_id = ids[10];
|
||||
|
||||
let name_handling = |id: &StrRef, loc: Location, unifier: &mut Unifier| {
|
||||
let name_handling = |id: &StrRef, loc: Location, unifier: &mut Unifier<R, G, S>| {
|
||||
if *id == int32_id {
|
||||
Ok(primitives.int32)
|
||||
} else if *id == int64_id {
|
||||
@ -475,7 +475,7 @@ pub fn parse_type_annotation<T>(
|
||||
}
|
||||
};
|
||||
|
||||
let subscript_name_handle = |id: &StrRef, slice: &Expr<T>, unifier: &mut Unifier| {
|
||||
let subscript_name_handle = |id: &StrRef, slice: &Expr<T>, unifier: &mut Unifier<R, G, S>| {
|
||||
if *id == virtual_id {
|
||||
let ty = parse_type_annotation(resolver, top_level_defs, unifier, primitives, slice)?;
|
||||
Ok(unifier.add_ty(TypeEnum::TVirtual { ty }))
|
||||
@ -577,43 +577,3 @@ pub fn parse_type_annotation<T>(
|
||||
_ => Err(HashSet::from([format!("unsupported type expression at {}", expr.location)])),
|
||||
}
|
||||
}
|
||||
|
||||
impl dyn SymbolResolver + Send + Sync {
|
||||
pub fn parse_type_annotation<T>(
|
||||
&self,
|
||||
top_level_defs: &[Arc<RwLock<TopLevelDef>>],
|
||||
unifier: &mut Unifier,
|
||||
primitives: &PrimitiveStore,
|
||||
expr: &Expr<T>,
|
||||
) -> Result<Type, HashSet<String>> {
|
||||
parse_type_annotation(self, top_level_defs, unifier, primitives, expr)
|
||||
}
|
||||
|
||||
pub fn get_type_name(
|
||||
&self,
|
||||
top_level_defs: &[Arc<RwLock<TopLevelDef>>],
|
||||
unifier: &mut Unifier,
|
||||
ty: Type,
|
||||
) -> String {
|
||||
unifier.internal_stringify(
|
||||
ty,
|
||||
&mut |id| {
|
||||
let top_level_def = &*top_level_defs[id].read();
|
||||
let (TopLevelDef::Class { name, .. } | TopLevelDef::Module { name, .. }) =
|
||||
top_level_def
|
||||
else {
|
||||
unreachable!("expected class/module definition")
|
||||
};
|
||||
name.to_string()
|
||||
},
|
||||
&mut |id| format!("typevar{id}"),
|
||||
&mut None,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for dyn SymbolResolver + Send + Sync {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "")
|
||||
}
|
||||
}
|
||||
|
@ -24,10 +24,10 @@ impl Default for ComposerConfig {
|
||||
}
|
||||
}
|
||||
|
||||
pub type DefAst = (Arc<RwLock<TopLevelDef>>, Option<Stmt<()>>);
|
||||
pub struct TopLevelComposer {
|
||||
pub type DefAst<R, G> = (Arc<RwLock<TopLevelDef<R, G>>>, Option<Stmt<()>>);
|
||||
pub struct TopLevelComposer<R: SymbolResolver, G: CodeGenerator> {
|
||||
// list of top level definitions, same as top level context
|
||||
pub definition_ast_list: Vec<DefAst>,
|
||||
pub definition_ast_list: Vec<DefAst<R, G>>,
|
||||
// start as a primitive unifier, will add more top_level defs inside
|
||||
pub unifier: Unifier,
|
||||
// primitive store
|
||||
@ -47,13 +47,13 @@ pub struct TopLevelComposer {
|
||||
|
||||
/// The specification for a builtin function, consisting of the function name, the function
|
||||
/// signature, and a [code generation callback][`GenCall`].
|
||||
pub type BuiltinFuncSpec = (StrRef, FunSignature, Arc<GenCall>);
|
||||
pub type BuiltinFuncSpec<T> = (StrRef, FunSignature, Arc<GenCall<T>>);
|
||||
|
||||
/// A function that creates a [`BuiltinFuncSpec`] using the provided [`PrimitiveStore`] and
|
||||
/// [`Unifier`].
|
||||
pub type BuiltinFuncCreator = dyn Fn(&PrimitiveStore, &mut Unifier) -> BuiltinFuncSpec;
|
||||
pub type BuiltinFuncCreator<T> = dyn Fn(&PrimitiveStore, &mut Unifier) -> BuiltinFuncSpec<T>;
|
||||
|
||||
impl TopLevelComposer {
|
||||
impl<R: SymbolResolver, G: CodeGenerator> TopLevelComposer<R, G> {
|
||||
/// return a composer and things to make a "primitive" symbol resolver, so that the symbol
|
||||
/// resolver can later figure out primitive tye definitions when passed a primitive type name
|
||||
///
|
||||
@ -64,8 +64,8 @@ impl TopLevelComposer {
|
||||
/// for method compilation.
|
||||
#[must_use]
|
||||
pub fn new(
|
||||
builtins: Vec<BuiltinFuncSpec>,
|
||||
lateinit_builtins: Vec<Box<BuiltinFuncCreator>>,
|
||||
builtins: Vec<BuiltinFuncSpec<G>>,
|
||||
lateinit_builtins: Vec<Box<BuiltinFuncCreator<G>>>,
|
||||
core_config: ComposerConfig,
|
||||
size_t: u32,
|
||||
) -> (Self, HashMap<StrRef, DefinitionId>, HashMap<StrRef, Type>) {
|
||||
@ -183,7 +183,7 @@ impl TopLevelComposer {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn make_top_level_context(&self) -> TopLevelContext {
|
||||
pub fn make_top_level_context(&self) -> TopLevelContext<T, G> {
|
||||
TopLevelContext {
|
||||
definitions: RwLock::new(
|
||||
self.definition_ast_list.iter().map(|(x, ..)| x.clone()).collect_vec(),
|
||||
@ -199,7 +199,7 @@ impl TopLevelComposer {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn extract_def_list(&self) -> Vec<Arc<RwLock<TopLevelDef>>> {
|
||||
pub fn extract_def_list(&self) -> Vec<Arc<RwLock<TopLevelDef<T, G>>>> {
|
||||
self.definition_ast_list.iter().map(|(def, ..)| def.clone()).collect_vec()
|
||||
}
|
||||
|
||||
@ -208,7 +208,7 @@ impl TopLevelComposer {
|
||||
&mut self,
|
||||
module_name: &str,
|
||||
name_to_pyid: &Rc<HashMap<StrRef, u64>>,
|
||||
resolver: Arc<dyn SymbolResolver + Send + Sync>,
|
||||
resolver: Arc<T>,
|
||||
location: Option<Location>,
|
||||
) -> Result<DefinitionId, String> {
|
||||
let mut methods: HashMap<StrRef, DefinitionId> = HashMap::new();
|
||||
@ -245,15 +245,15 @@ impl TopLevelComposer {
|
||||
pub fn register_top_level(
|
||||
&mut self,
|
||||
ast: Stmt<()>,
|
||||
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
||||
resolver: Option<Arc<T>>,
|
||||
mod_path: &str,
|
||||
allow_no_constructor: bool,
|
||||
) -> Result<(StrRef, DefinitionId, Option<Type>), String> {
|
||||
type MethodInfo = (
|
||||
type MethodInfo<T, G> = (
|
||||
// the simple method name without class name
|
||||
StrRef,
|
||||
// in this top level def, method name is prefixed with the class name
|
||||
Arc<RwLock<TopLevelDef>>,
|
||||
Arc<RwLock<TopLevelDef<T, G>>>,
|
||||
DefinitionId,
|
||||
Type,
|
||||
Stmt<()>,
|
||||
@ -468,7 +468,7 @@ impl TopLevelComposer {
|
||||
&mut self,
|
||||
name: Ident,
|
||||
annotation: Option<Expr>,
|
||||
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
||||
resolver: Option<Arc<T>>,
|
||||
mod_path: &str,
|
||||
location: Location,
|
||||
) -> Result<(StrRef, DefinitionId, Option<Type>), String> {
|
||||
|
@ -376,7 +376,7 @@ pub fn make_exception_fields(int32: Type, int64: Type, str: Type) -> Vec<(StrRef
|
||||
]
|
||||
}
|
||||
|
||||
impl TopLevelDef {
|
||||
impl<R: SymbolResolver, G: CodeGenerator> TopLevelDef<R, G> {
|
||||
pub fn to_string(&self, unifier: &mut Unifier) -> String {
|
||||
match self {
|
||||
TopLevelDef::Module { name, attributes, methods, .. } => {
|
||||
@ -432,7 +432,7 @@ impl TopLevelDef {
|
||||
}
|
||||
}
|
||||
|
||||
impl TopLevelComposer {
|
||||
impl<R: SymbolResolver, G: CodeGenerator> TopLevelComposer<R, G> {
|
||||
#[must_use]
|
||||
pub fn make_primitives(size_t: u32) -> (PrimitiveStore, Unifier) {
|
||||
let mut unifier = Unifier::new();
|
||||
@ -588,11 +588,11 @@ impl TopLevelComposer {
|
||||
#[must_use]
|
||||
pub fn make_top_level_class_def(
|
||||
obj_id: DefinitionId,
|
||||
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
||||
resolver: Option<Arc<R>>,
|
||||
name: StrRef,
|
||||
constructor: Option<Type>,
|
||||
loc: Option<Location>,
|
||||
) -> TopLevelDef {
|
||||
) -> TopLevelDef<R, G> {
|
||||
TopLevelDef::Class {
|
||||
name,
|
||||
object_id: obj_id,
|
||||
@ -613,9 +613,9 @@ impl TopLevelComposer {
|
||||
name: String,
|
||||
simple_name: StrRef,
|
||||
ty: Type,
|
||||
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
||||
resolver: Option<Arc<R>>,
|
||||
loc: Option<Location>,
|
||||
) -> TopLevelDef {
|
||||
) -> TopLevelDef<R, G> {
|
||||
TopLevelDef::Function {
|
||||
name,
|
||||
simple_name,
|
||||
@ -630,14 +630,14 @@ impl TopLevelComposer {
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn make_top_level_variable_def(
|
||||
pub fn make_top_level_variable_def<S: SymbolResolver>(
|
||||
name: String,
|
||||
simple_name: StrRef,
|
||||
ty: Type,
|
||||
ty_decl: Option<Expr>,
|
||||
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
||||
resolver: Option<Arc<S>>,
|
||||
loc: Option<Location>,
|
||||
) -> TopLevelDef {
|
||||
) -> TopLevelDef<R, G> {
|
||||
TopLevelDef::Variable { name, simple_name, ty, ty_decl, resolver, loc }
|
||||
}
|
||||
|
||||
@ -914,9 +914,9 @@ impl TopLevelComposer {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn parse_parameter_default_value(
|
||||
pub fn parse_parameter_default_value<S: SymbolResolver>(
|
||||
default: &ast::Expr,
|
||||
resolver: &(dyn SymbolResolver + Send + Sync),
|
||||
resolver: &Arc<S>,
|
||||
) -> Result<SymbolValue, HashSet<String>> {
|
||||
parse_parameter_default_value(default, resolver)
|
||||
}
|
||||
@ -1104,9 +1104,9 @@ impl TopLevelComposer {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse_parameter_default_value(
|
||||
pub fn parse_parameter_default_value<S: SymbolResolver>(
|
||||
default: &ast::Expr,
|
||||
resolver: &(dyn SymbolResolver + Send + Sync),
|
||||
resolver: &Arc<S>,
|
||||
) -> Result<SymbolValue, HashSet<String>> {
|
||||
fn handle_constant(val: &Constant, loc: &Location) -> Result<SymbolValue, HashSet<String>> {
|
||||
match val {
|
||||
|
@ -14,7 +14,7 @@ use nac3parser::ast::{self, Expr, Location, Stmt, StrRef};
|
||||
|
||||
use crate::{
|
||||
codegen::{CodeGenContext, CodeGenerator},
|
||||
symbol_resolver::{SymbolResolver, ValueEnum},
|
||||
symbol_resolver::{StaticValue, SymbolResolver, ValueEnum},
|
||||
typecheck::{
|
||||
type_inferencer::{CodeLocation, PrimitiveStore},
|
||||
typedef::{
|
||||
@ -37,46 +37,46 @@ pub mod type_annotation;
|
||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash, Debug)]
|
||||
pub struct DefinitionId(pub usize);
|
||||
|
||||
type GenCallCallback = dyn for<'ctx, 'a> Fn(
|
||||
&mut CodeGenContext<'ctx, 'a>,
|
||||
Option<(Type, ValueEnum<'ctx>)>,
|
||||
type GenCallCallback<R, G, S> = dyn for<'ctx, 'a> Fn(
|
||||
&mut CodeGenContext<'ctx, 'a, R, S, G>,
|
||||
Option<(Type, ValueEnum<'ctx, S>)>,
|
||||
(&FunSignature, DefinitionId),
|
||||
Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
|
||||
&mut dyn CodeGenerator,
|
||||
Vec<(Option<StrRef>, ValueEnum<'ctx, S>)>,
|
||||
&mut G,
|
||||
) -> Result<Option<BasicValueEnum<'ctx>>, String>
|
||||
+ Send
|
||||
+ Sync;
|
||||
|
||||
pub struct GenCall {
|
||||
fp: Box<GenCallCallback>,
|
||||
pub struct GenCall<R: SymbolResolver, G: CodeGenerator, S: StaticValue> {
|
||||
fp: Box<GenCallCallback<R, G, S>>,
|
||||
}
|
||||
|
||||
impl GenCall {
|
||||
impl<R: SymbolResolver, G: CodeGenerator, S: StaticValue> GenCall<R, G, S> {
|
||||
#[must_use]
|
||||
pub fn new(fp: Box<GenCallCallback>) -> GenCall {
|
||||
pub fn new(fp: Box<GenCallCallback<R, G, S>>) -> GenCall<R, G, S> {
|
||||
GenCall { fp }
|
||||
}
|
||||
|
||||
/// Creates a dummy instance of [`GenCall`], which invokes [`unreachable!()`] with the given
|
||||
/// `reason`.
|
||||
#[must_use]
|
||||
pub fn create_dummy(reason: String) -> GenCall {
|
||||
pub fn create_dummy(reason: String) -> GenCall<R, G, S> {
|
||||
Self::new(Box::new(move |_, _, _, _, _| unreachable!("{reason}")))
|
||||
}
|
||||
|
||||
pub fn run<'ctx>(
|
||||
&self,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
obj: Option<(Type, ValueEnum<'ctx>)>,
|
||||
ctx: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
obj: Option<(Type, ValueEnum<'ctx, S>)>,
|
||||
fun: (&FunSignature, DefinitionId),
|
||||
args: Vec<(Option<StrRef>, ValueEnum<'ctx>)>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
args: Vec<(Option<StrRef>, ValueEnum<'ctx, S>)>,
|
||||
generator: &mut G,
|
||||
) -> Result<Option<BasicValueEnum<'ctx>>, String> {
|
||||
(self.fp)(ctx, obj, fun, args, generator)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for GenCall {
|
||||
impl<R: SymbolResolver, G: CodeGenerator, S: StaticValue> Debug for GenCall<R, G, S> {
|
||||
fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
Ok(())
|
||||
}
|
||||
@ -91,7 +91,7 @@ pub struct FunInstance {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum TopLevelDef {
|
||||
pub enum TopLevelDef<R: SymbolResolver, G: CodeGenerator, S: StaticValue> {
|
||||
Module {
|
||||
/// Name of the module
|
||||
name: StrRef,
|
||||
@ -102,7 +102,7 @@ pub enum TopLevelDef {
|
||||
/// `DefinitionId` of `TopLevelDef::{Variable}` within the module
|
||||
attributes: Vec<(StrRef, DefinitionId)>,
|
||||
/// Symbol resolver of the module defined the class.
|
||||
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
||||
resolver: Option<Arc<R>>,
|
||||
/// Definition location.
|
||||
loc: Option<Location>,
|
||||
},
|
||||
@ -126,7 +126,7 @@ pub enum TopLevelDef {
|
||||
/// Ancestor classes, including itself.
|
||||
ancestors: Vec<TypeAnnotation>,
|
||||
/// Symbol resolver of the module defined the class; [None] if it is built-in type.
|
||||
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
||||
resolver: Option<Arc<R>>,
|
||||
/// Constructor type.
|
||||
constructor: Option<Type>,
|
||||
/// Definition location.
|
||||
@ -156,9 +156,9 @@ pub enum TopLevelDef {
|
||||
/// Rigid type variables that would be substituted when the function is instantiated.
|
||||
instance_to_stmt: HashMap<String, FunInstance>,
|
||||
/// Symbol resolver of the module defined the class.
|
||||
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
||||
resolver: Option<Arc<R>>,
|
||||
/// Custom code generation callback.
|
||||
codegen_callback: Option<Arc<GenCall>>,
|
||||
codegen_callback: Option<Arc<GenCall<R, G, S>>>,
|
||||
/// Definition location.
|
||||
loc: Option<Location>,
|
||||
},
|
||||
@ -176,15 +176,16 @@ pub enum TopLevelDef {
|
||||
ty_decl: Option<Expr>,
|
||||
|
||||
/// Symbol resolver of the module defined the class.
|
||||
resolver: Option<Arc<dyn SymbolResolver + Send + Sync>>,
|
||||
resolver: Option<Arc<R>>,
|
||||
|
||||
/// Definition location.
|
||||
loc: Option<Location>,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct TopLevelContext {
|
||||
pub definitions: Arc<RwLock<Vec<Arc<RwLock<TopLevelDef>>>>>,
|
||||
pub struct TopLevelContext<R: SymbolResolver, G: CodeGenerator, S: StaticValue>
|
||||
{
|
||||
pub definitions: Arc<RwLock<Vec<Arc<RwLock<TopLevelDef<R, G, S>>>>>>,
|
||||
pub unifiers: Arc<RwLock<Vec<(SharedUnifier, PrimitiveStore)>>>,
|
||||
pub personality_symbol: Option<String>,
|
||||
}
|
||||
|
@ -44,10 +44,10 @@ impl SymbolResolver for Resolver {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_symbol_type(
|
||||
fn get_symbol_type<R: SymbolResolver, G: CodeGenerator>(
|
||||
&self,
|
||||
_: &mut Unifier,
|
||||
_: &[Arc<RwLock<TopLevelDef>>],
|
||||
_: &[Arc<RwLock<TopLevelDef<R, G>>>],
|
||||
_: &PrimitiveStore,
|
||||
str: StrRef,
|
||||
) -> Result<Type, String> {
|
||||
@ -59,11 +59,11 @@ impl SymbolResolver for Resolver {
|
||||
.ok_or_else(|| format!("cannot find symbol `{str}`"))
|
||||
}
|
||||
|
||||
fn get_symbol_value<'ctx>(
|
||||
fn get_symbol_value<'ctx, G: CodeGenerator>(
|
||||
&self,
|
||||
_: StrRef,
|
||||
_: &mut CodeGenContext<'ctx, '_>,
|
||||
_: &mut dyn CodeGenerator,
|
||||
_: &mut G,
|
||||
) -> Option<ValueEnum<'ctx>> {
|
||||
unimplemented!()
|
||||
}
|
||||
@ -181,7 +181,7 @@ fn test_simple_function_analyze(source: &[&str], tys: &[&str], names: &[&str]) {
|
||||
let internal_resolver =
|
||||
Arc::new(ResolverInternal { id_to_def: Mutex::default(), id_to_type: Mutex::default() });
|
||||
let resolver =
|
||||
Arc::new(Resolver(internal_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>;
|
||||
Arc::new(Resolver(internal_resolver.clone()));
|
||||
|
||||
for s in source {
|
||||
let ast = parse_program(s, FileName::default()).unwrap();
|
||||
@ -550,7 +550,7 @@ fn test_analyze(source: &[&str], res: &[&str], case_name: &str) {
|
||||
print,
|
||||
);
|
||||
let resolver =
|
||||
Arc::new(Resolver(internal_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>;
|
||||
Arc::new(Resolver(internal_resolver.clone()));
|
||||
|
||||
for s in source {
|
||||
let ast = parse_program(s, FileName::default()).unwrap();
|
||||
@ -737,7 +737,7 @@ fn test_inference(source: Vec<&str>, res: &[&str]) {
|
||||
print,
|
||||
);
|
||||
let resolver =
|
||||
Arc::new(Resolver(internal_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>;
|
||||
Arc::new(Resolver(internal_resolver.clone()));
|
||||
|
||||
for s in source {
|
||||
let ast = parse_program(s, FileName::default()).unwrap();
|
||||
|
@ -26,7 +26,7 @@ pub enum TypeAnnotation {
|
||||
}
|
||||
|
||||
impl TypeAnnotation {
|
||||
pub fn stringify(&self, unifier: &mut Unifier) -> String {
|
||||
pub fn stringify<R: SymbolResolver, G: CodeGenerator, S: StaticValue>(&self, unifier: &mut Unifier<R, G, S>) -> String {
|
||||
use TypeAnnotation::*;
|
||||
match self {
|
||||
Primitive(ty) | TypeVar(ty) => unifier.stringify(*ty),
|
||||
@ -70,18 +70,18 @@ impl TypeAnnotation {
|
||||
/// generic variables associated with the definition.
|
||||
/// * `type_var` - The type variable associated with the type argument currently being parsed. Pass
|
||||
/// [`None`] when this function is invoked externally.
|
||||
pub fn parse_ast_to_type_annotation_kinds<T, S: std::hash::BuildHasher + Clone>(
|
||||
resolver: &(dyn SymbolResolver + Send + Sync),
|
||||
top_level_defs: &[Arc<RwLock<TopLevelDef>>],
|
||||
unifier: &mut Unifier,
|
||||
pub fn parse_ast_to_type_annotation_kinds<T, H: std::hash::BuildHasher + Clone, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
resolver: &Arc<R>,
|
||||
top_level_defs: &[Arc<RwLock<TopLevelDef<R, G, S>>>],
|
||||
unifier: &mut Unifier<R, G, S>,
|
||||
primitives: &PrimitiveStore,
|
||||
expr: &ast::Expr<T>,
|
||||
// the key stores the type_var of this topleveldef::class, we only need this field here
|
||||
locked: HashMap<DefinitionId, Vec<Type>, S>,
|
||||
locked: HashMap<DefinitionId, Vec<Type>, H>,
|
||||
) -> Result<TypeAnnotation, HashSet<String>> {
|
||||
let name_handle = |id: &StrRef,
|
||||
unifier: &mut Unifier,
|
||||
locked: HashMap<DefinitionId, Vec<Type>, S>| {
|
||||
unifier: &mut Unifier<R, G, S>,
|
||||
locked: HashMap<DefinitionId, Vec<Type>, H>| {
|
||||
if id == &"int32".into() {
|
||||
Ok(TypeAnnotation::Primitive(primitives.int32))
|
||||
} else if id == &"int64".into() {
|
||||
@ -151,8 +151,8 @@ pub fn parse_ast_to_type_annotation_kinds<T, S: std::hash::BuildHasher + Clone>(
|
||||
let class_name_handle =
|
||||
|id: &StrRef,
|
||||
slice: &ast::Expr<T>,
|
||||
unifier: &mut Unifier,
|
||||
mut locked: HashMap<DefinitionId, Vec<Type>, S>| {
|
||||
unifier: &mut Unifier<R, G, S>,
|
||||
mut locked: HashMap<DefinitionId, Vec<Type>, H>| {
|
||||
if ["virtual".into(), "Generic".into(), "tuple".into(), "Option".into()].contains(id) {
|
||||
return Err(HashSet::from([format!(
|
||||
"keywords cannot be class name (at {})",
|
||||
@ -369,9 +369,9 @@ pub fn parse_ast_to_type_annotation_kinds<T, S: std::hash::BuildHasher + Clone>(
|
||||
// no need to have the `locked` parameter, unlike the `parse_ast_to_type_annotation_kinds`, since
|
||||
// when calling this function, there should be no topleveldef::class being write, and this function
|
||||
// also only read the toplevedefs
|
||||
pub fn get_type_from_type_annotation_kinds(
|
||||
top_level_defs: &[Arc<RwLock<TopLevelDef>>],
|
||||
unifier: &mut Unifier,
|
||||
pub fn get_type_from_type_annotation_kinds<R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
top_level_defs: &[Arc<RwLock<TopLevelDef<R, G, S>>>],
|
||||
unifier: &mut Unifier<R, G, S>,
|
||||
primitives: &PrimitiveStore,
|
||||
ann: &TypeAnnotation,
|
||||
subst_list: &mut Option<Vec<Type>>,
|
||||
@ -379,7 +379,7 @@ pub fn get_type_from_type_annotation_kinds(
|
||||
match ann {
|
||||
TypeAnnotation::CustomClass { id: obj_id, params } => {
|
||||
let def_read = top_level_defs[obj_id.0].read();
|
||||
let class_def: &TopLevelDef = &def_read;
|
||||
let class_def: &TopLevelDef<R, G, S> = &def_read;
|
||||
let TopLevelDef::Class { fields, methods, type_vars, .. } = class_def else {
|
||||
unreachable!("should be class def here")
|
||||
};
|
||||
@ -618,10 +618,10 @@ pub fn get_type_var_contained_in_type_annotation(ann: &TypeAnnotation) -> Vec<Ty
|
||||
}
|
||||
|
||||
/// check the type compatibility for overload
|
||||
pub fn check_overload_type_annotation_compatible(
|
||||
pub fn check_overload_type_annotation_compatible<R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
this: &TypeAnnotation,
|
||||
other: &TypeAnnotation,
|
||||
unifier: &mut Unifier,
|
||||
unifier: &mut Unifier<R, G, S>,
|
||||
) -> bool {
|
||||
match (this, other) {
|
||||
(TypeAnnotation::Primitive(a), TypeAnnotation::Primitive(b)) => a == b,
|
||||
|
@ -24,6 +24,7 @@ use super::{
|
||||
},
|
||||
};
|
||||
use crate::{
|
||||
codegen::CodeGenerator,
|
||||
symbol_resolver::{SymbolResolver, SymbolValue},
|
||||
toplevel::{
|
||||
helper::{arraylike_flatten_element_type, arraylike_get_ndims, PrimDef},
|
||||
@ -122,16 +123,16 @@ impl IdentifierInfo {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FunctionData {
|
||||
pub resolver: Arc<dyn SymbolResolver + Send + Sync>,
|
||||
pub struct FunctionData<R: SymbolResolver> {
|
||||
pub resolver: Arc<R>,
|
||||
pub return_type: Option<Type>,
|
||||
pub bound_variables: Vec<Type>,
|
||||
}
|
||||
|
||||
pub struct Inferencer<'a> {
|
||||
pub top_level: &'a TopLevelContext,
|
||||
pub struct Inferencer<'a, R: SymbolResolver, G: CodeGenerator>{
|
||||
pub top_level: &'a TopLevelContext<R, G>,
|
||||
pub defined_identifiers: HashMap<StrRef, IdentifierInfo>,
|
||||
pub function_data: &'a mut FunctionData,
|
||||
pub function_data: &'a mut FunctionData<T>,
|
||||
pub unifier: &'a mut Unifier,
|
||||
pub primitives: &'a PrimitiveStore,
|
||||
pub virtual_checks: &'a mut Vec<(Type, Type, Location)>,
|
||||
@ -187,7 +188,7 @@ fn fix_assignment_target_context(node: &mut ast::Located<ExprKind>) {
|
||||
}
|
||||
}
|
||||
|
||||
impl Fold<()> for Inferencer<'_> {
|
||||
impl<R: SymbolResolver, G: CodeGenerator> Fold<()> for Inferencer<'_, R, G>{
|
||||
type TargetU = Option<Type>;
|
||||
type Error = InferenceError;
|
||||
|
||||
|
@ -9,8 +9,8 @@ use nac3parser::{ast::FileName, parser::parse_program};
|
||||
|
||||
use super::*;
|
||||
use crate::{
|
||||
codegen::{CodeGenContext, CodeGenerator},
|
||||
symbol_resolver::ValueEnum,
|
||||
codegen::{CodeGenContext, CodeGenerator, DefaultCodeGenerator},
|
||||
symbol_resolver::{StaticValue, ValueEnum},
|
||||
toplevel::{helper::PrimDef, DefinitionId, TopLevelDef},
|
||||
typecheck::{magic_methods::with_fields, typedef::*},
|
||||
};
|
||||
@ -28,22 +28,22 @@ impl SymbolResolver for Resolver {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_symbol_type(
|
||||
fn get_symbol_type<R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
&self,
|
||||
_: &mut Unifier,
|
||||
_: &[Arc<RwLock<TopLevelDef>>],
|
||||
_: &mut Unifier<R, G, S>,
|
||||
_: &[Arc<RwLock<TopLevelDef<R, G, S>>>],
|
||||
_: &PrimitiveStore,
|
||||
str: StrRef,
|
||||
) -> Result<Type, String> {
|
||||
self.id_to_type.get(&str).copied().ok_or_else(|| format!("cannot find symbol `{str}`"))
|
||||
}
|
||||
|
||||
fn get_symbol_value<'ctx>(
|
||||
fn get_symbol_value<'ctx, R: SymbolResolver, G: CodeGenerator, S: StaticValue>(
|
||||
&self,
|
||||
_: StrRef,
|
||||
_: &mut CodeGenContext<'ctx, '_>,
|
||||
_: &mut dyn CodeGenerator,
|
||||
) -> Option<ValueEnum<'ctx>> {
|
||||
_: &mut CodeGenContext<'ctx, '_, R, S, G>,
|
||||
_: &mut G,
|
||||
) -> Option<ValueEnum<'ctx, S>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
@ -64,14 +64,14 @@ impl SymbolResolver for Resolver {
|
||||
}
|
||||
|
||||
struct TestEnvironment {
|
||||
pub unifier: Unifier,
|
||||
pub function_data: FunctionData,
|
||||
pub unifier: Unifier<Resolver, DefaultCodeGenerator, ()>,
|
||||
pub function_data: FunctionData<Resolver>,
|
||||
pub primitives: PrimitiveStore,
|
||||
pub id_to_name: HashMap<usize, StrRef>,
|
||||
pub identifier_mapping: HashMap<StrRef, Type>,
|
||||
pub virtual_checks: Vec<(Type, Type, Location)>,
|
||||
pub calls: HashMap<CodeLocation, CallId>,
|
||||
pub top_level: TopLevelContext,
|
||||
pub top_level: TopLevelContext<Resolver, DefaultCodeGenerator, ()>,
|
||||
}
|
||||
|
||||
impl TestEnvironment {
|
||||
@ -197,7 +197,7 @@ impl TestEnvironment {
|
||||
let resolver = Arc::new(Resolver {
|
||||
id_to_type: identifier_mapping.clone(),
|
||||
id_to_def: HashMap::default(),
|
||||
}) as Arc<dyn SymbolResolver + Send + Sync>;
|
||||
});
|
||||
|
||||
TestEnvironment {
|
||||
top_level: TopLevelContext {
|
||||
@ -222,7 +222,7 @@ impl TestEnvironment {
|
||||
fn new() -> TestEnvironment {
|
||||
let mut unifier = Unifier::new();
|
||||
let mut identifier_mapping = HashMap::new();
|
||||
let mut top_level_defs: Vec<Arc<RwLock<TopLevelDef>>> = Vec::new();
|
||||
let mut top_level_defs: Vec<Arc<RwLock<TopLevelDef<Resolver, DefaultCodeGenerator>>>> = Vec::new();
|
||||
let int32 = unifier.add_ty(TypeEnum::TObj {
|
||||
obj_id: PrimDef::Int32.id(),
|
||||
fields: HashMap::new(),
|
||||
@ -489,7 +489,7 @@ impl TestEnvironment {
|
||||
("Bar2".into(), DefinitionId(defs + 3)),
|
||||
]
|
||||
.into(),
|
||||
}) as Arc<dyn SymbolResolver + Send + Sync>;
|
||||
});
|
||||
|
||||
TestEnvironment {
|
||||
unifier,
|
||||
@ -507,7 +507,7 @@ impl TestEnvironment {
|
||||
}
|
||||
}
|
||||
|
||||
fn get_inferencer(&mut self) -> Inferencer {
|
||||
fn get_inferencer(&mut self) -> Inferencer<'_, Resolver, DefaultCodeGenerator> {
|
||||
Inferencer {
|
||||
top_level: &self.top_level,
|
||||
function_data: &mut self.function_data,
|
||||
|
@ -20,8 +20,7 @@ use super::{
|
||||
unification_table::{UnificationKey, UnificationTable},
|
||||
};
|
||||
use crate::{
|
||||
symbol_resolver::SymbolValue,
|
||||
toplevel::{helper::PrimDef, DefinitionId, TopLevelContext, TopLevelDef},
|
||||
codegen::CodeGenerator, symbol_resolver::{StaticValue, SymbolResolver, SymbolValue}, toplevel::{helper::PrimDef, DefinitionId, TopLevelContext, TopLevelDef}
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
@ -147,7 +146,7 @@ impl Type {
|
||||
/// Wrapper function for cleaner code so that we don't need to write this long pattern matching
|
||||
/// just to get the field `obj_id`.
|
||||
#[must_use]
|
||||
pub fn obj_id(self, unifier: &Unifier) -> Option<DefinitionId> {
|
||||
pub fn obj_id<R: SymbolResolver, G: CodeGenerator, S: StaticValue>(self, unifier: &Unifier<R, G, S>) -> Option<DefinitionId> {
|
||||
if let TypeEnum::TObj { obj_id, .. } = &*unifier.get_ty_immutable(self) {
|
||||
Some(*obj_id)
|
||||
} else {
|
||||
@ -305,8 +304,8 @@ impl TypeEnum {
|
||||
pub type SharedUnifier = Arc<Mutex<(UnificationTable<TypeEnum>, u32, Vec<Call>)>>;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Unifier {
|
||||
pub(crate) top_level: Option<Arc<TopLevelContext>>,
|
||||
pub struct Unifier<R: SymbolResolver, G: CodeGenerator, S: StaticValue> {
|
||||
pub(crate) top_level: Option<Arc<TopLevelContext<R, G, S>>>,
|
||||
pub(crate) unification_table: UnificationTable<Rc<TypeEnum>>,
|
||||
pub(crate) calls: Vec<Rc<Call>>,
|
||||
var_id_counter: u32,
|
||||
@ -315,16 +314,16 @@ pub struct Unifier {
|
||||
primitive_store: Option<PrimitiveStore>,
|
||||
}
|
||||
|
||||
impl Default for Unifier {
|
||||
impl<R: SymbolResolver, G: CodeGenerator, S: StaticValue> Default for Unifier<R, G, S> {
|
||||
fn default() -> Self {
|
||||
Unifier::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl Unifier {
|
||||
impl<R: SymbolResolver, G: CodeGenerator, S: StaticValue> Unifier<R, G, S> {
|
||||
/// Get an empty unifier
|
||||
#[must_use]
|
||||
pub fn new() -> Unifier {
|
||||
pub fn new() -> Self {
|
||||
Unifier {
|
||||
unification_table: UnificationTable::new(),
|
||||
var_id_counter: 0,
|
||||
@ -362,7 +361,7 @@ impl Unifier {
|
||||
self.unification_table.unioned(a, b)
|
||||
}
|
||||
|
||||
pub fn from_shared_unifier(unifier: &SharedUnifier) -> Unifier {
|
||||
pub fn from_shared_unifier(unifier: &SharedUnifier) -> Self {
|
||||
let lock = unifier.lock().unwrap();
|
||||
Unifier {
|
||||
unification_table: UnificationTable::from_send(&lock.0),
|
||||
@ -1346,16 +1345,16 @@ impl Unifier {
|
||||
}
|
||||
|
||||
/// Get string representation of the type
|
||||
pub fn internal_stringify<F, G>(
|
||||
pub fn internal_stringify<F, V>(
|
||||
&self,
|
||||
ty: Type,
|
||||
obj_to_name: &mut F,
|
||||
var_to_name: &mut G,
|
||||
var_to_name: &mut V,
|
||||
notes: &mut Option<HashMap<TypeVarId, String>>,
|
||||
) -> String
|
||||
where
|
||||
F: FnMut(usize) -> String,
|
||||
G: FnMut(TypeVarId) -> String,
|
||||
V: FnMut(TypeVarId) -> String,
|
||||
{
|
||||
let ty = self.unification_table.probe_value_immutable(ty).clone();
|
||||
match ty.as_ref() {
|
||||
|
@ -71,11 +71,11 @@ impl SymbolResolver for Resolver {
|
||||
.ok_or(format!("cannot get type of {str}"))
|
||||
}
|
||||
|
||||
fn get_symbol_value<'ctx>(
|
||||
fn get_symbol_value<'ctx, T: CodeGenerator>(
|
||||
&self,
|
||||
str: StrRef,
|
||||
ctx: &mut CodeGenContext<'ctx, '_>,
|
||||
generator: &mut dyn CodeGenerator,
|
||||
generator: &mut T,
|
||||
) -> Option<ValueEnum<'ctx>> {
|
||||
self.0.module_globals.lock().get(&str).cloned().map(|v| {
|
||||
ctx.module
|
||||
|
@ -80,7 +80,7 @@ struct CommandLineArgs {
|
||||
|
||||
fn handle_typevar_definition(
|
||||
var: &Expr,
|
||||
resolver: &(dyn SymbolResolver + Send + Sync),
|
||||
resolver: &Arc<Resolver>,
|
||||
def_list: &[Arc<RwLock<TopLevelDef>>],
|
||||
unifier: &mut Unifier,
|
||||
primitives: &PrimitiveStore,
|
||||
@ -169,7 +169,7 @@ fn handle_typevar_definition(
|
||||
fn handle_assignment_pattern(
|
||||
targets: &[Expr],
|
||||
value: &Expr,
|
||||
resolver: Arc<dyn SymbolResolver + Send + Sync>,
|
||||
resolver: Arc<Resolver>,
|
||||
internal_resolver: &ResolverInternal,
|
||||
composer: &mut TopLevelComposer,
|
||||
) -> Result<(), String> {
|
||||
@ -244,7 +244,7 @@ fn handle_assignment_pattern(
|
||||
fn handle_global_var(
|
||||
target: &Expr,
|
||||
value: Option<&Expr>,
|
||||
resolver: &Arc<dyn SymbolResolver + Send + Sync>,
|
||||
resolver: &Arc<Resolver>,
|
||||
internal_resolver: &ResolverInternal,
|
||||
composer: &mut TopLevelComposer,
|
||||
) -> Result<(), String> {
|
||||
@ -342,7 +342,7 @@ fn main() {
|
||||
}
|
||||
.into();
|
||||
let resolver =
|
||||
Arc::new(Resolver(internal_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>;
|
||||
Arc::new(Resolver(internal_resolver.clone()));
|
||||
|
||||
// Process IRRT
|
||||
let irrt = load_irrt(&context, resolver.as_ref());
|
||||
|
Loading…
x
Reference in New Issue
Block a user