patch 9.1.0148: Vim9: can't call internal methods with objects

Problem:  Vim9: can't call internal methods with objects
Solution: Add support for empty(), len() and string() function
          calls for objects (Yegappan Lakshmanan)

closes: #14129

Signed-off-by: Yegappan Lakshmanan <yegappan@yahoo.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
diff --git a/src/testdir/test_vim9_disassemble.vim b/src/testdir/test_vim9_disassemble.vim
index 1a192cc..645b04b 100644
--- a/src/testdir/test_vim9_disassemble.vim
+++ b/src/testdir/test_vim9_disassemble.vim
@@ -3273,4 +3273,167 @@
   unlet g:instr
 enddef
 
+" Disassemble instructions for calls to a string() function in an object
+def Test_disassemble_object_string()
+  var lines =<< trim END
+    vim9script
+    class A
+      def string(): string
+        return 'A'
+      enddef
+    endclass
+    def Bar()
+      var a = A.new()
+      var s = string(a)
+      s = string(A)
+    enddef
+    g:instr = execute('disassemble Bar')
+  END
+  v9.CheckScriptSuccess(lines)
+  assert_match('<SNR>\d*_Bar\_s*' ..
+    'var a = A.new()\_s*' ..
+    '0 DCALL new(argc 0)\_s*' ..
+    '1 STORE $0\_s*' ..
+    'var s = string(a)\_s*' ..
+    '2 LOAD $0\_s*' ..
+    '3 METHODCALL A.string(argc 0)\_s*' ..
+    '4 STORE $1\_s*' ..
+    's = string(A)\_s*' ..
+    '5 LOADSCRIPT A-0 from .*\_s*' ..
+    '6 BCALL string(argc 1)\_s*' ..
+    '7 STORE $1\_s*' ..
+    '8 RETURN void', g:instr)
+  unlet g:instr
+
+  # Use the default string() function for a class
+  lines =<< trim END
+    vim9script
+    class A
+    endclass
+    def Bar()
+      var a = A.new()
+      var s = string(a)
+      s = string(A)
+    enddef
+    g:instr = execute('disassemble Bar')
+  END
+  v9.CheckScriptSuccess(lines)
+  assert_match('<SNR>\d*_Bar\_s*' ..
+    'var a = A.new()\_s*' ..
+    '0 DCALL new(argc 0)\_s*' ..
+    '1 STORE $0\_s*' ..
+    'var s = string(a)\_s*' ..
+    '2 LOAD $0\_s*' ..
+    '3 BCALL string(argc 1)\_s*' ..
+    '4 STORE $1\_s*' ..
+    's = string(A)\_s*' ..
+    '5 LOADSCRIPT A-0 from .*\_s*' ..
+    '6 BCALL string(argc 1)\_s*' ..
+    '7 STORE $1\_s*' ..
+    '8 RETURN void', g:instr)
+  unlet g:instr
+enddef
+
+" Disassemble instructions for calls to a empty() function in an object
+def Test_disassemble_object_empty()
+  var lines =<< trim END
+    vim9script
+    class A
+      def empty(): bool
+        return true
+      enddef
+    endclass
+    def Bar()
+      var a = A.new()
+      var s = empty(a)
+    enddef
+    g:instr = execute('disassemble Bar')
+  END
+  v9.CheckScriptSuccess(lines)
+  assert_match('<SNR>\d*_Bar\_s*' ..
+    'var a = A.new()\_s*' ..
+    '0 DCALL new(argc 0)\_s*' ..
+    '1 STORE $0\_s*' ..
+    'var s = empty(a)\_s*' ..
+    '2 LOAD $0\_s*' ..
+    '3 METHODCALL A.empty(argc 0)\_s*' ..
+    '4 STORE $1\_s*' ..
+    '5 RETURN void', g:instr)
+  unlet g:instr
+
+  # Use the default empty() function for a class
+  lines =<< trim END
+    vim9script
+    class A
+    endclass
+    def Bar()
+      var a = A.new()
+      var s = empty(a)
+    enddef
+    g:instr = execute('disassemble Bar')
+  END
+  v9.CheckScriptSuccess(lines)
+  assert_match('<SNR>\d*_Bar\_s*' ..
+    'var a = A.new()\_s*' ..
+    '0 DCALL new(argc 0)\_s*' ..
+    '1 STORE $0\_s*' ..
+    'var s = empty(a)\_s*' ..
+    '2 LOAD $0\_s*' ..
+    '3 BCALL empty(argc 1)\_s*' ..
+    '4 STORE $1\_s*' ..
+    '5 RETURN void', g:instr)
+  unlet g:instr
+enddef
+
+" Disassemble instructions for calls to a len() function in an object
+def Test_disassemble_object_len()
+  var lines =<< trim END
+    vim9script
+    class A
+      def len(): number
+        return 10
+      enddef
+    endclass
+    def Bar()
+      var a = A.new()
+      var s = len(a)
+    enddef
+    g:instr = execute('disassemble Bar')
+  END
+  v9.CheckScriptSuccess(lines)
+  assert_match('<SNR>\d*_Bar\_s*' ..
+    'var a = A.new()\_s*' ..
+    '0 DCALL new(argc 0)\_s*' ..
+    '1 STORE $0\_s*' ..
+    'var s = len(a)\_s*' ..
+    '2 LOAD $0\_s*' ..
+    '3 METHODCALL A.len(argc 0)\_s*' ..
+    '4 STORE $1\_s*' ..
+    '5 RETURN void', g:instr)
+  unlet g:instr
+
+  # Use the default len() function for a class
+  lines =<< trim END
+    vim9script
+    class A
+    endclass
+    def Bar()
+      var a = A.new()
+      var s = len(a)
+    enddef
+    g:instr = execute('disassemble Bar')
+  END
+  v9.CheckScriptSuccess(lines)
+  assert_match('<SNR>\d*_Bar\_s*' ..
+    'var a = A.new()\_s*' ..
+    '0 DCALL new(argc 0)\_s*' ..
+    '1 STORE $0\_s*' ..
+    'var s = len(a)\_s*' ..
+    '2 LOAD $0\_s*' ..
+    '3 BCALL len(argc 1)\_s*' ..
+    '4 STORE $1\_s*' ..
+    '5 RETURN void', g:instr)
+  unlet g:instr
+enddef
+
 " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker