julializer 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.
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: []