julializer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6b642dd1c03b8303e02dc986ef75b05e734310ed
4
+ data.tar.gz: c8e5c67d459b55cd43931fe89c668321196ca473
5
+ SHA512:
6
+ metadata.gz: ba346042cb89c7ff9ff2e90b0a2100e897f59ce672f30ac41edcb4fc8a4b88e30353d4097bcb94236ba087645d46b06a01489c5dfbfbd933b1115474417dcd1e
7
+ data.tar.gz: d8d2be6a6149114f545c54b415dce47e717f3662e1658b464a8c8dd58096a0ffddbfce3a734761d4856c4caf28a618cbbedcecade620f35a890964fa90ae5c68
data/README.md ADDED
@@ -0,0 +1,7 @@
1
+ A ruby2julia transpiler made with ❤️:
2
+
3
+ ## Limitation And Restrictions
4
+ TBD
5
+
6
+ ## License
7
+ MIT
data/Rakefile ADDED
@@ -0,0 +1,24 @@
1
+ specs = [
2
+ "spec/core/random/rand_spec.rb",
3
+ "spec/core/array/slice_spec.rb",
4
+ "spec/core/math/atan2_spec.rb",
5
+ "spec/core/math/atan_spec.rb",
6
+ "spec/core/math/asinh_spec.rb",
7
+ "spec/core/math/asin_spec.rb",
8
+ "spec/core/math/acosh_spec.rb",
9
+ "spec/core/math/acos_spec.rb",
10
+ "spec/core/integer/",
11
+ "spec/core/float/",
12
+ "spec/core/fixnum/",
13
+ "spec/core/false/",
14
+ ]
15
+
16
+ desc 'test behaviour using RSpec test files located in spec/*'
17
+ task :spec do
18
+ specs.each {|e| system("rspec #{e}")}
19
+ end
20
+
21
+ desc 'test behaviour using RSpec test files located in spec/* with JULIALIZE_DEBUG set to true'
22
+ task :spec_debug do
23
+ specs.each {|e| system("JULIALIZE_DEBUG=true rspec #{e}") }
24
+ end
data/bin/julializer ADDED
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+ require 'julializer'
4
+
5
+ Options = OptionParser.new do |opts|
6
+ opts.on("-v", "--version", "Print version") { |v| puts Julializer::VERSION; exit 0}
7
+ end
8
+ Options.parse!(ARGV)
9
+
10
+ if ARGV.empty?
11
+ printf Julializer.ruby2julia($stdin.read)
12
+ else
13
+ ARGV.each do |file|
14
+ if File.exist? file
15
+ printf Julializer.ruby2julia(File.read(file))
16
+ else
17
+ puts "File was not found: #{file}"
18
+ exit
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,3 @@
1
+ module Julializer
2
+ VERSION = "0.1.0"
3
+ end
data/lib/julializer.rb ADDED
@@ -0,0 +1,439 @@
1
+ require 'ripper'
2
+
3
+ module Julializer
4
+ class << self
5
+ require "julializer/version"
6
+
7
+ def ruby2julia(source)
8
+ @globals = []
9
+ #File.write("./__julialize_debug.log", Ripper.sexp(source).pretty_inspect)
10
+ transpile(Ripper.sexp(source))
11
+ end
12
+
13
+ private
14
+ def delim(s)
15
+ if s.kind_of?(Array) then
16
+ s.map{|line| "#{line};" }.join
17
+ else
18
+ "#{s};"
19
+ end
20
+ end
21
+
22
+ def transpile(s)
23
+ if s.instance_of?(String) then
24
+ s
25
+ elsif s.instance_of?(Array) && s[0].instance_of?(Symbol) then
26
+ #puts "s[0]=#{s[0]}"
27
+ #puts "s[1]=#{s[1]}"
28
+ case s[0]
29
+ when :program, :bodystmt #, :else
30
+ s[1].map{|e| delim(transpile(e))}.join
31
+
32
+ #when :if, :elsif
33
+ # s[2].map{|e| delim(transpile(e))}.join
34
+
35
+ when :assign
36
+ delim(transpile(s[1]) + "=" + transpile(s[2]))
37
+
38
+ when :var_field, :var_ref
39
+ if [:@gvar, :@ivar, :@cvar].include?(s[1][0])
40
+ @globals << s[1][1][1..-1]
41
+ s[1][1][1..-1]
42
+ elsif s[1][0]==:@const
43
+ (s[0]==:var_field ? "const " : "") + s[1][1].downcase
44
+ else
45
+ s[1][1]
46
+ end
47
+
48
+ when :next
49
+ delim("continue")
50
+
51
+ when :break
52
+ delim("break")
53
+
54
+ when :void_stmt
55
+ "" # this happens when rip "if true then # do nothing end" type of code
56
+
57
+ when :binary
58
+ if s[2] == :<< then
59
+ "push!(#{transpile(s[1])}, #{transpile(s[3])})"
60
+ elsif s[1][0] == :string_literal && s[2] == :% then
61
+ if s[3][0] == :array then
62
+ "@sprintf(#{transpile(s[1][1][1])},#{s[3][1].map{|e| transpile(e)}.join(',')})"
63
+ else
64
+ "@sprintf(#{transpile(s[1][1][1])},#{transpile(s[3])})"
65
+ end
66
+ else
67
+ case s[2]
68
+ when :or
69
+ operator = "||"
70
+ when :and
71
+ operator = "&&"
72
+ when :^
73
+ operator = "$"
74
+ when :**
75
+ operator = "^"
76
+ when :===
77
+ operator = "==" # Prevent using === since in Julia === checks much strictly than Ruby.
78
+ else
79
+ operator = s[2].to_s
80
+ end
81
+ transpile(s[1]) + operator + transpile(s[3])
82
+ end
83
+
84
+ when :opassign
85
+ delim(transpile(s[1]) + transpile(s[2]) + transpile(s[3]))
86
+
87
+ when :unary
88
+ case s[1]
89
+ when :not, :!
90
+ "!" + transpile(s[2])
91
+ when :-@
92
+ "(-" + transpile(s[2]) + ")"
93
+ when :~
94
+ "~" + transpile(s[2])
95
+ else
96
+ transpile(s[2])
97
+ end
98
+
99
+ when :paren
100
+ "(" + transpile(s[1][0]) + ")"
101
+
102
+ when :symbol
103
+ s[1][1]
104
+
105
+ when :field, :call
106
+ case s[1][1][1]
107
+ when "Math"
108
+ transpile(s[3][1])
109
+ when "Random"
110
+ case s[3][1]
111
+ when "rand"
112
+ "rand()"
113
+ else
114
+ transpile(s[3][1])
115
+ end
116
+ else
117
+ case s[3][1]
118
+ when "dup"
119
+ "copy(#{transpile(s[1])})"
120
+
121
+ when "shift"
122
+ "shift!(#{transpile(s[1])})"
123
+
124
+ when "to_f"
125
+ "float(#{transpile(s[1])})"
126
+
127
+ when "to_i", "to_int"
128
+ "trunc(Int64,parse(string(#{transpile(s[1])})))"
129
+
130
+ when "truncate"
131
+ "trunc(#{transpile(s[1])})"
132
+
133
+ when "chr"
134
+ "Char(#{transpile(s[1])})"
135
+
136
+ when "ord"
137
+ "Int(#{transpile(s[1])})"
138
+
139
+ when "class"
140
+ "typeof(#{transpile(s[1])})"
141
+
142
+ when "to_s"
143
+ "string(#{transpile(s[1])})"
144
+
145
+ when "even?"
146
+ "iseven(#{transpile(s[1])})"
147
+
148
+ when "odd?"
149
+ "isodd(#{transpile(s[1])})"
150
+
151
+ when "infinite?"
152
+ "isinf(#{transpile(s[1])})"
153
+
154
+ when "finite?"
155
+ "isfinite(#{transpile(s[1])})"
156
+
157
+ when "zero?"
158
+ "(#{transpile(s[1])}==0)"
159
+
160
+ when "integer?"
161
+ "(typeof(#{transpile(s[1])})==Int64)"
162
+
163
+ when "nan?"
164
+ "isnan(#{transpile(s[1])})"
165
+
166
+ when "abs", "magnitude"
167
+ "abs(#{transpile(s[1])})"
168
+
169
+ when "ceil", "floor"
170
+ "#{s[3][1]}(Int64,#{transpile(s[1])})"
171
+
172
+ when "size", "count"
173
+ "size(#{transpile(s[1])})[1]"
174
+
175
+ when "next", "succ"
176
+ "(#{transpile(s[1])}+1)"
177
+
178
+ when "pred"
179
+ "(#{transpile(s[1])}-1)"
180
+
181
+ when "next_float"
182
+ "(nextfloat(#{transpile(s[1])}))"
183
+
184
+ when "prev_float"
185
+ "(prevfloat(#{transpile(s[1])}))"
186
+
187
+ when "round"
188
+ "round(Int64,#{transpile(s[1])})"
189
+
190
+ else
191
+ "#{transpile(s[3])}(#{transpile(s[1])})"
192
+
193
+ end
194
+ end
195
+
196
+ when :array
197
+ s[1].nil? ? "[]" : "["+s[1].map{|e| transpile(e[1])}.join(",")+"]"
198
+
199
+ when :@CHAR
200
+ "'" + s[1][1] + "'"
201
+
202
+ when :@ident, :@int, :@kw, :@op
203
+ if s[0]==:@int && s[1][0..1]=="0x" then
204
+ "(#{s[1]}+0)" # Promote to Int64 from smaller numbers for cases like spec/core/float/divide_spec.rb (otherwise 91.1/-0xffffffff fails)
205
+ else
206
+ s[1]
207
+ end
208
+
209
+ when :string_content
210
+ s[1].nil? ? "" : 'string(' + s[1..-1].map{|e| transpile(e)}.join(",") + ')'
211
+
212
+ when :@tstring_content
213
+ '"' + s[1] + '"'
214
+
215
+ # commented out for simplification
216
+ #when :vcall
217
+
218
+ when :command
219
+ case s[1][1]
220
+ when "p", "puts", "printf", "print"
221
+ c = "print"
222
+ else
223
+ c = transpile(s[1])
224
+ end
225
+ delim(c + "(" + transpile(s[2]) + ")")
226
+
227
+ when :method_add_block
228
+ t = s[1][0]==:call ? s : s[1]
229
+ if t[1][3][1]=="each"
230
+ delim([
231
+ "___state = start(#{t[1][1][1][1]})",
232
+ "while !done(#{t[1][1][1][1]}, ___state)",
233
+ "___i, ___state = next(#{t[1][1][1][1]}, ___state)",
234
+ (s[2][1].nil? ? "" : "#{s[2][1][1][1][0][1]} = ___i"),
235
+ s[2][2].map{|e| delim(transpile(e))}.join,
236
+ "end"
237
+ ])
238
+ elsif t[1][3][1]=="downto"
239
+ delim([
240
+ "for #{transpile(s[2][1])} in countfrom(#{transpile(t[1][1])}, -1)",
241
+ "if #{transpile(s[2][1])}<#{transpile(t[2][1][1])} break end",
242
+ s[2][2].map{|e| delim(transpile(e))}.join,
243
+ "end"
244
+ ])
245
+ elsif t[1][3][1]=="times"
246
+ delim([
247
+ "for #{transpile(s[2][1]).nil? ? "___xyz___" : transpile(s[2][1]) } in 0:#{transpile(t[1][1])}-1",
248
+ s[2][2].map{|e| delim(transpile(e))}.join,
249
+ "end"
250
+ ])
251
+ else
252
+ transpile(s[1])
253
+ end
254
+
255
+ when :method_add_arg
256
+ if transpile(s[1][1])=="array" && transpile(s[1][3])=="new"
257
+ "fill(#{s[2][1][1][1][1]}, #{s[2][1][1][0][1][1]})"
258
+ elsif transpile(s[1][1])=="random" && transpile(s[1][3])=="rand"
259
+ "rand(#{transpile(s[2][1])})"
260
+ else
261
+ case transpile(s[1][3])
262
+ when "slice", "slice!"
263
+ method = transpile(s[1][3]) == "slice!" ? "splice!" : transpile(s[1][3])
264
+ start_index=0
265
+ if s[2][1][1][0][0] == :dot2 || s[2][1][1][0][0] == :dot3
266
+ range = "#{transpile(s[2])}"
267
+ elsif s[2][1][1].count == 1
268
+ range = "#{transpile(s[2])}+1"
269
+ else
270
+ range = "#{transpile(s[2][1][1][0])}+1:#{start_index}+#{transpile(s[2][1][1][0])}+#{transpile(s[2][1][1][1])}+1"
271
+ end
272
+ "#{method}(#{transpile(s[1][1])}, #{range})"
273
+
274
+ when "send"
275
+ case transpile(s[2][1][1][0])
276
+ when "==", "==="
277
+ # Prevent using === since in Julia === checks much strictly than Ruby.
278
+ "==(#{transpile(s[2][1][1][1])}, #{transpile(s[1][1])})"
279
+ when "magnitude"
280
+ "abs(#{transpile(s[1][1])})"
281
+ when "to_i", "to_int"
282
+ "trunc(Int64,parse(string(#{transpile(s[1][1])})))"
283
+ when "truncate"
284
+ "trunc(#{transpile(s[1][1])})"
285
+ when "-@"
286
+ "-(#{transpile(s[1][1])})"
287
+ when "+@"
288
+ transpile(s[1][1])
289
+ when "%", "modulo"
290
+ "#{transpile(s[1][1])}%#{transpile(s[2][1][1][1])}"
291
+ when "fdiv"
292
+ "#{transpile(s[1][1])}/#{transpile(s[2][1][1][1])}"
293
+ when "next", "succ"
294
+ "(#{transpile(s[1][1])}+1)"
295
+ else
296
+ "#{transpile(s[2])}(#{transpile(s[1][1])})"
297
+ end
298
+ when "index"
299
+ "findfirst(#{transpile(s[1][1])}, #{transpile(s[2])})"
300
+ when "rindex"
301
+ "findlast(#{transpile(s[1][1])}, #{transpile(s[2])})"
302
+ when "div"
303
+ "floor(#{transpile(s[1][1])}/#{transpile(s[2])})"
304
+ when "modulo"
305
+ "#{transpile(s[1][1])}%#{transpile(s[2])}"
306
+ when "divmod"
307
+ "divrem(#{transpile(s[1][1])},#{transpile(s[2])})"
308
+ when "fdiv"
309
+ "#{transpile(s[1][1])}/#{transpile(s[2])}"
310
+ when "eql?"
311
+ "===(#{transpile(s[1][1])}, #{transpile(s[2])})"
312
+ when "round"
313
+ "round(#{transpile(s[1][1])}, #{transpile(s[2])})"
314
+ when "atan2"
315
+ "atan2(#{transpile(s[2])})"
316
+ when "gcd"
317
+ "gcd(#{transpile(s[1][1])}, #{transpile(s[2])})"
318
+ when "lcm"
319
+ "lcm(#{transpile(s[1][1])}, #{transpile(s[2])})"
320
+ when "gcdlcm"
321
+ "[gcd(#{transpile(s[1][1])}, #{transpile(s[2])}), lcm(#{transpile(s[1][1])}, #{transpile(s[2])})]"
322
+ when "key?", "has_key?"
323
+ "haskey(#{transpile(s[1][1])}, #{transpile(s[2])})"
324
+ when "rand"
325
+ "int(rand() * #{transpile(s[2])})"
326
+
327
+ else
328
+ transpile(s[1]) + "(" + (transpile(s[2]) || "") + ")"
329
+ end
330
+ end
331
+
332
+ when :args_add_block
333
+ s[1].map{|e| transpile(e)}.join(",")
334
+
335
+ when :while
336
+ delim([
337
+ "while " + transpile(s[1]),
338
+ transpile(s[2]),
339
+ "end"
340
+ ])
341
+
342
+ when :for
343
+ delim([
344
+ "for #{transpile(s[1])}::Int64 = #{transpile(s[2])}",
345
+ transpile(s[3]),
346
+ "end"
347
+ ])
348
+
349
+ when :if, :elsif
350
+ if s[0]==:elsif then
351
+ keyword = "elseif"
352
+ else
353
+ keyword = "if"
354
+ end
355
+ additional_condition = !s[3].nil? ? transpile(s[3]) : "end"
356
+ delim([
357
+ "#{keyword} " + transpile(s[1]),
358
+ s[2].map{|e| delim(transpile(e))}.join,
359
+ "#{additional_condition}"
360
+ ])
361
+
362
+ when :if_mod
363
+ delim([
364
+ "if " + transpile(s[1]),
365
+ transpile(s[2]),
366
+ "end"
367
+ ])
368
+
369
+ when :else
370
+ delim([
371
+ "else",
372
+ s[1].map{|e| delim(transpile(e))}.join,
373
+ "end"
374
+ ])
375
+
376
+ when :def
377
+ code=transpile(s[3])
378
+ globals_code=@globals.uniq.join(",")
379
+ @globals=[]
380
+ delim([
381
+ "function #{s[1][1]}(#{transpile(s[2][1])})",
382
+ (globals_code.length>0 ? delim("global #{globals_code}") : "") + code,
383
+ "end"
384
+ ])
385
+
386
+ when :params
387
+ s[1].nil? ? "" : s[1].map{|e| e[1]}.join(", ")
388
+
389
+ when :dot2, :dot3
390
+ "#{transpile(s[1])}:#{transpile(s[2])}"
391
+
392
+ when :aref, :aref_field
393
+ if !s[2].flatten.include?(:dot2) && !s[2].flatten.include?(:dot3) && s[2][1][0][0]!=:string_literal then
394
+ transpile(s[1]) + "[" + transpile(s[2]) + "+1]"
395
+ else
396
+ if s[2].flatten.include?(:dot2)
397
+ range = "#{transpile(s[2][1][0][1])}+1:#{transpile(s[2][1][0][2])}+1"
398
+ elsif s[2].flatten.include?(:dot3)
399
+ range = "#{transpile(s[2][1][0][1])}+1:#{transpile(s[2][1][0][2])}"
400
+ else
401
+ range = transpile(s[2])
402
+ end
403
+ transpile(s[1]) + "[" + range + "]"
404
+ end
405
+
406
+ when :const_path_ref
407
+ if s[1][1][1]=="Float"
408
+ case transpile(s[2])
409
+ when "NAN"
410
+ "NaN"
411
+ when "INFINITY"
412
+ "Inf"
413
+ when "EPSILON"
414
+ "eps()"
415
+ when "MAX"
416
+ "typemax(Float64)"
417
+ when "MIN"
418
+ "typemin(Float64)"
419
+ else
420
+ transpile(s[1])
421
+ end
422
+ else
423
+ transpile(s[1])
424
+ end
425
+
426
+ when :return
427
+ delim("return #{transpile(s[1])}")
428
+
429
+ else
430
+ transpile(s[1])
431
+
432
+ end
433
+
434
+ elsif s.instance_of?(Array) && s[0].instance_of?(Array) then
435
+ s.map{|e| transpile(e)}.join
436
+ end
437
+ end
438
+ end
439
+ end
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: julializer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Kei Sawada(@remore)
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-08-23 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: A ruby2julia transpiler with only limited types of syntax conversion
28
+ supported
29
+ email:
30
+ - k@swd.cc
31
+ executables:
32
+ - julializer
33
+ extensions: []
34
+ extra_rdoc_files: []
35
+ files:
36
+ - README.md
37
+ - Rakefile
38
+ - bin/julializer
39
+ - lib/julializer.rb
40
+ - lib/julializer/version.rb
41
+ homepage: https://github.com/remore/julializer
42
+ licenses:
43
+ - MIT
44
+ metadata: {}
45
+ post_install_message:
46
+ rdoc_options: []
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: 1.9.1
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ requirements: []
60
+ rubyforge_project:
61
+ rubygems_version: 2.5.1
62
+ signing_key:
63
+ specification_version: 4
64
+ summary: A ruby2julia transpiler with only limited types of syntax conversion supported
65
+ test_files: []