nac3core: get exception ID from symbol resolver

We need to store the exception class somewhere in order to create them
back in the host. Fixes #200
master
pca006132 2022-03-05 00:26:35 +08:00
parent 84b4bd920b
commit 294943e303
5 changed files with 38 additions and 3 deletions

View File

@ -87,6 +87,7 @@ struct Nac3 {
working_directory: TempDir,
top_levels: Vec<TopLevelComponent>,
string_store: Arc<RwLock<HashMap<String, i32>>>,
exception_ids: Arc<RwLock<HashMap<usize, usize>>>,
}
create_exception!(nac3artiq, CompileError, exceptions::PyException);
@ -395,6 +396,7 @@ impl Nac3 {
pyid_to_def: Default::default(),
working_directory,
string_store: Default::default(),
exception_ids: Default::default(),
})
}
@ -442,6 +444,8 @@ impl Nac3 {
let builtins = PyModule::import(py, "builtins")?;
let typings = PyModule::import(py, "typing")?;
let id_fn = builtins.getattr("id")?;
let issubclass = builtins.getattr("issubclass")?;
let exn_class = builtins.getattr("Exception")?;
let store_obj = embedding_map.getattr("store_object").unwrap().to_object(py);
let store_str = embedding_map.getattr("store_str").unwrap().to_object(py);
let store_fun = embedding_map.getattr("store_function").unwrap().to_object(py);
@ -451,7 +455,7 @@ impl Nac3 {
type_fn: builtins.getattr("type").unwrap().to_object(py),
origin_ty_fn: typings.getattr("get_origin").unwrap().to_object(py),
args_ty_fn: typings.getattr("get_args").unwrap().to_object(py),
store_obj,
store_obj: store_obj.clone(),
store_str,
};
let mut module_to_resolver_cache: HashMap<u64, _> = HashMap::new();
@ -463,6 +467,18 @@ impl Nac3 {
let py_module: &PyAny = module.extract(py)?;
let module_id: u64 = id_fn.call1((py_module,))?.extract()?;
let helper = helper.clone();
let class_obj;
if let StmtKind::ClassDef { name, .. } = &stmt.node {
let class = py_module.getattr(name.to_string()).unwrap();
if issubclass.call1((class, exn_class)).unwrap().extract().unwrap() &&
class.getattr("artiq_builtin").is_err() {
class_obj = Some(class);
} else {
class_obj = None;
}
} else {
class_obj = None;
}
let (name_to_pyid, resolver) =
module_to_resolver_cache.get(&module_id).cloned().unwrap_or_else(|| {
let mut name_to_pyid: HashMap<StrRef, u64> = HashMap::new();
@ -488,6 +504,7 @@ impl Nac3 {
field_to_val: Default::default(),
helper,
string_store: self.string_store.clone(),
exception_ids: self.exception_ids.clone(),
})))
as Arc<dyn SymbolResolver + Send + Sync>;
let name_to_pyid = Rc::new(name_to_pyid);
@ -504,6 +521,9 @@ impl Nac3 {
e
))
})?;
if let Some(class_obj) = class_obj {
self.exception_ids.write().insert(def_id.0, store_obj.call1(py, (class_obj, ))?.extract(py)?);
}
match &stmt.node {
StmtKind::FunctionDef { decorator_list, .. } => {
@ -569,6 +589,7 @@ impl Nac3 {
module: module.to_object(py),
helper,
string_store: self.string_store.clone(),
exception_ids: self.exception_ids.clone(),
}))) as Arc<dyn SymbolResolver + Send + Sync>;
let (_, def_id, _) = composer
.register_top_level(synthesized.pop().unwrap(), Some(resolver.clone()), "".into())

View File

@ -41,6 +41,7 @@ pub struct InnerResolver {
pub primitive_ids: PrimitivePythonId,
pub helper: PythonHelper,
pub string_store: Arc<RwLock<HashMap<String, i32>>>,
pub exception_ids: Arc<RwLock<HashMap<usize, usize>>>,
// module specific
pub name_to_pyid: HashMap<StrRef, u64>,
pub module: PyObject,
@ -977,4 +978,9 @@ impl SymbolResolver for Resolver {
id
}
}
fn get_exception_id(&self, tyid: usize) -> usize {
let exn_ids = self.0.exception_ids.read();
exn_ids.get(&tyid).cloned().unwrap_or(0)
}
}

View File

@ -468,7 +468,7 @@ pub fn exn_constructor<'ctx, 'a>(
let def = defs[zelf_id].read();
let zelf_name =
if let TopLevelDef::Class { name, .. } = &*def { *name } else { unreachable!() };
let exception_name = format!("0:{}", zelf_name);
let exception_name = format!("{}:{}", ctx.resolver.get_exception_id(zelf_id), zelf_name);
unsafe {
let id_ptr = ctx.builder.build_in_bounds_gep(zelf, &[zero, zero], "exn.id");
let id = ctx.resolver.get_string_id(&exception_name);
@ -641,7 +641,13 @@ pub fn gen_try<'ctx, 'a, G: CodeGenerator>(
&mut ctx.unifier,
type_.custom.unwrap(),
);
let exn_id = ctx.resolver.get_string_id(&format!("0:{}", exn_name));
let obj_id = if let TypeEnum::TObj { obj_id, .. } = &*ctx.unifier.get_ty(type_.custom.unwrap()) {
*obj_id
} else {
unreachable!()
};
let exception_name = format!("{}:{}", ctx.resolver.get_exception_id(obj_id.0), exn_name);
let exn_id = ctx.resolver.get_string_id(&exception_name);
let exn_id_global =
ctx.module.add_global(ctx.ctx.i32_type(), None, &format!("exn.{}", exn_id));
exn_id_global.set_initializer(&ctx.ctx.i32_type().const_int(exn_id as u64, false));

View File

@ -136,6 +136,7 @@ pub trait SymbolResolver {
fn get_default_param_value(&self, expr: &nac3parser::ast::Expr) -> Option<SymbolValue>;
fn get_string_id(&self, s: &str) -> i32;
fn get_exception_id(&self, tyid: usize) -> usize;
// handle function call etc.
}

View File

@ -1281,6 +1281,7 @@ impl TopLevelComposer {
));
}
}
ast::StmtKind::Assign { .. } => {}, // we don't class attributes
ast::StmtKind::Pass { .. } => {}
ast::StmtKind::Expr { value: _, .. } => {} // typically a docstring; ignoring all expressions matches CPython behavior
_ => {