From 542300f378f0e863767e1c9c22c4d461766bfc65 Mon Sep 17 00:00:00 2001 From: tanay-man <93091118+tanay-man@users.noreply.github.com> Date: Tue, 23 Jul 2024 20:58:10 +0530 Subject: [PATCH] Throw an error for class objects assignment (#2784) --- src/lpython/semantics/python_ast_to_asr.cpp | 45 ++++++++++++--------- tests/errors/class_04.py | 12 ++++++ tests/reference/asr-class_04-b89178d.json | 13 ++++++ tests/reference/asr-class_04-b89178d.stderr | 5 +++ tests/tests.toml | 4 ++ 5 files changed, 61 insertions(+), 18 deletions(-) create mode 100644 tests/errors/class_04.py create mode 100644 tests/reference/asr-class_04-b89178d.json create mode 100644 tests/reference/asr-class_04-b89178d.stderr diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index dd61ef6fdf..97a9b38fbd 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -5255,24 +5255,26 @@ class BodyVisitor : public CommonVisitor { if ( sym && ASR::is_a(*sym) ) { ASR::Variable_t* var = ASR::down_cast(sym); if ( ASR::is_a(*(var->m_type)) && - !ASR::down_cast((var->m_type))->m_is_cstruct && - ASR::is_a(*init_expr) ) { - AST::Call_t* call = AST::down_cast(x.m_value); - if ( call->n_keywords>0 ) { - throw SemanticError("Kwargs not implemented yet", x.base.base.loc); - } - Vec 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((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((var->m_type))->m_is_cstruct ) { + if ( !ASR::is_a(*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(x.m_value); + if ( call->n_keywords>0 ) { + throw SemanticError("Kwargs not implemented yet", x.base.base.loc); } + Vec 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((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); + } } } @@ -5539,11 +5541,18 @@ class BodyVisitor : public CommonVisitor { if (target->type == ASR::exprType::Var) { ASR::Var_t *var = ASR::down_cast(target); ASR::symbol_t *sym = var->m_v; + ASR::Variable_t *v = ASR::down_cast(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(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(*(v->m_type)) && + !ASR::down_cast((v->m_type))->m_is_cstruct && + !(tmp_value->type == ASR::exprType::StructConstructor) ) { + ASR::Variable_t *v = ASR::down_cast(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)); diff --git a/tests/errors/class_04.py b/tests/errors/class_04.py new file mode 100644 index 0000000000..c8380a7910 --- /dev/null +++ b/tests/errors/class_04.py @@ -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) \ No newline at end of file diff --git a/tests/reference/asr-class_04-b89178d.json b/tests/reference/asr-class_04-b89178d.json new file mode 100644 index 0000000000..b0422ead8a --- /dev/null +++ b/tests/reference/asr-class_04-b89178d.json @@ -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 +} \ No newline at end of file diff --git a/tests/reference/asr-class_04-b89178d.stderr b/tests/reference/asr-class_04-b89178d.stderr new file mode 100644 index 0000000000..cff5dfbaca --- /dev/null +++ b/tests/reference/asr-class_04-b89178d.stderr @@ -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 + | ^^^^^^^^^^^^^^ diff --git a/tests/tests.toml b/tests/tests.toml index fb5909d0fe..452a018a43 100644 --- a/tests/tests.toml +++ b/tests/tests.toml @@ -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