Compare commits

...

1 Commits

Author SHA1 Message Date
237a44c477 heavily work in progress 2025-03-21 16:56:22 +08:00
19 changed files with 302 additions and 341 deletions

View File

@ -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);

View File

@ -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();

View File

@ -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();

View File

@ -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",

View File

@ -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> {

View File

@ -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> {

View File

@ -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();

View File

@ -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()

View File

@ -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, "")
}
}

View File

@ -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> {

View File

@ -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 {

View File

@ -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>,
}

View File

@ -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();

View File

@ -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,

View File

@ -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;

View File

@ -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,

View File

@ -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() {

View File

@ -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

View File

@ -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());