master #311
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
@ -74,6 +74,7 @@ pub fn get_exn_constructor(
|
||||||
constructor: Some(signature),
|
constructor: Some(signature),
|
||||||
resolver: None,
|
resolver: None,
|
||||||
loc: None,
|
loc: None,
|
||||||
|
static_fields: Default::default(),
|
||||||
};
|
};
|
||||||
(fun_def, class_def, signature, exn_type)
|
(fun_def, class_def, signature, exn_type)
|
||||||
}
|
}
|
||||||
|
@ -175,6 +176,7 @@ 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(),
|
||||||
|
static_fields: Default::default(),
|
||||||
ancestors: vec![],
|
ancestors: vec![],
|
||||||
|
|||||||
constructor: None,
|
constructor: None,
|
||||||
resolver: None,
|
resolver: None,
|
||||||
|
@ -200,6 +202,7 @@ 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![],
|
||||||
|
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,34 @@ 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, .. } => {
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
} 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 +1550,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 +1653,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
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
Typo
What does that mean anyway?
To call out the newly introduced static_fields data member in the TopLevelDef::Class struct.