@@ -893,6 +893,63 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
893
893
return true ;
894
894
}
895
895
896
+ int64_t find_argument_position_from_name (ASR::StructType_t* orig_struct, std::string arg_name) {
897
+ int64_t arg_position = -1 ;
898
+ for ( size_t i = 0 ; i < orig_struct->n_members ; i++ ) {
899
+ std::string original_arg_name = std::string (orig_struct->m_members [i]);
900
+ if ( original_arg_name == arg_name ) {
901
+ return i;
902
+ }
903
+ }
904
+ return arg_position;
905
+ }
906
+
907
+ void visit_expr_list (AST::expr_t ** pos_args, size_t n_pos_args,
908
+ AST::keyword_t * kwargs, size_t n_kwargs,
909
+ Vec<ASR::call_arg_t >& call_args_vec,
910
+ ASR::StructType_t* orig_struct, const Location &loc) {
911
+ LCOMPILERS_ASSERT (call_args_vec.reserve_called );
912
+
913
+ // Fill the whole call_args_vec with nullptr
914
+ // This is for error handling later on.
915
+ for ( size_t i = 0 ; i < n_pos_args + n_kwargs; i++ ) {
916
+ ASR::call_arg_t call_arg;
917
+ Location loc;
918
+ loc.first = loc.last = 1 ;
919
+ call_arg.m_value = nullptr ;
920
+ call_arg.loc = loc;
921
+ call_args_vec.push_back (al, call_arg);
922
+ }
923
+
924
+ // Now handle positional arguments in the following loop
925
+ for ( size_t i = 0 ; i < n_pos_args; i++ ) {
926
+ this ->visit_expr (*pos_args[i]);
927
+ ASR::expr_t * expr = ASRUtils::EXPR (tmp);
928
+ call_args_vec.p [i].loc = expr->base .loc ;
929
+ call_args_vec.p [i].m_value = expr;
930
+ }
931
+
932
+ // Now handle keyword arguments in the following loop
933
+ for ( size_t i = 0 ; i < n_kwargs; i++ ) {
934
+ this ->visit_expr (*kwargs[i].m_value );
935
+ ASR::expr_t * expr = ASRUtils::EXPR (tmp);
936
+ std::string arg_name = std::string (kwargs[i].m_arg );
937
+ int64_t arg_pos = find_argument_position_from_name (orig_struct, arg_name);
938
+ if ( arg_pos == -1 ) {
939
+ throw SemanticError (" Member '" + arg_name + " ' not found in struct" , kwargs[i].loc );
940
+ } else if (arg_pos >= (int64_t )call_args_vec.size ()) {
941
+ throw SemanticError (" Not enough arguments to " + std::string (orig_struct->m_name )
942
+ + " (), expected " + std::to_string (orig_struct->n_members ), loc);
943
+ }
944
+ if ( call_args_vec[arg_pos].m_value != nullptr ) {
945
+ throw SemanticError (std::string (orig_struct->m_name ) + " () got multiple values for argument '"
946
+ + arg_name + " '" , kwargs[i].loc );
947
+ }
948
+ call_args_vec.p [arg_pos].loc = expr->base .loc ;
949
+ call_args_vec.p [arg_pos].m_value = expr;
950
+ }
951
+ }
952
+
896
953
void visit_expr_list_with_cast (ASR::expr_t ** m_args, size_t n_args,
897
954
Vec<ASR::call_arg_t >& call_args_vec,
898
955
Vec<ASR::call_arg_t >& args,
@@ -1195,7 +1252,17 @@ class CommonVisitor : public AST::BaseVisitor<Struct> {
1195
1252
}
1196
1253
} else if (ASR::is_a<ASR::StructType_t>(*s)) {
1197
1254
ASR::StructType_t* StructType = ASR::down_cast<ASR::StructType_t>(s);
1198
- for ( size_t i = 0 ; i < std::min (args.size (), StructType->n_members ); i++ ) {
1255
+ if (n_kwargs > 0 ) {
1256
+ args.reserve (al, n_pos_args + n_kwargs);
1257
+ visit_expr_list (pos_args, n_pos_args, kwargs, n_kwargs,
1258
+ args, StructType, loc);
1259
+ }
1260
+
1261
+ if (args.size () > 0 && args.size () != StructType->n_members ) {
1262
+ throw SemanticError (" StructConstructor arguments do not match the number of struct members" , loc);
1263
+ }
1264
+
1265
+ for ( size_t i = 0 ; i < args.size (); i++ ) {
1199
1266
std::string member_name = StructType->m_members [i];
1200
1267
ASR::Variable_t* member_var = ASR::down_cast<ASR::Variable_t>(
1201
1268
StructType->m_symtab ->resolve_symbol (member_name));
@@ -6599,6 +6666,14 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
6599
6666
tmp = ASR::make_StringConstant_t (al, loc, s2c (al, s_var), str_type);
6600
6667
}
6601
6668
6669
+ void parse_args (const AST::Call_t &x, Vec<ASR::call_arg_t > &args) {
6670
+ // Keyword arguments handled in make_call_helper()
6671
+ if ( x.n_keywords == 0 ) {
6672
+ args.reserve (al, x.n_args );
6673
+ visit_expr_list (x.m_args , x.n_args , args);
6674
+ }
6675
+ }
6676
+
6602
6677
void visit_Call (const AST::Call_t &x) {
6603
6678
std::string call_name = " " ;
6604
6679
Vec<ASR::call_arg_t > args;
@@ -6612,14 +6687,9 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
6612
6687
tmp = nullptr ;
6613
6688
return ;
6614
6689
}
6615
- // Keyword arguments handled in make_call_helper
6616
- #define parse_args () if ( x.n_keywords == 0 ) { \
6617
- args.reserve (al, x.n_args ); \
6618
- visit_expr_list (x.m_args , x.n_args , args); \
6619
- } \
6620
6690
6621
6691
if (AST::is_a<AST::Attribute_t>(*x.m_func )) {
6622
- parse_args ()
6692
+ parse_args (x, args);
6623
6693
AST::Attribute_t *at = AST::down_cast<AST::Attribute_t>(x.m_func );
6624
6694
if (AST::is_a<AST::Name_t>(*at->m_value )) {
6625
6695
AST::Name_t *n = AST::down_cast<AST::Name_t>(at->m_value );
@@ -6788,7 +6858,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
6788
6858
// This will all be removed once we port it to intrinsic functions
6789
6859
// Intrinsic functions
6790
6860
if (call_name == " size" ) {
6791
- parse_args () ;
6861
+ parse_args (x, args); ;
6792
6862
if ( args.size () < 1 || args.size () > 2 ) {
6793
6863
throw SemanticError (" array accepts only 1 (arr) or 2 (arr, axis) arguments, got " +
6794
6864
std::to_string (args.size ()) + " arguments instead." ,
@@ -6820,7 +6890,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
6820
6890
tmp = nullptr ;
6821
6891
return ;
6822
6892
} else if (call_name == " callable" ) {
6823
- parse_args ()
6893
+ parse_args (x, args);
6824
6894
if (args.size () != 1 ) {
6825
6895
throw SemanticError (call_name + " () takes exactly one argument (" +
6826
6896
std::to_string (args.size ()) + " given)" , x.base .base .loc );
@@ -6836,13 +6906,13 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
6836
6906
tmp = ASR::make_LogicalConstant_t (al, x.base .base .loc , result, type);
6837
6907
return ;
6838
6908
} else if ( call_name == " pointer" ) {
6839
- parse_args ()
6909
+ parse_args (x, args);
6840
6910
ASR::ttype_t *type = ASRUtils::TYPE (ASR::make_Pointer_t (al, x.base .base .loc ,
6841
6911
ASRUtils::expr_type (args[0 ].m_value )));
6842
6912
tmp = ASR::make_GetPointer_t (al, x.base .base .loc , args[0 ].m_value , type, nullptr );
6843
6913
return ;
6844
6914
} else if ( call_name == " array" ) {
6845
- parse_args ()
6915
+ parse_args (x, args);
6846
6916
if ( args.size () != 1 ) {
6847
6917
throw SemanticError (" array accepts only 1 argument for now, got " +
6848
6918
std::to_string (args.size ()) + " arguments instead." ,
@@ -6862,7 +6932,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
6862
6932
}
6863
6933
return ;
6864
6934
} else if ( call_name == " deepcopy" ) {
6865
- parse_args ()
6935
+ parse_args (x, args);
6866
6936
if ( args.size () != 1 ) {
6867
6937
throw SemanticError (" deepcopy only accepts one argument, found " +
6868
6938
std::to_string (args.size ()) + " instead." ,
@@ -6921,7 +6991,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
6921
6991
call_name == " c32" ||
6922
6992
call_name == " c64"
6923
6993
) {
6924
- parse_args ()
6994
+ parse_args (x, args);
6925
6995
ASR::ttype_t * target_type = nullptr ;
6926
6996
if ( call_name == " i8" ) {
6927
6997
target_type = ASRUtils::TYPE (ASR::make_Integer_t (al, x.base .base .loc , 1 , nullptr , 0 ));
@@ -6953,7 +7023,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
6953
7023
tmp = (ASR::asr_t *) arg;
6954
7024
return ;
6955
7025
} else if (intrinsic_node_handler.is_present (call_name)) {
6956
- parse_args ()
7026
+ parse_args (x, args);
6957
7027
tmp = intrinsic_node_handler.get_intrinsic_node (call_name, al,
6958
7028
x.base .base .loc , args);
6959
7029
return ;
@@ -6965,7 +7035,7 @@ class BodyVisitor : public CommonVisitor<BodyVisitor> {
6965
7035
} // end of "comment"
6966
7036
}
6967
7037
6968
- parse_args ()
7038
+ parse_args (x, args);
6969
7039
tmp = make_call_helper (al, s, current_scope, args, call_name, x.base .base .loc ,
6970
7040
false , x.m_args , x.n_args , x.m_keywords , x.n_keywords );
6971
7041
}
0 commit comments