@@ -366,6 +366,14 @@ class CommonVisitor : public AST::BaseVisitor<Derived> {
366
366
367
367
368
368
ASR::asr_t *tmp;
369
+
370
+ /*
371
+ If `tmp` is not null, then `tmp_vec` is ignored and `tmp` is used as the only result (statement or
372
+ expression). If `tmp` is null, then `tmp_vec` is used to return any number of statements:
373
+ 0 (no statement returned), 1 (redundant, one should use `tmp` for that), 2, 3, ... etc.
374
+ */
375
+ std::vector<ASR::asr_t *> tmp_vec;
376
+
369
377
Allocator &al;
370
378
SymbolTable *current_scope;
371
379
// The current_module contains the current module that is being visited;
@@ -732,7 +740,7 @@ class CommonVisitor : public AST::BaseVisitor<Derived> {
732
740
if (ASR::is_a<ASR::Function_t>(*t)) {
733
741
new_call_name = (ASR::down_cast<ASR::Function_t>(t))->m_name ;
734
742
}
735
- return make_call_helper (al, t, current_scope, args, new_call_name, loc);
743
+ return make_call_helper (al, t, current_scope, args, new_call_name, loc);
736
744
}
737
745
if (ASR::down_cast<ASR::Function_t>(s)->m_return_var != nullptr ) {
738
746
ASR::ttype_t *a_type = nullptr ;
@@ -2421,7 +2429,7 @@ class SymbolTableVisitor : public CommonVisitor<SymbolTableVisitor> {
2421
2429
/* a_name */ s2c (al, sym_name),
2422
2430
/* a_args */ args.p ,
2423
2431
/* n_args */ args.size (),
2424
- /* a_type_params */ tps.p ,
2432
+ /* a_type_params */ tps.p ,
2425
2433
/* n_type_params */ tps.size (),
2426
2434
/* a_body */ nullptr ,
2427
2435
/* n_body */ 0 ,
@@ -2648,6 +2656,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
2648
2656
// The `body` Vec must already be reserved
2649
2657
void transform_stmts (Vec<ASR::stmt_t *> &body, size_t n_body, AST::stmt_t **m_body) {
2650
2658
tmp = nullptr ;
2659
+ tmp_vec.clear ();
2651
2660
Vec<ASR::stmt_t *>* current_body_copy = current_body;
2652
2661
current_body = &body;
2653
2662
for (size_t i=0 ; i<n_body; i++) {
@@ -2656,9 +2665,18 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
2656
2665
if (tmp != nullptr ) {
2657
2666
ASR::stmt_t * tmp_stmt = ASRUtils::STMT (tmp);
2658
2667
body.push_back (al, tmp_stmt);
2668
+ } else if (!tmp_vec.empty ()) {
2669
+ for (auto t: tmp_vec) {
2670
+ if (t != nullptr ) {
2671
+ ASR::stmt_t * tmp_stmt = ASRUtils::STMT (t);
2672
+ body.push_back (al, tmp_stmt);
2673
+ }
2674
+ }
2675
+ tmp_vec.clear ();
2659
2676
}
2660
2677
// To avoid last statement to be entered twice once we exit this node
2661
2678
tmp = nullptr ;
2679
+ tmp_vec.clear ();
2662
2680
}
2663
2681
current_body = current_body_copy;
2664
2682
}
@@ -2677,9 +2695,16 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
2677
2695
items.reserve (al, 4 );
2678
2696
for (size_t i=0 ; i<x.n_body ; i++) {
2679
2697
tmp = nullptr ;
2698
+ tmp_vec.clear ();
2680
2699
visit_stmt (*x.m_body [i]);
2681
2700
if (tmp) {
2682
2701
items.push_back (al, tmp);
2702
+ } else if (!tmp_vec.empty ()) {
2703
+ for (auto t: tmp_vec) {
2704
+ if (t) items.push_back (al, t);
2705
+ }
2706
+ // Ensure that statements in tmp_vec are used only once.
2707
+ tmp_vec.clear ();
2683
2708
}
2684
2709
}
2685
2710
// These global statements are added to the translation unit for now,
@@ -2782,10 +2807,21 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
2782
2807
}
2783
2808
2784
2809
void visit_Assign (const AST::Assign_t &x) {
2785
- ASR::expr_t *target;
2786
- if (x.n_targets == 1 ) {
2787
- if (AST::is_a<AST::Subscript_t>(*x.m_targets [0 ])) {
2788
- AST::Subscript_t *sb = AST::down_cast<AST::Subscript_t>(x.m_targets [0 ]);
2810
+ ASR::expr_t *target, *assign_value = nullptr , *tmp_value;
2811
+ this ->visit_expr (*x.m_value );
2812
+ if (tmp) {
2813
+ // This happens if `m.m_value` is `empty`, such as in:
2814
+ // a = empty(16)
2815
+ // We skip this statement for now, the array is declared
2816
+ // by the annotation.
2817
+ // TODO: enforce that empty(), ones(), zeros() is called
2818
+ // for every declaration.
2819
+ assign_value = ASRUtils::EXPR (tmp);
2820
+ }
2821
+ for (size_t i=0 ; i<x.n_targets ; i++) {
2822
+ tmp_value = assign_value;
2823
+ if (AST::is_a<AST::Subscript_t>(*x.m_targets [i])) {
2824
+ AST::Subscript_t *sb = AST::down_cast<AST::Subscript_t>(x.m_targets [i]);
2789
2825
if (AST::is_a<AST::Name_t>(*sb->m_value )) {
2790
2826
std::string name = AST::down_cast<AST::Name_t>(sb->m_value )->m_id ;
2791
2827
ASR::symbol_t *s = current_scope->get_symbol (name);
@@ -2799,8 +2835,6 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
2799
2835
// dict insert case;
2800
2836
this ->visit_expr (*sb->m_slice );
2801
2837
ASR::expr_t *key = ASRUtils::EXPR (tmp);
2802
- this ->visit_expr (*x.m_value );
2803
- ASR::expr_t *val = ASRUtils::EXPR (tmp);
2804
2838
ASR::ttype_t *key_type = ASR::down_cast<ASR::Dict_t>(type)->m_key_type ;
2805
2839
ASR::ttype_t *value_type = ASR::down_cast<ASR::Dict_t>(type)->m_value_type ;
2806
2840
if (!ASRUtils::check_equal_type (ASRUtils::expr_type (key), key_type)) {
@@ -2815,29 +2849,30 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
2815
2849
);
2816
2850
throw SemanticAbort ();
2817
2851
}
2818
- if (!ASRUtils::check_equal_type (ASRUtils::expr_type (val ), value_type)) {
2819
- std::string vtype = ASRUtils::type_to_str_python (ASRUtils::expr_type (val ));
2852
+ if (!ASRUtils::check_equal_type (ASRUtils::expr_type (tmp_value ), value_type)) {
2853
+ std::string vtype = ASRUtils::type_to_str_python (ASRUtils::expr_type (tmp_value ));
2820
2854
std::string totype = ASRUtils::type_to_str_python (value_type);
2821
2855
diag.add (diag::Diagnostic (
2822
2856
" Type mismatch in dictionary value, the types must be compatible" ,
2823
2857
diag::Level::Error, diag::Stage::Semantic, {
2824
2858
diag::Label (" type mismatch (found: '" + vtype + " ', expected: '" + totype + " ')" ,
2825
- {val ->base .loc })
2859
+ {tmp_value ->base .loc })
2826
2860
})
2827
2861
);
2828
2862
throw SemanticAbort ();
2829
2863
}
2830
2864
ASR::expr_t * se = ASR::down_cast<ASR::expr_t >(
2831
2865
ASR::make_Var_t (al, x.base .base .loc , s));
2832
- tmp = make_DictInsert_t (al, x.base .base .loc , se, key, val);
2833
- return ;
2866
+ tmp = nullptr ;
2867
+ tmp_vec.push_back (make_DictInsert_t (al, x.base .base .loc , se, key, tmp_value));
2868
+ continue ;
2834
2869
} else if (ASRUtils::is_immutable (type)) {
2835
2870
throw SemanticError (" '" + ASRUtils::type_to_str_python (type) + " ' object does not support"
2836
2871
" item assignment" , x.base .base .loc );
2837
2872
}
2838
2873
}
2839
- } else if (AST::is_a<AST::Attribute_t>(*x.m_targets [0 ])) {
2840
- AST::Attribute_t *attr = AST::down_cast<AST::Attribute_t>(x.m_targets [0 ]);
2874
+ } else if (AST::is_a<AST::Attribute_t>(*x.m_targets [i ])) {
2875
+ AST::Attribute_t *attr = AST::down_cast<AST::Attribute_t>(x.m_targets [i ]);
2841
2876
if (AST::is_a<AST::Name_t>(*attr->m_value )) {
2842
2877
std::string name = AST::down_cast<AST::Name_t>(attr->m_value )->m_id ;
2843
2878
ASR::symbol_t *s = current_scope->get_symbol (name);
@@ -2852,62 +2887,51 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
2852
2887
}
2853
2888
}
2854
2889
}
2855
- this ->visit_expr (*x.m_targets [0 ]);
2890
+ if (!tmp_value) continue ;
2891
+ this ->visit_expr (*x.m_targets [i]);
2856
2892
target = ASRUtils::EXPR (tmp);
2857
- } else {
2858
- throw SemanticError (" Assignment to multiple targets not supported" ,
2859
- x.base .base .loc );
2860
- }
2861
-
2862
- this ->visit_expr (*x.m_value );
2863
- if (tmp == nullptr ) {
2864
- // This happens if `m.m_value` is `empty`, such as in:
2865
- // a = empty(16)
2866
- // We skip this statement for now, the array is declared
2867
- // by the annotation.
2868
- // TODO: enforce that empty(), ones(), zeros() is called
2869
- // for every declaration.
2870
- tmp = nullptr ;
2871
- } else {
2872
- ASR::expr_t *value = ASRUtils::EXPR (tmp);
2873
2893
ASR::ttype_t *target_type = ASRUtils::expr_type (target);
2874
- ASR::ttype_t *value_type = ASRUtils::expr_type (value );
2894
+ ASR::ttype_t *value_type = ASRUtils::expr_type (tmp_value );
2875
2895
if ( ASR::is_a<ASR::Pointer_t>(*target_type) &&
2876
2896
ASR::is_a<ASR::Var_t>(*target) ) {
2877
- if ( !ASR::is_a<ASR::GetPointer_t>(*value ) ) {
2897
+ if ( !ASR::is_a<ASR::GetPointer_t>(*tmp_value ) ) {
2878
2898
throw SemanticError (" A pointer variable can only "
2879
2899
" be associated with the output "
2880
2900
" of pointer() call." ,
2881
- value ->base .loc );
2901
+ tmp_value ->base .loc );
2882
2902
}
2883
2903
if ( !ASRUtils::check_equal_type (target_type, value_type) ) {
2884
2904
throw SemanticError (" Casting not supported for different pointer types. Received "
2885
2905
" target pointer type, " + ASRUtils::type_to_str_python (target_type) +
2886
2906
" and value pointer type, " + ASRUtils::type_to_str_python (value_type),
2887
2907
x.base .base .loc );
2888
2908
}
2889
- tmp = ASR::make_Assignment_t (al, x.base .base .loc , target, value, nullptr );
2890
- return ;
2909
+ tmp = nullptr ;
2910
+ tmp_vec.push_back (ASR::make_Assignment_t (al, x.base .base .loc , target,
2911
+ tmp_value, nullptr ));
2912
+ continue ;
2891
2913
}
2892
-
2893
- cast_helper (target, value, true );
2894
- value_type = ASRUtils::expr_type (value);
2914
+ cast_helper (target, tmp_value, true );
2915
+ value_type = ASRUtils::expr_type (tmp_value);
2895
2916
if (!ASRUtils::check_equal_type (target_type, value_type)) {
2896
2917
std::string ltype = ASRUtils::type_to_str_python (target_type);
2897
2918
std::string rtype = ASRUtils::type_to_str_python (value_type);
2898
2919
diag.add (diag::Diagnostic (
2899
2920
" Type mismatch in assignment, the types must be compatible" ,
2900
2921
diag::Level::Error, diag::Stage::Semantic, {
2901
2922
diag::Label (" type mismatch ('" + ltype + " ' and '" + rtype + " ')" ,
2902
- {target->base .loc , value ->base .loc })
2923
+ {target->base .loc , tmp_value ->base .loc })
2903
2924
})
2904
2925
);
2905
2926
throw SemanticAbort ();
2906
2927
}
2907
2928
ASR::stmt_t *overloaded=nullptr ;
2908
- tmp = ASR::make_Assignment_t (al, x.base .base .loc , target, value,
2909
- overloaded);
2929
+ tmp = nullptr ;
2930
+ tmp_vec.push_back (ASR::make_Assignment_t (al, x.base .base .loc , target, tmp_value,
2931
+ overloaded));
2910
2932
}
2933
+ // to make sure that we add only those statements in tmp_vec
2934
+ tmp = nullptr ;
2911
2935
}
2912
2936
2913
2937
void visit_Assert (const AST::Assert_t &x) {
0 commit comments