diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-09-16 15:22:00 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-09-16 15:22:00 +0200 |
commit | 5e654230777ad21363a929dce3cfe0387da031a7 (patch) | |
tree | 967aea5363b039cb47c98bf2ef2e992f182b29da /src/vim9compile.c | |
parent | 8b51b7f0f17af149a8ce76e805050977857f9e50 (diff) | |
download | vim-git-5e654230777ad21363a929dce3cfe0387da031a7.tar.gz |
patch 8.2.1691: Vim9: list<any> is not accepted where list<number> is expectedv8.2.1691
Problem: Vim9: list<any> is not accepted where list<number> is expected.
Solution: Add functions to allocate and free a type_T, use it in
ISN_CHECKTYPE. (closes #6959)
Diffstat (limited to 'src/vim9compile.c')
-rw-r--r-- | src/vim9compile.c | 55 |
1 files changed, 36 insertions, 19 deletions
diff --git a/src/vim9compile.c b/src/vim9compile.c index a53f05d32..075bd12c4 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -704,7 +704,10 @@ generate_2BOOL(cctx_T *cctx, int invert) } static int -generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset) +generate_TYPECHECK( + cctx_T *cctx, + type_T *expected, + int offset) { isn_T *isn; garray_T *stack = &cctx->ctx_type_stack; @@ -712,19 +715,18 @@ generate_TYPECHECK(cctx_T *cctx, type_T *vartype, int offset) RETURN_OK_IF_SKIP(cctx); if ((isn = generate_instr(cctx, ISN_CHECKTYPE)) == NULL) return FAIL; - // TODO: whole type, e.g. for a function also arg and return types - isn->isn_arg.type.ct_type = vartype->tt_type; + isn->isn_arg.type.ct_type = alloc_type(expected); isn->isn_arg.type.ct_off = offset; - // type becomes vartype - ((type_T **)stack->ga_data)[stack->ga_len + offset] = vartype; + // type becomes expected + ((type_T **)stack->ga_data)[stack->ga_len + offset] = expected; return OK; } /* * Check that - * - "actual" is "expected" type or + * - "actual" matches "expected" type or * - "actual" is a type that can be "expected" type: add a runtime check; or * - return FAIL. */ @@ -747,17 +749,29 @@ need_type( if (check_type(expected, actual, FALSE, 0) == OK) return OK; - if (actual->tt_type != VAR_ANY - && actual->tt_type != VAR_UNKNOWN - && !(actual->tt_type == VAR_FUNC - && (actual->tt_member == &t_any || actual->tt_argcount < 0))) - { - if (!silent) - type_mismatch(expected, actual); - return FAIL; + + // If the actual type can be the expected type add a runtime check. + // TODO: if it's a constant a runtime check makes no sense. + if (actual->tt_type == VAR_ANY + || actual->tt_type == VAR_UNKNOWN + || (actual->tt_type == VAR_FUNC + && (expected->tt_type == VAR_FUNC + || expected->tt_type == VAR_PARTIAL) + && (actual->tt_member == &t_any || actual->tt_argcount < 0)) + || (actual->tt_type == VAR_LIST + && expected->tt_type == VAR_LIST + && actual->tt_member == &t_any) + || (actual->tt_type == VAR_DICT + && expected->tt_type == VAR_DICT + && actual->tt_member == &t_any)) + { + generate_TYPECHECK(cctx, expected, offset); + return OK; } - generate_TYPECHECK(cctx, expected, offset); - return OK; + + if (!silent) + type_mismatch(expected, actual); + return FAIL; } /* @@ -776,7 +790,7 @@ generate_PUSHNR(cctx_T *cctx, varnumber_T number) if (number == 0 || number == 1) { - type_T *type = alloc_type(cctx->ctx_type_list); + type_T *type = get_type_ptr(cctx->ctx_type_list); // A 0 or 1 number can also be used as a bool. if (type != NULL) @@ -4037,7 +4051,7 @@ compile_and_or( typep = ((type_T **)stack->ga_data) + stack->ga_len - 1; if (*typep != &t_bool) { - type_T *type = alloc_type(cctx->ctx_type_list); + type_T *type = get_type_ptr(cctx->ctx_type_list); if (type != NULL) { @@ -7290,6 +7304,10 @@ delete_instr(isn_T *isn) } break; + case ISN_CHECKTYPE: + free_type(isn->isn_arg.type.ct_type); + break; + case ISN_2BOOL: case ISN_2STRING: case ISN_2STRING_ANY: @@ -7301,7 +7319,6 @@ delete_instr(isn_T *isn) case ISN_CATCH: case ISN_CHECKLEN: case ISN_CHECKNR: - case ISN_CHECKTYPE: case ISN_COMPAREANY: case ISN_COMPAREBLOB: case ISN_COMPAREBOOL: |