riml 0.1.6 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
-
[](https://travis-ci.org/luke-gru/riml)
|
1
|
+
[](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
|