asmrb 0.0.2.6.2.1 → 0.0.2.6.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +143 -0
- data/bin/asmrb +30 -0
- data/lib/asmrb.rb +120 -82
- data/lib/ast.rb +3 -0
- data/lib/llvm_sample.rb +109 -0
- metadata +58 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d060fb46ed0c1da76426e94cc0f8a315cb5b5464
|
4
|
+
data.tar.gz: 2dd5ec988a198e5ef3b432dd1a1edc27d671f79e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6985a71aa49990685e5d6af7023ff03cac9439bea40ff1c2427921eac17880437a8d151926f21e68f1f7ddef65927ba383f2629446f077d898652aded36f8dd8
|
7
|
+
data.tar.gz: a4d2eaa1eb1b368b41577bd2ed192cf478a612dfb08f045006ce58d94c21c7e71e369bccaab0fc12aad71596ad58deac54c26be55fae4a630e9c38e47d1f6398
|
data/README.md
ADDED
@@ -0,0 +1,143 @@
|
|
1
|
+
asmrb
|
2
|
+
=======
|
3
|
+
|
4
|
+
I. Intro
|
5
|
+
|
6
|
+
Asmrb is my intend over making a high-level assembly language.
|
7
|
+
Which shorten your horizonal source, better flow and readability.
|
8
|
+
|
9
|
+
And to solve my question about how recursion loop through assembly
|
10
|
+
by just jumping from label to label.
|
11
|
+
|
12
|
+
Have fun !
|
13
|
+
|
14
|
+
Just a prototype, play around if you know Ruby.
|
15
|
+
Get the Gem: https://rubygems.org/gems/asmrb
|
16
|
+
|
17
|
+
II. Install
|
18
|
+
|
19
|
+
\* asmrb is at very early state of experiment,
|
20
|
+
so all required gems would be pretty light-weight
|
21
|
+
and just for debugging and colorful printing.
|
22
|
+
|
23
|
+
gem install asmrb
|
24
|
+
|
25
|
+
III. Usage
|
26
|
+
|
27
|
+
Let's create one as below:
|
28
|
+
|
29
|
+
a = Asmrb.new do
|
30
|
+
fun :rec_print # define a function, also label to jump.
|
31
|
+
arg arr # arguments
|
32
|
+
psh 0
|
33
|
+
len arr # get length of arr as array
|
34
|
+
jge :print # then jump to :print block
|
35
|
+
ret # else, jump to :exit block
|
36
|
+
blo :print # start of :print
|
37
|
+
car arr # get out first element of arr
|
38
|
+
cal :puts # call ruby's puts
|
39
|
+
cdr arr # get rest of arr Array to @stack
|
40
|
+
rec # jump back to :rec_print ( or start of this _fntion )
|
41
|
+
end
|
42
|
+
|
43
|
+
toggle the debug mode to see steps:
|
44
|
+
|
45
|
+
a.is_debug = true
|
46
|
+
|
47
|
+
invoke it with right arugument type:
|
48
|
+
|
49
|
+
a.invoke [1, 2]
|
50
|
+
|
51
|
+
convert it to ruby code:
|
52
|
+
|
53
|
+
a.to_ruby
|
54
|
+
|
55
|
+
Asmrb can run "infinite recursion" without being overflow,
|
56
|
+
by storing value with its own stack.
|
57
|
+
|
58
|
+
Look at "rake test" for more samples.
|
59
|
+
|
60
|
+
\* Execute source file:
|
61
|
+
|
62
|
+
To execute a source file like `demo.arb`:
|
63
|
+
|
64
|
+
asmrb demo.arb
|
65
|
+
|
66
|
+
VI. Features
|
67
|
+
|
68
|
+
* I actually created asmrb to see how it change the coding style
|
69
|
+
while still remain all high-level ruby functions. There're early
|
70
|
+
plans on making LLVM underhood to improve overall performance,
|
71
|
+
or just compiling down to ruby for maximum compatiability and
|
72
|
+
go on with all ruby implementations.
|
73
|
+
|
74
|
+
\* currently implemented:
|
75
|
+
|
76
|
+
Note: to see all implemented operators, run:
|
77
|
+
Asmrb.new.all_ops
|
78
|
+
|
79
|
+
\* operations:
|
80
|
+
|
81
|
+
all ops follow the rule:
|
82
|
+
|
83
|
+
psh 2
|
84
|
+
psh 1
|
85
|
+
add # push (1 + 2) to stack
|
86
|
+
|
87
|
+
|
88
|
+
to remove top-most element off stack:
|
89
|
+
|
90
|
+
psh 1
|
91
|
+
pop
|
92
|
+
|
93
|
+
same to above, when pushed values:
|
94
|
+
|
95
|
+
sub # 1 - 2
|
96
|
+
add # 1 + 2
|
97
|
+
mul # 1 * 2
|
98
|
+
div # 1 / 2
|
99
|
+
icr a # a = a + 1
|
100
|
+
dcr a # a = a - 1
|
101
|
+
dpl # duplicate top-most value on stack
|
102
|
+
|
103
|
+
\* array:
|
104
|
+
|
105
|
+
car arr # get first element of array
|
106
|
+
cdr arr # get rest element of array
|
107
|
+
len arr # get length of array
|
108
|
+
los arr # load all array elements on stack
|
109
|
+
los :a # load all elements in :a variable
|
110
|
+
|
111
|
+
\* jump:
|
112
|
+
|
113
|
+
blo :name # create a label/block
|
114
|
+
|
115
|
+
jlt :label # jump if a < b
|
116
|
+
jge :label # jump if a > b
|
117
|
+
jeq :label # jump if a = b
|
118
|
+
jnz :label # jump if not zero
|
119
|
+
jmp :label # jump to certain labeled immediately
|
120
|
+
jnl :label # jump if nil
|
121
|
+
|
122
|
+
\* function define:
|
123
|
+
|
124
|
+
fun :function # define function name and also a label to jump.
|
125
|
+
arg a,b # function parameters binded to a and b.
|
126
|
+
req 3 # function require 3 arguments.
|
127
|
+
rec # to recursively call function again.
|
128
|
+
lea :a # load top-most value to variable a
|
129
|
+
|
130
|
+
\* high-level:
|
131
|
+
|
132
|
+
mov 1, :a # there is still this, but it will soon be removed.
|
133
|
+
|
134
|
+
|
135
|
+
red :+ # reduce current stack frame by :+ operator
|
136
|
+
map :o # map as usual to current stack
|
137
|
+
cal :puts # calling ruby function
|
138
|
+
|
139
|
+
inv :a, :f # invoke function "f" of object "a" with n "args"
|
140
|
+
|
141
|
+
dbg # debug by pry at local instruction
|
142
|
+
ret # exit and return top-most stack value
|
143
|
+
exi # force exit
|
data/bin/asmrb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
dir = File.expand_path(File.dirname(__FILE__))
|
3
|
+
require dir + '/../lib/asmrb.rb'
|
4
|
+
|
5
|
+
require 'oyster'
|
6
|
+
spec = Oyster.spec do
|
7
|
+
name "asmrb -- Lisp to ruby transformation"#, v. #{Heist::VERSION}"
|
8
|
+
author 'The Trung <deulamco@mail.com>'
|
9
|
+
|
10
|
+
synopsis <<-EOS
|
11
|
+
asmrb -i [OPTIONS]
|
12
|
+
asmrb FILE_NAME [OPTIONS]
|
13
|
+
EOS
|
14
|
+
|
15
|
+
flag :interactive, :desc =>
|
16
|
+
'Start an interactive Scheme session'
|
17
|
+
end
|
18
|
+
|
19
|
+
|
20
|
+
begin
|
21
|
+
options = spec.parse
|
22
|
+
|
23
|
+
if options[:interactive] or options[:unclaimed].empty?
|
24
|
+
puts "Not implemented yet"
|
25
|
+
else
|
26
|
+
Asmrb.new.eval_file File.expand_path(options[:unclaimed].first)
|
27
|
+
end
|
28
|
+
|
29
|
+
rescue Oyster::HelpRendered
|
30
|
+
end
|
data/lib/asmrb.rb
CHANGED
@@ -44,6 +44,24 @@ class Asmrb
|
|
44
44
|
assemble &block unless block.nil?
|
45
45
|
end
|
46
46
|
|
47
|
+
def eval_file path
|
48
|
+
source = File.read path
|
49
|
+
eval_source source
|
50
|
+
end
|
51
|
+
|
52
|
+
def eval_source source
|
53
|
+
new_scope
|
54
|
+
puts source.light_yellow
|
55
|
+
eval <<-CODE
|
56
|
+
assemble do
|
57
|
+
#{source}
|
58
|
+
end
|
59
|
+
CODE
|
60
|
+
compiled = to_ruby
|
61
|
+
puts compiled.magenta
|
62
|
+
eval compiled
|
63
|
+
end
|
64
|
+
|
47
65
|
def compiled?
|
48
66
|
!@ruby_source.nil?
|
49
67
|
end
|
@@ -57,7 +75,6 @@ class Asmrb
|
|
57
75
|
# need parititioning first..
|
58
76
|
partition
|
59
77
|
unless @partitions.empty?
|
60
|
-
@compile_stack = Array.new
|
61
78
|
@ruby_source = Array.new
|
62
79
|
block_labels = @partitions.map &:first
|
63
80
|
@entry_point = @partitions.first.first
|
@@ -74,7 +91,7 @@ class Asmrb
|
|
74
91
|
end
|
75
92
|
end
|
76
93
|
|
77
|
-
def
|
94
|
+
def all_opcodes
|
78
95
|
puts "[OPCODES] check:".green
|
79
96
|
OPS.map do |k, v|
|
80
97
|
check = OPCODES.include?(k.to_sym) ? :implemented : :not_yet
|
@@ -136,7 +153,6 @@ class Asmrb
|
|
136
153
|
def define_block partition, index, block_labels
|
137
154
|
func = partition.first
|
138
155
|
body = partition.last
|
139
|
-
|
140
156
|
args = body.first.first.to_sym == :arg ? body.first.last.join(', ') : ""
|
141
157
|
|
142
158
|
block = Array.new
|
@@ -165,10 +181,8 @@ class Asmrb
|
|
165
181
|
if index != block_labels.length-1 && ![:rec, :ret, :exi].include?(body.last[0].to_sym)
|
166
182
|
func = block_labels[index+1]
|
167
183
|
body = @partitions[func].first
|
168
|
-
|
169
184
|
#binding.pry
|
170
|
-
|
171
|
-
if body.first == :arg
|
185
|
+
if body.first.to_sym == :arg
|
172
186
|
args = "#{body.last.join(', ')}"
|
173
187
|
block << " #{func} #{args}"
|
174
188
|
else
|
@@ -181,7 +195,10 @@ class Asmrb
|
|
181
195
|
block << "end\n"
|
182
196
|
@ruby_source << block.join("\n")
|
183
197
|
|
184
|
-
|
198
|
+
if @is_debug
|
199
|
+
puts @source.last.join(" ").light_yellow
|
200
|
+
puts "-------------------"
|
201
|
+
end
|
185
202
|
end
|
186
203
|
|
187
204
|
def refvar val
|
@@ -199,17 +216,9 @@ class Asmrb
|
|
199
216
|
|
200
217
|
OPS = {
|
201
218
|
:slp => lambda { |amount| sleep amount},
|
202
|
-
:los => lambda { |
|
203
|
-
args = args.
|
204
|
-
|
205
|
-
@variables[arg]
|
206
|
-
else
|
207
|
-
arg
|
208
|
-
end
|
209
|
-
end
|
210
|
-
args.reverse.each do |arg|
|
211
|
-
@stack.push arg
|
212
|
-
end
|
219
|
+
:los => lambda { | args |
|
220
|
+
args = @variables[args] if @variables.include?(args)
|
221
|
+
args.reverse.each {|arg| @stack.push arg}
|
213
222
|
},
|
214
223
|
|
215
224
|
:lea => lambda { | name |
|
@@ -258,51 +267,32 @@ class Asmrb
|
|
258
267
|
|
259
268
|
:jnl => lambda { | name |
|
260
269
|
req_args "jnl", 1
|
261
|
-
if @stack.pop.nil?
|
262
|
-
@pc = @labels[name]
|
263
|
-
new_title "[#{name}]" if @is_debug
|
264
|
-
end
|
270
|
+
@pc = @labels[name] if @stack.pop.nil?
|
265
271
|
},
|
266
272
|
|
267
273
|
:jz => lambda { | name |
|
268
274
|
req_args "jz", 1
|
269
|
-
if @stack.pop == 0
|
270
|
-
@pc = @labels[name]
|
271
|
-
new_title "[#{name}]" if @is_debug
|
272
|
-
end
|
275
|
+
@pc = @labels[name] if @stack.pop == 0
|
273
276
|
},
|
274
277
|
|
275
278
|
:jnz => lambda { | name |
|
276
279
|
req_args "jnz", 1
|
277
|
-
if @stack.pop != 0
|
278
|
-
@pc = @labels[name]
|
279
|
-
new_title "[#{name}]" if @is_debug
|
280
|
-
end
|
280
|
+
@pc = @labels[name] if @stack.pop != 0
|
281
281
|
},
|
282
282
|
|
283
283
|
:jge => lambda { |name|
|
284
284
|
req_args "jge", 2
|
285
|
-
if @stack.pop > @stack.pop
|
286
|
-
@pc = @labels[name]
|
287
|
-
new_title "[#{name}]" if @is_debug
|
288
|
-
end
|
285
|
+
@pc = @labels[name] if @stack.pop > @stack.pop
|
289
286
|
},
|
290
287
|
|
291
288
|
:jlt => lambda { |name|
|
292
289
|
req_args "jlt", 2
|
293
|
-
if @stack.pop < @stack.pop
|
294
|
-
@pc = @labels[name]
|
295
|
-
new_title "[#{name}]" if @is_debug
|
296
|
-
end
|
297
|
-
|
290
|
+
@pc = @labels[name] if @stack.pop < @stack.pop
|
298
291
|
},
|
299
292
|
|
300
293
|
:jeq => lambda { |name|
|
301
294
|
req_args "jeq", 2
|
302
|
-
if @stack.pop == @stack.pop
|
303
|
-
@pc = @labels[name]
|
304
|
-
new_title "[#{name}]" if @is_debug
|
305
|
-
end
|
295
|
+
@pc = @labels[name] if @stack.pop == @stack.pop
|
306
296
|
},
|
307
297
|
|
308
298
|
:jmp => lambda { |name|
|
@@ -363,7 +353,6 @@ class Asmrb
|
|
363
353
|
},
|
364
354
|
:rec => lambda {
|
365
355
|
@pc = -1
|
366
|
-
new_title "[#{@name}]" if @is_debug
|
367
356
|
},
|
368
357
|
|
369
358
|
:ret => lambda {
|
@@ -416,19 +405,17 @@ class Asmrb
|
|
416
405
|
puts "#{@stack} > #{@name}".yellow if debug
|
417
406
|
begin
|
418
407
|
@pc = 0
|
419
|
-
@variables = Hash.new
|
420
408
|
until @pc == @program.length
|
421
|
-
|
409
|
+
# get instruction:
|
422
410
|
instr = @program[@pc]
|
423
|
-
|
424
411
|
puts "#{@pc}: #{instr[0]} #{instr[1].join " "}".light_green if debug
|
425
|
-
|
412
|
+
# execute proc: arg , proc
|
426
413
|
self.instance_exec *instr[1], &OPS[instr[0]]
|
427
|
-
|
428
414
|
@pc += 1
|
429
415
|
end
|
416
|
+
#binding.pry
|
430
417
|
@result = @stack.last
|
431
|
-
|
418
|
+
clear
|
432
419
|
rescue Exception => e
|
433
420
|
debug e, instr
|
434
421
|
end
|
@@ -436,6 +423,20 @@ class Asmrb
|
|
436
423
|
@result
|
437
424
|
end
|
438
425
|
|
426
|
+
def fast_execute *args
|
427
|
+
arguments args
|
428
|
+
@pc = 0
|
429
|
+
until @pc == @program.length
|
430
|
+
# execute proc:
|
431
|
+
self.instance_exec *@program[@pc].last,
|
432
|
+
&OPS[@program[@pc].first]
|
433
|
+
@pc += 1
|
434
|
+
end
|
435
|
+
@result = @stack.last
|
436
|
+
clear
|
437
|
+
@result
|
438
|
+
end
|
439
|
+
|
439
440
|
def new_title title
|
440
441
|
puts "\n::#{title}"
|
441
442
|
end
|
@@ -457,7 +458,6 @@ class Asmrb
|
|
457
458
|
(scope_begin..scope_end).each do | i |
|
458
459
|
instr = @program[i]
|
459
460
|
color = i != @pc ? :light_green : :magenta
|
460
|
-
binding.pry
|
461
461
|
puts "#{i}: #{instr[0]} #{instr[1]}".colorize color
|
462
462
|
end
|
463
463
|
unless instr.nil?
|
@@ -483,6 +483,12 @@ class Asmrb
|
|
483
483
|
end
|
484
484
|
end
|
485
485
|
|
486
|
+
def clear
|
487
|
+
@pc = 0
|
488
|
+
@variables = { }
|
489
|
+
@stack = []
|
490
|
+
end
|
491
|
+
|
486
492
|
def assemble &block
|
487
493
|
extend_program &block
|
488
494
|
eval "$#{@name} = self.clone"
|
@@ -535,16 +541,7 @@ class Asmrb
|
|
535
541
|
end
|
536
542
|
|
537
543
|
def patched_arg label
|
538
|
-
|
539
|
-
if @labels_arg.include? label
|
540
|
-
patched = "#{label}(#{@labels_arg[label].join(', ')})"
|
541
|
-
else
|
542
|
-
patched = "#{label}"
|
543
|
-
end
|
544
|
-
if !@partitions[label].nil? && @partitions[label].last.first == :ret
|
545
|
-
patched = "return " + patched
|
546
|
-
end
|
547
|
-
patched
|
544
|
+
"#{label} #{@labels_arg[label].join(', ') if @labels_arg.include?(label)}"
|
548
545
|
end
|
549
546
|
|
550
547
|
def opcode_operator op
|
@@ -567,7 +564,7 @@ class Asmrb
|
|
567
564
|
end
|
568
565
|
|
569
566
|
OPCODES = {
|
570
|
-
:
|
567
|
+
:sleep => lambda {|amount| "sleep #{amount}"},
|
571
568
|
:dbg => lambda {"binding.pry"},
|
572
569
|
:req => lambda {|_|},
|
573
570
|
|
@@ -649,39 +646,80 @@ class Asmrb
|
|
649
646
|
}
|
650
647
|
end
|
651
648
|
|
652
|
-
|
653
|
-
|
654
|
-
|
649
|
+
# demo for testing
|
650
|
+
# @x = Asmrb.new do
|
651
|
+
# fun :play
|
652
|
+
# arg :toy
|
653
|
+
# psh :toy
|
654
|
+
# cal :puts
|
655
|
+
|
656
|
+
# blo :after_print
|
657
|
+
# psh :@times
|
658
|
+
# jnl :init_timer
|
659
|
+
|
660
|
+
# blo :append
|
661
|
+
# inv :@times, :to_s
|
662
|
+
# psh "X"
|
663
|
+
# add
|
664
|
+
# cal :puts
|
665
|
+
|
666
|
+
# blo :count
|
667
|
+
# psh :@times
|
668
|
+
# psh 1
|
669
|
+
# add
|
670
|
+
# lea :@times
|
671
|
+
# psh :@times
|
672
|
+
# psh 10
|
673
|
+
# jeq :final
|
674
|
+
# psh "__"
|
675
|
+
# rec
|
676
|
+
|
677
|
+
# blo :final
|
678
|
+
# psh "__"
|
679
|
+
# cal :puts
|
680
|
+
# inv :@times, :to_s
|
681
|
+
# psh "Final result = "
|
682
|
+
# add
|
683
|
+
# cal :puts
|
684
|
+
# exi
|
685
|
+
|
686
|
+
# blo :init_timer
|
687
|
+
# psh 0
|
688
|
+
# lea :@times
|
689
|
+
# jmp :append
|
690
|
+
# end
|
691
|
+
|
692
|
+
# @x.is_debug = false
|
693
|
+
# test = @x.to_ruby
|
694
|
+
# puts test.light_green
|
695
|
+
# eval test
|
696
|
+
# play "I'm The Trung, here we go:"
|
655
697
|
|
656
698
|
# # applying: argumented block ( lambda )
|
657
699
|
# # should be "inline block" technique also,
|
658
700
|
# # to improve performance and local variable sharing.
|
659
|
-
# @
|
701
|
+
# @f = Asmrb.new do
|
660
702
|
# fun :factorial
|
661
703
|
# arg :acc, :n
|
662
|
-
# los :acc, :n
|
663
704
|
# los :n, 1
|
664
|
-
# jlt :
|
705
|
+
# jlt :final
|
665
706
|
|
666
|
-
# blo :
|
707
|
+
# blo :cont
|
667
708
|
# arg :acc, :n
|
668
|
-
# los :
|
709
|
+
# los :n, :acc
|
669
710
|
# mul
|
670
711
|
# los :n, 1
|
671
712
|
# sub
|
672
|
-
# rec
|
673
|
-
|
674
|
-
# blo :
|
713
|
+
# rec
|
714
|
+
|
715
|
+
# blo :final
|
675
716
|
# arg :acc
|
676
717
|
# psh :acc
|
677
|
-
#
|
718
|
+
# cal :puts
|
719
|
+
# exi # no return yet, because return doesn't mean anything inside a block. we can't escape.
|
678
720
|
# end
|
679
721
|
|
680
|
-
#
|
681
|
-
# puts
|
682
|
-
#
|
683
|
-
#
|
684
|
-
# puts test
|
685
|
-
# eval test
|
686
|
-
# @y = factorial 1, 1000
|
687
|
-
# puts "Start test: #{@y}"
|
722
|
+
# source = @f.to_ruby
|
723
|
+
# puts source
|
724
|
+
# eval source
|
725
|
+
# factorial 1, 3
|
data/lib/ast.rb
ADDED
data/lib/llvm_sample.rb
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'llvm/core'
|
2
|
+
require 'llvm/execution_engine'
|
3
|
+
require 'llvm/transforms/scalar'
|
4
|
+
require "benchmark"
|
5
|
+
require 'asmrb'
|
6
|
+
|
7
|
+
# run this with any argument to get a speed comparison between llvm and different ruby implementations
|
8
|
+
|
9
|
+
# Start the "engine" before driving
|
10
|
+
LLVM.init_jit
|
11
|
+
|
12
|
+
# modules hold functions and variables
|
13
|
+
mod = LLVM::Module.new("Factorial")
|
14
|
+
|
15
|
+
mod.functions.add("fac", [LLVM::Int], LLVM::Int) do |fac, n|
|
16
|
+
n.name = "n"
|
17
|
+
entry = fac.basic_blocks.append("entry")
|
18
|
+
recur = fac.basic_blocks.append("recur")
|
19
|
+
result = fac.basic_blocks.append("result")
|
20
|
+
n_fac_n_1 = nil # predeclare within function's scope
|
21
|
+
|
22
|
+
entry.build do |b|
|
23
|
+
test = b.icmp(:eq, n, LLVM::Int(1), "test")
|
24
|
+
b.cond(test, result, recur)
|
25
|
+
end
|
26
|
+
|
27
|
+
recur.build do |b|
|
28
|
+
n_1 = b.sub(n, LLVM::Int(1), "n-1")
|
29
|
+
fac_n_1 = b.call(fac, n_1, "fac(n-1)")
|
30
|
+
n_fac_n_1 = b.mul(n, fac_n_1, "n*fac(n-1)")
|
31
|
+
b.br(result)
|
32
|
+
end
|
33
|
+
|
34
|
+
result.build do |b|
|
35
|
+
fac = b.phi(LLVM::Int,
|
36
|
+
{ entry => LLVM::Int(1),
|
37
|
+
recur => n_fac_n_1 },
|
38
|
+
"fac")
|
39
|
+
b.ret(fac)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
mod.verify
|
44
|
+
mod.dump
|
45
|
+
|
46
|
+
engine = LLVM::JITCompiler.new(mod)
|
47
|
+
|
48
|
+
def rec_factorial(n)
|
49
|
+
if n <= 1
|
50
|
+
1
|
51
|
+
else
|
52
|
+
n * rec_factorial(n - 1);
|
53
|
+
end
|
54
|
+
end
|
55
|
+
def iter_factorial(n)
|
56
|
+
nn = n
|
57
|
+
i = n - 1
|
58
|
+
while(i > 1) do
|
59
|
+
nn *= i
|
60
|
+
i -= 1
|
61
|
+
end
|
62
|
+
return nn;
|
63
|
+
end
|
64
|
+
def array_factorial(n)
|
65
|
+
(1..n).inject(:*)
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
Asm.new do
|
70
|
+
defn :factorial
|
71
|
+
arg acc, n
|
72
|
+
push 1
|
73
|
+
push n
|
74
|
+
cmp
|
75
|
+
jge :recursion
|
76
|
+
jmp :exit
|
77
|
+
|
78
|
+
label :recursion
|
79
|
+
push acc
|
80
|
+
push n
|
81
|
+
mul
|
82
|
+
push 1
|
83
|
+
push n
|
84
|
+
sub
|
85
|
+
jmp :factorial
|
86
|
+
label :exit
|
87
|
+
push acc
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
if( ARGV.length == 0 )
|
92
|
+
puts "Single run with 42 = " + engine.run_function(mod.functions["fac"], 42).to_i.to_s
|
93
|
+
exit
|
94
|
+
end
|
95
|
+
puts "Times show factorial execution times in milliseconds.".light_green
|
96
|
+
puts "Both for llvm and ruby iterative and recusive algorithms".light_green
|
97
|
+
puts ["Num" , "llvm rec","recursive" ,"iterative","array iter", "asmrb"].collect{|u|u.ljust(11)}.join
|
98
|
+
res = [ 1, 5 , 20 , 50 , 100 , 200 , 500 , 1000 , 2000 , 5000, 8710 ].each do |i|
|
99
|
+
res = [ ]
|
100
|
+
res << Benchmark.realtime {engine.run_function(mod.functions["fac"], i)}
|
101
|
+
res << Benchmark.realtime {rec_factorial(i)}
|
102
|
+
res << Benchmark.realtime {iter_factorial(i) }
|
103
|
+
res << Benchmark.realtime {array_factorial(i) }
|
104
|
+
res << Benchmark.realtime {$factorial.invoke(1,i)}
|
105
|
+
res = [i] + res.collect {|u| ((u*1000)).round(4) }
|
106
|
+
res = res.collect {|z| z.to_s.ljust(8)}
|
107
|
+
next if i < 10
|
108
|
+
puts res.join(" ")
|
109
|
+
end
|
metadata
CHANGED
@@ -1,29 +1,80 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asmrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.2.6.2.
|
4
|
+
version: 0.0.2.6.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- The Trung
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-05-
|
12
|
-
dependencies:
|
11
|
+
date: 2015-05-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pry
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: oyster
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: colorize
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
13
55
|
description: create a assembly-like toy language in ruby DSL. It can then compile
|
14
|
-
into ruby code.
|
56
|
+
into ruby code. * note that I have stopped this gem development, since I saw no
|
57
|
+
potential to make it further. Have fun playing around with it!
|
15
58
|
email: deulamco@gmail.com
|
16
|
-
executables:
|
59
|
+
executables:
|
60
|
+
- asmrb
|
17
61
|
extensions: []
|
18
|
-
extra_rdoc_files:
|
62
|
+
extra_rdoc_files:
|
63
|
+
- README.md
|
19
64
|
files:
|
65
|
+
- README.md
|
66
|
+
- bin/asmrb
|
20
67
|
- lib/asmrb.rb
|
68
|
+
- lib/ast.rb
|
69
|
+
- lib/llvm_sample.rb
|
21
70
|
homepage: http://github.com/thetrung/asmrb.git
|
22
71
|
licenses:
|
23
72
|
- MIT
|
24
73
|
metadata: {}
|
25
74
|
post_install_message:
|
26
|
-
rdoc_options:
|
75
|
+
rdoc_options:
|
76
|
+
- "--main"
|
77
|
+
- README.md
|
27
78
|
require_paths:
|
28
79
|
- lib
|
29
80
|
required_ruby_version: !ruby/object:Gem::Requirement
|