Skip to content

Incorrect results due to outdated compile time values #661

Closed
@czgdp1807

Description

@czgdp1807

Code

from ltypes import i32

def main0():
    i1: i32 = 10
    i2: i32 = 4
    i1 = 3
    i2 = 5
    print(-i1 ^ -i2)
    assert -i1 ^ -i2 == 6

main0()

Output

10
AssertionError

Reasons for failure,

  1. value attribute (this is the attribute which stores compile time values) is being set for non-constant variables.
  2. This leads to compile time value of -i1 as 10 and -i2 as 4. Hence, bitwise_xor is being evaluated at compile time.
  3. If we set value attribute as nullptr then we get random outputs because there is no implementation of bitwise_xor provided which can be used at runtime.

See the original code where value attribute of Variable ASR node is being set,

void visit_AnnAssign(const AST::AnnAssign_t &x) {
// We treat this as a declaration
std::string var_name;
std::string var_annotation;
if (AST::is_a<AST::Name_t>(*x.m_target)) {
AST::Name_t *n = AST::down_cast<AST::Name_t>(x.m_target);
var_name = n->m_id;
} else {
throw SemanticError("Only Name supported for now as LHS of annotated assignment",
x.base.base.loc);
}
if (current_scope->get_scope().find(var_name) !=
current_scope->get_scope().end()) {
if (current_scope->parent != nullptr) {
// Re-declaring a global scope variable is allowed,
// otherwise raise an error
ASR::symbol_t *orig_decl = current_scope->get_symbol(var_name);
throw SemanticError(diag::Diagnostic(
"Symbol is already declared in the same scope",
diag::Level::Error, diag::Stage::Semantic, {
diag::Label("original declaration", {orig_decl->base.loc}, false),
diag::Label("redeclaration", {x.base.base.loc}),
}));
}
}
ASR::ttype_t *type = ast_expr_to_asr_type(x.base.base.loc, *x.m_annotation);
ASR::expr_t *value = nullptr;
if (x.m_value) {
this->visit_expr(*x.m_value);
value = ASRUtils::EXPR(tmp);
value = cast_helper(type, value, true);
if (!ASRUtils::check_equal_type(type, ASRUtils::expr_type(value))) {
std::string ltype = ASRUtils::type_to_str_python(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 + "')",
{x.m_target->base.loc, value->base.loc})
})
);
throw SemanticAbort();
}
}
ASR::expr_t *init_expr = nullptr;
ASR::intentType s_intent = ASRUtils::intent_local;
ASR::storage_typeType storage_type =
ASR::storage_typeType::Default;
ASR::abiType current_procedure_abi_type = ASR::abiType::Source;
ASR::accessType s_access = ASR::accessType::Public;
ASR::presenceType s_presence = ASR::presenceType::Required;
bool value_attr = false;
ASR::asr_t *v = ASR::make_Variable_t(al, x.base.base.loc, current_scope,
s2c(al, var_name), s_intent, init_expr, value, storage_type, type,
current_procedure_abi_type, s_access, s_presence,
value_attr);
current_scope->add_symbol(var_name, ASR::down_cast<ASR::symbol_t>(v));
tmp = nullptr;
}

You can clearly see, init_expr is nullptr,

ASR::expr_t *init_expr = nullptr;

and value is filled with initial expression,

value = cast_helper(type, value, true);

I was compelled to follow this pattern in some of my PRs but now I think we should fix this because this is producing incorrect results.

Metadata

Metadata

Assignees

Labels

asrASR related changes

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions