riml 0.3.9 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/lib/riml/ast_rewriter.rb +99 -171
- data/lib/riml/compiler.rb +3 -10
- data/lib/riml/constants.rb +0 -1
- data/lib/riml/lexer.rb +2 -2
- data/lib/riml/nodes.rb +24 -125
- data/lib/riml/walkable.rb +97 -0
- data/version.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
YzcxODgxN2I3YzM3MjdlZjdhMDM1Y2E4NzhmZmM1ZjM3YWQ1ZjQ0YQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NjcxN2EzNDgyZTVjODZkZjE3MGIyZTk2MmQwMzI1NDRhNmViZjI0NA==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
YTU5N2JjMjdkODhhZjBkOTlkNmMwYjdkMTg5ZmUxZTIwNzAyNTZhYmMwMGZl
|
10
|
+
ZWE3MmI1ODI3Nzk3OTliOTcwZWZiOTcwMzkwY2I2OTUyZDQwZWNjYmI1ZmQy
|
11
|
+
NDVjYTIzNjdlNWQzNzk5YjBiOGMwZWY4NDBkNmZlZGE1MmU1ZDQ=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
NjhmMTc0MjIzMDMzNmU2ZDIyMWIyZTZlYWZkNWZmNDNkMzVhMzYzYWE4NWQ0
|
14
|
+
YjU5NDI2ZTQ5MmJhYmJjODE1ZDg0ZjFiMTg1MDllNWE3NDJjNjQwZjBlZDhj
|
15
|
+
YzQ4ODgyNTA5Y2JjNWFhZmVhNmIyZWZjMzVlODIxMGFhY2ZmOTI=
|
data/lib/riml/ast_rewriter.rb
CHANGED
@@ -63,7 +63,7 @@ module Riml
|
|
63
63
|
DefaultParamToIfNode.new(ast, classes),
|
64
64
|
DeserializeVarAssignment.new(ast, classes),
|
65
65
|
TopLevelDefMethodToDef.new(ast, classes),
|
66
|
-
|
66
|
+
SplatsToCallFunctionInCallingContext.new(ast, classes)
|
67
67
|
]
|
68
68
|
rewriters.each do |rewriter|
|
69
69
|
rewriter.rewrite_on_match
|
@@ -414,10 +414,11 @@ module Riml
|
|
414
414
|
|
415
415
|
InitializeSuperToObjectExtension.new(constructor, classes, node).rewrite_on_match
|
416
416
|
ExtendObjectWithMethods.new(node, classes).rewrite_on_match
|
417
|
-
|
417
|
+
SelfToDictNameInAssignments.new(dict_name).rewrite_on_match(constructor)
|
418
418
|
SuperToSuperclassFunction.new(node, classes).rewrite_on_match
|
419
419
|
PrivateFunctionCallToPassObjExplicitly.new(node, classes).rewrite_on_match
|
420
|
-
|
420
|
+
SplatsToCallFunctionInCallingContext.new(node, classes).rewrite_on_match
|
421
|
+
SelfToDictName.new(dict_name).rewrite_on_match(constructor)
|
421
422
|
|
422
423
|
constructor.expressions.nodes.push(
|
423
424
|
ReturnNode.new(GetVariableNode.new(nil, dict_name))
|
@@ -495,8 +496,11 @@ module Riml
|
|
495
496
|
|
496
497
|
class PrivateFunctionCallToPassObjExplicitly < AST_Rewriter
|
497
498
|
def match?(node)
|
498
|
-
CallNode === node &&
|
499
|
-
node.name.dict.
|
499
|
+
CallNode === node && node.name.instance_of?(DictGetDotNode) &&
|
500
|
+
!node.name.dict.is_a?(ListOrDictGetNode) &&
|
501
|
+
node.name.dict.scope_modifier.nil? &&
|
502
|
+
node.name.dict.name == 'self' &&
|
503
|
+
(node.name.keys & ast.private_function_names).size == 1
|
500
504
|
end
|
501
505
|
|
502
506
|
def replace(node)
|
@@ -575,7 +579,12 @@ module Riml
|
|
575
579
|
end
|
576
580
|
end
|
577
581
|
|
578
|
-
|
582
|
+
# if inside 'Foo' class,
|
583
|
+
# transforms:
|
584
|
+
# self.something = 1
|
585
|
+
# to:
|
586
|
+
# fooObj.something = 1
|
587
|
+
class SelfToDictNameInAssignments < AST_Rewriter
|
579
588
|
attr_reader :dict_name
|
580
589
|
def initialize(dict_name)
|
581
590
|
@dict_name = dict_name
|
@@ -586,7 +595,27 @@ module Riml
|
|
586
595
|
end
|
587
596
|
|
588
597
|
def replace(node)
|
589
|
-
node.lhs.dict.name = dict_name
|
598
|
+
node.lhs.dict.name = @dict_name
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
602
|
+
# if inside 'Foo' class,
|
603
|
+
# transforms:
|
604
|
+
# extend(self, {})
|
605
|
+
# to:
|
606
|
+
# extend(fooObj, {})
|
607
|
+
class SelfToDictName < AST_Rewriter
|
608
|
+
attr_reader :dict_name
|
609
|
+
def initialize(dict_name)
|
610
|
+
@dict_name = dict_name
|
611
|
+
end
|
612
|
+
|
613
|
+
def match?(node)
|
614
|
+
GetVariableNode === node && node.name == "self" && node.scope_modifier.nil?
|
615
|
+
end
|
616
|
+
|
617
|
+
def replace(node)
|
618
|
+
node.name = @dict_name
|
590
619
|
end
|
591
620
|
end
|
592
621
|
|
@@ -726,20 +755,11 @@ module Riml
|
|
726
755
|
# parameter to the function we're in) to the splat arg
|
727
756
|
if @function_node.private_function?
|
728
757
|
if (splat_node = node_args.detect { |arg| SplatNode === arg })
|
729
|
-
|
730
|
-
|
731
|
-
'+',
|
732
|
-
[
|
733
|
-
ListNode.new([
|
734
|
-
GetVariableNode.new('a:', @function_node.parameters.first)
|
735
|
-
]),
|
736
|
-
GetVariableNode.new('a:', '000')
|
737
|
-
]
|
738
|
-
)
|
739
|
-
)
|
758
|
+
self_var = GetVariableNode.new('a:', @function_node.parameters.first)
|
759
|
+
splat_node.expression = BinaryOperatorNode.new('+', [ListNode.wrap(self_var), splat_node.expression])
|
740
760
|
establish_parents(splat_node.expression)
|
741
761
|
end
|
742
|
-
# call s
|
762
|
+
# call s:ClassA_private_func(args)
|
743
763
|
call_node_name = superclass_func_name(superclass)
|
744
764
|
else
|
745
765
|
# call self.ClassA_public_func(args)
|
@@ -754,6 +774,7 @@ module Riml
|
|
754
774
|
node_args
|
755
775
|
)
|
756
776
|
|
777
|
+
call_node.super_call = true
|
757
778
|
node.replace_with(call_node)
|
758
779
|
# private functions are NOT extended in constructor function
|
759
780
|
unless @function_node.private_function?
|
@@ -803,164 +824,39 @@ module Riml
|
|
803
824
|
#
|
804
825
|
# to:
|
805
826
|
#
|
806
|
-
# let
|
807
|
-
# let __riml_splat_size = len(__riml_splat_list)
|
808
|
-
# let __riml_splat_str_vars = []
|
809
|
-
# let __riml_splat_idx = 1
|
810
|
-
# while __riml_splat_idx <=# __riml_splat_size
|
811
|
-
# let __riml_splat_var_{__riml_splat_idx} = get(__riml_splat_list, __riml_splat_idx - 1)
|
812
|
-
# call add(__riml_splat_str_vars, __riml_splat_var_{__riml_splat_idx})
|
813
|
-
# let __riml_splat_idx += 1
|
814
|
-
# endwhile
|
815
|
-
# execute 'let s:animalObj = s:AnimalConstructor(' . join(__riml_splat_str_vars, ', ') . ')'
|
827
|
+
# let animalObj = call('s:AnimalConstructor', a:000)
|
816
828
|
#
|
817
829
|
# Basically, mimic Ruby's approach to expanding lists to their
|
818
830
|
# constituent argument parts with '*' in calling context.
|
819
|
-
class
|
831
|
+
class SplatsToCallFunctionInCallingContext < AST_Rewriter
|
820
832
|
|
821
833
|
def match?(node)
|
822
|
-
|
823
|
-
@splat_node = node
|
824
|
-
end
|
834
|
+
SplatNode === node && CallNode === node.parent
|
825
835
|
end
|
826
836
|
|
827
837
|
def replace(node)
|
828
|
-
construct_splat_str_vars_node = build_construct_splat_str_vars_node
|
829
|
-
call_node_args =
|
830
|
-
CallNode.new(
|
831
|
-
nil,
|
832
|
-
'join',
|
833
|
-
[
|
834
|
-
GetVariableNode.new(tmp_var_modifier.dup, '__riml_splat_str_vars'),
|
835
|
-
StringNode.new(', ', :s)
|
836
|
-
]
|
837
|
-
)
|
838
838
|
call_node = node.parent
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
end
|
845
|
-
# This is necessary because this node is getting put into a new
|
846
|
-
# compiler where it not wrapped in a function context, therefore
|
847
|
-
# variables will be script-local there unless their scope_modifier
|
848
|
-
# is set
|
849
|
-
if n && assign_node.lhs.scope_modifier.nil?
|
850
|
-
if global_scope?
|
851
|
-
assign_node.lhs.scope_modifier = 's:'
|
852
|
-
else
|
853
|
-
assign_node.lhs.scope_modifier = 'l:'
|
854
|
-
end
|
855
|
-
end
|
856
|
-
assign_node
|
857
|
-
else
|
858
|
-
call_node
|
859
|
-
end
|
860
|
-
call_node.arguments.clear
|
861
|
-
compiler = Compiler.new
|
862
|
-
# have to dup node_to_execute here because, if not, its parent will
|
863
|
-
# get reset during this next compilation step
|
864
|
-
output = compiler.compile(Nodes.new([node_to_execute.clone]))
|
865
|
-
execute_string_node = StringNode.new(output.chomp[0..-2], :s)
|
866
|
-
if node_to_execute.instance_of?(CallNode)
|
867
|
-
execute_string_node.value.insert(0, 'call ')
|
868
|
-
end
|
869
|
-
execute_arg = BinaryOperatorNode.new(
|
870
|
-
'.',
|
871
|
-
[
|
872
|
-
execute_string_node,
|
873
|
-
BinaryOperatorNode.new(
|
874
|
-
'.',
|
875
|
-
[
|
876
|
-
call_node_args,
|
877
|
-
StringNode.new(')', :s)
|
878
|
-
]
|
879
|
-
)
|
880
|
-
]
|
881
|
-
)
|
882
|
-
execute_node = CallNode.new(nil, 'execute', [execute_arg])
|
883
|
-
establish_parents(execute_node)
|
884
|
-
node.remove
|
885
|
-
node_to_execute.replace_with(construct_splat_str_vars_node)
|
886
|
-
execute_node.parent = construct_splat_str_vars_node.parent
|
887
|
-
construct_splat_str_vars_node.parent.insert_after(construct_splat_str_vars_node, execute_node)
|
888
|
-
end
|
889
|
-
|
890
|
-
private
|
891
|
-
|
892
|
-
def build_construct_splat_str_vars_node
|
893
|
-
nodes = Nodes.new([])
|
894
|
-
splat_list_init = AssignNode.new(
|
895
|
-
'=',
|
896
|
-
GetVariableNode.new(tmp_var_modifier.dup, '__riml_splat_list'),
|
897
|
-
@splat_node.expression
|
898
|
-
)
|
899
|
-
splat_size = AssignNode.new(
|
900
|
-
'=',
|
901
|
-
GetVariableNode.new(tmp_var_modifier.dup, '__riml_splat_size'),
|
902
|
-
CallNode.new(nil, 'len', [GetVariableNode.new(tmp_var_modifier.dup, '__riml_splat_list')])
|
903
|
-
)
|
904
|
-
splat_string_vars_init = AssignNode.new(
|
905
|
-
'=',
|
906
|
-
GetVariableNode.new(tmp_var_modifier.dup, '__riml_splat_str_vars'),
|
907
|
-
ListNode.new([])
|
908
|
-
)
|
909
|
-
splat_list_idx_init = AssignNode.new(
|
910
|
-
'=',
|
911
|
-
GetVariableNode.new(tmp_var_modifier.dup, '__riml_splat_idx'),
|
912
|
-
NumberNode.new('1')
|
913
|
-
)
|
914
|
-
while_loop = WhileNode.new(
|
915
|
-
# condition
|
916
|
-
BinaryOperatorNode.new('<=', [GetVariableNode.new(tmp_var_modifier.dup, '__riml_splat_idx'), GetVariableNode.new(tmp_var_modifier.dup, '__riml_splat_size')]),
|
917
|
-
# body
|
918
|
-
Nodes.new([
|
919
|
-
AssignNode.new(
|
920
|
-
'=',
|
921
|
-
GetCurlyBraceNameNode.new(tmp_var_modifier.dup, CurlyBraceVariable.new([CurlyBracePart.new('__riml_splat_var_'), CurlyBraceVariable.new([CurlyBracePart.new(GetVariableNode.new(tmp_var_modifier.dup, '__riml_splat_idx'))])])),
|
922
|
-
CallNode.new(nil, 'get', [
|
923
|
-
GetVariableNode.new(tmp_var_modifier.dup, '__riml_splat_list'),
|
924
|
-
BinaryOperatorNode.new('-', [
|
925
|
-
GetVariableNode.new(tmp_var_modifier.dup, '__riml_splat_idx'),
|
926
|
-
NumberNode.new('1')
|
927
|
-
])
|
928
|
-
])
|
929
|
-
),
|
930
|
-
ExplicitCallNode.new(nil, 'add', [
|
931
|
-
GetVariableNode.new(tmp_var_modifier.dup, '__riml_splat_str_vars'),
|
932
|
-
BinaryOperatorNode.new('.', [StringNode.new('__riml_splat_var_', :s), GetVariableNode.new(tmp_var_modifier.dup, '__riml_splat_idx')])
|
839
|
+
is_method_call = call_node.method_call?
|
840
|
+
function_name_expr = if is_method_call && call_node.super_call?
|
841
|
+
BinaryOperatorNode.new('.', [
|
842
|
+
BinaryOperatorNode.new('.', [
|
843
|
+
StringNode.new('<SNR>', :s), CallNode.new('s:', 'SID', [])
|
933
844
|
]),
|
934
|
-
|
845
|
+
StringNode.new("_s:#{call_node.name.keys.last}", :s)
|
935
846
|
])
|
936
|
-
|
937
|
-
|
938
|
-
|
939
|
-
establish_parents(nodes)
|
940
|
-
nodes
|
941
|
-
end
|
942
|
-
|
943
|
-
def tmp_var_modifier
|
944
|
-
@tmp_var_modifier ||= begin
|
945
|
-
n = @splat_node
|
946
|
-
while n != nil && !(DefNode === n)
|
947
|
-
n = n.parent
|
948
|
-
end
|
949
|
-
# n is either `nil` or DefNode
|
950
|
-
if n.nil?
|
951
|
-
's:'
|
952
|
-
else
|
953
|
-
'n:'
|
954
|
-
end
|
847
|
+
else
|
848
|
+
call_node.scope_modifier = 's:' if call_node.scope_modifier.nil?
|
849
|
+
StringNode.new(call_node.full_name, :s)
|
955
850
|
end
|
956
|
-
|
957
|
-
|
958
|
-
|
959
|
-
|
960
|
-
|
961
|
-
|
962
|
-
|
963
|
-
|
851
|
+
call_node.scope_modifier = ''
|
852
|
+
call_node.name = 'call'
|
853
|
+
call_node.arguments = []
|
854
|
+
call_node.arguments << function_name_expr
|
855
|
+
call_node.arguments << node.expression
|
856
|
+
if is_method_call
|
857
|
+
call_node.arguments << GetVariableNode.new(nil, 'self')
|
858
|
+
end
|
859
|
+
reestablish_parents(call_node)
|
964
860
|
end
|
965
861
|
end
|
966
862
|
|
@@ -978,6 +874,13 @@ module Riml
|
|
978
874
|
call_node = node.call_node
|
979
875
|
call_node.name = class_node.constructor_name
|
980
876
|
call_node.scope_modifier = class_node.constructor.scope_modifier
|
877
|
+
# FIXME: `replace_with` doesn't take into account this scenario!
|
878
|
+
if CallNode === node.parent && node.parent.arguments.include?(node)
|
879
|
+
idx = node.parent.arguments.index(node)
|
880
|
+
node.parent.arguments[idx] = call_node
|
881
|
+
else
|
882
|
+
node.replace_with(call_node)
|
883
|
+
end
|
981
884
|
end
|
982
885
|
end
|
983
886
|
|
@@ -1015,19 +918,26 @@ module Riml
|
|
1015
918
|
end
|
1016
919
|
|
1017
920
|
if_expression = construct_if_expression(node)
|
921
|
+
if insert_idx.zero?
|
922
|
+
def_node.expressions.nodes.unshift(construct_copy_splat_var_assignment)
|
923
|
+
SplatVarToCopiedSplatVar.new(def_node, classes).rewrite_on_match
|
924
|
+
end
|
1018
925
|
|
1019
926
|
if last_default_param == node
|
1020
927
|
def_node.parameters.delete_if(&DefNode::DEFAULT_PARAMS)
|
1021
928
|
def_node.parameters << SPLAT_LITERAL unless def_node.splat
|
1022
929
|
end
|
1023
|
-
def_node.expressions.nodes.insert(insert_idx, if_expression)
|
930
|
+
def_node.expressions.nodes.insert(insert_idx + 1, if_expression)
|
1024
931
|
reestablish_parents(def_node)
|
1025
932
|
end
|
1026
933
|
|
934
|
+
private
|
935
|
+
|
1027
936
|
def construct_if_expression(node)
|
1028
|
-
|
1029
|
-
|
1030
|
-
|
937
|
+
condition_node = UnaryOperatorNode.new('!', [
|
938
|
+
CallNode.new(nil, 'empty', [ GetVariableNode.new('', '__splat_var_cpy') ])
|
939
|
+
])
|
940
|
+
remove_from_splat_node = CallNode.new(nil, 'remove', [ GetVariableNode.new('', '__splat_var_cpy'), NumberNode.new(0) ])
|
1031
941
|
IfNode.new(condition_node,
|
1032
942
|
Nodes.new([
|
1033
943
|
AssignNode.new('=', GetVariableNode.new(nil, node.parameter), remove_from_splat_node),
|
@@ -1038,9 +948,27 @@ module Riml
|
|
1038
948
|
)
|
1039
949
|
end
|
1040
950
|
|
1041
|
-
def
|
1042
|
-
|
951
|
+
def construct_copy_splat_var_assignment
|
952
|
+
AssignNode.new('=', GetVariableNode.new('', '__splat_var_cpy'), CallNode.new('', 'copy', [GetVariableNode.new('a:', '000')]))
|
1043
953
|
end
|
954
|
+
|
955
|
+
# rewrites a:000 or args (if function used *args parameter name) to:
|
956
|
+
# __splat_var_cpy
|
957
|
+
class SplatVarToCopiedSplatVar < AST_Rewriter
|
958
|
+
def initialize(def_node, classes)
|
959
|
+
super(def_node, classes)
|
960
|
+
end
|
961
|
+
|
962
|
+
def match?(node)
|
963
|
+
GetVariableNode === node &&
|
964
|
+
( (node.name == '000' && node.scope_modifier.nil?) || ast.is_splat_arg?(node) )
|
965
|
+
end
|
966
|
+
|
967
|
+
def replace(node)
|
968
|
+
node.name = '__splat_var_cpy'
|
969
|
+
end
|
970
|
+
end
|
971
|
+
|
1044
972
|
end
|
1045
973
|
|
1046
974
|
class DeserializeVarAssignment < AST_Rewriter
|
data/lib/riml/compiler.rb
CHANGED
@@ -46,9 +46,10 @@ module Riml
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def visitor_for_node(node, params={})
|
49
|
-
|
49
|
+
class_name = "#{node.class.name.split('::').last}Visitor"
|
50
|
+
Compiler.const_get(class_name).new(params)
|
50
51
|
rescue NameError
|
51
|
-
error = CompileError.new(
|
52
|
+
error = CompileError.new("unexpected construct: #{class_name}", node)
|
52
53
|
raise error
|
53
54
|
end
|
54
55
|
|
@@ -756,14 +757,6 @@ module Riml
|
|
756
757
|
end
|
757
758
|
end
|
758
759
|
|
759
|
-
class ObjectInstantiationNodeVisitor < Visitor
|
760
|
-
def compile(node)
|
761
|
-
node.call_node.parent_node = node
|
762
|
-
node.call_node.accept(visitor_for_node(node.call_node))
|
763
|
-
node.compiled_output
|
764
|
-
end
|
765
|
-
end
|
766
|
-
|
767
760
|
# root node has access to compiler instance in order to append to
|
768
761
|
# the compiler's `compile_queue`. This happens when another file is
|
769
762
|
# sourced using `riml_source`.
|
data/lib/riml/constants.rb
CHANGED
data/lib/riml/lexer.rb
CHANGED
@@ -150,8 +150,8 @@ module Riml
|
|
150
150
|
|
151
151
|
elsif @in_function_declaration && (splat_param = @s.scan(/\A(\.{3}|\*[a-zA-Z_]\w*)/))
|
152
152
|
@token_buf << [:SPLAT_PARAM, splat_param]
|
153
|
-
# splat in calling context. ex: super(*args) or super(*(args + other_args))
|
154
|
-
elsif !@in_function_declaration && prev_token &&
|
153
|
+
# splat in calling context. ex: super(*args) or super(*(args + other_args)) or func('hey', *args)
|
154
|
+
elsif !@in_function_declaration && prev_token && @s.check(/\A\*(\w+|\()/)
|
155
155
|
@token_buf << [:SPLAT_ARG, @s.getch]
|
156
156
|
# integer (octal)
|
157
157
|
elsif octal = @s.scan(/\A0[0-7]+/)
|
data/lib/riml/nodes.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
require File.expand_path('../constants', __FILE__)
|
2
2
|
require File.expand_path('../errors', __FILE__)
|
3
|
+
require File.expand_path('../walkable', __FILE__)
|
3
4
|
require 'set'
|
4
5
|
|
5
6
|
module Riml
|
6
7
|
module Visitable
|
8
|
+
include Walkable
|
9
|
+
|
7
10
|
def accept(visitor)
|
8
11
|
visitor.visit(self)
|
9
12
|
end
|
@@ -17,7 +20,7 @@ module Riml
|
|
17
20
|
@compiled_output ||= ''
|
18
21
|
end
|
19
22
|
|
20
|
-
EMPTY_CHILDREN = []
|
23
|
+
EMPTY_CHILDREN = [].freeze
|
21
24
|
|
22
25
|
def children
|
23
26
|
EMPTY_CHILDREN
|
@@ -40,101 +43,6 @@ module Riml
|
|
40
43
|
end
|
41
44
|
end
|
42
45
|
|
43
|
-
module Walkable
|
44
|
-
include Enumerable
|
45
|
-
|
46
|
-
def each(&block)
|
47
|
-
children.each(&block)
|
48
|
-
end
|
49
|
-
alias walk each
|
50
|
-
|
51
|
-
def previous
|
52
|
-
idx = index_by_member
|
53
|
-
if idx && parent.members[idx - 1]
|
54
|
-
attr = parent.members[idx - 1]
|
55
|
-
return send(attr)
|
56
|
-
else
|
57
|
-
idx = index_by_children
|
58
|
-
return unless idx
|
59
|
-
parent.children.fetch(idx - 1)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def child_previous_to(node)
|
64
|
-
node.previous
|
65
|
-
end
|
66
|
-
|
67
|
-
def insert_before(node, new_node)
|
68
|
-
idx = children.find_index(node)
|
69
|
-
return unless idx
|
70
|
-
children.insert(idx - 1, new_node)
|
71
|
-
end
|
72
|
-
|
73
|
-
def next
|
74
|
-
idx = index_by_member
|
75
|
-
if idx && parent.members[idx + 1]
|
76
|
-
attr = parent.members[idx + 1]
|
77
|
-
return parent.send(attr)
|
78
|
-
else
|
79
|
-
idx = index_by_children
|
80
|
-
return unless idx
|
81
|
-
parent.children.fetch(idx + 1)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
def child_after(node)
|
86
|
-
node.next
|
87
|
-
end
|
88
|
-
|
89
|
-
def insert_after(node, new_node)
|
90
|
-
idx = children.find_index(node)
|
91
|
-
return unless idx
|
92
|
-
children.insert(idx + 1, new_node)
|
93
|
-
end
|
94
|
-
|
95
|
-
def index_by_member
|
96
|
-
attrs = parent.members
|
97
|
-
attrs.each_with_index do |attr, i|
|
98
|
-
if parent.send(attr) == self
|
99
|
-
return i
|
100
|
-
end
|
101
|
-
end
|
102
|
-
nil
|
103
|
-
end
|
104
|
-
|
105
|
-
def index_by_children
|
106
|
-
parent.children.find_index(self)
|
107
|
-
end
|
108
|
-
|
109
|
-
def remove
|
110
|
-
idx = index_by_member
|
111
|
-
if idx
|
112
|
-
attr = parent.members[idx]
|
113
|
-
parent.send("#{attr}=", nil)
|
114
|
-
else
|
115
|
-
idx = index_by_children
|
116
|
-
parent.children.slice!(idx) if idx
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
def replace_with(new_node)
|
121
|
-
idx = index_by_member
|
122
|
-
if idx
|
123
|
-
attr = parent.members[idx]
|
124
|
-
new_node.parent = parent
|
125
|
-
parent.send("#{attr}=", new_node)
|
126
|
-
new_node
|
127
|
-
else
|
128
|
-
idx = index_by_children
|
129
|
-
return unless idx
|
130
|
-
new_node.parent = parent
|
131
|
-
parent.children.insert(idx, new_node)
|
132
|
-
parent.children.slice!(idx + 1)
|
133
|
-
new_node
|
134
|
-
end
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
46
|
module Indentable
|
139
47
|
def indent
|
140
48
|
@indent ||= ' ' * 2
|
@@ -167,7 +75,6 @@ module Riml
|
|
167
75
|
# Collection of nodes each one representing an expression.
|
168
76
|
class Nodes < Struct.new(:nodes)
|
169
77
|
include Visitable
|
170
|
-
include Walkable
|
171
78
|
|
172
79
|
def <<(node)
|
173
80
|
nodes << node
|
@@ -212,7 +119,6 @@ module Riml
|
|
212
119
|
|
213
120
|
class StringLiteralConcatNode < Struct.new(:string_nodes)
|
214
121
|
include Visitable
|
215
|
-
include Walkable
|
216
122
|
|
217
123
|
def initialize(*string_nodes)
|
218
124
|
super(string_nodes)
|
@@ -227,7 +133,6 @@ module Riml
|
|
227
133
|
class RegexpNode < LiteralNode; end
|
228
134
|
|
229
135
|
class ListNode < LiteralNode
|
230
|
-
include Walkable
|
231
136
|
def self.wrap(value)
|
232
137
|
val = Array === value ? value : [value]
|
233
138
|
new(val)
|
@@ -249,7 +154,6 @@ module Riml
|
|
249
154
|
end
|
250
155
|
|
251
156
|
class DictionaryNode < LiteralNode
|
252
|
-
include Walkable
|
253
157
|
|
254
158
|
def initialize(value)
|
255
159
|
super(value.to_a)
|
@@ -287,7 +191,6 @@ module Riml
|
|
287
191
|
# Ex: `super(*args)`, `super(*a:000)`, `someFunc(*(list + ['item']))`
|
288
192
|
class SplatNode < Struct.new(:expression)
|
289
193
|
include Visitable
|
290
|
-
include Walkable
|
291
194
|
|
292
195
|
def children
|
293
196
|
[expression]
|
@@ -316,7 +219,6 @@ module Riml
|
|
316
219
|
|
317
220
|
class ReturnNode < Struct.new(:expression)
|
318
221
|
include Visitable
|
319
|
-
include Walkable
|
320
222
|
|
321
223
|
def children
|
322
224
|
[expression]
|
@@ -325,7 +227,6 @@ module Riml
|
|
325
227
|
|
326
228
|
class WrapInParensNode < Struct.new(:expression)
|
327
229
|
include Visitable
|
328
|
-
include Walkable
|
329
230
|
|
330
231
|
def force_newline_if_child_call_node?
|
331
232
|
false
|
@@ -360,7 +261,8 @@ module Riml
|
|
360
261
|
include Riml::Constants
|
361
262
|
include Visitable
|
362
263
|
include FullyNameable
|
363
|
-
|
264
|
+
|
265
|
+
attr_accessor :super_call
|
364
266
|
|
365
267
|
ALL_BUILTIN_FUNCTIONS = BUILTIN_FUNCTIONS + BUILTIN_COMMANDS
|
366
268
|
ALL_BUILTIN_COMMANDS = BUILTIN_COMMANDS + RIML_COMMANDS + VIML_COMMANDS
|
@@ -391,6 +293,14 @@ module Riml
|
|
391
293
|
false
|
392
294
|
end
|
393
295
|
|
296
|
+
def method_call?
|
297
|
+
name.instance_of?(DictGetDotNode) &&
|
298
|
+
name.dict.name == 'self' &&
|
299
|
+
name.dict.scope_modifier.nil?
|
300
|
+
end
|
301
|
+
|
302
|
+
alias super_call? super_call
|
303
|
+
|
394
304
|
def autoload?
|
395
305
|
name.include?('#')
|
396
306
|
end
|
@@ -519,7 +429,6 @@ module Riml
|
|
519
429
|
|
520
430
|
class OperatorNode < Struct.new(:operator, :operands)
|
521
431
|
include Visitable
|
522
|
-
include Walkable
|
523
432
|
|
524
433
|
def force_newline_if_child_call_node?
|
525
434
|
false
|
@@ -575,7 +484,6 @@ module Riml
|
|
575
484
|
# let s:var = 4
|
576
485
|
class AssignNode < Struct.new(:operator, :lhs, :rhs)
|
577
486
|
include Visitable
|
578
|
-
include Walkable
|
579
487
|
|
580
488
|
def children
|
581
489
|
[lhs, rhs]
|
@@ -584,7 +492,6 @@ module Riml
|
|
584
492
|
|
585
493
|
class MultiAssignNode < Struct.new(:assigns)
|
586
494
|
include Visitable
|
587
|
-
include Walkable
|
588
495
|
|
589
496
|
def children
|
590
497
|
assigns
|
@@ -618,6 +525,10 @@ module Riml
|
|
618
525
|
include Visitable
|
619
526
|
include FullyNameable
|
620
527
|
include QuestionVariableExistence
|
528
|
+
|
529
|
+
def arguments_variable?
|
530
|
+
scope_modifier == 'a:' && name == '000'
|
531
|
+
end
|
621
532
|
end
|
622
533
|
|
623
534
|
# &autoindent
|
@@ -629,7 +540,6 @@ module Riml
|
|
629
540
|
|
630
541
|
class GetCurlyBraceNameNode < Struct.new(:scope_modifier, :variable)
|
631
542
|
include Visitable
|
632
|
-
include Walkable
|
633
543
|
|
634
544
|
def children
|
635
545
|
[variable]
|
@@ -638,7 +548,6 @@ module Riml
|
|
638
548
|
|
639
549
|
class CurlyBraceVariable < Struct.new(:parts)
|
640
550
|
include Visitable
|
641
|
-
include Walkable
|
642
551
|
|
643
552
|
def <<(part)
|
644
553
|
parts << part
|
@@ -652,7 +561,6 @@ module Riml
|
|
652
561
|
|
653
562
|
class CurlyBracePart < Struct.new(:value)
|
654
563
|
include Visitable
|
655
|
-
include Walkable
|
656
564
|
|
657
565
|
def interpolated?
|
658
566
|
GetVariableNode === value || GetSpecialVariableNode === value ||
|
@@ -680,7 +588,6 @@ module Riml
|
|
680
588
|
|
681
589
|
class UnletVariableNode < Struct.new(:bang, :variables)
|
682
590
|
include Visitable
|
683
|
-
include Walkable
|
684
591
|
|
685
592
|
def <<(variable)
|
686
593
|
variables << variable
|
@@ -697,7 +604,6 @@ module Riml
|
|
697
604
|
include Visitable
|
698
605
|
include Indentable
|
699
606
|
include FullyNameable
|
700
|
-
include Walkable
|
701
607
|
|
702
608
|
attr_accessor :private_function
|
703
609
|
alias private_function? private_function
|
@@ -783,6 +689,12 @@ module Riml
|
|
783
689
|
parameters.select(&DEFAULT_PARAMS)
|
784
690
|
end
|
785
691
|
|
692
|
+
def is_splat_arg?(node)
|
693
|
+
splat = splat()
|
694
|
+
return false unless splat
|
695
|
+
GetVariableNode === node && node.scope_modifier.nil? && node.name == splat[1..-1]
|
696
|
+
end
|
697
|
+
|
786
698
|
def children
|
787
699
|
children = if sid?
|
788
700
|
[sid, expressions]
|
@@ -795,7 +707,6 @@ module Riml
|
|
795
707
|
|
796
708
|
class DefaultParamNode < Struct.new(:parameter, :expression)
|
797
709
|
include Visitable
|
798
|
-
include Walkable
|
799
710
|
|
800
711
|
def children
|
801
712
|
[parameter, expression]
|
@@ -856,7 +767,6 @@ module Riml
|
|
856
767
|
class ControlStructure < Struct.new(:condition, :body)
|
857
768
|
include Visitable
|
858
769
|
include Indentable
|
859
|
-
include Walkable
|
860
770
|
|
861
771
|
def force_newline_if_child_call_node?
|
862
772
|
false
|
@@ -894,7 +804,6 @@ module Riml
|
|
894
804
|
|
895
805
|
class ElseNode < Struct.new(:expressions)
|
896
806
|
include Visitable
|
897
|
-
include Walkable
|
898
807
|
alias body expressions
|
899
808
|
|
900
809
|
def <<(expr)
|
@@ -917,7 +826,6 @@ module Riml
|
|
917
826
|
|
918
827
|
class ElseifNode < ControlStructure
|
919
828
|
include Visitable
|
920
|
-
include Walkable
|
921
829
|
alias expressions body
|
922
830
|
|
923
831
|
def <<(expr)
|
@@ -950,7 +858,6 @@ module Riml
|
|
950
858
|
class ForNode < Struct.new(:variable, :in_expression, :expressions)
|
951
859
|
include Visitable
|
952
860
|
include Indentable
|
953
|
-
include Walkable
|
954
861
|
|
955
862
|
alias for_variable variable
|
956
863
|
|
@@ -981,7 +888,6 @@ module Riml
|
|
981
888
|
|
982
889
|
class DictGetNode < Struct.new(:dict, :keys)
|
983
890
|
include Visitable
|
984
|
-
include Walkable
|
985
891
|
|
986
892
|
def children
|
987
893
|
[dict] + keys
|
@@ -1006,7 +912,6 @@ module Riml
|
|
1006
912
|
# function()[identifier]
|
1007
913
|
class ListOrDictGetNode < Struct.new(:list_or_dict, :keys)
|
1008
914
|
include Visitable
|
1009
|
-
include Walkable
|
1010
915
|
|
1011
916
|
alias list list_or_dict
|
1012
917
|
alias dict list_or_dict
|
@@ -1022,7 +927,6 @@ module Riml
|
|
1022
927
|
|
1023
928
|
class GetVariableByScopeAndDictNameNode < Struct.new(:scope_modifier, :keys)
|
1024
929
|
include Visitable
|
1025
|
-
include Walkable
|
1026
930
|
|
1027
931
|
def children
|
1028
932
|
[scope_modifier] + keys
|
@@ -1032,7 +936,6 @@ module Riml
|
|
1032
936
|
class TryNode < Struct.new(:try_block, :catch_nodes, :finally_block)
|
1033
937
|
include Visitable
|
1034
938
|
include Indentable
|
1035
|
-
include Walkable
|
1036
939
|
|
1037
940
|
def children
|
1038
941
|
[try_block] + catch_nodes.to_a + [finally_block].compact
|
@@ -1041,7 +944,6 @@ module Riml
|
|
1041
944
|
|
1042
945
|
class CatchNode < Struct.new(:regexp, :expressions)
|
1043
946
|
include Visitable
|
1044
|
-
include Walkable
|
1045
947
|
include NotNestedUnder
|
1046
948
|
|
1047
949
|
def children
|
@@ -1052,7 +954,6 @@ module Riml
|
|
1052
954
|
|
1053
955
|
class ClassDefinitionNode < Struct.new(:scope_modifier, :name, :superclass_name, :expressions)
|
1054
956
|
include Visitable
|
1055
|
-
include Walkable
|
1056
957
|
|
1057
958
|
FUNCTIONS = lambda {|expr| DefNode === expr}
|
1058
959
|
DEFAULT_SCOPE_MODIFIER = 's:'
|
@@ -1126,7 +1027,6 @@ module Riml
|
|
1126
1027
|
|
1127
1028
|
class SuperNode < Struct.new(:arguments, :with_parens)
|
1128
1029
|
include Visitable
|
1129
|
-
include Walkable
|
1130
1030
|
|
1131
1031
|
def use_all_arguments?
|
1132
1032
|
arguments.empty? && !with_parens
|
@@ -1139,7 +1039,6 @@ module Riml
|
|
1139
1039
|
|
1140
1040
|
class ObjectInstantiationNode < Struct.new(:call_node)
|
1141
1041
|
include Visitable
|
1142
|
-
include Walkable
|
1143
1042
|
|
1144
1043
|
def force_newline_if_child_call_node?
|
1145
1044
|
false
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Riml
|
2
|
+
module Walkable
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
def each(&block)
|
6
|
+
children.each(&block)
|
7
|
+
end
|
8
|
+
alias walk each
|
9
|
+
|
10
|
+
def previous
|
11
|
+
idx = index_by_member
|
12
|
+
if idx && parent.members[idx - 1]
|
13
|
+
attr = parent.members[idx - 1]
|
14
|
+
return send(attr)
|
15
|
+
else
|
16
|
+
idx = index_by_children
|
17
|
+
return unless idx
|
18
|
+
parent.children.fetch(idx - 1)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def child_previous_to(node)
|
23
|
+
node.previous
|
24
|
+
end
|
25
|
+
|
26
|
+
def insert_before(node, new_node)
|
27
|
+
idx = children.find_index(node)
|
28
|
+
return unless idx
|
29
|
+
children.insert(idx - 1, new_node)
|
30
|
+
end
|
31
|
+
|
32
|
+
def next
|
33
|
+
idx = index_by_member
|
34
|
+
if idx && parent.members[idx + 1]
|
35
|
+
attr = parent.members[idx + 1]
|
36
|
+
return parent.send(attr)
|
37
|
+
else
|
38
|
+
idx = index_by_children
|
39
|
+
return unless idx
|
40
|
+
parent.children.fetch(idx + 1)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def child_after(node)
|
45
|
+
node.next
|
46
|
+
end
|
47
|
+
|
48
|
+
def insert_after(node, new_node)
|
49
|
+
idx = children.find_index(node)
|
50
|
+
return unless idx
|
51
|
+
children.insert(idx + 1, new_node)
|
52
|
+
end
|
53
|
+
|
54
|
+
def index_by_member
|
55
|
+
attrs = parent.members
|
56
|
+
attrs.each_with_index do |attr, i|
|
57
|
+
if parent.send(attr) == self
|
58
|
+
return i
|
59
|
+
end
|
60
|
+
end
|
61
|
+
nil
|
62
|
+
end
|
63
|
+
|
64
|
+
def index_by_children
|
65
|
+
parent.children.find_index(self)
|
66
|
+
end
|
67
|
+
|
68
|
+
def remove
|
69
|
+
idx = index_by_member
|
70
|
+
if idx
|
71
|
+
attr = parent.members[idx]
|
72
|
+
parent.send("#{attr}=", nil)
|
73
|
+
else
|
74
|
+
idx = index_by_children
|
75
|
+
parent.children.slice!(idx) if idx
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def replace_with(new_node)
|
80
|
+
idx = index_by_member
|
81
|
+
if idx
|
82
|
+
attr = parent.members[idx]
|
83
|
+
new_node.parent = parent
|
84
|
+
parent.send("#{attr}=", new_node)
|
85
|
+
new_node
|
86
|
+
else
|
87
|
+
idx = index_by_children
|
88
|
+
return unless idx
|
89
|
+
new_node.parent = parent
|
90
|
+
parent.children.insert(idx, new_node)
|
91
|
+
parent.children.slice!(idx + 1)
|
92
|
+
new_node
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
end
|
data/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: riml
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Luke Gruber
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-02-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: racc
|
@@ -118,6 +118,7 @@ files:
|
|
118
118
|
- lib/riml/path_cache.rb
|
119
119
|
- lib/riml/repl.rb
|
120
120
|
- lib/riml/rewritten_ast_cache.rb
|
121
|
+
- lib/riml/walkable.rb
|
121
122
|
- lib/riml/walker.rb
|
122
123
|
- lib/riml/warning_buffer.rb
|
123
124
|
- version.rb
|