farleyknight-ionize 0.1.0
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.rdoc +59 -0
- data/Rakefile +5 -0
- data/bin/ionize +47 -0
- data/lib/ionize.rb +75 -0
- data/lib/ionize/environment.rb +56 -0
- data/lib/ionize/environment/application.rb +58 -0
- data/lib/ionize/environment/php_array.rb +95 -0
- data/lib/ionize/parser.rb +272 -0
- data/lib/ionize/tokenizer.rb +544 -0
- data/lib/ionize/translate.rb +34 -0
- data/lib/ionize/translate/composite_string_statements.rb +79 -0
- data/lib/ionize/translate/debug.rb +16 -0
- data/lib/ionize/translate/ext.rb +47 -0
- data/lib/ionize/translate/function_args.rb +132 -0
- data/lib/ionize/translate/if_statements.rb +42 -0
- data/lib/ionize/translate/multiple_statements.rb +22 -0
- data/lib/ionize/translate/php_to_ruby.rb +40 -0
- data/lib/ionize/translate/rails_for_php.rb +191 -0
- data/lib/ionize/translate/rewritable.rb +133 -0
- data/lib/ionize/translate/rewrites.rb +51 -0
- data/lib/ionize/translate/statements.rb +622 -0
- data/lib/ionize/translate/switch_case_statements.rb +52 -0
- data/lib/ionize/translate/term_statements.rb +76 -0
- data/lib/ionize/translate/translator.rb +52 -0
- data/lib/ionize/version.rb +9 -0
- data/spec/fixtures/array_lookup.php +10 -0
- data/spec/fixtures/boolean_operators.php +5 -0
- data/spec/fixtures/boolean_operators.rb +6 -0
- data/spec/fixtures/class_def.php +34 -0
- data/spec/fixtures/class_def.rb +34 -0
- data/spec/fixtures/dangling_else.php +8 -0
- data/spec/fixtures/dangling_else.rb +12 -0
- data/spec/fixtures/drupal_1.php +663 -0
- data/spec/fixtures/drupal_2.php +1152 -0
- data/spec/fixtures/empty_string.php +12 -0
- data/spec/fixtures/for_loop.php +17 -0
- data/spec/fixtures/for_loop2.php +13 -0
- data/spec/fixtures/for_loop3.php +16 -0
- data/spec/fixtures/for_loop3.rb +17 -0
- data/spec/fixtures/for_loop4.php +5 -0
- data/spec/fixtures/for_loop4.rb +6 -0
- data/spec/fixtures/foreach.php +9 -0
- data/spec/fixtures/foreach2.php +8 -0
- data/spec/fixtures/foreach3.php +7 -0
- data/spec/fixtures/foreach3.rb +7 -0
- data/spec/fixtures/fun_def.php +9 -0
- data/spec/fixtures/fun_def2.php +30 -0
- data/spec/fixtures/fun_def2.rb +30 -0
- data/spec/fixtures/fun_def3.php +33 -0
- data/spec/fixtures/fun_def4.php +43 -0
- data/spec/fixtures/fun_def4.rb +37 -0
- data/spec/fixtures/fun_def5.php +36 -0
- data/spec/fixtures/fun_with_if.php +6 -0
- data/spec/fixtures/fun_with_if.rb +6 -0
- data/spec/fixtures/fun_with_ifs.php +12 -0
- data/spec/fixtures/fun_with_ifs.rb +14 -0
- data/spec/fixtures/hello_world.php +6 -0
- data/spec/fixtures/heredoc.php +6 -0
- data/spec/fixtures/heredoc.rb +5 -0
- data/spec/fixtures/if.php +6 -0
- data/spec/fixtures/if.rb +7 -0
- data/spec/fixtures/if_boolean.php +5 -0
- data/spec/fixtures/if_boolean.rb +5 -0
- data/spec/fixtures/if_else.php +11 -0
- data/spec/fixtures/if_else1.php +17 -0
- data/spec/fixtures/if_else2.php +8 -0
- data/spec/fixtures/if_else3.php +15 -0
- data/spec/fixtures/if_else_nested.php +14 -0
- data/spec/fixtures/if_else_nested.rb +15 -0
- data/spec/fixtures/if_else_series.php +12 -0
- data/spec/fixtures/if_else_series.rb +12 -0
- data/spec/fixtures/if_not.php +5 -0
- data/spec/fixtures/if_not.rb +5 -0
- data/spec/fixtures/if_with_brackets.php +7 -0
- data/spec/fixtures/if_with_brackets.rb +7 -0
- data/spec/fixtures/long_if_else.php +10 -0
- data/spec/fixtures/long_if_else.rb +9 -0
- data/spec/fixtures/oo.php +16 -0
- data/spec/fixtures/php_nuke/sql_layer.php +527 -0
- data/spec/fixtures/postop.php +3 -0
- data/spec/fixtures/preop.php +7 -0
- data/spec/fixtures/simple_fun_def.php +4 -0
- data/spec/fixtures/switch_case.php +13 -0
- data/spec/fixtures/switch_case.rb +14 -0
- data/spec/fixtures/switch_case2.php +25 -0
- data/spec/fixtures/switch_case3.php +40 -0
- data/spec/fixtures/switch_case3.rb +42 -0
- data/spec/fixtures/switch_case4.php +56 -0
- data/spec/fixtures/switch_case5.php +71 -0
- data/spec/fixtures/switch_case_with_rescue_nil.php +43 -0
- data/spec/fixtures/switch_case_with_rescue_nil.rb +35 -0
- data/spec/fixtures/tertiary.php +3 -0
- data/spec/helper.rb +17 -0
- data/spec/php_environment_spec.rb +83 -0
- data/spec/php_parser_spec.rb +121 -0
- data/spec/php_translator_spec.rb +358 -0
- data/spec/rails_for_php_spec.rb +303 -0
- metadata +191 -0
@@ -0,0 +1,133 @@
|
|
1
|
+
module Ionize
|
2
|
+
module Php
|
3
|
+
module Translate
|
4
|
+
module Rewritable
|
5
|
+
def transform(*args)
|
6
|
+
parent.transform(*args)
|
7
|
+
end
|
8
|
+
|
9
|
+
def rewrite_fcall(name, args)
|
10
|
+
__send__("rewrite_fcall_#{name}", args)
|
11
|
+
end
|
12
|
+
|
13
|
+
def rewrite_lasgn(name, var, expr)
|
14
|
+
__send__("rewrite_lasgn_#{name}", var, expr)
|
15
|
+
end
|
16
|
+
|
17
|
+
def fcall_rewritable?(name)
|
18
|
+
respond_to? "rewrite_fcall_#{name}"
|
19
|
+
end
|
20
|
+
|
21
|
+
def lasgn_rewritable?(name)
|
22
|
+
respond_to? "rewrite_lasgn_#{name}"
|
23
|
+
end
|
24
|
+
|
25
|
+
def handle_regular_fun_call(node)
|
26
|
+
debug "Regular fun call #{node.inspect}"
|
27
|
+
name = parent.transform(node.first).to_sym
|
28
|
+
|
29
|
+
# TODO: Simplify this condition..
|
30
|
+
result = if node.third[:fun_args_within_call] == [{:no_args => []}] or
|
31
|
+
node.third[:fun_args_within_call] == [{:no_args_within_call=>[]}]
|
32
|
+
args = nil
|
33
|
+
[:fcall, name]
|
34
|
+
else
|
35
|
+
args = parent.transform(node.third)
|
36
|
+
[:fcall, name, args]
|
37
|
+
end
|
38
|
+
|
39
|
+
if fcall_rewritable? name
|
40
|
+
rewrite_fcall(name, args)
|
41
|
+
else
|
42
|
+
result
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def handle_term_assign_oo_variable(node)
|
47
|
+
debug "The oo assign node is #{node.inspect}"
|
48
|
+
# TODO: Pretty this up some.. If possible..
|
49
|
+
object = parent.transform(node.first)
|
50
|
+
|
51
|
+
debug "The object to be set is #{object.inspect}"
|
52
|
+
object.shift # discard leading :call
|
53
|
+
|
54
|
+
attribute = object.pop
|
55
|
+
debug "The attribute to be set is #{attribute.inspect}"
|
56
|
+
|
57
|
+
assigned = attribute.to_s + "=" # pop off assigned to var
|
58
|
+
debug "Before transforming, the expression to be set is #{node.third.inspect}"
|
59
|
+
expr = parent.transform(node.third)
|
60
|
+
debug "The expression to be set is #{expr.inspect}"
|
61
|
+
|
62
|
+
# TODO: Move this rewrite to the Rewrites class
|
63
|
+
object = (if object.first == [:lvar, :this] then [:self] else object.first end)
|
64
|
+
|
65
|
+
[:attrasgn, object, assigned.to_id, [:array, expr]]
|
66
|
+
end
|
67
|
+
|
68
|
+
def handle_term_assign_oo_array_lookup(node)
|
69
|
+
debug "Term assign oo array lookup is #{node.inspect}"
|
70
|
+
|
71
|
+
term = transform(node.first)
|
72
|
+
expr = transform(node.third)
|
73
|
+
|
74
|
+
debug "Term is #{term.inspect}"
|
75
|
+
|
76
|
+
[:attrasgn] +
|
77
|
+
[term.second] +
|
78
|
+
[:[]=] +
|
79
|
+
[term.fourth + [expr]]
|
80
|
+
end
|
81
|
+
|
82
|
+
def handle_term_assign_oo_variable_variable(node)
|
83
|
+
debug "Term assign oo variable variable is #{node.inspect}"
|
84
|
+
term = transform(node.first)
|
85
|
+
expr = transform(node.third)
|
86
|
+
debug "Term inside oo variable variable is #{term.inspect}"
|
87
|
+
term[0..1] + [:set] + [term[3] + [expr]]
|
88
|
+
end
|
89
|
+
|
90
|
+
def handle_term_assign_array_lookup(node)
|
91
|
+
term = transform(node.first)
|
92
|
+
expr = transform(node.third)
|
93
|
+
[:attrasgn] + [term[1]] + [:[]=] + [term[3] + [expr]]
|
94
|
+
end
|
95
|
+
|
96
|
+
def handle_term_assign_array_append(node)
|
97
|
+
[:call, transform(node.first), :<<, [:array, transform(node.third)]]
|
98
|
+
end
|
99
|
+
|
100
|
+
def handle_term_assign(node)
|
101
|
+
debug "Term assign node is #{node.inspect}"
|
102
|
+
|
103
|
+
if node.first.node_type == :oo_variable
|
104
|
+
return handle_term_assign_oo_variable(node)
|
105
|
+
elsif node.first.node_type == :oo_array_lookup
|
106
|
+
return handle_term_assign_oo_array_lookup(node)
|
107
|
+
elsif node.first.node_type == :oo_variable_variable
|
108
|
+
return handle_term_assign_oo_variable_variable(node)
|
109
|
+
elsif node.first.node_type == :array_lookup
|
110
|
+
return handle_term_assign_array_lookup(node)
|
111
|
+
elsif node.first.node_type == :array_append
|
112
|
+
return handle_term_assign_array_append(node)
|
113
|
+
end
|
114
|
+
|
115
|
+
term, op, expr = *node
|
116
|
+
var = parent.transform(term).last
|
117
|
+
debug "Term assign #{term.inspect}"
|
118
|
+
|
119
|
+
expr = parent.transform(expr)
|
120
|
+
if expr.is_a? Array
|
121
|
+
if expr.first == :fcall and lasgn_rewritable? expr.second
|
122
|
+
rewrite_lasgn(expr.second, var, expr)
|
123
|
+
else
|
124
|
+
[:lasgn, var, expr]
|
125
|
+
end
|
126
|
+
else
|
127
|
+
[:lasgn, var, [expr]]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
load 'ionize/translate/rewritable.rb'
|
2
|
+
|
3
|
+
module Ionize
|
4
|
+
module Php
|
5
|
+
module Translate
|
6
|
+
class Rewrites < Translator
|
7
|
+
include Debug, Rewritable, RailsForPhp
|
8
|
+
|
9
|
+
def rewrite_lasgn_ereg(var, expr)
|
10
|
+
regex, object, matches = *expr.last.rest
|
11
|
+
|
12
|
+
[:masgn,
|
13
|
+
[:array, [:lasgn, var], [:lasgn, matches.last]],
|
14
|
+
[:to_ary, [:call, object, :match, [:array, [:lit, eval("/" + regex.last + "/")]]]]]
|
15
|
+
end
|
16
|
+
|
17
|
+
def rewrite_lasgn_eregi(var, expr)
|
18
|
+
regex, object, matches = *expr.last.rest
|
19
|
+
|
20
|
+
[:masgn,
|
21
|
+
[:array, [:lasgn, var], [:lasgn, matches.last]],
|
22
|
+
[:to_ary, [:call, object, :match, [:array, [:lit, eval("/" + regex.last + "/i")]]]]]
|
23
|
+
end
|
24
|
+
|
25
|
+
def rewrite_fcall_var_dump(args)
|
26
|
+
[:fcall, :puts, args]
|
27
|
+
end
|
28
|
+
|
29
|
+
def rewrite_fcall_define(args)
|
30
|
+
[:cdecl, args.second.second.to_sym, args.third]
|
31
|
+
end
|
32
|
+
|
33
|
+
def rewrite_fcall_function_exists(args)
|
34
|
+
[:fcall, :respond_to?, args]
|
35
|
+
end
|
36
|
+
|
37
|
+
def rewrite_fcall_isset(args)
|
38
|
+
[:call, args.second, :not_nil?]
|
39
|
+
end
|
40
|
+
|
41
|
+
def rewrite_fcall_array_intersect(args)
|
42
|
+
[:call, args.second, :intersect, [:array, args.third]]
|
43
|
+
end
|
44
|
+
|
45
|
+
def rewrite_fcall_mysql_connect(args)
|
46
|
+
[:call, [:const, :Mysql], :new, args]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,622 @@
|
|
1
|
+
|
2
|
+
load 'ionize/translate/multiple_statements.rb'
|
3
|
+
load 'ionize/translate/if_statements.rb'
|
4
|
+
load 'ionize/translate/switch_case_statements.rb'
|
5
|
+
load 'ionize/translate/term_statements.rb'
|
6
|
+
load 'ionize/translate/composite_string_statements.rb'
|
7
|
+
load 'ionize/translate/rails_for_php.rb'
|
8
|
+
|
9
|
+
Object.class_eval do
|
10
|
+
def to_id
|
11
|
+
if is_a? String
|
12
|
+
to_sym
|
13
|
+
else
|
14
|
+
self
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module Ionize
|
20
|
+
module Php
|
21
|
+
module Translate
|
22
|
+
class Statements < Translator
|
23
|
+
include Debug, IfStatements, MultipleStatements
|
24
|
+
include SwitchCaseStatements, TermStatements
|
25
|
+
include CompositeStringStatements
|
26
|
+
|
27
|
+
attr_writer :globals
|
28
|
+
|
29
|
+
def globals
|
30
|
+
@globals ||= []
|
31
|
+
end
|
32
|
+
|
33
|
+
IdentityTransforms = [
|
34
|
+
"one_variable", "unmatched", "term", "single_statement",
|
35
|
+
"matched", "simple", "single_arg", "literal_variable",
|
36
|
+
"array_variable", "one_bracket"
|
37
|
+
]
|
38
|
+
|
39
|
+
IdentityTransforms.each do |transform|
|
40
|
+
define_method "handle_#{transform}" do |node|
|
41
|
+
transform(node)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# TODO: This is such a stupid name for a node
|
46
|
+
def handle_regular_fun_call(node)
|
47
|
+
# TODO: Move rewrites into it's own pass,
|
48
|
+
# instead of injecting it into this one..
|
49
|
+
Rewrites.new(self).handle_regular_fun_call(node)
|
50
|
+
end
|
51
|
+
|
52
|
+
def handle_class_method_call(node)
|
53
|
+
[:call, [:const, transform(node.first).to_id], transform(node.third).to_id, transform(node.fifth)]
|
54
|
+
end
|
55
|
+
|
56
|
+
def handle_multiple_variables(node)
|
57
|
+
first = transform(node.first)
|
58
|
+
rest = transform(node.third)
|
59
|
+
|
60
|
+
debug "Multiple variables #{first.inspect}, #{rest.inspect}"
|
61
|
+
|
62
|
+
result = if rest.composite_node?
|
63
|
+
[first] + rest
|
64
|
+
if first.composite_node?
|
65
|
+
first + rest
|
66
|
+
end
|
67
|
+
elsif first.composite_node?
|
68
|
+
first + [rest]
|
69
|
+
else
|
70
|
+
[first, rest]
|
71
|
+
end
|
72
|
+
|
73
|
+
debug "Multiple variables result #{result.inspect}"
|
74
|
+
result
|
75
|
+
end
|
76
|
+
|
77
|
+
###############
|
78
|
+
### globals ###
|
79
|
+
###############
|
80
|
+
|
81
|
+
# We will have to keep track of this at some point
|
82
|
+
# to replace every similar pattern in the entire tree
|
83
|
+
def handle_global_declaration(node)
|
84
|
+
variable = transform(node.second)
|
85
|
+
|
86
|
+
debug "Global variables are #{variable.inspect}"
|
87
|
+
|
88
|
+
# Keeping track of the global variables so we can
|
89
|
+
# replace them as we encounter local variables
|
90
|
+
if variable.composite_node?
|
91
|
+
multiple_globals = [:array] + variable.map do |lvar|
|
92
|
+
self.globals << lvar.last
|
93
|
+
lvar.last.to_global_variable
|
94
|
+
end
|
95
|
+
[:fcall, :global, multiple_globals]
|
96
|
+
elsif variable.first == :lvar
|
97
|
+
self.globals << variable.last
|
98
|
+
variable.last.to_global_variable
|
99
|
+
elsif variable.first == :gvar
|
100
|
+
variable
|
101
|
+
else
|
102
|
+
variable.to_global_variable
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def handle_break_statement(node)
|
107
|
+
[:break]
|
108
|
+
end
|
109
|
+
|
110
|
+
def handle_exit_statement(node)
|
111
|
+
[:vcall, :exit]
|
112
|
+
end
|
113
|
+
|
114
|
+
def handle_exit_call_statement(node)
|
115
|
+
[:vcall, :exit]
|
116
|
+
end
|
117
|
+
|
118
|
+
def handle_require_statement(node)
|
119
|
+
[:fcall, :require, [:array, transform(node.second)]]
|
120
|
+
end
|
121
|
+
|
122
|
+
def handle_require_once_statement(node)
|
123
|
+
[:fcall, :require, [:array, transform(node.second)]]
|
124
|
+
end
|
125
|
+
|
126
|
+
def handle_include_statement(node)
|
127
|
+
[:fcall, :load, [:array, transform(node.second)]]
|
128
|
+
end
|
129
|
+
|
130
|
+
def handle_include_once_statement(node)
|
131
|
+
[:fcall, :load, [:array, transform(node.second)]]
|
132
|
+
end
|
133
|
+
|
134
|
+
def handle_for_statement(node)
|
135
|
+
setup = transform(node.third)
|
136
|
+
condition = transform(node[4])
|
137
|
+
update = transform(node[6])
|
138
|
+
body = transform(node[8])
|
139
|
+
|
140
|
+
while_body = if body.composite_node?
|
141
|
+
[:block] + body + [update]
|
142
|
+
else
|
143
|
+
[:block] + [body] + [update]
|
144
|
+
end
|
145
|
+
|
146
|
+
[setup] + [[:while, condition, while_body, true]]
|
147
|
+
end
|
148
|
+
|
149
|
+
# This should get moved to Rewrites..
|
150
|
+
def handle_foreach_statement(node)
|
151
|
+
variable = transform(node[4]).last
|
152
|
+
|
153
|
+
body = transform(node[6])
|
154
|
+
body = body.replace_pattern([:lvar, variable], [:dvar, variable])
|
155
|
+
|
156
|
+
[:iter,
|
157
|
+
[:call, transform(node.third), :each],
|
158
|
+
[:dasgn_curr, variable], body.to_block]
|
159
|
+
end
|
160
|
+
|
161
|
+
def handle_while_statement(node)
|
162
|
+
condition = transform(node.third)
|
163
|
+
body = transform(node.fifth).to_block
|
164
|
+
|
165
|
+
[:while, condition, body, true]
|
166
|
+
end
|
167
|
+
|
168
|
+
#######################################
|
169
|
+
### recursive switch case statement ###
|
170
|
+
#######################################
|
171
|
+
|
172
|
+
def handle_opt_multiple_statements(node)
|
173
|
+
first_node = [transform(node.first)]
|
174
|
+
|
175
|
+
second_node = if (result = transform(node.second)).composite_node?
|
176
|
+
result
|
177
|
+
else
|
178
|
+
[result]
|
179
|
+
end
|
180
|
+
|
181
|
+
result = [:block] + first_node + second_node
|
182
|
+
debug "Opt multiple statements result is #{result.inspect}"
|
183
|
+
result
|
184
|
+
end
|
185
|
+
|
186
|
+
def handle_opt_no_statements(node)
|
187
|
+
nil
|
188
|
+
end
|
189
|
+
|
190
|
+
###################
|
191
|
+
### list assign ###
|
192
|
+
###################
|
193
|
+
|
194
|
+
# Yes, Php has a destructuring bind..
|
195
|
+
# kinda ugly, though
|
196
|
+
def handle_list_assign(node)
|
197
|
+
variables = [:array] + (transform(node.third).rest.map {|v| [:lasgn, v] })
|
198
|
+
[:masgn, variables,
|
199
|
+
[:splat, transform(node.sixth)]]
|
200
|
+
end
|
201
|
+
|
202
|
+
#####################
|
203
|
+
### oo statements ###
|
204
|
+
#####################
|
205
|
+
|
206
|
+
def handle_new_object(node)
|
207
|
+
[:call, [:const, transform(node.second).to_id], :new]
|
208
|
+
end
|
209
|
+
|
210
|
+
def handle_new_object_with_args(node)
|
211
|
+
if node.fourth == {:fun_args_within_call=>[{:no_args_within_call=>[]}]}
|
212
|
+
[:call, [:const, transform(node.second).to_id], :new]
|
213
|
+
else
|
214
|
+
# TODO: Handle this..
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
def handle_new_variable_class_object(node)
|
219
|
+
[:call,
|
220
|
+
[:call,
|
221
|
+
[:const, :Object], :const_get,
|
222
|
+
[:array, transform(node.second)]], :new]
|
223
|
+
end
|
224
|
+
|
225
|
+
def handle_class_statement(node)
|
226
|
+
[:class, transform(node.second).to_id, nil,
|
227
|
+
[:scope, transform(node.fourth).to_block]]
|
228
|
+
end
|
229
|
+
|
230
|
+
def handle_class_extends_statement(node)
|
231
|
+
[:class, transform(node.second).to_id, [:const, transform(node.fourth).to_id],
|
232
|
+
[:scope, transform(node[5]).to_block]]
|
233
|
+
end
|
234
|
+
|
235
|
+
def handle_class_var_statement(node)
|
236
|
+
[:fcall, :attr_accessor, [:array, [:lit, transform(node.second).last]]]
|
237
|
+
end
|
238
|
+
|
239
|
+
def handle_class_var_with_default_statement(node)
|
240
|
+
[:fcall, :attr_accessor, [:array, [:lit, transform(node.second).last], transform(node.fourth)]]
|
241
|
+
end
|
242
|
+
|
243
|
+
def handle_braced_statements(node)
|
244
|
+
transform(node.second)
|
245
|
+
end
|
246
|
+
|
247
|
+
def handle_print_statement(node)
|
248
|
+
[:fcall, :print, [:array, transform(node).first]]
|
249
|
+
end
|
250
|
+
|
251
|
+
def handle_echo_statement(node)
|
252
|
+
[:fcall, :echo, [:array, transform(node.second)]]
|
253
|
+
end
|
254
|
+
|
255
|
+
def handle_user_constant(node)
|
256
|
+
[:const, transform(node).to_id]
|
257
|
+
end
|
258
|
+
|
259
|
+
def handle_word(node)
|
260
|
+
node
|
261
|
+
end
|
262
|
+
|
263
|
+
def handle_no_args(node)
|
264
|
+
[:args]
|
265
|
+
end
|
266
|
+
|
267
|
+
def handle_no_args_within_call(node)
|
268
|
+
[:args]
|
269
|
+
end
|
270
|
+
|
271
|
+
# Comment this out and see if it can be refactored with the
|
272
|
+
# handler above
|
273
|
+
def handle_a_variable(node)
|
274
|
+
result = transform(node)
|
275
|
+
|
276
|
+
if result.is_a? Array
|
277
|
+
result
|
278
|
+
else
|
279
|
+
[:lvar, result.gsub("$", "").to_id]
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def handle_op(node)
|
284
|
+
if node == ".="
|
285
|
+
:<<
|
286
|
+
else
|
287
|
+
node.to_id
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
def handle_not_var(node)
|
292
|
+
debug "Not var #{node.inspect}"
|
293
|
+
[:not, transform(node.second)]
|
294
|
+
end
|
295
|
+
|
296
|
+
def handle_post_increment_var(node)
|
297
|
+
debug "Post increment var #{node.inspect}"
|
298
|
+
variable = transform(node.first)
|
299
|
+
[:lasgn, variable.second, [:call, variable, :+, [:array, [:lit, 1]]]]
|
300
|
+
end
|
301
|
+
|
302
|
+
def handle_post_decrement_var(node)
|
303
|
+
variable = transform(node.first)
|
304
|
+
[:lasgn, variable.second, [:call, variable, :-, [:array, [:lit, 1]]]]
|
305
|
+
end
|
306
|
+
|
307
|
+
def handle_negative_var(node)
|
308
|
+
result = transform(node.second)
|
309
|
+
result[1] = (-result[1])
|
310
|
+
result
|
311
|
+
end
|
312
|
+
|
313
|
+
def handle_multiple_args(node)
|
314
|
+
debug "Multiple args #{node.inspect}"
|
315
|
+
args = FunctionArgs.new(self).handle_multiple_args(node)
|
316
|
+
debug "Multiple args transformed is #{args.inspect}"
|
317
|
+
unless args == [:args]
|
318
|
+
[:args] + args
|
319
|
+
else
|
320
|
+
[:args]
|
321
|
+
end
|
322
|
+
end
|
323
|
+
|
324
|
+
def handle_multiple_args_within_call(node)
|
325
|
+
debug "Multiple args within fun call #{node.inspect}"
|
326
|
+
|
327
|
+
first = transform(node.first)
|
328
|
+
second = transform(node.third)
|
329
|
+
|
330
|
+
debug "Multiple args first is #{first.inspect} and second is #{second.inspect}"
|
331
|
+
|
332
|
+
result = if first.composite_node?
|
333
|
+
first + [second]
|
334
|
+
elsif first.first == :hash and second.first == :hash
|
335
|
+
first + second.rest
|
336
|
+
else
|
337
|
+
[first, second]
|
338
|
+
end
|
339
|
+
|
340
|
+
debug "Multiple args within fun call result #{result.inspect}"
|
341
|
+
result
|
342
|
+
end
|
343
|
+
|
344
|
+
def handle_single_arg_within_call(node)
|
345
|
+
result = transform(node)
|
346
|
+
debug "Single arg within fun call #{result.inspect}"
|
347
|
+
result
|
348
|
+
end
|
349
|
+
|
350
|
+
def handle_one_expr_bracket(node)
|
351
|
+
transform(node.second)
|
352
|
+
end
|
353
|
+
|
354
|
+
def handle_array_lookup(node)
|
355
|
+
[:call, transform(node.first), :[], [:array, transform(node.third)]]
|
356
|
+
end
|
357
|
+
|
358
|
+
def handle_braced_lookup(node)
|
359
|
+
[:call, transform(node.first), :[], [:array, transform(node.third)]]
|
360
|
+
end
|
361
|
+
|
362
|
+
def handle_paren_expr(node)
|
363
|
+
transform(node.second)
|
364
|
+
end
|
365
|
+
|
366
|
+
def handle_return_one(node)
|
367
|
+
[:return, transform(node.second)]
|
368
|
+
end
|
369
|
+
|
370
|
+
def handle_return_zero(node)
|
371
|
+
[:return]
|
372
|
+
end
|
373
|
+
|
374
|
+
def handle_tertiary(node)
|
375
|
+
[:if, transform(node.first), transform(node.third), transform(node.fifth)]
|
376
|
+
end
|
377
|
+
|
378
|
+
def handle_cast(node)
|
379
|
+
node
|
380
|
+
end
|
381
|
+
|
382
|
+
def handle_paren_cast(node)
|
383
|
+
type = ("to_" + transform(node.second).to_s).to_id
|
384
|
+
term = transform(node.fourth)
|
385
|
+
|
386
|
+
[:call, term, type]
|
387
|
+
end
|
388
|
+
|
389
|
+
def handle_fun_define(node)
|
390
|
+
args = FunctionArgs.new(self).transform(node[3])
|
391
|
+
|
392
|
+
debug "Args for fun_define are #{args.inspect}"
|
393
|
+
parameters = if args == [:args]
|
394
|
+
[:args]
|
395
|
+
elsif args.is_a? Array
|
396
|
+
[:args] + args
|
397
|
+
else
|
398
|
+
[:args, args]
|
399
|
+
end
|
400
|
+
|
401
|
+
body = transform(node[6])
|
402
|
+
body.shift if body.first == :block
|
403
|
+
debug "Body is #{body.inspect}"
|
404
|
+
|
405
|
+
if body.composite_node?
|
406
|
+
function_block = [:block, parameters] + body
|
407
|
+
else
|
408
|
+
function_block = [:block, parameters, body]
|
409
|
+
end
|
410
|
+
|
411
|
+
[:defn, node.second.to_a.first.second.to_id,
|
412
|
+
[:scope, function_block]]
|
413
|
+
end
|
414
|
+
|
415
|
+
def handle_variable(node)
|
416
|
+
result = node.gsub("$", "").to_id
|
417
|
+
|
418
|
+
if self.globals.include? result
|
419
|
+
[:gvar, ("$" + result.to_s.gsub("$", "")).to_id]
|
420
|
+
else
|
421
|
+
[:lvar, result]
|
422
|
+
end
|
423
|
+
end
|
424
|
+
|
425
|
+
def handle_fun_args_within_call(node)
|
426
|
+
debug "Fun args within call #{node.inspect}"
|
427
|
+
result = transform(node)
|
428
|
+
debug "Fun args within call result #{result.inspect}"
|
429
|
+
if result.empty?
|
430
|
+
nil
|
431
|
+
elsif result.nil?
|
432
|
+
nil
|
433
|
+
elsif result.composite_node?
|
434
|
+
[:array] + result
|
435
|
+
else
|
436
|
+
[:array, result]
|
437
|
+
end
|
438
|
+
end
|
439
|
+
|
440
|
+
def handle_fun_args_with_trailing_comma(node)
|
441
|
+
debug "Fun args with trailing comma #{node.inspect}"
|
442
|
+
result = transform(node.first)
|
443
|
+
|
444
|
+
if result.empty?
|
445
|
+
nil
|
446
|
+
elsif result.nil?
|
447
|
+
nil
|
448
|
+
elsif result.composite_node?
|
449
|
+
[:array] + result
|
450
|
+
else
|
451
|
+
[:array, result]
|
452
|
+
end
|
453
|
+
end
|
454
|
+
|
455
|
+
|
456
|
+
###########################
|
457
|
+
### multiple statements ###
|
458
|
+
###########################
|
459
|
+
|
460
|
+
def handle_multiple_statements(node)
|
461
|
+
# This implementation is kind of old
|
462
|
+
# and stinky.. Could probably be done
|
463
|
+
# a lot better
|
464
|
+
|
465
|
+
multiple_statements do
|
466
|
+
first, second = transform(node.first), transform(node.second)
|
467
|
+
result = if second.composite_node?
|
468
|
+
if first.composite_node?
|
469
|
+
first + second
|
470
|
+
else
|
471
|
+
[first] + second
|
472
|
+
end
|
473
|
+
else
|
474
|
+
[first, second]
|
475
|
+
end
|
476
|
+
|
477
|
+
final_result = if level == 1
|
478
|
+
[:block] + result
|
479
|
+
else
|
480
|
+
result
|
481
|
+
end
|
482
|
+
final_result
|
483
|
+
end
|
484
|
+
end
|
485
|
+
|
486
|
+
|
487
|
+
################
|
488
|
+
### oo exprs ###
|
489
|
+
################
|
490
|
+
|
491
|
+
def handle_oo_assign(node)
|
492
|
+
debug "The oo assign node is #{node.inspect}"
|
493
|
+
# TODO: Pretty this up some.. If possible..
|
494
|
+
object = transform(node.first)
|
495
|
+
|
496
|
+
debug "The object to be set is #{object.inspect}"
|
497
|
+
object.shift # discard leading :call
|
498
|
+
|
499
|
+
attribute = object.pop
|
500
|
+
debug "The attribute to be set is #{attribute.inspect}"
|
501
|
+
|
502
|
+
assigned = attribute.to_s + "=" # pop off assigned to var
|
503
|
+
expr = transform(node.fifth)
|
504
|
+
|
505
|
+
# TODO: Move this rewrite to the Rewrites class
|
506
|
+
object = (if object.first == [:lvar, :this] then [:self] else object.first end)
|
507
|
+
|
508
|
+
[:attrasgn, object, assigned.to_id, [:array, expr]]
|
509
|
+
end
|
510
|
+
|
511
|
+
def handle_oo_array_assign(node)
|
512
|
+
[:attrasgn,
|
513
|
+
[:call, transform(node.first), transform(node.third).to_id],
|
514
|
+
:[]=,
|
515
|
+
[:array, transform(node.fifth), transform(node[7])]]
|
516
|
+
end
|
517
|
+
|
518
|
+
def handle_oo_variable_variable(node)
|
519
|
+
[:call, transform(node.first), :get, [:array, transform(node.third)]]
|
520
|
+
end
|
521
|
+
|
522
|
+
def handle_oo_variable_variable_assign(node)
|
523
|
+
[:attrasgn, transform(node.first), :[]=, [:array, transform(node.third), transform(node.fifth)]]
|
524
|
+
end
|
525
|
+
|
526
|
+
def handle_oo_variable(node)
|
527
|
+
debug "oo_variable #{node.inspect}"
|
528
|
+
term = transform(node.first)
|
529
|
+
# TODO: Move this rewrite to the Rewrites class
|
530
|
+
object = (if term == [:lvar, :this] then [:self] else term end)
|
531
|
+
[:call, object, transform(node.third).to_id]
|
532
|
+
end
|
533
|
+
|
534
|
+
def handle_single_oo_fragment(node)
|
535
|
+
transform(node.second)
|
536
|
+
end
|
537
|
+
|
538
|
+
def handle_array_append(node)
|
539
|
+
transform(node.first)
|
540
|
+
end
|
541
|
+
|
542
|
+
def handle_oo_array_lookup(node)
|
543
|
+
[:call, [:call, transform(node.first), transform(node.third).to_sym], :[], [:array, transform(node.fifth)]]
|
544
|
+
end
|
545
|
+
|
546
|
+
def handle_oo_expr(node)
|
547
|
+
transform(node)
|
548
|
+
end
|
549
|
+
|
550
|
+
def handle_oo_call(node)
|
551
|
+
debug "oo call node is #{node.inspect}"
|
552
|
+
|
553
|
+
if node.fifth == {:fun_args_within_call=>[{:no_args_within_call=>[]}]}
|
554
|
+
[:call, transform(node.first), transform(node.third).to_id]
|
555
|
+
else
|
556
|
+
[:call, transform(node.first), transform(node.third).to_id, transform(node.fifth)]
|
557
|
+
end
|
558
|
+
end
|
559
|
+
|
560
|
+
def handle_oo_regular_fun_call(node)
|
561
|
+
[transform(node.first).to_id, transform(node.third)]
|
562
|
+
end
|
563
|
+
|
564
|
+
################
|
565
|
+
### literals ###
|
566
|
+
################
|
567
|
+
|
568
|
+
def handle_true_value(node)
|
569
|
+
[:true]
|
570
|
+
end
|
571
|
+
|
572
|
+
def handle_false_value(node)
|
573
|
+
[:false]
|
574
|
+
end
|
575
|
+
|
576
|
+
def handle_single_quoted_string(node)
|
577
|
+
[:str, node]
|
578
|
+
end
|
579
|
+
|
580
|
+
def handle_double_quoted_string(node)
|
581
|
+
[:str, node]
|
582
|
+
end
|
583
|
+
|
584
|
+
############
|
585
|
+
### nils ###
|
586
|
+
############
|
587
|
+
|
588
|
+
define_method "handle_;" do |node|
|
589
|
+
nil
|
590
|
+
end
|
591
|
+
|
592
|
+
def handle_print(arg)
|
593
|
+
nil
|
594
|
+
end
|
595
|
+
|
596
|
+
define_method "handle_," do |node|
|
597
|
+
nil
|
598
|
+
end
|
599
|
+
|
600
|
+
############
|
601
|
+
### html ###
|
602
|
+
############
|
603
|
+
|
604
|
+
def handle_html_text_with_php(node)
|
605
|
+
[:php] + transform(node)
|
606
|
+
end
|
607
|
+
|
608
|
+
def handle_html_string(node)
|
609
|
+
[:html, node]
|
610
|
+
end
|
611
|
+
|
612
|
+
def handle_php_start(node)
|
613
|
+
[:erb_start, "<% "]
|
614
|
+
end
|
615
|
+
|
616
|
+
def handle_php_end(node)
|
617
|
+
[:erb_end, " %>"]
|
618
|
+
end
|
619
|
+
end
|
620
|
+
end
|
621
|
+
end
|
622
|
+
end
|