asmrb 0.0.2.6.1.8 → 0.0.2.6.1.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/asmrb.rb +277 -61
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 151915b197bea335937f0343c7ad77572ac73a6d
|
4
|
+
data.tar.gz: 1463da6367aba6932894de04415c1714fd012200
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a38a19d27198ca21bdacb7a8aadb1e53437a9f1687802cacca44613877149051ac2bdd663eed9c2a71ff953dd24665512e3be45f78d861da3ab32ba877f484dd
|
7
|
+
data.tar.gz: 656d66a30c6bbd441ddc3250d2bb2fd37874a6acaaa2b7ef5f831e1c6d0e1609e78f5b58691f33dd30e86771c0a82331087e556cd39abe76f876a71cfffd2b02
|
data/lib/asmrb.rb
CHANGED
@@ -29,12 +29,14 @@ class Asmrb
|
|
29
29
|
# debug:
|
30
30
|
# => $rec_print.is_debug = true
|
31
31
|
#
|
32
|
-
#
|
32
|
+
# invoking:
|
33
33
|
# => $rec_print.invoke [1,2,3]
|
34
|
-
#
|
34
|
+
#
|
35
|
+
# calling:
|
36
|
+
# => rec_print [1,2,3]
|
35
37
|
#
|
36
38
|
|
37
|
-
attr_reader :variables, :stack, :source, :name, :result, :params,:is_debug
|
39
|
+
attr_reader :variables, :stack, :source, :name, :result, :params,:is_debug
|
38
40
|
attr_writer :is_debug
|
39
41
|
|
40
42
|
def initialize &block
|
@@ -42,6 +44,52 @@ class Asmrb
|
|
42
44
|
assemble &block unless block.nil?
|
43
45
|
end
|
44
46
|
|
47
|
+
def compiled?
|
48
|
+
!@source.nil?
|
49
|
+
end
|
50
|
+
|
51
|
+
def invoke *args
|
52
|
+
arguments args
|
53
|
+
execute is_debug
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_ruby
|
57
|
+
# need parititioning first..
|
58
|
+
partition
|
59
|
+
unless @partitions.empty?
|
60
|
+
@source = Array.new
|
61
|
+
block_labels = @partitions.map &:first
|
62
|
+
@entry_point = @partitions.first.first
|
63
|
+
@partitions.each.with_index do |partition, index|
|
64
|
+
define_block partition, index, block_labels
|
65
|
+
end
|
66
|
+
@source = @source.join "\n"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def all_ops
|
71
|
+
OPS.map do |k,v|
|
72
|
+
ops_info k
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def all_opcodes
|
77
|
+
puts "[OPCODES] check:".green
|
78
|
+
OPS.map do |k, v|
|
79
|
+
check = OPCODES.include?(k.to_sym) ? :implemented : :not_yet
|
80
|
+
report = ""
|
81
|
+
case check
|
82
|
+
when :implemented
|
83
|
+
report = "#{k} => #{check}".light_green
|
84
|
+
when :not_yet
|
85
|
+
report = "#{k} => #{check}".light_yellow
|
86
|
+
end
|
87
|
+
puts report
|
88
|
+
end
|
89
|
+
puts "-------------------------".green
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
45
93
|
def new_scope
|
46
94
|
@variables = {}
|
47
95
|
@source = []
|
@@ -53,7 +101,58 @@ class Asmrb
|
|
53
101
|
@pc = 0
|
54
102
|
@result = nil
|
55
103
|
@is_debug = false
|
56
|
-
@
|
104
|
+
@compile_stack = Array.new
|
105
|
+
end
|
106
|
+
|
107
|
+
def define_block partition, index, block_labels
|
108
|
+
func = partition.first
|
109
|
+
body = partition.last
|
110
|
+
args = body.first.first.to_sym == :arg ? body.first.last.join(', ') : ""
|
111
|
+
|
112
|
+
block = Array.new
|
113
|
+
block << "def #{func} #{args}"
|
114
|
+
indent = " " * 2
|
115
|
+
|
116
|
+
body.each do |statement|
|
117
|
+
# process statement here.
|
118
|
+
puts statement.to_s if @is_debug
|
119
|
+
if OPCODES.include? statement[0].to_sym
|
120
|
+
segment = self.instance_exec *statement[1], &OPCODES[statement[0].to_sym]
|
121
|
+
#binding.pry
|
122
|
+
block << (indent + segment.to_s) unless segment.nil?
|
123
|
+
else
|
124
|
+
puts "[define_block] Undefined OPCODE: #{statement[0]}\nAt: #{func}: #{statement}".red
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
make_jump_on_next block, block_labels, index, body
|
129
|
+
|
130
|
+
finalize_block block
|
131
|
+
end
|
132
|
+
|
133
|
+
def make_jump_on_next block, block_labels, index, body
|
134
|
+
# leave pointer of next function here:
|
135
|
+
if index != block_labels.length-1 && ![:rec, :ret, :exi].include?(body.last[0].to_sym)
|
136
|
+
func = block_labels[index+1]
|
137
|
+
body = @partitions[func].first
|
138
|
+
#binding.pry
|
139
|
+
if body.first.to_sym == :arg
|
140
|
+
args = "#{body.last.join(', ')}"
|
141
|
+
block << " #{func} #{args}"
|
142
|
+
else
|
143
|
+
block << " #{func}"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def finalize_block block
|
149
|
+
block << "end\n"
|
150
|
+
@source << block.join("\n")
|
151
|
+
|
152
|
+
if @is_debug
|
153
|
+
puts @source.last.light_yellow
|
154
|
+
puts "-------------------"
|
155
|
+
end
|
57
156
|
end
|
58
157
|
|
59
158
|
def refvar val
|
@@ -72,7 +171,7 @@ class Asmrb
|
|
72
171
|
OPS = {
|
73
172
|
"los" => lambda { | args |
|
74
173
|
args = @variables[args] if @variables.include?(args)
|
75
|
-
args.each {|arg| @stack.push arg}
|
174
|
+
args.reverse.each {|arg| @stack.push arg}
|
76
175
|
},
|
77
176
|
|
78
177
|
"lea" => lambda { | name |
|
@@ -91,7 +190,11 @@ class Asmrb
|
|
91
190
|
@stack.push @variables[lst].first
|
92
191
|
},
|
93
192
|
|
94
|
-
"
|
193
|
+
"map" => lambda { | ops |
|
194
|
+
eval "@stack.map(&:#{ops})"
|
195
|
+
},
|
196
|
+
|
197
|
+
"red" => lambda { | ops |
|
95
198
|
e = eval "@stack.reduce(:#{ops})"
|
96
199
|
@stack.clear
|
97
200
|
@stack.push e
|
@@ -147,29 +250,20 @@ class Asmrb
|
|
147
250
|
},
|
148
251
|
|
149
252
|
"jge" => lambda { |name|
|
150
|
-
req_args "jge",
|
151
|
-
@pc = @labels[name] if @stack.pop
|
253
|
+
req_args "jge", 2
|
254
|
+
@pc = @labels[name] if @stack.pop > @stack.pop
|
152
255
|
},
|
153
256
|
|
154
257
|
"jlt" => lambda { |name|
|
155
|
-
req_args "jlt",
|
156
|
-
@pc = @labels[name] if @stack.pop
|
258
|
+
req_args "jlt", 2
|
259
|
+
@pc = @labels[name] if @stack.pop < @stack.pop
|
157
260
|
},
|
158
261
|
|
159
262
|
"jeq" => lambda { |name|
|
160
|
-
req_args "jeq",
|
161
|
-
@pc = @labels[name] if @stack.pop ==
|
263
|
+
req_args "jeq", 2
|
264
|
+
@pc = @labels[name] if @stack.pop == @stack.pop
|
162
265
|
},
|
163
266
|
|
164
|
-
"cmp" => lambda {
|
165
|
-
a = @stack.pop
|
166
|
-
b = @stack.pop
|
167
|
-
@stack.push(
|
168
|
-
a > b ? :gt
|
169
|
-
: a == b ? :eq : :lt )
|
170
|
-
},
|
171
|
-
|
172
|
-
|
173
267
|
"jmp" => lambda { |name|
|
174
268
|
@pc = @labels[name]
|
175
269
|
new_title "[#{name}]" if @is_debug
|
@@ -203,18 +297,6 @@ class Asmrb
|
|
203
297
|
#binding.pry if @is_debug
|
204
298
|
},
|
205
299
|
|
206
|
-
"fnc" => lambda {|name|
|
207
|
-
args = []
|
208
|
-
params = eval "$#{name}.params"
|
209
|
-
params.times do
|
210
|
-
args << @stack.pop
|
211
|
-
end
|
212
|
-
eval "$#{name}.is_debug = true" if @is_debug
|
213
|
-
o = eval "$#{name}.invoke #{args.join(',')}"
|
214
|
-
@stack.push o if !o.nil?
|
215
|
-
#binding.pry
|
216
|
-
},
|
217
|
-
|
218
300
|
"inv" => lambda { |obj, f|
|
219
301
|
args = Array.new
|
220
302
|
@stack.each { args << @stack.pop } if @stack.length > 0
|
@@ -298,7 +380,6 @@ class Asmrb
|
|
298
380
|
puts "#{@pc}: #{instr[0]} #{instr[1].join " "}".light_green if debug
|
299
381
|
# execute proc: arg , proc
|
300
382
|
self.instance_exec *instr[1], &OPS[instr[0]]
|
301
|
-
#binding.pry if debug
|
302
383
|
@pc += 1
|
303
384
|
end
|
304
385
|
#binding.pry
|
@@ -356,12 +437,6 @@ class Asmrb
|
|
356
437
|
binding.pry if is_debug
|
357
438
|
end
|
358
439
|
|
359
|
-
def all_ops
|
360
|
-
OPS.map do |k,v|
|
361
|
-
ops_info k
|
362
|
-
end
|
363
|
-
end
|
364
|
-
|
365
440
|
def ops_info name
|
366
441
|
parameters = Array.new
|
367
442
|
OPS[name].parameters.each do |pair|
|
@@ -376,11 +451,6 @@ class Asmrb
|
|
376
451
|
end
|
377
452
|
end
|
378
453
|
|
379
|
-
def invoke(*args)
|
380
|
-
arguments args
|
381
|
-
execute is_debug
|
382
|
-
end
|
383
|
-
|
384
454
|
def clear
|
385
455
|
@pc = 0
|
386
456
|
@variables = { }
|
@@ -393,15 +463,25 @@ class Asmrb
|
|
393
463
|
eval "$#{@name}"
|
394
464
|
end
|
395
465
|
|
466
|
+
def collect_label_arg label
|
467
|
+
if @program[label.last+1].first.to_sym == :arg
|
468
|
+
@labels_arg[label.first] = @program[label.last+1].last
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
396
472
|
def partition
|
397
473
|
puts "partitioning...".light_green if@is_debug
|
398
474
|
if @labels.empty?
|
399
475
|
@partitions = { @name => @program }
|
400
476
|
else
|
401
477
|
@partitions = Hash.new
|
478
|
+
@labels_arg = Hash.new
|
402
479
|
@limitation = 0
|
403
480
|
@jump_points = @labels.map &:last
|
404
|
-
@labels.each.with_index do |label, label_index|
|
481
|
+
@labels.each.with_index do |label, label_index|
|
482
|
+
collect_label_arg label
|
483
|
+
# to save all args with a :blo ;)
|
484
|
+
|
405
485
|
if label_index != @jump_points.length-1
|
406
486
|
@limitation = @jump_points[label_index+1]
|
407
487
|
else
|
@@ -412,9 +492,8 @@ class Asmrb
|
|
412
492
|
# binding.pry
|
413
493
|
code_segment = @program[label.last+1..@limitation]
|
414
494
|
code_segment.each.with_index do |statement, index|
|
415
|
-
#break if [:rec].include? statement.first.to_sym
|
416
|
-
#binding.pry
|
417
495
|
partition << statement
|
496
|
+
|
418
497
|
puts (read_internal statement, index).light_yellow if @is_debug
|
419
498
|
end
|
420
499
|
@partitions[label.first] = partition.dup
|
@@ -428,46 +507,183 @@ class Asmrb
|
|
428
507
|
" #{index}: #{instruction.first}" +
|
429
508
|
" #{instruction.last.join(" ") unless instruction.last.empty?}"
|
430
509
|
end
|
510
|
+
|
511
|
+
def patched_arg label
|
512
|
+
"#{label} #{@labels_arg[label].join(', ') if @labels_arg.include?(label)}"
|
513
|
+
end
|
514
|
+
|
515
|
+
def opcode_operator op
|
516
|
+
@compile_stack.push "#{@compile_stack.pop} #{op} #{@compile_stack.pop}" if @compile_stack.length > 1
|
517
|
+
nil
|
518
|
+
end
|
519
|
+
|
520
|
+
def cond_jump op, label
|
521
|
+
return "if #{@compile_stack.pop} #{op} #{@compile_stack.pop}\n #{patched_arg label}\n end" if @compile_stack.length > 1
|
522
|
+
nil
|
523
|
+
end
|
524
|
+
|
525
|
+
def sole_cond_jump op, label
|
526
|
+
return "if #{@compile_stack.pop}#{op}\n #{patched_arg label}\n end" unless @compile_stack.empty?
|
527
|
+
nil
|
528
|
+
end
|
529
|
+
|
530
|
+
OPCODES = {
|
531
|
+
:dbg => lambda {|_|},
|
532
|
+
:req => lambda {|_|},
|
533
|
+
|
534
|
+
:map => lambda {|op| "#{@compile_stack}.map &:#{op}" },
|
535
|
+
:red => lambda {|op| "#{@compile_stack}.reduce :#{op}" },
|
536
|
+
|
537
|
+
:pop => lambda { @compile_stack.pop },
|
538
|
+
:icr => lambda {|arg| @compile_stack << "#{arg} = #{arg} + 1" },
|
539
|
+
:dcr => lambda {|arg| @compile_stack << "#{arg} = #{arg} - 1" },
|
540
|
+
|
541
|
+
:mov => lambda {|src, dest| "#{dest} = #{src}" },
|
542
|
+
:dpl => lambda { @compile_stack << @compile_stack.last },
|
543
|
+
|
544
|
+
:car => lambda {|arg| @compile_stack << "#{arg}.first" },
|
545
|
+
:cdr => lambda {|arg| @compile_stack << "#{arg}.drop(1)" },
|
546
|
+
:len => lambda {|arg| @compile_stack << "#{arg}.length" },
|
547
|
+
|
548
|
+
:arg => lambda {|*args|
|
549
|
+
# ignore it
|
550
|
+
},
|
551
|
+
:los => lambda {|*args|
|
552
|
+
args.reverse.each{|arg| @compile_stack << arg}
|
553
|
+
nil
|
554
|
+
},
|
555
|
+
:psh => lambda {|arg|
|
556
|
+
arg = "\"#{arg}\"" if arg.class == String
|
557
|
+
@compile_stack << arg
|
558
|
+
nil
|
559
|
+
},
|
560
|
+
:lea => lambda {|var|
|
561
|
+
return "#{var} = #{@compile_stack.pop}" unless @compile_stack.empty?
|
562
|
+
nil
|
563
|
+
},
|
564
|
+
:add => lambda { opcode_operator "+" },
|
565
|
+
:sub => lambda { opcode_operator "-" },
|
566
|
+
:mul => lambda { opcode_operator "*" },
|
567
|
+
:div => lambda { opcode_operator "/" },
|
568
|
+
:cal => lambda {|func|
|
569
|
+
_method = method func
|
570
|
+
if _method && _method.parameters.length > 0
|
571
|
+
args = Array.new
|
572
|
+
_method.parameters.length.times do
|
573
|
+
args.push @compile_stack.pop
|
574
|
+
end
|
575
|
+
return "#{func} #{args.join(', ')}"
|
576
|
+
else
|
577
|
+
return "#{func}"
|
578
|
+
end
|
579
|
+
},
|
580
|
+
:jmp => lambda {|label| "#{patched_arg label}"},
|
581
|
+
:jz => lambda {|label| sole_cond_jump " == 0", label },
|
582
|
+
:jnz => lambda {|label| sole_cond_jump " != 0", label },
|
583
|
+
:jnl => lambda {|label| sole_cond_jump ".nil?", label },
|
584
|
+
:jeq => lambda {|label| cond_jump "==", label },
|
585
|
+
:jge => lambda {|label| cond_jump ">", label },
|
586
|
+
:jlt => lambda {|label| cond_jump "<", label },
|
587
|
+
:rec => lambda {
|
588
|
+
"#{@entry_point} #{@labels_arg.first.last.length.times.collect{@compile_stack.pop}.reverse.join(', ')}"
|
589
|
+
},
|
590
|
+
:ret => lambda {
|
591
|
+
"return #{@compile_stack.pop unless @compile_stack.empty?}"
|
592
|
+
},
|
593
|
+
:exi => lambda {
|
594
|
+
"exit"
|
595
|
+
},
|
596
|
+
:inv => lambda {|obj, f|
|
597
|
+
begin
|
598
|
+
if method(f).parameters.length == 0
|
599
|
+
@compile_stack << "#{obj}.#{f}"
|
600
|
+
else
|
601
|
+
args = method(f).parameters.collect{@compile_stack.pop}
|
602
|
+
@compile_stack << "#{obj}.#{f} #{args.join(', ')}"
|
603
|
+
end
|
604
|
+
nil
|
605
|
+
rescue Exception => e
|
606
|
+
puts "[OPCODES]<inv> currently is not stable in compiling ruby mode.".red
|
607
|
+
end
|
608
|
+
}
|
609
|
+
}
|
431
610
|
end
|
432
611
|
|
433
|
-
# x = Asmrb.new do
|
612
|
+
# @x = Asmrb.new do
|
434
613
|
# fun :play
|
435
614
|
# arg :toy
|
436
615
|
# psh :toy
|
437
616
|
# cal :puts
|
438
617
|
|
439
618
|
# blo :after_print
|
440
|
-
# psh
|
619
|
+
# psh :@times
|
441
620
|
# jnl :init_timer
|
442
621
|
|
443
622
|
# blo :append
|
444
|
-
# inv
|
623
|
+
# inv :@times, :to_s
|
445
624
|
# psh "X"
|
446
625
|
# add
|
447
626
|
# cal :puts
|
448
627
|
|
449
628
|
# blo :count
|
450
|
-
# psh
|
629
|
+
# psh :@times
|
451
630
|
# psh 1
|
452
631
|
# add
|
453
|
-
# lea
|
454
|
-
# psh
|
632
|
+
# lea :@times
|
633
|
+
# psh :@times
|
455
634
|
# psh 10
|
456
|
-
# cmp
|
457
635
|
# jeq :final
|
458
636
|
# psh "__"
|
459
637
|
# rec
|
460
638
|
|
461
639
|
# blo :final
|
462
|
-
# psh
|
463
|
-
#
|
640
|
+
# psh "__"
|
641
|
+
# cal :puts
|
642
|
+
# inv :@times, :to_s
|
643
|
+
# psh "Final result = "
|
644
|
+
# add
|
645
|
+
# cal :puts
|
646
|
+
# exi
|
464
647
|
|
465
648
|
# blo :init_timer
|
466
649
|
# psh 0
|
467
|
-
# lea
|
650
|
+
# lea :@times
|
468
651
|
# jmp :append
|
469
652
|
# end
|
470
653
|
|
471
|
-
#x.is_debug =
|
472
|
-
#x.
|
473
|
-
#
|
654
|
+
# @x.is_debug = false
|
655
|
+
# test = @x.to_ruby
|
656
|
+
# puts test.light_green
|
657
|
+
# eval test
|
658
|
+
# play "I'm The Trung, here we go:"
|
659
|
+
|
660
|
+
# # applying: argumented block ( lambda )
|
661
|
+
# # should be "inline block" technique also,
|
662
|
+
# # to improve performance and local variable sharing.
|
663
|
+
# @y = Asmrb.new do
|
664
|
+
# fun :factorial
|
665
|
+
# arg :acc, :n
|
666
|
+
# los :n, 1
|
667
|
+
# jlt :final
|
668
|
+
|
669
|
+
# blo :cont
|
670
|
+
# arg :acc, :n
|
671
|
+
# los :n, :acc
|
672
|
+
# mul
|
673
|
+
# los :n, 1
|
674
|
+
# sub
|
675
|
+
# rec
|
676
|
+
|
677
|
+
# blo :final
|
678
|
+
# arg :acc
|
679
|
+
# psh :acc
|
680
|
+
# cal :puts
|
681
|
+
# exi # no return yet, because return doesn't mean anything inside a block. we can't escape.
|
682
|
+
# end
|
683
|
+
|
684
|
+
# @y.all_opcodes
|
685
|
+
# test = @y.to_ruby
|
686
|
+
#puts test
|
687
|
+
#eval test
|
688
|
+
#puts "Start test:"
|
689
|
+
#y = factorial 1, 1000
|
metadata
CHANGED
@@ -1,16 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: asmrb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.2.6.1.
|
4
|
+
version: 0.0.2.6.1.9
|
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-
|
11
|
+
date: 2015-05-14 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
|
-
description: create a assembly-like toy language in ruby DSL.
|
13
|
+
description: create a assembly-like toy language in ruby DSL. It can then compile
|
14
|
+
into ruby code.
|
14
15
|
email: deulamco@gmail.com
|
15
16
|
executables: []
|
16
17
|
extensions: []
|
@@ -40,6 +41,6 @@ rubyforge_project:
|
|
40
41
|
rubygems_version: 2.4.5
|
41
42
|
signing_key:
|
42
43
|
specification_version: 4
|
43
|
-
summary: assembly-like
|
44
|
+
summary: assembly-like Toy language
|
44
45
|
test_files: []
|
45
46
|
has_rdoc:
|