[vim/vim] [vim9script] Increment/decrement operator error when applied to class member inside function (Issue #12263)

13 views
Skip to first unread message

Lifepillar

unread,
Apr 15, 2023, 11:05:29 AM4/15/23
to vim/vim, Subscribed

Steps to reproduce

Source this script:

vim9script

class X
  public this.attr = 42
endclass

class Y
  public this.xobj = X.new()
endclass

def F(yobj: Y)
  var xx = yobj.xobj
  xx.attr += 1
enddef

var yy = Y.new()
F(yy)

This fails with E1089: Unknown variable: tr += 1. This is a minor issue, as a simple workaround is to just use + instead of +=:

xx.attr = xx.attr + 1

Note that out of a function the assignment with += works:

var xx = X.new()
xx.attr += 1
echo xx.attr  # OK

and even

var yy = Y.new()
yy.xobj.attr += 1
echo yy.xobj.attr  # OK

Expected behaviour

The sourced script should run without errors.

Version of Vim

9.0.1454

Environment

macOS
Apple Terminal
xterm-256color
ZSH 5.9

Logs and stack traces

No response


Reply to this email directly, view it on GitHub.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/12263@github.com>

Christian Brabandt

unread,
Apr 16, 2023, 12:56:04 PM4/16/23
to vim/vim, Subscribed

Hm, I haven't looked closely at the vim9 implementation, but here Vim only seems to handle this correctly. Which means, if you use:

var that = yobj.xobj

it starts to work :)

I think, instead of hard-coding the 5 we need this patch here:

diff --git a/src/vim9compile.c b/src/vim9compile.c
index 64526aa9d..0f795f799 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -2065,10 +2065,16 @@ compile_load_lhs_with_index(lhs_T *lhs, char_u *var_start, cctx_T *cctx)
 {
     if (lhs->lhs_type->tt_type == VAR_OBJECT)
     {
-       // "this.value": load "this" object and get the value at index
+       char_u *dot = vim_strchr(var_start, '.');
+
+       if (dot == NULL)
+           return FAIL;
+
+       // "object.value" or "this.value":
+       // load "this" object and get the value at index
        // for an object or class member get the type of the member
        class_T *cl = lhs->lhs_type->tt_class;
-       type_T *type = class_member_type(cl, var_start + 5,
+       type_T *type = class_member_type(cl, dot + 1,
                                           lhs->lhs_end, &lhs->lhs_member_idx);
        if (lhs->lhs_member_idx < 0)
            return FAIL;


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/12263/1510431026@github.com>

Bram Moolenaar

unread,
Apr 24, 2023, 9:03:26 AM4/24/23
to vim/vim, Subscribed


> Hm, I haven't looked closely at the vim9 implementation, but here Vim only seems to handle `this` correctly. Which means, if you use:
> ```
> var that = yobj.xobj
> ```
> it starts to work :)
>
> I think, instead of hard-coding the 5 we need this patch here:
> ```patch

> diff --git a/src/vim9compile.c b/src/vim9compile.c
> index 64526aa9d..0f795f799 100644
> --- a/src/vim9compile.c
> +++ b/src/vim9compile.c
> @@ -2065,10 +2065,16 @@ compile_load_lhs_with_index(lhs_T *lhs, char_u *var_start, cctx_T *cctx)
> {
> if (lhs->lhs_type->tt_type == VAR_OBJECT)
> {
> - // "this.value": load "this" object and get the value at index
> + char_u *dot = vim_strchr(var_start, '.');
> +
> + if (dot == NULL)
> + return FAIL;
> +
> + // "object.value" or "this.value":
> + // load "this" object and get the value at index
> // for an object or class member get the type of the member
> class_T *cl = lhs->lhs_type->tt_class;
> - type_T *type = class_member_type(cl, var_start + 5,
> + type_T *type = class_member_type(cl, dot + 1,
> lhs->lhs_end, &lhs->lhs_member_idx);
> if (lhs->lhs_member_idx < 0)
> return FAIL;
> ```

Thanks for the patch. This fixes the example given, but when I add a
test for it then it fails. I'll have to do some debugging to find out
why. I added the test in testdir/test_vim9_class.vim:

--- a/src/testdir/test_vim9_class.vim 2023-04-18 19:07:21.202891893 +0100
+++ b/src/testdir/test_vim9_class.vim 2023-04-24 13:52:50.350343550 +0100
@@ -401,6 +401,13 @@
var f = Foo.new(3)
f.Add(17)
assert_equal(20, f.x)
+
+ def AddToFoo(obj: Foo)
+ obj.x += 3
+ enddef
+
+ AddToFoo(f)
+ assert_equal(23, f.x)
END
v9.CheckScriptSuccess(lines)
enddef

--
People who want to share their religious views with you
almost never want you to share yours with them.

/// Bram Moolenaar -- ***@***.*** -- http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issues/12263/1520120237@github.com>

Bram Moolenaar

unread,
Apr 24, 2023, 12:14:42 PM4/24/23
to vim...@googlegroups.com, Bram Moolenaar
Turns out a LOAD instruction is generated that assumes "this". Thus
when the object is an argument it will load a random variable value.
I found a fix for that, will send out a patch.

--
Mushrooms always grow in damp places and so they look like umbrellas.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\

Bram Moolenaar

unread,
Apr 24, 2023, 12:16:08 PM4/24/23
to vim/vim, Subscribed

Closed #12263 as completed via 22363c6.


Reply to this email directly, view it on GitHub.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/issue/12263/issue_event/9083465852@github.com>

Reply all
Reply to author
Forward
0 new messages