diff options
author | Bram Moolenaar <Bram@vim.org> | 2022-01-04 15:17:03 +0000 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2022-01-04 15:17:03 +0000 |
commit | 078a46161e8b1b30bf306d6c1f4f0af7c616a989 (patch) | |
tree | 334c2fa968e1641524028ac18afedf5980446e64 /src/vim9type.c | |
parent | 9acf2d8be93f3b50607279e7f3484b019675d0a7 (diff) |
patch 8.2.3996: Vim9: type checking lacks information about declared typev8.2.3996
Problem: Vim9: type checking for list and dict lacks information about
declared type.
Solution: Add dv_decl_type and lv_decl_type. Refactor the type stack to
store two types in each entry.
Diffstat (limited to 'src/vim9type.c')
-rw-r--r-- | src/vim9type.c | 92 |
1 files changed, 82 insertions, 10 deletions
diff --git a/src/vim9type.c b/src/vim9type.c index d07c6e6a08..f2ed15b48c 100644 --- a/src/vim9type.c +++ b/src/vim9type.c @@ -1192,38 +1192,110 @@ common_type(type_T *type1, type_T *type2, type_T **dest, garray_T *type_gap) } /* - * Get the member type of a dict or list from the items on the stack. - * "stack_top" points just after the last type on the type stack. + * Push an entry onto the type stack. "type" used both for the current type + * and the declared type. + * Returns FAIL when out of memory. + */ + int +push_type_stack(cctx_T *cctx, type_T *type) +{ + return push_type_stack2(cctx, type, type); +} + +/* + * Push an entry onto the type stack. "type" is the current type, "decl_type" + * is the declared type. + * Returns FAIL when out of memory. + */ + int +push_type_stack2(cctx_T *cctx, type_T *type, type_T *decl_type) +{ + garray_T *stack = &cctx->ctx_type_stack; + type2_T *typep; + + if (GA_GROW_FAILS(stack, 1)) + return FAIL; + typep = ((type2_T *)stack->ga_data) + stack->ga_len; + typep->type_curr = type; + typep->type_decl = decl_type; + ++stack->ga_len; + return OK; +} + +/* + * Set the type of the top of the stack to "type". + */ + void +set_type_on_stack(cctx_T *cctx, type_T *type, int offset) +{ + garray_T *stack = &cctx->ctx_type_stack; + type2_T *typep = ((type2_T *)stack->ga_data) + + stack->ga_len - 1 - offset; + + typep->type_curr = type; + typep->type_decl = &t_any; +} + +/* + * Get the type from the type stack. If "offset" is zero the one at the top, + * if "offset" is one the type above that, etc. + * Returns &t_unknown if there is no such stack entry. + */ + type_T * +get_type_on_stack(cctx_T *cctx, int offset) +{ + garray_T *stack = &cctx->ctx_type_stack; + + if (offset + 1 > stack->ga_len) + return &t_unknown; + return (((type2_T *)stack->ga_data) + stack->ga_len - offset - 1) + ->type_curr; +} + +/* + * Get the member type of a dict or list from the items on the stack of "cctx". + * The declared type is stored in "decl_type". * For a list "skip" is 1, for a dict "skip" is 2, keys are skipped. * Returns &t_void for an empty list or dict. * Otherwise finds the common type of all items. */ type_T * get_member_type_from_stack( - type_T **stack_top, int count, int skip, - garray_T *type_gap) + type_T **decl_type, + cctx_T *cctx) { - int i; - type_T *result; - type_T *type; + garray_T *stack = &cctx->ctx_type_stack; + type2_T *typep = ((type2_T *)stack->ga_data) + stack->ga_len; + garray_T *type_gap = cctx->ctx_type_list; + int i; + type_T *result; + type_T *decl_result; + type_T *type; - // Use "any" for an empty list or dict. + // Use "unknown" for an empty list or dict. if (count == 0) + { + *decl_type = &t_unknown; return &t_unknown; + } // Use the first value type for the list member type, then find the common // type from following items. - result = *(stack_top -(count * skip) + skip - 1); + result = (typep -(count * skip) + skip - 1)->type_curr; + decl_result = (typep -(count * skip) + skip - 1)->type_decl; for (i = 1; i < count; ++i) { if (result == &t_any) break; // won't get more common - type = *(stack_top -((count - i) * skip) + skip - 1); + type = (typep -((count - i) * skip) + skip - 1)->type_curr; common_type(type, result, &result, type_gap); + type = (typep -((count - i) * skip) + skip - 1)->type_decl; + common_type(type, decl_result, &decl_result, type_gap); } + *decl_type = decl_result; return result; } |