Христо обнови решението на 15.01.2014 00:25 (преди почти 11 години)
+module JumpInterface
+ def jmp where
+ jump_to_instruction_int where if where.is_a? Integer
+ jump_to_label where if where.is_a? String
+ end
+ def je where
+ if @last_cmp_result == 0
+ jmp where
+ else
+ nil
+ end
+ end
+end
+module JumpInterfaceHelper
+ def jmp where
+ @instructions_evaluator.operations_queue.push([@instruction_number, __method__,
+ [where]])
+ end
+ def je where
+ @instructions_evaluator.operations_queue.push([@instruction_number, __method__,
+ [where]])
+ end
+end
+
+module Asm
+ class InstructionsQueueCreater
+ include JumpInterfaceHelper
+ attr_accessor :instruction_number
+ attr_accessor :instructions_evaluator
+ def initialize
+ @instructions_evaluator = Instructions.new
+ @instruction_number = 0
+ end
+ def mov (destination_register, source)
+ @instructions_evaluator.operations_queue.push([@instruction_number, __method__,
+ [destination_register, source]])
+ @instruction_number += 1
+ end
+
+ def inc (destination_register, value = 1)
+ @instructions_evaluator.operations_queue.push([@instruction_number, __method__,
+ [destination_register, value]])
+ @instruction_number += 1
+ end
+
+ def dec (destination_register, value = 1)
+ @instructions_evaluator.operations_queue.push([@instruction_number, __method__,
+ [destination_register, value]])
+ @instruction_number += 1
+ end
+
+ def cmp (register, value)
+ @instructions_evaluator.operations_queue.push([@instruction_number, __method__,
+ [register, value]])
+ @instruction_number += 1
+ end
+
+ def label (label_name)
+ @instructions_evaluator.operations_queue.push(label_name)
+ end
+ def method_missing(name, *args, &block)
+ name
+ end
+ end
+
+ class Instructions
+ # attr_writer :ax
+ # attr_writer :bx
+ # attr_writer :cx
+ include JumpInterface
+ attr_accessor :last_cmp_result
+ attr_accessor :operations_queue
+ def initialize
+ @ax,@bx,@cx,@dx = 0, 0, 0, 0
+ @operations_queue = []
+ @instruction_number = 0
+ end
+
+ def mov (destination_register, source)
+ destination_register, source_value = '@'+ destination_register.to_s, 0
+ if source.is_a? String or source.is_a? Symbol
+ source_value = self.instance_variable_get('@'+source.to_s)
+ else
+ source_value = source
+ end
+ self.instance_variable_set destination_register, source_value
+ end
+
+ def inc (destination_register, value = 1)
+ destination_register, source_value = '@'+ destination_register.to_s, 1
+ if value.is_a? String or value.is_a? Symbol
+ source_value = self.instance_variable_get('@'+value.to_s)
+ else
+ source_value = value
+ end
+ destination_value = self.instance_variable_get destination_register
+ self.instance_variable_set destination_register , destination_value + source_value
+ end
+
+ def dec (destination_register, value = 1)
+ destination_register, source_value = '@'+ destination_register.to_s, 1
+ if value.is_a? String or value.is_a? Symbol
+ source_value = self.instance_variable_get('@'+value.to_s)
+ else
+ source_value = value
+ end
+ destination_value = self.instance_variable_get destination_register
+ self.instance_variable_set destination_register , destination_value - source_value
+ end
+
+ def cmp (register, value)
+ register,source_value = '@'+ register.to_s
+ if value.is_a? String or value.is_a? Symbol
+ source_value = self.instance_variable_get('@'+value.to_s)
+ else
+ source_value = value
+ end
+ register_value = self.instance_variable_get register
+ @last_cmp_result = register_value <=> source_value
+ end
+ def method_missing(name, *args, &block)
+ name
+ end
+ private
+ def jump_to_instruction_int(instruction_number)
+ instruction_place = @operations_queue.index{|x| x[0]==instruction_number}
+ next_first_instruction = @operations_queue
+ .values_at(instruction_place..@operations_queue.size-1).index{|x| x[0] == 0}
+ next_first_instruction = @operations_queue.size-1 if next_first_instruction.nil?
+ @operations_queue.values_at(instruction_place..@operations_queue.size-1)
+ .map{ |x| self.send(x[1],*x[2]) if (!x[1].nil? and !x[2].nil?)}
+ end
+
+ def jump_to_label(label_name)
+ instruction_place = @operations_queue.index{|x| x == label_name}
+ next_first_instruction = @operations_queue
+ .values_at(instruction_place..@operations_queue.size-1).index{|x| x[0] == 0}
+ next_first_instruction = @operations_queue.size-1 if next_first_instruction.nil?
+ @operations_queue.values_at(instruction_place+1..next_first_instruction)
+ .map{ |x| self.send(x[1],*x[2]) if (!x[1].nil? and !x[2].nil?) }
+ end
+ end
+ def self.asm(&block)
+ evaluator = InstructionsQueueCreater.new
+ evaluator.instance_eval &block
+ evaluator.instructions_evaluator.instance_eval &block
+ end
+end
Whitespace-а ще ти коства поне 1 точка, ако го запазиш както е в момента. Отделно е добре JumpInterface
и JumpInterfaceHelper
да бъдат преместени в Asm
. Няма ли да имплементираш всички jump-ове, също така?
В кода има голямо количество повторения, което ще затрудни евентуален refactoring, или промяна/добавяне на функционалност. Погледни DRY принципа и виж какво можеш да направиш по въпроса.
Нямаше кога да го направя, за съжаление съм доста зает напоследък. Иначе не виждам Whitespace ,нито на скептик нито на око.а за JumpInterface и JumpInterfaceHelper немогат да са в асм заради най-много 9те метода на клас. П.с Благодаря за фийдбека :)