" Test the :disassemble command, and compilation as a side effect
source check.vim
+source vim9.vim
func NotCompiled()
echo "not"
enddef
def Test_disassemble_push()
- var res = execute('disass s:ScriptFuncPush')
- assert_match('<SNR>\d*_ScriptFuncPush.*' ..
- 'localbool = true.*' ..
- ' PUSH true.*' ..
- 'localspec = v:none.*' ..
- ' PUSH v:none.*' ..
- 'localblob = 0z1234.*' ..
- ' PUSHBLOB 0z1234.*',
- res)
- if has('float')
- assert_match('<SNR>\d*_ScriptFuncPush.*' ..
- 'localfloat = 1.234.*' ..
- ' PUSHF 1.234.*',
- res)
- endif
+ mkdir('Xdir/autoload', 'p')
+ var save_rtp = &rtp
+ exe 'set rtp^=' .. getcwd() .. '/Xdir'
+
+ var lines =<< trim END
+ vim9script
+ END
+ writefile(lines, 'Xdir/autoload/autoscript.vim')
+
+ lines =<< trim END
+ vim9script
+ import autoload 'autoscript.vim'
+
+ def s:AutoloadFunc()
+ &operatorfunc = autoscript.Opfunc
+ enddef
+
+ var res = execute('disass s:AutoloadFunc')
+ assert_match('<SNR>\d*_AutoloadFunc.*' ..
+ '&operatorfunc = autoscript.Opfunc\_s*' ..
+ '0 AUTOLOAD autoscript#Opfunc\_s*' ..
+ '1 STOREFUNCOPT &operatorfunc\_s*' ..
+ '2 RETURN void',
+ res)
+ END
+ CheckScriptSuccess(lines)
+
+ delete('Xdir', 'rf')
+ &rtp = save_rtp
enddef
def s:ScriptFuncStore()
return OK;
}
+/*
+ * Load instruction for w:/b:/g:/t: variable.
+ * "isn_type" is used instead of "iptr->isn_type".
+ */
+ static int
+load_namespace_var(ectx_T *ectx, isntype_T isn_type, isn_T *iptr)
+{
+ dictitem_T *di = NULL;
+ hashtab_T *ht = NULL;
+ char namespace;
+
+ if (GA_GROW_FAILS(&ectx->ec_stack, 1))
+ return NOTDONE;
+ switch (isn_type)
+ {
+ case ISN_LOADG:
+ ht = get_globvar_ht();
+ namespace = 'g';
+ break;
+ case ISN_LOADB:
+ ht = &curbuf->b_vars->dv_hashtab;
+ namespace = 'b';
+ break;
+ case ISN_LOADW:
+ ht = &curwin->w_vars->dv_hashtab;
+ namespace = 'w';
+ break;
+ case ISN_LOADT:
+ ht = &curtab->tp_vars->dv_hashtab;
+ namespace = 't';
+ break;
+ default: // Cannot reach here
+ return NOTDONE;
+ }
+ di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE);
+
+ if (di == NULL && ht == get_globvar_ht()
+ && vim_strchr(iptr->isn_arg.string,
+ AUTOLOAD_CHAR) != NULL)
+ {
+ // Global variable has an autoload name, may still need
+ // to load the script.
+ if (script_autoload(iptr->isn_arg.string, FALSE))
+ di = find_var_in_ht(ht, 0,
+ iptr->isn_arg.string, TRUE);
+ if (did_emsg)
+ return FAIL;
+ }
+
+ if (di == NULL)
+ {
+ SOURCING_LNUM = iptr->isn_lnum;
+ if (vim_strchr(iptr->isn_arg.string,
+ AUTOLOAD_CHAR) != NULL)
+ // no check if the item exists in the script but
+ // isn't exported, it is too complicated
+ semsg(_(e_item_not_found_in_script_str),
+ iptr->isn_arg.string);
+ else
+ semsg(_(e_undefined_variable_char_str),
+ namespace, iptr->isn_arg.string);
+ return FAIL;
+ }
+ else
+ {
+ copy_tv(&di->di_tv, STACK_TV_BOT(0));
+ ++ectx->ec_stack.ga_len;
+ }
+ return OK;
+}
+
/*
* Execute instructions in execution context "ectx".
* Return OK or FAIL;
case ISN_LOADW:
case ISN_LOADT:
{
- dictitem_T *di = NULL;
- hashtab_T *ht = NULL;
- char namespace;
+ int res = load_namespace_var(ectx, iptr->isn_type, iptr);
- if (GA_GROW_FAILS(&ectx->ec_stack, 1))
+ if (res == NOTDONE)
goto theend;
- switch (iptr->isn_type)
- {
- case ISN_LOADG:
- ht = get_globvar_ht();
- namespace = 'g';
- break;
- case ISN_LOADB:
- ht = &curbuf->b_vars->dv_hashtab;
- namespace = 'b';
- break;
- case ISN_LOADW:
- ht = &curwin->w_vars->dv_hashtab;
- namespace = 'w';
- break;
- case ISN_LOADT:
- ht = &curtab->tp_vars->dv_hashtab;
- namespace = 't';
- break;
- default: // Cannot reach here
- goto theend;
- }
- di = find_var_in_ht(ht, 0, iptr->isn_arg.string, TRUE);
-
- if (di == NULL && ht == get_globvar_ht()
- && vim_strchr(iptr->isn_arg.string,
- AUTOLOAD_CHAR) != NULL)
- {
- // Global variable has an autoload name, may still need
- // to load the script.
- if (script_autoload(iptr->isn_arg.string, FALSE))
- di = find_var_in_ht(ht, 0,
- iptr->isn_arg.string, TRUE);
- if (did_emsg)
- goto on_error;
- }
-
- if (di == NULL)
- {
- SOURCING_LNUM = iptr->isn_lnum;
- if (vim_strchr(iptr->isn_arg.string,
- AUTOLOAD_CHAR) != NULL)
- // no check if the item exists in the script but
- // isn't exported, it is too complicated
- semsg(_(e_item_not_found_in_script_str),
- iptr->isn_arg.string);
- else
- semsg(_(e_undefined_variable_char_str),
- namespace, iptr->isn_arg.string);
+ if (res == FAIL)
goto on_error;
- }
- else
- {
- copy_tv(&di->di_tv, STACK_TV_BOT(0));
- ++ectx->ec_stack.ga_len;
- }
}
+
break;
// load autoload variable
}
break;
+ case ISN_AUTOLOAD:
+ {
+ char_u *name = iptr->isn_arg.string;
+
+ (void)script_autoload(name, FALSE);
+ if (find_func(name, TRUE))
+ {
+ if (GA_GROW_FAILS(&ectx->ec_stack, 1))
+ goto theend;
+ tv = STACK_TV_BOT(0);
+ tv->v_lock = 0;
+ ++ectx->ec_stack.ga_len;
+ tv->v_type = VAR_FUNC;
+ tv->vval.v_string = vim_strsave(name);
+ }
+ else
+ {
+ int res = load_namespace_var(ectx, ISN_LOADG, iptr);
+
+ if (res == NOTDONE)
+ goto theend;
+ if (res == FAIL)
+ goto on_error;
+ }
+ }
+ break;
+
case ISN_UNLET:
if (do_unlet(iptr->isn_arg.unlet.ul_name,
iptr->isn_arg.unlet.ul_forceit) == FAIL)
case ISN_PUSHEXC:
smsg("%s%4d PUSH v:exception", pfx, current);
break;
+ case ISN_AUTOLOAD:
+ smsg("%s%4d AUTOLOAD %s", pfx, current, iptr->isn_arg.string);
+ break;
case ISN_UNLET:
smsg("%s%4d UNLET%s %s", pfx, current,
iptr->isn_arg.unlet.ul_forceit ? "!" : "",