Aadityavardhan Narayan: Progress toward support
for static class attributes
This commit is contained in:
parent
b514f91441
commit
f73f784cc0
|
@ -1,3 +1,9 @@
|
||||||
__pycache__
|
__pycache__
|
||||||
/target
|
/target
|
||||||
windows/msys2
|
windows/msys2
|
||||||
|
nac3standalone/demo/src/test.py
|
||||||
|
nac3standalone/demo/{
|
||||||
|
interpreted.log
|
||||||
|
nac3standalone/demo/module.o
|
||||||
|
nac3standalone/demo/demo
|
||||||
|
nac3standalone/demo/run.log
|
||||||
|
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
@ -74,6 +74,8 @@ pub fn get_exn_constructor(
|
||||||
constructor: Some(signature),
|
constructor: Some(signature),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
loc: None,
|
loc: None,
|
||||||
|
// Make TopLevelDef::Class initlializer compatible
|
||||||
|
static_fields: Default::default(),
|
||||||
};
|
};
|
||||||
(fun_def, class_def, signature, exn_type)
|
(fun_def, class_def, signature, exn_type)
|
||||||
}
|
}
|
||||||
|
@ -175,6 +177,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||||
type_vars: Default::default(),
|
type_vars: Default::default(),
|
||||||
fields: exception_fields,
|
fields: exception_fields,
|
||||||
methods: Default::default(),
|
methods: Default::default(),
|
||||||
|
// Make TopLevelDef::Class initlializer compatible
|
||||||
|
static_fields: Default::default(),
|
||||||
ancestors: vec![],
|
ancestors: vec![],
|
||||||
constructor: None,
|
constructor: None,
|
||||||
resolver: None,
|
resolver: None,
|
||||||
|
@ -200,6 +204,8 @@ pub fn get_builtins(primitives: &mut (PrimitiveStore, Unifier)) -> BuiltinInfo {
|
||||||
object_id: DefinitionId(10),
|
object_id: DefinitionId(10),
|
||||||
type_vars: vec![option_ty_var],
|
type_vars: vec![option_ty_var],
|
||||||
fields: vec![],
|
fields: vec![],
|
||||||
|
// Make TopLevelDef::Class initlializer compatible
|
||||||
|
static_fields: vec![],
|
||||||
methods: vec![
|
methods: vec![
|
||||||
("is_some".into(), is_some_ty.0, DefinitionId(11)),
|
("is_some".into(), is_some_ty.0, DefinitionId(11)),
|
||||||
("is_none".into(), is_some_ty.0, DefinitionId(12)),
|
("is_none".into(), is_some_ty.0, DefinitionId(12)),
|
||||||
|
|
|
@ -1040,6 +1040,7 @@ impl TopLevelComposer {
|
||||||
class_body_ast,
|
class_body_ast,
|
||||||
_class_ancestor_def,
|
_class_ancestor_def,
|
||||||
class_fields_def,
|
class_fields_def,
|
||||||
|
class_static_fields_def, // Introduce static class attribute list into the function
|
||||||
class_methods_def,
|
class_methods_def,
|
||||||
class_type_vars_def,
|
class_type_vars_def,
|
||||||
class_resolver,
|
class_resolver,
|
||||||
|
@ -1047,6 +1048,7 @@ impl TopLevelComposer {
|
||||||
object_id,
|
object_id,
|
||||||
ancestors,
|
ancestors,
|
||||||
fields,
|
fields,
|
||||||
|
static_fields,
|
||||||
methods,
|
methods,
|
||||||
resolver,
|
resolver,
|
||||||
type_vars,
|
type_vars,
|
||||||
|
@ -1054,7 +1056,7 @@ impl TopLevelComposer {
|
||||||
} = &mut *class_def
|
} = &mut *class_def
|
||||||
{
|
{
|
||||||
if let ast::StmtKind::ClassDef { name, bases, body, .. } = &class_ast {
|
if let ast::StmtKind::ClassDef { name, bases, body, .. } = &class_ast {
|
||||||
(*object_id, *name, bases, body, ancestors, fields, methods, type_vars, resolver)
|
(*object_id, *name, bases, body, ancestors, fields, static_fields, methods, type_vars, resolver)
|
||||||
} else {
|
} else {
|
||||||
unreachable!("here must be class def ast");
|
unreachable!("here must be class def ast");
|
||||||
}
|
}
|
||||||
|
@ -1268,7 +1270,8 @@ impl TopLevelComposer {
|
||||||
.unify(method_dummy_ty, method_type)
|
.unify(method_dummy_ty, method_type)
|
||||||
.map_err(|e| e.to_display(unifier).to_string())?;
|
.map_err(|e| e.to_display(unifier).to_string())?;
|
||||||
}
|
}
|
||||||
ast::StmtKind::AnnAssign { target, annotation, value: None, .. } => {
|
// Reset value from none since fields in the form "ATTR_0: int32 = 10" need to be initialised
|
||||||
|
ast::StmtKind::AnnAssign { target, annotation, value, .. } => {
|
||||||
if let ast::ExprKind::Name { id: attr, .. } = &target.node {
|
if let ast::ExprKind::Name { id: attr, .. } = &target.node {
|
||||||
if defined_fields.insert(attr.to_string()) {
|
if defined_fields.insert(attr.to_string()) {
|
||||||
let dummy_field_type = unifier.get_dummy_var().0;
|
let dummy_field_type = unifier.get_dummy_var().0;
|
||||||
|
@ -1294,6 +1297,10 @@ impl TopLevelComposer {
|
||||||
_ if core_config.kernel_ann.is_none() => (annotation, true),
|
_ if core_config.kernel_ann.is_none() => (annotation, true),
|
||||||
_ => continue, // ignore fields annotated otherwise
|
_ => continue, // ignore fields annotated otherwise
|
||||||
};
|
};
|
||||||
|
// If the value node is provided, then it must be a static class attribute
|
||||||
|
if let Option::Some(..) = &value{
|
||||||
|
class_static_fields_def.push((*attr, dummy_field_type, mutable));
|
||||||
|
}
|
||||||
class_fields_def.push((*attr, dummy_field_type, mutable));
|
class_fields_def.push((*attr, dummy_field_type, mutable));
|
||||||
|
|
||||||
let parsed_annotation = parse_ast_to_type_annotation_kinds(
|
let parsed_annotation = parse_ast_to_type_annotation_kinds(
|
||||||
|
@ -1335,7 +1342,76 @@ impl TopLevelComposer {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::StmtKind::Assign { .. } => {}, // we don't class attributes
|
|
||||||
|
// Add assign branch since fields in the form "ATTR_0 = 5" in the class body qualify as static class attributes
|
||||||
|
// However, type checking and expression folding needs to be performed in order to correctly
|
||||||
|
// Infer the type of target
|
||||||
|
ast::StmtKind::Assign { targets, value, .. } => {
|
||||||
|
// let ctx = Arc::new(self.make_top_level_context());
|
||||||
|
|
||||||
|
// let mut identifiers = {
|
||||||
|
// let mut result: HashSet<_> = HashSet::new();
|
||||||
|
// if self_type.is_some() {
|
||||||
|
// result.insert("self".into());
|
||||||
|
// }
|
||||||
|
// result.extend(inst_args.iter().map(|x| x.name));
|
||||||
|
// result
|
||||||
|
// };
|
||||||
|
// let mut calls: HashMap<CodeLocation, CallId> = HashMap::new();
|
||||||
|
// let mut inferencer = Inferencer {
|
||||||
|
// top_level: ctx.as_ref(),
|
||||||
|
// defined_identifiers: identifiers.clone(),
|
||||||
|
// function_data: &mut FunctionData {
|
||||||
|
// resolver: class_resolver.as_ref().unwrap().clone(),
|
||||||
|
// return_type: if unifier.unioned(inst_ret, primitives_ty.none) {
|
||||||
|
// None
|
||||||
|
// } else {
|
||||||
|
// Some(inst_ret)
|
||||||
|
// },
|
||||||
|
// // NOTE: allowed type vars
|
||||||
|
// bound_variables: no_range_vars.clone(),
|
||||||
|
// },
|
||||||
|
// unifier,
|
||||||
|
// variable_mapping: {
|
||||||
|
// let mut result: HashMap<StrRef, Type> = HashMap::new();
|
||||||
|
// if let Some(self_ty) = self_type {
|
||||||
|
// result.insert("self".into(), self_ty);
|
||||||
|
// }
|
||||||
|
// result.extend(inst_args.iter().map(|x| (x.name, x.ty)));
|
||||||
|
// result
|
||||||
|
// },
|
||||||
|
// primitives: primitives_ty,
|
||||||
|
// virtual_checks: &mut Vec::new(),
|
||||||
|
// calls: &mut calls,
|
||||||
|
// in_handler: false,
|
||||||
|
// };
|
||||||
|
|
||||||
|
for target in targets {
|
||||||
|
if let ast::ExprKind::Name { id: attr, .. } = &target.node {
|
||||||
|
if defined_fields.insert(attr.to_string()) {
|
||||||
|
let dummy_field_type = unifier.get_dummy_var().0;
|
||||||
|
|
||||||
|
class_static_fields_def.push((*attr, dummy_field_type, true));
|
||||||
|
class_fields_def.push((*attr, dummy_field_type, true));
|
||||||
|
|
||||||
|
// let value = inferencer.fold_expr(*value)?;
|
||||||
|
// let value_ty = value.custom.unwrap();
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
return Err(format!(
|
||||||
|
"same class fields `{}` defined twice (at {})",
|
||||||
|
attr, target.location
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return Err(format!(
|
||||||
|
"unsupported statement type in class definition body (at {})",
|
||||||
|
target.location
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
ast::StmtKind::Pass { .. } => {}
|
ast::StmtKind::Pass { .. } => {}
|
||||||
ast::StmtKind::Expr { value: _, .. } => {} // typically a docstring; ignoring all expressions matches CPython behavior
|
ast::StmtKind::Expr { value: _, .. } => {} // typically a docstring; ignoring all expressions matches CPython behavior
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1516,6 +1592,7 @@ impl TopLevelComposer {
|
||||||
ancestors,
|
ancestors,
|
||||||
methods,
|
methods,
|
||||||
fields,
|
fields,
|
||||||
|
static_fields, // Introduce static fields for (un)initialization check
|
||||||
type_vars,
|
type_vars,
|
||||||
name: class_name,
|
name: class_name,
|
||||||
object_id,
|
object_id,
|
||||||
|
@ -1618,11 +1695,13 @@ impl TopLevelComposer {
|
||||||
unreachable!("must be init function here")
|
unreachable!("must be init function here")
|
||||||
}
|
}
|
||||||
let all_inited = Self::get_all_assigned_field(body.as_slice())?;
|
let all_inited = Self::get_all_assigned_field(body.as_slice())?;
|
||||||
for (f, _, _) in fields {
|
// If a field is uninitialized but also a static class attribute, don't
|
||||||
if !all_inited.contains(f) {
|
// throw an error due to uninitialization
|
||||||
|
for f in fields {
|
||||||
|
if !all_inited.contains(&f.0) && !static_fields.contains(&f) {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"fields `{}` of class `{}` not fully initialized in the initializer (at {})",
|
"fields `{}` of class `{}` not fully initialized in the initializer (at {})",
|
||||||
f,
|
&f.0,
|
||||||
class_name,
|
class_name,
|
||||||
body[0].location,
|
body[0].location,
|
||||||
));
|
));
|
||||||
|
|
|
@ -162,6 +162,7 @@ impl TopLevelComposer {
|
||||||
object_id: DefinitionId(index),
|
object_id: DefinitionId(index),
|
||||||
type_vars: Default::default(),
|
type_vars: Default::default(),
|
||||||
fields: Default::default(),
|
fields: Default::default(),
|
||||||
|
static_fields: Default::default(), // Initialize for constructor
|
||||||
methods: Default::default(),
|
methods: Default::default(),
|
||||||
ancestors: Default::default(),
|
ancestors: Default::default(),
|
||||||
constructor,
|
constructor,
|
||||||
|
|
|
@ -92,6 +92,8 @@ pub enum TopLevelDef {
|
||||||
// name, type, is mutable
|
// name, type, is mutable
|
||||||
fields: Vec<(StrRef, Type, bool)>,
|
fields: Vec<(StrRef, Type, bool)>,
|
||||||
// class methods, pointing to the corresponding function definition.
|
// class methods, pointing to the corresponding function definition.
|
||||||
|
static_fields: Vec<(StrRef, Type, bool)>,
|
||||||
|
// list of static data members
|
||||||
methods: Vec<(StrRef, Type, DefinitionId)>,
|
methods: Vec<(StrRef, Type, DefinitionId)>,
|
||||||
// ancestor classes, including itself.
|
// ancestor classes, including itself.
|
||||||
ancestors: Vec<TypeAnnotation>,
|
ancestors: Vec<TypeAnnotation>,
|
||||||
|
|
0
nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__generic_class.snap
Normal file → Executable file
0
nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__generic_class.snap
Normal file → Executable file
0
nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__inheritance_override.snap
Normal file → Executable file
0
nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__inheritance_override.snap
Normal file → Executable file
0
nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__list_tuple_generic.snap
Normal file → Executable file
0
nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__list_tuple_generic.snap
Normal file → Executable file
0
nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__self1.snap
Normal file → Executable file
0
nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__self1.snap
Normal file → Executable file
0
nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__simple_class_compose.snap
Normal file → Executable file
0
nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__simple_class_compose.snap
Normal file → Executable file
0
nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__simple_pass_in_class.snap
Normal file → Executable file
0
nac3core/src/toplevel/snapshots/nac3core__toplevel__test__test_analyze__simple_pass_in_class.snap
Normal file → Executable file
|
@ -513,7 +513,7 @@ impl Unifier {
|
||||||
|
|
||||||
fn unify_impl(&mut self, a: Type, b: Type, swapped: bool) -> Result<(), TypeError> {
|
fn unify_impl(&mut self, a: Type, b: Type, swapped: bool) -> Result<(), TypeError> {
|
||||||
use TypeEnum::*;
|
use TypeEnum::*;
|
||||||
|
|
||||||
if !swapped {
|
if !swapped {
|
||||||
let rep_a = self.unification_table.get_representative(a);
|
let rep_a = self.unification_table.get_representative(a);
|
||||||
let rep_b = self.unification_table.get_representative(b);
|
let rep_b = self.unification_table.get_representative(b);
|
||||||
|
|
0
nac3parser/src/snapshots/nac3parser__fstring__tests__fstring_parse_selfdocumenting_base.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__fstring_parse_selfdocumenting_base.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__fstring_parse_selfdocumenting_base_more.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__fstring_parse_selfdocumenting_base_more.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__fstring_parse_selfdocumenting_format.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__fstring_parse_selfdocumenting_format.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_empty_fstring.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_empty_fstring.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_equals.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_equals.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_nested_spec.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_nested_spec.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_not_equals.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_not_equals.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_not_nested_spec.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_not_nested_spec.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_selfdoc_prec_space.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_selfdoc_prec_space.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_selfdoc_trailing_space.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_selfdoc_trailing_space.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_yield_expr.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__fstring__tests__parse_fstring_yield_expr.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__comment_ambiguity.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__comment_ambiguity.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__more_comment.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__more_comment.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_class.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_class.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_dict_comprehension.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_dict_comprehension.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_double_list_comprehension.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_double_list_comprehension.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_empty.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_empty.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_if_elif_else.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_if_elif_else.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_kwargs.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_kwargs.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_lambda.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_lambda.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_list_comprehension.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_list_comprehension.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_print_2.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_print_2.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_print_hello.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_print_hello.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_tuples.snap
Normal file → Executable file
0
nac3parser/src/snapshots/nac3parser__parser__tests__parse_tuples.snap
Normal file → Executable file
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue