FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Implement `reversed(seq)` by kmr-srbh · Pull Request #2644 · lcompilers/lpython · GitHub

Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension .cpp  (1) .h  (2) .py  (1) .txt  (1) All 4 file types selected
Viewed files
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Unified
Split
Hide whitespace
Diff view
Unified
Split
Hide whitespace
1 change: 1 addition & 0 deletions integration_tests/CMakeLists.txt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,7 @@ RUN(NAME callback_04 IMPORT_PATH .. LABELS cpython)
RUN(NAME intrinsics_01 LABELS cpython llvm NOFAST) # any
RUN(NAME intrinsics_02 LABELS cpython llvm c) # floordiv
RUN(NAME test_builtin_type LABELS cpython llvm c) # type
RUN(NAME test_builtin_reversed LABELS llvm) # reversed

# lpython decorator
RUN(NAME lpython_decorator_01 LABELS cpython)
Expand Down
40 changes: 40 additions & 0 deletions integration_tests/test_builtin_reversed.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from lpython import i32, f64


def test_builtin_reversed():
# list of strings
alphabets: list[str] = ["a", "b", "c", "d", "e"]

reversed_alphabets: list[str] = reversed(alphabets)
print(reversed_alphabets)
assert reversed_alphabets == ["e", "d", "c", "b", "a"]

# list of numbers
numbers: list[i32] = [1, 2, 3, 4, 5]

reversed_numbers: list[i32] = reversed(numbers)
print(reversed_numbers)
assert reversed_numbers == [5, 4, 3, 2, 1]

# list returned through function call
alphabet_dictionary: dict[str, i32] = {
"a": 1,
"b": 2,
"c": 3,
"d": 4,
"e": 5,
}
reversed_keys: list[str] = reversed(alphabet_dictionary.keys())
print(reversed_keys)

assert reversed_keys == ["e", "d", "c", "b", "a"]

# list of another object
points: list[tuple[f64, f64]] = [(1.0, 0.0), (2.3, 5.9), (78.1, 23.2)]
reversed_points: list[tuple[f64, f64]] = reversed(points)
print(reversed_points)

assert reversed_points == [(78.1, 23.2), (2.3, 5.9), (1.0, 0.0)]


test_builtin_reversed()
10 changes: 8 additions & 2 deletions src/libasr/codegen/asr_to_llvm.cpp
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -1792,7 +1792,7 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
tmp = builder->CreateFSub(exp, one);
}

