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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/lib/asmrb.rb +277 -61
  3. metadata +5 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6b206f0b382ffa2ab511a342452fa387fa77e542
4
- data.tar.gz: 3161af6af87ac4264de6fb8d00172f0c7a3471dd
3
+ metadata.gz: 151915b197bea335937f0343c7ad77572ac73a6d
4
+ data.tar.gz: 1463da6367aba6932894de04415c1714fd012200
5
5
  SHA512:
6
- metadata.gz: 522e99187befd8c7a1c336dc27bda590f1e6cd80a831815d6c83a309fbd475f7ff0c772be60b5450a7221753f68e1466be11624995b986eef816deb9fc4a9ec5
7
- data.tar.gz: abb44dd72d582f5323132c9661f9a12d6b83cc1829dec40f9fc83b09a870d8904cff61fa810eaa8f643973524ec6448b64275de653c7bae09d2f933917d19124
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
- # calling:
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, :is_compiled
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
- @is_compiled = false
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
- "rdu" => lambda { | ops |
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", 1
151
- @pc = @labels[name] if @stack.pop == :gt
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", 1
156
- @pc = @labels[name] if @stack.pop == :lt
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", 1
161
- @pc = @labels[name] if @stack.pop == :eq
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 :times
619
+ # psh :@times
441
620
  # jnl :init_timer
442
621
 
443
622
  # blo :append
444
- # inv :times, :to_s
623
+ # inv :@times, :to_s
445
624
  # psh "X"
446
625
  # add
447
626
  # cal :puts
448
627
 
449
628
  # blo :count
450
- # psh :times
629
+ # psh :@times
451
630
  # psh 1
452
631
  # add
453
- # lea :times
454
- # psh :times
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 :times
463
- # ret
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 :times
650
+ # lea :@times
468
651
  # jmp :append
469
652
  # end
470
653
 
471
- #x.is_debug = true
472
- #x.partition
473
- #x.invoke "I'm The Trung, here we go:"
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.8
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-12 00:00:00.000000000 Z
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 DSL toy in ruby
44
+ summary: assembly-like Toy language
44
45
  test_files: []
45
46
  has_rdoc: