Решение на Четвърта задача от Ясен Трифонов

Обратно към всички решения

Към профила на Ясен Трифонов

Резултати

  • 0 точки от тестове
  • 0 бонус точки
  • 0 точки общо
  • 0 успешни тест(а)
  • 8 неуспешни тест(а)

Код

module Asm
def Asm.asm(&block)
Assembler.new.assemble &block
end
class Assembler
attr_reader :memory, :labels
def initialize
@labels = {}
@memory = { ax: 0, bx: 0, cx: 0, dx: 0 }
@program = []
end
INSTRUCTIONS = {
"mov" => lambda { |register, src|
@memory[register] = (src.is_a?(Symbol) ? @memory[src] : src)
nil
},
"inc" => lambda { |register, value = 1|
value = @memory[value] if @memory.keys.index value
@memory[register] += value
nil
},
"dec" => lambda { |register, value = 1|
value = @memory[value] if @memory.keys.index value
@memory[register] -= value
nil
},
"cmp" => lambda { |register, value|
value = @memory[value] if @memory.keys.index value
@last_cmp = @memory[register] <=> value
nil
},
"jmp" => lambda { |destination| jump_to destination },
"je" => lambda { |destination| jump_to destination if @last_cmp == 0 },
"jne" => lambda { |destination| jump_to destination if @last_cmp != 0 },
"jl" => lambda { |destination| jump_to destination if @last_cmp < 0 },
"jle" => lambda { |destination| jump_to destination if @last_cmp <= 0 },
"jg" => lambda { |destination| jump_to destination if @last_cmp > 0 },
"jge" => lambda { |destination| jump_to destination if @last_cmp >= 0 }
}
def jump_to(destination)
@labels.keys.index(destination) ? @labels[destination] : destination
end
def method_missing(name, *args)
if INSTRUCTIONS.keys.include? name.to_s
@program << [name.to_s, args]
elsif name.to_s == "label"
@labels[args.first] = @program.size
else
name
end
end
def parse(&block)
self.instance_eval &block
end
def run
pc = 0
until pc == @program.length
instruction = @program[pc]
retval = instance_exec(*instruction[1], &INSTRUCTIONS[instruction[0]])
if retval
pc = retval
else
pc += 1
end
end
end
def assemble(&block)
parse &block
run
@memory
end
end
end

Лог от изпълнението

FFFFFFFF

Failures:

  1) Asm.asm works with empty programs
     Failure/Error: Asm.asm {}.should eq [0, 0, 0, 0]
       
       expected: [0, 0, 0, 0]
            got: {:ax=>0, :bx=>0, :cx=>0, :dx=>0}
       
       (compared using ==)
     # /tmp/d20140115-8451-10r0f00/spec.rb:3:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  2) Asm.asm implements MOV
     Failure/Error: Asm.asm do
       
       expected: [3, 4, 3, 0]
            got: {:ax=>3, :bx=>4, :cx=>3, :dx=>0}
       
       (compared using ==)
     # /tmp/d20140115-8451-10r0f00/spec.rb:7:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  3) Asm.asm implements INC
     Failure/Error: Asm.asm do
       
       expected: [1, 3, 3, 0]
            got: {:ax=>1, :bx=>3, :cx=>3, :dx=>0}
       
       (compared using ==)
     # /tmp/d20140115-8451-10r0f00/spec.rb:15:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  4) Asm.asm implements DEC
     Failure/Error: Asm.asm do
       
       expected: [2, 2, 5, 0]
            got: {:ax=>2, :bx=>2, :cx=>5, :dx=>0}
       
       (compared using ==)
     # /tmp/d20140115-8451-10r0f00/spec.rb:23:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  5) Asm.asm implements CMP
     Failure/Error: Asm.asm do
       
       expected: [2, 2, 0, 3]
            got: {:ax=>2, :bx=>2, :cx=>0, :dx=>3}
       
       (compared using ==)
     # /tmp/d20140115-8451-10r0f00/spec.rb:34:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  6) Asm.asm implements JMP
     Failure/Error: Asm.asm do
       
       expected: [0, 0, 1, 1]
            got: {:ax=>0, :bx=>0, :cx=>1, :dx=>1}
       
       (compared using ==)
     # /tmp/d20140115-8451-10r0f00/spec.rb:68:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  7) Asm.asm implements LABEL
     Failure/Error: Asm.asm do
       
       expected: [1, 1, 0, 0]
            got: {:ax=>1, :bx=>1, :cx=>0, :dx=>0}
       
       (compared using ==)
     # /tmp/d20140115-8451-10r0f00/spec.rb:78:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

  8) Asm.asm can be used to find GCD of two numbers
     Failure/Error: Asm.asm do
       
       expected: [8, 8, 0, 0]
            got: {:ax=>8, :bx=>8, :cx=>0, :dx=>0}
       
       (compared using ==)
     # /tmp/d20140115-8451-10r0f00/spec.rb:89:in `block (2 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (3 levels) in <top (required)>'
     # ./lib/language/ruby/run_with_timeout.rb:5:in `block (2 levels) in <top (required)>'

