nac3core: toplevel, fix for class constructors + spelling errors #263
@ -167,7 +167,7 @@ impl TopLevelComposer {
|
|||||||
) -> Result<(StrRef, DefinitionId, Option<Type>), String> {
|
) -> Result<(StrRef, DefinitionId, Option<Type>), String> {
|
||||||
let defined_names = &mut self.defined_names;
|
let defined_names = &mut self.defined_names;
|
||||||
match &ast.node {
|
match &ast.node {
|
||||||
ast::StmtKind::ClassDef { name: class_name, bases, body, .. } => {
|
ast::StmtKind::ClassDef { name: class_name, body, .. } => {
|
||||||
if self.keyword_list.contains(class_name) {
|
if self.keyword_list.contains(class_name) {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"cannot use keyword `{}` as a class name (at {})",
|
"cannot use keyword `{}` as a class name (at {})",
|
||||||
@ -221,18 +221,9 @@ impl TopLevelComposer {
|
|||||||
// we do not push anything to the def list, so we keep track of the index
|
// we do not push anything to the def list, so we keep track of the index
|
||||||
// and then push in the correct order after the for loop
|
// and then push in the correct order after the for loop
|
||||||
let mut class_method_index_offset = 0;
|
let mut class_method_index_offset = 0;
|
||||||
let init_id = "__init__".into();
|
|
||||||
let exception_id = "Exception".into();
|
|
||||||
// TODO: Fix this hack. We will generate constructor for classes that inherit
|
|
||||||
|
|||||||
// from Exception class (directly or indirectly), but this code cannot handle
|
|
||||||
// subclass of other exception classes.
|
|
||||||
let mut contains_constructor = bases
|
|
||||||
.iter().any(|base| matches!(base.node, ast::ExprKind::Name { id, .. } if id == exception_id));
|
|
||||||
for b in body {
|
for b in body {
|
||||||
if let ast::StmtKind::FunctionDef { name: method_name, .. } = &b.node {
|
if let ast::StmtKind::FunctionDef { name: method_name, .. } = &b.node {
|
||||||
if method_name == &init_id {
|
|
||||||
contains_constructor = true;
|
|
||||||
}
|
|
||||||
if self.keyword_list.contains(method_name) {
|
if self.keyword_list.contains(method_name) {
|
||||||
return Err(format!(
|
return Err(format!(
|
||||||
"cannot use keyword `{}` as a method name (at {})",
|
"cannot use keyword `{}` as a method name (at {})",
|
||||||
@ -298,7 +289,7 @@ impl TopLevelComposer {
|
|||||||
self.definition_ast_list.push((def, Some(ast)));
|
self.definition_ast_list.push((def, Some(ast)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let result_ty = if contains_constructor { Some(constructor_ty) } else { None };
|
let result_ty = Some(constructor_ty);
|
||||||
Ok((class_name, DefinitionId(class_def_id), result_ty))
|
Ok((class_name, DefinitionId(class_def_id), result_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1470,7 +1461,7 @@ impl TopLevelComposer {
|
|||||||
|
|
||||||
/// step 5, analyze and call type inferecer to fill the `instance_to_stmt` of topleveldef::function
|
/// step 5, analyze and call type inferecer to fill the `instance_to_stmt` of topleveldef::function
|
||||||
fn analyze_function_instance(&mut self) -> Result<(), String> {
|
fn analyze_function_instance(&mut self) -> Result<(), String> {
|
||||||
// first get the class contructor type correct for the following type check in function body
|
// first get the class constructor type correct for the following type check in function body
|
||||||
// also do class field instantiation check
|
// also do class field instantiation check
|
||||||
let init_str_id = "__init__".into();
|
let init_str_id = "__init__".into();
|
||||||
let mut definition_extension = Vec::new();
|
let mut definition_extension = Vec::new();
|
||||||
@ -1581,7 +1572,7 @@ impl TopLevelComposer {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let mut init_id: Option<DefinitionId> = None;
|
let mut init_id: Option<DefinitionId> = None;
|
||||||
// get the class contructor type correct
|
// get the class constructor type correct
|
||||||
let (contor_args, contor_type_vars) = {
|
let (contor_args, contor_type_vars) = {
|
||||||
let mut constructor_args: Vec<FuncArg> = Vec::new();
|
let mut constructor_args: Vec<FuncArg> = Vec::new();
|
||||||
let mut type_vars: HashMap<u32, Type> = HashMap::new();
|
let mut type_vars: HashMap<u32, Type> = HashMap::new();
|
||||||
|
13
nac3standalone/demo/src/initless.py
Normal file
13
nac3standalone/demo/src/initless.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
@extern
|
||||||
|
def output_int32(x: int32):
|
||||||
|
...
|
||||||
|
|
||||||
|
class A:
|
||||||
|
def foo(self):
|
||||||
|
output_int32(1)
|
||||||
|
|
||||||
|
def run() -> int32:
|
||||||
|
inst = A()
|
||||||
|
inst.foo()
|
||||||
|
output_int32(1)
|
||||||
|
return 0
|
Loading…
Reference in New Issue
Block a user
@pca006132 What is the purpose of this hack?
register_top_level
will returnResult<(StrRef, DefinitionId, Option<Type>), String>
, where the third element of the tuple is the type of the function or constructor of the class (if there is any). If the class does not have a constructor, the third element will be None to avoid adding this to the symbol table. If the class inherits fromException
, we will need to generate a default constructor for it.We will generate or we are generating? I think this is already implemented?