Skip to content

Commit 1bcf48b

Browse files
authored
Merge pull request #160 from vim-jp/add-method-op
Add method operator (obj->method())
2 parents c91b43a + 04342b9 commit 1bcf48b

File tree

5 files changed

+78
-0
lines changed

5 files changed

+78
-0
lines changed

autoload/vimlparser.vim

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ let s:NODE_BLOB = 93
141141
let s:NODE_CONST = 94
142142
let s:NODE_EVAL = 95
143143
let s:NODE_HEREDOC = 96
144+
let s:NODE_METHOD = 97
144145

145146
let s:TOKEN_EOF = 1
146147
let s:TOKEN_EOL = 2
@@ -399,6 +400,7 @@ endfunction
399400
" PLUS .left
400401
" SUBSCRIPT .left .right
401402
" SLICE .left .rlist
403+
" METHOD .left .right .lambda_rlist
402404
" CALL .left .rlist
403405
" DOT .left .right
404406
" NUMBER .value
@@ -3967,6 +3969,9 @@ endfunction
39673969
" expr8: expr8[expr1]
39683970
" expr8[expr1 : expr1]
39693971
" expr8.name
3972+
" expr8->name(expr1, ...)
3973+
" expr8->s:user_func(expr1, ...)
3974+
" expr8->{lambda}(expr1, ...)
39703975
" expr8(expr1, ...)
39713976
function! s:ExprParser.parse_expr8() abort
39723977
let left = self.parse_expr9()
@@ -4021,6 +4026,17 @@ function! s:ExprParser.parse_expr8() abort
40214026
endif
40224027
endif
40234028
unlet node
4029+
elseif token.type ==# s:TOKEN_ARROW
4030+
let node = s:Node(s:NODE_METHOD)
4031+
let node.pos = token.pos
4032+
let node.left = left
4033+
let node.right = self.parse_expr8()
4034+
let node.lambda_rlist = s:NIL
4035+
if node.right.type !=# s:NODE_CALL
4036+
throw s:Err('Rhs of method operator must be an function call', node.right.pos)
4037+
endif
4038+
let left = node
4039+
unlet node
40244040
elseif token.type ==# s:TOKEN_POPEN
40254041
let node = s:Node(s:NODE_CALL)
40264042
let node.pos = token.pos
@@ -4980,6 +4996,8 @@ function! s:Compiler.compile(node) abort
49804996
return self.compile_slice(a:node)
49814997
elseif a:node.type ==# s:NODE_DOT
49824998
return self.compile_dot(a:node)
4999+
elseif a:node.type ==# s:NODE_METHOD
5000+
return self.compile_method(a:node)
49835001
elseif a:node.type ==# s:NODE_CALL
49845002
return self.compile_call(a:node)
49855003
elseif a:node.type ==# s:NODE_NUMBER
@@ -5436,6 +5454,10 @@ function! s:Compiler.compile_dot(node) abort
54365454
return printf('(dot %s %s)', self.compile(a:node.left), self.compile(a:node.right))
54375455
endfunction
54385456

5457+
function! s:Compiler.compile_method(node) abort
5458+
return printf('(method %s %s)', self.compile(a:node.left), self.compile(a:node.right))
5459+
endfunction
5460+
54395461
function! s:Compiler.compile_call(node) abort
54405462
let rlist = map(a:node.rlist, 'self.compile(v:val)')
54415463
if empty(rlist)

