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.
Files changed (98) hide show
  1. data/README.rdoc +59 -0
  2. data/Rakefile +5 -0
  3. data/bin/ionize +47 -0
  4. data/lib/ionize.rb +75 -0
  5. data/lib/ionize/environment.rb +56 -0
  6. data/lib/ionize/environment/application.rb +58 -0
  7. data/lib/ionize/environment/php_array.rb +95 -0
  8. data/lib/ionize/parser.rb +272 -0
  9. data/lib/ionize/tokenizer.rb +544 -0
  10. data/lib/ionize/translate.rb +34 -0
  11. data/lib/ionize/translate/composite_string_statements.rb +79 -0
  12. data/lib/ionize/translate/debug.rb +16 -0
  13. data/lib/ionize/translate/ext.rb +47 -0
  14. data/lib/ionize/translate/function_args.rb +132 -0
  15. data/lib/ionize/translate/if_statements.rb +42 -0
  16. data/lib/ionize/translate/multiple_statements.rb +22 -0
  17. data/lib/ionize/translate/php_to_ruby.rb +40 -0
  18. data/lib/ionize/translate/rails_for_php.rb +191 -0
  19. data/lib/ionize/translate/rewritable.rb +133 -0
  20. data/lib/ionize/translate/rewrites.rb +51 -0
  21. data/lib/ionize/translate/statements.rb +622 -0
  22. data/lib/ionize/translate/switch_case_statements.rb +52 -0
  23. data/lib/ionize/translate/term_statements.rb +76 -0
  24. data/lib/ionize/translate/translator.rb +52 -0
  25. data/lib/ionize/version.rb +9 -0
  26. data/spec/fixtures/array_lookup.php +10 -0
  27. data/spec/fixtures/boolean_operators.php +5 -0
  28. data/spec/fixtures/boolean_operators.rb +6 -0
  29. data/spec/fixtures/class_def.php +34 -0
  30. data/spec/fixtures/class_def.rb +34 -0
  31. data/spec/fixtures/dangling_else.php +8 -0
  32. data/spec/fixtures/dangling_else.rb +12 -0
  33. data/spec/fixtures/drupal_1.php +663 -0
  34. data/spec/fixtures/drupal_2.php +1152 -0
  35. data/spec/fixtures/empty_string.php +12 -0
  36. data/spec/fixtures/for_loop.php +17 -0
  37. data/spec/fixtures/for_loop2.php +13 -0
  38. data/spec/fixtures/for_loop3.php +16 -0
  39. data/spec/fixtures/for_loop3.rb +17 -0
  40. data/spec/fixtures/for_loop4.php +5 -0
  41. data/spec/fixtures/for_loop4.rb +6 -0
  42. data/spec/fixtures/foreach.php +9 -0
  43. data/spec/fixtures/foreach2.php +8 -0
  44. data/spec/fixtures/foreach3.php +7 -0
  45. data/spec/fixtures/foreach3.rb +7 -0
  46. data/spec/fixtures/fun_def.php +9 -0
  47. data/spec/fixtures/fun_def2.php +30 -0
  48. data/spec/fixtures/fun_def2.rb +30 -0
  49. data/spec/fixtures/fun_def3.php +33 -0
  50. data/spec/fixtures/fun_def4.php +43 -0
  51. data/spec/fixtures/fun_def4.rb +37 -0
  52. data/spec/fixtures/fun_def5.php +36 -0
  53. data/spec/fixtures/fun_with_if.php +6 -0
  54. data/spec/fixtures/fun_with_if.rb +6 -0
  55. data/spec/fixtures/fun_with_ifs.php +12 -0
  56. data/spec/fixtures/fun_with_ifs.rb +14 -0
  57. data/spec/fixtures/hello_world.php +6 -0
  58. data/spec/fixtures/heredoc.php +6 -0
  59. data/spec/fixtures/heredoc.rb +5 -0
  60. data/spec/fixtures/if.php +6 -0
  61. data/spec/fixtures/if.rb +7 -0
  62. data/spec/fixtures/if_boolean.php +5 -0
  63. data/spec/fixtures/if_boolean.rb +5 -0
  64. data/spec/fixtures/if_else.php +11 -0
  65. data/spec/fixtures/if_else1.php +17 -0
  66. data/spec/fixtures/if_else2.php +8 -0
  67. data/spec/fixtures/if_else3.php +15 -0
  68. data/spec/fixtures/if_else_nested.php +14 -0
  69. data/spec/fixtures/if_else_nested.rb +15 -0
  70. data/spec/fixtures/if_else_series.php +12 -0
  71. data/spec/fixtures/if_else_series.rb +12 -0
  72. data/spec/fixtures/if_not.php +5 -0
  73. data/spec/fixtures/if_not.rb +5 -0
  74. data/spec/fixtures/if_with_brackets.php +7 -0
  75. data/spec/fixtures/if_with_brackets.rb +7 -0
  76. data/spec/fixtures/long_if_else.php +10 -0
  77. data/spec/fixtures/long_if_else.rb +9 -0
  78. data/spec/fixtures/oo.php +16 -0
  79. data/spec/fixtures/php_nuke/sql_layer.php +527 -0
  80. data/spec/fixtures/postop.php +3 -0
  81. data/spec/fixtures/preop.php +7 -0
  82. data/spec/fixtures/simple_fun_def.php +4 -0
  83. data/spec/fixtures/switch_case.php +13 -0
  84. data/spec/fixtures/switch_case.rb +14 -0
  85. data/spec/fixtures/switch_case2.php +25 -0
  86. data/spec/fixtures/switch_case3.php +40 -0
  87. data/spec/fixtures/switch_case3.rb +42 -0
  88. data/spec/fixtures/switch_case4.php +56 -0
  89. data/spec/fixtures/switch_case5.php +71 -0
  90. data/spec/fixtures/switch_case_with_rescue_nil.php +43 -0
  91. data/spec/fixtures/switch_case_with_rescue_nil.rb +35 -0
  92. data/spec/fixtures/tertiary.php +3 -0
  93. data/spec/helper.rb +17 -0
  94. data/spec/php_environment_spec.rb +83 -0
  95. data/spec/php_parser_spec.rb +121 -0
  96. data/spec/php_translator_spec.rb +358 -0
  97. data/spec/rails_for_php_spec.rb +303 -0
  98. 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