diff --git a/integration_tests/test_dict_keys_values.py b/integration_tests/test_dict_keys_values.py index e3c28b72d6..089eec236d 100644 --- a/integration_tests/test_dict_keys_values.py +++ b/integration_tests/test_dict_keys_values.py @@ -51,4 +51,27 @@ def test_dict_keys_values(): assert v2_copy[j] == d2[str(i)] assert key_count == 1 + + # dict.keys on dict constant + print({1: "a"}.keys()) + assert len({1: "a"}.keys()) == 1 + + print({"a": 1, "b": 2, "c": 3}.keys()) + assert len({"a": 1, "b": 2, "c": 3}.keys()) == 3 + + print({1: [1, 2, 3], 2: [4, 5, 6], 3: [7, 8, 9]}.keys()) + assert len({1: [1, 2, 3], 2: [4, 5, 6], 3: [7, 8, 9]}.keys()) == 3 + + print({(1, 2): "a", (3, 4): "b", (5, 6): "c"}.keys()) + assert len({(1, 2): "a", (3, 4): "b", (5, 6): "c"}.keys()) == 3 + + k_1: list[str] = {"list1": [1, 2, 3], "list2": [4, 5, 6], "list3": [7, 8, 9]}.keys() + print(k_1) + assert len(k_1) == 3 + + k_2: list[tuple[i32, i32]] = {(1, 2): "a", (3, 4): "b", (5, 6): "c"}.keys() + print(k_2) + assert len(k_2) == 3 + + test_dict_keys_values() diff --git a/src/libasr/pass/intrinsic_functions.h b/src/libasr/pass/intrinsic_functions.h index a78175bd28..71f644ba22 100644 --- a/src/libasr/pass/intrinsic_functions.h +++ b/src/libasr/pass/intrinsic_functions.h @@ -4734,10 +4734,15 @@ static inline void verify_args(const ASR::IntrinsicElementalFunction_t& x, diag: x.base.base.loc, diagnostics); } -static inline ASR::expr_t *eval_dict_keys(Allocator &/*al*/, - const Location &/*loc*/, ASR::ttype_t *, Vec& /*args*/, diag::Diagnostics& /*diag*/) { - // TODO: To be implemented for DictConstant expression - return nullptr; +static inline ASR::expr_t *eval_dict_keys(Allocator &al, + const Location &loc, ASR::ttype_t *t, Vec& args, diag::Diagnostics& /*diag*/) { + if (args[0] == nullptr) { + return nullptr; + } + ASR::DictConstant_t* cdict = ASR::down_cast(args[0]); + + return ASRUtils::EXPR(ASR::make_ListConstant_t(al, loc, + cdict->m_keys, cdict->n_keys, t)); } static inline ASR::asr_t* create_DictKeys(Allocator& al, const Location& loc, diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index d4509dd64a..571883a84e 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -7650,6 +7650,20 @@ we will have to use something else. } } } + } else if (AST::is_a(*at->m_value)) { + AST::Dict_t* cdict = AST::down_cast(at->m_value); + visit_Dict(*cdict); + if (tmp == nullptr) { + throw SemanticError("cannot call " + std::string(at->m_attr) + " on an empty dict" , loc); + } + ASR::expr_t* dict_expr = ASR::down_cast(tmp); + Vec eles; + eles.reserve(al, args.size()); + for (size_t i = 0; i < args.size(); i++) { + eles.push_back(al, args[i].m_value); + } + handle_builtin_attribute(dict_expr, at->m_attr, loc, eles); + return; } else { throw SemanticError("Only Name type and constant integers supported in Call", loc); }