Skip to content

Commit

Permalink
Throw an error for class objects assignment (lcompilers#2784)
Browse files Browse the repository at this point in the history
  • Loading branch information
tanay-man authored Jul 23, 2024
1 parent c58d31c commit 542300f
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 18 deletions.
45 changes: 27 additions & 18 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5255,24 +5255,26 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
if ( sym && ASR::is_a<ASR::Variable_t>(*sym) ) {
ASR::Variable_t* var = ASR::down_cast<ASR::Variable_t>(sym);
if ( ASR::is_a<ASR::StructType_t>(*(var->m_type)) &&
!ASR::down_cast<ASR::StructType_t>((var->m_type))->m_is_cstruct &&
ASR::is_a<ASR::StructConstructor_t>(*init_expr) ) {
AST::Call_t* call = AST::down_cast<AST::Call_t>(x.m_value);
if ( call->n_keywords>0 ) {
throw SemanticError("Kwargs not implemented yet", x.base.base.loc);
}
Vec<ASR::call_arg_t> args;
args.reserve(al, call->n_args + 1);
ASR::call_arg_t self_arg;
self_arg.loc = x.base.base.loc;
self_arg.m_value = ASRUtils::EXPR(ASR::make_Var_t(al, x.base.base.loc, sym));
args.push_back(al, self_arg);
visit_expr_list(call->m_args, call->n_args, args);
ASR::symbol_t* der = ASR::down_cast<ASR::StructType_t>((var->m_type))->m_derived_type;
std::string call_name = "__init__";
ASR::symbol_t* call_sym = get_struct_member(der, call_name, x.base.base.loc);
tmp = make_call_helper(al, call_sym, current_scope, args, call_name, x.base.base.loc);
!ASR::down_cast<ASR::StructType_t>((var->m_type))->m_is_cstruct ) {
if ( !ASR::is_a<ASR::StructConstructor_t>(*init_expr) ) {
throw SemanticError("Only Class constructor is allowed in the object assignment for now", x.base.base.loc);
}
AST::Call_t* call = AST::down_cast<AST::Call_t>(x.m_value);
if ( call->n_keywords>0 ) {
throw SemanticError("Kwargs not implemented yet", x.base.base.loc);
}
Vec<ASR::call_arg_t> args;
args.reserve(al, call->n_args + 1);
ASR::call_arg_t self_arg;
self_arg.loc = x.base.base.loc;
self_arg.m_value = ASRUtils::EXPR(ASR::make_Var_t(al, x.base.base.loc, sym));
args.push_back(al, self_arg);
visit_expr_list(call->m_args, call->n_args, args);
ASR::symbol_t* der = ASR::down_cast<ASR::StructType_t>((var->m_type))->m_derived_type;
std::string call_name = "__init__";
ASR::symbol_t* call_sym = get_struct_member(der, call_name, x.base.base.loc);
tmp = make_call_helper(al, call_sym, current_scope, args, call_name, x.base.base.loc);
}
}
}

Expand Down Expand Up @@ -5539,11 +5541,18 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
if (target->type == ASR::exprType::Var) {
ASR::Var_t *var = ASR::down_cast<ASR::Var_t>(target);
ASR::symbol_t *sym = var->m_v;
ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(sym);
if (do_loop_variables.size() > 0 && std::find(do_loop_variables.begin(), do_loop_variables.end(), sym) != do_loop_variables.end()) {
ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(sym);
std::string var_name = std::string(v->m_name);
throw SemanticError("Assignment to loop variable `" + std::string(to_lower(var_name)) +"` is not allowed", target->base.loc);
}
if ( ASR::is_a<ASR::StructType_t>(*(v->m_type)) &&
!ASR::down_cast<ASR::StructType_t>((v->m_type))->m_is_cstruct &&
!(tmp_value->type == ASR::exprType::StructConstructor) ) {
ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(sym);
std::string var_name = std::string(v->m_name);
throw SemanticError("Only Class constructor is allowed in the object assignment for now", target->base.loc);
}
}
tmp_vec.push_back(ASR::make_Assignment_t(al, x.base.base.loc, target, tmp_value,
overloaded));
Expand Down
12 changes: 12 additions & 0 deletions tests/errors/class_04.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from lpython import i32

class coord:
def __init__(self:"coord", x:i32, y:i32):
self.x: i32 = x
self.y: i32 = y

p1: coord = coord(1, 2)
p2: coord = p1
p2.x = 2
print(p1.x)
print(p2.x)
13 changes: 13 additions & 0 deletions tests/reference/asr-class_04-b89178d.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"basename": "asr-class_04-b89178d",
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}",
"infile": "tests/errors/class_04.py",
"infile_hash": "e1e1c48050cce1b2855e4f8409aa3d72df716f61b8aa045aa97ae914",
"outfile": null,
"outfile_hash": null,
"stdout": null,
"stdout_hash": null,
"stderr": "asr-class_04-b89178d.stderr",
"stderr_hash": "7f8e807f5582952b4ad93b1fb3d4d264842a0700aeda5be00611d098",
"returncode": 2
}
5 changes: 5 additions & 0 deletions tests/reference/asr-class_04-b89178d.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
semantic error: Only Class constructor is allowed in the object assignment for now
--> tests/errors/class_04.py:9:1
|
9 | p2: coord = p1
| ^^^^^^^^^^^^^^
4 changes: 4 additions & 0 deletions tests/tests.toml
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,10 @@ asr = true
pass = "class_constructor"
cumulative = true

[[test]]
filename = "errors/class_04.py"
asr = true

[[test]]
filename = "../integration_tests/callback_01.py"
asr = true
Expand Down

0 comments on commit 542300f

Please sign in to comment.