js/vimlparser.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ var NODE_BLOB = 93;
322322
var NODE_CONST = 94;
323323
var NODE_EVAL = 95;
324324
var NODE_HEREDOC = 96;
325+
var NODE_METHOD = 97;
325326
var TOKEN_EOF = 1;
326327
var TOKEN_EOL = 2;
327328
var TOKEN_SPACE = 3;
@@ -577,6 +578,7 @@ function ExArg() {
577578
// PLUS .left
578579
// SUBSCRIPT .left .right
579580
// SLICE .left .rlist
581+
// METHOD .left .right .lambda_rlist
580582
// CALL .left .rlist
581583
// DOT .left .right
582584
// NUMBER .value
@@ -3334,6 +3336,9 @@ ExprParser.prototype.parse_expr7 = function() {
33343336
// expr8: expr8[expr1]
33353337
// expr8[expr1 : expr1]
33363338
// expr8.name
3339+
// expr8->name(expr1, ...)
3340+
// expr8->s:user_func(expr1, ...)
3341+
// expr8->{lambda}(expr1, ...)
33373342
// expr8(expr1, ...)
33383343
ExprParser.prototype.parse_expr8 = function() {
33393344
var left = this.parse_expr9();
@@ -3391,6 +3396,18 @@ ExprParser.prototype.parse_expr8 = function() {
33913396
}
33923397
delete node;
33933398
}
3399+
else if (token.type == TOKEN_ARROW) {
3400+
var node = Node(NODE_METHOD);
3401+
node.pos = token.pos;
3402+
node.left = left;
3403+
node.right = this.parse_expr8();
3404+
node.lambda_rlist = NIL;
3405+
if (node.right.type != NODE_CALL) {
3406+
throw Err("Rhs of method operator must be an function call", node.right.pos);
3407+
}
3408+
var left = node;
3409+
delete node;
3410+
}
33943411
else if (token.type == TOKEN_POPEN) {
33953412
var node = Node(NODE_CALL);
33963413
node.pos = token.pos;
@@ -4471,6 +4488,9 @@ Compiler.prototype.compile = function(node) {
44714488
else if (node.type == NODE_DOT) {
44724489
return this.compile_dot(node);
44734490
}
4491+
else if (node.type == NODE_METHOD) {
4492+
return this.compile_method(node);
4493+
}
44744494
else if (node.type == NODE_CALL) {
44754495
return this.compile_call(node);
44764496
}
@@ -4958,6 +4978,10 @@ Compiler.prototype.compile_dot = function(node) {
49584978
return viml_printf("(dot %s %s)", this.compile(node.left), this.compile(node.right));
49594979
}
49604980

4981+
Compiler.prototype.compile_method = function(node) {
4982+
return viml_printf("(method %s %s)", this.compile(node.left), this.compile(node.right));
4983+
}
4984+
49614985
Compiler.prototype.compile_call = function(node) {
49624986
var rlist = node.rlist.map((function(vval) { return this.compile(vval); }).bind(this));
49634987
if (viml_empty(rlist)) {

py/vimlparser.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,7 @@ def viml_stridx(a, b):
309309
NODE_CONST = 94
310310
NODE_EVAL = 95
311311
NODE_HEREDOC = 96
312+
NODE_METHOD = 97
312313
TOKEN_EOF = 1
313314
TOKEN_EOL = 2
314315
TOKEN_SPACE = 3
@@ -566,6 +567,7 @@ def ExArg():
566567
# PLUS .left
567568
# SUBSCRIPT .left .right
568569
# SLICE .left .rlist
570+
# METHOD .left .right .lambda_rlist
569571
# CALL .left .rlist
570572
# DOT .left .right
571573
# NUMBER .value
@@ -2716,6 +2718,9 @@ def parse_expr7(self):
27162718
# expr8: expr8[expr1]
27172719
# expr8[expr1 : expr1]
27182720
# expr8.name
2721+
# expr8->name(expr1, ...)
2722+
# expr8->s:user_func(expr1, ...)
2723+
# expr8->{lambda}(expr1, ...)
27192724
# expr8(expr1, ...)
27202725
def parse_expr8(self):
27212726
left = self.parse_expr9()
@@ -2763,6 +2768,16 @@ def parse_expr8(self):
27632768
raise VimLParserException(Err(viml_printf("unexpected token: %s", token.value), token.pos))
27642769
left = node
27652770
del node
2771+
elif token.type == TOKEN_ARROW:
2772+
node = Node(NODE_METHOD)
2773+
node.pos = token.pos
2774+
node.left = left
2775+
node.right = self.parse_expr8()
2776+
node.lambda_rlist = NIL
2777+
if node.right.type != NODE_CALL:
2778+
raise VimLParserException(Err("Rhs of method operator must be an function call", node.right.pos))
2779+
left = node
2780+
del node
27662781
elif token.type == TOKEN_POPEN:
27672782
node = Node(NODE_CALL)
27682783
node.pos = token.pos
@@ -3588,6 +3603,8 @@ def compile(self, node):
35883603
return self.compile_slice(node)
35893604
elif node.type == NODE_DOT:
35903605
return self.compile_dot(node)
3606+
elif node.type == NODE_METHOD:
3607+
return self.compile_method(node)
35913608
elif node.type == NODE_CALL:
35923609
return self.compile_call(node)
35933610
elif node.type == NODE_NUMBER:
@@ -3950,6 +3967,9 @@ def compile_slice(self, node):
39503967
def compile_dot(self, node):
39513968
return viml_printf("(dot %s %s)", self.compile(node.left), self.compile(node.right))
39523969

3970+
def compile_method(self, node):
3971+
return viml_printf("(method %s %s)", self.compile(node.left), self.compile(node.right))
3972+
39533973
def compile_call(self, node):
39543974
rlist = [self.compile(vval) for vval in node.rlist]
39553975
if viml_empty(rlist):

test/test_method.ok

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
(echo (method 'alice' (s:hello)))
2+
(echo (method 'alice' (s:hello 'bob')))
3+
(echo (method (list 1 2 3) (map (lambda (i n) (* n 2)))))
4+
(echo (method 'john' ((lambda (s) (concat 'hello ' s)))))
5+
(echo (method 'john' ((lambda (s b) (concat (concat (concat (concat 'hello ' s) ' ... and goodbye ') b) '!')) 'bob')))
6+
(echo (method 'john' ((lambda (...) (concat 'hello ' (method a:000 (join ', ')))) 'bob')))

test/test_method.vim

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
echo 'alice'->s:hello()
2+
echo 'alice'->s:hello('bob')
3+
echo [1,2,3]->map({i,n -> n * 2})
4+
echo 'john'->{s -> 'hello ' .. s }()
5+
echo 'john'->{s,b -> 'hello ' .. s .. ' ... and goodbye ' .. b .. '!' }('bob')
6+
echo 'john'->{... -> 'hello ' .. a:000->join(', ') }('bob')

0 commit comments

Comments
 (0)