diff options
-rw-r--r-- | src/dict.c | 5 | ||||
-rw-r--r-- | src/evalbuffer.c | 6 | ||||
-rw-r--r-- | src/evalfunc.c | 217 | ||||
-rw-r--r-- | src/list.c | 4 | ||||
-rw-r--r-- | src/proto/evalbuffer.pro | 1 | ||||
-rw-r--r-- | src/proto/evalfunc.pro | 4 | ||||
-rw-r--r-- | src/proto/vim9instr.pro | 1 | ||||
-rw-r--r-- | src/proto/vim9type.pro | 8 | ||||
-rw-r--r-- | src/structs.h | 11 | ||||
-rw-r--r-- | src/testdir/test_vim9_assign.vim | 34 | ||||
-rw-r--r-- | src/testdir/test_vim9_builtin.vim | 14 | ||||
-rw-r--r-- | src/version.c | 2 | ||||
-rw-r--r-- | src/vim9cmds.c | 30 | ||||
-rw-r--r-- | src/vim9compile.c | 27 | ||||
-rw-r--r-- | src/vim9expr.c | 111 | ||||
-rw-r--r-- | src/vim9instr.c | 262 | ||||
-rw-r--r-- | src/vim9type.c | 92 |
17 files changed, 464 insertions, 365 deletions
diff --git a/src/dict.c b/src/dict.c index b3cdfd9b9e..27cde11a3f 100644 --- a/src/dict.c +++ b/src/dict.c @@ -109,6 +109,8 @@ dict_free_contents(dict_T *d) hashtab_free_contents(&d->dv_hashtab); free_type(d->dv_type); d->dv_type = NULL; + free_type(d->dv_decl_type); + d->dv_decl_type = NULL; } /* @@ -1354,8 +1356,7 @@ dict_filter_map( if (filtermap == FILTERMAP_MAP) { if (argtype != NULL && check_typval_arg_type( - argtype->tt_member, &newtv, - func_name, 0) == FAIL) + argtype->tt_member, &newtv, func_name, 0) == FAIL) { clear_tv(&newtv); break; diff --git a/src/evalbuffer.c b/src/evalbuffer.c index 37febe4059..58834785aa 100644 --- a/src/evalbuffer.c +++ b/src/evalbuffer.c @@ -807,12 +807,6 @@ f_getbufline(typval_T *argvars, typval_T *rettv) get_buffer_lines(buf, lnum, end, TRUE, rettv); } - type_T * -ret_f_getline(int argcount, type_T **argtypes UNUSED) -{ - return argcount == 1 ? &t_string : &t_list_string; -} - /* * "getline(lnum, [end])" function */ diff --git a/src/evalfunc.c b/src/evalfunc.c index e469520730..8cb2d755d5 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -195,7 +195,7 @@ static void f_xor(typval_T *argvars, typval_T *rettv); // Context passed to an arg_ function. typedef struct { int arg_count; // actual argument count - type_T **arg_types; // list of argument types + type2_T *arg_types; // list of argument types int arg_idx; // current argument index (first arg is zero) cctx_T *arg_cctx; } argcontext_T; @@ -203,7 +203,7 @@ typedef struct { // A function to check one argument type. The first argument is the type to // check. If needed, other argument types can be obtained with the context. // E.g. if "arg_idx" is 1, then (type - 1) is the first argument type. -typedef int (*argcheck_T)(type_T *, argcontext_T *); +typedef int (*argcheck_T)(type_T *, type_T *, argcontext_T *); /* * Call need_type() to check an argument type. @@ -225,7 +225,7 @@ check_arg_type( * Check "type" is a float or a number. */ static int -arg_float_or_nr(type_T *type, argcontext_T *context) +arg_float_or_nr(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -240,7 +240,7 @@ arg_float_or_nr(type_T *type, argcontext_T *context) * Check "type" is a number. */ static int -arg_number(type_T *type, argcontext_T *context) +arg_number(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { return check_arg_type(&t_number, type, context); } @@ -249,7 +249,7 @@ arg_number(type_T *type, argcontext_T *context) * Check "type" is a dict of 'any'. */ static int -arg_dict_any(type_T *type, argcontext_T *context) +arg_dict_any(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { return check_arg_type(&t_dict_any, type, context); } @@ -258,7 +258,7 @@ arg_dict_any(type_T *type, argcontext_T *context) * Check "type" is a list of 'any'. */ static int -arg_list_any(type_T *type, argcontext_T *context) +arg_list_any(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { return check_arg_type(&t_list_any, type, context); } @@ -267,7 +267,7 @@ arg_list_any(type_T *type, argcontext_T *context) * Check "type" is a list of numbers. */ static int -arg_list_number(type_T *type, argcontext_T *context) +arg_list_number(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { return check_arg_type(&t_list_number, type, context); } @@ -276,7 +276,7 @@ arg_list_number(type_T *type, argcontext_T *context) * Check "type" is a list of strings. */ static int -arg_list_string(type_T *type, argcontext_T *context) +arg_list_string(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { return check_arg_type(&t_list_string, type, context); } @@ -285,7 +285,7 @@ arg_list_string(type_T *type, argcontext_T *context) * Check "type" is a string. */ static int -arg_string(type_T *type, argcontext_T *context) +arg_string(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { return check_arg_type(&t_string, type, context); } @@ -294,7 +294,7 @@ arg_string(type_T *type, argcontext_T *context) * Check "type" is a blob */ static int -arg_blob(type_T *type, argcontext_T *context) +arg_blob(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { return check_arg_type(&t_blob, type, context); } @@ -303,7 +303,7 @@ arg_blob(type_T *type, argcontext_T *context) * Check "type" is a bool or number 0 or 1. */ static int -arg_bool(type_T *type, argcontext_T *context) +arg_bool(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { return check_arg_type(&t_bool, type, context); } @@ -312,7 +312,7 @@ arg_bool(type_T *type, argcontext_T *context) * Check "type" is a list of 'any' or a blob. */ static int -arg_list_or_blob(type_T *type, argcontext_T *context) +arg_list_or_blob(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -327,7 +327,7 @@ arg_list_or_blob(type_T *type, argcontext_T *context) * Check "type" is a string or a number */ static int -arg_string_or_nr(type_T *type, argcontext_T *context) +arg_string_or_nr(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -342,7 +342,7 @@ arg_string_or_nr(type_T *type, argcontext_T *context) * Check "type" is a buffer (string or a number) */ static int -arg_buffer(type_T *type, argcontext_T *context) +arg_buffer(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -357,7 +357,7 @@ arg_buffer(type_T *type, argcontext_T *context) * Check "type" is a buffer or a dict of any */ static int -arg_buffer_or_dict_any(type_T *type, argcontext_T *context) +arg_buffer_or_dict_any(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -373,7 +373,7 @@ arg_buffer_or_dict_any(type_T *type, argcontext_T *context) * Check "type" is a line (string or a number) */ static int -arg_lnum(type_T *type, argcontext_T *context) +arg_lnum(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -388,7 +388,7 @@ arg_lnum(type_T *type, argcontext_T *context) * Check "type" is a string or a list of strings. */ static int -arg_string_or_list_string(type_T *type, argcontext_T *context) +arg_string_or_list_string(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -411,7 +411,7 @@ arg_string_or_list_string(type_T *type, argcontext_T *context) * Check "type" is a string or a list of 'any' */ static int -arg_string_or_list_any(type_T *type, argcontext_T *context) +arg_string_or_list_any(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -426,7 +426,7 @@ arg_string_or_list_any(type_T *type, argcontext_T *context) * Check "type" is a string or a blob */ static int -arg_string_or_blob(type_T *type, argcontext_T *context) +arg_string_or_blob(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -441,7 +441,7 @@ arg_string_or_blob(type_T *type, argcontext_T *context) * Check "type" is a list of 'any' or a dict of 'any'. */ static int -arg_list_or_dict(type_T *type, argcontext_T *context) +arg_list_or_dict(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -456,7 +456,7 @@ arg_list_or_dict(type_T *type, argcontext_T *context) * Check "type" is a list of 'any' or a dict of 'any' or a blob. */ static int -arg_list_or_dict_or_blob(type_T *type, argcontext_T *context) +arg_list_or_dict_or_blob(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -472,7 +472,7 @@ arg_list_or_dict_or_blob(type_T *type, argcontext_T *context) * Check "type" is a list of 'any' or a dict of 'any' or a blob or a string. */ static int -arg_list_or_dict_or_blob_or_string(type_T *type, argcontext_T *context) +arg_list_or_dict_or_blob_or_string(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -489,7 +489,7 @@ arg_list_or_dict_or_blob_or_string(type_T *type, argcontext_T *context) * Check second argument of filter(): func must return a bool. */ static int -arg_filter_func(type_T *type, argcontext_T *context) +arg_filter_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_FUNC && !(type->tt_member->tt_type == VAR_BOOL @@ -507,7 +507,7 @@ arg_filter_func(type_T *type, argcontext_T *context) * Check second argument of map(). */ static int -arg_map_func(type_T *type, argcontext_T *context) +arg_map_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_FUNC && type->tt_member != &t_any @@ -515,12 +515,12 @@ arg_map_func(type_T *type, argcontext_T *context) { type_T *expected = NULL; - if (context->arg_types[0]->tt_type == VAR_LIST - || context->arg_types[0]->tt_type == VAR_DICT) - expected = context->arg_types[0]->tt_member; - else if (context->arg_types[0]->tt_type == VAR_STRING) + if (context->arg_types[0].type_curr->tt_type == VAR_LIST + || context->arg_types[0].type_curr->tt_type == VAR_DICT) + expected = context->arg_types[0].type_curr->tt_member; + else if (context->arg_types[0].type_curr->tt_type == VAR_STRING) expected = &t_string; - else if (context->arg_types[0]->tt_type == VAR_BLOB) + else if (context->arg_types[0].type_curr->tt_type == VAR_BLOB) expected = &t_number; if (expected != NULL) { @@ -539,7 +539,7 @@ arg_map_func(type_T *type, argcontext_T *context) * Also accept a number, one and zero are accepted. */ static int -arg_string_or_func(type_T *type, argcontext_T *context) +arg_string_or_func(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -557,7 +557,7 @@ arg_string_or_func(type_T *type, argcontext_T *context) * Check "type" is a list of 'any' or a blob or a string. */ static int -arg_string_list_or_blob(type_T *type, argcontext_T *context) +arg_string_list_or_blob(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -573,7 +573,7 @@ arg_string_list_or_blob(type_T *type, argcontext_T *context) * Check "type" is a job. */ static int -arg_job(type_T *type, argcontext_T *context) +arg_job(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { return check_arg_type(&t_job, type, context); } @@ -582,7 +582,7 @@ arg_job(type_T *type, argcontext_T *context) * Check "type" is a channel or a job. */ static int -arg_chan_or_job(type_T *type, argcontext_T *context) +arg_chan_or_job(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -594,13 +594,13 @@ arg_chan_or_job(type_T *type, argcontext_T *context) } /* - * Check "type" is the same type as the previous argument. + * Check "type" can be used as the type_decl of the previous argument. * Must not be used for the first argcheck_T entry. */ static int -arg_same_as_prev(type_T *type, argcontext_T *context) +arg_same_as_prev(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { - type_T *prev_type = context->arg_types[context->arg_idx - 1]; + type_T *prev_type = context->arg_types[context->arg_idx - 1].type_decl; return check_arg_type(prev_type, type, context); } @@ -611,11 +611,11 @@ arg_same_as_prev(type_T *type, argcontext_T *context) * Must not be used for the first argcheck_T entry. */ static int -arg_same_struct_as_prev(type_T *type, argcontext_T *context) +arg_same_struct_as_prev(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { - type_T *prev_type = context->arg_types[context->arg_idx - 1]; + type_T *prev_type = context->arg_types[context->arg_idx - 1].type_curr; - if (prev_type->tt_type != context->arg_types[context->arg_idx]->tt_type) + if (prev_type->tt_type != context->arg_types[context->arg_idx].type_curr->tt_type) return check_arg_type(prev_type, type, context); return OK; } @@ -625,9 +625,9 @@ arg_same_struct_as_prev(type_T *type, argcontext_T *context) * Must not be used for the first argcheck_T entry. */ static int -arg_item_of_prev(type_T *type, argcontext_T *context) +arg_item_of_prev(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { - type_T *prev_type = context->arg_types[context->arg_idx - 1]; + type_T *prev_type = context->arg_types[context->arg_idx - 1].type_curr; type_T *expected; if (prev_type->tt_type == VAR_LIST) @@ -645,7 +645,7 @@ arg_item_of_prev(type_T *type, argcontext_T *context) * Check "type" is a string or a number or a list */ static int -arg_str_or_nr_or_list(type_T *type, argcontext_T *context) +arg_str_or_nr_or_list(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -661,7 +661,7 @@ arg_str_or_nr_or_list(type_T *type, argcontext_T *context) * Check "type" is a dict of 'any' or a string */ static int -arg_dict_any_or_string(type_T *type, argcontext_T *context) +arg_dict_any_or_string(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -677,14 +677,14 @@ arg_dict_any_or_string(type_T *type, argcontext_T *context) * any) */ static int -arg_extend3(type_T *type, argcontext_T *context) +arg_extend3(type_T *type, type_T *decl_type, argcontext_T *context) { - type_T *first_type = context->arg_types[context->arg_idx - 2]; + type_T *first_type = context->arg_types[context->arg_idx - 2].type_curr; if (first_type->tt_type == VAR_LIST) - return arg_number(type, context); + return arg_number(type, decl_type, context); if (first_type->tt_type == VAR_DICT) - return arg_string(type, context); + return arg_string(type, decl_type, context); return OK; } @@ -693,7 +693,7 @@ arg_extend3(type_T *type, argcontext_T *context) * funcref) */ static int -arg_get1(type_T *type, argcontext_T *context) +arg_get1(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -713,7 +713,7 @@ arg_get1(type_T *type, argcontext_T *context) * blob or list or dict) */ static int -arg_len1(type_T *type, argcontext_T *context) +arg_len1(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -733,14 +733,14 @@ arg_len1(type_T *type, argcontext_T *context) * any) */ static int -arg_remove2(type_T *type, argcontext_T *context) +arg_remove2(type_T *type, type_T *decl_type, argcontext_T *context) { - type_T *first_type = context->arg_types[context->arg_idx - 1]; + type_T *first_type = context->arg_types[context->arg_idx - 1].type_curr; if (first_type->tt_type == VAR_LIST || first_type->tt_type == VAR_BLOB) - return arg_number(type, context); + return arg_number(type, decl_type, context); if (first_type->tt_type == VAR_DICT) - return arg_string_or_nr(type, context); + return arg_string_or_nr(type, decl_type, context); return OK; } @@ -749,7 +749,7 @@ arg_remove2(type_T *type, argcontext_T *context) * list or any) */ static int -arg_repeat1(type_T *type, argcontext_T *context) +arg_repeat1(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -767,7 +767,7 @@ arg_repeat1(type_T *type, argcontext_T *context) * or any) */ static int -arg_slice1(type_T *type, argcontext_T *context) +arg_slice1(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -785,7 +785,7 @@ arg_slice1(type_T *type, argcontext_T *context) * or any) */ static int -arg_count1(type_T *type, argcontext_T *context) +arg_count1(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -803,7 +803,7 @@ arg_count1(type_T *type, argcontext_T *context) * list or any) */ static int -arg_cursor1(type_T *type, argcontext_T *context) +arg_cursor1(type_T *type, type_T *decl_type UNUSED, argcontext_T *context) { if (type->tt_type == VAR_ANY || type->tt_type == VAR_UNKNOWN @@ -960,152 +960,158 @@ static argcheck_T arg24_match_func[] = {arg_string_or_list_any, arg_string, arg_ * Note that "argtypes" is NULL if "argcount" is zero. */ static type_T * -ret_void(int argcount UNUSED, type_T **argtypes UNUSED) +ret_void(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_void; } static type_T * -ret_any(int argcount UNUSED, type_T **argtypes UNUSED) +ret_any(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_any; } static type_T * -ret_bool(int argcount UNUSED, type_T **argtypes UNUSED) +ret_bool(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_bool; } static type_T * -ret_number_bool(int argcount UNUSED, type_T **argtypes UNUSED) +ret_number_bool(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_number_bool; } static type_T * -ret_number(int argcount UNUSED, type_T **argtypes UNUSED) +ret_number(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_number; } static type_T * -ret_float(int argcount UNUSED, type_T **argtypes UNUSED) +ret_float(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_float; } static type_T * -ret_string(int argcount UNUSED, type_T **argtypes UNUSED) +ret_string(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_string; } static type_T * -ret_list_any(int argcount UNUSED, type_T **argtypes UNUSED) +ret_list_any(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_list_any; } static type_T * -ret_list_number(int argcount UNUSED, type_T **argtypes UNUSED) +ret_list_number(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_list_number; } static type_T * -ret_list_string(int argcount UNUSED, type_T **argtypes UNUSED) +ret_list_string(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_list_string; } static type_T * -ret_list_dict_any(int argcount UNUSED, type_T **argtypes UNUSED) +ret_list_dict_any(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_list_dict_any; } static type_T * -ret_list_items(int argcount UNUSED, type_T **argtypes UNUSED) +ret_list_items(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_list_list_any; } static type_T * -ret_list_string_items(int argcount UNUSED, type_T **argtypes UNUSED) +ret_list_string_items(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_list_list_string; } static type_T * -ret_dict_any(int argcount UNUSED, type_T **argtypes UNUSED) +ret_dict_any(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_dict_any; } static type_T * -ret_job_info(int argcount, type_T **argtypes UNUSED) +ret_job_info(int argcount, type2_T *argtypes UNUSED) { if (argcount == 0) return &t_list_job; return &t_dict_any; } static type_T * -ret_dict_number(int argcount UNUSED, type_T **argtypes UNUSED) +ret_dict_number(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_dict_number; } static type_T * -ret_dict_string(int argcount UNUSED, type_T **argtypes UNUSED) +ret_dict_string(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_dict_string; } static type_T * -ret_blob(int argcount UNUSED, type_T **argtypes UNUSED) +ret_blob(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_blob; } static type_T * -ret_func_any(int argcount UNUSED, type_T **argtypes UNUSED) +ret_func_any(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_func_any; } static type_T * -ret_func_unknown(int argcount UNUSED, type_T **argtypes UNUSED) +ret_func_unknown(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_func_unknown; } static type_T * -ret_channel(int argcount UNUSED, type_T **argtypes UNUSED) +ret_channel(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_channel; } static type_T * -ret_job(int argcount UNUSED, type_T **argtypes UNUSED) +ret_job(int argcount UNUSED, type2_T *argtypes UNUSED) { return &t_job; } static type_T * -ret_first_arg(int argcount, type_T **argtypes) +ret_first_arg(int argcount, type2_T *argtypes) { if (argcount > 0) - return argtypes[0]; + return argtypes[0].type_curr; return &t_void; } static type_T * -ret_repeat(int argcount, type_T **argtypes) +ret_repeat(int argcount, type2_T *argtypes) { if (argcount == 0) return &t_any; - if (argtypes[0] == &t_number) + if (argtypes[0].type_curr == &t_number) return &t_string; - return argtypes[0]; + return argtypes[0].type_curr; } // for map(): returns first argument but item type may differ static type_T * -ret_first_cont(int argcount, type_T **argtypes) +ret_first_cont(int argcount, type2_T *argtypes) { if (argcount > 0) { - if (argtypes[0]->tt_type == VAR_LIST) + if (argtypes[0].type_curr->tt_type == VAR_LIST) return &t_list_any; - if (argtypes[0]->tt_type == VAR_DICT) + if (argtypes[0].type_curr->tt_type == VAR_DICT) return &t_dict_any; - if (argtypes[0]->tt_type == VAR_BLOB) - return argtypes[0]; + if (argtypes[0].type_curr->tt_type == VAR_BLOB) + return argtypes[0].type_curr; } return &t_any; } +// for getline() + static type_T * +ret_getline(int argcount, type2_T *argtypes UNUSED) +{ + return argcount == 1 ? &t_string : &t_list_string; +} // for finddir() static type_T * -ret_finddir(int argcount, type_T **argtypes UNUSED) +ret_finddir(int argcount, type2_T *argtypes UNUSED) { if (argcount < 3) return &t_string; @@ -1118,7 +1124,7 @@ ret_finddir(int argcount, type_T **argtypes UNUSED) * one. */ static type_T * -ret_list_or_dict_0(int argcount, type_T **argtypes UNUSED) +ret_list_or_dict_0(int argcount, type2_T *argtypes UNUSED) { if (argcount > 0) return &t_dict_any; @@ -1130,7 +1136,7 @@ ret_list_or_dict_0(int argcount, type_T **argtypes UNUSED) * are two. */ static type_T * -ret_list_or_dict_1(int argcount, type_T **argtypes UNUSED) +ret_list_or_dict_1(int argcount, type2_T *argtypes UNUSED) { if (argcount > 1) return &t_dict_any; @@ -1138,7 +1144,7 @@ ret_list_or_dict_1(int argcount, type_T **argtypes UNUSED) } static type_T * -ret_argv(int argcount, type_T **argtypes UNUSED) +ret_argv(int argcount, type2_T *argtypes UNUSED) { // argv() returns list of strings if (argcount == 0) @@ -1149,21 +1155,21 @@ ret_argv(int argcount, type_T **argtypes UNUSED) } static type_T * -ret_remove(int argcount, type_T **argtypes) +ret_remove(int argcount, type2_T *argtypes) { if (argcount > 0) { - if (argtypes[0]->tt_type == VAR_LIST - || argtypes[0]->tt_type == VAR_DICT) - return argtypes[0]->tt_member; - if (argtypes[0]->tt_type == VAR_BLOB) + if (argtypes[0].type_curr->tt_type == VAR_LIST + || argtypes[0].type_curr->tt_type == VAR_DICT) + return argtypes[0].type_curr->tt_member; + if (argtypes[0].type_curr->tt_type == VAR_BLOB) return &t_number; } return &t_any; } static type_T * -ret_getreg(int argcount, type_T **argtypes UNUSED) +ret_getreg(int argcount, type2_T *argtypes UNUSED) { // Assume that if the third argument is passed it's non-zero if (argcount == 3) @@ -1172,7 +1178,7 @@ ret_getreg(int argcount, type_T **argtypes UNUSED) } static type_T * -ret_maparg(int argcount, type_T **argtypes UNUSED) +ret_maparg(int argcount, type2_T *argtypes UNUSED) { // Assume that if the fourth argument is passed it's non-zero if (argcount == 4) @@ -1191,7 +1197,7 @@ typedef struct char f_max_argc; // maximal number of arguments char f_argtype; // for method: FEARG_ values argcheck_T *f_argcheck; // list of functions to check argument types - type_T *(*f_retfunc)(int argcount, type_T **argtypes); + type_T *(*f_retfunc)(int argcount, type2_T *argtypes); // return type function void (*f_func)(typval_T *args, typval_T *rvar); // implementation of function @@ -1599,7 +1605,7 @@ static funcentry_T global_functions[] = {"getjumplist", 0, 2, FEARG_1, arg2_number, ret_list_any, f_getjumplist}, {"getline", 1, 2, FEARG_1, arg2_lnum, - ret_f_getline, f_getline}, + ret_getline, f_getline}, {"getloclist", 1, 2, 0, arg2_number_dict_any, ret_list_or_dict_1, f_getloclist}, {"getmarklist", 0, 1, FEARG_1, arg1_buffer, @@ -2576,7 +2582,7 @@ internal_func_name(int idx) */ int internal_func_check_arg_types( - type_T **types, + type2_T *types, int idx, int argcount, cctx_T *cctx) @@ -2595,7 +2601,8 @@ internal_func_check_arg_types( if (argchecks[i] != NULL) { context.arg_idx = i; - if (argchecks[i](types[i], &context) == FAIL) + if (argchecks[i](types[i].type_curr, types[i].type_decl, + &context) == FAIL) return FAIL; } } @@ -2621,7 +2628,7 @@ internal_func_get_argcount(int idx, int *argcount, int *min_argcount) * "argcount" may be less than the actual count when only getting the type. */ type_T * -internal_func_ret_type(int idx, int argcount, type_T **argtypes) +internal_func_ret_type(int idx, int argcount, type2_T *argtypes) { return global_functions[idx].f_retfunc(argcount, argtypes); } diff --git a/src/list.c b/src/list.c index aadc7233d0..6ad3e9211e 100644 --- a/src/list.c +++ b/src/list.c @@ -271,6 +271,7 @@ list_free_list(list_T *l) l->lv_used_next->lv_used_prev = l->lv_used_prev; free_type(l->lv_type); + free_type(l->lv_decl_type); vim_free(l); } @@ -1025,6 +1026,8 @@ flatten_common(typval_T *argvars, typval_T *rettv, int make_copy) // The type will change. free_type(l->lv_type); l->lv_type = NULL; + free_type(l->lv_decl_type); + l->lv_decl_type = NULL; } else { @@ -1220,6 +1223,7 @@ list_copy(list_T *orig, int deep, int copyID) if (copy != NULL) { copy->lv_type = alloc_type(orig->lv_type); + copy->lv_decl_type = alloc_type(orig->lv_decl_type); if (copyID != 0) { // Do this before adding the items, because one of the items may diff --git a/src/proto/evalbuffer.pro b/src/proto/evalbuffer.pro index 57c84ceb76..b59c5f5e9b 100644 --- a/src/proto/evalbuffer.pro +++ b/src/proto/evalbuffer.pro @@ -16,7 +16,6 @@ void f_bufwinnr(typval_T *argvars, typval_T *rettv); void f_deletebufline(typval_T *argvars, typval_T *rettv); void f_getbufinfo(typval_T *argvars, typval_T *rettv); void f_getbufline(typval_T *argvars, typval_T *rettv); -type_T *ret_f_getline(int argcount, type_T **argtypes); void f_getline(typval_T *argvars, typval_T *rettv); void f_setbufline(typval_T *argvars, typval_T *rettv); void f_setline(typval_T *argvars, typval_T *rettv); diff --git a/src/proto/evalfunc.pro b/src/proto/evalfunc.pro index eb89e6452d..e508604983 100644 --- a/src/proto/evalfunc.pro +++ b/src/proto/evalfunc.pro @@ -5,9 +5,9 @@ char_u *get_expr_name(expand_T *xp, int idx); int find_internal_func(char_u *name); int has_internal_func(char_u *name); char *internal_func_name(int idx); -int internal_func_check_arg_types(type_T **types, int idx, int argcount, cctx_T *cctx); +int internal_func_check_arg_types(type2_T *types, int idx, int argcount, cctx_T *cctx); void internal_func_get_argcount(int idx, int *argcount, int *min_argcount); -type_T *internal_func_ret_type(int idx, int argcount, type_T **argtypes); +type_T *internal_func_ret_type(int idx, int argcount, type2_T *argtypes); int internal_func_is_map(int idx); int check_internal_func(int idx, int argcount); int call_internal_func(char_u *name, int argcount, typval_T *argvars, typval_T *rettv); diff --git a/src/proto/vim9instr.pro b/src/proto/vim9instr.pro index 0083334d91..b20dcf7d1b 100644 --- a/src/proto/vim9instr.pro +++ b/src/proto/vim9instr.pro @@ -1,6 +1,7 @@ /* vim9instr.c */ isn_T *generate_instr(cctx_T *cctx, isntype_T isn_type); isn_T *generate_instr_drop(cctx_T *cctx, isntype_T isn_type, int drop); +isn_T *generate_instr_type2(cctx_T *cctx, isntype_T isn_type, type_T *type, type_T *decl_type); isn_T *generate_instr_type(cctx_T *cctx, isntype_T isn_type, type_T *type); isn_T *generate_instr_debug(cctx_T *cctx); int may_generate_2STRING(int offset, int tolerant, cctx_T *cctx); diff --git a/src/proto/vim9type.pro b/src/proto/vim9type.pro index 0bdc227745..015531c1ed 100644 --- a/src/proto/vim9type.pro +++ b/src/proto/vim9type.pro @@ -8,7 +8,7 @@ type_T *alloc_func_type(type_T *ret_type, int argcount, garray_T *type_gap); type_T *get_func_type(type_T *ret_type, int argcount, garray_T *type_gap); int func_type_add_arg_types(type_T *functype, int argcount, garray_T *type_gap); int need_convert_to_bool(type_T *type, typval_T *tv); -type_T *typval2type(typval_T *tv, int copyID, garray_T *type_gap, int do_member); +type_T *typval2type(typval_T *tv, int copyID, garray_T *type_gap, int flags); type_T *typval2type_vimvar(typval_T *tv, garray_T *type_gap); int check_typval_arg_type(type_T *expected, typval_T *actual_tv, char *func_name, int arg_idx); int check_typval_type(type_T *expected, typval_T *actual_tv, where_T where); @@ -22,7 +22,11 @@ char_u *skip_type(char_u *start, int optional); type_T *parse_type(char_u **arg, garray_T *type_gap, int give_error); int equal_type(type_T *type1, type_T *type2, int flags); void common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap); -type_T *get_member_type_from_stack(type_T **stack_top, int count, int skip, garray_T *type_gap); +int push_type_stack(cctx_T *cctx, type_T *type); +int push_type_stack2(cctx_T *cctx, type_T *type, type_T *decl_type); +void set_type_on_stack(cctx_T *cctx, type_T *type, int offset); +type_T *get_type_on_stack(cctx_T *cctx, int offset); +type_T *get_member_type_from_stack(int count, int skip, type_T **decl_type, cctx_T *cctx); char *vartype_name(vartype_T type); char *type_name(type_T *type, char **tofree); void f_typename(typval_T *argvars, typval_T *rettv); diff --git a/src/structs.h b/src/structs.h index 4e770f1187..7d040eb6f4 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1422,6 +1422,11 @@ struct type_S { type_T **tt_args; // func argument types, allocated }; +typedef struct { + type_T *type_curr; // current type, value type + type_T *type_decl; // declared type or equal to type_current +} type2_T; + #define TTFLAG_VARARGS 1 // func args ends with "..." #define TTFLAG_OPTARG 2 // func arg type with "?" #define TTFLAG_BOOL_OK 4 // can be converted to bool @@ -1507,7 +1512,8 @@ struct listvar_S int lv_idx; // cached index of an item } mat; } lv_u; - type_T *lv_type; // allocated by alloc_type() + type_T *lv_type; // current type, allocated by alloc_type() + type_T *lv_decl_type; // declared type, allocated by alloc_type() list_T *lv_copylist; // copied list used by deepcopy() list_T *lv_used_next; // next list in used lists list list_T *lv_used_prev; // previous list in used lists list @@ -1571,7 +1577,8 @@ struct dictvar_S int dv_refcount; // refere |