Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added static methods for classes #2721

Closed
wants to merge 14 commits into from
4 changes: 3 additions & 1 deletion src/libasr/asr_verify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -524,11 +524,13 @@ class VerifyVisitor : public BaseWalkVisitor<VerifyVisitor>
ASR::is_a<ASR::StructType_t>(*a.second) ||
ASR::is_a<ASR::UnionType_t>(*a.second) ||
ASR::is_a<ASR::ExternalSymbol_t>(*a.second) ||
ASR::is_a<ASR::CustomOperator_t>(*a.second) ) {
ASR::is_a<ASR::CustomOperator_t>(*a.second) ||
ASR::is_a<ASR::Function_t>(*a.second)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What was the issue here? Why is Function now skipped?

continue ;
}
// TODO: Uncomment the following line
// ASR::ttype_t* var_type = ASRUtils::extract_type(ASRUtils::symbol_type(a.second));

ASR::ttype_t* var_type = ASRUtils::type_get_past_pointer(ASRUtils::symbol_type(a.second));
char* aggregate_type_name = nullptr;
ASR::symbol_t* sym = nullptr;
Expand Down
1 change: 1 addition & 0 deletions src/libasr/stzY3vVD
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
!<arch>
tanay-man marked this conversation as resolved.
Show resolved Hide resolved
186 changes: 112 additions & 74 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2926,7 +2926,15 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
void visit_ClassMembers(const AST::ClassDef_t& x,
Vec<char*>& member_names, SetChar& struct_dependencies,
Vec<ASR::call_arg_t> &member_init,
bool is_enum_scope=false, ASR::abiType abi=ASR::abiType::Source) {
bool is_enum_scope=false, ASR::abiType abi=ASR::abiType::Source,
bool is_generating_body = false) {
if(is_generating_body){
for( size_t i = 0; i < x.n_body; i++ ){
if ( AST::is_a<AST::FunctionDef_t>(*x.m_body[i]) )
this->visit_stmt(*x.m_body[i]);
}
return;
}
int64_t prev_value = 1;
for( size_t i = 0; i < x.n_body; i++ ) {
if (AST::is_a<AST::Expr_t>(*x.m_body[i])) {
Expand All @@ -2939,77 +2947,102 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
}
throw SemanticError("Only doc strings and const ellipsis allowed as expressions inside class", expr->base.base.loc);
} else if( AST::is_a<AST::ClassDef_t>(*x.m_body[i]) ) {
visit_ClassDef(*AST::down_cast<AST::ClassDef_t>(x.m_body[i]));
visit_ClassDef(*AST::down_cast<AST::ClassDef_t>(x.m_body[i]));
continue;
} else if ( AST::is_a<AST::FunctionDef_t>(*x.m_body[i]) ) {
throw SemanticError("Struct member functions are not supported", x.m_body[i]->base.loc);
this->visit_stmt(*x.m_body[i]);
AST::FunctionDef_t* f_ast = AST::down_cast<AST::FunctionDef_t>(x.m_body[i]);
ASR::symbol_t* f_sym = current_scope->get_symbol(f_ast->m_name);
ASR::Function_t* f = ASR::down_cast<ASR::Function_t>(f_sym);
std::string class_proc_name = "Xx_Class_Procedure_"+std::string(f->m_name);
SymbolTable* proc_scope = ASRUtils::symbol_parent_symtab(f_sym);
Str s;
s.from_str(al,class_proc_name);
ASR::abiType abi = ASR::abiType::Source;
tmp = make_ClassProcedure_t(
al,
f_sym->base.loc,
proc_scope,
tanay-man marked this conversation as resolved.
Show resolved Hide resolved
s.p,
nullptr,
f->m_name,
f_sym,
abi,
false,
false
);
ASR::symbol_t *cls_proc_sym = ASR::down_cast<ASR::symbol_t>(tmp);
current_scope->add_symbol(class_proc_name, cls_proc_sym);
continue;
} else if (AST::is_a<AST::Pass_t>(*x.m_body[i])) {
continue;
} else if (!AST::is_a<AST::AnnAssign_t>(*x.m_body[i])) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this changes, it seems very confusing, we will it in another PR

throw SemanticError("AnnAssign expected inside struct", x.m_body[i]->base.loc);
}
AST::AnnAssign_t* ann_assign = AST::down_cast<AST::AnnAssign_t>(x.m_body[i]);
if (!AST::is_a<AST::Name_t>(*ann_assign->m_target)) {
throw SemanticError("Only Name supported as target in AnnAssign inside struct", x.m_body[i]->base.loc);
}
AST::Name_t *n = AST::down_cast<AST::Name_t>(ann_assign->m_target);
std::string var_name = n->m_id;
ASR::expr_t* init_expr = nullptr;
if( is_enum_scope ) {
ASR::ttype_t* i64_type = ASRUtils::TYPE(ASR::make_Integer_t(al, x.base.base.loc, 8));
init_expr = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, x.base.base.loc, -1, i64_type));
}
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;
member_init.push_back(al, c_arg);
if( is_enum_scope ) {
if( AST::is_a<AST::Call_t>(*ann_assign->m_value) ) {
AST::Call_t* auto_call_cand = AST::down_cast<AST::Call_t>(ann_assign->m_value);
if( AST::is_a<AST::Name_t>(*auto_call_cand->m_func) ) {
AST::Name_t* func = AST::down_cast<AST::Name_t>(auto_call_cand->m_func);
std::string func_name = func->m_id;
if( func_name == "auto" ) {
ASR::ttype_t* int_type = ASRUtils::symbol_type(var_sym);
init_expr = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al,
auto_call_cand->base.base.loc, prev_value, int_type));
prev_value += 1;
} else if (AST::is_a<AST::AnnAssign_t>(*x.m_body[i])) {
AST::AnnAssign_t* ann_assign = AST::down_cast<AST::AnnAssign_t>(x.m_body[i]);
if (!AST::is_a<AST::Name_t>(*ann_assign->m_target)) {
throw SemanticError("Only Name supported as target in AnnAssign inside struct", x.m_body[i]->base.loc);
}
AST::Name_t *n = AST::down_cast<AST::Name_t>(ann_assign->m_target);
std::string var_name = n->m_id;
ASR::expr_t* init_expr = nullptr;
if( is_enum_scope ) {
ASR::ttype_t* i64_type = ASRUtils::TYPE(ASR::make_Integer_t(al, x.base.base.loc, 8));
init_expr = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al, x.base.base.loc, -1, i64_type));
}
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;
member_init.push_back(al, c_arg);
if( is_enum_scope ) {
if( AST::is_a<AST::Call_t>(*ann_assign->m_value) ) {
AST::Call_t* auto_call_cand = AST::down_cast<AST::Call_t>(ann_assign->m_value);
if( AST::is_a<AST::Name_t>(*auto_call_cand->m_func) ) {
AST::Name_t* func = AST::down_cast<AST::Name_t>(auto_call_cand->m_func);
std::string func_name = func->m_id;
if( func_name == "auto" ) {
ASR::ttype_t* int_type = ASRUtils::symbol_type(var_sym);
init_expr = ASRUtils::EXPR(ASR::make_IntegerConstant_t(al,
auto_call_cand->base.base.loc, prev_value, int_type));
prev_value += 1;
}
}
} else {
this->visit_expr(*ann_assign->m_value);
ASR::expr_t* enum_value = ASRUtils::expr_value(ASRUtils::EXPR(tmp));
LCOMPILERS_ASSERT(ASRUtils::is_value_constant(enum_value));
ASRUtils::extract_value(enum_value, prev_value);
prev_value += 1;
init_expr = enum_value;
}
} else {
this->visit_expr(*ann_assign->m_value);
ASR::expr_t* enum_value = ASRUtils::expr_value(ASRUtils::EXPR(tmp));
LCOMPILERS_ASSERT(ASRUtils::is_value_constant(enum_value));
ASRUtils::extract_value(enum_value, prev_value);
prev_value += 1;
init_expr = enum_value;
}
} else {
init_expr = nullptr;
}
if( ASR::is_a<ASR::Variable_t>(*var_sym) ) {
ASR::Variable_t* variable = ASR::down_cast<ASR::Variable_t>(var_sym);
variable->m_symbolic_value = init_expr;
init_expr = nullptr;
}
if( ASR::is_a<ASR::Variable_t>(*var_sym) ) {
ASR::Variable_t* variable = ASR::down_cast<ASR::Variable_t>(var_sym);
variable->m_symbolic_value = init_expr;
}
ASR::ttype_t* var_type = ASRUtils::type_get_past_pointer(ASRUtils::symbol_type(var_sym));
char* aggregate_type_name = nullptr;
if( ASR::is_a<ASR::Struct_t>(*var_type) ) {
aggregate_type_name = ASRUtils::symbol_name(
ASR::down_cast<ASR::Struct_t>(var_type)->m_derived_type);
} else if( ASR::is_a<ASR::Enum_t>(*var_type) ) {
aggregate_type_name = ASRUtils::symbol_name(
ASR::down_cast<ASR::Enum_t>(var_type)->m_enum_type);
} else if( ASR::is_a<ASR::Union_t>(*var_type) ) {
aggregate_type_name = ASRUtils::symbol_name(
ASR::down_cast<ASR::Union_t>(var_type)->m_union_type);
}
if( aggregate_type_name &&
!current_scope->get_symbol(std::string(aggregate_type_name)) ) {
struct_dependencies.push_back(al, aggregate_type_name);
}
member_names.push_back(al, n->m_id);
}
ASR::ttype_t* var_type = ASRUtils::type_get_past_pointer(ASRUtils::symbol_type(var_sym));
char* aggregate_type_name = nullptr;
if( ASR::is_a<ASR::Struct_t>(*var_type) ) {
aggregate_type_name = ASRUtils::symbol_name(
ASR::down_cast<ASR::Struct_t>(var_type)->m_derived_type);
} else if( ASR::is_a<ASR::Enum_t>(*var_type) ) {
aggregate_type_name = ASRUtils::symbol_name(
ASR::down_cast<ASR::Enum_t>(var_type)->m_enum_type);
} else if( ASR::is_a<ASR::Union_t>(*var_type) ) {
aggregate_type_name = ASRUtils::symbol_name(
ASR::down_cast<ASR::Union_t>(var_type)->m_union_type);
}
if( aggregate_type_name &&
!current_scope->get_symbol(std::string(aggregate_type_name)) ) {
struct_dependencies.push_back(al, aggregate_type_name);
else {
throw SemanticError("AnnAssign or Function def expected inside struct", x.m_body[i]->base.loc);
}
member_names.push_back(al, n->m_id);
}
}

