Решение на Четвърта задача от Иван Проданов

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

Към профила на Иван Проданов

Резултати

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

Код

module Asm
class Register
include Comparable
attr_reader :value
def initialize (value=0)
@value = value
end
def +(other)
@value += other.to_i
self
end
def -(other)
@value -= other.to_i
self
end
def assign(value)
@value = value.to_i
end
def to_i
@value
end
def <=>(other)
to_i <=> other.to_i
end
end
module Arithmetics
attr_reader :arithmetic_flag
def inc (destination, value=1)
destination += value
end
def dec (destination, value=1)
destination -= value
end
def mov (destination, source)
destination.assign source
end
def cmp (register, value)
@arithmetic_flag = register <=> value
end
end
module Registers
attr_reader :ax, :bx, :cx, :dx
end
module Locator
attr_reader :labels, :ip
def jmp (label)
@ip = label.is_a?(Numeric) ? label - 1 : labels[[label]]
end
def label (name)
end
def je (label)
jmp label if @arithmetic_flag.zero?
end
def jne (label)
jmp label if @arithmetic_flag.nonzero?
end
def jl (label)
jmp label if @arithmetic_flag < 0
end
def jle (label)
jmp label if @arithmetic_flag <= 0
end
def jg (label)
jmp label if @arithmetic_flag > 0
end
def jge (label)
jmp label if @arithmetic_flag >= 0
end
end
class Assembler
include Arithmetics
include Registers
include Locator
@registerSet = Registers.instance_methods
@instructionSet = Arithmetics.instance_methods + Locator.instance_methods
class << self
attr_accessor :instructionSet, :registerSet
end
def get_registers
[@ax.to_i, @bx.to_i, @cx.to_i, @dx.to_i]
end
def initialize
@ip = 0
@labels = {}
@ax, @bx, @cx, @dx = Register.new, Register.new, Register.new, Register.new
@arithmetic_flag = 0
end
def initialize_labels (instructions)
instructions.each do |instruction|
if instruction.name == :label
@labels[instruction.args] = instructions.index(instruction)
end
end
end
def execute (instructions)
unless instructions.empty?
initialize_labels instructions
begin
send(instructions[@ip].name, *instructions[@ip].args)
@ip+=1
end until @ip == instructions.size
end
get_registers
end
end
class Instruction
attr_accessor :name, :args
def initialize(name="", args=[])
@name, @args = name, args
end
end
class Evaluator
attr_reader :instructions
def initialize (assembler)
@instructions = []
@assembler = assembler
end
def method_missing(name, *args, &block)
if Assembler.instructionSet.include?(name)
return @instructions << (Instruction.new name, args)
elsif Assembler.registerSet.include?(name)
return @assembler.send(name)
end
name
end
end
def self.asm(&block)
assembler = Assembler.new
evaluator = Evaluator.new(assembler)
evaluator.instance_eval &block
assembler.execute evaluator.instructions
end
end

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

........

Finished in 0.00775 seconds
8 examples, 0 failures

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

Иван обнови решението на 15.01.2014 16:46 (преди почти 11 години)

+module Asm
+ class Register
+ include Comparable
+ attr_reader :value
+
+ def initialize (value=0)
+ @value = value
+ end
+
+ def +(other)
+ @value += other.to_i
+ self
+ end
+
+ def -(other)
+ @value -= other.to_i
+ self
+ end
+
+ def assign(value)
+ @value = value.to_i
+ end
+
+ def to_i
+ @value
+ end
+
+ def <=>(other)
+ to_i <=> other.to_i
+ end
+ end
+
+ module Arithmetics
+ attr_reader :arithmetic_flag
+
+ def inc (destination, value=1)
+ destination += value
+ end
+
+ def dec (destination, value=1)
+ destination -= value
+ end
+
+ def mov (destination, source)
+ destination.assign source
+ end
+
+ def cmp (register, value)
+ @arithmetic_flag = register <=> value
+ end
+ end
+
+ module Registers
+ attr_reader :ax, :bx, :cx, :dx
+ end
+
+ module Locator
+ attr_reader :labels, :ip
+
+ def jmp (label)
+ @ip = label.is_a?(Numeric) ? label - 1 : labels[[label]]
+ end
+
+ def label (name)
+ end
+
+ def je (label)
+ jmp label if @arithmetic_flag.zero?
+ end
+
+ def jne (label)
+ jmp label if @arithmetic_flag.nonzero?
+ end
+
+ def jl (label)
+ jmp label if @arithmetic_flag < 0
+ end
+
+ def jle (label)
+ jmp label if @arithmetic_flag <= 0
+ end
+
+ def jg (label)
+ jmp label if @arithmetic_flag > 0
+ end
+
+ def jge (label)
+ jmp label if @arithmetic_flag >= 0
+ end
+ end
+
+ class Assembler
+ include Arithmetics
+ include Registers
+ include Locator
+
+ @registerSet = Registers.instance_methods
+ @instructionSet = Arithmetics.instance_methods + Locator.instance_methods
+
+ class << self
+ attr_accessor :instructionSet, :registerSet
+ end
+
+ def get_registers
+ [@ax.to_i, @bx.to_i, @cx.to_i, @dx.to_i]
+ end
+
+ def initialize
+ @ip = 0
+ @labels = {}
+ @ax, @bx, @cx, @dx = Register.new, Register.new, Register.new, Register.new
+ @arithmetic_flag = 0
+ end
+
+ def initialize_labels (instructions)
+ instructions.each do |instruction|
+ if instruction.name == :label
+ @labels[instruction.args] = instructions.index(instruction)
+ end
+ end
+ end
+
+ def execute (instructions)
+ unless instructions.empty?
+ initialize_labels instructions
+ begin
+ send(instructions[@ip].name, *instructions[@ip].args)
+ @ip+=1
+ end until @ip == instructions.size
+ end
+ get_registers
+ end
+ end
+
+ class Instruction
+ attr_accessor :name, :args
+
+ def initialize(name="", args=[])
+ @name, @args = name, args
+ end
+ end
+
+ class Evaluator
+ attr_reader :instructions
+
+ def initialize (assembler)
+ @instructions = []
+ @assembler = assembler
+ end
+
+ def method_missing(name, *args, &block)
+ if Assembler.instructionSet.include?(name)
+ return @instructions << (Instruction.new name, args)
+ elsif Assembler.registerSet.include?(name)
+ return @assembler.send(name)
+ end
+ name
+ end
+
+ end
+
+ def self.asm(&block)
+ assembler = Assembler.new
+ evaluator = Evaluator.new(assembler)
+ evaluator.instance_eval &block
+ assembler.execute evaluator.instructions
+ end
+end

Имаш разни дребни стилистични проблеми:

  • Не оставяй интервал преди отварящата скоба при дефиниция/извикване на метод: def jg (label). Освен това го правиш неконсистентно (не навсякъде си оставял интервал там).
  • Трябва да има интервали около оператори като +=, = и прочее.
  • Не трябва да има празен ред на ред 159.