class MicroCisc::Compile::Compiler
Attributes
command_count[R]
Public Class Methods
new(text)
click to toggle source
# File lib/micro_cisc/compile/compiler.rb, line 6 def initialize(text) @text = text @command_count = 0 parse end
Public Instance Methods
parse()
click to toggle source
# File lib/micro_cisc/compile/compiler.rb, line 12 def parse line_number = 1 @instructions = [] address = 0 @labels = {} @indexed_vars = {} @equivalents = {} errors = [] lgen = MicroCisc::Compile::LabelGenerator.new @command_count = 0 @text.each_line do |line| begin statement = MicroCisc::Compile::Statement.new(lgen, line, @indexed_vars, @equivalents) command = false statement.parse.each do |instruction| if instruction.label? @labels[instruction.label] = address elsif instruction.instruction? @instructions << [line_number, instruction] command = true address += 1 elsif instruction.data? @instructions += instruction.data.map { |d| [line_number, d] } line_string = [] word_counts = instruction.data.map do |d| if d.is_a?(String) line_string << d.unpack("S*").map { |w| '%04x' % w }.join d.size / 2 else line_string << d.join('.') 1 # 1 16-bit word reference end end address += word_counts.sum end end @command_count += 1 if command rescue ArgumentError => e MicroCisc.logger.error("Error on line #{line_number}: #{e.message}\n #{line}") errors << [line_number, e, line] end line_number += 1 end if errors.size > 0 errors = errors.map do |error| "#{error[0]}: #{error[1]}\n #{error[2]}" end MicroCisc.logger.error("\n\nErrors found:\n\n#{errors.join("\n")}") exit(1) end end
serialize(file = nil)
click to toggle source
# File lib/micro_cisc/compile/compiler.rb, line 65 def serialize(file = nil) @serialize ||= begin words = [] dstart = nil MicroCisc.logger.info("ADDRESS: INS-WORD LINE#: SOURCE") @instructions.each do |(line_number, ins)| if ins.is_a?(String) address = words.length ins_words = ins.unpack("S*") dstart ||= address words += ins_words elsif ins.is_a?(Array) dstart ||= address # Address reference in data label_address = @labels[ins.first] if ins.last == 'disp' words << label_address - address elsif ins.last == 'imm' words << (label_address & 0xFFFF) end else address = words.length if dstart MicroCisc.logger.info(" 0x#{'%04x' % dstart}: #{(address - dstart)} words of data") dstart = nil end MicroCisc.logger.info(" 0x#{'%04x' % address}: 0x#{'%04x' % ins.encoded(@labels, address)} #{'% 6d' % line_number}: " + ins.original.gsub("\n", "")) words << ins.encoded(@labels, address) end end if dstart address = words.length MicroCisc.logger.info(" 0x#{'%04x' % dstart}: #{(address - dstart)} words of data") end words end File.open(file, 'w') do |file| file.write(@serialize.pack("S*")) end if file @serialize end