Диан обнови решението на 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-а и потърси несъответствия с него в кода си.