Miscellaneous Code Cleanup #364

Merged
sb10q merged 1 commits from code-cleanup into master 2024-08-17 17:37:20 +08:00
4 changed files with 177 additions and 198 deletions

View File

@ -425,7 +425,7 @@ fn rpc_codegen_callback_fn<'ctx>(
if obj.is_some() { if obj.is_some() {
tag.push(b'O'); tag.push(b'O');
} }
for arg in fun.0.args.iter() { for arg in &fun.0.args {
gen_rpc_tag(ctx, arg.ty, &mut tag)?; gen_rpc_tag(ctx, arg.ty, &mut tag)?;
} }
tag.push(b':'); tag.push(b':');
@ -461,7 +461,7 @@ fn rpc_codegen_callback_fn<'ctx>(
}) })
.as_pointer_value(); .as_pointer_value();
let arg_length = args.len() + if obj.is_some() { 1 } else { 0 }; let arg_length = args.len() + usize::from(obj.is_some());
let stacksave = ctx.module.get_function("llvm.stacksave").unwrap_or_else(|| { let stacksave = ctx.module.get_function("llvm.stacksave").unwrap_or_else(|| {
ctx.module.add_function("llvm.stacksave", ptr_type.fn_type(&[], false), None) ctx.module.add_function("llvm.stacksave", ptr_type.fn_type(&[], false), None)
@ -484,11 +484,11 @@ fn rpc_codegen_callback_fn<'ctx>(
// -- rpc args handling // -- rpc args handling
let mut keys = fun.0.args.clone(); let mut keys = fun.0.args.clone();
let mut mapping = HashMap::new(); let mut mapping = HashMap::new();
for (key, value) in args.into_iter() { for (key, value) in args {
mapping.insert(key.unwrap_or_else(|| keys.remove(0).name), value); mapping.insert(key.unwrap_or_else(|| keys.remove(0).name), value);
} }
// default value handling // default value handling
for k in keys.into_iter() { for k in keys {
mapping.insert( mapping.insert(
k.name, k.name,
ctx.gen_symbol_val(generator, &k.default_value.unwrap(), k.ty).into() ctx.gen_symbol_val(generator, &k.default_value.unwrap(), k.ty).into()
@ -518,7 +518,7 @@ fn rpc_codegen_callback_fn<'ctx>(
ctx.builder.build_gep( ctx.builder.build_gep(
args_ptr, args_ptr,
&[int32.const_int(i as u64, false)], &[int32.const_int(i as u64, false)],
&format!("rpc.arg{}", i), &format!("rpc.arg{i}"),
) )
}; };
ctx.builder.build_store(arg_ptr, arg_slot); ctx.builder.build_store(arg_ptr, arg_slot);
@ -621,7 +621,7 @@ pub fn attributes_writeback(
ctx: &mut CodeGenContext<'_, '_>, ctx: &mut CodeGenContext<'_, '_>,
generator: &mut dyn CodeGenerator, generator: &mut dyn CodeGenerator,
inner_resolver: &InnerResolver, inner_resolver: &InnerResolver,
host_attributes: PyObject, host_attributes: &PyObject,
) -> Result<(), String> { ) -> Result<(), String> {
Python::with_gil(|py| -> PyResult<Result<(), String>> { Python::with_gil(|py| -> PyResult<Result<(), String>> {
let host_attributes: &PyList = host_attributes.downcast(py)?; let host_attributes: &PyList = host_attributes.downcast(py)?;
@ -631,7 +631,7 @@ pub fn attributes_writeback(
let zero = int32.const_zero(); let zero = int32.const_zero();
let mut values = Vec::new(); let mut values = Vec::new();
let mut scratch_buffer = Vec::new(); let mut scratch_buffer = Vec::new();
for (_, val) in globals.iter() { for val in (*globals).values() {
let val = val.as_ref(py); let val = val.as_ref(py);
let ty = inner_resolver.get_obj_type(py, val, &mut ctx.unifier, &top_levels, &ctx.primitives)?; let ty = inner_resolver.get_obj_type(py, val, &mut ctx.unifier, &top_levels, &ctx.primitives)?;
if let Err(ty) = ty { if let Err(ty) = ty {
@ -646,7 +646,7 @@ pub fn attributes_writeback(
// for non-primitive attributes, they should be in another global // for non-primitive attributes, they should be in another global
let mut attributes = Vec::new(); let mut attributes = Vec::new();
let obj = inner_resolver.get_obj_value(py, val, ctx, generator, ty)?.unwrap(); let obj = inner_resolver.get_obj_value(py, val, ctx, generator, ty)?.unwrap();
for (name, (field_ty, is_mutable)) in fields.iter() { for (name, (field_ty, is_mutable)) in fields {
if !is_mutable { if !is_mutable {
continue continue
} }
@ -683,7 +683,7 @@ pub fn attributes_writeback(
default_value: None default_value: None
}).collect(), }).collect(),
ret: ctx.primitives.none, ret: ctx.primitives.none,
vars: Default::default() vars: HashMap::default()
}; };
let args: Vec<_> = values.into_iter().map(|(_, val)| (None, ValueEnum::Dynamic(val))).collect(); let args: Vec<_> = values.into_iter().map(|(_, val)| (None, ValueEnum::Dynamic(val))).collect();
if let Err(e) = rpc_codegen_callback_fn(ctx, None, (&fun, DefinitionId(0)), args, generator) { if let Err(e) = rpc_codegen_callback_fn(ctx, None, (&fun, DefinitionId(0)), args, generator) {

View File

@ -109,7 +109,7 @@ create_exception!(nac3artiq, CompileError, exceptions::PyException);
impl Nac3 { impl Nac3 {
fn register_module( fn register_module(
&mut self, &mut self,
module: PyObject, module: &PyObject,
registered_class_ids: &HashSet<u64>, registered_class_ids: &HashSet<u64>,
) -> PyResult<()> { ) -> PyResult<()> {
let (module_name, source_file) = Python::with_gil(|py| -> PyResult<(String, String)> { let (module_name, source_file) = Python::with_gil(|py| -> PyResult<(String, String)> {
@ -118,12 +118,12 @@ impl Nac3 {
})?; })?;
let source = fs::read_to_string(&source_file).map_err(|e| { let source = fs::read_to_string(&source_file).map_err(|e| {
exceptions::PyIOError::new_err(format!("failed to read input file: {}", e)) exceptions::PyIOError::new_err(format!("failed to read input file: {e}"))
})?; })?;
let parser_result = parse_program(&source, source_file.into()) let parser_result = parse_program(&source, source_file.into())
.map_err(|e| exceptions::PySyntaxError::new_err(format!("parse error: {}", e)))?; .map_err(|e| exceptions::PySyntaxError::new_err(format!("parse error: {e}")))?;
for mut stmt in parser_result.into_iter() { for mut stmt in parser_result {
let include = match stmt.node { let include = match stmt.node {
StmtKind::ClassDef { StmtKind::ClassDef {
ref decorator_list, ref mut body, ref mut bases, .. ref decorator_list, ref mut body, ref mut bases, ..
@ -197,7 +197,7 @@ impl Nac3 {
fn report_modinit( fn report_modinit(
arg_names: &[String], arg_names: &[String],
method_name: &str, method_name: &str,
resolver: Arc<dyn SymbolResolver + Send + Sync>, resolver: &Arc<dyn SymbolResolver + Send + Sync>,
top_level_defs: &[Arc<RwLock<TopLevelDef>>], top_level_defs: &[Arc<RwLock<TopLevelDef>>],
unifier: &mut Unifier, unifier: &mut Unifier,
primitives: &PrimitiveStore, primitives: &PrimitiveStore,
@ -205,7 +205,7 @@ impl Nac3 {
let base_ty = let base_ty =
match resolver.get_symbol_type(unifier, top_level_defs, primitives, "base".into()) { match resolver.get_symbol_type(unifier, top_level_defs, primitives, "base".into()) {
Ok(ty) => ty, Ok(ty) => ty,
Err(e) => return Some(format!("type error inside object launching kernel: {}", e)), Err(e) => return Some(format!("type error inside object launching kernel: {e}")),
}; };
let fun_ty = if method_name.is_empty() { let fun_ty = if method_name.is_empty() {
@ -215,8 +215,7 @@ impl Nac3 {
Some(t) => t.0, Some(t) => t.0,
None => { None => {
return Some(format!( return Some(format!(
"object launching kernel does not have method `{}`", "object launching kernel does not have method `{method_name}`"
method_name
)) ))
} }
} }
@ -237,8 +236,7 @@ impl Nac3 {
Some(n) => n, Some(n) => n,
None if default_value.is_none() => { None if default_value.is_none() => {
return Some(format!( return Some(format!(
"argument `{}` not provided when launching kernel function", "argument `{name}` not provided when launching kernel function"
name
)) ))
} }
_ => break, _ => break,
@ -252,8 +250,7 @@ impl Nac3 {
Ok(t) => t, Ok(t) => t,
Err(e) => { Err(e) => {
return Some(format!( return Some(format!(
"type error ({}) at parameter #{} when calling kernel function", "type error ({e}) at parameter #{i} when calling kernel function"
e, i
)) ))
} }
}; };
@ -322,7 +319,7 @@ impl Nac3 {
let mut module_to_resolver_cache: HashMap<u64, _> = HashMap::new(); let mut module_to_resolver_cache: HashMap<u64, _> = HashMap::new();
let mut rpc_ids = vec![]; let mut rpc_ids = vec![];
for (stmt, path, module) in self.top_levels.iter() { for (stmt, path, module) in &self.top_levels {
let py_module: &PyAny = module.extract(py)?; let py_module: &PyAny = module.extract(py)?;
let module_id: u64 = id_fn.call1((py_module,))?.extract()?; let module_id: u64 = id_fn.call1((py_module,))?.extract()?;
let helper = helper.clone(); let helper = helper.clone();
@ -343,7 +340,7 @@ impl Nac3 {
let mut name_to_pyid: HashMap<StrRef, u64> = HashMap::new(); let mut name_to_pyid: HashMap<StrRef, u64> = HashMap::new();
let members: &PyDict = let members: &PyDict =
py_module.getattr("__dict__").unwrap().downcast().unwrap(); py_module.getattr("__dict__").unwrap().downcast().unwrap();
for (key, val) in members.iter() { for (key, val) in members {
let key: &str = key.extract().unwrap(); let key: &str = key.extract().unwrap();
let val = id_fn.call1((val,)).unwrap().extract().unwrap(); let val = id_fn.call1((val,)).unwrap().extract().unwrap();
name_to_pyid.insert(key.into(), val); name_to_pyid.insert(key.into(), val);
@ -355,12 +352,12 @@ impl Nac3 {
pyid_to_type: pyid_to_type.clone(), pyid_to_type: pyid_to_type.clone(),
primitive_ids: self.primitive_ids.clone(), primitive_ids: self.primitive_ids.clone(),
global_value_ids: global_value_ids.clone(), global_value_ids: global_value_ids.clone(),
class_names: Default::default(), class_names: Mutex::default(),
name_to_pyid: name_to_pyid.clone(), name_to_pyid: name_to_pyid.clone(),
module: module.clone(), module: module.clone(),
id_to_pyval: Default::default(), id_to_pyval: RwLock::default(),
id_to_primitive: Default::default(), id_to_primitive: RwLock::default(),
field_to_val: Default::default(), field_to_val: RwLock::default(),
helper, helper,
string_store: self.string_store.clone(), string_store: self.string_store.clone(),
exception_ids: self.exception_ids.clone(), exception_ids: self.exception_ids.clone(),
@ -377,8 +374,7 @@ impl Nac3 {
.register_top_level(stmt.clone(), Some(resolver.clone()), path, false) .register_top_level(stmt.clone(), Some(resolver.clone()), path, false)
.map_err(|e| { .map_err(|e| {
CompileError::new_err(format!( CompileError::new_err(format!(
"compilation failed\n----------\n{}", "compilation failed\n----------\n{e}"
e
)) ))
})?; })?;
if let Some(class_obj) = class_obj { if let Some(class_obj) = class_obj {
@ -395,7 +391,7 @@ impl Nac3 {
StmtKind::ClassDef { name, body, .. } => { StmtKind::ClassDef { name, body, .. } => {
let class_name = name.to_string(); let class_name = name.to_string();
let class_obj = module.getattr(py, class_name.as_str()).unwrap(); let class_obj = module.getattr(py, class_name.as_str()).unwrap();
for stmt in body.iter() { for stmt in body {
if let StmtKind::FunctionDef { name, decorator_list, .. } = &stmt.node { if let StmtKind::FunctionDef { name, decorator_list, .. } = &stmt.node {
if decorator_list.iter().any(|decorator| matches!(decorator.node, ExprKind::Name { id, .. } if id == "rpc".into())) { if decorator_list.iter().any(|decorator| matches!(decorator.node, ExprKind::Name { id, .. } if id == "rpc".into())) {
if name == &"__init__".into() { if name == &"__init__".into() {
@ -429,7 +425,7 @@ impl Nac3 {
name_to_pyid.insert("base".into(), id_fun.call1((obj,))?.extract()?); name_to_pyid.insert("base".into(), id_fun.call1((obj,))?.extract()?);
let mut arg_names = vec![]; let mut arg_names = vec![];
for (i, arg) in args.into_iter().enumerate() { for (i, arg) in args.into_iter().enumerate() {
let name = format!("tmp{}", i); let name = format!("tmp{i}");
module.add(&name, arg)?; module.add(&name, arg)?;
name_to_pyid.insert(name.clone().into(), id_fun.call1((arg,))?.extract()?); name_to_pyid.insert(name.clone().into(), id_fun.call1((arg,))?.extract()?);
arg_names.push(name); arg_names.push(name);
@ -448,10 +444,10 @@ impl Nac3 {
pyid_to_type: pyid_to_type.clone(), pyid_to_type: pyid_to_type.clone(),
primitive_ids: self.primitive_ids.clone(), primitive_ids: self.primitive_ids.clone(),
global_value_ids: global_value_ids.clone(), global_value_ids: global_value_ids.clone(),
class_names: Default::default(), class_names: Mutex::default(),
id_to_pyval: Default::default(), id_to_pyval: RwLock::default(),
id_to_primitive: Default::default(), id_to_primitive: RwLock::default(),
field_to_val: Default::default(), field_to_val: RwLock::default(),
name_to_pyid, name_to_pyid,
module: module.to_object(py), module: module.to_object(py),
helper, helper,
@ -461,7 +457,7 @@ impl Nac3 {
}); });
let resolver = Arc::new(Resolver(inner_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>; let resolver = Arc::new(Resolver(inner_resolver.clone())) as Arc<dyn SymbolResolver + Send + Sync>;
let (_, def_id, _) = composer let (_, def_id, _) = composer
.register_top_level(synthesized.pop().unwrap(), Some(resolver.clone()), "".into(), false) .register_top_level(synthesized.pop().unwrap(), Some(resolver.clone()), "", false)
.unwrap(); .unwrap();
let fun_signature = let fun_signature =
@ -474,16 +470,11 @@ impl Nac3 {
if let Err(e) = composer.start_analysis(true) { if let Err(e) = composer.start_analysis(true) {
// report error of __modinit__ separately // report error of __modinit__ separately
return if !e.contains("<nac3_synthesized_modinit>") { return if e.contains("<nac3_synthesized_modinit>") {
Err(CompileError::new_err(format!(
"compilation failed\n----------\n{}",
e
)))
} else {
let msg = Self::report_modinit( let msg = Self::report_modinit(
&arg_names, &arg_names,
method_name, method_name,
resolver.clone(), &resolver,
&composer.extract_def_list(), &composer.extract_def_list(),
&mut composer.unifier, &mut composer.unifier,
&self.primitive, &self.primitive,
@ -492,6 +483,10 @@ impl Nac3 {
"compilation failed\n----------\n{}", "compilation failed\n----------\n{}",
msg.unwrap_or(e) msg.unwrap_or(e)
))) )))
} else {
Err(CompileError::new_err(format!(
"compilation failed\n----------\n{e}"
)))
} }
} }
let top_level = Arc::new(composer.make_top_level_context()); let top_level = Arc::new(composer.make_top_level_context());
@ -499,7 +494,7 @@ impl Nac3 {
{ {
let rpc_codegen = rpc_codegen_callback(); let rpc_codegen = rpc_codegen_callback();
let defs = top_level.definitions.read(); let defs = top_level.definitions.read();
for (class_data, id) in rpc_ids.iter() { for (class_data, id) in &rpc_ids {
let mut def = defs[id.0].write(); let mut def = defs[id.0].write();
match &mut *def { match &mut *def {
TopLevelDef::Function { codegen_callback, .. } => { TopLevelDef::Function { codegen_callback, .. } => {
@ -507,7 +502,7 @@ impl Nac3 {
} }
TopLevelDef::Class { methods, .. } => { TopLevelDef::Class { methods, .. } => {
let (class_def, method_name) = class_data.as_ref().unwrap(); let (class_def, method_name) = class_data.as_ref().unwrap();
for (name, _, id) in methods.iter() { for (name, _, id) in &*methods {
if name != method_name { if name != method_name {
continue; continue;
} }
@ -537,7 +532,7 @@ impl Nac3 {
if let TopLevelDef::Function { instance_to_stmt, instance_to_symbol, .. } = if let TopLevelDef::Function { instance_to_stmt, instance_to_symbol, .. } =
&mut *definition &mut *definition
{ {
instance_to_symbol.insert("".to_string(), "__modinit__".into()); instance_to_symbol.insert(String::new(), "__modinit__".into());
instance_to_stmt[""].clone() instance_to_stmt[""].clone()
} else { } else {
unreachable!() unreachable!()
@ -545,7 +540,7 @@ impl Nac3 {
}; };
let task = CodeGenTask { let task = CodeGenTask {
subst: Default::default(), subst: Vec::default(),
symbol_name: "__modinit__".to_string(), symbol_name: "__modinit__".to_string(),
body: instance.body, body: instance.body,
signature, signature,
@ -562,18 +557,18 @@ impl Nac3 {
store.from_signature(&mut composer.unifier, &self.primitive, &fun_signature, &mut cache); store.from_signature(&mut composer.unifier, &self.primitive, &fun_signature, &mut cache);
let signature = store.add_cty(signature); let signature = store.add_cty(signature);
let attributes_writeback_task = CodeGenTask { let attributes_writeback_task = CodeGenTask {
subst: Default::default(), subst: Vec::default(),
symbol_name: "attributes_writeback".to_string(), symbol_name: "attributes_writeback".to_string(),
body: Arc::new(Default::default()), body: Arc::new(Vec::default()),
signature, signature,
resolver, resolver,
store, store,
unifier_index: instance.unifier_id, unifier_index: instance.unifier_id,
calls: Arc::new(Default::default()), calls: Arc::new(HashMap::default()),
id: 0, id: 0,
}; };
let membuffers: Arc<Mutex<Vec<Vec<u8>>>> = Default::default(); let membuffers: Arc<Mutex<Vec<Vec<u8>>>> = Arc::default();
let membuffer = membuffers.clone(); let membuffer = membuffers.clone();
@ -607,7 +602,7 @@ impl Nac3 {
let builder = context.create_builder(); let builder = context.create_builder();
let (_, module, _) = gen_func_impl(&context, &mut generator, &registry, builder, module, let (_, module, _) = gen_func_impl(&context, &mut generator, &registry, builder, module,
attributes_writeback_task, |generator, ctx| { attributes_writeback_task, |generator, ctx| {
attributes_writeback(ctx, generator, inner_resolver.as_ref(), host_attributes) attributes_writeback(ctx, generator, inner_resolver.as_ref(), &host_attributes)
}).unwrap(); }).unwrap();
let buffer = module.write_bitcode_to_memory(); let buffer = module.write_bitcode_to_memory();
let buffer = buffer.as_slice().into(); let buffer = buffer.as_slice().into();
@ -671,7 +666,7 @@ impl Nac3 {
link_fn(&main) link_fn(&main)
} }
/// Returns the [TargetTriple] used for compiling to [isa]. /// Returns the [`TargetTriple`] used for compiling to [isa].
fn get_llvm_target_triple(isa: Isa) -> TargetTriple { fn get_llvm_target_triple(isa: Isa) -> TargetTriple {
match isa { match isa {
Isa::Host => TargetMachine::get_default_triple(), Isa::Host => TargetMachine::get_default_triple(),
@ -680,7 +675,7 @@ impl Nac3 {
} }
} }
/// Returns the [String] representing the target CPU used for compiling to [isa]. /// Returns the [`String`] representing the target CPU used for compiling to [isa].
fn get_llvm_target_cpu(isa: Isa) -> String { fn get_llvm_target_cpu(isa: Isa) -> String {
match isa { match isa {
Isa::Host => TargetMachine::get_host_cpu_name().to_string(), Isa::Host => TargetMachine::get_host_cpu_name().to_string(),
@ -689,7 +684,7 @@ impl Nac3 {
} }
} }
/// Returns the [String] representing the target features used for compiling to [isa]. /// Returns the [`String`] representing the target features used for compiling to [isa].
fn get_llvm_target_features(isa: Isa) -> String { fn get_llvm_target_features(isa: Isa) -> String {
match isa { match isa {
Isa::Host => TargetMachine::get_host_cpu_features().to_string(), Isa::Host => TargetMachine::get_host_cpu_features().to_string(),
@ -699,7 +694,7 @@ impl Nac3 {
} }
} }
/// Returns an instance of [CodeGenTargetMachineOptions] representing the target machine /// Returns an instance of [`CodeGenTargetMachineOptions`] representing the target machine
/// options used for compiling to [isa]. /// options used for compiling to [isa].
fn get_llvm_target_options(isa: Isa) -> CodeGenTargetMachineOptions { fn get_llvm_target_options(isa: Isa) -> CodeGenTargetMachineOptions {
CodeGenTargetMachineOptions { CodeGenTargetMachineOptions {
@ -711,7 +706,7 @@ impl Nac3 {
} }
} }
/// Returns an instance of [TargetMachine] used in compiling and linking of a program to the /// Returns an instance of [`TargetMachine`] used in compiling and linking of a program to the
/// target [isa]. /// target [isa].
fn get_llvm_target_machine(&self) -> TargetMachine { fn get_llvm_target_machine(&self) -> TargetMachine {
Nac3::get_llvm_target_options(self.isa) Nac3::get_llvm_target_options(self.isa)
@ -790,10 +785,9 @@ impl Nac3 {
_ => return Err(exceptions::PyValueError::new_err("invalid ISA")), _ => return Err(exceptions::PyValueError::new_err("invalid ISA")),
}; };
let time_fns: &(dyn TimeFns + Sync) = match isa { let time_fns: &(dyn TimeFns + Sync) = match isa {
Isa::Host => &timeline::EXTERN_TIME_FNS,
Isa::RiscV32G => &timeline::NOW_PINNING_TIME_FNS_64, Isa::RiscV32G => &timeline::NOW_PINNING_TIME_FNS_64,
Isa::RiscV32IMA => &timeline::NOW_PINNING_TIME_FNS, Isa::RiscV32IMA => &timeline::NOW_PINNING_TIME_FNS,
Isa::CortexA9 => &timeline::EXTERN_TIME_FNS, Isa::CortexA9 | Isa::Host => &timeline::EXTERN_TIME_FNS,
}; };
let primitive: PrimitiveStore = TopLevelComposer::make_primitives().0; let primitive: PrimitiveStore = TopLevelComposer::make_primitives().0;
let builtins = vec![ let builtins = vec![
@ -884,7 +878,7 @@ impl Nac3 {
.and_then(|v| v.get_item("_ConstGenericMarker")) .and_then(|v| v.get_item("_ConstGenericMarker"))
.unwrap(), .unwrap(),
)) ))
.and_then(|v| v.extract()) .and_then(PyAny::extract)
.unwrap(), .unwrap(),
int: get_attr_id(builtins_mod, "int"), int: get_attr_id(builtins_mod, "int"),
int32: get_attr_id(numpy_mod, "int32"), int32: get_attr_id(numpy_mod, "int32"),
@ -919,11 +913,11 @@ impl Nac3 {
primitive, primitive,
builtins, builtins,
primitive_ids, primitive_ids,
top_levels: Default::default(), top_levels: Vec::default(),
pyid_to_def: Default::default(), pyid_to_def: Arc::default(),
working_directory, working_directory,
string_store: Default::default(), string_store: Arc::default(),
exception_ids: Default::default(), exception_ids: Arc::default(),
deferred_eval_store: DeferredEvaluationStore::new(), deferred_eval_store: DeferredEvaluationStore::new(),
llvm_options: CodeGenLLVMOptions { llvm_options: CodeGenLLVMOptions {
opt_level: OptimizationLevel::Default, opt_level: OptimizationLevel::Default,
@ -941,11 +935,11 @@ impl Nac3 {
let id_fn = PyModule::import(py, "builtins")?.getattr("id")?; let id_fn = PyModule::import(py, "builtins")?.getattr("id")?;
let getmodule_fn = PyModule::import(py, "inspect")?.getattr("getmodule")?; let getmodule_fn = PyModule::import(py, "inspect")?.getattr("getmodule")?;
for function in functions.iter() { for function in functions {
let module = getmodule_fn.call1((function,))?.extract()?; let module = getmodule_fn.call1((function,))?.extract()?;
modules.insert(id_fn.call1((&module,))?.extract()?, module); modules.insert(id_fn.call1((&module,))?.extract()?, module);
} }
for class in classes.iter() { for class in classes {
let module = getmodule_fn.call1((class,))?.extract()?; let module = getmodule_fn.call1((class,))?.extract()?;
modules.insert(id_fn.call1((&module,))?.extract()?, module); modules.insert(id_fn.call1((&module,))?.extract()?, module);
class_ids.insert(id_fn.call1((class,))?.extract()?); class_ids.insert(id_fn.call1((class,))?.extract()?);
@ -954,7 +948,7 @@ impl Nac3 {
})?; })?;
for module in modules.into_values() { for module in modules.into_values() {
self.register_module(module, &class_ids)?; self.register_module(&module, &class_ids)?;
} }
Ok(()) Ok(())
} }

View File

@ -100,25 +100,25 @@ impl StaticValue for PythonValue {
) -> BasicValueEnum<'ctx> { ) -> BasicValueEnum<'ctx> {
ctx.module ctx.module
.get_global(format!("{}_const", self.id).as_str()) .get_global(format!("{}_const", self.id).as_str())
.map(|val| val.as_pointer_value().into()) .map_or_else(
.unwrap_or_else(|| { || Python::with_gil(|py| -> PyResult<BasicValueEnum<'ctx>> {
Python::with_gil(|py| -> PyResult<BasicValueEnum<'ctx>> { let id: u32 = self.store_obj.call1(py, (self.value.clone(),))?.extract(py)?;
let id: u32 = self.store_obj.call1(py, (self.value.clone(),))?.extract(py)?; let struct_type = ctx.ctx.struct_type(&[ctx.ctx.i32_type().into()], false);
let struct_type = ctx.ctx.struct_type(&[ctx.ctx.i32_type().into()], false); let global = ctx.module.add_global(
let global = ctx.module.add_global( struct_type,
struct_type, None,
None, format!("{}_const", self.id).as_str(),
format!("{}_const", self.id).as_str(), );
); global.set_constant(true);
global.set_constant(true); global.set_initializer(&ctx.ctx.const_struct(
global.set_initializer(&ctx.ctx.const_struct( &[ctx.ctx.i32_type().const_int(id as u64, false).into()],
&[ctx.ctx.i32_type().const_int(id as u64, false).into()], false,
false, ));
)); Ok(global.as_pointer_value().into())
Ok(global.as_pointer_value().into()) })
}) .unwrap(),
.unwrap() |val| val.as_pointer_value().into(),
}) )
} }
fn to_basic_value_enum<'ctx, 'a>( fn to_basic_value_enum<'ctx, 'a>(
@ -176,7 +176,7 @@ impl StaticValue for PythonValue {
let mut mutable = true; let mut mutable = true;
let defs = ctx.top_level.definitions.read(); let defs = ctx.top_level.definitions.read();
if let TopLevelDef::Class { fields, .. } = &*defs[def_id.0].read() { if let TopLevelDef::Class { fields, .. } = &*defs[def_id.0].read() {
for (field_name, _, is_mutable) in fields.iter() { for (field_name, _, is_mutable) in fields {
if field_name == &name { if field_name == &name {
mutable = *is_mutable; mutable = *is_mutable;
break; break;
@ -240,7 +240,7 @@ impl InnerResolver {
) -> PyResult<Result<Type, String>> { ) -> PyResult<Result<Type, String>> {
let mut ty = match self.get_obj_type(py, list.get_item(0)?, unifier, defs, primitives)? { let mut ty = match self.get_obj_type(py, list.get_item(0)?, unifier, defs, primitives)? {
Ok(t) => t, Ok(t) => t,
Err(e) => return Ok(Err(format!("type error ({}) at element #0 of the list", e))), Err(e) => return Ok(Err(format!("type error ({e}) at element #0 of the list"))),
}; };
for i in 1..len { for i in 1..len {
let b = match list let b = match list
@ -249,11 +249,11 @@ impl InnerResolver {
{ {
Ok(t) => t, Ok(t) => t,
Err(e) => { Err(e) => {
return Ok(Err(format!("type error ({}) at element #{} of the list", e, i))) return Ok(Err(format!("type error ({e}) at element #{i} of the list")))
} }
}; };
ty = match unifier.unify(ty, b) { ty = match unifier.unify(ty, b) {
Ok(_) => ty, Ok(()) => ty,
Err(e) => { Err(e) => {
return Ok(Err(format!( return Ok(Err(format!(
"inhomogeneous type ({}) at element #{i} of the list", "inhomogeneous type ({}) at element #{i} of the list",
@ -268,7 +268,7 @@ impl InnerResolver {
/// Handles python objects that represent types themselves, /// Handles python objects that represent types themselves,
/// ///
/// Primitives and class types should be themselves, use `ty_id` to check; /// Primitives and class types should be themselves, use `ty_id` to check;
/// TypeVars and GenericAlias(`A[int, bool]`) should use `ty_ty_id` to check. /// `TypeVars` and `GenericAlias`(`A[int, bool]`) should use `ty_ty_id` to check.
/// ///
/// The `bool` value returned indicates whether they are instantiated or not /// The `bool` value returned indicates whether they are instantiated or not
fn get_pyty_obj_type( fn get_pyty_obj_type(
@ -309,7 +309,7 @@ impl InnerResolver {
Ok(Ok((primitives.option, false))) Ok(Ok((primitives.option, false)))
} else if ty_id == self.primitive_ids.none { } else if ty_id == self.primitive_ids.none {
unreachable!("none cannot be typeid") unreachable!("none cannot be typeid")
} else if let Some(def_id) = self.pyid_to_def.read().get(&ty_id).cloned() { } else if let Some(def_id) = self.pyid_to_def.read().get(&ty_id).copied() {
let def = defs[def_id.0].read(); let def = defs[def_id.0].read();
if let TopLevelDef::Class { object_id, type_vars, fields, methods, .. } = &*def { if let TopLevelDef::Class { object_id, type_vars, fields, methods, .. } = &*def {
// do not handle type var param and concrete check here, and no subst // do not handle type var param and concrete check here, and no subst
@ -376,7 +376,7 @@ impl InnerResolver {
} }
Err(err) => return Ok(Err(err)), Err(err) => return Ok(Err(err)),
} }
}) });
} }
} else { } else {
break; break;
@ -388,7 +388,7 @@ impl InnerResolver {
.push((result.clone(), .push((result.clone(),
constraints.extract()?, constraints.extract()?,
pyty.getattr("__name__")?.extract::<String>()? pyty.getattr("__name__")?.extract::<String>()?
)) ));
} }
(result, is_const_generic) (result, is_const_generic)
@ -514,11 +514,10 @@ impl InnerResolver {
Ok(ty) => ty, Ok(ty) => ty,
Err(err) => return Ok(Err(err)), Err(err) => return Ok(Err(err)),
}; };
if !unifier.is_concrete(ty.0, &[]) && !ty.1 { assert!(
panic!( unifier.is_concrete(ty.0, &[]) || ty.1,
"virtual class should take concrete parameters in type var ranges" "virtual class should take concrete parameters in type var ranges"
) );
}
Ok(Ok((unifier.add_ty(TypeEnum::TVirtual { ty: ty.0 }), true))) Ok(Ok((unifier.add_ty(TypeEnum::TVirtual { ty: ty.0 }), true)))
} else { } else {
return Ok(Err(format!( return Ok(Err(format!(
@ -542,8 +541,7 @@ impl InnerResolver {
pyo3::types::PyModule::import(py, "builtins").unwrap().getattr("repr").unwrap(); pyo3::types::PyModule::import(py, "builtins").unwrap().getattr("repr").unwrap();
let str_repr: String = str_fn.call1((pyty,)).unwrap().extract().unwrap(); let str_repr: String = str_fn.call1((pyty,)).unwrap().extract().unwrap();
Ok(Err(format!( Ok(Err(format!(
"{} is not registered with NAC3 (@nac3 decorator missing?)", "{str_repr} is not registered with NAC3 (@nac3 decorator missing?)"
str_repr
))) )))
} }
} }
@ -624,7 +622,7 @@ impl InnerResolver {
self.get_list_elem_type(py, obj, len, unifier, defs, primitives)?; self.get_list_elem_type(py, obj, len, unifier, defs, primitives)?;
match actual_ty { match actual_ty {
Ok(t) => match unifier.unify(*ty, t) { Ok(t) => match unifier.unify(*ty, t) {
Ok(_) => Ok(Ok(unifier.add_ty(TypeEnum::TList { ty: *ty }))), Ok(()) => Ok(Ok(unifier.add_ty(TypeEnum::TList { ty: *ty }))),
Err(e) => Ok(Err(format!( Err(e) => Ok(Err(format!(
"type error ({}) for the list", "type error ({}) for the list",
e.to_display(unifier) e.to_display(unifier)
@ -648,10 +646,8 @@ impl InnerResolver {
(TypeEnum::TObj { obj_id, params, .. }, false) (TypeEnum::TObj { obj_id, params, .. }, false)
if *obj_id == primitives.option.get_obj_id(unifier) => if *obj_id == primitives.option.get_obj_id(unifier) =>
{ {
let field_data = match obj.getattr("_nac3_option") { let Ok(field_data) = obj.getattr("_nac3_option") else {
Ok(d) => d, unreachable!("cannot be None")
// we use `none = Option(None)`, so the obj always have attr `_nac3_option`
Err(_) => unreachable!("cannot be None")
}; };
// if is `none` // if is `none`
let zelf_id: u64 = self.helper.id_fn.call1(py, (obj,))?.extract(py)?; let zelf_id: u64 = self.helper.id_fn.call1(py, (obj,))?.extract(py)?;
@ -671,17 +667,15 @@ impl InnerResolver {
}) })
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
return Ok(Ok(unifier.subst(primitives.option, &var_map).unwrap())) return Ok(Ok(unifier.subst(primitives.option, &var_map).unwrap()))
} else {
unreachable!("must be tobj")
} }
unreachable!("must be tobj")
} }
let ty = match self.get_obj_type(py, field_data, unifier, defs, primitives)? { let ty = match self.get_obj_type(py, field_data, unifier, defs, primitives)? {
Ok(t) => t, Ok(t) => t,
Err(e) => { Err(e) => {
return Ok(Err(format!( return Ok(Err(format!(
"error when getting type of the option object ({})", "error when getting type of the option object ({e})"
e
))) )))
} }
}; };
@ -706,38 +700,36 @@ impl InnerResolver {
.collect::<HashMap<_, _>>(); .collect::<HashMap<_, _>>();
let mut instantiate_obj = || { let mut instantiate_obj = || {
// loop through non-function fields of the class to get the instantiated value // loop through non-function fields of the class to get the instantiated value
for field in fields.iter() { for field in fields {
let name: String = (*field.0).into(); let name: String = (*field.0).into();
if let TypeEnum::TFunc(..) = &*unifier.get_ty(field.1.0) { if let TypeEnum::TFunc(..) = &*unifier.get_ty(field.1.0) {
continue; continue;
} else { }
let field_data = match obj.getattr(name.as_str()) { let field_data = match obj.getattr(name.as_str()) {
Ok(d) => d, Ok(d) => d,
Err(e) => return Ok(Err(format!("{}", e))), Err(e) => return Ok(Err(format!("{e}"))),
}; };
let ty = match self let ty = match self
.get_obj_type(py, field_data, unifier, defs, primitives)? .get_obj_type(py, field_data, unifier, defs, primitives)?
{ {
Ok(t) => t, Ok(t) => t,
Err(e) => { Err(e) => {
return Ok(Err(format!(
"error when getting type of field `{}` ({})",
name, e
)))
}
};
let field_ty =
unifier.subst(field.1.0, &var_map).unwrap_or(field.1.0);
if let Err(e) = unifier.unify(ty, field_ty) {
// field type mismatch
return Ok(Err(format!( return Ok(Err(format!(
"error when getting type of field `{name}` ({})", "error when getting type of field `{name}` ({e})"
e.to_display(unifier) )))
)));
} }
};
let field_ty =
unifier.subst(field.1.0, &var_map).unwrap_or(field.1.0);
if let Err(e) = unifier.unify(ty, field_ty) {
// field type mismatch
return Ok(Err(format!(
"error when getting type of field `{name}` ({})",
e.to_display(unifier)
)));
} }
} }
for (_, ty) in var_map.iter() { for ty in var_map.values() {
// must be concrete type // must be concrete type
if !unifier.is_concrete(*ty, &[]) { if !unifier.is_concrete(*ty, &[]) {
return Ok(Err("object is not of concrete type".into())); return Ok(Err("object is not of concrete type".into()));
@ -758,32 +750,32 @@ impl InnerResolver {
// check integer bounds // check integer bounds
if unifier.unioned(extracted_ty, primitives.int32) { if unifier.unioned(extracted_ty, primitives.int32) {
obj.extract::<i32>().map_or_else( obj.extract::<i32>().map_or_else(
|_| Ok(Err(format!("{} is not in the range of int32", obj))), |_| Ok(Err(format!("{obj} is not in the range of int32"))),
|_| Ok(Ok(extracted_ty)) |_| Ok(Ok(extracted_ty))
) )
} else if unifier.unioned(extracted_ty, primitives.int64) { } else if unifier.unioned(extracted_ty, primitives.int64) {
obj.extract::<i64>().map_or_else( obj.extract::<i64>().map_or_else(
|_| Ok(Err(format!("{} is not in the range of int64", obj))), |_| Ok(Err(format!("{obj} is not in the range of int64"))),
|_| Ok(Ok(extracted_ty)) |_| Ok(Ok(extracted_ty))
) )
} else if unifier.unioned(extracted_ty, primitives.uint32) { } else if unifier.unioned(extracted_ty, primitives.uint32) {
obj.extract::<u32>().map_or_else( obj.extract::<u32>().map_or_else(
|_| Ok(Err(format!("{} is not in the range of uint32", obj))), |_| Ok(Err(format!("{obj} is not in the range of uint32"))),
|_| Ok(Ok(extracted_ty)) |_| Ok(Ok(extracted_ty))
) )
} else if unifier.unioned(extracted_ty, primitives.uint64) { } else if unifier.unioned(extracted_ty, primitives.uint64) {
obj.extract::<u64>().map_or_else( obj.extract::<u64>().map_or_else(
|_| Ok(Err(format!("{} is not in the range of uint64", obj))), |_| Ok(Err(format!("{obj} is not in the range of uint64"))),
|_| Ok(Ok(extracted_ty)) |_| Ok(Ok(extracted_ty))
) )
} else if unifier.unioned(extracted_ty, primitives.bool) { } else if unifier.unioned(extracted_ty, primitives.bool) {
obj.extract::<bool>().map_or_else( obj.extract::<bool>().map_or_else(
|_| Ok(Err(format!("{} is not in the range of bool", obj))), |_| Ok(Err(format!("{obj} is not in the range of bool"))),
|_| Ok(Ok(extracted_ty)) |_| Ok(Ok(extracted_ty))
) )
} else if unifier.unioned(extracted_ty, primitives.float) { } else if unifier.unioned(extracted_ty, primitives.float) {
obj.extract::<f64>().map_or_else( obj.extract::<f64>().map_or_else(
|_| Ok(Err(format!("{} is not in the range of float64", obj))), |_| Ok(Err(format!("{obj} is not in the range of float64"))),
|_| Ok(Ok(extracted_ty)) |_| Ok(Ok(extracted_ty))
) )
} else { } else {
@ -855,9 +847,8 @@ impl InnerResolver {
ctx.module.add_global(arr_ty, Some(AddressSpace::default()), &id_str) ctx.module.add_global(arr_ty, Some(AddressSpace::default()), &id_str)
}); });
return Ok(Some(global.as_pointer_value().into())); return Ok(Some(global.as_pointer_value().into()));
} else {
self.global_value_ids.write().insert(id, obj.into());
} }
self.global_value_ids.write().insert(id, obj.into());
} }
let arr: Result<Option<Vec<_>>, _> = (0..len) let arr: Result<Option<Vec<_>>, _> = (0..len)
@ -867,7 +858,7 @@ impl InnerResolver {
.and_then(|elem| self.get_obj_value(py, elem, ctx, generator, elem_ty) .and_then(|elem| self.get_obj_value(py, elem, ctx, generator, elem_ty)
.map_err( .map_err(
|e| super::CompileError::new_err( |e| super::CompileError::new_err(
format!("Error getting element {}: {}", i, e)) format!("Error getting element {i}: {e}"))
)) ))
}) })
.collect(); .collect();
@ -921,7 +912,7 @@ impl InnerResolver {
.map(|((i, elem), ty)| self .map(|((i, elem), ty)| self
.get_obj_value(py, elem, ctx, generator, *ty).map_err(|e| .get_obj_value(py, elem, ctx, generator, *ty).map_err(|e|
super::CompileError::new_err( super::CompileError::new_err(
format!("Error getting element {}: {}", i, e) format!("Error getting element {i}: {e}")
) )
) )
).collect(); ).collect();
@ -953,21 +944,19 @@ impl InnerResolver {
.get_obj_value(py, obj.getattr("_nac3_option").unwrap(), ctx, generator, option_val_ty) .get_obj_value(py, obj.getattr("_nac3_option").unwrap(), ctx, generator, option_val_ty)
.map_err(|e| { .map_err(|e| {
super::CompileError::new_err(format!( super::CompileError::new_err(format!(
"Error getting value of Option object: {}", "Error getting value of Option object: {e}"
e
)) ))
})? { })? {
Some(v) => { Some(v) => {
let global_str = format!("{}_option", id); let global_str = format!("{id}_option");
{ {
if self.global_value_ids.read().contains_key(&id) { if self.global_value_ids.read().contains_key(&id) {
let global = ctx.module.get_global(&global_str).unwrap_or_else(|| { let global = ctx.module.get_global(&global_str).unwrap_or_else(|| {
ctx.module.add_global(v.get_type(), Some(AddressSpace::default()), &global_str) ctx.module.add_global(v.get_type(), Some(AddressSpace::default()), &global_str)
}); });
return Ok(Some(global.as_pointer_value().into())); return Ok(Some(global.as_pointer_value().into()));
} else {
self.global_value_ids.write().insert(id, obj.into());
} }
self.global_value_ids.write().insert(id, obj.into());
} }
let global = ctx.module.add_global(v.get_type(), Some(AddressSpace::default()), &global_str); let global = ctx.module.add_global(v.get_type(), Some(AddressSpace::default()), &global_str);
global.set_initializer(&v); global.set_initializer(&v);
@ -998,9 +987,8 @@ impl InnerResolver {
ctx.module.add_global(ty, Some(AddressSpace::default()), &id_str) ctx.module.add_global(ty, Some(AddressSpace::default()), &id_str)
}); });
return Ok(Some(global.as_pointer_value().into())); return Ok(Some(global.as_pointer_value().into()));
} else {
self.global_value_ids.write().insert(id, obj.into());
} }
self.global_value_ids.write().insert(id, obj.into());
} }
// should be classes // should be classes
let definition = let definition =
@ -1010,7 +998,7 @@ impl InnerResolver {
.iter() .iter()
.map(|(name, ty, _)| { .map(|(name, ty, _)| {
self.get_obj_value(py, obj.getattr(name.to_string().as_str())?, ctx, generator, *ty) self.get_obj_value(py, obj.getattr(name.to_string().as_str())?, ctx, generator, *ty)
.map_err(|e| super::CompileError::new_err(format!("Error getting field {}: {}", name, e))) .map_err(|e| super::CompileError::new_err(format!("Error getting field {name}: {e}")))
}) })
.collect(); .collect();
let values = values?; let values = values?;
@ -1083,11 +1071,11 @@ impl SymbolResolver for Resolver {
let obj: &PyAny = self.0.module.extract(py)?; let obj: &PyAny = self.0.module.extract(py)?;
let members: &PyDict = obj.getattr("__dict__").unwrap().downcast().unwrap(); let members: &PyDict = obj.getattr("__dict__").unwrap().downcast().unwrap();
let mut sym_value = None; let mut sym_value = None;
for (key, val) in members.iter() { for (key, val) in members {
let key: &str = key.extract()?; let key: &str = key.extract()?;
if key == id.to_string() { if key == id.to_string() {
if let Ok(Ok(v)) = self.0.get_default_param_obj_value(py, val) { if let Ok(Ok(v)) = self.0.get_default_param_obj_value(py, val) {
sym_value = Some(v) sym_value = Some(v);
} }
break; break;
} }
@ -1107,43 +1095,41 @@ impl SymbolResolver for Resolver {
primitives: &PrimitiveStore, primitives: &PrimitiveStore,
str: StrRef, str: StrRef,
) -> Result<Type, String> { ) -> Result<Type, String> {
match { if let Some(ty) = {
let id_to_type = self.0.id_to_type.read(); let id_to_type = self.0.id_to_type.read();
id_to_type.get(&str).cloned() id_to_type.get(&str).copied()
} { } {
Some(ty) => Ok(ty), Ok(ty)
None => { } else {
let id = match self.0.name_to_pyid.get(&str) { let Some(id) = self.0.name_to_pyid.get(&str) else {
Some(id) => id, return Err(format!("cannot find symbol `{str}`"))
None => return Err(format!("cannot find symbol `{}`", str)), };
}; let result = if let Some(t) = {
let result = match { let pyid_to_type = self.0.pyid_to_type.read();
let pyid_to_type = self.0.pyid_to_type.read(); pyid_to_type.get(id).copied()
pyid_to_type.get(id).copied() } {
} { Ok(t)
Some(t) => Ok(t), } else {
None => Python::with_gil(|py| -> PyResult<Result<Type, String>> { Python::with_gil(|py| -> PyResult<Result<Type, String>> {
let obj: &PyAny = self.0.module.extract(py)?; let obj: &PyAny = self.0.module.extract(py)?;
let mut sym_ty = Err(format!("cannot find symbol `{}`", str)); let mut sym_ty = Err(format!("cannot find symbol `{str}`"));
let members: &PyDict = obj.getattr("__dict__").unwrap().downcast().unwrap(); let members: &PyDict = obj.getattr("__dict__").unwrap().downcast().unwrap();
for (key, val) in members.iter() { for (key, val) in members {
let key: &str = key.extract()?; let key: &str = key.extract()?;
if key == str.to_string() { if key == str.to_string() {
sym_ty = self.0.get_obj_type(py, val, unifier, defs, primitives)?; sym_ty = self.0.get_obj_type(py, val, unifier, defs, primitives)?;
break; break;
}
} }
if let Ok(t) = sym_ty { }
if let TypeEnum::TVar { .. } = &*unifier.get_ty(t) { if let Ok(t) = sym_ty {
self.0.pyid_to_type.write().insert(*id, t); if let TypeEnum::TVar { .. } = &*unifier.get_ty(t) {
} self.0.pyid_to_type.write().insert(*id, t);
} }
Ok(sym_ty) }
}) Ok(sym_ty)
.unwrap(), }).unwrap()
}; };
result result
}
} }
} }
@ -1161,7 +1147,7 @@ impl SymbolResolver for Resolver {
let obj: &PyAny = self.0.module.extract(py)?; let obj: &PyAny = self.0.module.extract(py)?;
let mut sym_value: Option<(u64, PyObject)> = None; let mut sym_value: Option<(u64, PyObject)> = None;
let members: &PyDict = obj.getattr("__dict__").unwrap().downcast().unwrap(); let members: &PyDict = obj.getattr("__dict__").unwrap().downcast().unwrap();
for (key, val) in members.iter() { for (key, val) in members {
let key: &str = key.extract()?; let key: &str = key.extract()?;
if key == id.to_string() { if key == id.to_string() {
let id = self.0.helper.id_fn.call1(py, (val,))?.extract(py)?; let id = self.0.helper.id_fn.call1(py, (val,))?.extract(py)?;
@ -1189,14 +1175,13 @@ impl SymbolResolver for Resolver {
fn get_identifier_def(&self, id: StrRef) -> Result<DefinitionId, String> { fn get_identifier_def(&self, id: StrRef) -> Result<DefinitionId, String> {
{ {
let id_to_def = self.0.id_to_def.read(); let id_to_def = self.0.id_to_def.read();
id_to_def.get(&id).cloned().ok_or_else(|| "".to_string()) id_to_def.get(&id).copied().ok_or_else(String::new)
} }
.or_else(|_| { .or_else(|_| {
let py_id = let py_id =
self.0.name_to_pyid.get(&id).ok_or(format!("Undefined identifier `{}`", id))?; self.0.name_to_pyid.get(&id).ok_or(format!("Undefined identifier `{id}`"))?;
let result = self.0.pyid_to_def.read().get(py_id).copied().ok_or(format!( let result = self.0.pyid_to_def.read().get(py_id).copied().ok_or(format!(
"`{}` is not registered with NAC3 (@nac3 decorator missing?)", "`{id}` is not registered with NAC3 (@nac3 decorator missing?)"
id
))?; ))?;
self.0.id_to_def.write().insert(id, result); self.0.id_to_def.write().insert(id, result);
Ok(result) Ok(result)
@ -1241,7 +1226,7 @@ impl SymbolResolver for Resolver {
name, name,
))); )));
} }
unifier.unify(ty, *var).unwrap() unifier.unify(ty, *var).unwrap();
} }
Err(err) => return Ok(Err(err)), Err(err) => return Ok(Err(err)),
} }
@ -1251,13 +1236,13 @@ impl SymbolResolver for Resolver {
} }
} }
Ok(Ok(())) Ok(Ok(()))
}).unwrap()? }).unwrap()?;
} }
Ok(()) Ok(())
} }
fn get_exception_id(&self, tyid: usize) -> usize { fn get_exception_id(&self, tyid: usize) -> usize {
let exn_ids = self.0.exception_ids.read(); let exn_ids = self.0.exception_ids.read();
exn_ids.get(&tyid).cloned().unwrap_or(0) exn_ids.get(&tyid).copied().unwrap_or(0)
} }
} }

View File

@ -227,7 +227,7 @@ fn test_primitives() {
threads, threads,
top_level, top_level,
&llvm_options, &llvm_options,
f &f
); );
registry.add_task(task); registry.add_task(task);
registry.wait_tasks_complete(handles); registry.wait_tasks_complete(handles);
@ -417,7 +417,7 @@ fn test_simple_call() {
threads, threads,
top_level, top_level,
&llvm_options, &llvm_options,
f &f
); );
registry.add_task(task); registry.add_task(task);
registry.wait_tasks_complete(handles); registry.wait_tasks_complete(handles);