comparison src/vim9expr.c @ 26935:ccb9be1cdd71 v8.2.3996

patch 8.2.3996: Vim9: type checking lacks information about declared type Commit: https://github.com/vim/vim/commit/078a46161e8b1b30bf306d6c1f4f0af7c616a989 Author: Bram Moolenaar <Bram@vim.org> Date: Tue Jan 4 15:17:03 2022 +0000 patch 8.2.3996: Vim9: type checking lacks information about declared type 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.
author Bram Moolenaar <Bram@vim.org>
date Tue, 04 Jan 2022 16:30:06 +0100
parents 612339679616
children 8796f1384750
comparison
equal deleted inserted replaced
26934:2d3dd8065e25 26935:ccb9be1cdd71
75 * "keeping_dict" is used for dict[func](arg) to pass dict to func. 75 * "keeping_dict" is used for dict[func](arg) to pass dict to func.
76 */ 76 */
77 int 77 int
78 compile_member(int is_slice, int *keeping_dict, cctx_T *cctx) 78 compile_member(int is_slice, int *keeping_dict, cctx_T *cctx)
79 { 79 {
80 type_T **typep; 80 type2_T *typep;
81 garray_T *stack = &cctx->ctx_type_stack; 81 garray_T *stack = &cctx->ctx_type_stack;
82 vartype_T vartype; 82 vartype_T vartype;
83 type_T *idxtype; 83 type_T *idxtype;
84 84
85 // We can index a list, dict and blob. If we don't know the type 85 // We can index a list, dict and blob. If we don't know the type
86 // we can use the index value type. If we still don't know use an "ANY" 86 // we can use the index value type. If we still don't know use an "ANY"
87 // instruction. 87 // instruction.
88 typep = ((type_T **)stack->ga_data) + stack->ga_len 88 // TODO: what about the decl type?
89 - (is_slice ? 3 : 2); 89 typep = (((type2_T *)stack->ga_data) + stack->ga_len - (is_slice ? 3 : 2));
90 vartype = (*typep)->tt_type; 90 vartype = typep->type_curr->tt_type;
91 idxtype = ((type_T **)stack->ga_data)[stack->ga_len - 1]; 91 idxtype = (((type2_T *)stack->ga_data) + stack->ga_len - 1)->type_curr;
92 // If the index is a string, the variable must be a Dict. 92 // If the index is a string, the variable must be a Dict.
93 if ((*typep == &t_any || *typep == &t_unknown) && idxtype == &t_string) 93 if ((typep->type_curr == &t_any || typep->type_curr == &t_unknown)
94 && idxtype == &t_string)
94 vartype = VAR_DICT; 95 vartype = VAR_DICT;
95 if (vartype == VAR_STRING || vartype == VAR_LIST || vartype == VAR_BLOB) 96 if (vartype == VAR_STRING || vartype == VAR_LIST || vartype == VAR_BLOB)
96 { 97 {
97 if (need_type(idxtype, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL) 98 if (need_type(idxtype, &t_number, -1, 0, cctx, FALSE, FALSE) == FAIL)
98 return FAIL; 99 return FAIL;
99 if (is_slice) 100 if (is_slice)
100 { 101 {
101 idxtype = ((type_T **)stack->ga_data)[stack->ga_len - 2]; 102 idxtype = get_type_on_stack(cctx, 1);
102 if (need_type(idxtype, &t_number, -2, 0, cctx, 103 if (need_type(idxtype, &t_number, -2, 0, cctx,
103 FALSE, FALSE) == FAIL) 104 FALSE, FALSE) == FAIL)
104 return FAIL; 105 return FAIL;
105 } 106 }
106 } 107 }
110 if (is_slice) 111 if (is_slice)
111 { 112 {
112 emsg(_(e_cannot_slice_dictionary)); 113 emsg(_(e_cannot_slice_dictionary));
113 return FAIL; 114 return FAIL;
114 } 115 }
115 if ((*typep)->tt_type == VAR_DICT) 116 if (typep->type_curr->tt_type == VAR_DICT)
116 { 117 {
117 *typep = (*typep)->tt_member; 118 typep->type_curr = typep->type_curr->tt_member;
118 if (*typep == &t_unknown) 119 if (typep->type_curr == &t_unknown)
119 // empty dict was used 120 // empty dict was used
120 *typep = &t_any; 121 typep->type_curr = &t_any;
122 if (typep->type_decl->tt_type == VAR_DICT)
123 {
124 typep->type_decl = typep->type_decl->tt_member;
125 if (typep->type_decl == &t_unknown)
126 // empty dict was used
127 typep->type_decl = &t_any;
128 }
129 else
130 typep->type_decl = typep->type_curr;
121 } 131 }
122 else 132 else
123 { 133 {
124 if (need_type(*typep, &t_dict_any, -2, 0, cctx, 134 if (need_type(typep->type_curr, &t_dict_any, -2, 0, cctx,
125 FALSE, FALSE) == FAIL) 135 FALSE, FALSE) == FAIL)
126 return FAIL; 136 return FAIL;
127 *typep = &t_any; 137 typep->type_curr = &t_any;
138 typep->type_decl = &t_any;
128 } 139 }
129 if (may_generate_2STRING(-1, FALSE, cctx) == FAIL) 140 if (may_generate_2STRING(-1, FALSE, cctx) == FAIL)
130 return FAIL; 141 return FAIL;
131 if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL) 142 if (generate_instr_drop(cctx, ISN_MEMBER, 1) == FAIL)
132 return FAIL; 143 return FAIL;
133 if (keeping_dict != NULL) 144 if (keeping_dict != NULL)
134 *keeping_dict = TRUE; 145 *keeping_dict = TRUE;
135 } 146 }
136 else if (vartype == VAR_STRING) 147 else if (vartype == VAR_STRING)
137 { 148 {
138 *typep = &t_string; 149 typep->type_curr = &t_string;
150 typep->type_decl = &t_string;
139 if ((is_slice 151 if ((is_slice
140 ? generate_instr_drop(cctx, ISN_STRSLICE, 2) 152 ? generate_instr_drop(cctx, ISN_STRSLICE, 2)
141 : generate_instr_drop(cctx, ISN_STRINDEX, 1)) == FAIL) 153 : generate_instr_drop(cctx, ISN_STRINDEX, 1)) == FAIL)
142 return FAIL; 154 return FAIL;
143 } 155 }
144 else if (vartype == VAR_BLOB) 156 else if (vartype == VAR_BLOB)
145 { 157 {
146 if (is_slice) 158 if (is_slice)
147 { 159 {
148 *typep = &t_blob; 160 typep->type_curr = &t_blob;
161 typep->type_decl = &t_blob;
149 if (generate_instr_drop(cctx, ISN_BLOBSLICE, 2) == FAIL) 162 if (generate_instr_drop(cctx, ISN_BLOBSLICE, 2) == FAIL)
150 return FAIL; 163 return FAIL;
151 } 164 }
152 else 165 else
153 { 166 {
154 *typep = &t_number; 167 typep->type_curr = &t_number;
168 typep->type_decl = &t_number;
155 if (generate_instr_drop(cctx, ISN_BLOBINDEX, 1) == FAIL) 169 if (generate_instr_drop(cctx, ISN_BLOBINDEX, 1) == FAIL)
156 return FAIL; 170 return FAIL;
157 } 171 }
158 } 172 }
159 else if (vartype == VAR_LIST || *typep == &t_any || *typep == &t_unknown) 173 else if (vartype == VAR_LIST || typep->type_curr == &t_any
174 || typep->type_curr == &t_unknown)
160 { 175 {
161 if (is_slice) 176 if (is_slice)
162 { 177 {
163 if (generate_instr_drop(cctx, 178 if (generate_instr_drop(cctx,
164 vartype == VAR_LIST ? ISN_LISTSLICE : ISN_ANYSLICE, 179 vartype == VAR_LIST ? ISN_LISTSLICE : ISN_ANYSLICE,
165 2) == FAIL) 180 2) == FAIL)
166 return FAIL; 181 return FAIL;
167 } 182 }
168 else 183 else
169 { 184 {
170 if ((*typep)->tt_type == VAR_LIST) 185 if (typep->type_curr->tt_type == VAR_LIST)
171 { 186 {
172 *typep = (*typep)->tt_member; 187 typep->type_curr = typep->type_curr->tt_member;
173 if (*typep == &t_unknown) 188 if (typep->type_curr == &t_unknown)
174 // empty list was used 189 // empty list was used
175 *typep = &t_any; 190 typep->type_curr = &t_any;
191 if (typep->type_decl->tt_type == VAR_LIST)
192 {
193 typep->type_decl = typep->type_decl->tt_member;
194 if (typep->type_decl == &t_unknown)
195 // empty list was used
196 typep->type_decl = &t_any;
197 }
198 else
199 typep->type_decl = typep->type_curr;
176 } 200 }
177 if (generate_instr_drop(cctx, 201 if (generate_instr_drop(cctx,
178 vartype == VAR_LIST ? ISN_LISTINDEX : ISN_ANYINDEX, 1) 202 vartype == VAR_LIST ? ISN_LISTINDEX : ISN_ANYINDEX, 1)
179 == FAIL) 203 == FAIL)
180 return FAIL; 204 return FAIL;
707 goto theend; 731 goto theend;
708 } 732 }
709 733
710 if (STRCMP(name, "add") == 0 && argcount == 2) 734 if (STRCMP(name, "add") == 0 && argcount == 2)
711 { 735 {
712 garray_T *stack = &cctx->ctx_type_stack; 736 type_T *type = get_type_on_stack(cctx, 1);
713 type_T *type = ((type_T **)stack->ga_data)[
714 stack->ga_len - 2];
715 737
716 // add() can be compiled to instructions if we know the type 738 // add() can be compiled to instructions if we know the type
717 if (type->tt_type == VAR_LIST) 739 if (type->tt_type == VAR_LIST)
718 { 740 {
719 // inline "add(list, item)" so that the type can be checked 741 // inline "add(list, item)" so that the type can be checked
756 // Not for eome#Func(), it will be loaded later. 778 // Not for eome#Func(), it will be loaded later.
757 p = namebuf; 779 p = namebuf;
758 if (STRNCMP(namebuf, "g:", 2) != 0 && !is_autoload 780 if (STRNCMP(namebuf, "g:", 2) != 0 && !is_autoload
759 && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK) 781 && compile_load(&p, namebuf + varlen, cctx, FALSE, FALSE) == OK)
760 { 782 {
761 garray_T *stack = &cctx->ctx_type_stack; 783 type_T *type = get_type_on_stack(cctx, 0);
762 type_T *type = ((type_T **)stack->ga_data)[stack->ga_len - 1];
763 784
764 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE); 785 res = generate_PCALL(cctx, argcount, namebuf, type, FALSE);
765 goto theend; 786 goto theend;
766 } 787 }
767 788
1419 * condition. Give an error and return FAIL if not. 1440 * condition. Give an error and return FAIL if not.
1420 */ 1441 */
1421 int 1442 int
1422 bool_on_stack(cctx_T *cctx) 1443 bool_on_stack(cctx_T *cctx)
1423 { 1444 {
1424 garray_T *stack = &cctx->ctx_type_stack;
1425 type_T *type; 1445 type_T *type;
1426 1446
1427 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; 1447 type = get_type_on_stack(cctx, 0);
1428 if (type == &t_bool) 1448 if (type == &t_bool)
1429 return OK; 1449 return OK;
1430 1450
1431 if (type == &t_any 1451 if (type == &t_any
1432 || type == &t_unknown 1452 || type == &t_unknown
1468 --p; 1488 --p;
1469 if (*p == '-' || *p == '+') 1489 if (*p == '-' || *p == '+')
1470 { 1490 {
1471 int negate = *p == '-'; 1491 int negate = *p == '-';
1472 isn_T *isn; 1492 isn_T *isn;
1473 garray_T *stack = &cctx->ctx_type_stack;
1474 type_T *type; 1493 type_T *type;
1475 1494
1476 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; 1495 type = get_type_on_stack(cctx, 0);
1477 if (type != &t_float && need_type(type, &t_number, 1496 if (type != &t_float && need_type(type, &t_number,
1478 -1, 0, cctx, FALSE, FALSE) == FAIL) 1497 -1, 0, cctx, FALSE, FALSE) == FAIL)
1479 return FAIL; 1498 return FAIL;
1480 1499
1481 while (p > start && (p[-1] == '-' || p[-1] == '+')) 1500 while (p > start && (p[-1] == '-' || p[-1] == '+'))
1592 1611
1593 // Do not skip over white space to find the "(", "execute 'x' (expr)" 1612 // Do not skip over white space to find the "(", "execute 'x' (expr)"
1594 // is not a function call. 1613 // is not a function call.
1595 if (**arg == '(') 1614 if (**arg == '(')
1596 { 1615 {
1597 garray_T *stack = &cctx->ctx_type_stack;
1598 type_T *type; 1616 type_T *type;
1599 int argcount = 0; 1617 int argcount = 0;
1600 1618
1601 if (generate_ppconst(cctx, ppconst) == FAIL) 1619 if (generate_ppconst(cctx, ppconst) == FAIL)
1602 return FAIL; 1620 return FAIL;
1603 ppconst->pp_is_const = FALSE; 1621 ppconst->pp_is_const = FALSE;
1604 1622
1605 // funcref(arg) 1623 // funcref(arg)
1606 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; 1624 type = get_type_on_stack(cctx, 0);
1607 1625
1608 *arg = skipwhite(p + 1); 1626 *arg = skipwhite(p + 1);
1609 if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL) 1627 if (compile_arguments(arg, cctx, &argcount, FALSE) == FAIL)
1610 return FAIL; 1628 return FAIL;
1611 if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL) 1629 if (generate_PCALL(cctx, argcount, name_start, type, TRUE) == FAIL)
1670 1688
1671 // Move the instructions for the arguments to before the 1689 // Move the instructions for the arguments to before the
1672 // instructions of the expression and move the type of the 1690 // instructions of the expression and move the type of the
1673 // expression after the argument types. This is what ISN_PCALL 1691 // expression after the argument types. This is what ISN_PCALL
1674 // expects. 1692 // expects.
1675 stack = &cctx->ctx_type_stack;
1676 arg_isn_count = cctx->ctx_instr.ga_len - expr_isn_end; 1693 arg_isn_count = cctx->ctx_instr.ga_len - expr_isn_end;
1677 if (arg_isn_count > 0) 1694 if (arg_isn_count > 0)
1678 { 1695 {
1679 int expr_isn_count = expr_isn_end - expr_isn_start; 1696 int expr_isn_count = expr_isn_end - expr_isn_start;
1680 isn_T *isn = ALLOC_MULT(isn_T, expr_isn_count); 1697 isn_T *isn = ALLOC_MULT(isn_T, expr_isn_count);
1698 type_T *decl_type;
1699 type2_T *typep;
1681 1700
1682 if (isn == NULL) 1701 if (isn == NULL)
1683 return FAIL; 1702 return FAIL;
1684 mch_memmove(isn, ((isn_T *)cctx->ctx_instr.ga_data) 1703 mch_memmove(isn, ((isn_T *)cctx->ctx_instr.ga_data)
1685 + expr_isn_start, 1704 + expr_isn_start,
1691 mch_memmove(((isn_T *)cctx->ctx_instr.ga_data) 1710 mch_memmove(((isn_T *)cctx->ctx_instr.ga_data)
1692 + expr_isn_start + arg_isn_count, 1711 + expr_isn_start + arg_isn_count,
1693 isn, sizeof(isn_T) * expr_isn_count); 1712 isn, sizeof(isn_T) * expr_isn_count);
1694 vim_free(isn); 1713 vim_free(isn);
1695 1714
1696 type = ((type_T **)stack->ga_data)[type_idx_start]; 1715 typep = ((type2_T *)stack->ga_data) + type_idx_start;
1697 mch_memmove(((type_T **)stack->ga_data) + type_idx_start, 1716 type = typep->type_curr;
1698 ((type_T **)stack->ga_data) + type_idx_start + 1, 1717 decl_type = typep->type_decl;
1699 sizeof(type_T *) 1718 mch_memmove(((type2_T *)stack->ga_data) + type_idx_start,
1719 ((type2_T *)stack->ga_data) + type_idx_start + 1,
1720 sizeof(type2_T)
1700 * (stack->ga_len - type_idx_start - 1)); 1721 * (stack->ga_len - type_idx_start - 1));
1701 ((type_T **)stack->ga_data)[stack->ga_len - 1] = type; 1722 typep = ((type2_T *)stack->ga_data) + stack->ga_len - 1;
1723 typep->type_curr = type;
1724 typep->type_decl = decl_type;
1702 } 1725 }
1703 1726
1704 type = ((type_T **)stack->ga_data)[stack->ga_len - 1]; 1727 type = get_type_on_stack(cctx, 0);
1705 if (generate_PCALL(cctx, argcount, p - 2, type, FALSE) == FAIL) 1728 if (generate_PCALL(cctx, argcount, p - 2, type, FALSE) == FAIL)
1706 return FAIL; 1729 return FAIL;
1707 } 1730 }
1708 else 1731 else
1709 { 1732 {
2150 if (compile_expr8(arg, cctx, ppconst) == FAIL) 2173 if (compile_expr8(arg, cctx, ppconst) == FAIL)
2151 return FAIL; 2174 return FAIL;
2152 2175
2153 if (want_type != NULL) 2176 if (want_type != NULL)
2154 { 2177 {
2155 garray_T *stack = &cctx->ctx_type_stack;
2156 type_T *actual; 2178 type_T *actual;
2157 where_T where = WHERE_INIT; 2179 where_T where = WHERE_INIT;
2158 2180
2159 generate_ppconst(cctx, ppconst); 2181 generate_ppconst(cctx, ppconst);
2160 actual = ((type_T **)stack->ga_data)[stack->ga_len - 1]; 2182 actual = get_type_on_stack(cctx, 0);
2161 if (check_type_maybe(want_type, actual, FALSE, where) != OK) 2183 if (check_type_maybe(want_type, actual, FALSE, where) != OK)
2162 { 2184 {
2163 if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE) 2185 if (need_type(actual, want_type, -1, 0, cctx, FALSE, FALSE)
2164 == FAIL) 2186 == FAIL)
2165 return FAIL; 2187 return FAIL;
2779 if (op_falsy) 2801 if (op_falsy)
2780 end_idx = instr->ga_len; 2802 end_idx = instr->ga_len;
2781 generate_JUMP(cctx, op_falsy 2803 generate_JUMP(cctx, op_falsy
2782 ? JUMP_AND_KEEP_IF_TRUE : JUMP_IF_FALSE, 0); 2804 ? JUMP_AND_KEEP_IF_TRUE : JUMP_IF_FALSE, 0);
2783 if (op_falsy) 2805 if (op_falsy)
2784 type1 = ((type_T **)stack->ga_data)[stack->ga_len]; 2806 type1 = get_type_on_stack(cctx, -1);
2785 } 2807 }
2786 2808
2787 // evaluate the second expression; any type is accepted 2809 // evaluate the second expression; any type is accepted
2788 if (may_get_next_line_error(p + 1 + op_falsy, arg, cctx) == FAIL) 2810 if (may_get_next_line_error(p + 1 + op_falsy, arg, cctx) == FAIL)
2789 return FAIL; 2811 return FAIL;
2795 generate_ppconst(cctx, ppconst); 2817 generate_ppconst(cctx, ppconst);
2796 2818
2797 if (!op_falsy) 2819 if (!op_falsy)
2798 { 2820 {
2799 // remember the type and drop it 2821 // remember the type and drop it
2822 type1 = get_type_on_stack(cctx, 0);
2800 --stack->ga_len; 2823 --stack->ga_len;
2801 type1 = ((type_T **)stack->ga_data)[stack->ga_len];
2802 2824
2803 end_idx = instr->ga_len; 2825 end_idx = instr->ga_len;
2804 generate_JUMP(cctx, JUMP_ALWAYS, 0); 2826 generate_JUMP(cctx, JUMP_ALWAYS, 0);
2805 2827
2806 // jump here from JUMP_IF_FALSE 2828 // jump here from JUMP_IF_FALSE
2847 2869
2848 generate_ppconst(cctx, ppconst); 2870 generate_ppconst(cctx, ppconst);
2849 ppconst->pp_is_const = FALSE; 2871 ppconst->pp_is_const = FALSE;
2850 2872
2851 // If the types differ, the result has a more generic type. 2873 // If the types differ, the result has a more generic type.
2852 typep = ((type_T **)stack->ga_data) + stack->ga_len - 1; 2874 typep = &((((type2_T *)stack->ga_data)
2875 + stack->ga_len - 1)->type_curr);
2853 common_type(type1, *typep, typep, cctx->ctx_type_list); 2876 common_type(type1, *typep, typep, cctx->ctx_type_list);
2854 2877
2855 // jump here from JUMP_ALWAYS or JUMP_AND_KEEP_IF_TRUE 2878 // jump here from JUMP_ALWAYS or JUMP_AND_KEEP_IF_TRUE
2856 isn = ((isn_T *)instr->ga_data) + end_idx; 2879 isn = ((isn_T *)instr->ga_data) + end_idx;
2857 isn->isn_arg.jump.jump_where = instr->ga_len; 2880 isn->isn_arg.jump.jump_where = instr->ga_len;