Skip to content

Commit 5723ba1

Browse files
authored
Merge pull request #435 from Smit-create/dict_get
Add DictItem in ASR
2 parents ac438de + 85c8137 commit 5723ba1

12 files changed

+92
-7
lines changed

src/libasr/ASR.asdl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ expr
253253
| Cast(expr arg, cast_kind kind, ttype type, expr? value)
254254
| ComplexRe(expr arg, ttype type, expr? value)
255255
| ComplexIm(expr arg, ttype type, expr? value)
256+
| DictItem(symbol a, expr key, expr? default, ttype type)
256257

257258

258259
-- `len` in Character:

src/libasr/asr_utils.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ static inline ASR::ttype_t* expr_type(const ASR::expr_t *f)
128128
case ASR::exprType::Cast: { return ((ASR::Cast_t*)f)->m_type; }
129129
case ASR::exprType::ComplexRe: { return ((ASR::ComplexRe_t*)f)->m_type; }
130130
case ASR::exprType::ComplexIm: { return ((ASR::ComplexIm_t*)f)->m_type; }
131+
case ASR::exprType::DictItem: { return ((ASR::DictItem_t*)f)->m_type; }
131132
default : throw LFortranException("Not implemented");
132133
}
133134
}
@@ -284,6 +285,7 @@ static inline ASR::expr_t* expr_value(ASR::expr_t *f)
284285
case ASR::exprType::SetLen: { return ASR::down_cast<ASR::SetLen_t>(f)->m_value; }
285286
case ASR::exprType::ComplexRe: { return ASR::down_cast<ASR::ComplexRe_t>(f)->m_value; }
286287
case ASR::exprType::ComplexIm: { return ASR::down_cast<ASR::ComplexIm_t>(f)->m_value; }
288+
case ASR::exprType::DictItem: // Drop through
287289
case ASR::exprType::ArrayConstant: // Drop through
288290
case ASR::exprType::IntegerConstant: // Drop through
289291
case ASR::exprType::RealConstant: // Drop through

src/lpython/semantics/python_ast_to_asr.cpp

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2814,6 +2814,53 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
28142814
SymbolTable *symtab = current_scope;
28152815
while (symtab->parent != nullptr) symtab = symtab->parent;
28162816
if (symtab->scope.find(mod_name) == symtab->scope.end()) {
2817+
if (current_scope->scope.find(mod_name) != current_scope->scope.end()) {
2818+
// this case when we have variable and attribute
2819+
st = current_scope->scope[mod_name];
2820+
ASR::Variable_t *v = ASR::down_cast<ASR::Variable_t>(st);
2821+
ASR::ttype_t *type = v->m_type;
2822+
if (ASR::is_a<ASR::Dict_t>(*type)) {
2823+
if (call_name == "get") {
2824+
ASR::expr_t *def = nullptr;
2825+
if (args.size() > 2 || args.size() < 1) {
2826+
throw SemanticError("'get' takes atleast 1 and atmost 2 arguments",
2827+
x.base.base.loc);
2828+
}
2829+
ASR::ttype_t *key_type = ASR::down_cast<ASR::Dict_t>(type)->m_key_type;
2830+
ASR::ttype_t *value_type = ASR::down_cast<ASR::Dict_t>(type)->m_value_type;
2831+
if (args.size() == 2) {
2832+
def = args[1].m_value;
2833+
if (!ASRUtils::check_equal_type(ASRUtils::expr_type(def), value_type)) {
2834+
std::string vtype = ASRUtils::type_to_str_python(ASRUtils::expr_type(def));
2835+
std::string totype = ASRUtils::type_to_str_python(value_type);
2836+
diag.add(diag::Diagnostic(
2837+
"Type mismatch in get's default value, the types must be compatible",
2838+
diag::Level::Error, diag::Stage::Semantic, {
2839+
diag::Label("type mismatch (found: '" + vtype + "', expected: '" + totype + "')",
2840+
{def->base.loc})
2841+
})
2842+
);
2843+
throw SemanticAbort();
2844+
}
2845+
}
2846+
if (!ASRUtils::check_equal_type(ASRUtils::expr_type(args[0].m_value), key_type)) {
2847+
std::string ktype = ASRUtils::type_to_str_python(ASRUtils::expr_type(args[0].m_value));
2848+
std::string totype = ASRUtils::type_to_str_python(key_type);
2849+
diag.add(diag::Diagnostic(
2850+
"Type mismatch in get's key value, the types must be compatible",
2851+
diag::Level::Error, diag::Stage::Semantic, {
2852+
diag::Label("type mismatch (found: '" + ktype + "', expected: '" + totype + "')",
2853+
{args[0].m_value->base.loc})
2854+
})
2855+
);
2856+
throw SemanticAbort();
2857+
}
2858+
tmp = make_DictItem_t(al, x.base.base.loc, st, args[0].m_value, def,
2859+
value_type);
2860+
return;
2861+
}
2862+
}
2863+
}
28172864
throw SemanticError("module '" + mod_name + "' is not imported",
28182865
x.base.base.loc);
28192866
}