Finished in 0.00865 seconds
8 examples, 8 failures

Failed examples:

rspec /tmp/d20140115-8451-10r0f00/spec.rb:2 # Asm.asm works with empty programs
rspec /tmp/d20140115-8451-10r0f00/spec.rb:6 # Asm.asm implements MOV
rspec /tmp/d20140115-8451-10r0f00/spec.rb:14 # Asm.asm implements INC
rspec /tmp/d20140115-8451-10r0f00/spec.rb:22 # Asm.asm implements DEC
rspec /tmp/d20140115-8451-10r0f00/spec.rb:33 # Asm.asm implements CMP
rspec /tmp/d20140115-8451-10r0f00/spec.rb:67 # Asm.asm implements JMP
rspec /tmp/d20140115-8451-10r0f00/spec.rb:77 # Asm.asm implements LABEL
rspec /tmp/d20140115-8451-10r0f00/spec.rb:88 # Asm.asm can be used to find GCD of two numbers

История (1 версия и 3 коментара)

Ясен обнови решението на 15.01.2014 13:18 (преди почти 11 години)

+module Asm
+ def Asm.asm(&block)
+ Assembler.new.assemble &block
+ end
+
+ class Assembler
+ attr_reader :memory, :labels
+
+ def initialize
+ @labels = {}
+ @memory = { ax: 0, bx: 0, cx: 0, dx: 0 }
+ @program = []
+ end
+
+ INSTRUCTIONS = {
+ "mov" => lambda { |register, src|
+ @memory[register] = (src.is_a?(Symbol) ? @memory[src] : src)
+ nil
+ },
+ "inc" => lambda { |register, value = 1|
+ value = @memory[value] if @memory.keys.index value
+ @memory[register] += value
+ nil
+ },
+ "dec" => lambda { |register, value = 1|
+ value = @memory[value] if @memory.keys.index value
+ @memory[register] -= value
+ nil
+ },
+ "cmp" => lambda { |register, value|
+ value = @memory[value] if @memory.keys.index value
+ @last_cmp = @memory[register] <=> value
+ nil
+ },
+ "jmp" => lambda { |destination| jump_to destination },
+ "je" => lambda { |destination| jump_to destination if @last_cmp == 0 },
+ "jne" => lambda { |destination| jump_to destination if @last_cmp != 0 },
+ "jl" => lambda { |destination| jump_to destination if @last_cmp < 0 },
+ "jle" => lambda { |destination| jump_to destination if @last_cmp <= 0 },
+ "jg" => lambda { |destination| jump_to destination if @last_cmp > 0 },
+ "jge" => lambda { |destination| jump_to destination if @last_cmp >= 0 }
+ }
+
+ def jump_to(destination)
+ @labels.keys.index(destination) ? @labels[destination] : destination
+ end
+
+ def method_missing(name, *args)
+ if INSTRUCTIONS.keys.include? name.to_s
+ @program << [name.to_s, args]
+ elsif name.to_s == "label"
+ @labels[args.first] = @program.size
+ else
+ name
+ end
+ end
+
+ def parse(&block)
+ self.instance_eval &block
+ end
+
+ def run
+ pc = 0
+ until pc == @program.length
+ instruction = @program[pc]
+ retval = instance_exec(*instruction[1], &INSTRUCTIONS[instruction[0]])
+ if retval
+ pc = retval
+ else
+ pc += 1
+ end
+ end
+ end
+
+ def assemble(&block)
+ parse &block
+ run
+ @memory
+ end
+ end
+end