farleyknight-ionize 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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