summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/testdir/test_vim9_disassemble.vim20
-rw-r--r--src/testdir/test_vim9_expr.vim26
-rw-r--r--src/version.c2
-rw-r--r--src/vim9.h4
-rw-r--r--src/vim9compile.c89
-rw-r--r--src/vim9execute.c46
6 files changed, 147 insertions, 40 deletions
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim
index 3448d8557..98a9e207e 100644
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -21,9 +21,13 @@ def s:ScriptFuncLoad(arg: string)
echo v:version
echo s:scriptvar
echo g:globalvar
+ echo get(g:, "global")
echo b:buffervar
+ echo get(b:, "buffer")
echo w:windowvar
+ echo get(w:, "window")
echo t:tabpagevar
+ echo get(t:, "tab")
echo &tabstop
echo $ENVVAR
echo @z
@@ -47,9 +51,25 @@ def Test_disassemble_load()
' LOADV v:version.*' ..
' LOADS s:scriptvar from .*test_vim9_disassemble.vim.*' ..
' LOADG g:globalvar.*' ..
+ 'echo get(g:, "global")\_s*' ..
+ '\d\+ LOAD g:\_s*' ..
+ '\d\+ PUSHS "global"\_s*' ..
+ '\d\+ BCALL get(argc 2).*' ..
' LOADB b:buffervar.*' ..
+ 'echo get(b:, "buffer")\_s*' ..
+ '\d\+ LOAD b:\_s*' ..
+ '\d\+ PUSHS "buffer"\_s*' ..
+ '\d\+ BCALL get(argc 2).*' ..
' LOADW w:windowvar.*' ..
+ 'echo get(w:, "window")\_s*' ..
+ '\d\+ LOAD w:\_s*' ..
+ '\d\+ PUSHS "window"\_s*' ..
+ '\d\+ BCALL get(argc 2).*' ..
' LOADT t:tabpagevar.*' ..
+ 'echo get(t:, "tab")\_s*' ..
+ '\d\+ LOAD t:\_s*' ..
+ '\d\+ PUSHS "tab"\_s*' ..
+ '\d\+ BCALL get(argc 2).*' ..
' LOADENV $ENVVAR.*' ..
' LOADREG @z.*',
res)
diff --git a/src/testdir/test_vim9_expr.vim b/src/testdir/test_vim9_expr.vim
index de88ea7d8..7feec382a 100644
--- a/src/testdir/test_vim9_expr.vim
+++ b/src/testdir/test_vim9_expr.vim
@@ -1345,6 +1345,32 @@ def Test_expr7_register()
assert_equal('register a', @a)
enddef
+def Test_expr7_namespace()
+ g:some_var = 'some'
+ assert_equal('some', get(g:, 'some_var'))
+ assert_equal('some', get(g:, 'some_var', 'xxx'))
+ assert_equal('xxx', get(g:, 'no_var', 'xxx'))
+ unlet g:some_var
+
+ b:some_var = 'some'
+ assert_equal('some', get(b:, 'some_var'))
+ assert_equal('some', get(b:, 'some_var', 'xxx'))
+ assert_equal('xxx', get(b:, 'no_var', 'xxx'))
+ unlet b:some_var
+
+ w:some_var = 'some'
+ assert_equal('some', get(w:, 'some_var'))
+ assert_equal('some', get(w:, 'some_var', 'xxx'))
+ assert_equal('xxx', get(w:, 'no_var', 'xxx'))
+ unlet w:some_var
+
+ t:some_var = 'some'
+ assert_equal('some', get(t:, 'some_var'))
+ assert_equal('some', get(t:, 'some_var', 'xxx'))
+ assert_equal('xxx', get(t:, 'no_var', 'xxx'))
+ unlet t:some_var
+enddef
+
def Test_expr7_parens()
# (expr)
assert_equal(4, (6 * 4) / 6)
diff --git a/src/version.c b/src/version.c
index 6ffb98db5..936e4df96 100644
--- a/src/version.c
+++ b/src/version.c
@@ -755,6 +755,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 1250,
+/**/
1249,
/**/
1248,
diff --git a/src/vim9.h b/src/vim9.h
index 39d36f973..0d51c98b5 100644
--- a/src/vim9.h
+++ b/src/vim9.h
@@ -26,6 +26,10 @@ typedef enum {
ISN_LOADB, // push b: variable isn_arg.string
ISN_LOADW, // push w: variable isn_arg.string
ISN_LOADT, // push t: variable isn_arg.string
+ ISN_LOADGDICT, // push g: dict
+ ISN_LOADBDICT, // push b: dict
+ ISN_LOADWDICT, // push w: dict
+ ISN_LOADTDICT, // push t: dict
ISN_LOADS, // push s: variable isn_arg.loadstore
ISN_LOADOUTER, // push variable from outer scope isn_arg.number
ISN_LOADSCRIPT, // push script-local variable isn_arg.script.
diff --git a/src/vim9compile.c b/src/vim9compile.c
index a9db1d0b7..93a4d896c 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -147,6 +147,7 @@ static char e_var_notfound[] = N_("E1001: variable not found: %s");
static char e_syntax_at[] = N_("E1002: Syntax error at %s");
static char e_used_as_arg[] = N_("E1006: %s is used as an argument");
static char e_cannot_use_void[] = N_("E1031: Cannot use void value");
+static char e_namespace[] = N_("E1075: Namespace not supported: %s");
static void delete_def_function_contents(dfunc_T *dfunc);
static void arg_type_mismatch(type_T *expected, type_T *actual, int argidx);
@@ -2781,7 +2782,7 @@ generate_funcref(cctx_T *cctx, char_u *name)
compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
{
type_T *type;
- char_u *name;
+ char_u *name = NULL;
char_u *end = end_arg;
int res = FAIL;
int prev_called_emsg = called_emsg;
@@ -2790,48 +2791,52 @@ compile_load(char_u **arg, char_u *end_arg, cctx_T *cctx, int error)
{
// load namespaced variable
if (end <= *arg + 2)
- name = vim_strsave((char_u *)"[empty]");
- else
- name = vim_strnsave(*arg + 2, end - (*arg + 2));
- if (name == NULL)
- return FAIL;
-
- if (**arg == 'v')
- {
- res = generate_LOADV(cctx, name, error);
- }
- else if (**arg == 'g')
{
- // Global variables can be defined later, thus we don't check if it
- // exists, give error at runtime.
- res = generate_LOAD(cctx, ISN_LOADG, 0, name, &t_any);
- }
- else if (**arg == 's')
- {
- res = compile_load_scriptvar(cctx, name, NULL, NULL, error);
- }
- else if (**arg == 'b')
- {
- // Buffer-local variables can be defined later, thus we don't check
- // if it exists, give error at runtime.
- res = generate_LOAD(cctx, ISN_LOADB, 0, name, &t_any);
- }
- else if (**arg == 'w')
- {
- // Window-local variables can be defined later, thus we don't check
- // if it exists, give error at runtime.
- res = generate_LOAD(cctx, ISN_LOADW, 0, name, &t_any);
- }
- else if (**arg == 't')
- {
- // Tabpage-local variables can be defined later, thus we don't
- // check if it exists, give error at runtime.
- res = generate_LOAD(cctx, ISN_LOADT, 0, name, &t_any);
+ isntype_T isn_type;
+
+ switch (**arg)
+ {
+ case 'g': isn_type = ISN_LOADGDICT; break;
+ case 'w': isn_type = ISN_LOADWDICT; break;
+ case 't': isn_type = ISN_LOADTDICT; break;
+ case 'b': isn_type = ISN_LOADBDICT; break;
+ default:
+ semsg(_(e_namespace), *arg);
+ goto theend;
+ }
+ if (generate_instr_type(cctx, isn_type, &t_dict_any) == NULL)
+ goto theend;
+ res = OK;
}
else
{
- semsg("E1075: Namespace not supported: %s", *arg);
- goto theend;
+ isntype_T isn_type = ISN_DROP;
+
+ name = vim_strnsave(*arg + 2, end - (*arg + 2));
+ if (name == NULL)
+ return FAIL;
+
+ switch (**arg)
+ {
+ case 'v': res = generate_LOADV(cctx, name, error);
+ break;
+ case 's': res = compile_load_scriptvar(cctx, name,
+ NULL, NULL, error);
+ break;
+ case 'g': isn_type = ISN_LOADG; break;
+ case 'w': isn_type = ISN_LOADW; break;
+ case 't': isn_type = ISN_LOADT; break;
+ case 'b': isn_type = ISN_LOADB; break;
+ default: semsg(_(e_namespace), *arg);
+ goto theend;
+ }
+ if (isn_type != ISN_DROP)
+ {
+ // Global, Buffer-local, Window-local and Tabpage-local
+ // variables can be defined later, thus we don't check if it
+ // exists, give error at runtime.
+ res = generate_LOAD(cctx, isn_type, 0, name, &t_any);
+ }
}
}
else
@@ -7556,10 +7561,14 @@ delete_instr(isn_T *isn)
case ISN_MEMBER:
case ISN_JUMP:
case ISN_LOAD:
+ case ISN_LOADBDICT:
+ case ISN_LOADGDICT:
case ISN_LOADOUTER:
- case ISN_LOADSCRIPT:
case ISN_LOADREG:
+ case ISN_LOADSCRIPT:
+ case ISN_LOADTDICT:
case ISN_LOADV:
+ case ISN_LOADWDICT:
case ISN_NEGATENR:
case ISN_NEWDICT:
case ISN_NEWLIST:
diff --git a/src/vim9execute.c b/src/vim9execute.c
index 9612bf461..35419dae4 100644
--- a/src/vim9execute.c
+++ b/src/vim9execute.c
@@ -1089,6 +1089,7 @@ call_def_function(
dictitem_T *di = NULL;
hashtab_T *ht = NULL;
char namespace;
+
switch (iptr->isn_type)
{
case ISN_LOADG:
@@ -1128,6 +1129,33 @@ call_def_function(
}
break;
+ // load g:/b:/w:/t: namespace
+ case ISN_LOADGDICT:
+ case ISN_LOADBDICT:
+ case ISN_LOADWDICT:
+ case ISN_LOADTDICT:
+ {
+ dict_T *d = NULL;
+
+ switch (iptr->isn_type)
+ {
+ case ISN_LOADG: d = get_globvar_dict(); break;
+ case ISN_LOADB: d = &curbuf->b_vars; break;
+ case ISN_LOADW: d = &curwin->w_vars; break;
+ case ISN_LOADT: d = &curtab->tp_vars; break;
+ default: // Cannot reach here
+ goto failed;
+ }
+ if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
+ goto failed;
+ tv = STACK_TV_BOT(0);
+ tv->v_type = VAR_DICT;
+ tv->v_lock = 0;
+ tv->vval.v_dict = d;
+ ++ectx.ec_stack.ga_len;
+ }
+ break;
+
// load &option
case ISN_LOADOPT:
{
@@ -1166,6 +1194,7 @@ call_def_function(
goto failed;
tv = STACK_TV_BOT(0);
tv->v_type = VAR_STRING;
+ tv->v_lock = 0;
tv->vval.v_string = get_reg_contents(
iptr->isn_arg.number, GREG_EXPR_SRC);
++ectx.ec_stack.ga_len;
@@ -1411,6 +1440,7 @@ call_def_function(
if (GA_GROW(&ectx.ec_stack, 1) == FAIL)
goto failed;
tv = STACK_TV_BOT(0);
+ tv->v_lock = 0;
++ectx.ec_stack.ga_len;
switch (iptr->isn_type)
{
@@ -1529,6 +1559,7 @@ call_def_function(
++ectx.ec_stack.ga_len;
tv = STACK_TV_BOT(-1);
tv->v_type = VAR_DICT;
+ tv->v_lock = 0;
tv->vval.v_dict = dict;
++dict->dv_refcount;
}
@@ -1673,6 +1704,7 @@ call_def_function(
++ectx.ec_stack.ga_len;
tv->vval.v_partial = pt;
tv->v_type = VAR_PARTIAL;
+ tv->v_lock = 0;
}
break;
@@ -1719,6 +1751,7 @@ call_def_function(
// non-materialized range() list
tv = STACK_TV_BOT(0);
tv->v_type = VAR_NUMBER;
+ tv->v_lock = 0;
tv->vval.v_number = list_find_nr(
list, idxtv->vval.v_number, NULL);
++ectx.ec_stack.ga_len;
@@ -1762,6 +1795,7 @@ call_def_function(
tv = STACK_TV_BOT(0);
++ectx.ec_stack.ga_len;
tv->v_type = VAR_STRING;
+ tv->v_lock = 0;
tv->vval.v_string = vim_strsave(
(char_u *)current_exception->value);
break;
@@ -2626,6 +2660,18 @@ ex_disassemble(exarg_T *eap)
case ISN_LOADT:
smsg("%4d LOADT t:%s", current, iptr->isn_arg.string);
break;
+ case ISN_LOADGDICT:
+ smsg("%4d LOAD g:", current);
+ break;
+ case ISN_LOADBDICT:
+ smsg("%4d LOAD b:", current);
+ break;
+ case ISN_LOADWDICT:
+ smsg("%4d LOAD w:", current);
+ break;
+ case ISN_LOADTDICT:
+ smsg("%4d LOAD t:", current);
+ break;
case ISN_LOADOPT:
smsg("%4d LOADOPT %s", current, iptr->isn_arg.string);
break;