Files
nand2tetris/fertige_Projekte/Writer.rb
Sven Riwoldt c7bc862c6f asm
2024-04-01 20:30:24 +02:00

118 lines
2.6 KiB
Ruby

require_relative "Parser.rb"
class Writer
A_INSTRUCTION = /^@\d+$/
def initialize(asm_file_path, hack_file_path)
@hack_file = File.open(hack_file_path, "w")
@parser = Parser.new(asm_file_path)
end
def write
while @parser.has_more_commands
compile
end
@parser.close
@hack_file.close
end
def compile
if command.match(A_INSTRUCTION)
compile_a_ins
else
compile_c_ins
write_txt("", true)
end
@parser.advance
end
def compile_a_ins
ains = command[1..-1].to_i.to_s(base=2)
(16-ains.length).times {ains = "0" + ains}
write_txt(ains, true)
end
def compile_c_ins
write_txt("111")
commands = command.split(/=|;/)
if command.include?("=")
compile_alu(commands[1].strip)
compile_save_to(commands[0].strip)
compile_jump_to("#{commands[2] ? commands[2].strip : nil}")
else
compile_alu(commands[0].strip)
compile_save_to("")
compile_jump_to("#{commands[1] ? commands[1].strip : nil}")
end
end
def compile_alu(cmd)
cmd.include?("M") ? write_txt("1") : write_txt("0")
case cmd
when "0"
write_txt("101010")
when "1"
write_txt("111111")
when "-1"
write_txt("111010")
when "D"
write_txt("001100")
when "A", "M"
write_txt("110000")
when "!D"
write_txt("001101")
when "!A", "!M"
write_txt("110001")
when "-D"
write_txt("001111")
when "-A", "-M"
write_txt("110011")
when "D+1"
write_txt("011111")
when "A+1", "M+1"
write_txt("110111")
when "D-1"
write_txt("001110")
when "A-1", "M-1"
write_txt("110010")
when "D+A", "D+M"
write_txt("000010")
when "D-A", "D-M"
write_txt("010011")
when "A-D", "M-D"
write_txt("000111")
when "D&A", "D&M"
write_txt("000000")
when "D|A", "D|M"
write_txt("010101")
else
raise "no such alu command"
end
end
def compile_save_to(cmd)
cmd.include?("A") ? write_txt("1") : write_txt("0")
cmd.include?("D") ? write_txt("1") : write_txt("0")
cmd.include?("M") ? write_txt("1") : write_txt("0")
end
def compile_jump_to(command)
case command
when nil, ""
write_txt("000")
when "JGT"
write_txt("001")
when "JEQ"
write_txt("010")
when "JGE"
write_txt("011")
when "JLT"
write_txt("100")
when "JNE"
write_txt("101")
when "JLE"
write_txt("110")
when "JMP"
write_txt("111")
end
end
private
def command
@parser.current_command
end
def write_txt(binaries, ending=false)
@hack_file.write("#{binaries}#{ending ? "\n" : ""}")
end
end