asmrb 0.0.2.6.1.8 → 0.0.2.6.1.9
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/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:
|