riml 0.1.3

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/nodes.rb ADDED
@@ -0,0 +1,723 @@
1
+ require File.expand_path('../constants', __FILE__)
2
+ require 'set'
3
+
4
+ module Visitable
5
+ def accept(visitor)
6
+ visitor.visit(self)
7
+ end
8
+
9
+ attr_accessor :parent_node, :scope, :force_newline
10
+ alias parent parent_node
11
+ alias parent= parent_node=
12
+
13
+ attr_writer :compiled_output
14
+ def compiled_output
15
+ @compiled_output ||= ''
16
+ end
17
+
18
+ # catches "descendant_of_#{some_class}?" methods
19
+ # def descendant_of_call_node?
20
+ # CallNode === self.parent_node
21
+ # end
22
+ DESCENDANT_OF_REGEX = /\Adescendant_of_(.*?)\?/
23
+ def method_missing(method, *args, &blk)
24
+ if method =~ DESCENDANT_OF_REGEX
25
+ parent_node_name = $1.split('_').map(&:capitalize).join
26
+ parent_node = self.class.const_get parent_node_name
27
+ parent_node === self.parent_node
28
+ else
29
+ super
30
+ end
31
+ end
32
+ def respond_to_missing?(method, include_private = false)
33
+ return true if method =~ DESCENDANT_OF_REGEX
34
+ super
35
+ end
36
+ end
37
+
38
+ module Walkable
39
+ include Enumerable
40
+
41
+ def each &block
42
+ children.each &block
43
+ end
44
+ alias walk each
45
+
46
+ def previous
47
+ idx = index
48
+ return unless idx
49
+ parent.children.fetch(idx - 1)
50
+ end
51
+
52
+ def child_previous_to(node)
53
+ idx = children.find_index(node)
54
+ return unless idx
55
+ children.fetch(idx - 1)
56
+ end
57
+
58
+ def insert_before(node, new_node)
59
+ idx = children.find_index(node)
60
+ return unless idx
61
+ children.insert(idx-1, new_node)
62
+ end
63
+
64
+ def next
65
+ idx = index
66
+ return unless idx
67
+ parent.children.fetch(idx + 1)
68
+ end
69
+
70
+ def child_after(node)
71
+ idx = children.find_index(node)
72
+ return unless idx
73
+ children.fetch(idx + 1)
74
+ end
75
+
76
+ def insert_after(node, new_node)
77
+ idx = children.find_index(node)
78
+ return unless idx
79
+ children.insert(idx+1, new_node)
80
+ end
81
+
82
+ def index
83
+ parent.children.find_index(self)
84
+ end
85
+
86
+ def remove
87
+ idx = index
88
+ parent.children.slice!(idx) if idx
89
+ end
90
+
91
+ def replace_with(new_node)
92
+ idx = index
93
+ return unless idx
94
+ parent.children.insert(idx, new_node)
95
+ parent.children.slice!(idx+1)
96
+ end
97
+ end
98
+
99
+ module Indentable
100
+ def indent
101
+ @indent ||= " " * 2
102
+ end
103
+ end
104
+
105
+ # Collection of nodes each one representing an expression.
106
+ class Nodes < Struct.new(:nodes)
107
+ include Visitable
108
+ include Walkable
109
+
110
+ def <<(node)
111
+ nodes << node
112
+ self
113
+ end
114
+
115
+ def concat(list_of_nodes)
116
+ nodes.concat(list_of_nodes)
117
+ self
118
+ end
119
+
120
+ # forward missing methods to `nodes` array
121
+ def method_missing(method, *args, &block)
122
+ if nodes.respond_to?(method)
123
+ nodes.send(method, *args, &block)
124
+ else
125
+ super
126
+ end
127
+ end
128
+
129
+ def respond_to_missing?(method, include_private = false)
130
+ return true if nodes.respond_to?(method)
131
+ super
132
+ end
133
+
134
+ def children
135
+ nodes
136
+ end
137
+ end
138
+
139
+ # Literals are static values that have a Ruby representation, eg.: a string, number, list,
140
+ # true, false, nil, etc.
141
+ class LiteralNode < Struct.new(:value)
142
+ include Visitable
143
+ end
144
+
145
+ class KeywordNode < Struct.new(:value)
146
+ include Visitable
147
+ end
148
+
149
+ class NumberNode < LiteralNode; end
150
+
151
+ class StringNode < Struct.new(:value, :type) # type: :d or :s for double- or single-quoted
152
+ include Visitable
153
+ end
154
+
155
+ class RegexpNode < LiteralNode; end
156
+ class ListNode < LiteralNode
157
+ include Walkable
158
+ def self.wrap(value)
159
+ val = Array === value ? value : [value]
160
+ new(val)
161
+ end
162
+
163
+ def children
164
+ value
165
+ end
166
+ end
167
+ class DictionaryNode < LiteralNode; end
168
+ class ScopeModifierLiteralNode < LiteralNode; end
169
+
170
+ class TrueNode < LiteralNode
171
+ def initialize() super(true) end
172
+ end
173
+
174
+ class FalseNode < LiteralNode
175
+ def initialize() super(false) end
176
+ end
177
+
178
+ class NilNode < LiteralNode
179
+ def initialize() super(nil) end
180
+ end
181
+
182
+ class NewlineNode < LiteralNode
183
+ def initialize() super("\n") end
184
+ end
185
+
186
+ class ExLiteralNode < LiteralNode
187
+ def initialize(*)
188
+ super
189
+ self.force_newline = true
190
+ end
191
+ end
192
+
193
+ class FinishNode < KeywordNode
194
+ def initialize() super("finish\n") end
195
+ end
196
+
197
+ class BreakNode < KeywordNode
198
+ def initialize() super("break\n") end
199
+ end
200
+
201
+ class ContinueNode < KeywordNode
202
+ def initialize() super("continue\n") end
203
+ end
204
+
205
+
206
+ class ReturnNode < Struct.new(:expression)
207
+ include Visitable
208
+ include Walkable
209
+
210
+ def children
211
+ [expression]
212
+ end
213
+ end
214
+
215
+ module FullyNameable
216
+ def self.included(base)
217
+ base.class_eval do
218
+ raise "#{base} must define method 'name'" unless method_defined?(:name)
219
+ end
220
+ end
221
+
222
+ def full_name
223
+ if respond_to?(:scope_modifier)
224
+ "#{scope_modifier}#{name}"
225
+ elsif respond_to?(:prefix)
226
+ "#{prefix}#{name}"
227
+ end
228
+ end
229
+ end
230
+
231
+ # Node of a method call, can take any of these forms:
232
+ #
233
+ # Method()
234
+ # s:Method(argument1, argument2)
235
+ class CallNode < Struct.new(:scope_modifier, :name, :arguments)
236
+ include Riml::Constants
237
+ include Visitable
238
+ include FullyNameable
239
+ include Walkable
240
+
241
+ def builtin_function?
242
+ return false unless name.is_a?(String)
243
+ scope_modifier.nil? and (BUILTIN_FUNCTIONS + BUILTIN_COMMANDS).include?(name)
244
+ end
245
+
246
+ def builtin_command?
247
+ return false unless name.is_a?(String)
248
+ scope_modifier.nil? and BUILTIN_COMMANDS.include?(name)
249
+ end
250
+ alias no_parens_necessary? builtin_command?
251
+
252
+ def must_be_explicit_call?
253
+ return false if builtin_command?
254
+ return true if parent.nil?
255
+ return true if Nodes === parent
256
+ false
257
+ end
258
+
259
+ def children
260
+ if name.is_a?(String)
261
+ arguments
262
+ else
263
+ [name] + arguments
264
+ end
265
+ end
266
+ end
267
+
268
+ # Node of an explicitly called method, can take any of these forms:
269
+ #
270
+ # call Method()
271
+ # call s:Method(argument1, argument2)
272
+ class ExplicitCallNode < CallNode; end
273
+
274
+ class OperatorNode < Struct.new(:operator, :operands)
275
+ include Visitable
276
+ include Walkable
277
+
278
+ def children
279
+ operands
280
+ end
281
+ end
282
+
283
+ class BinaryOperatorNode < OperatorNode
284
+ include Riml::Constants
285
+
286
+ def operand1() operands[0] end
287
+ def operand1=(val) operands[0] = val end
288
+
289
+ def operand2() operands[1] end
290
+ def operand2=(val) operands[1] = val end
291
+
292
+ def ignorecase_capable_operator?(operator)
293
+ IGNORECASE_CAPABLE_OPERATORS.include?(operator)
294
+ end
295
+ end
296
+
297
+ class UnaryOperatorNode < OperatorNode
298
+ alias operand operands
299
+ end
300
+
301
+ # operator = :ternary
302
+ # operands = [condition, if_expr, else_expr]
303
+ class TernaryOperatorNode < OperatorNode
304
+ def initialize(operands, operator=:ternary)
305
+ super(operator, operands)
306
+ end
307
+
308
+ def condition() operands[0] end
309
+
310
+ def if_expr() operands[1] end
311
+
312
+ def else_expr() operands[2] end
313
+ end
314
+
315
+ # let var = 2
316
+ # let s:var = 4
317
+ class AssignNode < Struct.new(:operator, :lhs, :rhs)
318
+ include Visitable
319
+ include Walkable
320
+
321
+ def children
322
+ [lhs, rhs]
323
+ end
324
+ end
325
+
326
+ module QuestionVariableExistence
327
+ def self.included(base)
328
+ base.class_eval do
329
+ raise "#{base} must define method 'name'" unless method_defined?(:name)
330
+ alias name_with_question_mark name
331
+ def name_without_question_mark
332
+ if question_existence?
333
+ name_with_question_mark[0...-1]
334
+ else
335
+ name_with_question_mark
336
+ end
337
+ end
338
+ alias name name_without_question_mark
339
+ end
340
+ end
341
+
342
+ def question_existence?
343
+ name_with_question_mark[-1] == ??
344
+ end
345
+ end
346
+
347
+ # s:var
348
+ # var
349
+ class GetVariableNode < Struct.new(:scope_modifier, :name)
350
+ include Visitable
351
+ include FullyNameable
352
+ include QuestionVariableExistence
353
+ end
354
+
355
+ # &autoindent
356
+ # @q
357
+ class GetSpecialVariableNode < Struct.new(:prefix, :name)
358
+ include Visitable
359
+ include FullyNameable
360
+ end
361
+
362
+ class CurlyBracePart < Struct.new(:value)
363
+ def interpolated?
364
+ GetVariableNode === value || GetSpecialVariableNode === value
365
+ end
366
+
367
+ def regular?
368
+ not interpolated?
369
+ end
370
+ end
371
+ class CurlyBraceVariable < Struct.new(:parts)
372
+ def <<(part)
373
+ parts << part
374
+ self
375
+ end
376
+ end
377
+ class GetCurlyBraceNameNode < Struct.new(:scope_modifier, :variable)
378
+ include Visitable
379
+ include Walkable
380
+
381
+ def children
382
+ [variable]
383
+ end
384
+ end
385
+
386
+ class UnletVariableNode < Struct.new(:bang, :variables)
387
+ include Visitable
388
+ include Walkable
389
+
390
+ def <<(variable)
391
+ variables << variable
392
+ self
393
+ end
394
+
395
+ def children
396
+ variables
397
+ end
398
+ end
399
+
400
+ # Method definition.
401
+ class DefNode < Struct.new(:bang, :scope_modifier, :name, :parameters, :keyword, :expressions)
402
+ include Visitable
403
+ include Indentable
404
+ include FullyNameable
405
+ include Walkable
406
+
407
+ def initialize(*args)
408
+ super
409
+ # max number of arguments in viml
410
+ if parameters.size > 20
411
+ raise ArgumentError, "can't have more than 20 parameters for #{full_name}"
412
+ end
413
+ end
414
+
415
+ SPLAT = lambda {|arg| arg == '...' || arg[0] == "*"}
416
+
417
+ # ["arg1", "arg2"}
418
+ def argument_variable_names
419
+ @argument_variable_names ||= parameters.reject(&SPLAT)
420
+ end
421
+
422
+ # returns the splat argument or nil
423
+ def splat
424
+ @splat ||= begin
425
+ parameters.select(&SPLAT).first
426
+ end
427
+ end
428
+
429
+ def keyword
430
+ return super unless name.include?(".")
431
+ "dict"
432
+ end
433
+
434
+ def super_node
435
+ expressions.detect {|n| SuperNode === n}
436
+ end
437
+
438
+ def to_scope
439
+ ScopeNode.new.tap do |scope|
440
+ scope.argument_variable_names += argument_variable_names
441
+ scope.function = self
442
+ end
443
+ end
444
+
445
+ def children
446
+ [expressions]
447
+ end
448
+
449
+ def method_missing(method, *args, &blk)
450
+ if children.respond_to?(method)
451
+ children.send(method, *args &blk)
452
+ else
453
+ super
454
+ end
455
+ end
456
+ end
457
+
458
+ class ScopeNode
459
+ attr_writer :for_node_variable_names, :argument_variable_names
460
+ attr_accessor :function
461
+
462
+ def for_node_variable_names
463
+ @for_node_variable_names ||= Set.new
464
+ end
465
+
466
+ def argument_variable_names
467
+ @argument_variable_names ||= Set.new
468
+ end
469
+
470
+ alias function? function
471
+
472
+ def initialize_copy(source)
473
+ super
474
+ self.for_node_variable_names = for_node_variable_names.dup
475
+ self.argument_variable_names = argument_variable_names.dup
476
+ self.function = source.function
477
+ end
478
+
479
+ def merge(other)
480
+ dup.merge! other
481
+ end
482
+
483
+ def merge!(other)
484
+ unless other.is_a?(ScopeNode)
485
+ raise ArgumentError, "other must be ScopeNode, is #{other.class}"
486
+ end
487
+ self.for_node_variable_names += other.for_node_variable_names
488
+ self.argument_variable_names -= for_node_variable_names
489
+ self.function = other.function if function.nil? && other.function
490
+ self
491
+ end
492
+ end
493
+
494
+ class DefMethodNode < DefNode
495
+ def to_def_node
496
+ DefNode.new(bang, scope_modifier, name, parameters, keyword, expressions)
497
+ end
498
+ end
499
+
500
+ # abstract control structure
501
+ class ControlStructure < Struct.new(:condition, :body)
502
+ include Visitable
503
+ include Indentable
504
+ include Walkable
505
+
506
+ def children
507
+ [condition, body]
508
+ end
509
+ end
510
+
511
+ class IfNode < ControlStructure; end
512
+ class UnlessNode < ControlStructure; end
513
+
514
+ class WhileNode < ControlStructure; end
515
+ class UntilNode < ControlStructure; end
516
+
517
+ class ElseNode < Struct.new(:expressions)
518
+ include Visitable
519
+ include Walkable
520
+ alias body expressions
521
+
522
+ def <<(expr)
523
+ expressions << expr
524
+ self
525
+ end
526
+
527
+ def pop
528
+ expressions.pop
529
+ end
530
+
531
+ def last
532
+ expressions.last
533
+ end
534
+
535
+ def children
536
+ [expressions]
537
+ end
538
+ end
539
+
540
+ class ElseifNode < ControlStructure
541
+ include Visitable
542
+ include Walkable
543
+ alias expressions body
544
+
545
+ def <<(expr)
546
+ expressions << expr
547
+ self
548
+ end
549
+
550
+ def pop
551
+ expressions.pop
552
+ end
553
+
554
+ def last
555
+ expressions.last
556
+ end
557
+
558
+ def children
559
+ [expressions]
560
+ end
561
+ end
562
+
563
+ # for variable in someFunction(1,2,3)
564
+ # echo variable
565
+ # end
566
+ #
567
+ # OR
568
+ #
569
+ # for variable in [1,2,3]
570
+ # echo variable
571
+ # end
572
+ class ForNode < Struct.new(:variable, :in_expression, :expressions)
573
+ include Visitable
574
+ include Indentable
575
+ include Walkable
576
+
577
+ alias for_variable variable
578
+
579
+ def variables
580
+ variable if ListNode === variable
581
+ end
582
+
583
+ def for_node_variable_names
584
+ if ListNode === variable
585
+ variable.value.map(&:name)
586
+ else
587
+ [variable]
588
+ end
589
+ end
590
+
591
+ def to_scope
592
+ ScopeNode.new.tap {|s| s.for_node_variable_names += for_node_variable_names}
593
+ end
594
+
595
+ def children
596
+ [variable, in_expression, expressions]
597
+ end
598
+ end
599
+
600
+ # lines: [5, 6, 8, 9]
601
+ # This means the continuation has 4 lines (line.size is 4) and each line
602
+ # preserves the amt of whitespace specified as the value in the array.
603
+ # Ex: 1st line preserves 5 spaces, 2nd line preserves 6 spaces, etc...
604
+ class LineContinuation < Struct.new(:lines)
605
+ include Visitable
606
+
607
+ def size
608
+ lines.size
609
+ end
610
+
611
+ def [](idx)
612
+ lines[idx]
613
+ end
614
+ end
615
+
616
+ class DictGetNode < Struct.new(:dict, :keys)
617
+ include Visitable
618
+ include Walkable
619
+
620
+ def children
621
+ [dict] + keys
622
+ end
623
+ end
624
+
625
+ # dict['key']
626
+ # dict['key1']['key2']
627
+ class DictGetBracketNode < DictGetNode; end
628
+
629
+ # dict.key
630
+ # dict.key.key2
631
+ class DictGetDotNode < DictGetNode; end
632
+
633
+
634
+ # list_or_dict[0]
635
+ # function()[identifier]
636
+ class ListOrDictGetNode < Struct.new(:list_or_dict, :keys)
637
+ include Visitable
638
+ include Walkable
639
+
640
+ alias list list_or_dict
641
+ alias dict list_or_dict
642
+ def children
643
+ [list_or_dict] + keys
644
+ end
645
+ end
646
+
647
+ class TryNode < Struct.new(:try_block, :catch_nodes, :ensure_block)
648
+ include Visitable
649
+ include Indentable
650
+ include Walkable
651
+
652
+ def children
653
+ [try_block, catch_nodes, ensure_block]
654
+ end
655
+ end
656
+
657
+ class CatchNode < Struct.new(:regexp, :expressions)
658
+ include Visitable
659
+ include Walkable
660
+
661
+ def children
662
+ [expressions]
663
+ end
664
+ end
665
+
666
+ class HeredocNode < Struct.new(:pattern, :string_node)
667
+ include Visitable
668
+ include Walkable
669
+
670
+ def children
671
+ [string_node]
672
+ end
673
+ end
674
+
675
+ class ClassDefinitionNode < Struct.new(:name, :superclass_name, :expressions)
676
+ include Visitable
677
+ include Walkable
678
+
679
+ def superclass?
680
+ not superclass_name.nil?
681
+ end
682
+
683
+ def constructor
684
+ expressions.detect do |n|
685
+ DefNode === n && (n.name == 'initialize' || n.name.match(/Constructor\Z/))
686
+ end
687
+ end
688
+ alias constructor? constructor
689
+
690
+ def constructor_name
691
+ "#{name}Constructor"
692
+ end
693
+
694
+ def constructor_obj_name
695
+ name[0].downcase + name[1..-1] + "Obj"
696
+ end
697
+
698
+ def children
699
+ [expressions]
700
+ end
701
+ end
702
+
703
+ class SuperNode < Struct.new(:arguments, :with_parens)
704
+ include Visitable
705
+ include Walkable
706
+
707
+ def use_all_arguments?
708
+ arguments.empty? && !with_parens
709
+ end
710
+
711
+ def children
712
+ arguments
713
+ end
714
+ end
715
+
716
+ class ObjectInstantiationNode < Struct.new(:call_node)
717
+ include Visitable
718
+ include Walkable
719
+
720
+ def children
721
+ [call_node]
722
+ end
723
+ end