From 7da50a69f3b0af5d44b283d3d6af7ebe57db6e12 Mon Sep 17 00:00:00 2001 From: Tanay Manerikar Date: Mon, 24 Jun 2024 20:46:39 +0530 Subject: [PATCH 1/9] Constructors initial implementation --- src/libasr/ASR.asdl | 2 +- src/libasr/asr_utils.h | 4 +- src/libasr/pass/instantiate_template.cpp | 17 +- src/lpython/semantics/python_ast_to_asr.cpp | 174 +++++++++++++----- tests/reference/asr-intent_01-66824bc.json | 2 +- tests/reference/asr-intent_01-66824bc.stdout | 1 + tests/reference/asr-structs_01-66dc2c9.json | 2 +- tests/reference/asr-structs_01-66dc2c9.stdout | 1 + tests/reference/asr-structs_01-be14d49.json | 2 +- tests/reference/asr-structs_01-be14d49.stdout | 1 + tests/reference/asr-structs_02-2ab459a.json | 2 +- tests/reference/asr-structs_02-2ab459a.stdout | 1 + tests/reference/asr-structs_03-0cef911.json | 2 +- tests/reference/asr-structs_03-0cef911.stdout | 1 + tests/reference/asr-structs_04-387747b.json | 2 +- tests/reference/asr-structs_04-387747b.stdout | 2 + tests/reference/asr-structs_05-fa98307.json | 2 +- tests/reference/asr-structs_05-fa98307.stdout | 1 + tests/reference/asr-structs_16-44de89a.json | 2 +- tests/reference/asr-structs_16-44de89a.stdout | 1 + ..._class_constructor-structs_16-5e3508f.json | 2 +- ...lass_constructor-structs_16-5e3508f.stdout | 1 + 22 files changed, 162 insertions(+), 63 deletions(-) diff --git a/src/libasr/ASR.asdl b/src/libasr/ASR.asdl index 1d4cf6ee7d..6b56fba342 100644 --- a/src/libasr/ASR.asdl +++ b/src/libasr/ASR.asdl @@ -15,7 +15,7 @@ symbol | GenericProcedure(symbol_table parent_symtab, identifier name, symbol* procs, access access) | CustomOperator(symbol_table parent_symtab, identifier name, symbol* procs, access access) | ExternalSymbol(symbol_table parent_symtab, identifier name, symbol external, identifier module_name, identifier* scope_names, identifier original_name, access access) - | Struct(symbol_table symtab, identifier name, identifier* dependencies, identifier* members, abi abi, access access, bool is_packed, bool is_abstract, call_arg* initializers, expr? alignment, symbol? parent) + | Struct(symbol_table symtab, identifier name, identifier* dependencies, identifier* members, identifier* member_functions, abi abi, access access, bool is_packed, bool is_abstract, call_arg* initializers, expr? alignment, symbol? parent) | EnumType(symbol_table symtab, identifier name, identifier* dependencies, identifier* members, abi abi, access access, enumtype enum_value_type, ttype type, symbol? parent) | UnionType(symbol_table symtab, identifier name, identifier* dependencies, identifier* members, abi abi, access access, call_arg* initializers, symbol? parent) | Variable(symbol_table parent_symtab, identifier name, identifier* dependencies, intent intent, expr? symbolic_value, expr? value, storage_type storage, ttype type, symbol? type_declaration, abi abi, access access, presence presence, bool value_attr) diff --git a/src/libasr/asr_utils.h b/src/libasr/asr_utils.h index a09db5685b..bfe7a098a6 100644 --- a/src/libasr/asr_utils.h +++ b/src/libasr/asr_utils.h @@ -4299,7 +4299,9 @@ class SymbolDuplicator { return ASR::down_cast(ASR::make_Struct_t( al, struct_type_t->base.base.loc, struct_type_symtab, struct_type_t->m_name, struct_type_t->m_dependencies, struct_type_t->n_dependencies, - struct_type_t->m_members, struct_type_t->n_members, struct_type_t->m_abi, + struct_type_t->m_members, struct_type_t->n_members, + struct_type_t->m_member_functions, struct_type_t->n_member_functions, + struct_type_t->m_abi, struct_type_t->m_access, struct_type_t->m_is_packed, struct_type_t->m_is_abstract, struct_type_t->m_initializers, struct_type_t->n_initializers, struct_type_t->m_alignment, struct_type_t->m_parent)); diff --git a/src/libasr/pass/instantiate_template.cpp b/src/libasr/pass/instantiate_template.cpp index ab5b9cc478..bae3d9235e 100644 --- a/src/libasr/pass/instantiate_template.cpp +++ b/src/libasr/pass/instantiate_template.cpp @@ -328,12 +328,19 @@ class SymbolInstantiator : public ASR::BaseExprStmtDuplicatorm_members[i]); } + Vec data_member_fn_names; + data_member_fn_names.reserve(al, x->n_member_functions); + for (size_t i=0; in_members; i++) { + data_member_fn_names.push_back(al, x->m_member_functions[i]); + } + ASR::expr_t *m_alignment = duplicate_expr(x->m_alignment); ASR::asr_t *result = ASR::make_Struct_t(al, x->base.base.loc, current_scope, s2c(al, new_sym_name), nullptr, 0, data_member_names.p, data_member_names.size(), + data_member_fn_names.p, data_member_fn_names.size(), x->m_abi, x->m_access, x->m_is_packed, x->m_is_abstract, nullptr, 0, m_alignment, nullptr); @@ -1255,11 +1262,19 @@ class SymbolInstantiator : public ASR::BaseExprStmtDuplicatorm_members[i]); } + Vec data_member_fn_names; + data_member_fn_names.reserve(al, x->n_member_functions); + for (size_t i=0; in_members; i++) { + data_member_fn_names.push_back(al, x->m_member_functions[i]); + } + ASR::expr_t* m_alignment = duplicate_expr(x->m_alignment); ASR::asr_t* result = ASR::make_Struct_t(al, x->base.base.loc, new_scope, s2c(al, new_sym_name), nullptr, 0, data_member_names.p, - data_member_names.size(), x->m_abi, x->m_access, x->m_is_packed, + data_member_names.size(), + data_member_fn_names.p, data_member_fn_names.size(), + x->m_abi, x->m_access, x->m_is_packed, x->m_is_abstract, nullptr, 0, m_alignment, nullptr); ASR::symbol_t* s = ASR::down_cast(result); diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 2e6337dcb6..4c6e041656 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -2493,13 +2493,12 @@ class CommonVisitor : public AST::BaseVisitor { return false; } - bool is_dataclass(AST::expr_t** decorators, size_t n, + + void get_alignment(AST::expr_t** decorators, size_t n, ASR::expr_t*& aligned_expr, bool& is_packed) { - bool is_dataclass_ = false; for( size_t i = 0; i < n; i++ ) { if( AST::is_a(*decorators[i]) ) { AST::Name_t* dc_name = AST::down_cast(decorators[i]); - is_dataclass_ = std::string(dc_name->m_id) == "dataclass"; is_packed = is_packed || std::string(dc_name->m_id) == "packed"; } else if( AST::is_a(*decorators[i]) ) { AST::Call_t* dc_call = AST::down_cast(decorators[i]); @@ -2531,7 +2530,17 @@ class CommonVisitor : public AST::BaseVisitor { } } } + return; + } + bool is_dataclass(AST::expr_t** decorators, size_t n) { + bool is_dataclass_ = false; + for( size_t i = 0; i < n; i++ ) { + if( AST::is_a(*decorators[i]) ) { + AST::Name_t* dc_name = AST::down_cast(decorators[i]); + is_dataclass_ = std::string(dc_name->m_id) == "dataclass"; + } + } return is_dataclass_; } @@ -2924,9 +2933,10 @@ class CommonVisitor : public AST::BaseVisitor { } void visit_ClassMembers(const AST::ClassDef_t& x, - Vec& member_names, SetChar& struct_dependencies, - Vec &member_init, - bool is_enum_scope=false, ASR::abiType abi=ASR::abiType::Source) { + Vec& member_names, Vec& member_fn_names, + SetChar& struct_dependencies, Vec &member_init, + bool is_enum_scope=false, ASR::abiType abi=ASR::abiType::Source, + bool is_genr_body=false, bool is_class_scope = false) { int64_t prev_value = 1; for( size_t i = 0; i < x.n_body; i++ ) { if (AST::is_a(*x.m_body[i])) { @@ -2942,7 +2952,15 @@ class CommonVisitor : public AST::BaseVisitor { visit_ClassDef(*AST::down_cast(x.m_body[i])); continue; } else if ( AST::is_a(*x.m_body[i]) ) { - throw SemanticError("Struct member functions are not supported", x.m_body[i]->base.loc); + if ( !is_class_scope ) { + throw SemanticError("Struct member functions are not supported", x.m_body[i]->base.loc); + } + else { + this->visit_stmt(*x.m_body[i]); + AST::FunctionDef_t *f = AST::down_cast(x.m_body[i]); + member_fn_names.push_back(al, f->m_name); + continue; + } } else if (AST::is_a(*x.m_body[i])) { continue; } else if (!AST::is_a(*x.m_body[i])) { @@ -3030,6 +3048,8 @@ class CommonVisitor : public AST::BaseVisitor { void visit_ClassDef(const AST::ClassDef_t& x) { std::string x_m_name = x.m_name; + ASR::expr_t* aligned_expr = nullptr; + bool is_packed = false; if( is_enum(x.m_bases, x.n_bases) ) { if( current_scope->resolve_symbol(x_m_name) ) { return ; @@ -3038,14 +3058,16 @@ class CommonVisitor : public AST::BaseVisitor { SymbolTable *parent_scope = current_scope; current_scope = al.make_new(parent_scope); Vec member_names; + Vec member_fn_names; Vec member_init; member_names.reserve(al, x.n_body); + member_fn_names.reserve(al, 1); member_init.reserve(al, 1); Vec* current_body_copy = current_body; current_body = nullptr; SetChar struct_dependencies; struct_dependencies.reserve(al, 1); - visit_ClassMembers(x, member_names, struct_dependencies, member_init, true, enum_abi); + visit_ClassMembers(x, member_names, member_fn_names, struct_dependencies, member_init, true, enum_abi); current_body = current_body_copy; ASR::ttype_t* common_type = nullptr; for( auto sym: current_scope->get_scope() ) { @@ -3124,12 +3146,14 @@ class CommonVisitor : public AST::BaseVisitor { SymbolTable *parent_scope = current_scope; current_scope = al.make_new(parent_scope); Vec member_names; + Vec member_fn_names; Vec member_init; member_names.reserve(al, x.n_body); member_init.reserve(al, x.n_body); + member_fn_names.reserve(al, 1); SetChar struct_dependencies; struct_dependencies.reserve(al, 1); - visit_ClassMembers(x, member_names, struct_dependencies, member_init); + visit_ClassMembers(x, member_names, member_fn_names, struct_dependencies, member_init); LCOMPILERS_ASSERT(member_init.size() == member_names.size()); ASR::symbol_t* union_type = ASR::down_cast(ASR::make_UnionType_t(al, x.base.base.loc, current_scope, x.m_name, @@ -3147,49 +3171,97 @@ class CommonVisitor : public AST::BaseVisitor { current_scope->add_symbol(x_m_name, union_type); } return ; - } - ASR::expr_t* algined_expr = nullptr; - bool is_packed = false; - if( !is_dataclass(x.m_decorator_list, x.n_decorator_list, - algined_expr, is_packed) ) { - throw SemanticError("Only dataclass-decorated classes and Enum subclasses are supported.", - x.base.base.loc); - } - - if( x.n_bases > 0 ) { - throw SemanticError("Inheritance in classes isn't supported yet.", - x.base.base.loc); - } - - SymbolTable *parent_scope = current_scope; - current_scope = al.make_new(parent_scope); - Vec member_names; - Vec member_init; - member_names.reserve(al, x.n_body); - member_init.reserve(al, x.n_body); - SetChar struct_dependencies; - struct_dependencies.reserve(al, 1); - ASR::abiType class_abi = ASR::abiType::Source; - if( is_bindc_class(x.m_decorator_list, x.n_decorator_list) ) { - class_abi = ASR::abiType::BindC; - } - visit_ClassMembers(x, member_names, struct_dependencies, member_init, false, class_abi); - LCOMPILERS_ASSERT(member_init.size() == member_names.size()); - ASR::symbol_t* class_type = ASR::down_cast(ASR::make_Struct_t(al, - x.base.base.loc, current_scope, x.m_name, - struct_dependencies.p, struct_dependencies.size(), - member_names.p, member_names.size(), - class_abi, ASR::accessType::Public, - is_packed, false, member_init.p, member_init.size(), algined_expr, - nullptr)); - current_scope = parent_scope; - if (current_scope->resolve_symbol(x_m_name)) { - ASR::symbol_t* sym = current_scope->resolve_symbol(x_m_name); - ASR::Struct_t *st = ASR::down_cast(sym); - st->m_initializers = member_init.p; - st->n_initializers = member_init.size(); + } else if( is_dataclass(x.m_decorator_list, x.n_decorator_list) ){ + get_alignment(x.m_decorator_list, x.n_decorator_list, + aligned_expr, is_packed); + if( x.n_bases > 0 ) { + throw SemanticError("Inheritance in classes isn't supported yet.", + x.base.base.loc); + } + SymbolTable *parent_scope = current_scope; + current_scope = al.make_new(parent_scope); + Vec member_names; + Vec member_fn_names; + Vec member_init; + member_names.reserve(al, x.n_body); + member_fn_names.reserve(al, 1); + member_init.reserve(al, x.n_body); + SetChar struct_dependencies; + struct_dependencies.reserve(al, 1); + ASR::abiType class_abi = ASR::abiType::Source; + if( is_bindc_class(x.m_decorator_list, x.n_decorator_list) ) { + class_abi = ASR::abiType::BindC; + } + visit_ClassMembers(x, member_names, member_fn_names, struct_dependencies, member_init, false, class_abi);//TODO add member functions to the list + LCOMPILERS_ASSERT(member_init.size() == member_names.size()); + ASR::symbol_t* class_type = ASR::down_cast(ASR::make_Struct_t(al, + x.base.base.loc, current_scope, x.m_name, + struct_dependencies.p, struct_dependencies.size(), + member_names.p, member_names.size(), + member_fn_names.p, member_fn_names.size(), + class_abi, ASR::accessType::Public, + is_packed, false, member_init.p, member_init.size(), aligned_expr, + nullptr)); + current_scope = parent_scope; + if (current_scope->resolve_symbol(x_m_name)) { + ASR::symbol_t* sym = current_scope->resolve_symbol(x_m_name); + ASR::Struct_t *st = ASR::down_cast(sym); + st->m_initializers = member_init.p; + st->n_initializers = member_init.size(); + } else { + current_scope->add_symbol(x_m_name, class_type); + } } else { - current_scope->add_symbol(x_m_name, class_type); + get_alignment(x.m_decorator_list, x.n_decorator_list, + aligned_expr, is_packed); + if( x.n_bases > 0 ) { + throw SemanticError("Inheritance in classes isn't supported yet.", + x.base.base.loc); + } + bool is_genr_body = false; + ASR::symbol_t* sym = nullptr; + ASR::Struct_t *st = nullptr; + SymbolTable *parent_scope = current_scope; + if( current_scope->resolve_symbol(x_m_name) ){ + sym = current_scope->resolve_symbol(x_m_name); + st = ASR::down_cast(sym); + is_genr_body = true; + current_scope = st->m_symtab; + } else{ + current_scope = al.make_new(parent_scope); + } + Vec member_names; + Vec member_fn_names; + Vec member_init; + member_names.reserve(al, 1); + member_fn_names.reserve(al, 1); + member_init.reserve(al, 1);//we do not know the size of the members and member functions + SetChar struct_dependencies; + struct_dependencies.reserve(al, 1); + ASR::abiType class_abi = ASR::abiType::Source; + if( is_bindc_class(x.m_decorator_list, x.n_decorator_list) ) { + class_abi = ASR::abiType::BindC; + throw SemanticError("Bindc in classes is not supported,instead use the dataclass decorator ", + x.base.base.loc); + } + visit_ClassMembers(x, member_names, member_fn_names, struct_dependencies, member_init, false, class_abi, is_genr_body,true); + LCOMPILERS_ASSERT(member_init.size() == member_names.size()); + ASR::symbol_t* class_type = ASR::down_cast(ASR::make_Struct_t(al, + x.base.base.loc, current_scope, x.m_name, + struct_dependencies.p, struct_dependencies.size(), + member_names.p, member_names.size(), + member_fn_names.p, member_fn_names.size(), + class_abi, ASR::accessType::Public, + is_packed, false, member_init.p, member_init.size(), aligned_expr, + nullptr)); + current_scope = parent_scope; + if ( is_genr_body ) { + continue; + } else { + current_scope->add_symbol(x_m_name, class_type); + st->m_initializers = member_init.p; + st->n_initializers = member_init.size(); + } } } diff --git a/tests/reference/asr-intent_01-66824bc.json b/tests/reference/asr-intent_01-66824bc.json index af6613fc4f..3942c5b46c 100644 --- a/tests/reference/asr-intent_01-66824bc.json +++ b/tests/reference/asr-intent_01-66824bc.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-intent_01-66824bc.stdout", - "stdout_hash": "96424532864b51ff2a8d92da1fb40a8498342dcea99b54660a4c83c5", + "stdout_hash": "12394e08fadf84d503f288f7a93436c33128f480b266825a9469c279", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-intent_01-66824bc.stdout b/tests/reference/asr-intent_01-66824bc.stdout index f918d2d8d7..baf2dd79aa 100644 --- a/tests/reference/asr-intent_01-66824bc.stdout +++ b/tests/reference/asr-intent_01-66824bc.stdout @@ -32,6 +32,7 @@ Foo [] [p] + [] Source Public .false. diff --git a/tests/reference/asr-structs_01-66dc2c9.json b/tests/reference/asr-structs_01-66dc2c9.json index 0036b2bb93..fe9478ad22 100644 --- a/tests/reference/asr-structs_01-66dc2c9.json +++ b/tests/reference/asr-structs_01-66dc2c9.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-structs_01-66dc2c9.stdout", - "stdout_hash": "153f705e29f2c88ec969ce035e2c91aca1caa2bdd3571966dd5c4f87", + "stdout_hash": "4563ec59631929caa75b3fa47a4dba53cc7a0728df84c9e3c10d2ba8", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-structs_01-66dc2c9.stdout b/tests/reference/asr-structs_01-66dc2c9.stdout index 97b901c18a..76dcabe701 100644 --- a/tests/reference/asr-structs_01-66dc2c9.stdout +++ b/tests/reference/asr-structs_01-66dc2c9.stdout @@ -49,6 +49,7 @@ [] [x y] + [] Source Public .false. diff --git a/tests/reference/asr-structs_01-be14d49.json b/tests/reference/asr-structs_01-be14d49.json index 0c2f355882..6024c1a2bd 100644 --- a/tests/reference/asr-structs_01-be14d49.json +++ b/tests/reference/asr-structs_01-be14d49.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-structs_01-be14d49.stdout", - "stdout_hash": "d70bd606bcda91e16034b677f6b03ae998de9012002a4c6a7c6a1bd2", + "stdout_hash": "21e2ee8fce90f2107dd5139b94d72a45f593beb4f362ba675b7d8899", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-structs_01-be14d49.stdout b/tests/reference/asr-structs_01-be14d49.stdout index c3fd7f2c91..6db6895dc4 100644 --- a/tests/reference/asr-structs_01-be14d49.stdout +++ b/tests/reference/asr-structs_01-be14d49.stdout @@ -49,6 +49,7 @@ [] [y x] + [] Source Public .false. diff --git a/tests/reference/asr-structs_02-2ab459a.json b/tests/reference/asr-structs_02-2ab459a.json index a7cdf7fe0a..7f9ffb2cfc 100644 --- a/tests/reference/asr-structs_02-2ab459a.json +++ b/tests/reference/asr-structs_02-2ab459a.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-structs_02-2ab459a.stdout", - "stdout_hash": "579bf1e4f7b37ce8e0483caa4a8d82bfb99cc5d30698ca3fd976a058", + "stdout_hash": "b40584460088bb971a11bed14949fe141475cc3321d61c79f08726a9", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-structs_02-2ab459a.stdout b/tests/reference/asr-structs_02-2ab459a.stdout index 28b5500a56..339ab0ffe7 100644 --- a/tests/reference/asr-structs_02-2ab459a.stdout +++ b/tests/reference/asr-structs_02-2ab459a.stdout @@ -49,6 +49,7 @@ [] [x y] + [] Source Public .false. diff --git a/tests/reference/asr-structs_03-0cef911.json b/tests/reference/asr-structs_03-0cef911.json index 2e58761fee..e139681b12 100644 --- a/tests/reference/asr-structs_03-0cef911.json +++ b/tests/reference/asr-structs_03-0cef911.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-structs_03-0cef911.stdout", - "stdout_hash": "861480a7b8a448fb0d9e773baf8e0ef2242c7fd5ea683e4e95fde396", + "stdout_hash": "a769decc0762ba0ed0996a04db1137b238ca295a979e0e9b002bb702", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-structs_03-0cef911.stdout b/tests/reference/asr-structs_03-0cef911.stdout index 331f14ed1d..cdfeffbace 100644 --- a/tests/reference/asr-structs_03-0cef911.stdout +++ b/tests/reference/asr-structs_03-0cef911.stdout @@ -49,6 +49,7 @@ [] [x y] + [] Source Public .false. diff --git a/tests/reference/asr-structs_04-387747b.json b/tests/reference/asr-structs_04-387747b.json index 87a0559771..0f247ffc92 100644 --- a/tests/reference/asr-structs_04-387747b.json +++ b/tests/reference/asr-structs_04-387747b.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-structs_04-387747b.stdout", - "stdout_hash": "56f0b2b928e0341162acaf38cbf035abf58005563f71011f588597db", + "stdout_hash": "9a036fc0d926bde642e0108df6772c65c66e2e73cffdb571e07ced1b", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-structs_04-387747b.stdout b/tests/reference/asr-structs_04-387747b.stdout index fd9d5f8de9..2232114f9a 100644 --- a/tests/reference/asr-structs_04-387747b.stdout +++ b/tests/reference/asr-structs_04-387747b.stdout @@ -49,6 +49,7 @@ [] [y x] + [] Source Public .false. @@ -106,6 +107,7 @@ [A] [z a] + [] Source Public .false. diff --git a/tests/reference/asr-structs_05-fa98307.json b/tests/reference/asr-structs_05-fa98307.json index dcdf412398..5a33c8bbad 100644 --- a/tests/reference/asr-structs_05-fa98307.json +++ b/tests/reference/asr-structs_05-fa98307.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-structs_05-fa98307.stdout", - "stdout_hash": "94cc7a800d3a6722461f1b7da81cf7cf74d432c0ddf918dcbeec0981", + "stdout_hash": "51664111cbba842e52f3e2dcd01ccc7b4a43ac308991d04835995b47", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-structs_05-fa98307.stdout b/tests/reference/asr-structs_05-fa98307.stdout index 11f0f329e4..d4e8ce4abd 100644 --- a/tests/reference/asr-structs_05-fa98307.stdout +++ b/tests/reference/asr-structs_05-fa98307.stdout @@ -134,6 +134,7 @@ b c d] + [] Source Public .false. diff --git a/tests/reference/asr-structs_16-44de89a.json b/tests/reference/asr-structs_16-44de89a.json index 5a28565876..42040af0f7 100644 --- a/tests/reference/asr-structs_16-44de89a.json +++ b/tests/reference/asr-structs_16-44de89a.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "asr-structs_16-44de89a.stdout", - "stdout_hash": "56e72c6d35e8827acf67645e7e998e962ff4e6939ec6e54c91cd0774", + "stdout_hash": "24bbd100d135eea623b79878e65615f9a9f470be0d4a6152ae639c42", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/asr-structs_16-44de89a.stdout b/tests/reference/asr-structs_16-44de89a.stdout index af43192b11..ba102c3ec4 100644 --- a/tests/reference/asr-structs_16-44de89a.stdout +++ b/tests/reference/asr-structs_16-44de89a.stdout @@ -99,6 +99,7 @@ [] [b c] + [] Source Public .false. diff --git a/tests/reference/pass_class_constructor-structs_16-5e3508f.json b/tests/reference/pass_class_constructor-structs_16-5e3508f.json index efa0a357c3..c8ed39fc84 100644 --- a/tests/reference/pass_class_constructor-structs_16-5e3508f.json +++ b/tests/reference/pass_class_constructor-structs_16-5e3508f.json @@ -6,7 +6,7 @@ "outfile": null, "outfile_hash": null, "stdout": "pass_class_constructor-structs_16-5e3508f.stdout", - "stdout_hash": "6b3bd1934a2cd04b82f44484a9307b3d9b1619f469a364678b53d839", + "stdout_hash": "8a6c529f9775e12f88fef55e4535b808cba1f67c5d1fd91bf28a6648", "stderr": null, "stderr_hash": null, "returncode": 0 diff --git a/tests/reference/pass_class_constructor-structs_16-5e3508f.stdout b/tests/reference/pass_class_constructor-structs_16-5e3508f.stdout index 1200961b84..fdab23e983 100644 --- a/tests/reference/pass_class_constructor-structs_16-5e3508f.stdout +++ b/tests/reference/pass_class_constructor-structs_16-5e3508f.stdout @@ -99,6 +99,7 @@ [] [b c] + [] Source Public .false. From 8e895bfbe40b3d5641554dd6f4243de46c2e5c1a Mon Sep 17 00:00:00 2001 From: Tanay Manerikar Date: Mon, 24 Jun 2024 20:47:40 +0530 Subject: [PATCH 2/9] typo fixed --- src/lpython/semantics/python_ast_to_asr.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 4c6e041656..bbb33c589b 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -3256,7 +3256,6 @@ class CommonVisitor : public AST::BaseVisitor { nullptr)); current_scope = parent_scope; if ( is_genr_body ) { - continue; } else { current_scope->add_symbol(x_m_name, class_type); st->m_initializers = member_init.p; From 159074ce9da0bf0b3ba2891cd72b2f95029c2524 Mon Sep 17 00:00:00 2001 From: Tanay Manerikar Date: Tue, 25 Jun 2024 14:22:02 +0530 Subject: [PATCH 3/9] msg --- src/lpython/semantics/python_ast_to_asr.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index bbb33c589b..a5d65d3578 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -3224,7 +3224,9 @@ class CommonVisitor : public AST::BaseVisitor { SymbolTable *parent_scope = current_scope; if( current_scope->resolve_symbol(x_m_name) ){ sym = current_scope->resolve_symbol(x_m_name); - st = ASR::down_cast(sym); + if (ASR::is_a(sym) ){ + st = ASR::down_cast(sym); + } is_genr_body = true; current_scope = st->m_symtab; } else{ From cff4dd5d1c6924aa41be8965cc47b33e2256fac6 Mon Sep 17 00:00:00 2001 From: Tanay Manerikar Date: Wed, 26 Jun 2024 20:19:55 +0530 Subject: [PATCH 4/9] basic init --- src/libasr/asr_verify.cpp | 3 +- src/lpython/semantics/python_ast_to_asr.cpp | 157 ++++++++++++-------- 2 files changed, 101 insertions(+), 59 deletions(-) diff --git a/src/libasr/asr_verify.cpp b/src/libasr/asr_verify.cpp index 37248c3883..4ebfe83aa2 100644 --- a/src/libasr/asr_verify.cpp +++ b/src/libasr/asr_verify.cpp @@ -529,7 +529,8 @@ class VerifyVisitor : public BaseWalkVisitor ASR::is_a(*a.second) || ASR::is_a(*a.second) || ASR::is_a(*a.second) || - ASR::is_a(*a.second) ) { + ASR::is_a(*a.second) || + ASR::is_a(*a.second)) { continue ; } // TODO: Uncomment the following line diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index a5d65d3578..2ec274bd3b 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -1166,7 +1166,7 @@ class CommonVisitor : public AST::BaseVisitor { ASR::call_arg_t call_arg; call_arg.m_value = var->m_symbolic_value; call_arg.loc = (var->m_symbolic_value->base).loc; - args.push_back(al,call_arg); + args.push_back(al,call_arg); } } if(missed_args_count > 0){ @@ -1752,7 +1752,7 @@ class CommonVisitor : public AST::BaseVisitor { diag.add(diag::Diagnostic( "Unhashable type: '" + ASRUtils::type_to_str(type) + "'", diag::Level::Error, diag::Stage::Semantic, { - diag::Label("Mutable type '" + ASRUtils::type_to_str(type) + diag::Label("Mutable type '" + ASRUtils::type_to_str(type) + "' cannot be stored in a set.", {s->m_slice->base.loc}) }) @@ -1798,7 +1798,7 @@ class CommonVisitor : public AST::BaseVisitor { diag.add(diag::Diagnostic( "Unhashable type: '" + ASRUtils::type_to_str(key_type) + "'", diag::Level::Error, diag::Stage::Semantic, { - diag::Label("Mutable type '" + ASRUtils::type_to_str(key_type) + diag::Label("Mutable type '" + ASRUtils::type_to_str(key_type) + "' cannot become a key in dict. Hint: Use an immutable type for key.", {t->m_elts[0]->base.loc}) }) @@ -2539,7 +2539,7 @@ class CommonVisitor : public AST::BaseVisitor { if( AST::is_a(*decorators[i]) ) { AST::Name_t* dc_name = AST::down_cast(decorators[i]); is_dataclass_ = std::string(dc_name->m_id) == "dataclass"; - } + } } return is_dataclass_; } @@ -2578,7 +2578,7 @@ class CommonVisitor : public AST::BaseVisitor { std::string var_name = v_variable->m_name; ASR::ttype_t* type = v_variable->m_type; if (!init_expr && ASR::is_a(*type)) { - init_expr = ASRUtils::EXPR(ASR::make_DictConstant_t(al, loc, + init_expr = ASRUtils::EXPR(ASR::make_DictConstant_t(al, loc, nullptr, 0, nullptr, 0, type)); } @@ -2932,11 +2932,49 @@ class CommonVisitor : public AST::BaseVisitor { assign_asr_target = assign_asr_target_copy; } + void visit_Constructor(const AST::FunctionDef_t &x){ + if(x.n_decorator_list>0){ + throw SemanticError("Decorators for __init__ not implemented" , x.base.base.loc); + } + // if( !x.m_returns ){ + // throw SemanticError("__init__ should return None " , x.base.base.loc); + // } + if( x.m_args.n_args > 1 ){ + throw SemanticError("Only default constructors implemented " , x.base.base.loc); + } + std::string self_name = x.m_args.m_args[0].m_arg; + for(size_t i = 0; i < x.n_body; i++){ + std::string var_name; + if (! AST::is_a(*x.m_body[i]) ){ + throw SemanticError("Only AnnAssign implemented in __init__ " , x.m_body[i]->base.loc); + } + AST::AnnAssign_t* ann_assign = AST::down_cast(x.m_body[i]); + if (!AST::is_a(*ann_assign->m_target)) { + if(AST::is_a(*ann_assign->m_target)){ + AST::Attribute_t* a = AST::down_cast(ann_assign->m_target); + var_name = a->m_attr; + }else{ + throw SemanticError("Only Name supported as target in AnnAssign inside struct", x.m_body[i]->base.loc); + } + } + + ASR::expr_t* init_expr = nullptr; + ASR::abiType abi=ASR::abiType::Source; + visit_AnnAssignUtil(*ann_assign, var_name, init_expr, false, abi, true); + ASR::symbol_t* var_sym = current_scope->resolve_symbol(var_name); + ASR::call_arg_t c_arg; + c_arg.loc = var_sym->base.loc; + c_arg.m_value = init_expr; + init_expr = nullptr; + } + + } + void visit_ClassMembers(const AST::ClassDef_t& x, Vec& member_names, Vec& member_fn_names, SetChar& struct_dependencies, Vec &member_init, bool is_enum_scope=false, ASR::abiType abi=ASR::abiType::Source, - bool is_genr_body=false, bool is_class_scope = false) { + bool is_class_scope = false) { int64_t prev_value = 1; for( size_t i = 0; i < x.n_body; i++ ) { if (AST::is_a(*x.m_body[i])) { @@ -2955,10 +2993,15 @@ class CommonVisitor : public AST::BaseVisitor { if ( !is_class_scope ) { throw SemanticError("Struct member functions are not supported", x.m_body[i]->base.loc); } - else { - this->visit_stmt(*x.m_body[i]); + else { AST::FunctionDef_t *f = AST::down_cast(x.m_body[i]); member_fn_names.push_back(al, f->m_name); + std::string f_name = f->m_name; + if (f_name == "__init__"){ + this->visit_Constructor(*f); + }else{ + this->visit_stmt(*x.m_body[i]); + } continue; } } else if (AST::is_a(*x.m_body[i])) { @@ -3218,51 +3261,47 @@ class CommonVisitor : public AST::BaseVisitor { throw SemanticError("Inheritance in classes isn't supported yet.", x.base.base.loc); } - bool is_genr_body = false; - ASR::symbol_t* sym = nullptr; - ASR::Struct_t *st = nullptr; SymbolTable *parent_scope = current_scope; - if( current_scope->resolve_symbol(x_m_name) ){ - sym = current_scope->resolve_symbol(x_m_name); - if (ASR::is_a(sym) ){ - st = ASR::down_cast(sym); - } - is_genr_body = true; + ASR::symbol_t* sym = current_scope->resolve_symbol(x_m_name); + if( sym && !(ASR::is_a(*sym) && + ASR::is_a(*ASR::down_cast(sym)->m_type))) { + LCOMPILERS_ASSERT(ASR::is_a(*sym)); + ASR::Struct_t *st = ASR::down_cast(sym); current_scope = st->m_symtab; - } else{ + for( size_t i = 0; i < x.n_body; i++ ) { + if ( AST::is_a(*x.m_body[i]) ) { + this->visit_stmt(*x.m_body[i]); + } + } + } else { current_scope = al.make_new(parent_scope); + Vec member_names; + Vec member_fn_names; + Vec member_init; + member_names.reserve(al, 1); + member_fn_names.reserve(al, 1); + member_init.reserve(al, 1);//we do not know the size of the members and member functions + SetChar struct_dependencies; + struct_dependencies.reserve(al, 1); + ASR::abiType class_abi = ASR::abiType::Source; + if( is_bindc_class(x.m_decorator_list, x.n_decorator_list) ) { + class_abi = ASR::abiType::BindC; + throw SemanticError("Bindc in classes is not supported,instead use the dataclass decorator ", + x.base.base.loc); + } + visit_ClassMembers(x, member_names, member_fn_names, struct_dependencies, member_init, false, class_abi, true); + LCOMPILERS_ASSERT(member_init.size() == member_names.size()); + ASR::symbol_t* class_type = ASR::down_cast(ASR::make_Struct_t(al, + x.base.base.loc, current_scope, x.m_name, + struct_dependencies.p, struct_dependencies.size(), + member_names.p, member_names.size(), + member_fn_names.p, member_fn_names.size(), + class_abi, ASR::accessType::Public, + is_packed, false, member_init.p, member_init.size(), aligned_expr, + nullptr)); + parent_scope->add_or_overwrite_symbol(x.m_name, class_type); } - Vec member_names; - Vec member_fn_names; - Vec member_init; - member_names.reserve(al, 1); - member_fn_names.reserve(al, 1); - member_init.reserve(al, 1);//we do not know the size of the members and member functions - SetChar struct_dependencies; - struct_dependencies.reserve(al, 1); - ASR::abiType class_abi = ASR::abiType::Source; - if( is_bindc_class(x.m_decorator_list, x.n_decorator_list) ) { - class_abi = ASR::abiType::BindC; - throw SemanticError("Bindc in classes is not supported,instead use the dataclass decorator ", - x.base.base.loc); - } - visit_ClassMembers(x, member_names, member_fn_names, struct_dependencies, member_init, false, class_abi, is_genr_body,true); - LCOMPILERS_ASSERT(member_init.size() == member_names.size()); - ASR::symbol_t* class_type = ASR::down_cast(ASR::make_Struct_t(al, - x.base.base.loc, current_scope, x.m_name, - struct_dependencies.p, struct_dependencies.size(), - member_names.p, member_names.size(), - member_fn_names.p, member_fn_names.size(), - class_abi, ASR::accessType::Public, - is_packed, false, member_init.p, member_init.size(), aligned_expr, - nullptr)); current_scope = parent_scope; - if ( is_genr_body ) { - } else { - current_scope->add_symbol(x_m_name, class_type); - st->m_initializers = member_init.p; - st->n_initializers = member_init.size(); - } } } @@ -4189,7 +4228,7 @@ class SymbolTableVisitor : public CommonVisitor { create_GenericProcedure(x.base.base.loc); } } else { - ASR::Module_t* module_sym = + ASR::Module_t* module_sym = ASR::down_cast(parent_scope->resolve_symbol(module_name)); LCOMPILERS_ASSERT(module_sym != nullptr); current_scope = module_sym->m_symtab; @@ -4436,7 +4475,7 @@ class SymbolTableVisitor : public CommonVisitor { } ASR::accessType s_access = ASR::accessType::Public; ASR::presenceType s_presence = ASR::presenceType::Required; - if (i >= default_arg_index_start){ + if (i >= default_arg_index_start){ s_presence = ASR::presenceType::Optional; } bool value_attr = false; @@ -5035,6 +5074,8 @@ class BodyVisitor : public CommonVisitor { rt_vec.clear(); } + void visit_Constructor(const AST::FunctionDef_t & /*x*/){} + void visit_FunctionDef(const AST::FunctionDef_t &x) { SymbolTable *old_scope = current_scope; ASR::symbol_t *t = current_scope->get_symbol(x.m_name); @@ -6259,7 +6300,7 @@ class BodyVisitor : public CommonVisitor { diag.add(diag::Diagnostic( "Unhashable type: '" + ASRUtils::type_to_str(key_type) + "'", diag::Level::Error, diag::Stage::Semantic, { - diag::Label("Mutable type '" + ASRUtils::type_to_str(key_type) + diag::Label("Mutable type '" + ASRUtils::type_to_str(key_type) + "' cannot become a key in dict. Hint: Use an immutable type for key.", {key->base.loc}) }) @@ -6659,9 +6700,9 @@ class BodyVisitor : public CommonVisitor { ASR::expr_t *value = nullptr; ASR::ttype_t *type = ASRUtils::TYPE(ASR::make_Logical_t( - al, x.base.base.loc, 4)); + al, x.base.base.loc, 4)); if (ASR::is_a(*right_type)) { - ASR::ttype_t *contained_type = ASRUtils::get_contained_type(right_type); + ASR::ttype_t *contained_type = ASRUtils::get_contained_type(right_type); if (!ASRUtils::check_equal_type(left_type, contained_type)) { std::string ltype = ASRUtils::type_to_str_python(ASRUtils::expr_type(left)); std::string rtype = ASRUtils::type_to_str_python(ASRUtils::expr_type(right)); @@ -6701,10 +6742,10 @@ class BodyVisitor : public CommonVisitor { value = ASR::down_cast(ASR::make_LogicalConstant_t( al, x.base.base.loc, result, type)); - } + } tmp = make_StringContains_t(al, x.base.base.loc, left, right, type, value); } else if (ASR::is_a(*right_type)) { - ASR::ttype_t *contained_type = ASRUtils::get_contained_type(right_type); + ASR::ttype_t *contained_type = ASRUtils::get_contained_type(right_type); if (!ASRUtils::check_equal_type(left_type, contained_type)) { std::string ltype = ASRUtils::type_to_str_python(ASRUtils::expr_type(left)); std::string rtype = ASRUtils::type_to_str_python(ASRUtils::expr_type(right)); @@ -6720,7 +6761,7 @@ class BodyVisitor : public CommonVisitor { tmp = ASR::make_TupleContains_t(al, x.base.base.loc, left, right, type, value); } else if (ASR::is_a(*right_type)) { - ASR::ttype_t *contained_type = ASRUtils::get_contained_type(right_type); + ASR::ttype_t *contained_type = ASRUtils::get_contained_type(right_type); if (!ASRUtils::check_equal_type(left_type, contained_type)) { std::string ltype = ASRUtils::type_to_str_python(ASRUtils::expr_type(left)); std::string rtype = ASRUtils::type_to_str_python(ASRUtils::expr_type(right)); @@ -6736,7 +6777,7 @@ class BodyVisitor : public CommonVisitor { tmp = ASR::make_SetContains_t(al, x.base.base.loc, left, right, type, value); } else if (ASR::is_a(*right_type)) { - ASR::ttype_t *contained_type = ASRUtils::get_contained_type(right_type); + ASR::ttype_t *contained_type = ASRUtils::get_contained_type(right_type); if (!ASRUtils::check_equal_type(left_type, contained_type)) { std::string ltype = ASRUtils::type_to_str_python(ASRUtils::expr_type(left)); std::string rtype = ASRUtils::type_to_str_python(ASRUtils::expr_type(right)); @@ -6851,7 +6892,7 @@ class BodyVisitor : public CommonVisitor { diag.add(diag::Diagnostic( "Unhashable type: '" + ASRUtils::type_to_str(type) + "'", diag::Level::Error, diag::Stage::Semantic, { - diag::Label("Mutable type '" + ASRUtils::type_to_str(type) + diag::Label("Mutable type '" + ASRUtils::type_to_str(type) + "' cannot be stored in a set.", {value->base.loc}) }) From 4d813ea088bd882bcebfd3ffcb8d035937ee9163 Mon Sep 17 00:00:00 2001 From: Tanay Manerikar Date: Thu, 27 Jun 2024 17:42:43 +0530 Subject: [PATCH 5/9] Default constructors --- integration_tests/CMakeLists.txt | 1 + integration_tests/class_01.py | 27 ++++++ src/lpython/semantics/python_ast_to_asr.cpp | 101 ++++++++++++++++---- 3 files changed, 111 insertions(+), 18 deletions(-) create mode 100644 integration_tests/class_01.py diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index ea416e764b..f10bb882fb 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -828,6 +828,7 @@ RUN(NAME callback_03 LABELS cpython llvm llvm_jit c) RUN(NAME lambda_01 LABELS cpython llvm llvm_jit) RUN(NAME c_mangling LABELS cpython llvm llvm_jit c) +RUN(NAME class_01 LABELS cpython llvm llvm_jit c) # callback_04 is to test emulation. So just run with cpython RUN(NAME callback_04 IMPORT_PATH .. LABELS cpython) diff --git a/integration_tests/class_01.py b/integration_tests/class_01.py new file mode 100644 index 0000000000..b1e1e909c4 --- /dev/null +++ b/integration_tests/class_01.py @@ -0,0 +1,27 @@ +from lpython import i32,f64 +from math import sqrt + +class coord: + def __init__(self:"coord"): + self.x: i32 = 3 + self.y: i32 = 4 + +def main(): + p1: coord = coord() + sq_dist : i32 = p1.x*p1.x + p1.y*p1.y + dist : f64 = sqrt(f64(sq_dist)) + print("Squared Distance from origin = ",sq_dist) + assert sq_dist == 25 + print("Distance from origin = ",dist) + assert dist == f64(5) + print("p1.x = 6") + print("p1.y = 8") + p1.x = i32(6) + p1.y = 8 + sq_dist = p1.x*p1.x + p1.y*p1.y + dist = sqrt(f64(sq_dist)) + print("Squared Distance from origin = ",sq_dist) + assert sq_dist == 100 + print("Distance from origin = ",dist) + assert dist == f64(10) +main() \ No newline at end of file diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 2ec274bd3b..b5ff11ba6f 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -2932,13 +2932,11 @@ class CommonVisitor : public AST::BaseVisitor { assign_asr_target = assign_asr_target_copy; } - void visit_Constructor(const AST::FunctionDef_t &x){ + void visit_Constructor(const AST::FunctionDef_t &x, + Vec& member_names, Vec &member_init){ if(x.n_decorator_list>0){ throw SemanticError("Decorators for __init__ not implemented" , x.base.base.loc); } - // if( !x.m_returns ){ - // throw SemanticError("__init__ should return None " , x.base.base.loc); - // } if( x.m_args.n_args > 1 ){ throw SemanticError("Only default constructors implemented " , x.base.base.loc); } @@ -2948,23 +2946,85 @@ class CommonVisitor : public AST::BaseVisitor { if (! AST::is_a(*x.m_body[i]) ){ throw SemanticError("Only AnnAssign implemented in __init__ " , x.m_body[i]->base.loc); } - AST::AnnAssign_t* ann_assign = AST::down_cast(x.m_body[i]); - if (!AST::is_a(*ann_assign->m_target)) { - if(AST::is_a(*ann_assign->m_target)){ - AST::Attribute_t* a = AST::down_cast(ann_assign->m_target); - var_name = a->m_attr; - }else{ - throw SemanticError("Only Name supported as target in AnnAssign inside struct", x.m_body[i]->base.loc); + AST::AnnAssign_t ann_assign = *AST::down_cast(x.m_body[i]); + if(AST::is_a(*ann_assign.m_target)){ + AST::Attribute_t* a = AST::down_cast(ann_assign.m_target); + if(AST::is_a(*a->m_value)){ + AST::Name_t* n = AST::down_cast(a->m_value); + if(std::string(n->m_id)!=self_name && current_scope->resolve_symbol(std::string(n->m_id))){ + throw SemanticError("Symbol not declared" , x.m_body[i]->base.loc); + } } + var_name = a->m_attr; + member_names.push_back(al,s2c(al,var_name)); + }else{ + throw SemanticError("Only Name supported as target in AnnAssign inside struct", x.m_body[i]->base.loc); } - ASR::expr_t* init_expr = nullptr; ASR::abiType abi=ASR::abiType::Source; - visit_AnnAssignUtil(*ann_assign, var_name, init_expr, false, abi, true); + bool is_allocatable = false, is_const = false; + ASR::ttype_t *type = nullptr; + type = ast_expr_to_asr_type(ann_assign.m_annotation->base.loc, *ann_assign.m_annotation, is_allocatable, is_const, true); + if (ASR::is_a(*type)) { + ASR::FunctionType_t* fn_type = ASR::down_cast(type); + handle_lambda_function_declaration(var_name, fn_type, ann_assign.m_value, ann_assign.base.base.loc); + return; + } + ASR::storage_typeType storage_type = ASR::storage_typeType::Default; + if (is_allocatable) { + type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, type->base.loc, + ASRUtils::type_get_past_pointer(type))); + } + if (is_const) { + storage_type = ASR::storage_typeType::Parameter; + } + + create_add_variable_to_scope(var_name, type, + ann_assign.base.base.loc, abi, storage_type); + + tmp = nullptr; + if (ann_assign.m_value) { + this->visit_expr(*ann_assign.m_value); + } else { + if (ASR::is_a(*type)) { + //`s` must be initialized with an instance of S + throw SemanticError("`" + var_name + "` must be initialized with an instance of " + + ASRUtils::type_to_str_python(type), ann_assign.base.base.loc); + } + } + if (tmp && ASR::is_a(*tmp)) { + ASR::expr_t* value = ASRUtils::EXPR(tmp); + ASR::ttype_t* underlying_type = type; + cast_helper(underlying_type, value, value->base.loc); + if (!ASRUtils::check_equal_type(underlying_type, ASRUtils::expr_type(value), true)) { + std::string ltype = ASRUtils::type_to_str_python(underlying_type); + std::string rtype = ASRUtils::type_to_str_python(ASRUtils::expr_type(value)); + diag.add(diag::Diagnostic( + "Type mismatch in annotation-assignment, the types must be compatible", + diag::Level::Error, diag::Stage::Semantic, { + diag::Label("type mismatch ('" + ltype + "' and '" + rtype + "')", + {ann_assign.m_target->base.loc, value->base.loc}) + }) + ); + throw SemanticAbort(); + } + init_expr = value; + } + + if ( is_const ) { + process_variable_init_val(current_scope->get_symbol(var_name), ann_assign.base.base.loc, init_expr); + } + + if ( !(tmp && ASR::is_a(*tmp) && + (ASR::is_a(*ASR::down_cast(tmp)) || + ASR::is_a(*ASR::down_cast(tmp)))) ) { + tmp = nullptr; + } ASR::symbol_t* var_sym = current_scope->resolve_symbol(var_name); ASR::call_arg_t c_arg; c_arg.loc = var_sym->base.loc; c_arg.m_value = init_expr; + member_init.push_back(al, c_arg); init_expr = nullptr; } @@ -2998,7 +3058,7 @@ class CommonVisitor : public AST::BaseVisitor { member_fn_names.push_back(al, f->m_name); std::string f_name = f->m_name; if (f_name == "__init__"){ - this->visit_Constructor(*f); + this->visit_Constructor(*f,member_names,member_init); }else{ this->visit_stmt(*x.m_body[i]); } @@ -3255,8 +3315,6 @@ class CommonVisitor : public AST::BaseVisitor { current_scope->add_symbol(x_m_name, class_type); } } else { - get_alignment(x.m_decorator_list, x.n_decorator_list, - aligned_expr, is_packed); if( x.n_bases > 0 ) { throw SemanticError("Inheritance in classes isn't supported yet.", x.base.base.loc); @@ -3270,7 +3328,10 @@ class CommonVisitor : public AST::BaseVisitor { current_scope = st->m_symtab; for( size_t i = 0; i < x.n_body; i++ ) { if ( AST::is_a(*x.m_body[i]) ) { - this->visit_stmt(*x.m_body[i]); + AST::FunctionDef_t* f = AST::down_cast(x.m_body[i]); + if ( std::string(f->m_name) != std::string("__init__") ){ + this->visit_stmt(*x.m_body[i]); + } } } } else { @@ -3299,7 +3360,11 @@ class CommonVisitor : public AST::BaseVisitor { class_abi, ASR::accessType::Public, is_packed, false, member_init.p, member_init.size(), aligned_expr, nullptr)); - parent_scope->add_or_overwrite_symbol(x.m_name, class_type); + parent_scope->add_symbol(x.m_name, class_type); + ASR::symbol_t* sym = current_scope->resolve_symbol(x_m_name); + ASR::Struct_t *st = ASR::down_cast(sym); + st->m_initializers = member_init.p; + st->n_initializers = member_init.size(); } current_scope = parent_scope; } From 74927cfcd157feb04a0aa62e22c18d0ced141ca0 Mon Sep 17 00:00:00 2001 From: Tanay Manerikar Date: Fri, 28 Jun 2024 19:52:56 +0530 Subject: [PATCH 6/9] Cleanup --- src/lpython/semantics/python_ast_to_asr.cpp | 50 +++------------------ 1 file changed, 5 insertions(+), 45 deletions(-) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index b3056a5e00..826daff4b0 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -2530,7 +2530,6 @@ class CommonVisitor : public AST::BaseVisitor { } } } - return; } bool is_dataclass(AST::expr_t** decorators, size_t n) { @@ -2932,7 +2931,7 @@ class CommonVisitor : public AST::BaseVisitor { assign_asr_target = assign_asr_target_copy; } - void visit_Constructor(const AST::FunctionDef_t &x, + void handle_init_method(const AST::FunctionDef_t &x, Vec& member_names, Vec &member_init){ if(x.n_decorator_list>0){ throw SemanticError("Decorators for __init__ not implemented" , x.base.base.loc); @@ -2965,32 +2964,12 @@ class CommonVisitor : public AST::BaseVisitor { bool is_allocatable = false, is_const = false; ASR::ttype_t *type = nullptr; type = ast_expr_to_asr_type(ann_assign.m_annotation->base.loc, *ann_assign.m_annotation, is_allocatable, is_const, true); - if (ASR::is_a(*type)) { - ASR::FunctionType_t* fn_type = ASR::down_cast(type); - handle_lambda_function_declaration(var_name, fn_type, ann_assign.m_value, ann_assign.base.base.loc); - return; - } ASR::storage_typeType storage_type = ASR::storage_typeType::Default; - if (is_allocatable) { - type = ASRUtils::TYPE(ASR::make_Allocatable_t(al, type->base.loc, - ASRUtils::type_get_past_pointer(type))); - } - if (is_const) { - storage_type = ASR::storage_typeType::Parameter; - } - create_add_variable_to_scope(var_name, type, ann_assign.base.base.loc, abi, storage_type); - tmp = nullptr; if (ann_assign.m_value) { this->visit_expr(*ann_assign.m_value); - } else { - if (ASR::is_a(*type)) { - //`s` must be initialized with an instance of S - throw SemanticError("`" + var_name + "` must be initialized with an instance of " + - ASRUtils::type_to_str_python(type), ann_assign.base.base.loc); - } } if (tmp && ASR::is_a(*tmp)) { ASR::expr_t* value = ASRUtils::EXPR(tmp); @@ -3010,16 +2989,6 @@ class CommonVisitor : public AST::BaseVisitor { } init_expr = value; } - - if ( is_const ) { - process_variable_init_val(current_scope->get_symbol(var_name), ann_assign.base.base.loc, init_expr); - } - - if ( !(tmp && ASR::is_a(*tmp) && - (ASR::is_a(*ASR::down_cast(tmp)) || - ASR::is_a(*ASR::down_cast(tmp)))) ) { - tmp = nullptr; - } ASR::symbol_t* var_sym = current_scope->resolve_symbol(var_name); ASR::call_arg_t c_arg; c_arg.loc = var_sym->base.loc; @@ -3058,7 +3027,7 @@ class CommonVisitor : public AST::BaseVisitor { member_fn_names.push_back(al, f->m_name); std::string f_name = f->m_name; if (f_name == "__init__"){ - this->visit_Constructor(*f,member_names,member_init); + this->handle_init_method(*f,member_names,member_init); }else{ this->visit_stmt(*x.m_body[i]); } @@ -3295,7 +3264,7 @@ class CommonVisitor : public AST::BaseVisitor { if( is_bindc_class(x.m_decorator_list, x.n_decorator_list) ) { class_abi = ASR::abiType::BindC; } - visit_ClassMembers(x, member_names, member_fn_names, struct_dependencies, member_init, false, class_abi);//TODO add member functions to the list + visit_ClassMembers(x, member_names, member_fn_names, struct_dependencies, member_init, false, class_abi); LCOMPILERS_ASSERT(member_init.size() == member_names.size()); ASR::symbol_t* class_type = ASR::down_cast(ASR::make_Struct_t(al, x.base.base.loc, current_scope, x.m_name, @@ -3320,16 +3289,14 @@ class CommonVisitor : public AST::BaseVisitor { x.base.base.loc); } SymbolTable *parent_scope = current_scope; - ASR::symbol_t* sym = current_scope->resolve_symbol(x_m_name); - if( sym && !(ASR::is_a(*sym) && - ASR::is_a(*ASR::down_cast(sym)->m_type))) { + if( ASR::symbol_t* sym = current_scope->resolve_symbol(x_m_name) ) { LCOMPILERS_ASSERT(ASR::is_a(*sym)); ASR::Struct_t *st = ASR::down_cast(sym); current_scope = st->m_symtab; for( size_t i = 0; i < x.n_body; i++ ) { if ( AST::is_a(*x.m_body[i]) ) { AST::FunctionDef_t* f = AST::down_cast(x.m_body[i]); - if ( std::string(f->m_name) != std::string("__init__") ){ + if ( std::string(f->m_name) != std::string("__init__") ) { this->visit_stmt(*x.m_body[i]); } } @@ -3346,7 +3313,6 @@ class CommonVisitor : public AST::BaseVisitor { struct_dependencies.reserve(al, 1); ASR::abiType class_abi = ASR::abiType::Source; if( is_bindc_class(x.m_decorator_list, x.n_decorator_list) ) { - class_abi = ASR::abiType::BindC; throw SemanticError("Bindc in classes is not supported,instead use the dataclass decorator ", x.base.base.loc); } @@ -3361,10 +3327,6 @@ class CommonVisitor : public AST::BaseVisitor { is_packed, false, member_init.p, member_init.size(), aligned_expr, nullptr)); parent_scope->add_symbol(x.m_name, class_type); - ASR::symbol_t* sym = current_scope->resolve_symbol(x_m_name); - ASR::Struct_t *st = ASR::down_cast(sym); - st->m_initializers = member_init.p; - st->n_initializers = member_init.size(); } current_scope = parent_scope; } @@ -5139,8 +5101,6 @@ class BodyVisitor : public CommonVisitor { rt_vec.clear(); } - void visit_Constructor(const AST::FunctionDef_t & /*x*/){} - void visit_FunctionDef(const AST::FunctionDef_t &x) { SymbolTable *old_scope = current_scope; ASR::symbol_t *t = current_scope->get_symbol(x.m_name); From 0199e2c5d3cd40efd52a8600bfd215e050c68386 Mon Sep 17 00:00:00 2001 From: Tanay Manerikar Date: Tue, 2 Jul 2024 18:46:27 +0530 Subject: [PATCH 7/9] Added self to symtab, fixed mem_fns in structType --- src/libasr/asr_utils.h | 19 +++++++++++++++---- src/lpython/semantics/python_ast_to_asr.cpp | 10 +++++++--- 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/libasr/asr_utils.h b/src/libasr/asr_utils.h index bfe7a098a6..929e24eb07 100644 --- a/src/libasr/asr_utils.h +++ b/src/libasr/asr_utils.h @@ -2453,7 +2453,9 @@ static inline ASR::dimension_t* duplicate_dimensions(Allocator& al, ASR::dimensi static inline ASR::asr_t* make_StructType_t_util(Allocator& al, Location loc, ASR::symbol_t* der){ ASR::Struct_t* st = ASR::down_cast(ASRUtils::symbol_get_past_external(der)); Vec members; - members.reserve(al, st->n_members); + members.reserve(al, 1); + Vec member_functions; + member_functions.reserve(al, 1); SymbolTable* current_scope = st->m_symtab; for(size_t i = 0; i < st->n_members; i++){ ASR::symbol_t* temp = current_scope->get_symbol(st->m_members[i]); @@ -2463,13 +2465,22 @@ static inline ASR::asr_t* make_StructType_t_util(Allocator& al, Location loc, AS members.push_back(al,var->m_type); } } + for(size_t i = 0; i < st->n_member_functions; i++){ + ASR::symbol_t* temp = current_scope->get_symbol(st->m_member_functions[i]); + if(temp && ASR::is_a(*temp)){ + ASR::Function_t *f = ASR::down_cast(ASRUtils::symbol_get_past_external(temp)); + ASR::ttype_t* f_type = f->m_function_signature; + member_functions.push_back(al,f_type); + } + } + bool is_cstruct = member_functions.n==0; return ASR::make_StructType_t(al, loc, members.p, members.n, - nullptr, //Correct this when mem fn added to Struct_t - 0, //Correct this when mem fn added to Struct_t - true, //Correct this when mem fn added to Struct_t + member_functions.p, + member_functions.n, + is_cstruct, der); } diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 826daff4b0..0568c6a4e3 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -3024,12 +3024,13 @@ class CommonVisitor : public AST::BaseVisitor { } else { AST::FunctionDef_t *f = AST::down_cast(x.m_body[i]); - member_fn_names.push_back(al, f->m_name); std::string f_name = f->m_name; if (f_name == "__init__"){ this->handle_init_method(*f,member_names,member_init); + struct_dependencies.push_back(al, x.m_name); }else{ this->visit_stmt(*x.m_body[i]); + member_fn_names.push_back(al, f->m_name); } continue; } @@ -3318,7 +3319,7 @@ class CommonVisitor : public AST::BaseVisitor { } visit_ClassMembers(x, member_names, member_fn_names, struct_dependencies, member_init, false, class_abi, true); LCOMPILERS_ASSERT(member_init.size() == member_names.size()); - ASR::symbol_t* class_type = ASR::down_cast(ASR::make_Struct_t(al, + ASR::symbol_t* class_sym = ASR::down_cast(ASR::make_Struct_t(al, x.base.base.loc, current_scope, x.m_name, struct_dependencies.p, struct_dependencies.size(), member_names.p, member_names.size(), @@ -3326,7 +3327,10 @@ class CommonVisitor : public AST::BaseVisitor { class_abi, ASR::accessType::Public, is_packed, false, member_init.p, member_init.size(), aligned_expr, nullptr)); - parent_scope->add_symbol(x.m_name, class_type); + ASR::ttype_t* class_type = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, x.base.base.loc, class_sym)); + std::string self_name = "self"; + create_add_variable_to_scope(self_name ,class_type, x.base.base.loc,class_abi); + parent_scope->add_symbol(x.m_name, class_sym); } current_scope = parent_scope; } From 734dab5fda5507164a367a5ddd7acebfc8ca5968 Mon Sep 17 00:00:00 2001 From: Tanay Manerikar Date: Tue, 2 Jul 2024 20:08:41 +0530 Subject: [PATCH 8/9] Removed c backend for integration_tests/class_01 --- integration_tests/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration_tests/CMakeLists.txt b/integration_tests/CMakeLists.txt index 1dfe3a344e..f6396d0be6 100644 --- a/integration_tests/CMakeLists.txt +++ b/integration_tests/CMakeLists.txt @@ -831,7 +831,7 @@ RUN(NAME callback_03 LABELS cpython llvm llvm_jit c) RUN(NAME lambda_01 LABELS cpython llvm llvm_jit) RUN(NAME c_mangling LABELS cpython llvm llvm_jit c) -RUN(NAME class_01 LABELS cpython llvm llvm_jit c) +RUN(NAME class_01 LABELS cpython llvm llvm_jit) # callback_04 is to test emulation. So just run with cpython RUN(NAME callback_04 IMPORT_PATH .. LABELS cpython) From a1ec77f26d7c2491707e2d4086764c3525108c9c Mon Sep 17 00:00:00 2001 From: Tanay Manerikar Date: Tue, 2 Jul 2024 21:35:51 +0530 Subject: [PATCH 9/9] Minor improvements --- integration_tests/class_01.py | 17 +-- src/libasr/asr_utils.h | 37 +++--- src/lpython/semantics/python_ast_to_asr.cpp | 119 ++++++++++++-------- 3 files changed, 99 insertions(+), 74 deletions(-) diff --git a/integration_tests/class_01.py b/integration_tests/class_01.py index b1e1e909c4..103cb612c3 100644 --- a/integration_tests/class_01.py +++ b/integration_tests/class_01.py @@ -2,17 +2,17 @@ from math import sqrt class coord: - def __init__(self:"coord"): - self.x: i32 = 3 + def __init__(self: "coord"): + self.x: i32 = 3 self.y: i32 = 4 - + def main(): p1: coord = coord() sq_dist : i32 = p1.x*p1.x + p1.y*p1.y dist : f64 = sqrt(f64(sq_dist)) - print("Squared Distance from origin = ",sq_dist) + print("Squared Distance from origin = ", sq_dist) assert sq_dist == 25 - print("Distance from origin = ",dist) + print("Distance from origin = ", dist) assert dist == f64(5) print("p1.x = 6") print("p1.y = 8") @@ -20,8 +20,9 @@ def main(): p1.y = 8 sq_dist = p1.x*p1.x + p1.y*p1.y dist = sqrt(f64(sq_dist)) - print("Squared Distance from origin = ",sq_dist) + print("Squared Distance from origin = ", sq_dist) assert sq_dist == 100 - print("Distance from origin = ",dist) + print("Distance from origin = ", dist) assert dist == f64(10) -main() \ No newline at end of file + +main() diff --git a/src/libasr/asr_utils.h b/src/libasr/asr_utils.h index 929e24eb07..89f3adb0a5 100644 --- a/src/libasr/asr_utils.h +++ b/src/libasr/asr_utils.h @@ -2462,24 +2462,25 @@ static inline ASR::asr_t* make_StructType_t_util(Allocator& al, Location loc, AS if(ASR::is_a(*temp)){ ASR::Variable_t* var = ASR::down_cast( ASRUtils::symbol_get_past_external(temp)); - members.push_back(al,var->m_type); + members.push_back(al,var->m_type); } } for(size_t i = 0; i < st->n_member_functions; i++){ - ASR::symbol_t* temp = current_scope->get_symbol(st->m_member_functions[i]); - if(temp && ASR::is_a(*temp)){ - ASR::Function_t *f = ASR::down_cast(ASRUtils::symbol_get_past_external(temp)); + ASR::symbol_t* sym = current_scope->get_symbol(st->m_member_functions[i]); + if(sym && ASR::is_a(*sym)){ + ASR::Function_t *f = ASR::down_cast( + ASRUtils::symbol_get_past_external(sym)); ASR::ttype_t* f_type = f->m_function_signature; - member_functions.push_back(al,f_type); + member_functions.push_back(al, f_type); } } - bool is_cstruct = member_functions.n==0; - return ASR::make_StructType_t(al, - loc, - members.p, + bool is_cstruct = member_functions.n == 0; + return ASR::make_StructType_t(al, + loc, + members.p, members.n, - member_functions.p, - member_functions.n, + member_functions.p, + member_functions.n, is_cstruct, der); @@ -2541,12 +2542,12 @@ static inline ASR::ttype_t* duplicate_type(Allocator& al, const ASR::ttype_t* t, } case ASR::ttypeType::StructType: { ASR::StructType_t* tnew = ASR::down_cast(t); - t_ = ASRUtils::TYPE(ASR::make_StructType_t(al, t->base.loc, - tnew->m_data_member_types, + t_ = ASRUtils::TYPE(ASR::make_StructType_t(al, t->base.loc, + tnew->m_data_member_types, tnew->n_data_member_types, tnew->m_member_function_types, tnew->n_member_function_types, - tnew->m_is_cstruct, + tnew->m_is_cstruct, tnew->m_derived_type)); break; } @@ -2697,12 +2698,12 @@ static inline ASR::ttype_t* duplicate_type_without_dims(Allocator& al, const ASR } case ASR::ttypeType::StructType: { ASR::StructType_t* tstruct = ASR::down_cast(t); - return ASRUtils::TYPE(ASR::make_StructType_t(al, t->base.loc, - tstruct->m_data_member_types, + return ASRUtils::TYPE(ASR::make_StructType_t(al, t->base.loc, + tstruct->m_data_member_types, tstruct->n_data_member_types, tstruct->m_member_function_types, tstruct->n_member_function_types, - tstruct->m_is_cstruct, + tstruct->m_is_cstruct, tstruct->m_derived_type)); } case ASR::ttypeType::Pointer: { @@ -4311,7 +4312,7 @@ class SymbolDuplicator { al, struct_type_t->base.base.loc, struct_type_symtab, struct_type_t->m_name, struct_type_t->m_dependencies, struct_type_t->n_dependencies, struct_type_t->m_members, struct_type_t->n_members, - struct_type_t->m_member_functions, struct_type_t->n_member_functions, + struct_type_t->m_member_functions, struct_type_t->n_member_functions, struct_type_t->m_abi, struct_type_t->m_access, struct_type_t->m_is_packed, struct_type_t->m_is_abstract, struct_type_t->m_initializers, struct_type_t->n_initializers, struct_type_t->m_alignment, diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 0568c6a4e3..0adf860653 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -2493,7 +2493,6 @@ class CommonVisitor : public AST::BaseVisitor { return false; } - void get_alignment(AST::expr_t** decorators, size_t n, ASR::expr_t*& aligned_expr, bool& is_packed) { for( size_t i = 0; i < n; i++ ) { @@ -2933,44 +2932,57 @@ class CommonVisitor : public AST::BaseVisitor { void handle_init_method(const AST::FunctionDef_t &x, Vec& member_names, Vec &member_init){ - if(x.n_decorator_list>0){ - throw SemanticError("Decorators for __init__ not implemented" , x.base.base.loc); + if(x.n_decorator_list > 0) { + throw SemanticError("Decorators for __init__ not implemented", + x.base.base.loc); + } + if( x.m_args.n_args > 1 ) { + throw SemanticError("Only default constructors implemented ", + x.base.base.loc); } - if( x.m_args.n_args > 1 ){ - throw SemanticError("Only default constructors implemented " , x.base.base.loc); + // TODO: the obj_name can be anything + std::string obj_name = "self"; + if ( std::string(x.m_args.m_args[0].m_arg) != obj_name) { + throw SemanticError("Only `self` can be used as object name for now", + x.base.base.loc); } - std::string self_name = x.m_args.m_args[0].m_arg; - for(size_t i = 0; i < x.n_body; i++){ + for(size_t i = 0; i < x.n_body; i++) { std::string var_name; if (! AST::is_a(*x.m_body[i]) ){ - throw SemanticError("Only AnnAssign implemented in __init__ " , x.m_body[i]->base.loc); + throw SemanticError("Only AnnAssign implemented in __init__ ", + x.m_body[i]->base.loc); } AST::AnnAssign_t ann_assign = *AST::down_cast(x.m_body[i]); if(AST::is_a(*ann_assign.m_target)){ AST::Attribute_t* a = AST::down_cast(ann_assign.m_target); - if(AST::is_a(*a->m_value)){ + if(AST::is_a(*a->m_value)) { AST::Name_t* n = AST::down_cast(a->m_value); - if(std::string(n->m_id)!=self_name && current_scope->resolve_symbol(std::string(n->m_id))){ - throw SemanticError("Symbol not declared" , x.m_body[i]->base.loc); + if(std::string(n->m_id) != obj_name) { + throw SemanticError("Object name doesn't matach", + x.m_body[i]->base.loc); } } var_name = a->m_attr; - member_names.push_back(al,s2c(al,var_name)); - }else{ - throw SemanticError("Only Name supported as target in AnnAssign inside struct", x.m_body[i]->base.loc); + member_names.push_back(al, s2c(al, var_name)); + } else { + throw SemanticError("Only Attribute supported as target in " + "AnnAssign inside Class", x.m_body[i]->base.loc); } ASR::expr_t* init_expr = nullptr; - ASR::abiType abi=ASR::abiType::Source; + ASR::abiType abi = ASR::abiType::Source; bool is_allocatable = false, is_const = false; - ASR::ttype_t *type = nullptr; - type = ast_expr_to_asr_type(ann_assign.m_annotation->base.loc, *ann_assign.m_annotation, is_allocatable, is_const, true); + ASR::ttype_t *type = ast_expr_to_asr_type(ann_assign.m_annotation->base.loc, + *ann_assign.m_annotation, is_allocatable, is_const, true); + ASR::storage_typeType storage_type = ASR::storage_typeType::Default; create_add_variable_to_scope(var_name, type, ann_assign.base.base.loc, abi, storage_type); - tmp = nullptr; - if (ann_assign.m_value) { - this->visit_expr(*ann_assign.m_value); + + if (ann_assign.m_value == nullptr) { + throw SemanticError("Missing an initialiser for the data member", + x.m_body[i]->base.loc); } + this->visit_expr(*ann_assign.m_value); if (tmp && ASR::is_a(*tmp)) { ASR::expr_t* value = ASRUtils::EXPR(tmp); ASR::ttype_t* underlying_type = type; @@ -2994,14 +3006,13 @@ class CommonVisitor : public AST::BaseVisitor { c_arg.loc = var_sym->base.loc; c_arg.m_value = init_expr; member_init.push_back(al, c_arg); - init_expr = nullptr; } } void visit_ClassMembers(const AST::ClassDef_t& x, Vec& member_names, Vec& member_fn_names, - SetChar& struct_dependencies, Vec &member_init, + SetChar& struct_dependencies, Vec &member_init, bool is_enum_scope=false, ASR::abiType abi=ASR::abiType::Source, bool is_class_scope = false) { int64_t prev_value = 1; @@ -3021,14 +3032,17 @@ class CommonVisitor : public AST::BaseVisitor { } else if ( AST::is_a(*x.m_body[i]) ) { if ( !is_class_scope ) { throw SemanticError("Struct member functions are not supported", x.m_body[i]->base.loc); - } - else { - AST::FunctionDef_t *f = AST::down_cast(x.m_body[i]); + } else { + AST::FunctionDef_t + *f = AST::down_cast(x.m_body[i]); std::string f_name = f->m_name; - if (f_name == "__init__"){ - this->handle_init_method(*f,member_names,member_init); + if (f_name == "__init__") { + this->handle_init_method(*f, member_names, member_init); + // This seems hackish, as struct depends on itself + // We need to handle this later. + // Removing this throws a ASR verify error struct_dependencies.push_back(al, x.m_name); - }else{ + } else { this->visit_stmt(*x.m_body[i]); member_fn_names.push_back(al, f->m_name); } @@ -3121,8 +3135,6 @@ class CommonVisitor : public AST::BaseVisitor { void visit_ClassDef(const AST::ClassDef_t& x) { std::string x_m_name = x.m_name; - ASR::expr_t* aligned_expr = nullptr; - bool is_packed = false; if( is_enum(x.m_bases, x.n_bases) ) { if( current_scope->resolve_symbol(x_m_name) ) { return ; @@ -3245,6 +3257,8 @@ class CommonVisitor : public AST::BaseVisitor { } return ; } else if( is_dataclass(x.m_decorator_list, x.n_decorator_list) ){ + ASR::expr_t* aligned_expr = nullptr; + bool is_packed = false; get_alignment(x.m_decorator_list, x.n_decorator_list, aligned_expr, is_packed); if( x.n_bases > 0 ) { @@ -3296,7 +3310,8 @@ class CommonVisitor : public AST::BaseVisitor { current_scope = st->m_symtab; for( size_t i = 0; i < x.n_body; i++ ) { if ( AST::is_a(*x.m_body[i]) ) { - AST::FunctionDef_t* f = AST::down_cast(x.m_body[i]); + AST::FunctionDef_t* + f = AST::down_cast(x.m_body[i]); if ( std::string(f->m_name) != std::string("__init__") ) { this->visit_stmt(*x.m_body[i]); } @@ -3309,27 +3324,35 @@ class CommonVisitor : public AST::BaseVisitor { Vec member_init; member_names.reserve(al, 1); member_fn_names.reserve(al, 1); - member_init.reserve(al, 1);//we do not know the size of the members and member functions + member_init.reserve(al, 1); SetChar struct_dependencies; struct_dependencies.reserve(al, 1); ASR::abiType class_abi = ASR::abiType::Source; if( is_bindc_class(x.m_decorator_list, x.n_decorator_list) ) { - throw SemanticError("Bindc in classes is not supported,instead use the dataclass decorator ", - x.base.base.loc); + throw SemanticError("Bindc in classes is not supported, " + "instead use the dataclass decorator ", + x.base.base.loc); } - visit_ClassMembers(x, member_names, member_fn_names, struct_dependencies, member_init, false, class_abi, true); + visit_ClassMembers(x, member_names, member_fn_names, + struct_dependencies, member_init, false, class_abi, true); LCOMPILERS_ASSERT(member_init.size() == member_names.size()); - ASR::symbol_t* class_sym = ASR::down_cast(ASR::make_Struct_t(al, - x.base.base.loc, current_scope, x.m_name, - struct_dependencies.p, struct_dependencies.size(), - member_names.p, member_names.size(), - member_fn_names.p, member_fn_names.size(), - class_abi, ASR::accessType::Public, - is_packed, false, member_init.p, member_init.size(), aligned_expr, - nullptr)); - ASR::ttype_t* class_type = ASRUtils::TYPE(ASRUtils::make_StructType_t_util(al, x.base.base.loc, class_sym)); - std::string self_name = "self"; - create_add_variable_to_scope(self_name ,class_type, x.base.base.loc,class_abi); + ASR::symbol_t* class_sym = ASR::down_cast( + ASR::make_Struct_t(al, x.base.base.loc, current_scope, + x.m_name, struct_dependencies.p, struct_dependencies.size(), + member_names.p, member_names.size(), member_fn_names.p, + member_fn_names.size(), class_abi, ASR::accessType::Public, + false, false, member_init.p, member_init.size(), + nullptr, nullptr)); + ASR::ttype_t* class_type = ASRUtils::TYPE( + ASRUtils::make_StructType_t_util(al, x.base.base.loc, + class_sym)); + std::string self_name = "self"; + if ( current_scope->get_symbol(self_name) ) { + throw SemanticError("`self` cannot be used as a data member " + "for now", x.base.base.loc); + } + create_add_variable_to_scope(self_name, class_type, + x.base.base.loc, class_abi); parent_scope->add_symbol(x.m_name, class_sym); } current_scope = parent_scope; @@ -5700,7 +5723,7 @@ class BodyVisitor : public CommonVisitor { LCOMPILERS_ASSERT(loop_src_var_symbol!=nullptr); auto loop_src_var_ttype = ASRUtils::symbol_type(loop_src_var_symbol); - if (ASR::is_a(*loop_src_var_ttype) || + if (ASR::is_a(*loop_src_var_ttype) || ASR::is_a(*loop_src_var_ttype)) { is_explicit_iterator_required = false; for_each = true; @@ -5740,7 +5763,7 @@ class BodyVisitor : public CommonVisitor { global_init.push_back(al, assign); } loop_src_var_name = tmp_assign_name; - if (ASR::is_a(*loop_src_var_ttype) || + if (ASR::is_a(*loop_src_var_ttype) || ASR::is_a(*loop_src_var_ttype)) { is_explicit_iterator_required = false; for_each = true;