void generate_ListReverse(ASR::expr_t* m_arg) {
void generate_ListReverse(ASR::expr_t* m_arg, bool is_intrinsic_function) {
ASR::ttype_t* asr_el_type = ASRUtils::get_contained_type(ASRUtils::expr_type(m_arg));
int64_t ptr_loads_copy = ptr_loads;
ptr_loads = 0;
Expand All @@ -1802,6 +1802,8 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
ptr_loads = !LLVM::is_llvm_struct(asr_el_type);
ptr_loads = ptr_loads_copy;
list_api->reverse(plist, *module);

if (is_intrinsic_function) tmp = plist;
}

void generate_ListPop_0(ASR::expr_t* m_arg) {
Expand Down Expand Up @@ -1954,8 +1956,12 @@ class ASRToLLVMVisitor : public ASR::BaseVisitor<ASRToLLVMVisitor>
generate_ListIndex(m_arg, m_ele, m_start, m_end);
break ;
}
case ASRUtils::IntrinsicElementalFunctions::Reversed: {
generate_ListReverse(x.m_args[0], true);
break;
}
case ASRUtils::IntrinsicElementalFunctions::ListReverse: {
generate_ListReverse(x.m_args[0]);
generate_ListReverse(x.m_args[0], false);
break;
}
case ASRUtils::IntrinsicElementalFunctions::ListPop: {
Expand Down
6 changes: 6 additions & 0 deletions src/libasr/pass/intrinsic_function_registry.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ namespace ASRUtils {
inline std::string get_intrinsic_name(int x) {
switch (x) {
INTRINSIC_NAME_CASE(ObjectType)
INTRINSIC_NAME_CASE(Reversed)
INTRINSIC_NAME_CASE(Kind)
INTRINSIC_NAME_CASE(Rank)
INTRINSIC_NAME_CASE(Sin)
Expand Down Expand Up @@ -172,6 +173,8 @@ namespace IntrinsicElementalFunctionRegistry {
verify_function>>& intrinsic_function_by_id_db = {
{static_cast<int64_t>(IntrinsicElementalFunctions::ObjectType),
{nullptr, &ObjectType::verify_args}},
{static_cast<int64_t>(IntrinsicElementalFunctions::Reversed),
{nullptr, &Reversed::verify_args}},
{static_cast<int64_t>(IntrinsicElementalFunctions::Gamma),
{&Gamma::instantiate_Gamma, &UnaryIntrinsicFunction::verify_args}},
{static_cast<int64_t>(IntrinsicElementalFunctions::Log10),
Expand Down Expand Up @@ -459,6 +462,8 @@ namespace IntrinsicElementalFunctionRegistry {
static const std::map<int64_t, std::string>& intrinsic_function_id_to_name = {
{static_cast<int64_t>(IntrinsicElementalFunctions::ObjectType),
"type"},
{static_cast<int64_t>(IntrinsicElementalFunctions::Reversed),
"reversed"},
{static_cast<int64_t>(IntrinsicElementalFunctions::Gamma),
"gamma"},
{static_cast<int64_t>(IntrinsicElementalFunctions::Log),
Expand Down Expand Up @@ -744,6 +749,7 @@ namespace IntrinsicElementalFunctionRegistry {
std::tuple<create_intrinsic_function,
eval_intrinsic_function>>& intrinsic_function_by_name_db = {
{"type", {&ObjectType::create_ObjectType, &ObjectType::eval_ObjectType}},
{"reversed", {&Reversed::create_Reversed, &Reversed::eval_Reversed}},
{"gamma", {&Gamma::create_Gamma, &Gamma::eval_Gamma}},
{"log", {&Log::create_Log, &Log::eval_Log}},
{"log10", {&Log10::create_Log10, &Log10::eval_Log10}},
Expand Down
42 changes: 42 additions & 0 deletions src/libasr/pass/intrinsic_functions.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ the code size.

enum class IntrinsicElementalFunctions : int64_t {
ObjectType,
Reversed,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Reversed returns an iterator, but does not actually reverse a list. I think we do not have support for iterators yet in LPython.

The approach in this PR reverses the entire list, which I think is not the correct approach.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

@Shaikh-Ubaid I return a reversed list using the approach used for dict.keys (#1881 (comment)) as we do not support iterators now.

Kind, // if kind is reordered, update `extract_kind` in `asr_utils.h`
Rank,
Sin,
Expand Down Expand Up @@ -568,6 +569,47 @@ namespace ObjectType {

} // namespace ObjectType

namespace Reversed {

static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag::Diagnostics& diagnostics) {
ASRUtils::require_impl(x.n_args == 1, "Call to reversed() must have atleast one argument",
x.base.base.loc, diagnostics);
ASR::ttype_t* arg_type = ASRUtils::expr_type(x.m_args[0]);
ASRUtils::require_impl(ASR::is_a<ASR::List_t>(*arg_type),
"Argument to reversed() must be of list type.",
x.base.base.loc, diagnostics);
}

static inline ASR::expr_t *eval_Reversed(Allocator &/*al*/,
const Location &/*loc*/, ASR::ttype_t */*t*/, Vec<ASR::expr_t*>& /*args*/, diag::Diagnostics& /*diag*/) {
// TODO: To be implemented for ListConstant expression
return nullptr;
}


static inline ASR::asr_t* create_Reversed(Allocator& al, const Location& loc,
Vec<ASR::expr_t*>& args,
diag::Diagnostics& diag) {
if (!ASR::is_a<ASR::List_t>(*ASRUtils::expr_type(args[0]))) {
append_error(diag,
"reversed() currently only accepts an object of type `list`", loc);
return nullptr;
}

Vec<ASR::expr_t*> arg_values;
arg_values.reserve(al, args.size());
for( size_t i = 0; i < args.size(); i++ ) {
arg_values.push_back(al, ASRUtils::expr_value(args[i]));
}
ASR::ttype_t *to_type = ASRUtils::expr_type(args[0]);
ASR::expr_t* compile_time_value = eval_Reversed(al, loc, to_type, arg_values, diag);
return ASR::make_IntrinsicElementalFunction_t(al, loc,
static_cast<int64_t>(IntrinsicElementalFunctions::Reversed),
args.p, args.n, 0, to_type, compile_time_value);
}

} // namespace Reversed

namespace Fix {
static inline ASR::expr_t *eval_Fix(Allocator &al, const Location &loc,
ASR::ttype_t *t, Vec<ASR::expr_t*>& args, diag::Diagnostics& /*diag*/) {
Expand Down

Back | FazBrowse Home | New Git URL