Skip to content

Supporting list of lists, list of tuples and tuples with lists #952

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 10 commits into from
Aug 13, 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
3 changes: 3 additions & 0 deletions integration_tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ 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_05 LABELS cpython llvm)
RUN(NAME test_list_06 LABELS cpython llvm)
RUN(NAME test_list_07 LABELS cpython llvm)
RUN(NAME test_tuple_01 LABELS cpython llvm)
RUN(NAME test_tuple_02 LABELS cpython llvm)
RUN(NAME modules_01 LABELS cpython llvm)
Expand Down
56 changes: 56 additions & 0 deletions integration_tests/test_list_05.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
from ltypes import i32, f64

def check_list_of_tuples(l: list[tuple[i32, f64, str]], sign: i32):
size: i32 = len(l)
i: i32
t: tuple[i32, f64, str]
string: str

for i in range(size):
t = l[i]
string = str(sign * i) + "_str"
assert t[0] == sign * i
assert l[i][0] == sign * i

assert t[1] == float(sign * i)
assert l[i][1] == float(sign * i)

assert t[2] == string
assert l[i][2] == string

def test_list_of_tuples():
l1: list[tuple[i32, f64, str]] = []
t: tuple[i32, f64, str]
size: i32 = 20
i: i32
string: str

for i in range(size):
t = (i, float(i), str(i) + "_str")
l1.append(t)

check_list_of_tuples(l1, 1)

