Mercurial > vim
comparison src/vim9execute.c @ 19862:846fbbacce3a v8.2.0487
patch 8.2.0487: Vim9: compiling not sufficiently tested
Commit: https://github.com/vim/vim/commit/bd5da371aafe5a2207065643502f4d1ff6b286c7
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue Mar 31 23:13:10 2020 +0200
patch 8.2.0487: Vim9: compiling not sufficiently tested
Problem: Vim9: compiling not sufficiently tested.
Solution: Add more tests. Fix bug with PCALL.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Tue, 31 Mar 2020 23:15:04 +0200 |
parents | e4ade28bfaf7 |
children | 8a7bede7b138 |
comparison
equal
deleted
inserted
replaced
19861:e517915a786d | 19862:846fbbacce3a |
---|---|
343 } | 343 } |
344 | 344 |
345 static int | 345 static int |
346 call_partial(typval_T *tv, int argcount, ectx_T *ectx) | 346 call_partial(typval_T *tv, int argcount, ectx_T *ectx) |
347 { | 347 { |
348 char_u *name; | 348 char_u *name = NULL; |
349 int called_emsg_before = called_emsg; | 349 int called_emsg_before = called_emsg; |
350 | 350 |
351 if (tv->v_type == VAR_PARTIAL) | 351 if (tv->v_type == VAR_PARTIAL) |
352 { | 352 { |
353 partial_T *pt = tv->vval.v_partial; | 353 partial_T *pt = tv->vval.v_partial; |
354 | 354 |
355 if (pt->pt_func != NULL) | 355 if (pt->pt_func != NULL) |
356 return call_ufunc(pt->pt_func, argcount, ectx, NULL); | 356 return call_ufunc(pt->pt_func, argcount, ectx, NULL); |
357 name = pt->pt_name; | 357 name = pt->pt_name; |
358 } | 358 } |
359 else | 359 else if (tv->v_type == VAR_FUNC) |
360 name = tv->vval.v_string; | 360 name = tv->vval.v_string; |
361 if (call_by_name(name, argcount, ectx, NULL) == FAIL) | 361 if (name == NULL || call_by_name(name, argcount, ectx, NULL) == FAIL) |
362 { | 362 { |
363 if (called_emsg == called_emsg_before) | 363 if (called_emsg == called_emsg_before) |
364 semsg(_(e_unknownfunc), name); | 364 semsg(_(e_unknownfunc), name); |
365 return FAIL; | 365 return FAIL; |
366 } | 366 } |
419 ectx_T ectx; // execution context | 419 ectx_T ectx; // execution context |
420 int initial_frame_ptr; | 420 int initial_frame_ptr; |
421 typval_T *tv; | 421 typval_T *tv; |
422 int idx; | 422 int idx; |
423 int ret = FAIL; | 423 int ret = FAIL; |
424 dfunc_T *dfunc; | |
425 int defcount = ufunc->uf_args.ga_len - argc; | 424 int defcount = ufunc->uf_args.ga_len - argc; |
426 | 425 |
427 // Get pointer to item in the stack. | 426 // Get pointer to item in the stack. |
428 #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) | 427 #define STACK_TV(idx) (((typval_T *)ectx.ec_stack.ga_data) + idx) |
429 | 428 |
465 { | 464 { |
466 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN; | 465 STACK_TV(ectx.ec_stack.ga_len)->v_type = VAR_UNKNOWN; |
467 ++ectx.ec_stack.ga_len; | 466 ++ectx.ec_stack.ga_len; |
468 } | 467 } |
469 | 468 |
470 // Reserve space for local variables. | 469 { |
471 dfunc = ((dfunc_T *)def_functions.ga_data) + ufunc->uf_dfunc_idx; | 470 // Reserve space for local variables. |
472 for (idx = 0; idx < dfunc->df_varcount; ++idx) | 471 dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) |
473 STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN; | 472 + ufunc->uf_dfunc_idx; |
474 ectx.ec_stack.ga_len += dfunc->df_varcount; | 473 |
475 | 474 for (idx = 0; idx < dfunc->df_varcount; ++idx) |
476 ectx.ec_instr = dfunc->df_instr; | 475 STACK_TV_VAR(idx)->v_type = VAR_UNKNOWN; |
476 ectx.ec_stack.ga_len += dfunc->df_varcount; | |
477 | |
478 ectx.ec_instr = dfunc->df_instr; | |
479 } | |
477 | 480 |
478 // Decide where to start execution, handles optional arguments. | 481 // Decide where to start execution, handles optional arguments. |
479 init_instr_idx(ufunc, argc, &ectx); | 482 init_instr_idx(ufunc, argc, &ectx); |
480 | 483 |
481 for (;;) | 484 for (;;) |
1020 r = call_partial(tv, pfunc->cpf_argcount, &ectx); | 1023 r = call_partial(tv, pfunc->cpf_argcount, &ectx); |
1021 if (tv == &partial) | 1024 if (tv == &partial) |
1022 clear_tv(&partial); | 1025 clear_tv(&partial); |
1023 if (r == FAIL) | 1026 if (r == FAIL) |
1024 goto failed; | 1027 goto failed; |
1025 | 1028 } |
1026 if (pfunc->cpf_top) | 1029 break; |
1027 { | 1030 |
1028 // Get the funcref from the stack, overwrite with the | 1031 case ISN_PCALL_END: |
1029 // return value. | 1032 // PCALL finished, arguments have been consumed and replaced by |
1030 clear_tv(tv); | 1033 // the return value. Now clear the funcref from the stack, |
1031 --ectx.ec_stack.ga_len; | 1034 // and move the return value in its place. |
1032 *STACK_TV_BOT(-1) = *STACK_TV_BOT(0); | 1035 --ectx.ec_stack.ga_len; |
1033 } | 1036 clear_tv(STACK_TV_BOT(-1)); |
1034 } | 1037 *STACK_TV_BOT(-1) = *STACK_TV_BOT(0); |
1035 break; | 1038 break; |
1036 | 1039 |
1037 // call a user defined function or funcref/partial | 1040 // call a user defined function or funcref/partial |
1038 case ISN_UCALL: | 1041 case ISN_UCALL: |
1039 { | 1042 { |
1076 | 1079 |
1077 // push a function reference to a compiled function | 1080 // push a function reference to a compiled function |
1078 case ISN_FUNCREF: | 1081 case ISN_FUNCREF: |
1079 { | 1082 { |
1080 partial_T *pt = NULL; | 1083 partial_T *pt = NULL; |
1084 dfunc_T *dfunc; | |
1081 | 1085 |
1082 pt = ALLOC_CLEAR_ONE(partial_T); | 1086 pt = ALLOC_CLEAR_ONE(partial_T); |
1083 if (pt == NULL) | 1087 if (pt == NULL) |
1084 goto failed; | 1088 goto failed; |
1085 dfunc = ((dfunc_T *)def_functions.ga_data) | 1089 dfunc = ((dfunc_T *)def_functions.ga_data) |
2002 cpfunc_T *cpfunc = &iptr->isn_arg.pfunc; | 2006 cpfunc_T *cpfunc = &iptr->isn_arg.pfunc; |
2003 | 2007 |
2004 smsg("%4d PCALL%s (argc %d)", current, | 2008 smsg("%4d PCALL%s (argc %d)", current, |
2005 cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount); | 2009 cpfunc->cpf_top ? " top" : "", cpfunc->cpf_argcount); |
2006 } | 2010 } |
2011 break; | |
2012 case ISN_PCALL_END: | |
2013 smsg("%4d PCALL end", current); | |
2007 break; | 2014 break; |
2008 case ISN_RETURN: | 2015 case ISN_RETURN: |
2009 smsg("%4d RETURN", current); | 2016 smsg("%4d RETURN", current); |
2010 break; | 2017 break; |
2011 case ISN_FUNCREF: | 2018 case ISN_FUNCREF: |