Mercurial > vim
comparison src/vim9compile.c @ 31551:67d9fbe516a3 v9.0.1108
patch 9.0.1108: type error when using "any" type and adding to float
Commit: https://github.com/vim/vim/commit/c6951a76a58663ef8a773d340f2260da7455643c
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Dec 29 20:56:24 2022 +0000
patch 9.0.1108: type error when using "any" type and adding to float
Problem: Type error when using "any" type and adding a number to a float.
Solution: Accept both a number and a float. (closes https://github.com/vim/vim/issues/11753)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Thu, 29 Dec 2022 22:00:04 +0100 |
parents | cd5247f4da06 |
children | aee868b9229a |
comparison
equal
deleted
inserted
replaced
31550:aadc3446d666 | 31551:67d9fbe516a3 |
---|---|
449 */ | 449 */ |
450 int | 450 int |
451 need_type_where( | 451 need_type_where( |
452 type_T *actual, | 452 type_T *actual, |
453 type_T *expected, | 453 type_T *expected, |
454 int number_ok, // expect VAR_FLOAT but VAR_NUMBER is OK | |
454 int offset, | 455 int offset, |
455 where_T where, | 456 where_T where, |
456 cctx_T *cctx, | 457 cctx_T *cctx, |
457 int silent, | 458 int silent, |
458 int actual_is_const) | 459 int actual_is_const) |
478 return OK; | 479 return OK; |
479 | 480 |
480 // If the actual type can be the expected type add a runtime check. | 481 // If the actual type can be the expected type add a runtime check. |
481 if (!actual_is_const && ret == MAYBE && use_typecheck(actual, expected)) | 482 if (!actual_is_const && ret == MAYBE && use_typecheck(actual, expected)) |
482 { | 483 { |
483 generate_TYPECHECK(cctx, expected, offset, | 484 generate_TYPECHECK(cctx, expected, number_ok, offset, |
484 where.wt_variable, where.wt_index); | 485 where.wt_variable, where.wt_index); |
485 return OK; | 486 return OK; |
486 } | 487 } |
487 | 488 |
488 if (!silent) | 489 if (!silent) |
492 | 493 |
493 int | 494 int |
494 need_type( | 495 need_type( |
495 type_T *actual, | 496 type_T *actual, |
496 type_T *expected, | 497 type_T *expected, |
498 int number_ok, // when expected is float number is also OK | |
497 int offset, | 499 int offset, |
498 int arg_idx, | 500 int arg_idx, |
499 cctx_T *cctx, | 501 cctx_T *cctx, |
500 int silent, | 502 int silent, |
501 int actual_is_const) | 503 int actual_is_const) |
502 { | 504 { |
503 where_T where = WHERE_INIT; | 505 where_T where = WHERE_INIT; |
504 | 506 |
505 where.wt_index = arg_idx; | 507 where.wt_index = arg_idx; |
506 return need_type_where(actual, expected, offset, where, | 508 return need_type_where(actual, expected, number_ok, offset, where, |
507 cctx, silent, actual_is_const); | 509 cctx, silent, actual_is_const); |
508 } | 510 } |
509 | 511 |
510 /* | 512 /* |
511 * Set type of variable "lvar" to "type". If the variable is a constant then | 513 * Set type of variable "lvar" to "type". If the variable is a constant then |
1998 lhs->lhs_type = cctx->ctx_type_stack.ga_len == 0 ? &t_void | 2000 lhs->lhs_type = cctx->ctx_type_stack.ga_len == 0 ? &t_void |
1999 : get_type_on_stack(cctx, 0); | 2001 : get_type_on_stack(cctx, 0); |
2000 // now we can properly check the type | 2002 // now we can properly check the type |
2001 if (rhs_type != NULL && lhs->lhs_type->tt_member != NULL | 2003 if (rhs_type != NULL && lhs->lhs_type->tt_member != NULL |
2002 && rhs_type != &t_void | 2004 && rhs_type != &t_void |
2003 && need_type(rhs_type, lhs->lhs_type->tt_member, -2, 0, cctx, | 2005 && need_type(rhs_type, lhs->lhs_type->tt_member, FALSE, |
2004 FALSE, FALSE) == FAIL) | 2006 -2, 0, cctx, FALSE, FALSE) == FAIL) |
2005 return FAIL; | 2007 return FAIL; |
2006 } | 2008 } |
2007 else | 2009 else |
2008 generate_loadvar(cctx, lhs); | 2010 generate_loadvar(cctx, lhs); |
2009 return OK; | 2011 return OK; |
2088 type_T *type; | 2090 type_T *type; |
2089 | 2091 |
2090 if (range) | 2092 if (range) |
2091 { | 2093 { |
2092 type = get_type_on_stack(cctx, 1); | 2094 type = get_type_on_stack(cctx, 1); |
2093 if (need_type(type, &t_number, | 2095 if (need_type(type, &t_number, FALSE, |
2094 -2, 0, cctx, FALSE, FALSE) == FAIL) | 2096 -2, 0, cctx, FALSE, FALSE) == FAIL) |
2095 return FAIL; | 2097 return FAIL; |
2096 } | 2098 } |
2097 type = get_type_on_stack(cctx, 0); | 2099 type = get_type_on_stack(cctx, 0); |
2098 if ((dest_type != VAR_BLOB && type->tt_type != VAR_SPECIAL) | 2100 if ((dest_type != VAR_BLOB && type->tt_type != VAR_SPECIAL) |
2099 && need_type(type, &t_number, | 2101 && need_type(type, &t_number, FALSE, |
2100 -1, 0, cctx, FALSE, FALSE) == FAIL) | 2102 -1, 0, cctx, FALSE, FALSE) == FAIL) |
2101 return FAIL; | 2103 return FAIL; |
2102 } | 2104 } |
2103 } | 2105 } |
2104 | 2106 |
2355 if (stacktype->tt_type == VAR_VOID) | 2357 if (stacktype->tt_type == VAR_VOID) |
2356 { | 2358 { |
2357 emsg(_(e_cannot_use_void_value)); | 2359 emsg(_(e_cannot_use_void_value)); |
2358 goto theend; | 2360 goto theend; |
2359 } | 2361 } |
2360 if (need_type(stacktype, &t_list_any, -1, 0, cctx, | 2362 if (need_type(stacktype, &t_list_any, FALSE, -1, 0, cctx, |
2361 FALSE, FALSE) == FAIL) | 2363 FALSE, FALSE) == FAIL) |
2362 goto theend; | 2364 goto theend; |
2363 // If a constant list was used we can check the length right here. | 2365 // If a constant list was used we can check the length right here. |
2364 needed_list_len = semicolon ? var_count - 1 : var_count; | 2366 needed_list_len = semicolon ? var_count - 1 : var_count; |
2365 if (instr->ga_len > 0) | 2367 if (instr->ga_len > 0) |
2422 goto theend; | 2424 goto theend; |
2423 if (heredoc) | 2425 if (heredoc) |
2424 { | 2426 { |
2425 SOURCING_LNUM = start_lnum; | 2427 SOURCING_LNUM = start_lnum; |
2426 if (lhs.lhs_has_type | 2428 if (lhs.lhs_has_type |
2427 && need_type(&t_list_string, lhs.lhs_type, | 2429 && need_type(&t_list_string, lhs.lhs_type, FALSE, |
2428 -1, 0, cctx, FALSE, FALSE) == FAIL) | 2430 -1, 0, cctx, FALSE, FALSE) == FAIL) |
2429 goto theend; | 2431 goto theend; |
2430 } | 2432 } |
2431 else | 2433 else |
2432 { | 2434 { |
2547 // member type. Not for "list[:] =". | 2549 // member type. Not for "list[:] =". |
2548 if (lhs.lhs_has_index | 2550 if (lhs.lhs_has_index |
2549 && !has_list_index(var_start + lhs.lhs_varlen, | 2551 && !has_list_index(var_start + lhs.lhs_varlen, |
2550 cctx)) | 2552 cctx)) |
2551 use_type = lhs.lhs_member_type; | 2553 use_type = lhs.lhs_member_type; |
2552 if (need_type_where(rhs_type, use_type, -1, where, | 2554 if (need_type_where(rhs_type, use_type, FALSE, -1, |
2553 cctx, FALSE, is_const) == FAIL) | 2555 where, cctx, FALSE, is_const) == FAIL) |
2554 goto theend; | 2556 goto theend; |
2555 } | 2557 } |
2556 } | 2558 } |
2557 else | 2559 else |
2558 { | 2560 { |
2563 // Also: can assign a number to a float. | 2565 // Also: can assign a number to a float. |
2564 if ((lhs_type == &t_number_or_string | 2566 if ((lhs_type == &t_number_or_string |
2565 || lhs_type == &t_float) | 2567 || lhs_type == &t_float) |
2566 && rhs_type->tt_type == VAR_NUMBER) | 2568 && rhs_type->tt_type == VAR_NUMBER) |
2567 lhs_type = &t_number; | 2569 lhs_type = &t_number; |
2568 if (*p != '=' && need_type(rhs_type, lhs_type, | 2570 if (*p != '=' && need_type(rhs_type, lhs_type, FALSE, |
2569 -1, 0, cctx, FALSE, FALSE) == FAIL) | 2571 -1, 0, cctx, FALSE, FALSE) == FAIL) |
2570 goto theend; | 2572 goto theend; |
2571 } | 2573 } |
2572 } | 2574 } |
2573 else if (cmdidx == CMD_final) | 2575 else if (cmdidx == CMD_final) |
2620 expected = lhs.lhs_member_type; | 2622 expected = lhs.lhs_member_type; |
2621 stacktype = get_type_on_stack(cctx, 0); | 2623 stacktype = get_type_on_stack(cctx, 0); |
2622 if ( | 2624 if ( |
2623 // If variable is float operation with number is OK. | 2625 // If variable is float operation with number is OK. |
2624 !(expected == &t_float && (stacktype == &t_number | 2626 !(expected == &t_float && (stacktype == &t_number |
2625 || stacktype == &t_number_bool)) && | 2627 || stacktype == &t_number_bool)) |
2626 need_type(stacktype, expected, -1, 0, cctx, | 2628 && need_type(stacktype, expected, TRUE, -1, 0, cctx, |
2627 FALSE, FALSE) == FAIL) | 2629 FALSE, FALSE) == FAIL) |
2628 goto theend; | 2630 goto theend; |
2629 } | 2631 } |
2630 | 2632 |
2631 if (*op == '.') | 2633 if (*op == '.') |
3102 { | 3104 { |
3103 did_set_arg_type = TRUE; | 3105 did_set_arg_type = TRUE; |
3104 ufunc->uf_arg_types[arg_idx] = val_type; | 3106 ufunc->uf_arg_types[arg_idx] = val_type; |
3105 } | 3107 } |
3106 else if (need_type_where(val_type, ufunc->uf_arg_types[arg_idx], | 3108 else if (need_type_where(val_type, ufunc->uf_arg_types[arg_idx], |
3107 -1, where, &cctx, FALSE, FALSE) == FAIL) | 3109 FALSE, -1, where, &cctx, FALSE, FALSE) == FAIL) |
3108 goto erret; | 3110 goto erret; |
3109 | 3111 |
3110 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL) | 3112 if (generate_STORE(&cctx, ISN_STORE, i - count - off, NULL) == FAIL) |
3111 goto erret; | 3113 goto erret; |
3112 | 3114 |