Expand All @@ -3030,6 +3063,7 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {

void visit_ClassDef(const AST::ClassDef_t& x) {
std::string x_m_name = x.m_name;
bool is_generating_body = false;
if( is_enum(x.m_bases, x.n_bases) ) {
if( current_scope->resolve_symbol(x_m_name) ) {
return ;
Expand Down Expand Up @@ -3150,19 +3184,21 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
}
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<SymbolTable>(parent_scope);
ASR::symbol_t* clss_sym = current_scope->get_symbol(x_m_name);
ASR::StructType_t* clss = nullptr;
if(clss_sym != nullptr && !is_enum(x.m_bases, x.n_bases) && !is_union(x.m_bases, x.n_bases)){
clss = ASR::down_cast<ASR::StructType_t>(clss_sym);
current_scope = clss->m_symtab;
is_generating_body = true;
}else{
current_scope = al.make_new<SymbolTable>(parent_scope);
}
Vec<char*> member_names;
Vec<ASR::call_arg_t> member_init;
member_names.reserve(al, x.n_body);
Expand All @@ -3173,7 +3209,7 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
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);
visit_ClassMembers(x, member_names, struct_dependencies, member_init, false, class_abi,is_generating_body);
LCOMPILERS_ASSERT(member_init.size() == member_names.size());
ASR::symbol_t* class_type = ASR::down_cast<ASR::symbol_t>(ASR::make_StructType_t(al,
x.base.base.loc, current_scope, x.m_name,
Expand All @@ -3184,12 +3220,14 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
nullptr));
current_scope = parent_scope;
if (current_scope->resolve_symbol(x_m_name)) {
clss->m_symtab->asr_owner = &clss_sym->base;
return;
} else {
current_scope->add_symbol(x_m_name, class_type);
ASR::symbol_t* sym = current_scope->resolve_symbol(x_m_name);
ASR::StructType_t *st = ASR::down_cast<ASR::StructType_t>(sym);
st->m_initializers = member_init.p;
st->n_initializers = member_init.size();
} else {
current_scope->add_symbol(x_m_name, class_type);
st->n_initializers = member_init.size();
}
}

Expand Down
Loading