Решение на Четвърта задача от Диан Николов

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

Към профила на Диан Николов

Резултати

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

Код

module Asm
class Evaluator
def initialize(instruction_sequence, labels)
@current_instruction = 0
@registers = { ax: 0, bx: 0, cx: 0, dx: 0 }
@labels = labels
@instruction_sequence = instruction_sequence
@jump_operations = { jmp: true, je: '==', jne: '!=', jl: '<',
jle: '<=', jg: '>', jge: '>=' }.freeze
@register_operations = { mov: '=', inc: '+', dec: '-', cmp: '==' }
end
def evaluate()
while @current_instruction < @instruction_sequence.length
instruction = @instruction_sequence[@current_instruction]
if nil != @jump_operations[instruction['name']]
jump @jump_operations[instruction['name']], *instruction['args']
elsif nil != @register_operations[instruction['name']]
calculate @register_operations[instruction['name']], *instruction['args']
else
send instruction['name'], *instruction['args']
end
end
end
def registers()
@registers
end
def value_of(source)
case source
when Symbol then value = @registers[source]
else value = source
end
end
def jump(cond, where)
if cond == true or @last_cmp.send(cond.to_sym, 0) == true
case where
when Symbol then @current_instruction = @labels[where]
else @current_instruction = where
end
else
@current_instruction += 1
end
end
def calculate(op, destination, source = 1)
@current_instruction += 1
value = value_of source
case op
when '=' then @registers[destination] = value
when '==' then @last_cmp = @registers[destination] <=> value
else @registers[destination] = @registers[destination].send(op.to_sym, value)
end
end
end
class ScriptParser
def initialize(&block)
@instruction_sequence = []
@labels = {}
instance_eval &block
end
def labels()
@labels
end
def instruction_sequence()
@instruction_sequence
end
private
def method_missing(name, *args)
instructions = [:mov, :inc, :dec, :cmp, :jmp, :je, :jne, :jl, :jle, :jg, :jge]
if nil != instructions.find_index(name)
@instruction_sequence << { 'name' => name, 'args' => args }
else
name
end
end
def label(name)
@labels[name] = @instruction_sequence.size
end
end
def self.asm(&block)
script = ScriptParser.new(&block)
instance = Evaluator.new(script.instruction_sequence, script.labels)
instance.evaluate
instance.registers.map { |key, value| value }
end
end

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

........

Finished in 0.00837 seconds
8 examples, 0 failures

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

Диан обнови решението на 12.01.2014 23:33 (преди почти 11 години)

+module Asm
+ class Evaluator
+ def initialize(instruction_sequence, labels)
+ @current_instruction = 0
+ @registers = { ax: 0, bx: 0, cx: 0, dx: 0 }
+ @labels = labels
+ @instruction_sequence = instruction_sequence
+ @jump_operations = { jmp: true, je: '==', jne: '!=', jl: '<',
+ jle: '<=', jg: '>', jge: '>=' }
+
+ @register_operations = { inc: '+', dec: '-' }
+ end
+
+ def method_missing(name)
+ name
+ end
+
+ def evaluate()
+ while @current_instruction < @instruction_sequence.length
+ instruction = @instruction_sequence[@current_instruction]
+
+ if nil != @jump_operations[instruction['name']]
+ jump @jump_operations[instruction['name']], *instruction['args']
+
+ elsif nil != @register_operations[instruction['name']]
+ calculate @register_operations[instruction['name']], *instruction['args']
+
+ else
+ send instruction['name'], *instruction['args']
+ end
+ end
+ end
+
+ def registers()
+ @registers
+ end
+
+ def jump(cond, where)
+ if cond == true or @last_cmp.send(cond.to_sym, 0) == true
+ case where
+ when Symbol
+ @current_instruction = @labels[where]
+ else
+ @current_instruction = where
+ end
+ else
+ @current_instruction += 1
+ end
+ end
+
+ def calculate(operation, destination, source = 1)
+ case source
+ when Symbol
+ value = @registers[source]
+ else
+ value = source
+ end
+ @current_instruction += 1
+ @registers[destination] = @registers[destination].send(operation.to_sym, value)
+ end
+
+ def mov(destination, source)
+ case source
+ when Symbol
+ value = @registers[source]
+ else
+ value = source
+ end
+ @current_instruction += 1
+ @registers[destination] = value
+ end
+
+ def cmp(destination, source)
+ case source
+ when Symbol
+ value = @registers[source]
+ else
+ value = source
+ end
+ @current_instruction += 1
+ @last_cmp = @registers[destination] <=> value
+ end
+ end
+
+ def self.label(name)
+ @@labels[name] = @@instruction_sequence.size
+ end
+
+ def self.method_missing(name, *args)
+ instructions = [:mov, :inc, :dec, :cmp, :jmp, :je, :jne, :jl, :jle, :jg, :jge]
+ if nil != instructions.find_index(name)
+ @@instruction_sequence << { 'name' => name, 'args' => args }
+ else
+ name
+ end
+ end
+
+ def self.asm(&block)
+ class_eval &block
+ instance = Evaluator.new(@@instruction_sequence, @@labels)
+
+ @@instruction_sequence = []
+ @@labels = {}
+
+ instance.evaluate
+ instance.registers.map { |key, value| value }
+ end
+
+ private
+
+ @@instruction_sequence = []
+ @@labels = {}
+end
  • case-овете ти не са индентирани правилно.
  • Не те ли дразни повторението на case-овете? Можеш ли да ги абстрахираш в помощен метод? В момента кодът ти нарушава DRY принципа.
  • @jump_operations може да се направи по-четимо като всяко операция иде на отделен ред.
  • Използването на class променливи, като @@labels не е препоръчително. Може да ги превърнеш в class instance променливи на Evaluator, или на някой нов клас/модул.
  • Прегледай още веднъж style guide-а и потърси несъответствия с него в кода си.

