Skip to content

Commit

Permalink
Add tuple concat
Browse files Browse the repository at this point in the history
  • Loading branch information
kabra1110 authored and czgdp1807 committed May 29, 2023
1 parent 9e8b2db commit 4a2f9b3
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 0 deletions.
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@ RUN(NAME test_list_reverse LABELS cpython llvm)
RUN(NAME test_tuple_01 LABELS cpython llvm c)
RUN(NAME test_tuple_02 LABELS cpython llvm c)
RUN(NAME test_tuple_03 LABELS cpython llvm c)
RUN(NAME test_tuple_concat LABELS cpython llvm)
RUN(NAME test_dict_01 LABELS cpython llvm c)
RUN(NAME test_dict_02 LABELS cpython llvm c)
RUN(NAME test_dict_03 LABELS cpython llvm)
Expand Down
42 changes: 42 additions & 0 deletions integration_tests/test_tuple_concat.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from lpython import i32, f64

def test_tuple_concat():
t1: tuple[i32, i32]
t2: tuple[f64, str, i32]
t3: tuple[f64]
t4: tuple[i32, i32, f64, str, i32, f64]
t5: tuple[i32, f64]
t6: tuple[i32, f64, i32, f64]
t7: tuple[i32, f64, i32, f64, i32, f64]
t8: tuple[i32, f64, i32, f64, i32, f64, i32, f64]
l1: list[tuple[i32, f64]] = []
start: i32
i:i32
t9: tuple[tuple[i32, i32], tuple[f64, str, i32]]

t1 = (1, 2)
t2 = (3.0, "abc", -10)
t3 = (10.0,)
t4 = t1 + t2 + t3
assert t4 == (t1[0], t1[1], t2[0], t2[1], t2[2], t3[0])
assert t4 + t3 == t1 + t2 + t3 + (t3[0],)

start = 117
for i in range(start, start + 3):
t5 = (i, f64(i*i))
l1.append(t5)
if i == start:
t6 = t5 + l1[-1]
elif i == start + 1:
t7 = t6 + l1[-1]
else:
t8 = t7 + l1[-1]

assert t6 == l1[0] + l1[0]
assert t7 == t6 + l1[1]
assert t8 == t7 + l1[2]

t9 = (t1,) + (t2,)
assert t9[0] == t1 and t9[1] == t2

test_tuple_concat()
1 change: 1 addition & 0 deletions src/libasr/ASR.asdl
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ expr
| TupleConstant(expr* elements, ttype type)
| TupleLen(expr arg, ttype type, expr value)
| TupleCompare(expr left, cmpop op, expr right, ttype type, expr? value)
| TupleConcat(expr left, expr right, ttype type, expr? value)

| StringConstant(string s, ttype type)
| StringConcat(expr left, expr right, ttype type, expr? value)
Expand Down
44 changes: 44 additions & 0 deletions src/libasr/codegen/asr_to_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2129,6 +2129,50 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
tmp = tuple_api->read_item(ptuple, pos, LLVM::is_llvm_struct(x.m_type));
}

void visit_TupleConcat(const ASR::TupleConcat_t& x) {
int64_t ptr_loads_copy = ptr_loads;
ptr_loads = 0;
this->visit_expr(*x.m_left);
llvm::Value* left = tmp;
this->visit_expr(*x.m_right);
llvm::Value* right = tmp;
ptr_loads = ptr_loads_copy;

ASR::Tuple_t* tuple_type_left = ASR::down_cast<ASR::Tuple_t>(ASRUtils::expr_type(x.m_left));
std::string type_code_left = ASRUtils::get_type_code(tuple_type_left->m_type,
tuple_type_left->n_type);
ASR::Tuple_t* tuple_type_right = ASR::down_cast<ASR::Tuple_t>(ASRUtils::expr_type(x.m_right));
std::string type_code_right = ASRUtils::get_type_code(tuple_type_right->m_type,
tuple_type_right->n_type);
std::string type_code = type_code_left + type_code_right;
std::vector<llvm::Type*> llvm_el_types;
ASR::storage_typeType m_storage = ASR::storage_typeType::Default;
bool is_array_type = false, is_malloc_array_type = false;
bool is_list = false;
ASR::dimension_t* m_dims = nullptr;
int n_dims = 0, a_kind = -1;
for( size_t i = 0; i < tuple_type_left->n_type; i++ ) {
llvm_el_types.push_back(get_type_from_ttype_t(tuple_type_left->m_type[i],
nullptr,
m_storage, is_array_type, is_malloc_array_type,
is_list, m_dims, n_dims, a_kind));
}
is_array_type = false; is_malloc_array_type = false;
is_list = false;
m_dims = nullptr;
n_dims = 0; a_kind = -1;
for( size_t i = 0; i < tuple_type_right->n_type; i++ ) {
llvm_el_types.push_back(get_type_from_ttype_t(tuple_type_right->m_type[i],
nullptr,
m_storage, is_array_type, is_malloc_array_type,
is_list, m_dims, n_dims, a_kind));
}
llvm::Type* concat_tuple_type = tuple_api->get_tuple_type(type_code, llvm_el_types);
llvm::Value* concat_tuple = builder->CreateAlloca(concat_tuple_type, nullptr, "concat_tuple");
tuple_api->concat(left, right, tuple_type_left, tuple_type_right, concat_tuple, *module);
tmp = concat_tuple;
}

