Mercurial > vim
comparison src/vim9compile.c @ 23640:8dcb2255ff9a v8.2.2362
patch 8.2.2362: Vim9: check of builtin function argument type is incomplete
Commit: https://github.com/vim/vim/commit/351ead09dd365ebdee2bfa27ab22542d4920c779
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Jan 16 16:07:01 2021 +0100
patch 8.2.2362: Vim9: check of builtin function argument type is incomplete
Problem: Vim9: check of builtin function argument type is incomplete.
Solution: Use need_type() instead of check_arg_type().
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 16 Jan 2021 16:15:04 +0100 |
parents | 455ad460ff4f |
children | c8f26523d7d7 |
comparison
equal
deleted
inserted
replaced
23639:a93ecfa78aef | 23640:8dcb2255ff9a |
---|---|
876 * - "actual" is a type that can be "expected" type: add a runtime check; or | 876 * - "actual" is a type that can be "expected" type: add a runtime check; or |
877 * - return FAIL. | 877 * - return FAIL. |
878 * If "actual_is_const" is TRUE then the type won't change at runtime, do not | 878 * If "actual_is_const" is TRUE then the type won't change at runtime, do not |
879 * generate a TYPECHECK. | 879 * generate a TYPECHECK. |
880 */ | 880 */ |
881 static int | 881 int |
882 need_type( | 882 need_type( |
883 type_T *actual, | 883 type_T *actual, |
884 type_T *expected, | 884 type_T *expected, |
885 int offset, | 885 int offset, |
886 int arg_idx, | |
886 cctx_T *cctx, | 887 cctx_T *cctx, |
887 int silent, | 888 int silent, |
888 int actual_is_const) | 889 int actual_is_const) |
889 { | 890 { |
890 if (expected == &t_bool && actual != &t_bool | 891 if (expected == &t_bool && actual != &t_bool |
894 // boolean is OK but requires a conversion. | 895 // boolean is OK but requires a conversion. |
895 generate_2BOOL(cctx, FALSE); | 896 generate_2BOOL(cctx, FALSE); |
896 return OK; | 897 return OK; |
897 } | 898 } |
898 | 899 |
899 if (check_type(expected, actual, FALSE, 0) == OK) | 900 if (check_type(expected, actual, FALSE, arg_idx) == OK) |
900 return OK; | 901 return OK; |
901 | 902 |
902 // If the actual type can be the expected type add a runtime check. | 903 // If the actual type can be the expected type add a runtime check. |
903 // If it's a constant a runtime check makes no sense. | 904 // If it's a constant a runtime check makes no sense. |
904 if (!actual_is_const && use_typecheck(actual, expected)) | 905 if (!actual_is_const && use_typecheck(actual, expected)) |
906 generate_TYPECHECK(cctx, expected, offset); | 907 generate_TYPECHECK(cctx, expected, offset); |
907 return OK; | 908 return OK; |
908 } | 909 } |
909 | 910 |
910 if (!silent) | 911 if (!silent) |
911 type_mismatch(expected, actual); | 912 arg_type_mismatch(expected, actual, arg_idx); |
912 return FAIL; | 913 return FAIL; |
913 } | 914 } |
914 | 915 |
915 /* | 916 /* |
916 * Check that the top of the type stack has a type that can be used as a | 917 * Check that the top of the type stack has a type that can be used as a |
929 if (type == &t_any || type == &t_number) | 930 if (type == &t_any || type == &t_number) |
930 // Number 0 and 1 are OK to use as a bool. "any" could also be a bool. | 931 // Number 0 and 1 are OK to use as a bool. "any" could also be a bool. |
931 // This requires a runtime type check. | 932 // This requires a runtime type check. |
932 return generate_COND2BOOL(cctx); | 933 return generate_COND2BOOL(cctx); |
933 | 934 |
934 return need_type(type, &t_bool, -1, cctx, FALSE, FALSE); | 935 return need_type(type, &t_bool, -1, 0, cctx, FALSE, FALSE); |
935 } | 936 } |
936 | 937 |
937 /* | 938 /* |
938 * Generate an ISN_PUSHNR instruction. | 939 * Generate an ISN_PUSHNR instruction. |
939 */ | 940 */ |
1611 | 1612 |
1612 if (argcount > 0) | 1613 if (argcount > 0) |
1613 { | 1614 { |
1614 // Check the types of the arguments. | 1615 // Check the types of the arguments. |
1615 argtypes = ((type_T **)stack->ga_data) + stack->ga_len - argcount; | 1616 argtypes = ((type_T **)stack->ga_data) + stack->ga_len - argcount; |
1616 if (internal_func_check_arg_types(argtypes, func_idx, argcount) == FAIL) | 1617 if (internal_func_check_arg_types(argtypes, func_idx, argcount, |
1618 cctx) == FAIL) | |
1617 return FAIL; | 1619 return FAIL; |
1618 if (internal_func_is_map(func_idx)) | 1620 if (internal_func_is_map(func_idx)) |
1619 maptype = *argtypes; | 1621 maptype = *argtypes; |
1620 } | 1622 } |
1621 | 1623 |
1654 | 1656 |
1655 // Caller already checked that list_type is a list. | 1657 // Caller already checked that list_type is a list. |
1656 list_type = ((type_T **)stack->ga_data)[stack->ga_len - 2]; | 1658 list_type = ((type_T **)stack->ga_data)[stack->ga_len - 2]; |
1657 item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | 1659 item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; |
1658 expected = list_type->tt_member; | 1660 expected = list_type->tt_member; |
1659 if (need_type(item_type, expected, -1, cctx, FALSE, FALSE) == FAIL) | 1661 if (need_type(item_type, expected, -1, 0, cctx, FALSE, FALSE) == FAIL) |
1660 return FAIL; | 1662 return FAIL; |
1661 | 1663 |
1662 if (generate_instr(cctx, ISN_LISTAPPEND) == NULL) | 1664 if (generate_instr(cctx, ISN_LISTAPPEND) == NULL) |
1663 return FAIL; | 1665 return FAIL; |
1664 | 1666 |
1676 garray_T *stack = &cctx->ctx_type_stack; | 1678 garray_T *stack = &cctx->ctx_type_stack; |
1677 type_T *item_type; | 1679 type_T *item_type; |
1678 | 1680 |
1679 // Caller already checked that blob_type is a blob. | 1681 // Caller already checked that blob_type is a blob. |
1680 item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | 1682 item_type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; |
1681 if (need_type(item_type, &t_number, -1, cctx, FALSE, FALSE) == FAIL) | 1683 if (need_type(item_type, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL) |
1682 return FAIL; | 1684 return FAIL; |
1683 | 1685 |
1684 if (generate_instr(cctx, ISN_BLOBAPPEND) == NULL) | 1686 if (generate_instr(cctx, ISN_BLOBAPPEND) == NULL) |
1685 return FAIL; | 1687 return FAIL; |
1686 | 1688 |
1731 // possibly a lambda or "...: any" | 1733 // possibly a lambda or "...: any" |
1732 expected = &t_any; | 1734 expected = &t_any; |
1733 else | 1735 else |
1734 expected = ufunc->uf_va_type->tt_member; | 1736 expected = ufunc->uf_va_type->tt_member; |
1735 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i]; | 1737 actual = ((type_T **)stack->ga_data)[stack->ga_len - argcount + i]; |
1736 if (need_type(actual, expected, -argcount + i, cctx, | 1738 if (need_type(actual, expected, -argcount + i, 0, cctx, |
1737 TRUE, FALSE) == FAIL) | 1739 TRUE, FALSE) == FAIL) |
1738 { | 1740 { |
1739 arg_type_mismatch(expected, actual, i + 1); | 1741 arg_type_mismatch(expected, actual, i + 1); |
1740 return FAIL; | 1742 return FAIL; |
1741 } | 1743 } |
1848 if (varargs && i >= type->tt_argcount - 1) | 1850 if (varargs && i >= type->tt_argcount - 1) |
1849 expected = type->tt_args[ | 1851 expected = type->tt_args[ |
1850 type->tt_argcount - 1]->tt_member; | 1852 type->tt_argcount - 1]->tt_member; |
1851 else | 1853 else |
1852 expected = type->tt_args[i]; | 1854 expected = type->tt_args[i]; |
1853 if (need_type(actual, expected, offset, | 1855 if (need_type(actual, expected, offset, 0, |
1854 cctx, TRUE, FALSE) == FAIL) | 1856 cctx, TRUE, FALSE) == FAIL) |
1855 { | 1857 { |
1856 arg_type_mismatch(expected, actual, i + 1); | 1858 arg_type_mismatch(expected, actual, i + 1); |
1857 return FAIL; | 1859 return FAIL; |
1858 } | 1860 } |
3133 key = isn->isn_arg.string; | 3135 key = isn->isn_arg.string; |
3134 else | 3136 else |
3135 { | 3137 { |
3136 type_T *keytype = ((type_T **)stack->ga_data) | 3138 type_T *keytype = ((type_T **)stack->ga_data) |
3137 [stack->ga_len - 1]; | 3139 [stack->ga_len - 1]; |
3138 if (need_type(keytype, &t_string, -1, cctx, | 3140 if (need_type(keytype, &t_string, -1, 0, cctx, |
3139 FALSE, FALSE) == FAIL) | 3141 FALSE, FALSE) == FAIL) |
3140 return FAIL; | 3142 return FAIL; |
3141 } | 3143 } |
3142 *arg = skipwhite(*arg); | 3144 *arg = skipwhite(*arg); |
3143 if (**arg != ']') | 3145 if (**arg != ']') |
3806 // If the index is a string, the variable must be a Dict. | 3808 // If the index is a string, the variable must be a Dict. |
3807 if (*typep == &t_any && valtype == &t_string) | 3809 if (*typep == &t_any && valtype == &t_string) |
3808 vtype = VAR_DICT; | 3810 vtype = VAR_DICT; |
3809 if (vtype == VAR_STRING || vtype == VAR_LIST || vtype == VAR_BLOB) | 3811 if (vtype == VAR_STRING || vtype == VAR_LIST || vtype == VAR_BLOB) |
3810 { | 3812 { |
3811 if (need_type(valtype, &t_number, -1, cctx, | 3813 if (need_type(valtype, &t_number, -1, 0, cctx, |
3812 FALSE, FALSE) == FAIL) | 3814 FALSE, FALSE) == FAIL) |
3813 return FAIL; | 3815 return FAIL; |
3814 if (is_slice) | 3816 if (is_slice) |
3815 { | 3817 { |
3816 valtype = ((type_T **)stack->ga_data)[stack->ga_len - 2]; | 3818 valtype = ((type_T **)stack->ga_data)[stack->ga_len - 2]; |
3817 if (need_type(valtype, &t_number, -2, cctx, | 3819 if (need_type(valtype, &t_number, -2, 0, cctx, |
3818 FALSE, FALSE) == FAIL) | 3820 FALSE, FALSE) == FAIL) |
3819 return FAIL; | 3821 return FAIL; |
3820 } | 3822 } |
3821 } | 3823 } |
3822 | 3824 |
3834 // empty dict was used | 3836 // empty dict was used |
3835 *typep = &t_any; | 3837 *typep = &t_any; |
3836 } | 3838 } |
3837 else | 3839 else |
3838 { | 3840 { |
3839 if (need_type(*typep, &t_dict_any, -2, cctx, | 3841 if (need_type(*typep, &t_dict_any, -2, 0, cctx, |
3840 FALSE, FALSE) == FAIL) | 3842 FALSE, FALSE) == FAIL) |
3841 return FAIL; | 3843 return FAIL; |
3842 *typep = &t_any; | 3844 *typep = &t_any; |
3843 } | 3845 } |
3844 if (may_generate_2STRING(-1, cctx) == FAIL) | 3846 if (may_generate_2STRING(-1, cctx) == FAIL) |
4233 | 4235 |
4234 generate_ppconst(cctx, ppconst); | 4236 generate_ppconst(cctx, ppconst); |
4235 actual = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | 4237 actual = ((type_T **)stack->ga_data)[stack->ga_len - 1]; |
4236 if (check_type(want_type, actual, FALSE, 0) == FAIL) | 4238 if (check_type(want_type, actual, FALSE, 0) == FAIL) |
4237 { | 4239 { |
4238 if (need_type(actual, want_type, -1, cctx, FALSE, FALSE) == FAIL) | 4240 if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE) == FAIL) |
4239 return FAIL; | 4241 return FAIL; |
4240 } | 4242 } |
4241 } | 4243 } |
4242 | 4244 |
4243 return OK; | 4245 return OK; |
4915 { | 4917 { |
4916 emsg(_(e_returning_value_in_function_without_return_type)); | 4918 emsg(_(e_returning_value_in_function_without_return_type)); |
4917 return NULL; | 4919 return NULL; |
4918 } | 4920 } |
4919 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, | 4921 if (need_type(stack_type, cctx->ctx_ufunc->uf_ret_type, -1, |
4920 cctx, FALSE, FALSE) == FAIL) | 4922 0, cctx, FALSE, FALSE) == FAIL) |
4921 return NULL; | 4923 return NULL; |
4922 } | 4924 } |
4923 } | 4925 } |
4924 } | 4926 } |
4925 else | 4927 else |
5829 | 5831 |
5830 lhs->lhs_type = stack->ga_len == 0 ? &t_void | 5832 lhs->lhs_type = stack->ga_len == 0 ? &t_void |
5831 : ((type_T **)stack->ga_data)[stack->ga_len - 1]; | 5833 : ((type_T **)stack->ga_data)[stack->ga_len - 1]; |
5832 // now we can properly check the type | 5834 // now we can properly check the type |
5833 if (lhs->lhs_type->tt_member != NULL && rhs_type != &t_void | 5835 if (lhs->lhs_type->tt_member != NULL && rhs_type != &t_void |
5834 && need_type(rhs_type, lhs->lhs_type->tt_member, -2, cctx, | 5836 && need_type(rhs_type, lhs->lhs_type->tt_member, -2, 0, cctx, |
5835 FALSE, FALSE) == FAIL) | 5837 FALSE, FALSE) == FAIL) |
5836 return FAIL; | 5838 return FAIL; |
5837 } | 5839 } |
5838 else | 5840 else |
5839 generate_loadvar(cctx, lhs->lhs_dest, lhs->lhs_name, | 5841 generate_loadvar(cctx, lhs->lhs_dest, lhs->lhs_name, |
5974 if (stacktype->tt_type == VAR_VOID) | 5976 if (stacktype->tt_type == VAR_VOID) |
5975 { | 5977 { |
5976 emsg(_(e_cannot_use_void_value)); | 5978 emsg(_(e_cannot_use_void_value)); |
5977 goto theend; | 5979 goto theend; |
5978 } | 5980 } |
5979 if (need_type(stacktype, &t_list_any, -1, cctx, | 5981 if (need_type(stacktype, &t_list_any, -1, 0, cctx, |
5980 FALSE, FALSE) == FAIL) | 5982 FALSE, FALSE) == FAIL) |
5981 goto theend; | 5983 goto theend; |
5982 // TODO: check the length of a constant list here | 5984 // TODO: check the length of a constant list here |
5983 generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count, | 5985 generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count, |
5984 semicolon); | 5986 semicolon); |
6121 type_T *use_type = lhs.lhs_lvar->lv_type; | 6123 type_T *use_type = lhs.lhs_lvar->lv_type; |
6122 | 6124 |
6123 // without operator check type here, otherwise below | 6125 // without operator check type here, otherwise below |
6124 if (lhs.lhs_has_index) | 6126 if (lhs.lhs_has_index) |
6125 use_type = lhs.lhs_member_type; | 6127 use_type = lhs.lhs_member_type; |
6126 if (need_type(rhs_type, use_type, -1, cctx, | 6128 if (need_type(rhs_type, use_type, -1, 0, cctx, |
6127 FALSE, is_const) == FAIL) | 6129 FALSE, is_const) == FAIL) |
6128 goto theend; | 6130 goto theend; |
6129 } | 6131 } |
6130 } | 6132 } |
6131 else if (*p != '=' && need_type(rhs_type, lhs.lhs_member_type, | 6133 else if (*p != '=' && need_type(rhs_type, lhs.lhs_member_type, |
6132 -1, cctx, FALSE, FALSE) == FAIL) | 6134 -1, 0, cctx, FALSE, FALSE) == FAIL) |
6133 goto theend; | 6135 goto theend; |
6134 } | 6136 } |
6135 else if (cmdidx == CMD_final) | 6137 else if (cmdidx == CMD_final) |
6136 { | 6138 { |
6137 emsg(_(e_final_requires_a_value)); | 6139 emsg(_(e_final_requires_a_value)); |
6214 if ( | 6216 if ( |
6215 #ifdef FEAT_FLOAT | 6217 #ifdef FEAT_FLOAT |
6216 // If variable is float operation with number is OK. | 6218 // If variable is float operation with number is OK. |
6217 !(expected == &t_float && stacktype == &t_number) && | 6219 !(expected == &t_float && stacktype == &t_number) && |
6218 #endif | 6220 #endif |
6219 need_type(stacktype, expected, -1, cctx, | 6221 need_type(stacktype, expected, -1, 0, cctx, |
6220 FALSE, FALSE) == FAIL) | 6222 FALSE, FALSE) == FAIL) |
6221 goto theend; | 6223 goto theend; |
6222 | 6224 |
6223 if (*op == '.') | 6225 if (*op == '.') |
6224 { | 6226 { |
6923 arg_end = arg; | 6925 arg_end = arg; |
6924 | 6926 |
6925 // Now that we know the type of "var", check that it is a list, now or at | 6927 // Now that we know the type of "var", check that it is a list, now or at |
6926 // runtime. | 6928 // runtime. |
6927 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1]; | 6929 vartype = ((type_T **)stack->ga_data)[stack->ga_len - 1]; |
6928 if (need_type(vartype, &t_list_any, -1, cctx, FALSE, FALSE) == FAIL) | 6930 if (need_type(vartype, &t_list_any, -1, 0, cctx, FALSE, FALSE) == FAIL) |
6929 { | 6931 { |
6930 drop_scope(cctx); | 6932 drop_scope(cctx); |
6931 return NULL; | 6933 return NULL; |
6932 } | 6934 } |
6933 | 6935 |