Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add support for accessing values from data-structures contained within Const #2560

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

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions src/libasr/codegen/asr_to_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1523,8 +1523,15 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}

void visit_ListItem(const ASR::ListItem_t& x) {
ASR::ttype_t* el_type = ASRUtils::get_contained_type(
ASRUtils::expr_type(x.m_a));
/* Check whether the `list` is a `Const[list[data_type]]`:
- If true, set the list `el_type` to `data_type` by first going to `Const`, then `list`.
- If false, we have a normal list - `list[data_type]`, go to `list` and get `data_type`.

We do the type checking through strings because `ASR::is_a<T>` throws an error.
*/
ASR::ttype_t *el_type = ASRUtils::type_to_str(ASRUtils::expr_type(x.m_a)) == "list const"
? ASRUtils::get_contained_type(ASRUtils::get_contained_type(ASRUtils::expr_type(x.m_a)))
: ASRUtils::get_contained_type(ASRUtils::expr_type(x.m_a));
int64_t ptr_loads_copy = ptr_loads;
ptr_loads = 0;
this->visit_expr(*x.m_a);
Expand All @@ -1540,8 +1547,16 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}

void visit_DictItem(const ASR::DictItem_t& x) {
ASR::Dict_t* dict_type = ASR::down_cast<ASR::Dict_t>(
ASRUtils::expr_type(x.m_a));
/* Check whether the `dict` is a `Const[dict[key_type, value_type]]`:
- If true, set the `dict_type` to `dict[key_type, value_type]' by going to `Const`.
- If false, we have a normal dict - `dict[key_type, value_type]`.

We do the type checking through strings because `ASR::is_a<T>` throws an error.
*/
ASR::Dict_t *dict_type = ASRUtils::type_to_str(ASRUtils::expr_type(x.m_a)) == "dict const"
? ASR::down_cast<ASR::Dict_t>(ASRUtils::get_contained_type(ASRUtils::expr_type(x.m_a)))
: ASR::down_cast<ASR::Dict_t>(ASRUtils::expr_type(x.m_a));

int64_t ptr_loads_copy = ptr_loads;
ptr_loads = 0;
this->visit_expr(*x.m_a);
Expand Down
144 changes: 83 additions & 61 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1750,7 +1750,13 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
} else if (var_annotation == "Const") {
ASR::ttype_t *type = ast_expr_to_asr_type(loc, *s->m_slice,
is_allocatable, raise_error, abi, is_argument);
return ASRUtils::TYPE(ASR::make_Const_t(al, loc, type));
if (ASRUtils::type_to_str(type) == "tuple") {
throw SemanticError("'Const' not required as tuples are already immutable", loc);
}
else if (ASRUtils::type_to_str(type) == "character") {
throw SemanticError("'Const' not required as strings are already immutable", loc);
}
return ASRUtils::TYPE(ASR::make_Const_t(al, loc, type));
} else {
AST::expr_t* dim_info = s->m_slice;

Expand Down Expand Up @@ -3680,7 +3686,8 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
ai.m_left = nullptr;
ai.m_right = nullptr;
ai.m_step = nullptr;
if (AST::is_a<AST::Slice_t>(*m_slice)) {
if (AST::is_a<AST::Slice_t>(*m_slice))
{
AST::Slice_t *sl = AST::down_cast<AST::Slice_t>(m_slice);
if (sl->m_lower != nullptr) {
this->visit_expr(*sl->m_lower);
Expand Down Expand Up @@ -3720,7 +3727,14 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
ai.m_step == nullptr &&
ai.m_right != nullptr);
}
if (ASR::is_a<ASR::List_t>(*type)) {
if (ASR::is_a<ASR::Const_t>(*type))
{
if (ASRUtils::type_to_str(ASRUtils::get_contained_type(type)) == "list")
{
throw SemanticError("slicing on a const list is not implemented till now", loc);
}
}
else if (ASR::is_a<ASR::List_t>(*type)) {
tmp = ASR::make_ListSection_t(al, loc, value, ai, type, nullptr);
return false;
} else if (ASR::is_a<ASR::Character_t>(*type)) {
Expand All @@ -3730,17 +3744,55 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
} else if (ASR::is_a<ASR::Dict_t>(*type)) {
throw SemanticError("unhashable type in dict: 'slice'", loc);
}
} else if(AST::is_a<AST::Tuple_t>(*m_slice) &&
ASRUtils::is_array(type)) {
}
else if (AST::is_a<AST::Tuple_t>(*m_slice) &&
ASRUtils::is_array(type)) {
bool final_result = true;
AST::Tuple_t* indices = AST::down_cast<AST::Tuple_t>(m_slice);
for( size_t i = 0; i < indices->n_elts; i++ ) {
final_result &= visit_SubscriptIndices(indices->m_elts[i], args,
value, type, is_item, loc);
}
return final_result;
} else {
}
else
{
ASR::expr_t *index = nullptr;
this->visit_expr(*m_slice);
if (ASR::is_a<ASR::Const_t>(*type))
{
ASR::ttype_t *contained_type = ASRUtils::type_get_past_const(type);
if (ASR::is_a<ASR::Dict_t>(*contained_type))
{
index = ASRUtils::EXPR(tmp);
ASR::ttype_t *key_type = ASR::down_cast<ASR::Dict_t>(contained_type)->m_key_type;
if (!ASRUtils::check_equal_type(ASRUtils::expr_type(index), key_type))
{
throw SemanticError("Key type should be '" + ASRUtils::type_to_str_python(key_type) +
"' instead of '" +
ASRUtils::type_to_str_python(ASRUtils::expr_type(index)) + "'",
index->base.loc);
}
tmp = ASR::make_DictItem_t(al, loc, value, index, nullptr, ASR::down_cast<ASR::Dict_t>(contained_type)->m_value_type, nullptr);
return false;
}
else if (ASR::is_a<ASR::List_t>(*contained_type))
{
this->visit_expr(*m_slice);
index = ASRUtils::EXPR(tmp);
tmp = make_ListItem_t(al, loc, value, index,
ASR::down_cast<ASR::List_t>(contained_type)->m_type, nullptr);
return false;
}
else if (ASR::is_a<ASR::Character_t>(*contained_type))
{
throw SemanticError("Const not required as strings are already immutable", loc);
}
else if (ASR::is_a<ASR::Tuple_t>(*contained_type))
{
throw SemanticError("Const not required as tuples are already immutable", loc);
}
}
if (!ASR::is_a<ASR::Dict_t>(*type) &&
!ASRUtils::is_integer(*ASRUtils::expr_type(ASRUtils::EXPR(tmp)))) {
std::string fnd = ASRUtils::type_to_str_python(ASRUtils::expr_type(ASRUtils::EXPR(tmp)));
Expand All @@ -3753,8 +3805,8 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
);
throw SemanticAbort();
}
ASR::expr_t *index = nullptr;
if (ASR::is_a<ASR::Dict_t>(*type)) {
this->visit_expr(*m_slice);
index = ASRUtils::EXPR(tmp);
ASR::ttype_t *key_type = ASR::down_cast<ASR::Dict_t>(type)->m_key_type;
if (!ASRUtils::check_equal_type(ASRUtils::expr_type(index), key_type)) {
Expand Down Expand Up @@ -3830,7 +3882,8 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
void visit_Subscript(const AST::Subscript_t &x) {
this->visit_expr(*x.m_value);
if (using_args_attr) {
if (AST::is_a<AST::Attribute_t>(*x.m_value)){
if (AST::is_a<AST::Attribute_t>(*x.m_value))
{
AST::Attribute_t *attr = AST::down_cast<AST::Attribute_t>(x.m_value);
if (AST::is_a<AST::Name_t>(*attr->m_value)) {
AST::Name_t *var_name = AST::down_cast<AST::Name_t>(attr->m_value);
Expand Down Expand Up @@ -6577,6 +6630,26 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
arg.loc = loc;
arg.m_value = s_var;
fn_args.push_back(al, arg);
} else if (attr_name == "isalpha") {
if (args.size() != 0) {
throw SemanticError("str.isalpha() takes no arguments",
loc);
}
fn_call_name = "_lpython_str_isalpha";
ASR::call_arg_t arg;
arg.loc = loc;
arg.m_value = s_var;
fn_args.push_back(al, arg);
} else if (attr_name == "istitle") {
if (args.size() != 0) {
throw SemanticError("str.istitle() takes no arguments",
loc);
}
fn_call_name = "_lpython_str_istitle";
ASR::call_arg_t arg;
arg.loc = loc;
arg.m_value = s_var;
fn_args.push_back(al, arg);
} else if (attr_name == "title") {
if (args.size() != 0) {
throw SemanticError("str.title() takes no arguments",
Expand Down Expand Up @@ -6793,7 +6866,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
/*
String Validation Methods i.e all "is" based functions are handled here
*/
std::vector<std::string> validation_methods{"lower", "upper", "decimal", "ascii", "space", "alpha", "title"}; // Database of validation methods supported
std::vector<std::string> validation_methods{"lower", "upper", "decimal", "ascii", "space"}; // Database of validation methods supported
std::string method_name = attr_name.substr(2);

if(std::find(validation_methods.begin(),validation_methods.end(), method_name) == validation_methods.end()) {
Expand Down Expand Up @@ -7096,7 +7169,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
* islower() method is limited to English Alphabets currently
* TODO: We can support other characters from Unicode Library
*/
std::vector<std::string> validation_methods{"lower", "upper", "decimal", "ascii", "space", "alpha", "title"}; // Database of validation methods supported
std::vector<std::string> validation_methods{"lower", "upper", "decimal", "ascii", "space"}; // Database of validation methods supported
std::string method_name = attr_name.substr(2);
if(std::find(validation_methods.begin(),validation_methods.end(), method_name) == validation_methods.end()) {
throw SemanticError("String method not implemented: " + attr_name, loc);
Expand Down Expand Up @@ -7194,57 +7267,6 @@ we will have to use something else.
tmp = ASR::make_LogicalConstant_t(al, loc, is_space,
ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)));
return;
} else if (attr_name == "isalpha") {
/*
* Specification -
Return True if all characters in the string are alphabets,
and there is at least one character in the string.
*/
bool is_alpha = (s_var.size() != 0);
for (auto &i : s_var) {
if (!((i >= 'A' && i <= 'Z') || (i >= 'a' && i <= 'z'))) {
is_alpha = false;
break;
}
}
tmp = ASR::make_LogicalConstant_t(al, loc, is_alpha,
ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)));
return;
} else if (attr_name == "istitle") {
/*
* Specification -
Returns True if all words in the string are in title case,
and there is at least one character in the string.
*/
bool is_title = (s_var.size() != 0);

bool in_word = false; // Represents if we are in a word or not
bool is_alpha_present = false;
for (auto &i : s_var) {
if (i >= 'A' && i <= 'Z') {
is_alpha_present = true;
if (in_word) {
// We have come across an uppercase character in the middle of a word
is_title = false;
break;
} else {
in_word = true;
}
} else if (i >= 'a' && i <= 'z') {
is_alpha_present = true;
if (!in_word) {
//We have come across a lowercase character at the start of a word
is_title = false;
break;
}
} else {
in_word = false;
}
}
is_title = is_title && is_alpha_present;
tmp = ASR::make_LogicalConstant_t(al, loc, is_title,
ASRUtils::TYPE(ASR::make_Logical_t(al, loc, 4)));
return;
} else {
throw SemanticError("'str' object has no attribute '" + attr_name + "'", loc);
}
Expand Down