riml 0.2.3 → 0.2.4
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/lib/compiler.rb +40 -10
- data/lib/constants.rb +4 -4
- data/lib/grammar.y +132 -131
- data/lib/lexer.rb +2 -2
- data/lib/nodes.rb +689 -679
- data/lib/parser.rb +908 -900
- data/lib/riml.rb +26 -3
- data/lib/warning_buffer.rb +42 -0
- data/version.rb +2 -2
- metadata +3 -2
data/lib/lexer.rb
CHANGED
@@ -225,7 +225,7 @@ module Riml
|
|
225
225
|
@token_buf << [value, value]
|
226
226
|
end
|
227
227
|
@i += 1
|
228
|
-
if value == ']' || value == ')' && chunk[1, 1] == '.'
|
228
|
+
if value == ']' || value == ')' && (chunk[1, 1] == '.' && chunk[3, 1] != ':')
|
229
229
|
parse_dict_vals!
|
230
230
|
end
|
231
231
|
end
|
@@ -256,7 +256,7 @@ module Riml
|
|
256
256
|
def parse_dict_vals!
|
257
257
|
# dict.key OR dict.key.other_key
|
258
258
|
new_chunk = get_new_chunk
|
259
|
-
if vals = new_chunk[/\A\.([\w.]+)/, 1]
|
259
|
+
if vals = new_chunk[/\A\.([\w.]+)(?!:)/, 1]
|
260
260
|
parts = vals.split('.')
|
261
261
|
@i += vals.size + 1
|
262
262
|
if @in_function_declaration
|
data/lib/nodes.rb
CHANGED
@@ -2,908 +2,918 @@ require File.expand_path('../constants', __FILE__)
|
|
2
2
|
require File.expand_path('../errors', __FILE__)
|
3
3
|
require 'set'
|
4
4
|
|
5
|
-
module
|
6
|
-
|
7
|
-
visitor
|
8
|
-
|
5
|
+
module Riml
|
6
|
+
module Visitable
|
7
|
+
def accept(visitor)
|
8
|
+
visitor.visit(self)
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
attr_accessor :parent_node, :scope, :force_newline
|
12
|
+
alias parent parent_node
|
13
|
+
alias parent= parent_node=
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
attr_writer :compiled_output
|
16
|
+
def compiled_output
|
17
|
+
@compiled_output ||= ''
|
18
|
+
end
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
20
|
+
# catches "descendant_of_#{some_class}?" methods
|
21
|
+
# def descendant_of_call_node?
|
22
|
+
# CallNode === self.parent_node
|
23
|
+
# end
|
24
|
+
DESCENDANT_OF_REGEX = /\Adescendant_of_(.*?)\?/
|
25
|
+
def method_missing(method, *args, &blk)
|
26
|
+
if method =~ DESCENDANT_OF_REGEX
|
27
|
+
parent_node_name = $1.split('_').map(&:capitalize).join
|
28
|
+
parent_node = Riml.const_get parent_node_name
|
29
|
+
parent_node === self.parent_node
|
30
|
+
else
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
def respond_to?(method, include_private = false)
|
35
|
+
super || method =~ DESCENDANT_OF_REGEX
|
31
36
|
end
|
32
37
|
end
|
33
|
-
def respond_to?(method, include_private = false)
|
34
|
-
super || method =~ DESCENDANT_OF_REGEX
|
35
|
-
end
|
36
|
-
end
|
37
38
|
|
38
|
-
module Walkable
|
39
|
-
|
39
|
+
module Walkable
|
40
|
+
include Enumerable
|
40
41
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
def each(&block)
|
43
|
+
children.each(&block)
|
44
|
+
end
|
45
|
+
alias walk each
|
45
46
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
47
|
+
def previous
|
48
|
+
idx = index
|
49
|
+
return unless idx
|
50
|
+
parent.children.fetch(idx - 1)
|
51
|
+
end
|
51
52
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
53
|
+
def child_previous_to(node)
|
54
|
+
idx = children.find_index(node)
|
55
|
+
return unless idx
|
56
|
+
children.fetch(idx - 1)
|
57
|
+
end
|
57
58
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
59
|
+
def insert_before(node, new_node)
|
60
|
+
idx = children.find_index(node)
|
61
|
+
return unless idx
|
62
|
+
children.insert(idx-1, new_node)
|
63
|
+
end
|
63
64
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
65
|
+
def next
|
66
|
+
idx = index
|
67
|
+
return unless idx
|
68
|
+
parent.children.fetch(idx + 1)
|
69
|
+
end
|
69
70
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
71
|
+
def child_after(node)
|
72
|
+
idx = children.find_index(node)
|
73
|
+
return unless idx
|
74
|
+
children.fetch(idx + 1)
|
75
|
+
end
|
75
76
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
77
|
+
def insert_after(node, new_node)
|
78
|
+
idx = children.find_index(node)
|
79
|
+
return unless idx
|
80
|
+
children.insert(idx+1, new_node)
|
81
|
+
end
|
81
82
|
|
82
|
-
|
83
|
-
|
84
|
-
|
83
|
+
def index
|
84
|
+
parent.children.find_index(self)
|
85
|
+
end
|
85
86
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
87
|
+
def remove
|
88
|
+
idx = index
|
89
|
+
parent.children.slice!(idx) if idx
|
90
|
+
end
|
90
91
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
92
|
+
def replace_with(new_node)
|
93
|
+
idx = index
|
94
|
+
return unless idx
|
95
|
+
parent.children.insert(idx, new_node)
|
96
|
+
parent.children.slice!(idx+1)
|
97
|
+
new_node
|
98
|
+
end
|
97
99
|
end
|
98
|
-
end
|
99
100
|
|
100
|
-
module Indentable
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
101
|
+
module Indentable
|
102
|
+
def indent
|
103
|
+
@indent ||= ' ' * 2
|
104
|
+
end
|
105
|
+
def indented?
|
106
|
+
indent.size > 0
|
107
|
+
end
|
108
|
+
def outdent
|
109
|
+
size = indent.size
|
110
|
+
return '' unless size > 0
|
111
|
+
' ' * (size - 2)
|
112
|
+
end
|
111
113
|
end
|
112
|
-
end
|
113
114
|
|
114
|
-
module NotNestedUnder
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
115
|
+
module NotNestedUnder
|
116
|
+
def non_nested?(klass = not_nested_under_class)
|
117
|
+
n = self
|
118
|
+
while (n = n.parent) != nil
|
119
|
+
return false if n.is_a?(klass)
|
120
|
+
end
|
121
|
+
true
|
119
122
|
end
|
120
|
-
true
|
121
|
-
end
|
122
123
|
|
123
|
-
|
124
|
-
|
125
|
-
|
124
|
+
# override if applicable
|
125
|
+
def not_nested_under_class
|
126
|
+
self.class
|
127
|
+
end
|
126
128
|
end
|
127
|
-
end
|
128
129
|
|
129
|
-
# Collection of nodes each one representing an expression.
|
130
|
-
class Nodes < Struct.new(:nodes)
|
131
|
-
|
132
|
-
|
130
|
+
# Collection of nodes each one representing an expression.
|
131
|
+
class Nodes < Struct.new(:nodes)
|
132
|
+
include Visitable
|
133
|
+
include Walkable
|
133
134
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
135
|
+
def <<(node)
|
136
|
+
nodes << node
|
137
|
+
self
|
138
|
+
end
|
138
139
|
|
139
|
-
|
140
|
-
|
141
|
-
|
140
|
+
def [](idx)
|
141
|
+
nodes[idx]
|
142
|
+
end
|
142
143
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
144
|
+
def concat(list_of_nodes)
|
145
|
+
nodes.concat(list_of_nodes)
|
146
|
+
self
|
147
|
+
end
|
147
148
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
149
|
+
# forward missing methods to `nodes` array
|
150
|
+
def method_missing(method, *args, &block)
|
151
|
+
if nodes.respond_to?(method)
|
152
|
+
nodes.send(method, *args, &block)
|
153
|
+
else
|
154
|
+
super
|
155
|
+
end
|
154
156
|
end
|
155
|
-
end
|
156
157
|
|
157
|
-
|
158
|
-
|
159
|
-
|
158
|
+
def respond_to?(method, include_private = false)
|
159
|
+
super || nodes.respond_to?(method, include_private)
|
160
|
+
end
|
160
161
|
|
161
|
-
|
162
|
-
|
162
|
+
def children
|
163
|
+
nodes
|
164
|
+
end
|
163
165
|
end
|
164
|
-
end
|
165
166
|
|
166
|
-
class SublistNode < Nodes; end
|
167
|
+
class SublistNode < Nodes; end
|
167
168
|
|
168
|
-
# Literals are static values that have a Ruby representation, eg.: a string, number, list,
|
169
|
-
# true, false, nil, etc.
|
170
|
-
class LiteralNode < Struct.new(:value)
|
171
|
-
|
172
|
-
end
|
169
|
+
# Literals are static values that have a Ruby representation, eg.: a string, number, list,
|
170
|
+
# true, false, nil, etc.
|
171
|
+
class LiteralNode < Struct.new(:value)
|
172
|
+
include Visitable
|
173
|
+
end
|
173
174
|
|
174
|
-
class KeywordNode < Struct.new(:value)
|
175
|
-
|
176
|
-
end
|
175
|
+
class KeywordNode < Struct.new(:value)
|
176
|
+
include Visitable
|
177
|
+
end
|
177
178
|
|
178
|
-
class NumberNode < LiteralNode; end
|
179
|
+
class NumberNode < LiteralNode; end
|
179
180
|
|
180
|
-
class StringNode < Struct.new(:value, :type) # type: :d or :s for double- or single-quoted
|
181
|
-
|
182
|
-
end
|
181
|
+
class StringNode < Struct.new(:value, :type) # type: :d or :s for double- or single-quoted
|
182
|
+
include Visitable
|
183
|
+
end
|
183
184
|
|
184
|
-
class StringLiteralConcatNode < Struct.new(:string_nodes)
|
185
|
-
|
186
|
-
|
185
|
+
class StringLiteralConcatNode < Struct.new(:string_nodes)
|
186
|
+
include Visitable
|
187
|
+
include Walkable
|
187
188
|
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
189
|
+
def initialize(*string_nodes)
|
190
|
+
super(string_nodes)
|
191
|
+
end
|
192
|
+
alias nodes string_nodes
|
192
193
|
|
193
|
-
|
194
|
-
|
194
|
+
def children
|
195
|
+
string_nodes
|
196
|
+
end
|
195
197
|
end
|
196
|
-
end
|
197
198
|
|
198
|
-
class RegexpNode < LiteralNode; end
|
199
|
+
class RegexpNode < LiteralNode; end
|
199
200
|
|
200
|
-
class ListNode < LiteralNode
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
201
|
+
class ListNode < LiteralNode
|
202
|
+
include Walkable
|
203
|
+
def self.wrap(value)
|
204
|
+
val = Array === value ? value : [value]
|
205
|
+
new(val)
|
206
|
+
end
|
206
207
|
|
207
|
-
|
208
|
-
|
208
|
+
def children
|
209
|
+
value
|
210
|
+
end
|
209
211
|
end
|
210
|
-
end
|
211
212
|
|
212
|
-
class ListUnpackNode < ListNode
|
213
|
-
|
214
|
-
|
213
|
+
class ListUnpackNode < ListNode
|
214
|
+
def rest
|
215
|
+
value.last
|
216
|
+
end
|
215
217
|
end
|
216
|
-
end
|
217
218
|
|
218
|
-
class DictionaryNode < LiteralNode; end
|
219
|
-
class ScopeModifierLiteralNode < LiteralNode; end
|
219
|
+
class DictionaryNode < LiteralNode; end
|
220
|
+
class ScopeModifierLiteralNode < LiteralNode; end
|
220
221
|
|
221
|
-
class TrueNode < LiteralNode
|
222
|
-
|
223
|
-
end
|
222
|
+
class TrueNode < LiteralNode
|
223
|
+
def initialize() super(true) end
|
224
|
+
end
|
224
225
|
|
225
|
-
class FalseNode < LiteralNode
|
226
|
-
|
227
|
-
end
|
226
|
+
class FalseNode < LiteralNode
|
227
|
+
def initialize() super(false) end
|
228
|
+
end
|
228
229
|
|
229
|
-
class NilNode < LiteralNode
|
230
|
-
|
231
|
-
end
|
230
|
+
class NilNode < LiteralNode
|
231
|
+
def initialize() super(nil) end
|
232
|
+
end
|
232
233
|
|
233
|
-
class NewlineNode < LiteralNode
|
234
|
-
|
235
|
-
end
|
234
|
+
class NewlineNode < LiteralNode
|
235
|
+
def initialize() super("\n") end
|
236
|
+
end
|
236
237
|
|
237
|
-
class ExLiteralNode < LiteralNode
|
238
|
-
|
239
|
-
|
240
|
-
|
238
|
+
class ExLiteralNode < LiteralNode
|
239
|
+
def initialize(*)
|
240
|
+
super
|
241
|
+
self.force_newline = true
|
242
|
+
end
|
241
243
|
end
|
242
|
-
end
|
243
244
|
|
244
|
-
class FinishNode < KeywordNode
|
245
|
-
|
246
|
-
end
|
245
|
+
class FinishNode < KeywordNode
|
246
|
+
def initialize() super("finish\n") end
|
247
|
+
end
|
247
248
|
|
248
|
-
class BreakNode < KeywordNode
|
249
|
-
|
250
|
-
end
|
249
|
+
class BreakNode < KeywordNode
|
250
|
+
def initialize() super("break\n") end
|
251
|
+
end
|
251
252
|
|
252
|
-
class ContinueNode < KeywordNode
|
253
|
-
|
254
|
-
end
|
253
|
+
class ContinueNode < KeywordNode
|
254
|
+
def initialize() super("continue\n") end
|
255
|
+
end
|
255
256
|
|
256
|
-
class ReturnNode < Struct.new(:expression)
|
257
|
-
|
258
|
-
|
257
|
+
class ReturnNode < Struct.new(:expression)
|
258
|
+
include Visitable
|
259
|
+
include Walkable
|
259
260
|
|
260
|
-
|
261
|
-
|
261
|
+
def children
|
262
|
+
[expression]
|
263
|
+
end
|
262
264
|
end
|
263
|
-
end
|
264
265
|
|
265
|
-
class WrapInParensNode < Struct.new(:expression)
|
266
|
-
|
267
|
-
|
266
|
+
class WrapInParensNode < Struct.new(:expression)
|
267
|
+
include Visitable
|
268
|
+
include Walkable
|
268
269
|
|
269
|
-
|
270
|
-
|
270
|
+
def children
|
271
|
+
[expression]
|
272
|
+
end
|
271
273
|
end
|
272
|
-
end
|
273
274
|
|
274
|
-
module FullyNameable
|
275
|
-
|
276
|
-
|
277
|
-
|
275
|
+
module FullyNameable
|
276
|
+
def self.included(base)
|
277
|
+
base.class_eval do
|
278
|
+
raise "#{base} must define method 'name'" unless method_defined?(:name)
|
279
|
+
end
|
278
280
|
end
|
279
|
-
end
|
280
281
|
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
282
|
+
def full_name
|
283
|
+
if respond_to?(:scope_modifier)
|
284
|
+
"#{scope_modifier}#{name}"
|
285
|
+
elsif respond_to?(:prefix)
|
286
|
+
"#{prefix}#{name}"
|
287
|
+
end
|
286
288
|
end
|
287
289
|
end
|
288
|
-
end
|
289
290
|
|
290
|
-
# Node of a method call, can take any of these forms:
|
291
|
-
#
|
292
|
-
# Method()
|
293
|
-
# s:Method(argument1, argument2)
|
294
|
-
class CallNode < Struct.new(:scope_modifier, :name, :arguments)
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
291
|
+
# Node of a method call, can take any of these forms:
|
292
|
+
#
|
293
|
+
# Method()
|
294
|
+
# s:Method(argument1, argument2)
|
295
|
+
class CallNode < Struct.new(:scope_modifier, :name, :arguments)
|
296
|
+
include Riml::Constants
|
297
|
+
include Visitable
|
298
|
+
include FullyNameable
|
299
|
+
include Walkable
|
299
300
|
|
300
|
-
|
301
|
-
|
301
|
+
ALL_BUILTIN_FUNCTIONS = BUILTIN_FUNCTIONS + BUILTIN_COMMANDS
|
302
|
+
ALL_BUILTIN_COMMANDS = BUILTIN_COMMANDS + RIML_COMMANDS + VIML_COMMANDS
|
302
303
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
304
|
+
def initialize(scope_modifier, name, arguments)
|
305
|
+
super
|
306
|
+
remove_parens_wrapper if builtin_command?
|
307
|
+
end
|
307
308
|
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
309
|
+
# TODO: find way to remove this hack
|
310
|
+
def remove_parens_wrapper
|
311
|
+
return unless WrapInParensNode === arguments.first
|
312
|
+
arguments[0] = arguments[0].expression
|
313
|
+
end
|
313
314
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
315
|
+
def builtin_function?
|
316
|
+
return false unless name.is_a?(String)
|
317
|
+
scope_modifier.nil? and ALL_BUILTIN_FUNCTIONS.include?(name)
|
318
|
+
end
|
318
319
|
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
320
|
+
def builtin_command?
|
321
|
+
return false unless name.is_a?(String)
|
322
|
+
scope_modifier.nil? and ALL_BUILTIN_COMMANDS.include?(name)
|
323
|
+
end
|
323
324
|
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
325
|
+
def must_be_explicit_call?
|
326
|
+
return false if builtin_command?
|
327
|
+
return true if parent.instance_of?(Nodes)
|
328
|
+
false
|
329
|
+
end
|
329
330
|
|
330
|
-
|
331
|
-
|
332
|
-
|
331
|
+
def autoload?
|
332
|
+
name.include?('#')
|
333
|
+
end
|
333
334
|
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
335
|
+
def children
|
336
|
+
if name.is_a?(String)
|
337
|
+
arguments
|
338
|
+
else
|
339
|
+
[name] + arguments
|
340
|
+
end
|
339
341
|
end
|
340
342
|
end
|
341
|
-
end
|
342
343
|
|
343
|
-
# Node of an explicitly called method, can take any of these forms:
|
344
|
-
#
|
345
|
-
# call Method()
|
346
|
-
# call s:Method(argument1, argument2)
|
347
|
-
class ExplicitCallNode < CallNode; end
|
348
|
-
class RimlCommandNode < CallNode
|
344
|
+
# Node of an explicitly called method, can take any of these forms:
|
345
|
+
#
|
346
|
+
# call Method()
|
347
|
+
# call s:Method(argument1, argument2)
|
348
|
+
class ExplicitCallNode < CallNode; end
|
349
|
+
class RimlCommandNode < CallNode
|
349
350
|
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
351
|
+
def initialize(*)
|
352
|
+
super
|
353
|
+
if arguments.empty? || !arguments.all? { |arg| arg.is_a?(StringNode) }
|
354
|
+
raise Riml::UserArgumentError, "#{name.inspect} error: must pass string(s) (name of file(s))"
|
355
|
+
end
|
354
356
|
end
|
355
|
-
end
|
356
357
|
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
358
|
+
def each_existing_file!
|
359
|
+
files = []
|
360
|
+
arguments.map(&:value).each do |file|
|
361
|
+
if File.exists?(File.join(Riml.source_path, file))
|
362
|
+
files << file
|
363
|
+
else
|
364
|
+
raise Riml::FileNotFound, "#{file.inspect} could not be found in " \
|
365
|
+
"source path (#{Riml.source_path.inspect})"
|
366
|
+
end
|
365
367
|
end
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
368
|
+
return unless block_given?
|
369
|
+
# all files exist
|
370
|
+
files.each do |f|
|
371
|
+
begin
|
372
|
+
yield f
|
373
|
+
rescue Riml::IncludeFileLoop
|
374
|
+
arguments.delete_if { |arg| arg.value == f }
|
375
|
+
end
|
374
376
|
end
|
375
377
|
end
|
376
378
|
end
|
377
|
-
end
|
378
379
|
|
379
|
-
class OperatorNode < Struct.new(:operator, :operands)
|
380
|
-
|
381
|
-
|
380
|
+
class OperatorNode < Struct.new(:operator, :operands)
|
381
|
+
include Visitable
|
382
|
+
include Walkable
|
382
383
|
|
383
|
-
|
384
|
-
|
384
|
+
def children
|
385
|
+
operands
|
386
|
+
end
|
385
387
|
end
|
386
|
-
end
|
387
388
|
|
388
|
-
class BinaryOperatorNode < OperatorNode
|
389
|
-
|
389
|
+
class BinaryOperatorNode < OperatorNode
|
390
|
+
include Riml::Constants
|
390
391
|
|
391
|
-
|
392
|
-
|
392
|
+
def operand1() operands[0] end
|
393
|
+
def operand1=(val) operands[0] = val end
|
393
394
|
|
394
|
-
|
395
|
-
|
395
|
+
def operand2() operands[1] end
|
396
|
+
def operand2=(val) operands[1] = val end
|
396
397
|
|
397
|
-
|
398
|
-
|
398
|
+
def ignorecase_capable_operator?(operator)
|
399
|
+
IGNORECASE_CAPABLE_OPERATORS.include?(operator)
|
400
|
+
end
|
399
401
|
end
|
400
|
-
end
|
401
402
|
|
402
|
-
class UnaryOperatorNode < OperatorNode
|
403
|
-
|
404
|
-
end
|
405
|
-
|
406
|
-
# operator = :ternary
|
407
|
-
# operands = [condition, if_expr, else_expr]
|
408
|
-
class TernaryOperatorNode < OperatorNode
|
409
|
-
def initialize(operands, operator=:ternary)
|
410
|
-
super(operator, operands)
|
403
|
+
class UnaryOperatorNode < OperatorNode
|
404
|
+
alias operand operands
|
411
405
|
end
|
412
406
|
|
413
|
-
|
407
|
+
# operator = :ternary
|
408
|
+
# operands = [condition, if_expr, else_expr]
|
409
|
+
class TernaryOperatorNode < OperatorNode
|
410
|
+
def initialize(operands, operator=:ternary)
|
411
|
+
super(operator, operands)
|
412
|
+
end
|
414
413
|
|
415
|
-
|
414
|
+
def condition() operands[0] end
|
416
415
|
|
417
|
-
|
418
|
-
|
416
|
+
def if_expr() operands[1] end
|
417
|
+
|
418
|
+
def else_expr() operands[2] end
|
419
|
+
end
|
419
420
|
|
420
|
-
# let var = 2
|
421
|
-
# let s:var = 4
|
422
|
-
class AssignNode < Struct.new(:operator, :lhs, :rhs)
|
423
|
-
|
424
|
-
|
421
|
+
# let var = 2
|
422
|
+
# let s:var = 4
|
423
|
+
class AssignNode < Struct.new(:operator, :lhs, :rhs)
|
424
|
+
include Visitable
|
425
|
+
include Walkable
|
425
426
|
|
426
|
-
|
427
|
-
|
427
|
+
def children
|
428
|
+
[lhs, rhs]
|
429
|
+
end
|
428
430
|
end
|
429
|
-
end
|
430
431
|
|
431
|
-
module QuestionVariableExistence
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
432
|
+
module QuestionVariableExistence
|
433
|
+
def self.included(base)
|
434
|
+
base.class_eval do
|
435
|
+
raise "#{base} must define method 'name'" unless method_defined?(:name)
|
436
|
+
alias name_with_question_mark name
|
437
|
+
def name_without_question_mark
|
438
|
+
if question_existence?
|
439
|
+
name_with_question_mark[0...-1]
|
440
|
+
else
|
441
|
+
name_with_question_mark
|
442
|
+
end
|
441
443
|
end
|
444
|
+
alias name name_without_question_mark
|
442
445
|
end
|
443
|
-
alias name name_without_question_mark
|
444
446
|
end
|
445
|
-
end
|
446
447
|
|
447
|
-
|
448
|
-
|
448
|
+
def question_existence?
|
449
|
+
name_with_question_mark[-1] == ??
|
450
|
+
end
|
449
451
|
end
|
450
|
-
end
|
451
452
|
|
452
|
-
# s:var
|
453
|
-
# var
|
454
|
-
class GetVariableNode < Struct.new(:scope_modifier, :name)
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
end
|
453
|
+
# s:var
|
454
|
+
# var
|
455
|
+
class GetVariableNode < Struct.new(:scope_modifier, :name)
|
456
|
+
include Visitable
|
457
|
+
include FullyNameable
|
458
|
+
include QuestionVariableExistence
|
459
|
+
end
|
459
460
|
|
460
|
-
# &autoindent
|
461
|
-
# @q
|
462
|
-
class GetSpecialVariableNode < Struct.new(:prefix, :name)
|
463
|
-
|
464
|
-
|
465
|
-
end
|
461
|
+
# &autoindent
|
462
|
+
# @q
|
463
|
+
class GetSpecialVariableNode < Struct.new(:prefix, :name)
|
464
|
+
include Visitable
|
465
|
+
include FullyNameable
|
466
|
+
end
|
466
467
|
|
467
|
-
class GetCurlyBraceNameNode < Struct.new(:scope_modifier, :variable)
|
468
|
-
|
469
|
-
|
468
|
+
class GetCurlyBraceNameNode < Struct.new(:scope_modifier, :variable)
|
469
|
+
include Visitable
|
470
|
+
include Walkable
|
470
471
|
|
471
|
-
|
472
|
-
|
472
|
+
def children
|
473
|
+
[variable]
|
474
|
+
end
|
473
475
|
end
|
474
|
-
end
|
475
476
|
|
476
|
-
class CurlyBraceVariable < Struct.new(:parts)
|
477
|
-
|
478
|
-
|
477
|
+
class CurlyBraceVariable < Struct.new(:parts)
|
478
|
+
include Visitable
|
479
|
+
include Walkable
|
479
480
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
481
|
+
def <<(part)
|
482
|
+
parts << part
|
483
|
+
self
|
484
|
+
end
|
484
485
|
|
485
|
-
|
486
|
-
|
486
|
+
def children
|
487
|
+
parts
|
488
|
+
end
|
487
489
|
end
|
488
|
-
end
|
489
490
|
|
490
|
-
class CurlyBracePart < Struct.new(:value)
|
491
|
-
|
492
|
-
|
491
|
+
class CurlyBracePart < Struct.new(:value)
|
492
|
+
include Visitable
|
493
|
+
include Walkable
|
493
494
|
|
494
|
-
|
495
|
-
|
496
|
-
|
495
|
+
def interpolated?
|
496
|
+
GetVariableNode === value || GetSpecialVariableNode === value || nested?
|
497
|
+
end
|
497
498
|
|
498
|
-
|
499
|
-
|
500
|
-
|
499
|
+
def nested?
|
500
|
+
value.is_a?(Array) && value.detect {|part| part.is_a?(CurlyBracePart)}
|
501
|
+
end
|
501
502
|
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
503
|
+
def children
|
504
|
+
return [] unless interpolated?
|
505
|
+
return value if nested?
|
506
|
+
[value]
|
507
|
+
end
|
506
508
|
end
|
507
|
-
end
|
508
509
|
|
509
|
-
class UnletVariableNode < Struct.new(:bang, :variables)
|
510
|
-
|
511
|
-
|
510
|
+
class UnletVariableNode < Struct.new(:bang, :variables)
|
511
|
+
include Visitable
|
512
|
+
include Walkable
|
512
513
|
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
514
|
+
def <<(variable)
|
515
|
+
variables << variable
|
516
|
+
self
|
517
|
+
end
|
517
518
|
|
518
|
-
|
519
|
-
|
519
|
+
def children
|
520
|
+
variables
|
521
|
+
end
|
520
522
|
end
|
521
|
-
end
|
522
523
|
|
523
|
-
# Method definition.
|
524
|
-
class DefNode < Struct.new(:bang, :scope_modifier, :name, :parameters, :keywords, :expressions)
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
524
|
+
# Method definition.
|
525
|
+
class DefNode < Struct.new(:bang, :scope_modifier, :name, :parameters, :keywords, :expressions)
|
526
|
+
include Visitable
|
527
|
+
include Indentable
|
528
|
+
include FullyNameable
|
529
|
+
include Walkable
|
529
530
|
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
531
|
+
def initialize(*args)
|
532
|
+
super
|
533
|
+
# max number of arguments in viml
|
534
|
+
if parameters.reject(&DEFAULT_PARAMS).size > 20
|
535
|
+
raise Riml::UserArgumentError, "can't have more than 20 parameters for #{full_name}"
|
536
|
+
end
|
537
|
+
expressions.nodes.select { |node| DefNode === node}.each do |nested_func|
|
538
|
+
nested_func.nested_within.unshift(self)
|
539
|
+
end
|
535
540
|
end
|
536
|
-
|
537
|
-
|
541
|
+
|
542
|
+
SPLAT = lambda {|arg| arg == Riml::Constants::SPLAT_LITERAL || arg[0] == "*"}
|
543
|
+
DEFAULT_PARAMS = lambda {|p| DefaultParamNode === p}
|
544
|
+
|
545
|
+
def original_name
|
546
|
+
@original_name ||= name
|
538
547
|
end
|
539
|
-
|
548
|
+
attr_writer :original_name
|
540
549
|
|
541
|
-
|
542
|
-
|
550
|
+
# ["arg1", "arg2"}
|
551
|
+
def argument_variable_names
|
552
|
+
parameters.reject(&SPLAT)
|
553
|
+
end
|
543
554
|
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
attr_writer :original_name
|
555
|
+
def shadowed_argument?(var_name)
|
556
|
+
shadowed_argument_variable_names.include?(var_name)
|
557
|
+
end
|
548
558
|
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
end
|
559
|
+
def shadowed_argument_variable_names
|
560
|
+
@shadowed_argument_variable_names ||= Set.new
|
561
|
+
end
|
553
562
|
|
554
|
-
|
555
|
-
|
556
|
-
|
563
|
+
def nested_within
|
564
|
+
@nested_within ||= []
|
565
|
+
end
|
557
566
|
|
558
|
-
|
559
|
-
|
560
|
-
|
567
|
+
def nested_function?
|
568
|
+
not nested_within.empty?
|
569
|
+
end
|
561
570
|
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
571
|
+
# returns the splat argument or nil
|
572
|
+
def splat
|
573
|
+
parameters.detect(&SPLAT)
|
574
|
+
end
|
566
575
|
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
576
|
+
def keywords
|
577
|
+
if name.include?('.')
|
578
|
+
(super.to_a + ['dict']).uniq
|
579
|
+
else
|
580
|
+
super.to_a
|
581
|
+
end
|
572
582
|
end
|
573
|
-
end
|
574
583
|
|
575
|
-
|
576
|
-
|
577
|
-
|
584
|
+
def defined_on_dictionary?
|
585
|
+
keywords.include?('dict')
|
586
|
+
end
|
578
587
|
|
579
|
-
|
580
|
-
|
581
|
-
|
588
|
+
def autoload?
|
589
|
+
name.include?('#')
|
590
|
+
end
|
582
591
|
|
583
|
-
|
584
|
-
|
585
|
-
|
592
|
+
def super_node
|
593
|
+
expressions.nodes.detect {|n| SuperNode === n}
|
594
|
+
end
|
586
595
|
|
587
|
-
|
588
|
-
|
589
|
-
|
590
|
-
|
596
|
+
def to_scope
|
597
|
+
ScopeNode.new.tap do |scope|
|
598
|
+
scope.argument_variable_names += argument_variable_names
|
599
|
+
scope.function = self
|
600
|
+
end
|
591
601
|
end
|
592
|
-
end
|
593
602
|
|
594
|
-
|
595
|
-
|
596
|
-
|
603
|
+
def default_param_nodes
|
604
|
+
parameters.select(&DEFAULT_PARAMS)
|
605
|
+
end
|
597
606
|
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
607
|
+
def children
|
608
|
+
children = [expressions]
|
609
|
+
children.concat(default_param_nodes)
|
610
|
+
end
|
602
611
|
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
612
|
+
def method_missing(method, *args, &blk)
|
613
|
+
if children.respond_to?(method)
|
614
|
+
children.send(method, *args, &blk)
|
615
|
+
else
|
616
|
+
super
|
617
|
+
end
|
608
618
|
end
|
609
619
|
end
|
610
|
-
end
|
611
620
|
|
612
|
-
class DefaultParamNode < Struct.new(:parameter, :expression)
|
613
|
-
|
614
|
-
|
621
|
+
class DefaultParamNode < Struct.new(:parameter, :expression)
|
622
|
+
include Visitable
|
623
|
+
include Walkable
|
615
624
|
|
616
|
-
|
617
|
-
|
625
|
+
def children
|
626
|
+
[parameter, expression]
|
627
|
+
end
|
618
628
|
end
|
619
|
-
end
|
620
629
|
|
621
|
-
class ScopeNode
|
622
|
-
|
623
|
-
|
630
|
+
class ScopeNode
|
631
|
+
attr_writer :for_node_variable_names, :argument_variable_names
|
632
|
+
attr_accessor :function
|
624
633
|
|
625
|
-
|
626
|
-
|
627
|
-
|
634
|
+
def for_node_variable_names
|
635
|
+
@for_node_variable_names ||= Set.new
|
636
|
+
end
|
628
637
|
|
629
|
-
|
630
|
-
|
631
|
-
|
638
|
+
def argument_variable_names
|
639
|
+
@argument_variable_names ||= Set.new
|
640
|
+
end
|
632
641
|
|
633
|
-
|
642
|
+
alias function? function
|
634
643
|
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
644
|
+
def initialize_copy(source)
|
645
|
+
super
|
646
|
+
self.for_node_variable_names = for_node_variable_names.dup
|
647
|
+
self.argument_variable_names = argument_variable_names.dup
|
648
|
+
self.function = source.function
|
649
|
+
end
|
641
650
|
|
642
|
-
|
643
|
-
|
644
|
-
|
651
|
+
def merge(other)
|
652
|
+
dup.merge! other
|
653
|
+
end
|
645
654
|
|
646
|
-
|
647
|
-
|
648
|
-
|
655
|
+
def merge!(other)
|
656
|
+
unless other.is_a?(ScopeNode)
|
657
|
+
raise ArgumentError, "other must be ScopeNode, is #{other.class}"
|
658
|
+
end
|
659
|
+
self.for_node_variable_names += other.for_node_variable_names
|
660
|
+
self.argument_variable_names -= for_node_variable_names
|
661
|
+
self.function = other.function
|
662
|
+
self
|
649
663
|
end
|
650
|
-
self.for_node_variable_names += other.for_node_variable_names
|
651
|
-
self.argument_variable_names -= for_node_variable_names
|
652
|
-
self.function = other.function
|
653
|
-
self
|
654
664
|
end
|
655
|
-
end
|
656
665
|
|
657
|
-
class DefMethodNode < DefNode
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
666
|
+
class DefMethodNode < DefNode
|
667
|
+
def to_def_node
|
668
|
+
def_node = DefNode.new(bang, 'g:', name, parameters, ['dict'], expressions)
|
669
|
+
def_node.parent = parent
|
670
|
+
def_node
|
671
|
+
end
|
662
672
|
end
|
663
|
-
end
|
664
673
|
|
665
|
-
# abstract control structure
|
666
|
-
class ControlStructure < Struct.new(:condition, :body)
|
667
|
-
|
668
|
-
|
669
|
-
|
674
|
+
# abstract control structure
|
675
|
+
class ControlStructure < Struct.new(:condition, :body)
|
676
|
+
include Visitable
|
677
|
+
include Indentable
|
678
|
+
include Walkable
|
670
679
|
|
671
|
-
|
672
|
-
|
673
|
-
|
680
|
+
def children
|
681
|
+
[condition, body]
|
682
|
+
end
|
674
683
|
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
684
|
+
def wrap_condition_in_parens!
|
685
|
+
return if WrapInParensNode === condition
|
686
|
+
_parent = condition.parent
|
687
|
+
self.condition = WrapInParensNode.new(condition)
|
688
|
+
self.condition.parent = _parent
|
689
|
+
end
|
680
690
|
end
|
681
|
-
end
|
682
691
|
|
683
|
-
class IfNode < ControlStructure
|
684
|
-
|
685
|
-
end
|
686
|
-
class WhileNode < ControlStructure; end
|
692
|
+
class IfNode < ControlStructure
|
693
|
+
include NotNestedUnder
|
694
|
+
end
|
695
|
+
class WhileNode < ControlStructure; end
|
687
696
|
|
688
|
-
class UnlessNode < ControlStructure
|
689
|
-
|
690
|
-
|
691
|
-
|
697
|
+
class UnlessNode < ControlStructure
|
698
|
+
def initialize(*)
|
699
|
+
super
|
700
|
+
wrap_condition_in_parens!
|
701
|
+
end
|
692
702
|
end
|
693
|
-
|
694
|
-
|
695
|
-
|
696
|
-
|
697
|
-
|
703
|
+
class UntilNode < ControlStructure
|
704
|
+
def initialize(*)
|
705
|
+
super
|
706
|
+
wrap_condition_in_parens!
|
707
|
+
end
|
698
708
|
end
|
699
|
-
end
|
700
709
|
|
701
|
-
class ElseNode < Struct.new(:expressions)
|
702
|
-
|
703
|
-
|
704
|
-
|
710
|
+
class ElseNode < Struct.new(:expressions)
|
711
|
+
include Visitable
|
712
|
+
include Walkable
|
713
|
+
alias body expressions
|
705
714
|
|
706
|
-
|
707
|
-
|
708
|
-
|
709
|
-
|
715
|
+
def <<(expr)
|
716
|
+
expressions << expr
|
717
|
+
self
|
718
|
+
end
|
710
719
|
|
711
|
-
|
712
|
-
|
713
|
-
|
720
|
+
def pop
|
721
|
+
expressions.pop
|
722
|
+
end
|
714
723
|
|
715
|
-
|
716
|
-
|
717
|
-
|
724
|
+
def last
|
725
|
+
expressions.last
|
726
|
+
end
|
718
727
|
|
719
|
-
|
720
|
-
|
728
|
+
def children
|
729
|
+
[expressions]
|
730
|
+
end
|
721
731
|
end
|
722
|
-
end
|
723
732
|
|
724
|
-
class ElseifNode < ControlStructure
|
725
|
-
|
726
|
-
|
727
|
-
|
733
|
+
class ElseifNode < ControlStructure
|
734
|
+
include Visitable
|
735
|
+
include Walkable
|
736
|
+
alias expressions body
|
728
737
|
|
729
|
-
|
730
|
-
|
731
|
-
|
732
|
-
|
738
|
+
def <<(expr)
|
739
|
+
expressions << expr
|
740
|
+
self
|
741
|
+
end
|
733
742
|
|
734
|
-
|
735
|
-
|
736
|
-
|
743
|
+
def pop
|
744
|
+
expressions.pop
|
745
|
+
end
|
737
746
|
|
738
|
-
|
739
|
-
|
740
|
-
|
747
|
+
def last
|
748
|
+
expressions.last
|
749
|
+
end
|
741
750
|
|
742
|
-
|
743
|
-
|
751
|
+
def children
|
752
|
+
[expressions]
|
753
|
+
end
|
744
754
|
end
|
745
|
-
end
|
746
755
|
|
747
|
-
# for variable in someFunction(1,2,3)
|
748
|
-
# echo variable
|
749
|
-
# end
|
750
|
-
#
|
751
|
-
# OR
|
752
|
-
#
|
753
|
-
# for variable in [1,2,3]
|
754
|
-
# echo variable
|
755
|
-
# end
|
756
|
-
class ForNode < Struct.new(:variable, :in_expression, :expressions)
|
757
|
-
|
758
|
-
|
759
|
-
|
760
|
-
|
761
|
-
|
762
|
-
|
763
|
-
|
764
|
-
|
765
|
-
end
|
766
|
-
|
767
|
-
def for_node_variable_names
|
768
|
-
if ListNode === variable
|
769
|
-
variable.value.map(&:name)
|
770
|
-
else
|
771
|
-
[variable]
|
756
|
+
# for variable in someFunction(1,2,3)
|
757
|
+
# echo variable
|
758
|
+
# end
|
759
|
+
#
|
760
|
+
# OR
|
761
|
+
#
|
762
|
+
# for variable in [1,2,3]
|
763
|
+
# echo variable
|
764
|
+
# end
|
765
|
+
class ForNode < Struct.new(:variable, :in_expression, :expressions)
|
766
|
+
include Visitable
|
767
|
+
include Indentable
|
768
|
+
include Walkable
|
769
|
+
|
770
|
+
alias for_variable variable
|
771
|
+
|
772
|
+
def variables
|
773
|
+
variable if ListNode === variable
|
772
774
|
end
|
773
|
-
end
|
774
775
|
|
775
|
-
|
776
|
-
|
777
|
-
|
776
|
+
def for_node_variable_names
|
777
|
+
if ListNode === variable
|
778
|
+
variable.value.map(&:name)
|
779
|
+
else
|
780
|
+
[variable]
|
781
|
+
end
|
782
|
+
end
|
778
783
|
|
779
|
-
|
780
|
-
|
784
|
+
def to_scope
|
785
|
+
ScopeNode.new.tap {|s| s.for_node_variable_names += for_node_variable_names}
|
786
|
+
end
|
787
|
+
|
788
|
+
def children
|
789
|
+
[variable, in_expression, expressions]
|
790
|
+
end
|
781
791
|
end
|
782
|
-
end
|
783
792
|
|
784
|
-
class DictGetNode < Struct.new(:dict, :keys)
|
785
|
-
|
786
|
-
|
793
|
+
class DictGetNode < Struct.new(:dict, :keys)
|
794
|
+
include Visitable
|
795
|
+
include Walkable
|
787
796
|
|
788
|
-
|
789
|
-
|
797
|
+
def children
|
798
|
+
[dict] + keys
|
799
|
+
end
|
790
800
|
end
|
791
|
-
end
|
792
801
|
|
793
|
-
# dict['key']
|
794
|
-
# dict['key1']['key2']
|
795
|
-
class DictGetBracketNode < DictGetNode; end
|
802
|
+
# dict['key']
|
803
|
+
# dict['key1']['key2']
|
804
|
+
class DictGetBracketNode < DictGetNode; end
|
796
805
|
|
797
|
-
# dict.key
|
798
|
-
# dict.key.key2
|
799
|
-
class DictGetDotNode < DictGetNode; end
|
806
|
+
# dict.key
|
807
|
+
# dict.key.key2
|
808
|
+
class DictGetDotNode < DictGetNode; end
|
800
809
|
|
801
810
|
|
802
|
-
# list_or_dict[0]
|
803
|
-
# function()[identifier]
|
804
|
-
class ListOrDictGetNode < Struct.new(:list_or_dict, :keys)
|
805
|
-
|
806
|
-
|
811
|
+
# list_or_dict[0]
|
812
|
+
# function()[identifier]
|
813
|
+
class ListOrDictGetNode < Struct.new(:list_or_dict, :keys)
|
814
|
+
include Visitable
|
815
|
+
include Walkable
|
807
816
|
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
817
|
+
alias list list_or_dict
|
818
|
+
alias dict list_or_dict
|
819
|
+
def children
|
820
|
+
[list_or_dict] + keys
|
821
|
+
end
|
812
822
|
end
|
813
|
-
end
|
814
823
|
|
815
|
-
class GetVariableByScopeAndDictNameNode < Struct.new(:scope_modifier, :keys)
|
816
|
-
|
817
|
-
|
824
|
+
class GetVariableByScopeAndDictNameNode < Struct.new(:scope_modifier, :keys)
|
825
|
+
include Visitable
|
826
|
+
include Walkable
|
818
827
|
|
819
|
-
|
820
|
-
|
828
|
+
def children
|
829
|
+
[scope_modifier] + keys
|
830
|
+
end
|
821
831
|
end
|
822
|
-
end
|
823
832
|
|
824
|
-
class TryNode < Struct.new(:try_block, :catch_nodes, :finally_block)
|
825
|
-
|
826
|
-
|
827
|
-
|
833
|
+
class TryNode < Struct.new(:try_block, :catch_nodes, :finally_block)
|
834
|
+
include Visitable
|
835
|
+
include Indentable
|
836
|
+
include Walkable
|
828
837
|
|
829
|
-
|
830
|
-
|
838
|
+
def children
|
839
|
+
[try_block] + catch_nodes.to_a + [finally_block].compact
|
840
|
+
end
|
831
841
|
end
|
832
|
-
end
|
833
842
|
|
834
|
-
class CatchNode < Struct.new(:regexp, :expressions)
|
835
|
-
|
836
|
-
|
837
|
-
|
843
|
+
class CatchNode < Struct.new(:regexp, :expressions)
|
844
|
+
include Visitable
|
845
|
+
include Walkable
|
846
|
+
include NotNestedUnder
|
838
847
|
|
839
|
-
|
840
|
-
|
841
|
-
|
848
|
+
def children
|
849
|
+
[expressions]
|
850
|
+
end
|
842
851
|
|
843
|
-
end
|
852
|
+
end
|
844
853
|
|
845
|
-
class ClassDefinitionNode < Struct.new(:name, :superclass_name, :expressions)
|
846
|
-
|
847
|
-
|
854
|
+
class ClassDefinitionNode < Struct.new(:name, :superclass_name, :expressions)
|
855
|
+
include Visitable
|
856
|
+
include Walkable
|
848
857
|
|
849
|
-
|
858
|
+
FUNCTIONS = lambda {|expr| DefNode === expr}
|
850
859
|
|
851
|
-
|
852
|
-
|
853
|
-
|
860
|
+
def superclass?
|
861
|
+
not superclass_name.nil?
|
862
|
+
end
|
854
863
|
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
864
|
+
def constructor
|
865
|
+
expressions.nodes.detect do |n|
|
866
|
+
next(false) unless DefNode === n && (n.name == 'initialize' || n.name == constructor_name)
|
867
|
+
if n.instance_of?(DefMethodNode)
|
868
|
+
Riml.warn("class #{name.inspect} has an initialize function declared with 'defm'. Please use 'def'.")
|
869
|
+
new_node = n.to_def_node
|
870
|
+
new_node.keywords = nil
|
871
|
+
n.replace_with(new_node)
|
872
|
+
end
|
873
|
+
true
|
863
874
|
end
|
864
|
-
true
|
865
875
|
end
|
866
|
-
|
867
|
-
alias constructor? constructor
|
876
|
+
alias constructor? constructor
|
868
877
|
|
869
|
-
|
870
|
-
|
871
|
-
|
878
|
+
def find_function(scope_modifier, name)
|
879
|
+
expressions.nodes.select(&FUNCTIONS).detect do |def_node|
|
880
|
+
def_node.name == name && def_node.scope_modifier == scope_modifier
|
881
|
+
end
|
872
882
|
end
|
873
|
-
|
874
|
-
alias has_function? find_function
|
883
|
+
alias has_function? find_function
|
875
884
|
|
876
|
-
|
877
|
-
|
878
|
-
|
885
|
+
def constructor_name
|
886
|
+
"#{name}Constructor"
|
887
|
+
end
|
879
888
|
|
880
|
-
|
881
|
-
|
882
|
-
|
889
|
+
def constructor_obj_name
|
890
|
+
name[0].downcase + name[1..-1] + "Obj"
|
891
|
+
end
|
883
892
|
|
884
|
-
|
885
|
-
|
893
|
+
def children
|
894
|
+
[expressions]
|
895
|
+
end
|
886
896
|
end
|
887
|
-
end
|
888
897
|
|
889
|
-
class SuperNode < Struct.new(:arguments, :with_parens)
|
890
|
-
|
891
|
-
|
898
|
+
class SuperNode < Struct.new(:arguments, :with_parens)
|
899
|
+
include Visitable
|
900
|
+
include Walkable
|
892
901
|
|
893
|
-
|
894
|
-
|
895
|
-
|
902
|
+
def use_all_arguments?
|
903
|
+
arguments.empty? && !with_parens
|
904
|
+
end
|
896
905
|
|
897
|
-
|
898
|
-
|
906
|
+
def children
|
907
|
+
arguments
|
908
|
+
end
|
899
909
|
end
|
900
|
-
end
|
901
910
|
|
902
|
-
class ObjectInstantiationNode < Struct.new(:call_node)
|
903
|
-
|
904
|
-
|
911
|
+
class ObjectInstantiationNode < Struct.new(:call_node)
|
912
|
+
include Visitable
|
913
|
+
include Walkable
|
905
914
|
|
906
|
-
|
907
|
-
|
915
|
+
def children
|
916
|
+
[call_node]
|
917
|
+
end
|
908
918
|
end
|
909
919
|
end
|