diff --git a/grammar/ASR.asdl b/grammar/ASR.asdl index 3b4ac64312..f105bc1c56 100644 --- a/grammar/ASR.asdl +++ b/grammar/ASR.asdl @@ -210,6 +210,7 @@ expr | ConstantReal(float r, ttype type) | ConstantComplex(float re, float im, ttype type) | ConstantSet(expr* elements, ttype type) + | ConstantTuple(expr* elements, ttype type) | ConstantLogical(bool value, ttype type) | ConstantString(string s, ttype type) | ConstantDictionary(expr* keys, expr* values, ttype type) @@ -233,6 +234,7 @@ ttype | Character(int kind, int len, expr? len_expr, dimension* dims) | Logical(int kind, dimension* dims) | Set(ttype type) + | Tuple(ttype type) | Derived(symbol derived_type, dimension* dims) | Class(symbol class_type, dimension* dims) | Dict(ttype key_type, ttype value_type) diff --git a/src/lpython/semantics/python_ast_to_asr.cpp b/src/lpython/semantics/python_ast_to_asr.cpp index 8f28a18d50..a7e0a90eb6 100644 --- a/src/lpython/semantics/python_ast_to_asr.cpp +++ b/src/lpython/semantics/python_ast_to_asr.cpp @@ -573,6 +573,27 @@ class BodyVisitor : public CommonVisitor { list.size(), type); } + void visit_Tuple(const AST::Tuple_t &x) { + Vec tuple; + tuple.reserve(al, x.n_elts); + ASR::ttype_t *type = nullptr; + for (size_t i=0; ivisit_expr(*x.m_elts[i]); + ASR::expr_t *expr = ASRUtils::EXPR(tmp); + if (type == nullptr) { + type = ASRUtils::expr_type(expr); + } else { + if (!ASRUtils::check_equal_type(ASRUtils::expr_type(expr), type)) { + throw SemanticError("All Tuple elements must be of the same type for now", + x.base.base.loc); + } + } + tuple.push_back(al, expr); + } + ASR::ttype_t *tuple_type = ASRUtils::TYPE(ASR::make_Tuple_t(al, x.base.base.loc, type)); + tmp = ASR::make_ConstantTuple_t(al, x.base.base.loc, tuple.p, tuple.size(), tuple_type); + } + void visit_For(const AST::For_t &x) { this->visit_expr(*x.m_target); ASR::expr_t *target=ASRUtils::EXPR(tmp); diff --git a/src/runtime/lpython_parser.py b/src/runtime/lpython_parser.py index 23957899af..fa8d4e77b6 100644 --- a/src/runtime/lpython_parser.py +++ b/src/runtime/lpython_parser.py @@ -35,6 +35,8 @@ def visit_Constant(self, node): node.value.imag, node.kind) elif isinstance(node.value, dict): return python_ast.Dict(node.keys, node.values) + elif isinstance(node.value, tuple): + return python_ast.Tuple(node.elts) else: print(type(node.value)) raise Exception("Unsupported Constant type") diff --git a/tests/reference/asr-tuple1-09972ab.json b/tests/reference/asr-tuple1-09972ab.json new file mode 100644 index 0000000000..97dc6c2d3e --- /dev/null +++ b/tests/reference/asr-tuple1-09972ab.json @@ -0,0 +1,13 @@ +{ + "basename": "asr-tuple1-09972ab", + "cmd": "lpython --show-asr --no-color {infile} -o {outfile}", + "infile": "tests/tuple1.py", + "infile_hash": "c216176d4d1417b152919937341f86d003e29ee69ced98dff06293fa", + "outfile": null, + "outfile_hash": null, + "stdout": "asr-tuple1-09972ab.stdout", + "stdout_hash": "c75404eba3e5698ef6787f2d09e8421071515d847e16af38ff054c21", + "stderr": null, + "stderr_hash": null, + "returncode": 0 +} \ No newline at end of file diff --git a/tests/reference/asr-tuple1-09972ab.stdout b/tests/reference/asr-tuple1-09972ab.stdout new file mode 100644 index 0000000000..b6b6ec618d --- /dev/null +++ b/tests/reference/asr-tuple1-09972ab.stdout @@ -0,0 +1 @@ +(TranslationUnit (SymbolTable 1 {test_Tuple: (Subroutine (SymbolTable 2 {a: (Variable 2 a Local () () Default (Integer 4 []) Source Public Required .false.), b: (Variable 2 b Local () () Default (Integer 4 []) Source Public Required .false.), b1: (Variable 2 b1 Local () () Default (Integer 4 []) Source Public Required .false.)}) test_Tuple [] [(= (Var 2 a) (ConstantTuple [(ConstantInteger 1 (Integer 4 [])) (ConstantInteger 2 (Integer 4 [])) (ConstantInteger 3 (Integer 4 []))] (Tuple (Integer 4 []))) ()) (= (Var 2 a) (ConstantTuple [(UnaryOp USub (ConstantInteger 3 (Integer 4 [])) (Integer 4 []) (ConstantInteger -3 (Integer 4 []))) (UnaryOp USub (ConstantInteger 2 (Integer 4 [])) (Integer 4 []) (ConstantInteger -2 (Integer 4 []))) (UnaryOp USub (ConstantInteger 1 (Integer 4 [])) (Integer 4 []) (ConstantInteger -1 (Integer 4 [])))] (Tuple (Integer 4 []))) ()) (= (Var 2 a) (ConstantTuple [(ConstantString "a" (Character 1 1 () [])) (ConstantString "b" (Character 1 1 () [])) (ConstantString "c" (Character 1 1 () []))] (Tuple (Character 1 1 () []))) ()) (= (Var 2 b) (ArrayRef 2 a [(() (ConstantInteger 0 (Integer 4 [])) ())] (Integer 4 []) ()) ()) (= (ConstantTuple [(Var 2 b) (Var 2 b1)] (Tuple (Integer 4 []))) (ConstantTuple [(ArrayRef 2 a [(() (ConstantInteger 2 (Integer 4 [])) ())] (Integer 4 []) ()) (ArrayRef 2 a [(() (ConstantInteger 1 (Integer 4 [])) ())] (Integer 4 []) ())] (Tuple (Integer 4 []))) ())] Source Public Implementation () .false. .false.)}) []) diff --git a/tests/reference/ast-tuple1-2fb5396.json b/tests/reference/ast-tuple1-2fb5396.json new file mode 100644 index 0000000000..8c0a818ed0 --- /dev/null +++ b/tests/reference/ast-tuple1-2fb5396.json @@ -0,0 +1,13 @@ +{ + "basename": "ast-tuple1-2fb5396", + "cmd": "lpython --show-ast --no-color {infile} -o {outfile}", + "infile": "tests/tuple1.py", + "infile_hash": "c216176d4d1417b152919937341f86d003e29ee69ced98dff06293fa", + "outfile": null, + "outfile_hash": null, + "stdout": "ast-tuple1-2fb5396.stdout", + "stdout_hash": "e88991d4093266a2aad97d5d60c6cc9e1313417c791e3bcea8f7e0ea", + "stderr": null, + "stderr_hash": null, + "returncode": 0 +} \ No newline at end of file diff --git a/tests/reference/ast-tuple1-2fb5396.stdout b/tests/reference/ast-tuple1-2fb5396.stdout new file mode 100644 index 0000000000..f35dd98965 --- /dev/null +++ b/tests/reference/ast-tuple1-2fb5396.stdout @@ -0,0 +1 @@ +(Module [(FunctionDef test_Tuple ([] [] [] [] [] [] []) [(AnnAssign (Name a Store) (Name i32 Load) () 1) (AnnAssign (Name b Store) (Name i32 Load) () 1) (AnnAssign (Name b1 Store) (Name i32 Load) () 1) (Assign [(Name a Store)] (Tuple [(ConstantInt 1 ()) (ConstantInt 2 ()) (ConstantInt 3 ())] Load) ()) (Assign [(Name a Store)] (Tuple [(UnaryOp USub (ConstantInt 3 ())) (UnaryOp USub (ConstantInt 2 ())) (UnaryOp USub (ConstantInt 1 ()))] Load) ()) (Assign [(Name a Store)] (Tuple [(ConstantStr "a" ()) (ConstantStr "b" ()) (ConstantStr "c" ())] Load) ()) (Assign [(Name b Store)] (Subscript (Name a Load) (ConstantInt 0 ()) Load) ()) (Assign [(Tuple [(Name b Store) (Name b1 Store)] Store)] (Tuple [(Subscript (Name a Load) (ConstantInt 2 ()) Load) (Subscript (Name a Load) (ConstantInt 1 ()) Load)] Load) ())] [] () ())] []) diff --git a/tests/tests.toml b/tests/tests.toml index 293014ab1d..bfdf3b4bfa 100644 --- a/tests/tests.toml +++ b/tests/tests.toml @@ -28,6 +28,11 @@ filename = "list1.py" ast = true asr = true +[[test]] +filename = "tuple1.py" +ast = true +asr = true + [[test]] filename = "dictionary1.py" ast = true diff --git a/tests/tuple1.py b/tests/tuple1.py new file mode 100644 index 0000000000..89e68ae450 --- /dev/null +++ b/tests/tuple1.py @@ -0,0 +1,11 @@ +def test_Tuple(): + a: i32 + b: i32 + b1: i32 + + a = (1, 2, 3) + a = (-3, -2, -1) + a = ("a", "b", "c") + + b = a[0] + b, b1 = a[2], a[1]