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.
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: