Miscellaneous Code Cleanup #364
|
@ -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) {
|
||||||
|
|
|
@ -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, ®istry, builder, module,
|
let (_, module, _) = gen_func_impl(&context, &mut generator, ®istry, 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(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,9 +100,8 @@ 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(
|
||||||
|
@ -117,8 +116,9 @@ impl StaticValue for PythonValue {
|
||||||
));
|
));
|
||||||
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,14 +700,14 @@ 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)?
|
||||||
|
@ -721,8 +715,7 @@ impl InnerResolver {
|
||||||
Ok(t) => t,
|
Ok(t) => t,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Ok(Err(format!(
|
return Ok(Err(format!(
|
||||||
"error when getting type of field `{}` ({})",
|
"error when getting type of field `{name}` ({e})"
|
||||||
name, e
|
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -736,8 +729,7 @@ impl InnerResolver {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
for ty in var_map.values() {
|
||||||
for (_, ty) in var_map.iter() {
|
|
||||||
// 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,26 +1095,26 @@ 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 = match {
|
let result = if let Some(t) = {
|
||||||
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()
|
||||||
} {
|
} {
|
||||||
Some(t) => Ok(t),
|
Ok(t)
|
||||||
None => Python::with_gil(|py| -> PyResult<Result<Type, String>> {
|
} else {
|
||||||
|
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)?;
|
||||||
|
@ -1139,13 +1127,11 @@ impl SymbolResolver for Resolver {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(sym_ty)
|
Ok(sym_ty)
|
||||||
})
|
}).unwrap()
|
||||||
.unwrap(),
|
|
||||||
};
|
};
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn get_symbol_value<'ctx>(
|
fn get_symbol_value<'ctx>(
|
||||||
&self,
|
&self,
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue