Skip to content

List in C/C++ backend #1095

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

Merged
merged 4 commits into from
Sep 23, 2022
Merged
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
8 changes: 4 additions & 4 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -171,10 +171,10 @@ RUN(NAME test_types_01 LABELS cpython llvm)
RUN(NAME test_str_01 LABELS cpython llvm)
RUN(NAME test_str_02 LABELS cpython llvm)
RUN(NAME test_str_03 LABELS cpython llvm c)
RUN(NAME test_list_01 LABELS cpython llvm)
RUN(NAME test_list_02 LABELS cpython llvm)
RUN(NAME test_list_03 LABELS cpython llvm)
RUN(NAME test_list_04 LABELS cpython llvm)
RUN(NAME test_list_01 LABELS cpython llvm c)
RUN(NAME test_list_02 LABELS cpython llvm c)
RUN(NAME test_list_03 LABELS cpython llvm c)
RUN(NAME test_list_04 LABELS cpython llvm c)
RUN(NAME test_list_05 LABELS cpython llvm)
RUN(NAME test_list_06 LABELS cpython llvm)
RUN(NAME test_list_07 LABELS cpython llvm)
Expand Down
87 changes: 67 additions & 20 deletions src/libasr/asr_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -629,39 +629,59 @@ static inline std::string type_python_1dim_helper(const std::string & res,
return res;
}

static inline void encode_dimensions(size_t n_dims, std::string& res) {
if( n_dims > 0 ) {
static inline void encode_dimensions(size_t n_dims, std::string& res,
bool use_underscore_sep=false) {
if( n_dims == 0 ) {
return ;
}

if( use_underscore_sep ) {
res += "_";
} else {
res += "[";
}

for( size_t i = 0; i < n_dims; i++ ) {
res += ":";
if( use_underscore_sep ) {
res += "_";
} else {
res += ":";
}
if( i == n_dims - 1 ) {
res += "]";
if( use_underscore_sep ) {
res += "_";
} else {
res += "]";
}
} else {
res += ", ";
if( use_underscore_sep ) {
res += "_";
} else {
res += ", ";
}
}
}
}

static inline std::string get_type_code(const ASR::ttype_t *t)
static inline std::string get_type_code(const ASR::ttype_t *t, bool use_underscore_sep=false)
{
switch (t->type) {
case ASR::ttypeType::Integer: {
ASR::Integer_t *integer = ASR::down_cast<ASR::Integer_t>(t);
std::string res = "i" + std::to_string(integer->m_kind * 8);
encode_dimensions(integer->n_dims, res);
encode_dimensions(integer->n_dims, res, use_underscore_sep);
return res;
}
case ASR::ttypeType::Real: {
ASR::Real_t *real = ASR::down_cast<ASR::Real_t>(t);
std::string res = "r" + std::to_string(real->m_kind * 8);
encode_dimensions(real->n_dims, res);
encode_dimensions(real->n_dims, res, use_underscore_sep);
return res;
}
case ASR::ttypeType::Complex: {
ASR::Complex_t *complx = ASR::down_cast<ASR::Complex_t>(t);
std::string res = "r" + std::to_string(complx->m_kind * 8);
encode_dimensions(complx->n_dims, res);
encode_dimensions(complx->n_dims, res, use_underscore_sep);
return res;
}
case ASR::ttypeType::Logical: {
Expand All @@ -672,28 +692,51 @@ static inline std::string get_type_code(const ASR::ttype_t *t)
}
case ASR::ttypeType::Tuple: {
ASR::Tuple_t *tup = ASR::down_cast<ASR::Tuple_t>(t);
std::string result = "tuple[";
std::string result = "tuple";
if( use_underscore_sep ) {
result += "_";
} else {
result += "[";
}
for (size_t i = 0; i < tup->n_type; i++) {
result += get_type_code(tup->m_type[i]);
result += get_type_code(tup->m_type[i], use_underscore_sep);
if (i + 1 != tup->n_type) {
result += ", ";
if( use_underscore_sep ) {
result += "_";
} else {
result += ", ";
}
}
}
result += "]";
if( use_underscore_sep ) {
result += "_";
} else {
result += "]";
}
return result;
}
case ASR::ttypeType::Set: {
ASR::Set_t *s = ASR::down_cast<ASR::Set_t>(t);
return "set[" + get_type_code(s->m_type) + "]";
if( use_underscore_sep ) {
return "set_" + get_type_code(s->m_type, use_underscore_sep) + "_";
}
return "set[" + get_type_code(s->m_type, use_underscore_sep) + "]";
}
case ASR::ttypeType::Dict: {
ASR::Dict_t *d = ASR::down_cast<ASR::Dict_t>(t);
return "dict[" + get_type_code(d->m_key_type) +
", " + get_type_code(d->m_value_type) + "]";
if( use_underscore_sep ) {
return "dict_" + get_type_code(d->m_key_type, use_underscore_sep) +
"_" + get_type_code(d->m_value_type, use_underscore_sep) + "_";
}
return "dict[" + get_type_code(d->m_key_type, use_underscore_sep) +
", " + get_type_code(d->m_value_type, use_underscore_sep) + "]";
}
case ASR::ttypeType::List: {
ASR::List_t *l = ASR::down_cast<ASR::List_t>(t);
return "list[" + get_type_code(l->m_type) + "]";
if( use_underscore_sep ) {
return "list_" + get_type_code(l->m_type, use_underscore_sep) + "_";
}
return "list[" + get_type_code(l->m_type, use_underscore_sep) + "]";
}
case ASR::ttypeType::CPtr: {
return "CPtr";
Expand All @@ -704,7 +747,10 @@ static inline std::string get_type_code(const ASR::ttype_t *t)
}
case ASR::ttypeType::Pointer: {
ASR::Pointer_t* p = ASR::down_cast<ASR::Pointer_t>(t);
return "Pointer[" + get_type_code(p->m_type) + "]";
if( use_underscore_sep ) {
return "Pointer_" + get_type_code(p->m_type, use_underscore_sep) + "_";
}
return "Pointer[" + get_type_code(p->m_type, use_underscore_sep) + "]";
}
default: {
throw LCompilersException("Type encoding not implemented for "
Expand All @@ -713,10 +759,11 @@ static inline std::string get_type_code(const ASR::ttype_t *t)
}
}

static inline std::string get_type_code(ASR::ttype_t** types, size_t n_types) {
static inline std::string get_type_code(ASR::ttype_t** types, size_t n_types,
bool use_underscore_sep=false) {
std::string code = "";
for( size_t i = 0; i < n_types; i++ ) {
code += get_type_code(types[i]) + "_";
code += get_type_code(types[i], use_underscore_sep) + "_";
}
return code;
}
Expand Down
38 changes: 35 additions & 3 deletions src/libasr/codegen/asr_to_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
int64_t default_lower_bound)
: BaseCCPPVisitor(diag, platform, false, false, true, default_lower_bound),
array_types_decls(std::string("\nstruct dimension_descriptor\n"
"{\n int32_t lower_bound, length;\n};\n")) {
}
"{\n int32_t lower_bound, length;\n};\n")) {
}

std::string convert_dims_c(size_t n_dims, ASR::dimension_t *m_dims,
bool convert_to_1d=false)
Expand Down Expand Up @@ -249,6 +249,10 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
ASR::Character_t *t = ASR::down_cast<ASR::Character_t>(v.m_type);
std::string dims = convert_dims_c(t->n_dims, t->m_dims);
sub = format_type_c(dims, "char *", v.m_name, use_ref, dummy);
if( v.m_intent == ASRUtils::intent_local ) {
sub += " = (char*) malloc(40 * sizeof(char))";
return sub;
}
} else if (ASR::is_a<ASR::Derived_t>(*v.m_type)) {
std::string indent(indentation_level*indentation_spaces, ' ');
ASR::Derived_t *t = ASR::down_cast<ASR::Derived_t>(v.m_type);
Expand Down Expand Up @@ -321,6 +325,12 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>
sub = format_type_c(dims, "union " + der_type_name,
v.m_name, use_ref, dummy);
}
} else if (ASR::is_a<ASR::List_t>(*v.m_type)) {
ASR::List_t* t = ASR::down_cast<ASR::List_t>(v.m_type);
std::string list_element_type = get_c_type_from_ttype_t(t->m_type);
std::string list_type_c = list_api->get_list_type(t, list_element_type);
sub = format_type_c("", list_type_c, v.m_name,
false, false);
} else if (ASR::is_a<ASR::CPtr_t>(*v.m_type)) {
sub = format_type_c("", "void*", v.m_name, false, false);
} else if (ASR::is_a<ASR::Enum_t>(*v.m_type)) {
Expand All @@ -347,13 +357,16 @@ class ASRToCVisitor : public BaseCCPPVisitor<ASRToCVisitor>


void visit_TranslationUnit(const ASR::TranslationUnit_t &x) {
is_string_concat_present = false;
global_scope = x.m_global_scope;
// All loose statements must be converted to a function, so the items
// must be empty:
LFORTRAN_ASSERT(x.n_items == 0);
std::string unit_src = "";
indentation_level = 0;
indentation_spaces = 4;
list_api->set_indentation(indentation_level, indentation_spaces);
list_api->set_global_scope(global_scope);

std::string head =
R"(
Expand Down Expand Up @@ -388,6 +401,15 @@ R"(

)";

std::string indent(indentation_level * indentation_spaces, ' ');
std::string tab(indentation_spaces, ' ');
std::string strcat_def = "";
strcat_def += indent + "char* " + global_scope->get_unique_name("strcat_") + "(char* x, char* y) {\n";
strcat_def += indent + tab + "char* str_tmp = (char*) malloc((strlen(x) + strlen(y) + 2) * sizeof(char));\n";
strcat_def += indent + tab + "strcpy(str_tmp, x);\n";
strcat_def += indent + tab + "return strcat(str_tmp, y);\n";
strcat_def += indent + "}\n\n";

for (auto &item : x.m_global_scope->get_scope()) {
if (ASR::is_a<ASR::DerivedType_t>(*item.second)) {
array_types_decls += "struct " + item.first + ";\n\n";
Expand Down Expand Up @@ -482,7 +504,17 @@ R"(
for (auto s: headers) {
to_include += "#include <" + s + ".h>\n";
}
src = to_include + head + array_types_decls + unit_src;
if( list_api->get_list_func_decls().size() > 0 ) {
array_types_decls += "\n" + list_api->get_list_func_decls() + "\n";
}
std::string list_funcs_defined = "";
if( list_api->get_generated_code().size() > 0 ) {
list_funcs_defined = "\n" + list_api->get_generated_code() + "\n";
}
if( is_string_concat_present ) {
head += strcat_def;
}
src = to_include + head + array_types_decls + unit_src + list_funcs_defined;
}

void visit_Program(const ASR::Program_t &x) {
Expand Down
Loading