for i in range(size//2):
l1.remove(l1[len(l1) - 1])

t = l1[len(l1) - 1]
assert t[0] == size//2 - 1
assert t[1] == size//2 - 1
assert t[2] == str(size//2 - 1) + "_str"

for i in range(size//2, size):
string = str(i) + "_str"
t = (i, float(i), string)
l1.insert(i, t)

check_list_of_tuples(l1, 1)

for i in range(size):
string = str(-i) + "_str"
t = (-i, float(-i), string)
l1[i] = t

check_list_of_tuples(l1, -1)

test_list_of_tuples()
64 changes: 64 additions & 0 deletions integration_tests/test_list_06.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
from ltypes import i32, f64
from copy import deepcopy

def check_mat_and_vec(mat: list[list[f64]], vec: list[f64]):
rows: i32 = len(mat)
cols: i32 = len(vec)
i: i32
j: i32

for i in range(rows):
for j in range(cols):
assert mat[i][j] == float(i + j)

for i in range(cols):
assert vec[i] == 2 * float(i)

def test_list_of_lists():
tensors: list[list[list[list[f64]]]] = []
tensor: list[list[list[f64]]] = []
mat: list[list[f64]] = []
vec: list[f64] = []
rows: i32 = 10
cols: i32 = 5
i: i32
j: i32
k: i32
l: i32

for i in range(rows):
for j in range(cols):
vec.append(float(i + j))
mat.append(deepcopy(vec))
vec.clear()

for i in range(cols):
vec.append(2 * float(i))

check_mat_and_vec(mat, vec)

for k in range(rows):
tensor.append(deepcopy(mat))
for i in range(rows):
for j in range(cols):
mat[i][j] += float(1)

for k in range(rows):
for i in range(rows):
for j in range(cols):
assert mat[i][j] - tensor[k][i][j] == rows - k

for l in range(2 * rows):
tensors.append(deepcopy(tensor))
for i in range(rows):
for j in range(rows):
for k in range(cols):
tensor[i][j][k] += float(1)

for l in range(2 * rows):
for i in range(rows):
for j in range(rows):
for k in range(cols):
assert tensor[i][j][k] - tensors[l][i][j][k] == 2 * rows - l

test_list_of_lists()
67 changes: 67 additions & 0 deletions integration_tests/test_list_07.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
from ltypes import c64, i32
from copy import deepcopy

def test_tuple_with_lists():
mat: list[list[c64]] = []
vec: list[c64] = []
tensor: tuple[list[list[c64]], list[c64]]
tensors: list[tuple[list[list[c64]], list[c64]]] = []
i: i32
j: i32
k: i32
l: i32
rows: i32 = 10
cols: i32 = 5

for i in range(rows):
for j in range(cols):
vec.append(complex(i + j, 0))
mat.append(deepcopy(vec))
vec.clear()

for i in range(cols):
vec.append(complex(2 * i, 0))

for i in range(rows):
for j in range(cols):
assert mat[i][j] - vec[j] == i - j

tensor = (deepcopy(mat), deepcopy(vec))

for i in range(rows):
for j in range(cols):
mat[i][j] += complex(0, 3.0)

for i in range(cols):
vec[i] += complex(0, 2.0)

for i in range(rows):
for j in range(cols):
assert tensor[0][i][j] - mat[i][j] == -complex(0, 3.0)

for i in range(cols):
assert tensor[1][i] - vec[i] == -complex(0, 2.0)

tensor = (deepcopy(mat), deepcopy(vec))

for k in range(2 * rows):
tensors.append(deepcopy(tensor))
for i in range(rows):
for j in range(cols):
mat[i][j] += complex(1.0, 2.0)

for i in range(cols):
vec[i] += complex(1.0, 2.0)

tensor = (deepcopy(mat), deepcopy(vec))

for k in range(2 * rows):
for i in range(rows):
for j in range(cols):
assert tensors[k][0][i][j] - mat[i][j] == -(2 * rows - k) * complex(1.0, 2.0)

for k in range(2 * rows):
for i in range(cols):
assert tensors[k][1][i] - vec[i] == -(2 * rows - k) * complex(1.0, 2.0)

test_tuple_with_lists()
1 change: 1 addition & 0 deletions src/libasr/ASR.asdl
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ stmt
| SetRemove(expr a, expr ele)
| ListInsert(expr a, expr pos, expr ele)
| ListRemove(expr a, expr ele)
| ListClear(expr a)
| DictInsert(expr a, expr key, expr value)


Expand Down
69 changes: 49 additions & 20 deletions src/libasr/codegen/asr_to_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
ptr_loads(2),
is_assignment_target(false)
{
llvm_utils->tuple_api = tuple_api.get();
llvm_utils->list_api = list_api.get();
}

llvm::Value* CreateLoad(llvm::Value *x) {
Expand Down Expand Up @@ -1147,7 +1149,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
this->visit_expr(*x.m_args[i]);
llvm::Value* item = tmp;
llvm::Value* pos = llvm::ConstantInt::get(context, llvm::APInt(32, i));
list_api->write_item(const_list, pos, item);
list_api->write_item(const_list, pos, item, list_type->m_type, *module);
}
ptr_loads = ptr_loads_copy;
tmp = const_list;
Expand Down Expand Up @@ -1203,31 +1205,34 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}

void visit_ListAppend(const ASR::ListAppend_t& x) {
ASR::List_t* asr_list = ASR::down_cast<ASR::List_t>(ASRUtils::expr_type(x.m_a));
uint64_t ptr_loads_copy = ptr_loads;
ptr_loads = 0;
this->visit_expr(*x.m_a);
ptr_loads = ptr_loads_copy;
llvm::Value* plist = tmp;

ptr_loads = !LLVM::is_llvm_struct(asr_list->m_type);
this->visit_expr_wrapper(x.m_ele, true);
llvm::Value *item = tmp;
ptr_loads = ptr_loads_copy;

ASR::List_t* asr_list = ASR::down_cast<ASR::List_t>(ASRUtils::expr_type(x.m_a));
std::string type_code = ASRUtils::get_type_code(asr_list->m_type);
list_api->append(plist, item, *module, type_code);
list_api->append(plist, item, asr_list->m_type, *module);
}

void visit_ListItem(const ASR::ListItem_t& x) {
ASR::ttype_t* el_type = ASRUtils::get_contained_type(
ASRUtils::expr_type(x.m_a));
uint64_t ptr_loads_copy = ptr_loads;
ptr_loads = 0;
this->visit_expr(*x.m_a);
ptr_loads = ptr_loads_copy;
llvm::Value* plist = tmp;

ptr_loads = 1;
this->visit_expr_wrapper(x.m_pos, true);
ptr_loads = ptr_loads_copy;
llvm::Value *pos = tmp;

tmp = list_api->read_item(plist, pos);
tmp = list_api->read_item(plist, pos, LLVM::is_llvm_struct(el_type));
}

void visit_ListLen(const ASR::ListLen_t& x) {
Expand All @@ -1244,36 +1249,47 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
}

void visit_ListInsert(const ASR::ListInsert_t& x) {
ASR::List_t* asr_list = ASR::down_cast<ASR::List_t>(
ASRUtils::expr_type(x.m_a));
uint64_t ptr_loads_copy = ptr_loads;
ptr_loads = 0;
this->visit_expr(*x.m_a);
ptr_loads = ptr_loads_copy;
llvm::Value* plist = tmp;

ptr_loads = 1;
this->visit_expr_wrapper(x.m_pos, true);
llvm::Value *pos = tmp;

ptr_loads = !LLVM::is_llvm_struct(asr_list->m_type);
this->visit_expr_wrapper(x.m_ele, true);
llvm::Value *item = tmp;
ptr_loads = ptr_loads_copy;

ASR::List_t* asr_list = ASR::down_cast<ASR::List_t>(
ASRUtils::expr_type(x.m_a));
std::string type_code = ASRUtils::get_type_code(asr_list->m_type);

list_api->insert_item(plist, pos, item, *module, type_code);
list_api->insert_item(plist, pos, item, asr_list->m_type, *module);
}

void visit_ListRemove(const ASR::ListRemove_t& x) {
ASR::ttype_t* asr_el_type = ASRUtils::get_contained_type(ASRUtils::expr_type(x.m_a));
uint64_t ptr_loads_copy = ptr_loads;
ptr_loads = 0;
this->visit_expr(*x.m_a);
ptr_loads = ptr_loads_copy;
llvm::Value* plist = tmp;

ptr_loads = !LLVM::is_llvm_struct(asr_el_type);
this->visit_expr_wrapper(x.m_ele, true);
ptr_loads = ptr_loads_copy;
llvm::Value *item = tmp;
list_api->remove(plist, item, asr_el_type->type, *module);
list_api->remove(plist, item, asr_el_type, *module);
}

void visit_ListClear(const ASR::ListClear_t& x) {
uint64_t ptr_loads_copy = ptr_loads;
ptr_loads = 0;
this->visit_expr(*x.m_a);
llvm::Value* plist = tmp;
ptr_loads = ptr_loads_copy;

list_api->list_clear(plist);
}

void visit_TupleLen(const ASR::TupleLen_t& x) {
Expand All @@ -1291,7 +1307,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
this->visit_expr_wrapper(x.m_pos, true);
llvm::Value *pos = tmp;

tmp = tuple_api->read_item(ptuple, pos);
tmp = tuple_api->read_item(ptuple, pos, LLVM::is_llvm_struct(x.m_type));
}

void visit_ArrayItem(const ASR::ArrayItem_t& x) {
Expand Down Expand Up @@ -1838,7 +1854,9 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
a_kind);
std::string el_type_code = ASRUtils::get_type_code(asr_list->m_type);
int32_t type_size = -1;
if( ASR::is_a<ASR::Character_t>(*asr_list->m_type) ) {
if( LLVM::is_llvm_struct(asr_list->m_type) ||
ASR::is_a<ASR::Character_t>(*asr_list->m_type) ||
ASR::is_a<ASR::Complex_t>(*asr_list->m_type) ) {
llvm::DataLayout data_layout(module.get());
type_size = data_layout.getTypeAllocSize(el_llvm_type);
} else {
Expand Down Expand Up @@ -2218,8 +2236,17 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
is_malloc_array_type,
is_list, m_dims, n_dims,
a_kind);
int32_t type_size = -1;
if( LLVM::is_llvm_struct(asr_list->m_type) ||
ASR::is_a<ASR::Character_t>(*asr_list->m_type) ||
ASR::is_a<ASR::Complex_t>(*asr_list->m_type) ) {
llvm::DataLayout data_layout(module.get());
type_size = data_layout.getTypeAllocSize(el_llvm_type);
} else {
type_size = a_kind;
}
std::string el_type_code = ASRUtils::get_type_code(asr_list->m_type);
type = list_api->get_list_type(el_llvm_type, el_type_code, a_kind)->getPointerTo();
type = list_api->get_list_type(el_llvm_type, el_type_code, type_size)->getPointerTo();
break;
}
default :
Expand Down Expand Up @@ -2943,7 +2970,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
ASR::List_t* value_asr_list = ASR::down_cast<ASR::List_t>(
ASRUtils::expr_type(x.m_value));
std::string value_type_code = ASRUtils::get_type_code(value_asr_list->m_type);
list_api->list_deepcopy(value_list, target_list, value_type_code, *module);
list_api->list_deepcopy(value_list, target_list,
value_asr_list, *module);
return ;
} else if( is_target_tuple && is_value_tuple ) {
uint64_t ptr_loads_copy = ptr_loads;
Expand Down Expand Up @@ -2981,7 +3009,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
ASR::Tuple_t* value_tuple_type = ASR::down_cast<ASR::Tuple_t>(asr_value_type);
std::string type_code = ASRUtils::get_type_code(value_tuple_type->m_type,
value_tuple_type->n_type);
tuple_api->tuple_deepcopy(value_tuple, target_tuple, type_code);
tuple_api->tuple_deepcopy(value_tuple, target_tuple,
value_tuple_type, *module);
}
}
return ;
Expand Down
Loading