Диан обнови решението на 14.01.2014 22:29 (преди почти 11 години)

module Asm
class Evaluator
def initialize(instruction_sequence, labels)
@current_instruction = 0
@registers = { ax: 0, bx: 0, cx: 0, dx: 0 }
+
@labels = labels
@instruction_sequence = instruction_sequence
+
@jump_operations = { jmp: true, je: '==', jne: '!=', jl: '<',
- jle: '<=', jg: '>', jge: '>=' }
+ jle: '<=', jg: '>', jge: '>=' }.freeze
- @register_operations = { inc: '+', dec: '-' }
+ @register_operations = { mov: '=', inc: '+', dec: '-', cmp: '==' }
end
- def method_missing(name)
- name
- end
-
def evaluate()
while @current_instruction < @instruction_sequence.length
instruction = @instruction_sequence[@current_instruction]
if nil != @jump_operations[instruction['name']]
jump @jump_operations[instruction['name']], *instruction['args']
elsif nil != @register_operations[instruction['name']]
calculate @register_operations[instruction['name']], *instruction['args']
else
send instruction['name'], *instruction['args']
end
end
end
def registers()
@registers
end
+ def value_of(source)
+ case source
+ when Symbol then value = @registers[source]
+ else value = source
+ end
+ end
+
def jump(cond, where)
if cond == true or @last_cmp.send(cond.to_sym, 0) == true
case where
- when Symbol
- @current_instruction = @labels[where]
- else
- @current_instruction = where
+ when Symbol then @current_instruction = @labels[where]
+ else @current_instruction = where
end
else
@current_instruction += 1
end
end
- def calculate(operation, destination, source = 1)
- case source
- when Symbol
- value = @registers[source]
- else
- value = source
- end
+ def calculate(op, destination, source = 1)
@current_instruction += 1
- @registers[destination] = @registers[destination].send(operation.to_sym, value)
+ value = value_of source
+ case op
+ when '=' then @registers[destination] = value
+ when '==' then @last_cmp = @registers[destination] <=> value
+ else @registers[destination] = @registers[destination].send(op.to_sym, value)
+ end
end
+ end
- def mov(destination, source)
- case source
- when Symbol
- value = @registers[source]
- else
- value = source
- end
- @current_instruction += 1
- @registers[destination] = value
+ class ScriptParser
+ def initialize(&block)
+ @instruction_sequence = []
+ @labels = {}
+ instance_eval &block
end
- def cmp(destination, source)
- case source
- when Symbol
- value = @registers[source]
- else
- value = source
- end
- @current_instruction += 1
- @last_cmp = @registers[destination] <=> value
+ def labels()
+ @labels
end
- end
- def self.label(name)
- @@labels[name] = @@instruction_sequence.size
- end
+ def instruction_sequence()
+ @instruction_sequence
+ end
- def self.method_missing(name, *args)
- instructions = [:mov, :inc, :dec, :cmp, :jmp, :je, :jne, :jl, :jle, :jg, :jge]
- if nil != instructions.find_index(name)
- @@instruction_sequence << { 'name' => name, 'args' => args }
- else
- name
+ private
+
+ def method_missing(name, *args)
+ instructions = [:mov, :inc, :dec, :cmp, :jmp, :je, :jne, :jl, :jle, :jg, :jge]
+ if nil != instructions.find_index(name)
+ @instruction_sequence << { 'name' => name, 'args' => args }
+ else
+ name
+ end
end
+
+ def label(name)
+ @labels[name] = @instruction_sequence.size
+ end
+
end
def self.asm(&block)
- class_eval &block
- instance = Evaluator.new(@@instruction_sequence, @@labels)
+ script = ScriptParser.new(&block)
+ instance = Evaluator.new(script.instruction_sequence, script.labels)
- @@instruction_sequence = []
- @@labels = {}
-
instance.evaluate
instance.registers.map { |key, value| value }
end
-
- private
-
- @@instruction_sequence = []
- @@labels = {}
end