void visit_ArrayItem(const ASR::ArrayItem_t& x) {
if (x.m_value) {
this->visit_expr_wrapper(x.m_value, true);
Expand Down
14 changes: 14 additions & 0 deletions src/libasr/codegen/llvm_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3045,4 +3045,18 @@ namespace LCompilers {
return is_equal;
}

void LLVMTuple::concat(llvm::Value* t1, llvm::Value* t2,
ASR::Tuple_t* tuple_type_1, ASR::Tuple_t* tuple_type_2,
llvm::Value* concat_tuple,
llvm::Module& module) {
std::vector<llvm::Value*> values;
for( size_t i = 0; i < tuple_type_1->n_type; i++ ) {
values.push_back(llvm_utils->tuple_api->read_item(t1, i, false));
}
for( size_t i = 0; i < tuple_type_2->n_type; i++ ) {
values.push_back(llvm_utils->tuple_api->read_item(t2, i, false));
}
tuple_init(concat_tuple, values);
}

} // namespace LCompilers
5 changes: 5 additions & 0 deletions src/libasr/codegen/llvm_utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,11 @@ namespace LCompilers {
llvm::Value* check_tuple_equality(llvm::Value* t1, llvm::Value* t2,
ASR::Tuple_t* tuple_type, llvm::LLVMContext& context,
llvm::IRBuilder<>* builder, llvm::Module& module);

void concat(llvm::Value* t1, llvm::Value* t2,
ASR::Tuple_t* tuple_type_1, ASR::Tuple_t* tuple_type_2,
llvm::Value* concat_tuple,
llvm::Module& module);
};

class LLVMDictInterface {
Expand Down
16 changes: 16 additions & 0 deletions src/lpython/semantics/python_ast_to_asr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2156,6 +2156,22 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
}
tmp = ASR::make_ListConcat_t(al, loc, left, right, dest_type, value);
return;
} else if (ASR::is_a<ASR::Tuple_t>(*left_type) && ASR::is_a<ASR::Tuple_t>(*right_type)
&& op == ASR::binopType::Add) {
Vec<ASR::ttype_t*> tuple_type_vec;
ASR::Tuple_t* tuple_type_left = ASR::down_cast<ASR::Tuple_t>(left_type);
ASR::Tuple_t* tuple_type_right = ASR::down_cast<ASR::Tuple_t>(right_type);
tuple_type_vec.reserve(al, tuple_type_left->n_type + tuple_type_right->n_type);
for (size_t i=0; i<tuple_type_left->n_type; i++) {
tuple_type_vec.push_back(al, tuple_type_left->m_type[i]);
}
for (size_t i=0; i<tuple_type_right->n_type; i++) {
tuple_type_vec.push_back(al, tuple_type_right->m_type[i]);
}
ASR::ttype_t *tuple_type = ASRUtils::TYPE(ASR::make_Tuple_t(al, loc,
tuple_type_vec.p, tuple_type_vec.n));
tmp = ASR::make_TupleConcat_t(al, loc, left, right, tuple_type, value);
return;
} else {
std::string ltype = ASRUtils::type_to_str_python(ASRUtils::expr_type(left));
std::string rtype = ASRUtils::type_to_str_python(ASRUtils::expr_type(right));
Expand Down

0 comments on commit 4a2f9b3

Please sign in to comment.