forked from M-Labs/nac3
1
0
Fork 0

nac3core/artiq/standalone: symbol resolver return error msg for type error of host variables

This commit is contained in:
ychenfo 2022-01-13 03:14:06 +08:00
parent eba9fc8a69
commit 4a1a4dc076
6 changed files with 112 additions and 104 deletions

View File

@ -155,24 +155,30 @@ impl InnerResolver {
unifier: &mut Unifier,
defs: &[Arc<RwLock<TopLevelDef>>],
primitives: &PrimitiveStore,
) -> PyResult<Option<Type>> {
let first = self.get_obj_type(py, list.get_item(0)?, unifier, defs, primitives)?;
Ok((1..len).fold(first, |a, i| {
let b = list
) -> PyResult<Result<Type, String>> {
let mut ty = match self.get_obj_type(py, list.get_item(0)?, unifier, defs, primitives)? {
Ok(t) => t,
Err(e) => return Ok(Err(format!(
"type error ({}) at element #0 of the list", e
))),
};
for i in 1..len {
let b = match list
.get_item(i)
.map(|elem| self.get_obj_type(py, elem, unifier, defs, primitives));
a.and_then(|a| {
if let Ok(Ok(Some(ty))) = b {
if unifier.unify(a, ty).is_ok() {
Some(a)
} else {
None
.map(|elem| self.get_obj_type(py, elem, unifier, defs, primitives))?? {
Ok(t) => t,
Err(e) => return Ok(Err(format!(
"type error ({}) at element #{} of the list", e, i
))),
};
ty = match unifier.unify(ty, b) {
Ok(_) => ty,
Err(e) => return Ok(Err(format!(
"inhomogeneous type ({}) at element #{} of the list", e, i
)))
};
}
} else {
None
}
})
}))
Ok(Ok(ty))
}
// handle python objects that represent types themselves
@ -311,7 +317,9 @@ impl InnerResolver {
Err(err) => return Ok(Err(err)),
};
if !unifier.is_concrete(ty.0, &[]) && !ty.1 {
panic!("type list should take concrete parameters in type var ranges")
return Ok(Err(
"type list should take concrete parameters in typevar range".into()
));
}
Ok(Ok((unifier.add_ty(TypeEnum::TList { ty: ty.0 }), true)))
} else {
@ -430,7 +438,7 @@ impl InnerResolver {
unifier: &mut Unifier,
defs: &[Arc<RwLock<TopLevelDef>>],
primitives: &PrimitiveStore,
) -> PyResult<Option<Type>> {
) -> PyResult<Result<Type, String>> {
let ty = self.helper.type_fn.call1(py, (obj,)).unwrap();
let (extracted_ty, inst_check) = match self.get_pyty_obj_type(
py,
@ -457,7 +465,7 @@ impl InnerResolver {
primitives,
)? {
Ok(s) => s,
Err(_) => return Ok(None),
Err(e) => return Ok(Err(e)),
};
return match (&*unifier.get_ty(extracted_ty), inst_check) {
// do the instantiation for these three types
@ -469,21 +477,22 @@ impl InnerResolver {
TypeEnum::TVar { meta: nac3core::typecheck::typedef::TypeVarMeta::Generic, range, .. }
if range.borrow().is_empty()
));
Ok(Some(extracted_ty))
Ok(Ok(extracted_ty))
} else {
let actual_ty =
self.get_list_elem_type(py, obj, len, unifier, defs, primitives)?;
if let Some(actual_ty) = actual_ty {
unifier.unify(*ty, actual_ty).unwrap();
Ok(Some(extracted_ty))
} else {
Ok(None)
match actual_ty {
Ok(t) => match unifier.unify(*ty, t) {
Ok(_) => Ok(Ok(unifier.add_ty(TypeEnum::TList{ ty: *ty }))),
Err(e) => Ok(Err(format!("type error ({}) for the list", e))),
}
Err(e) => Ok(Err(e)),
}
}
}
(TypeEnum::TTuple { .. }, false) => {
let elements: &PyTuple = obj.cast_as()?;
let types: Result<Option<Vec<_>>, _> = elements
let types: Result<Result<Vec<_>, _>, _> = elements
.iter()
.map(|elem| self.get_obj_type(py, elem, unifier, defs, primitives))
.collect();
@ -510,29 +519,35 @@ impl InnerResolver {
continue;
} else {
let field_data = obj.getattr(&name)?;
let ty = self
.get_obj_type(py, field_data, unifier, defs, primitives)?
.unwrap_or(primitives.none);
let ty = match self
.get_obj_type(py, field_data, unifier, defs, primitives)? {
Ok(t) => t,
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 unifier.unify(ty, field_ty).is_err() {
if let Err(e) = unifier.unify(ty, field_ty) {
// field type mismatch
return Ok(None);
return Ok(Err(format!(
"error when getting type of field `{}` ({})", name, e
)));
}
}
}
for (_, ty) in var_map.iter() {
// must be concrete type
if !unifier.is_concrete(*ty, &[]) {
return Ok(None);
return Ok(Err("object is not of concrete type".into()));
}
}
return Ok(Some(
return Ok(Ok(
unifier
.subst(extracted_ty, &var_map)
.unwrap_or(extracted_ty),
));
}
_ => Ok(Some(extracted_ty)),
_ => Ok(Ok(extracted_ty)),
};
}
@ -686,7 +701,7 @@ impl InnerResolver {
}
let elements: &PyTuple = obj.cast_as()?;
let types: Result<Option<Vec<_>>, _> = elements
let types: Result<Result<Vec<_>, _>, _> = elements
.iter()
.map(|elem| {
self.get_obj_type(
@ -858,22 +873,25 @@ impl SymbolResolver for Resolver {
defs: &[Arc<RwLock<TopLevelDef>>],
primitives: &PrimitiveStore,
str: StrRef,
) -> Option<Type> {
{
) -> Result<Type, String> {
match {
let id_to_type = self.0.id_to_type.read();
id_to_type.get(&str).cloned()
}
.or_else(|| {
let py_id = self.0.name_to_pyid.get(&str);
let result = py_id.and_then(|id| {
{
} {
Some(ty) => Ok(ty),
None => {
let id = match self.0.name_to_pyid.get(&str) {
Some(id) => id,
None => return Err(format!("cannot find symbol `{}`", str)),
};
let result = match {
let pyid_to_type = self.0.pyid_to_type.read();
pyid_to_type.get(id).copied()
}
.or_else(|| {
let result = Python::with_gil(|py| -> PyResult<Option<Type>> {
} {
Some(t) => Ok(t),
None => Python::with_gil(|py| -> PyResult<Result<Type, String>> {
let obj: &PyAny = self.0.module.extract(py)?;
let mut sym_ty = None;
let mut sym_ty = Err(format!("cannot find symbol `{}`", str));
let members: &PyDict = obj.getattr("__dict__").unwrap().cast_as().unwrap();
for (key, val) in members.iter() {
let key: &str = key.extract()?;
@ -882,20 +900,19 @@ impl SymbolResolver for Resolver {
break;
}
}
if let Ok(t) = sym_ty {
self.0.pyid_to_type.write().insert(*id, t);
}
Ok(sym_ty)
})
.unwrap();
if let Some(result) = result {
self.0.pyid_to_type.write().insert(*id, result);
.unwrap(),
};
if let Ok(t) = &result {
self.0.id_to_type.write().insert(str, *t);
}
result
})
});
if let Some(result) = &result {
self.0.id_to_type.write().insert(str, *result);
}
result
})
}
}
fn get_symbol_value<'ctx, 'a>(

View File

@ -92,7 +92,7 @@ pub trait SymbolResolver {
top_level_defs: &[Arc<RwLock<TopLevelDef>>],
primitives: &PrimitiveStore,
str: StrRef,
) -> Option<Type>;
) -> Result<Type, String>;
// get the top-level definition of identifiers
fn get_identifier_def(&self, str: StrRef) -> Option<DefinitionId>;
@ -180,8 +180,7 @@ pub fn parse_type_annotation<T>(
} else {
// it could be a type variable
let ty = resolver
.get_symbol_type(unifier, top_level_defs, primitives, *id)
.ok_or_else(|| "unknown type variable name".to_owned())?;
.get_symbol_type(unifier, top_level_defs, primitives, *id)?;
if let TypeEnum::TVar { .. } = &*unifier.get_ty(ty) {
Ok(ty)
} else {

View File

@ -88,7 +88,7 @@ pub fn parse_ast_to_type_annotation_kinds<T>(
));
}
Ok(TypeAnnotation::CustomClass { id: obj_id, params: vec![] })
} else if let Some(ty) = resolver.get_symbol_type(unifier, top_level_defs, primitives, *id) {
} else if let Ok(ty) = resolver.get_symbol_type(unifier, top_level_defs, primitives, *id) {
if let TypeEnum::TVar { .. } = unifier.get_ty(ty).as_ref() {
Ok(TypeAnnotation::TypeVar(ty))
} else {

View File

@ -69,26 +69,24 @@ impl<'a> Inferencer<'a> {
ExprKind::Name { id, .. } => {
self.should_have_value(expr)?;
if !defined_identifiers.contains(id) {
if self
.function_data
.resolver
.get_symbol_type(
match self.function_data.resolver.get_symbol_type(
self.unifier,
&self.top_level.definitions.read(),
self.primitives,
*id,
)
.is_some()
{
defined_identifiers.insert(*id);
} else {
) {
Ok(_) => {
self.defined_identifiers.insert(*id);
}
Err(e) => {
return Err(format!(
"unknown identifier {} (use before def?) at {}",
id, expr.location
"type error of identifier `{}` ({}) at {}",
id, e, expr.location
));
}
}
}
}
ExprKind::List { elts, .. }
| ExprKind::Tuple { elts, .. }
| ExprKind::BoolOp { values: elts, .. } => {

View File

@ -181,7 +181,7 @@ impl<'a> fold::Fold<()> for Inferencer<'a> {
self.primitives,
id,
)
.unwrap_or_else(|| {
.unwrap_or_else(|_| {
self.variable_mapping.insert(id, value_ty);
value_ty
})
@ -360,25 +360,23 @@ impl<'a> fold::Fold<()> for Inferencer<'a> {
Some(self.infer_constant(value, &expr.location)?),
ast::ExprKind::Name { id, .. } => {
if !self.defined_identifiers.contains(id) {
if self
.function_data
.resolver
.get_symbol_type(
match self.function_data.resolver.get_symbol_type(
self.unifier,
&self.top_level.definitions.read(),
self.primitives,
*id,
)
.is_some()
{
) {
Ok(_) => {
self.defined_identifiers.insert(*id);
} else {
}
Err(e) => {
return report_error(
&format!("unknown identifier {} (use before def?)", id),
&format!("type error of identifier `{}` ({})", id, e),
expr.location,
);
}
}
}
Some(self.infer_identifier(*id)?)
}
ast::ExprKind::List { elts, .. } => Some(self.infer_list(elts)?),
@ -765,7 +763,7 @@ impl<'a> Inferencer<'a> {
.function_data
.resolver
.get_symbol_type(unifier, &self.top_level.definitions.read(), self.primitives, id)
.unwrap_or_else(|| {
.unwrap_or_else(|_| {
let ty = unifier.get_fresh_var().0;
variable_mapping.insert(id, ty);
ty

View File

@ -51,12 +51,8 @@ impl SymbolResolver for Resolver {
_: &[Arc<RwLock<TopLevelDef>>],
_: &PrimitiveStore,
str: StrRef,
) -> Option<Type> {
let ret = self.0.id_to_type.lock().get(&str).cloned();
if ret.is_none() {
// println!("unknown here resolver {}", str);
}
ret
) -> Result<Type, String> {
self.0.id_to_type.lock().get(&str).cloned().ok_or(format!("cannot get type of {}", str))
}
fn get_symbol_value<'ctx, 'a>(