Mercurial > vim
comparison src/vim9compile.c @ 23033:b98003d73150 v8.2.2063
patch 8.2.2063: Vim9: only one level of indexing supported
Commit: https://github.com/vim/vim/commit/dc234caff22131bdc1ff9ea50d67e11843d0d73e
Author: Bram Moolenaar <Bram@vim.org>
Date: Sat Nov 28 18:52:33 2020 +0100
patch 8.2.2063: Vim9: only one level of indexing supported
Problem: Vim9: only one level of indexing supported.
Solution: Handle more than one index in an assignment.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 28 Nov 2020 19:00:04 +0100 |
parents | a943b175586a |
children | 9775df18916b |
comparison
equal
deleted
inserted
replaced
23032:52326852b941 | 23033:b98003d73150 |
---|---|
4959 dest_window, | 4959 dest_window, |
4960 dest_tab, | 4960 dest_tab, |
4961 dest_vimvar, | 4961 dest_vimvar, |
4962 dest_script, | 4962 dest_script, |
4963 dest_reg, | 4963 dest_reg, |
4964 dest_expr, | |
4964 } assign_dest_T; | 4965 } assign_dest_T; |
4965 | 4966 |
4966 /* | 4967 /* |
4967 * Generate the load instruction for "name". | 4968 * Generate the load instruction for "name". |
4968 */ | 4969 */ |
5011 generate_LOAD(cctx, ISN_LOADOUTER, lvar->lv_idx, | 5012 generate_LOAD(cctx, ISN_LOADOUTER, lvar->lv_idx, |
5012 NULL, type); | 5013 NULL, type); |
5013 else | 5014 else |
5014 generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type); | 5015 generate_LOAD(cctx, ISN_LOAD, lvar->lv_idx, NULL, type); |
5015 break; | 5016 break; |
5016 } | 5017 case dest_expr: |
5018 // list or dict value should already be on the stack. | |
5019 break; | |
5020 } | |
5021 } | |
5022 | |
5023 /* | |
5024 * Skip over "[expr]" or ".member". | |
5025 * Does not check for any errors. | |
5026 */ | |
5027 static char_u * | |
5028 skip_index(char_u *start) | |
5029 { | |
5030 char_u *p = start; | |
5031 | |
5032 if (*p == '[') | |
5033 { | |
5034 p = skipwhite(p + 1); | |
5035 (void)skip_expr(&p, NULL); | |
5036 p = skipwhite(p); | |
5037 if (*p == ']') | |
5038 return p + 1; | |
5039 return p; | |
5040 } | |
5041 // if (*p == '.') | |
5042 return to_name_end(p + 1, TRUE); | |
5017 } | 5043 } |
5018 | 5044 |
5019 void | 5045 void |
5020 vim9_declare_error(char_u *name) | 5046 vim9_declare_error(char_u *name) |
5021 { | 5047 { |
5067 char_u *op; | 5093 char_u *op; |
5068 int oplen = 0; | 5094 int oplen = 0; |
5069 int heredoc = FALSE; | 5095 int heredoc = FALSE; |
5070 type_T *type = &t_any; | 5096 type_T *type = &t_any; |
5071 type_T *member_type = &t_any; | 5097 type_T *member_type = &t_any; |
5098 type_T *rhs_type = &t_any; | |
5072 char_u *name = NULL; | 5099 char_u *name = NULL; |
5073 char_u *sp; | 5100 char_u *sp; |
5074 int is_decl = cmdidx == CMD_let || cmdidx == CMD_var | 5101 int is_decl = cmdidx == CMD_let || cmdidx == CMD_var |
5075 || cmdidx == CMD_final || cmdidx == CMD_const; | 5102 || cmdidx == CMD_final || cmdidx == CMD_const; |
5076 | 5103 |
5155 FALSE, FALSE) == FAIL) | 5182 FALSE, FALSE) == FAIL) |
5156 goto theend; | 5183 goto theend; |
5157 // TODO: check the length of a constant list here | 5184 // TODO: check the length of a constant list here |
5158 generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count, | 5185 generate_CHECKLEN(cctx, semicolon ? var_count - 1 : var_count, |
5159 semicolon); | 5186 semicolon); |
5187 if (stacktype->tt_member != NULL) | |
5188 rhs_type = stacktype->tt_member; | |
5160 } | 5189 } |
5161 } | 5190 } |
5162 | 5191 |
5163 /* | 5192 /* |
5164 * Loop over variables in "[var, var] = expr". | 5193 * Loop over variables in "[var, var] = expr". |
5465 | 5494 |
5466 member_type = type; | 5495 member_type = type; |
5467 if (var_end > var_start + varlen) | 5496 if (var_end > var_start + varlen) |
5468 { | 5497 { |
5469 // Something follows after the variable: "var[idx]" or "var.key". | 5498 // Something follows after the variable: "var[idx]" or "var.key". |
5499 // TODO: should we also handle "->func()" here? | |
5470 if (is_decl) | 5500 if (is_decl) |
5471 { | 5501 { |
5472 emsg(_(e_cannot_use_index_when_declaring_variable)); | 5502 emsg(_(e_cannot_use_index_when_declaring_variable)); |
5473 goto theend; | 5503 goto theend; |
5474 } | 5504 } |
5475 | 5505 |
5476 if (var_start[varlen] == '[' || var_start[varlen] == '.') | 5506 if (var_start[varlen] == '[' || var_start[varlen] == '.') |
5477 { | 5507 { |
5508 char_u *after = var_start + varlen; | |
5509 | |
5510 // Only the last index is used below, if there are others | |
5511 // before it generate code for the expression. Thus for | |
5512 // "ll[1][2]" the expression is "ll[1]" and "[2]" is the index. | |
5513 for (;;) | |
5514 { | |
5515 p = skip_index(after); | |
5516 if (*p != '[' && *p != '.') | |
5517 break; | |
5518 after = p; | |
5519 } | |
5520 if (after > var_start + varlen) | |
5521 { | |
5522 varlen = after - var_start; | |
5523 dest = dest_expr; | |
5524 // We don't know the type before evaluating the expression, | |
5525 // use "any" until then. | |
5526 type = &t_any; | |
5527 } | |
5528 | |
5478 has_index = TRUE; | 5529 has_index = TRUE; |
5479 if (type->tt_member == NULL) | 5530 if (type->tt_member == NULL) |
5480 member_type = &t_any; | 5531 member_type = &t_any; |
5481 else | 5532 else |
5482 member_type = type->tt_member; | 5533 member_type = type->tt_member; |
5509 compile_expr0(&p, cctx); | 5560 compile_expr0(&p, cctx); |
5510 } | 5561 } |
5511 } | 5562 } |
5512 else if (oplen > 0) | 5563 else if (oplen > 0) |
5513 { | 5564 { |
5514 type_T *stacktype; | |
5515 int is_const = FALSE; | 5565 int is_const = FALSE; |
5516 | 5566 |
5517 // For "var = expr" evaluate the expression. | 5567 // For "var = expr" evaluate the expression. |
5518 if (var_count == 0) | 5568 if (var_count == 0) |
5519 { | 5569 { |
5556 // list. | 5606 // list. |
5557 if (generate_GETITEM(cctx, var_idx) == FAIL) | 5607 if (generate_GETITEM(cctx, var_idx) == FAIL) |
5558 return FAIL; | 5608 return FAIL; |
5559 } | 5609 } |
5560 | 5610 |
5561 stacktype = stack->ga_len == 0 ? &t_void | 5611 rhs_type = stack->ga_len == 0 ? &t_void |
5562 : ((type_T **)stack->ga_data)[stack->ga_len - 1]; | 5612 : ((type_T **)stack->ga_data)[stack->ga_len - 1]; |
5563 if (lvar != NULL && (is_decl || !has_type)) | 5613 if (lvar != NULL && (is_decl || !has_type)) |
5564 { | 5614 { |
5565 if ((stacktype->tt_type == VAR_FUNC | 5615 if ((rhs_type->tt_type == VAR_FUNC |
5566 || stacktype->tt_type == VAR_PARTIAL) | 5616 || rhs_type->tt_type == VAR_PARTIAL) |
5567 && var_wrong_func_name(name, TRUE)) | 5617 && var_wrong_func_name(name, TRUE)) |
5568 goto theend; | 5618 goto theend; |
5569 | 5619 |
5570 if (new_local && !has_type) | 5620 if (new_local && !has_type) |
5571 { | 5621 { |
5572 if (stacktype->tt_type == VAR_VOID) | 5622 if (rhs_type->tt_type == VAR_VOID) |
5573 { | 5623 { |
5574 emsg(_(e_cannot_use_void_value)); | 5624 emsg(_(e_cannot_use_void_value)); |
5575 goto theend; | 5625 goto theend; |
5576 } | 5626 } |
5577 else | 5627 else |
5578 { | 5628 { |
5579 // An empty list or dict has a &t_unknown member, | 5629 // An empty list or dict has a &t_unknown member, |
5580 // for a variable that implies &t_any. | 5630 // for a variable that implies &t_any. |
5581 if (stacktype == &t_list_empty) | 5631 if (rhs_type == &t_list_empty) |
5582 lvar->lv_type = &t_list_any; | 5632 lvar->lv_type = &t_list_any; |
5583 else if (stacktype == &t_dict_empty) | 5633 else if (rhs_type == &t_dict_empty) |
5584 lvar->lv_type = &t_dict_any; | 5634 lvar->lv_type = &t_dict_any; |
5585 else if (stacktype == &t_unknown) | 5635 else if (rhs_type == &t_unknown) |
5586 lvar->lv_type = &t_any; | 5636 lvar->lv_type = &t_any; |
5587 else | 5637 else |
5588 lvar->lv_type = stacktype; | 5638 lvar->lv_type = rhs_type; |
5589 } | 5639 } |
5590 } | 5640 } |
5591 else if (*op == '=') | 5641 else if (*op == '=') |
5592 { | 5642 { |
5593 type_T *use_type = lvar->lv_type; | 5643 type_T *use_type = lvar->lv_type; |
5594 | 5644 |
5595 // without operator check type here, otherwise below | 5645 // without operator check type here, otherwise below |
5596 if (has_index) | 5646 if (has_index) |
5597 { | 5647 { |
5598 use_type = use_type->tt_member; | 5648 use_type = member_type; |
5599 if (use_type == NULL) | 5649 if (member_type == NULL) |
5600 // could be indexing "any" | 5650 // could be indexing "any" |
5601 use_type = &t_any; | 5651 use_type = &t_any; |
5602 } | 5652 } |
5603 if (need_type(stacktype, use_type, -1, cctx, | 5653 if (need_type(rhs_type, use_type, -1, cctx, |
5604 FALSE, is_const) == FAIL) | 5654 FALSE, is_const) == FAIL) |
5605 goto theend; | 5655 goto theend; |
5606 } | 5656 } |
5607 } | 5657 } |
5608 else if (*p != '=' && need_type(stacktype, member_type, -1, | 5658 else if (*p != '=' && need_type(rhs_type, member_type, -1, |
5609 cctx, FALSE, FALSE) == FAIL) | 5659 cctx, FALSE, FALSE) == FAIL) |
5610 goto theend; | 5660 goto theend; |
5611 } | 5661 } |
5612 else if (cmdidx == CMD_final) | 5662 else if (cmdidx == CMD_final) |
5613 { | 5663 { |
5769 | 5819 |
5770 // Load the dict or list. On the stack we then have: | 5820 // Load the dict or list. On the stack we then have: |
5771 // - value | 5821 // - value |
5772 // - index | 5822 // - index |
5773 // - variable | 5823 // - variable |
5774 generate_loadvar(cctx, dest, name, lvar, type); | 5824 if (dest == dest_expr) |
5825 { | |
5826 int c = var_start[varlen]; | |
5827 | |
5828 // Evaluate "ll[expr]" of "ll[expr][idx]" | |
5829 p = var_start; | |
5830 var_start[varlen] = NUL; | |
5831 if (compile_expr0(&p, cctx) == OK && p != var_start + varlen) | |
5832 { | |
5833 // this should not happen | |
5834 emsg(_(e_missbrac)); | |
5835 goto theend; | |
5836 } | |
5837 var_start[varlen] = c; | |
5838 | |
5839 type = stack->ga_len == 0 ? &t_void | |
5840 : ((type_T **)stack->ga_data)[stack->ga_len - 1]; | |
5841 // now we can properly check the type | |
5842 if (type->tt_member != NULL | |
5843 && need_type(rhs_type, type->tt_member, -2, cctx, | |
5844 FALSE, FALSE) == FAIL) | |
5845 goto theend; | |
5846 } | |
5847 else | |
5848 generate_loadvar(cctx, dest, name, lvar, type); | |
5775 | 5849 |
5776 if (type->tt_type == VAR_LIST) | 5850 if (type->tt_type == VAR_LIST) |
5777 { | 5851 { |
5778 if (generate_instr_drop(cctx, ISN_STORELIST, 3) == FAIL) | 5852 if (generate_instr_drop(cctx, ISN_STORELIST, 3) == FAIL) |
5779 return FAIL; | 5853 return FAIL; |
5783 if (generate_instr_drop(cctx, ISN_STOREDICT, 3) == FAIL) | 5857 if (generate_instr_drop(cctx, ISN_STOREDICT, 3) == FAIL) |
5784 return FAIL; | 5858 return FAIL; |
5785 } | 5859 } |
5786 else | 5860 else |
5787 { | 5861 { |
5788 emsg(_(e_listreq)); | 5862 emsg(_(e_indexable_type_required)); |
5789 goto theend; | 5863 goto theend; |
5790 } | 5864 } |
5791 } | 5865 } |
5792 else | 5866 else |
5793 { | 5867 { |
5879 generate_STORE(cctx, ISN_STOREOUTER, lvar->lv_idx, | 5953 generate_STORE(cctx, ISN_STOREOUTER, lvar->lv_idx, |
5880 NULL); | 5954 NULL); |
5881 else | 5955 else |
5882 generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL); | 5956 generate_STORE(cctx, ISN_STORE, lvar->lv_idx, NULL); |
5883 } | 5957 } |
5958 break; | |
5959 case dest_expr: | |
5960 // cannot happen | |
5884 break; | 5961 break; |
5885 } | 5962 } |
5886 } | 5963 } |
5887 | 5964 |
5888 if (var_idx + 1 < var_count) | 5965 if (var_idx + 1 < var_count) |