tests/dictionary1.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,11 @@ def test_dict_insert():
1616
y: dict[str, i32]
1717
y = {"a": -1, "b": -2}
1818
y["c"] = -3
19+
20+
21+
def test_dict_get():
22+
y: dict[str, i32]
23+
y = {"a": -1, "b": -2}
24+
x: i32
25+
x = y.get("a")
26+
x = y.get("a", 0)

tests/errors/test_dict3.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
def test_e1():
2+
y: dict[str, i32]
3+
y = {"a": -1, "b": -2}
4+
x: i32
5+
x = y.get(1)

tests/reference/asr-dictionary1-a105a36.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
"basename": "asr-dictionary1-a105a36",
33
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}",
44
"infile": "tests/dictionary1.py",
5-
"infile_hash": "de60b11cae2fca92d379d49e16dff8e844880a8d399d5ce663fef743",
5+
"infile_hash": "d24f9165c2fb6f0441d774936dc2dfce99a0fec7225713607806a19a",
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "asr-dictionary1-a105a36.stdout",
9-
"stdout_hash": "01abb24628bd259575ffe0e0290ef41bdd4c8899fb8ca4e9d35af443",
9+
"stdout_hash": "e7bc564ba9f0544a67c0ff05f0825f70f8e56872521068389dd9134e",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
(TranslationUnit (SymbolTable 1 {main_program: (Program (SymbolTable 4 {}) main_program [] []), test_Dict: (Subroutine (SymbolTable 2 {x: (Variable 2 x Local () () Default (Dict (Integer 4 []) (Integer 4 [])) Source Public Required .false.), y: (Variable 2 y Local () () Default (Dict (Character 1 -2 () []) (Integer 4 [])) Source Public Required .false.), z: (Variable 2 z Local () () Default (Integer 4 []) Source Public Required .false.)}) test_Dict [] [(= (Var 2 x) (DictConstant [(IntegerConstant 1 (Integer 4 [])) (IntegerConstant 3 (Integer 4 []))] [(IntegerConstant 2 (Integer 4 [])) (IntegerConstant 4 (Integer 4 []))] (Dict (Integer 4 []) (Integer 4 []))) ()) (= (Var 2 y) (DictConstant [(StringConstant "a" (Character 1 1 () [])) (StringConstant "b" (Character 1 1 () []))] [(UnaryOp USub (IntegerConstant 1 (Integer 4 [])) (Integer 4 []) (IntegerConstant -1 (Integer 4 []))) (UnaryOp USub (IntegerConstant 2 (Integer 4 [])) (Integer 4 []) (IntegerConstant -2 (Integer 4 [])))] (Dict (Character 1 1 () []) (Integer 4 []))) ()) (= (Var 2 z) (ArrayRef 2 y [(() (StringConstant "a" (Character 1 1 () [])) ())] (Integer 4 []) ()) ()) (= (Var 2 z) (ArrayRef 2 y [(() (StringConstant "b" (Character 1 1 () [])) ())] (Integer 4 []) ()) ()) (= (Var 2 z) (ArrayRef 2 x [(() (IntegerConstant 1 (Integer 4 [])) ())] (Integer 4 []) ()) ())] Source Public Implementation () .false. .false.), test_dict_insert: (Subroutine (SymbolTable 3 {y: (Variable 3 y Local () () Default (Dict (Character 1 -2 () []) (Integer 4 [])) Source Public Required .false.)}) test_dict_insert [] [(= (Var 3 y) (DictConstant [(StringConstant "a" (Character 1 1 () [])) (StringConstant "b" (Character 1 1 () []))] [(UnaryOp USub (IntegerConstant 1 (Integer 4 [])) (Integer 4 []) (IntegerConstant -1 (Integer 4 []))) (UnaryOp USub (IntegerConstant 2 (Integer 4 [])) (Integer 4 []) (IntegerConstant -2 (Integer 4 [])))] (Dict (Character 1 1 () []) (Integer 4 []))) ()) (DictInsert 3 y (StringConstant "c" (Character 1 1 () [])) (UnaryOp USub (IntegerConstant 3 (Integer 4 [])) (Integer 4 []) (IntegerConstant -3 (Integer 4 []))))] Source Public Implementation () .false. .false.)}) [])
1+
(TranslationUnit (SymbolTable 1 {main_program: (Program (SymbolTable 5 {}) main_program [] []), test_Dict: (Subroutine (SymbolTable 2 {x: (Variable 2 x Local () () Default (Dict (Integer 4 []) (Integer 4 [])) Source Public Required .false.), y: (Variable 2 y Local () () Default (Dict (Character 1 -2 () []) (Integer 4 [])) Source Public Required .false.), z: (Variable 2 z Local () () Default (Integer 4 []) Source Public Required .false.)}) test_Dict [] [(= (Var 2 x) (DictConstant [(IntegerConstant 1 (Integer 4 [])) (IntegerConstant 3 (Integer 4 []))] [(IntegerConstant 2 (Integer 4 [])) (IntegerConstant 4 (Integer 4 []))] (Dict (Integer 4 []) (Integer 4 []))) ()) (= (Var 2 y) (DictConstant [(StringConstant "a" (Character 1 1 () [])) (StringConstant "b" (Character 1 1 () []))] [(UnaryOp USub (IntegerConstant 1 (Integer 4 [])) (Integer 4 []) (IntegerConstant -1 (Integer 4 []))) (UnaryOp USub (IntegerConstant 2 (Integer 4 [])) (Integer 4 []) (IntegerConstant -2 (Integer 4 [])))] (Dict (Character 1 1 () []) (Integer 4 []))) ()) (= (Var 2 z) (ArrayRef 2 y [(() (StringConstant "a" (Character 1 1 () [])) ())] (Integer 4 []) ()) ()) (= (Var 2 z) (ArrayRef 2 y [(() (StringConstant "b" (Character 1 1 () [])) ())] (Integer 4 []) ()) ()) (= (Var 2 z) (ArrayRef 2 x [(() (IntegerConstant 1 (Integer 4 [])) ())] (Integer 4 []) ()) ())] Source Public Implementation () .false. .false.), test_dict_get: (Subroutine (SymbolTable 4 {x: (Variable 4 x Local () () Default (Integer 4 []) Source Public Required .false.), y: (Variable 4 y Local () () Default (Dict (Character 1 -2 () []) (Integer 4 [])) Source Public Required .false.)}) test_dict_get [] [(= (Var 4 y) (DictConstant [(StringConstant "a" (Character 1 1 () [])) (StringConstant "b" (Character 1 1 () []))] [(UnaryOp USub (IntegerConstant 1 (Integer 4 [])) (Integer 4 []) (IntegerConstant -1 (Integer 4 []))) (UnaryOp USub (IntegerConstant 2 (Integer 4 [])) (Integer 4 []) (IntegerConstant -2 (Integer 4 [])))] (Dict (Character 1 1 () []) (Integer 4 []))) ()) (= (Var 4 x) (DictItem 4 y (StringConstant "a" (Character 1 1 () [])) () (Integer 4 [])) ()) (= (Var 4 x) (DictItem 4 y (StringConstant "a" (Character 1 1 () [])) (IntegerConstant 0 (Integer 4 [])) (Integer 4 [])) ())] Source Public Implementation () .false. .false.), test_dict_insert: (Subroutine (SymbolTable 3 {y: (Variable 3 y Local () () Default (Dict (Character 1 -2 () []) (Integer 4 [])) Source Public Required .false.)}) test_dict_insert [] [(= (Var 3 y) (DictConstant [(StringConstant "a" (Character 1 1 () [])) (StringConstant "b" (Character 1 1 () []))] [(UnaryOp USub (IntegerConstant 1 (Integer 4 [])) (Integer 4 []) (IntegerConstant -1 (Integer 4 []))) (UnaryOp USub (IntegerConstant 2 (Integer 4 [])) (Integer 4 []) (IntegerConstant -2 (Integer 4 [])))] (Dict (Character 1 1 () []) (Integer 4 []))) ()) (DictInsert 3 y (StringConstant "c" (Character 1 1 () [])) (UnaryOp USub (IntegerConstant 3 (Integer 4 [])) (Integer 4 []) (IntegerConstant -3 (Integer 4 []))))] Source Public Implementation () .false. .false.)}) [])
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
{
2+
"basename": "asr-test_dict3-d28f38f",
3+
"cmd": "lpython --show-asr --no-color {infile} -o {outfile}",
4+
"infile": "tests/errors/test_dict3.py",
5+
"infile_hash": "c8930919a9c47244ed4c57c1235dd2000650eb61dbfb6f413ae934e0",
6+
"outfile": null,
7+
"outfile_hash": null,
8+
"stdout": null,
9+
"stdout_hash": null,
10+
"stderr": "asr-test_dict3-d28f38f.stderr",
11+
"stderr_hash": "e2cc26634c1ee7aeca96c006b3bd01205200e1a6187e01fde041c3b4",
12+
"returncode": 2
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
semantic error: Type mismatch in get's key value, the types must be compatible
2+
--> tests/errors/test_dict3.py:5:15
3+
|
4+
5 | x = y.get(1)
5+
| ^ type mismatch (found: 'i32', expected: 'str')

tests/reference/ast-dictionary1-1a7e00a.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
"basename": "ast-dictionary1-1a7e00a",
33
"cmd": "lpython --show-ast --no-color {infile} -o {outfile}",
44
"infile": "tests/dictionary1.py",
5-
"infile_hash": "de60b11cae2fca92d379d49e16dff8e844880a8d399d5ce663fef743",
5+
"infile_hash": "d24f9165c2fb6f0441d774936dc2dfce99a0fec7225713607806a19a",
66
"outfile": null,
77
"outfile_hash": null,
88
"stdout": "ast-dictionary1-1a7e00a.stdout",
9-
"stdout_hash": "a1ee1abcc12edf02f1947e80709e5515366025a7c13744b682e87fa9",
9+
"stdout_hash": "a4d907b481d700a454753881457ddb21264620b417ab442221241e1b",
1010
"stderr": null,
1111
"stderr_hash": null,
1212
"returncode": 0
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
(Module [(FunctionDef test_Dict ([] [] [] [] [] [] []) [(AnnAssign (Name x Store) (Subscript (Name dict Load) (Tuple [(Name i32 Load) (Name i32 Load)] Load) Load) () 1) (Assign [(Name x Store)] (Dict [(ConstantInt 1 ()) (ConstantInt 3 ())] [(ConstantInt 2 ()) (ConstantInt 4 ())]) ()) (AnnAssign (Name y Store) (Subscript (Name dict Load) (Tuple [(Name str Load) (Name i32 Load)] Load) Load) () 1) (Assign [(Name y Store)] (Dict [(ConstantStr "a" ()) (ConstantStr "b" ())] [(UnaryOp USub (ConstantInt 1 ())) (UnaryOp USub (ConstantInt 2 ()))]) ()) (AnnAssign (Name z Store) (Name i32 Load) () 1) (Assign [(Name z Store)] (Subscript (Name y Load) (ConstantStr "a" ()) Load) ()) (Assign [(Name z Store)] (Subscript (Name y Load) (ConstantStr "b" ()) Load) ()) (Assign [(Name z Store)] (Subscript (Name x Load) (ConstantInt 1 ()) Load) ())] [] () ()) (FunctionDef test_dict_insert ([] [] [] [] [] [] []) [(AnnAssign (Name y Store) (Subscript (Name dict Load) (Tuple [(Name str Load) (Name i32 Load)] Load) Load) () 1) (Assign [(Name y Store)] (Dict [(ConstantStr "a" ()) (ConstantStr "b" ())] [(UnaryOp USub (ConstantInt 1 ())) (UnaryOp USub (ConstantInt 2 ()))]) ()) (Assign [(Subscript (Name y Load) (ConstantStr "c" ()) Store)] (UnaryOp USub (ConstantInt 3 ())) ())] [] () ())] [])
1+
(Module [(FunctionDef test_Dict ([] [] [] [] [] [] []) [(AnnAssign (Name x Store) (Subscript (Name dict Load) (Tuple [(Name i32 Load) (Name i32 Load)] Load) Load) () 1) (Assign [(Name x Store)] (Dict [(ConstantInt 1 ()) (ConstantInt 3 ())] [(ConstantInt 2 ()) (ConstantInt 4 ())]) ()) (AnnAssign (Name y Store) (Subscript (Name dict Load) (Tuple [(Name str Load) (Name i32 Load)] Load) Load) () 1) (Assign [(Name y Store)] (Dict [(ConstantStr "a" ()) (ConstantStr "b" ())] [(UnaryOp USub (ConstantInt 1 ())) (UnaryOp USub (ConstantInt 2 ()))]) ()) (AnnAssign (Name z Store) (Name i32 Load) () 1) (Assign [(Name z Store)] (Subscript (Name y Load) (ConstantStr "a" ()) Load) ()) (Assign [(Name z Store)] (Subscript (Name y Load) (ConstantStr "b" ()) Load) ()) (Assign [(Name z Store)] (Subscript (Name x Load) (ConstantInt 1 ()) Load) ())] [] () ()) (FunctionDef test_dict_insert ([] [] [] [] [] [] []) [(AnnAssign (Name y Store) (Subscript (Name dict Load) (Tuple [(Name str Load) (Name i32 Load)] Load) Load) () 1) (Assign [(Name y Store)] (Dict [(ConstantStr "a" ()) (ConstantStr "b" ())] [(UnaryOp USub (ConstantInt 1 ())) (UnaryOp USub (ConstantInt 2 ()))]) ()) (Assign [(Subscript (Name y Load) (ConstantStr "c" ()) Store)] (UnaryOp USub (ConstantInt 3 ())) ())] [] () ()) (FunctionDef test_dict_get ([] [] [] [] [] [] []) [(AnnAssign (Name y Store) (Subscript (Name dict Load) (Tuple [(Name str Load) (Name i32 Load)] Load) Load) () 1) (Assign [(Name y Store)] (Dict [(ConstantStr "a" ()) (ConstantStr "b" ())] [(UnaryOp USub (ConstantInt 1 ())) (UnaryOp USub (ConstantInt 2 ()))]) ()) (AnnAssign (Name x Store) (Name i32 Load) () 1) (Assign [(Name x Store)] (Call (Attribute (Name y Load) get Load) [(ConstantStr "a" ())] []) ()) (Assign [(Name x Store)] (Call (Attribute (Name y Load) get Load) [(ConstantStr "a" ()) (ConstantInt 0 ())] []) ())] [] () ())] [])

tests/tests.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,4 +377,8 @@ asr = true
377377

378378
[[test]]
379379
filename = "errors/test_dict2.py"
380-
asr = true
380+
asr = true
381+
382+
[[test]]
383+
filename = "errors/test_dict3.py"
384+
asr = true

0 commit comments

Comments
 (0)