riml 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +51 -86
- data/lib/ast_rewriter.rb +28 -15
- data/lib/compiler.rb +34 -5
- data/lib/grammar.y +21 -10
- data/lib/lexer.rb +12 -12
- data/lib/nodes.rb +33 -25
- data/lib/parser.rb +813 -765
- data/version.rb +2 -2
- metadata +4 -4
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
[![Build Status](https://travis-ci.org/luke-gru/riml.png)](https://travis-ci.org/luke-gru/riml)
|
1
|
+
[![Build Status](https://secure.travis-ci.org/luke-gru/riml.png?branch=master)](https://travis-ci.org/luke-gru/riml)
|
2
2
|
|
3
3
|
Riml, a relaxed version of Vimscript
|
4
4
|
====================================
|
@@ -10,7 +10,6 @@ programmers take for granted. Also, Riml takes some liberties and provides
|
|
10
10
|
some syntactic sugar for lots of VimL constructs. To see how Riml constructs
|
11
11
|
are compiled into VimL, just take a look in this README. The left side is Riml,
|
12
12
|
and the right side is the equivalent VimL after compilation.
|
13
|
-
|
14
13
|
Variables
|
15
14
|
---------
|
16
15
|
|
@@ -38,11 +37,11 @@ old local variables.
|
|
38
37
|
|
39
38
|
###Checking for existence
|
40
39
|
|
41
|
-
unless s:callcount?
|
42
|
-
callcount = 0
|
43
|
-
end
|
44
|
-
callcount += 1
|
45
|
-
|
40
|
+
unless s:callcount? if !exists("s:callcount")
|
41
|
+
callcount = 0 let s:callcount = 0
|
42
|
+
end endif
|
43
|
+
callcount += 1 let s:callcount += 1
|
44
|
+
echo "called #{callcount} times" echo "called " . s:callcount . " times"
|
46
45
|
|
47
46
|
Comparisons
|
48
47
|
-----------
|
@@ -56,93 +55,59 @@ Comparisons
|
|
56
55
|
Heredocs
|
57
56
|
--------
|
58
57
|
|
59
|
-
msg = <<EOS let s:msg = "a vim heredoc!\n"
|
60
|
-
|
58
|
+
msg = <<EOS let s:msg = "a vim heredoc! " . s:cryForJoy() . "!\n"
|
59
|
+
A vim heredoc! #{cryForJoy()}!
|
61
60
|
EOS
|
62
61
|
|
63
62
|
Classes
|
64
63
|
-------
|
65
64
|
|
66
|
-
###
|
67
|
-
|
68
|
-
class MyClass
|
69
|
-
def initialize(
|
65
|
+
###Basic Class
|
66
|
+
|
67
|
+
class MyClass function! g:MyClassConstructor(data, otherData, ...)
|
68
|
+
def initialize(data, otherData, *options) let myClassObj = {}
|
69
|
+
self.data = data let myClassObj.data = a:data
|
70
|
+
self.otherData = otherData let myClassObj.otherData = a:otherData
|
71
|
+
self.options = options let myClassObj.options = a:000
|
72
|
+
end let myClassObj.getData = function('g:MyClass_getData')
|
73
|
+
let myClassObj.getOtherData = function('g:MyClass_getOtherData')
|
74
|
+
defm getData return myClassObj
|
75
|
+
return self.data endfunction
|
70
76
|
end
|
71
|
-
|
72
|
-
defm
|
73
|
-
return self.
|
77
|
+
function! g:MyClass_getdata() dict
|
78
|
+
defm getOtherData return self.data
|
79
|
+
return self.otherData endfunction
|
74
80
|
end
|
75
|
-
|
76
|
-
|
77
|
-
|
81
|
+
end function! g:MyClass_getOtherData() dict
|
82
|
+
return self.otherData
|
83
|
+
endfunction
|
84
|
+
|
85
|
+
###Class with Inheritance
|
86
|
+
|
87
|
+
class Translation function! g:TranslationConstructor(input)
|
88
|
+
def initialize(input) let translationObj = {}
|
89
|
+
self.input = input let translationObj.input = a:input
|
90
|
+
end return translationObj
|
91
|
+
end endfunction
|
92
|
+
|
93
|
+
class FrenchToEnglishTranslation < Translation function! g:FrenchToEnglishTranslationConstructor(input)
|
94
|
+
defm translate let frenchToEnglishTranslationObj = {}
|
95
|
+
if (self.input == "Bonjour!") let translationObj = g:TranslationConstructor(a:input)
|
96
|
+
echo "Hello!" call extend(frenchToEnglishTranslationObj, translationObj)
|
97
|
+
else let translationObj.translate = function('g:FrenchToEnglishTranslation_translate')
|
98
|
+
echo "Sorry, I don't know that word." return frenchToEnglishTranslationObj
|
99
|
+
end endfunction
|
78
100
|
end
|
79
|
-
end
|
80
|
-
|
81
|
-
|
82
|
-
|
101
|
+
end function! g:FrenchToEnglishTranslation_translate() dict
|
102
|
+
if (self.input ==# "Bonjour!")
|
103
|
+
translation = new echo "Hello!"
|
104
|
+
\ FrenchToEnglishTranslation("Bonjour!") else
|
105
|
+
translation.translate() echo "Sorry, I don't know that word."
|
106
|
+
endif
|
107
|
+
endfunction
|
83
108
|
|
84
|
-
|
85
|
-
|
86
|
-
function! myClassObj.getData() dict
|
87
|
-
return self.data
|
88
|
-
endfunction
|
89
|
-
function! myClassObj.getOtherData() dict
|
90
|
-
return self.otherData
|
91
|
-
endfunction
|
92
|
-
return myClassObj
|
93
|
-
endfunction
|
94
|
-
|
95
|
-
###Riml example 2
|
96
|
-
|
97
|
-
class Translation
|
98
|
-
def initialize(input)
|
99
|
-
self.input = input
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
class FrenchToEnglishTranslation < Translation
|
104
|
-
defm translate
|
105
|
-
if (self.input == "Bonjour!")
|
106
|
-
echo "Hello!"
|
107
|
-
else
|
108
|
-
echo "Sorry, I don't know that word."
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
translation = new FrenchToEnglishTranslation("Bonjour!")
|
114
|
-
translation.translate()
|
115
|
-
|
116
|
-
###VimL example 2
|
117
|
-
|
118
|
-
function! g:TranslationConstructor(input)
|
119
|
-
let translationObj = {}
|
120
|
-
let translationObj.input = a:input
|
121
|
-
return translationObj
|
122
|
-
endfunction
|
123
|
-
|
124
|
-
function! g:FrenchToEnglishTranslationConstructor(input)
|
125
|
-
let frenchToEnglishTranslationObj = {}
|
126
|
-
let translationObj = g:TranslationConstructor(a:input)
|
127
|
-
call extend(frenchToEnglishTranslationObj, translationObj)
|
128
|
-
function! frenchToEnglishTranslationObj.translate() dict
|
129
|
-
if (self.input ==# "Bonjour!")
|
130
|
-
echo "Hello!"
|
131
|
-
else
|
132
|
-
echo "Sorry, I don't know that word."
|
133
|
-
endif
|
134
|
-
endfunction
|
135
|
-
return frenchToEnglishTranslationObj
|
136
|
-
endfunction
|
137
|
-
|
138
|
-
let s:translation = g:FrenchToEnglishTranslationConstructor("Bonjour!")
|
139
|
-
call s:translation.translate()
|
140
|
-
|
141
|
-
Hacking
|
142
|
-
-------
|
109
|
+
let s:translation = g:TranslationConstructor("Bonjour!")
|
110
|
+
call s:translation.translate()
|
143
111
|
|
144
|
-
Make sure to generate the parser before running tests or developing on Riml.
|
145
|
-
Also, make sure to regenerate the parser after modifiying the grammar file.
|
146
112
|
|
147
|
-
|
148
|
-
2. Go to the lib directory and enter `racc -o parser.rb grammar.y`
|
113
|
+
Coming soon: for a full list of the language's rules complete with examples, check out the Wiki
|
data/lib/ast_rewriter.rb
CHANGED
@@ -79,8 +79,8 @@ module Riml
|
|
79
79
|
def replace(node)
|
80
80
|
binary_op = node.nodes[0].rhs
|
81
81
|
old_set_var = node.nodes[0]
|
82
|
-
assign_true = old_set_var.
|
83
|
-
assign_false = old_set_var.
|
82
|
+
assign_true = old_set_var.dup.tap {|assign_t| assign_t.rhs = TrueNode.new}
|
83
|
+
assign_false = old_set_var.dup.tap {|assign_f| assign_f.rhs = FalseNode.new}
|
84
84
|
node.nodes = [
|
85
85
|
IfNode.new(binary_op, Nodes.new([
|
86
86
|
assign_true, ElseNode.new(Nodes.new([
|
@@ -112,7 +112,7 @@ module Riml
|
|
112
112
|
)
|
113
113
|
|
114
114
|
SuperToObjectExtension.new(constructor, classes, node).rewrite_on_match
|
115
|
-
|
115
|
+
ExtendObjectWithMethods.new(node, classes).rewrite_on_match
|
116
116
|
SelfToDictName.new(dict_name).rewrite_on_match(constructor)
|
117
117
|
|
118
118
|
constructor.expressions.push(
|
@@ -121,26 +121,39 @@ module Riml
|
|
121
121
|
reestablish_parents(constructor)
|
122
122
|
end
|
123
123
|
|
124
|
-
class
|
125
|
-
attr_reader :constructor, :dict_name
|
126
|
-
def initialize(class_node, classes, constructor, dict_name)
|
127
|
-
super(class_node, classes)
|
128
|
-
@dict_name, @constructor = dict_name, constructor
|
129
|
-
end
|
130
|
-
|
124
|
+
class ExtendObjectWithMethods < AST_Rewriter
|
131
125
|
def match?(node)
|
132
126
|
DefMethodNode === node
|
133
127
|
end
|
134
128
|
|
135
129
|
def replace(node)
|
136
130
|
def_node = node.to_def_node
|
137
|
-
|
138
|
-
|
131
|
+
class_expressions = ast.expressions
|
132
|
+
class_expressions.insert_after(class_expressions.last, def_node)
|
133
|
+
def_node.parent = class_expressions
|
134
|
+
# to remove it
|
135
|
+
node.parent = class_expressions
|
139
136
|
node.remove
|
140
|
-
def_node.name.
|
141
|
-
def_node.
|
142
|
-
constructor.expressions << def_node
|
137
|
+
def_node.original_name = def_node.name.dup
|
138
|
+
def_node.name.insert(0, "#{ast.name}_")
|
143
139
|
reestablish_parents(def_node)
|
140
|
+
extend_obj_with_methods(def_node)
|
141
|
+
end
|
142
|
+
|
143
|
+
def extend_obj_with_methods(def_node)
|
144
|
+
constructor = ast.constructor
|
145
|
+
extension =
|
146
|
+
AssignNode.new('=',
|
147
|
+
DictGetDotNode.new(
|
148
|
+
GetVariableNode.new(nil, ast.constructor_obj_name),
|
149
|
+
[def_node.original_name]
|
150
|
+
),
|
151
|
+
CallNode.new(
|
152
|
+
nil, 'function', [StringNode.new("#{def_node.scope_modifier}#{def_node.name}", :s)]
|
153
|
+
)
|
154
|
+
)
|
155
|
+
constructor.expressions << extension
|
156
|
+
extension.parent = constructor.expressions
|
144
157
|
end
|
145
158
|
end
|
146
159
|
|
data/lib/compiler.rb
CHANGED
@@ -159,7 +159,7 @@ module Riml
|
|
159
159
|
|
160
160
|
private
|
161
161
|
def string_surround(string_node)
|
162
|
-
case string_node.type
|
162
|
+
case string_node.type.to_sym
|
163
163
|
when :d
|
164
164
|
'"' << string_node.value << '"'
|
165
165
|
when :s
|
@@ -283,16 +283,45 @@ module Riml
|
|
283
283
|
def compile(node)
|
284
284
|
set_modifier(node)
|
285
285
|
node.compiled_output = node.scope_modifier
|
286
|
-
node.variable.parts
|
287
|
-
|
288
|
-
|
286
|
+
node.compiled_output << compile_parts(node.variable.parts)
|
287
|
+
end
|
288
|
+
|
289
|
+
def compile_parts(parts)
|
290
|
+
compiled = ""
|
291
|
+
parts.each do |part|
|
292
|
+
output = if CurlyBraceVariable === part
|
293
|
+
compile_parts(part)
|
294
|
+
elsif part.nested?
|
295
|
+
compile_nested_parts(part.value, part)
|
296
|
+
part.compiled_output
|
297
|
+
elsif part.interpolated?
|
289
298
|
part.value.accept(visitor_for_node(part.value))
|
290
299
|
"{#{part.value.compiled_output}}"
|
291
300
|
else
|
292
301
|
"#{part.value}"
|
293
302
|
end
|
303
|
+
compiled << output
|
294
304
|
end
|
295
|
-
|
305
|
+
compiled
|
306
|
+
end
|
307
|
+
|
308
|
+
def compile_nested_parts(parts, root_part)
|
309
|
+
nested = 0
|
310
|
+
parts.each do |part|
|
311
|
+
if !part.respond_to?(:value)
|
312
|
+
part.accept(visitor_for_node(part, :propagate_up_tree => false))
|
313
|
+
root_part.compiled_output << "{#{part.compiled_output}"
|
314
|
+
nested += 1
|
315
|
+
next
|
316
|
+
end
|
317
|
+
if part.value.is_a?(Array)
|
318
|
+
compile_nested_parts(part.value, root_part)
|
319
|
+
next
|
320
|
+
end
|
321
|
+
part.value.accept(visitor_for_node(part.value, :propagate_up_tree => false))
|
322
|
+
root_part.compiled_output << "{#{part.value.compiled_output}}"
|
323
|
+
end
|
324
|
+
root_part.compiled_output << ('}' * nested)
|
296
325
|
end
|
297
326
|
end
|
298
327
|
|
data/lib/grammar.y
CHANGED
@@ -76,7 +76,7 @@ rule
|
|
76
76
|
| Assign { result = val[0] }
|
77
77
|
| DictGet { result = val[0] }
|
78
78
|
| ListOrDictGet { result = val[0] }
|
79
|
-
|
|
79
|
+
| AllVariableRetrieval { result = val[0] }
|
80
80
|
| Literal { result = val[0] }
|
81
81
|
| Call { result = val[0] }
|
82
82
|
| Ternary { result = val[0] }
|
@@ -164,7 +164,7 @@ rule
|
|
164
164
|
|
165
165
|
DictGet:
|
166
166
|
Dictionary DictGetWithDotLiteral { result = DictGetDotNode.new(val[0], val[1]) }
|
167
|
-
|
|
167
|
+
| AllVariableRetrieval DictGetWithDot { result = DictGetDotNode.new(val[0], val[1]) }
|
168
168
|
| ListOrDictGet DictGetWithDot { result = DictGetDotNode.new(val[0], val[1]) }
|
169
169
|
;
|
170
170
|
|
@@ -295,7 +295,7 @@ rule
|
|
295
295
|
;
|
296
296
|
|
297
297
|
AssignLHS:
|
298
|
-
|
298
|
+
AllVariableRetrieval { result = val[0] }
|
299
299
|
| DictGet { result = val[0] }
|
300
300
|
| List { result = val[0] }
|
301
301
|
| ListUnpack { result = val[0] }
|
@@ -306,6 +306,10 @@ rule
|
|
306
306
|
VariableRetrieval:
|
307
307
|
Scope IDENTIFIER { result = GetVariableNode.new(val[0], val[1]) }
|
308
308
|
| SPECIAL_VAR_PREFIX IDENTIFIER { result = GetSpecialVariableNode.new(val[0], val[1]) }
|
309
|
+
;
|
310
|
+
|
311
|
+
AllVariableRetrieval:
|
312
|
+
VariableRetrieval { result = val[0] }
|
309
313
|
| Scope CurlyBraceName { result = GetCurlyBraceNameNode.new(val[0], val[1]) }
|
310
314
|
;
|
311
315
|
|
@@ -316,18 +320,25 @@ rule
|
|
316
320
|
;
|
317
321
|
|
318
322
|
CurlyBraceName:
|
319
|
-
|
320
|
-
|
|
323
|
+
CurlyBraceVarPart { result = CurlyBraceVariable.new([ val[0] ]) }
|
324
|
+
| IDENTIFIER CurlyBraceName { result = CurlyBraceVariable.new([ CurlyBracePart.new(val[0]), val[1] ]) }
|
321
325
|
| CurlyBraceName IDENTIFIER { result = val[0] << CurlyBracePart.new(val[1]) }
|
326
|
+
| CurlyBraceName CurlyBraceVarPart { result = val[0] << val[1] }
|
327
|
+
;
|
328
|
+
|
329
|
+
CurlyBraceVarPart:
|
330
|
+
'{' VariableRetrieval '}' { result = CurlyBracePart.new(val[1]) }
|
331
|
+
| '{' VariableRetrieval CurlyBraceVarPart '}' { result = CurlyBracePart.new([val[1], val[2]]) }
|
332
|
+
| '{' CurlyBraceVarPart VariableRetrieval '}' { result = CurlyBracePart.new([val[1], val[2]]) }
|
322
333
|
;
|
323
334
|
|
324
335
|
# Method definition
|
325
336
|
# [scope_modifier, name, parameters, keyword, expressions]
|
326
337
|
Def:
|
327
|
-
FunctionType Scope DefCallIdentifier
|
328
|
-
| FunctionType Scope DefCallIdentifier '(' ParamList ')'
|
329
|
-
| FunctionType Scope DefCallIdentifier '(' SPLAT ')'
|
330
|
-
| FunctionType Scope DefCallIdentifier '(' ParamList ',' SPLAT ')'
|
338
|
+
FunctionType Scope DefCallIdentifier DefKeyword Block END { result = Object.const_get(val[0]).new('!', val[1], val[2], [], val[3], val[4]) }
|
339
|
+
| FunctionType Scope DefCallIdentifier '(' ParamList ')' DefKeyword Block END { result = Object.const_get(val[0]).new('!', val[1], val[2], val[4], val[6], val[7]) }
|
340
|
+
| FunctionType Scope DefCallIdentifier '(' SPLAT ')' DefKeyword Block END { result = Object.const_get(val[0]).new('!', val[1], val[2], [val[4]], val[6], val[7]) }
|
341
|
+
| FunctionType Scope DefCallIdentifier '(' ParamList ',' SPLAT ')' DefKeyword Block END { result = Object.const_get(val[0]).new('!', val[1], val[2], val[4] << val[6], val[8], val[9]) }
|
331
342
|
;
|
332
343
|
|
333
344
|
FunctionType:
|
@@ -343,7 +354,7 @@ rule
|
|
343
354
|
;
|
344
355
|
|
345
356
|
# Example: 'range', 'dict' or 'abort' after function definition
|
346
|
-
|
357
|
+
DefKeyword:
|
347
358
|
IDENTIFIER { result = val[0] }
|
348
359
|
| /* nothing */ { result = nil }
|
349
360
|
;
|
data/lib/lexer.rb
CHANGED
@@ -71,19 +71,19 @@ module Riml
|
|
71
71
|
@i += splat_var.size
|
72
72
|
@token_buf << [:SCOPE_MODIFIER, 'a:'] << [:IDENTIFIER, splat_var[2..-1]]
|
73
73
|
# the 'n' scope modifier is added by riml
|
74
|
-
elsif scope_modifier = chunk[/\A([bwtglsavn]:)
|
74
|
+
elsif scope_modifier = chunk[/\A([bwtglsavn]:)\w/, 1]
|
75
75
|
@i += 2
|
76
|
-
@token_buf << [:SCOPE_MODIFIER,
|
76
|
+
@token_buf << [:SCOPE_MODIFIER, scope_modifier]
|
77
77
|
elsif scope_modifier_literal = chunk[/\A([bwtglsavn]:)/]
|
78
|
-
@i +=
|
79
|
-
@token_buf << [:SCOPE_MODIFIER_LITERAL,
|
78
|
+
@i += scope_modifier_literal.size
|
79
|
+
@token_buf << [:SCOPE_MODIFIER_LITERAL, scope_modifier_literal]
|
80
80
|
elsif special_var_prefix = chunk[/\A(&(\w:)?(?!&)|\$|@)/]
|
81
81
|
@token_buf << [:SPECIAL_VAR_PREFIX, special_var_prefix.strip]
|
82
82
|
@expecting_identifier = true
|
83
83
|
@i += special_var_prefix.size
|
84
|
-
elsif function_method = chunk[/\A(function)\(
|
85
|
-
@token_buf << [:IDENTIFIER,
|
86
|
-
@i +=
|
84
|
+
elsif function_method = chunk[/\A(function)\(/, 1]
|
85
|
+
@token_buf << [:IDENTIFIER, function_method]
|
86
|
+
@i += function_method.size
|
87
87
|
elsif identifier = chunk[/\A[a-zA-Z_][\w#]*(\?|!)?/]
|
88
88
|
# keyword identifiers
|
89
89
|
if KEYWORDS.include?(identifier)
|
@@ -130,15 +130,15 @@ module Riml
|
|
130
130
|
@i += splat.size
|
131
131
|
# integer (octal)
|
132
132
|
elsif octal = chunk[/\A0[0-7]+/]
|
133
|
-
@token_buf << [:NUMBER, octal
|
133
|
+
@token_buf << [:NUMBER, octal]
|
134
134
|
@i += octal.size
|
135
135
|
# integer (hex)
|
136
136
|
elsif hex = chunk[/\A0[xX]\h+/]
|
137
|
-
@token_buf << [:NUMBER, hex
|
137
|
+
@token_buf << [:NUMBER, hex]
|
138
138
|
@i += hex.size
|
139
139
|
# integer or float (decimal)
|
140
140
|
elsif decimal = chunk[/\A[0-9]+(\.[0-9]+)?/]
|
141
|
-
@token_buf << [:NUMBER, decimal
|
141
|
+
@token_buf << [:NUMBER, decimal]
|
142
142
|
@i += decimal.size
|
143
143
|
elsif interpolation = chunk[INTERPOLATION_REGEX]
|
144
144
|
# "hey there, #{name}" = "hey there, " . name
|
@@ -221,7 +221,7 @@ module Riml
|
|
221
221
|
when :if, :unless
|
222
222
|
if one_line_conditional?(chunk)
|
223
223
|
@one_line_conditional_end_pending = true
|
224
|
-
elsif !statement_modifier?
|
224
|
+
elsif !statement_modifier?
|
225
225
|
@current_indent += 2
|
226
226
|
@indent_pending = true
|
227
227
|
end
|
@@ -274,7 +274,7 @@ module Riml
|
|
274
274
|
Lexer.new(code).tokenize
|
275
275
|
end
|
276
276
|
|
277
|
-
def statement_modifier?
|
277
|
+
def statement_modifier?
|
278
278
|
old_i = @i
|
279
279
|
# backtrack until the beginning of the line
|
280
280
|
@i -= 1 while @code[@i-1] =~ /[^\n\r]/ && !@code[@i-1].empty?
|
data/lib/nodes.rb
CHANGED
@@ -391,27 +391,49 @@ class GetSpecialVariableNode < Struct.new(:prefix, :name)
|
|
391
391
|
include FullyNameable
|
392
392
|
end
|
393
393
|
|
394
|
-
class
|
395
|
-
|
396
|
-
|
397
|
-
end
|
394
|
+
class GetCurlyBraceNameNode < Struct.new(:scope_modifier, :variable)
|
395
|
+
include Visitable
|
396
|
+
include Walkable
|
398
397
|
|
399
|
-
def
|
400
|
-
|
398
|
+
def children
|
399
|
+
[variable]
|
401
400
|
end
|
402
401
|
end
|
402
|
+
|
403
403
|
class CurlyBraceVariable < Struct.new(:parts)
|
404
|
+
include Visitable
|
405
|
+
include Walkable
|
406
|
+
|
404
407
|
def <<(part)
|
405
408
|
parts << part
|
406
409
|
self
|
407
410
|
end
|
411
|
+
|
412
|
+
def children
|
413
|
+
parts
|
414
|
+
end
|
408
415
|
end
|
409
|
-
|
416
|
+
|
417
|
+
class CurlyBracePart < Struct.new(:value)
|
410
418
|
include Visitable
|
411
419
|
include Walkable
|
412
420
|
|
421
|
+
def interpolated?
|
422
|
+
GetVariableNode === value || GetSpecialVariableNode === value || nested?
|
423
|
+
end
|
424
|
+
|
425
|
+
def nested?
|
426
|
+
value.is_a?(Array) && value.detect {|part| part.is_a?(CurlyBracePart)}
|
427
|
+
end
|
428
|
+
|
429
|
+
def regular?
|
430
|
+
not interpolated?
|
431
|
+
end
|
432
|
+
|
413
433
|
def children
|
414
|
-
[
|
434
|
+
return [] if regular?
|
435
|
+
return value if nested?
|
436
|
+
[value]
|
415
437
|
end
|
416
438
|
end
|
417
439
|
|
@@ -436,6 +458,8 @@ class DefNode < Struct.new(:bang, :scope_modifier, :name, :parameters, :keyword,
|
|
436
458
|
include FullyNameable
|
437
459
|
include Walkable
|
438
460
|
|
461
|
+
attr_accessor :original_name
|
462
|
+
|
439
463
|
def initialize(*args)
|
440
464
|
super
|
441
465
|
# max number of arguments in viml
|
@@ -529,7 +553,7 @@ end
|
|
529
553
|
|
530
554
|
class DefMethodNode < DefNode
|
531
555
|
def to_def_node
|
532
|
-
def_node = DefNode.new(bang,
|
556
|
+
def_node = DefNode.new(bang, 'g:', name, parameters, 'dict', expressions)
|
533
557
|
def_node.parent = parent
|
534
558
|
def_node
|
535
559
|
end
|
@@ -652,22 +676,6 @@ class ForNode < Struct.new(:variable, :in_expression, :expressions)
|
|
652
676
|
end
|
653
677
|
end
|
654
678
|
|
655
|
-
# lines: [5, 6, 8, 9]
|
656
|
-
# This means the continuation has 4 lines (line.size is 4) and each line
|
657
|
-
# preserves the amt of whitespace specified as the value in the array.
|
658
|
-
# Ex: 1st line preserves 5 spaces, 2nd line preserves 6 spaces, etc...
|
659
|
-
class LineContinuation < Struct.new(:lines)
|
660
|
-
include Visitable
|
661
|
-
|
662
|
-
def size
|
663
|
-
lines.size
|
664
|
-
end
|
665
|
-
|
666
|
-
def [](idx)
|
667
|
-
lines[idx]
|
668
|
-
end
|
669
|
-
end
|
670
|
-
|
671
679
|
class DictGetNode < Struct.new(:dict, :keys)
|
672
680
|
include Visitable
|
673
681
|
include Walkable
|