Skip to content

Commit 7679ab1

Browse files
kmr-srbhubaidsk
authored andcommitted
Add compile-time support for dict.keys (lcompilers#2660)
* Implement `dict.keys` for `DictConstant` * Tests: Add tests and update references * Tests: Update test * Uncomment check for modifying attributes * Tests: Update test references * Delete tests/reference/asr-func_04-eef2656.stdout * Style changes Co-authored-by: Shaikh Ubaid <[email protected]> * Style changes Co-authored-by: Shaikh Ubaid <[email protected]> * Tests: Move `print` before `assert` --------- Co-authored-by: Shaikh Ubaid <[email protected]>
1 parent 38a080a commit 7679ab1

File tree

3 files changed

+46
-4
lines changed

3 files changed

+46
-4
lines changed

integration_tests/test_dict_keys_values.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,27 @@ def test_dict_keys_values():
5151
assert v2_copy[j] == d2[str(i)]
5252
assert key_count == 1
5353

54+
55+
# dict.keys on dict constant
56+
print({1: "a"}.keys())
57+
assert len({1: "a"}.keys()) == 1
58+
59+
print({"a": 1, "b": 2, "c": 3}.keys())
60+
assert len({"a": 1, "b": 2, "c": 3}.keys()) == 3
61+
62+
print({1: [1, 2, 3], 2: [4, 5, 6], 3: [7, 8, 9]}.keys())
63+
assert len({1: [1, 2, 3], 2: [4, 5, 6], 3: [7, 8, 9]}.keys()) == 3
64+
65+
print({(1, 2): "a", (3, 4): "b", (5, 6): "c"}.keys())
66+
assert len({(1, 2): "a", (3, 4): "b", (5, 6): "c"}.keys()) == 3
67+
68+
k_1: list[str] = {"list1": [1, 2, 3], "list2": [4, 5, 6], "list3": [7, 8, 9]}.keys()
69+
print(k_1)
70+
assert len(k_1) == 3
71+
72+
k_2: list[tuple[i32, i32]] = {(1, 2): "a", (3, 4): "b", (5, 6): "c"}.keys()
73+
print(k_2)
74+
assert len(k_2) == 3
75+
76+
5477
test_dict_keys_values()

src/libasr/pass/intrinsic_functions.h

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4734,10 +4734,15 @@ static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag:
47344734
x.base.base.loc, diagnostics);
47354735
}
47364736

4737-
static inline ASR::expr_t *eval_dict_keys(Allocator &/*al*/,
4738-
const Location &/*loc*/, ASR::ttype_t *, Vec<ASR::expr_t*>& /*args*/, diag::Diagnostics& /*diag*/) {
4739-
// TODO: To be implemented for DictConstant expression
4740-
return nullptr;
4737+
static inline ASR::expr_t *eval_dict_keys(Allocator &al,
4738+
const Location &loc, ASR::ttype_t *t, Vec<ASR::expr_t*>& args, diag::Diagnostics& /*diag*/) {
4739+
if (args[0] == nullptr) {
4740+
return nullptr;
4741+
}
4742+
ASR::DictConstant_t* cdict = ASR::down_cast<ASR::DictConstant_t>(args[0]);
4743+
4744+
return ASRUtils::EXPR(ASR::make_ListConstant_t(al, loc,
4745+
cdict->m_keys, cdict->n_keys, t));
47414746
}
47424747

47434748
static inline ASR::asr_t* create_DictKeys(Allocator& al, const Location& loc,

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7689,6 +7689,20 @@ we will have to use something else.
76897689
}
76907690
}
76917691
}
7692+
} else if (AST::is_a<AST::Dict_t>(*at->m_value)) {
7693+
AST::Dict_t* cdict = AST::down_cast<AST::Dict_t>(at->m_value);
7694+
visit_Dict(*cdict);
7695+
if (tmp == nullptr) {
7696+
throw SemanticError("cannot call " + std::string(at->m_attr) + " on an empty dict" , loc);
7697+
}
7698+
ASR::expr_t* dict_expr = ASR::down_cast<ASR::expr_t>(tmp);
7699+
Vec<ASR::expr_t*> eles;
7700+
eles.reserve(al, args.size());
7701+
for (size_t i = 0; i < args.size(); i++) {
7702+
eles.push_back(al, args[i].m_value);
7703+
}
7704+
handle_builtin_attribute(dict_expr, at->m_attr, loc, eles);
7705+
return;
76927706
} else {
76937707
throw SemanticError("Only Name type and constant integers supported in Call", loc);
76947708
}

0 commit comments

Comments
 (0)