asmrb 0.0.2.6.2.1 → 0.0.2.6.2.2
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 +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
|