87 lines
2.9 KiB
Ruby
87 lines
2.9 KiB
Ruby
|
module Mom
|
||
|
# The Compiler/Collection for the Mom level is a collection of Mom level Method
|
||
|
# compilers These will transform to Risc MethodCompilers on the way down.
|
||
|
#
|
||
|
# As RubyCompiler pools source at the vool level, when several classes are compiled
|
||
|
# from vool to mom, several MomCompilers get instantiated. They must be merged before
|
||
|
# proceeding with translate. Thus we have a append method.
|
||
|
#
|
||
|
class MomCollection
|
||
|
attr_reader :method_compilers
|
||
|
|
||
|
# Initialize with an array of risc MethodCompilers
|
||
|
def initialize(compilers = [])
|
||
|
@method_compilers = compilers
|
||
|
end
|
||
|
|
||
|
# lazily instantiate the compilers for boot functions
|
||
|
# (in the hope of only booting the functions once)
|
||
|
def boot_compilers
|
||
|
@boot_compilers ||= Risc::Builtin.boot_functions
|
||
|
end
|
||
|
|
||
|
# Return all compilers, namely the MethodCompilers passed in, plus the
|
||
|
# boot_function's compilers (boot_compilers)
|
||
|
def compilers
|
||
|
@method_compilers #+ boot_compilers
|
||
|
end
|
||
|
|
||
|
# collects constants from all compilers into one array
|
||
|
def constants
|
||
|
compilers.inject([]){|sum ,comp| sum + comp.constants }
|
||
|
end
|
||
|
|
||
|
# Append another MomCompilers method_compilers to this one.
|
||
|
def append(mom_compiler)
|
||
|
@method_compilers += mom_compiler.method_compilers
|
||
|
self
|
||
|
end
|
||
|
|
||
|
# Translate code to whatever cpu is specified.
|
||
|
# Currently only :arm and :interpret
|
||
|
#
|
||
|
# Translating means translating the initial jump
|
||
|
# and then translating all methods
|
||
|
def translate( platform_sym )
|
||
|
platform_sym = platform_sym.to_s.capitalize
|
||
|
platform = Risc::Platform.for(platform_sym)
|
||
|
assemblers = translate_methods( platform.translator )
|
||
|
Risc::Linker.new(platform , assemblers , constants)
|
||
|
end
|
||
|
|
||
|
# go through all methods and translate them to cpu, given the translator
|
||
|
def translate_methods(translator)
|
||
|
compilers.collect do |compiler|
|
||
|
#log.debug "Translate method #{compiler.method.name}"
|
||
|
translate_method(compiler , translator)
|
||
|
end.flatten
|
||
|
end
|
||
|
|
||
|
# translate one method, which means the method itself and all blocks inside it
|
||
|
# returns an array of assemblers
|
||
|
def translate_method( method_compiler , translator)
|
||
|
all = []
|
||
|
all << translate_cpu( method_compiler , translator )
|
||
|
method_compiler.block_compilers.each do |block_compiler|
|
||
|
all << translate_cpu(block_compiler , translator)
|
||
|
end
|
||
|
all
|
||
|
end
|
||
|
|
||
|
# compile the callable (method or block) to cpu
|
||
|
# return an Assembler that will then translate to binary
|
||
|
def translate_cpu(compiler , translator)
|
||
|
risc = compiler.risc_instructions
|
||
|
cpu_instructions = risc.to_cpu(translator)
|
||
|
nekst = risc.next
|
||
|
while(nekst)
|
||
|
cpu = nekst.to_cpu(translator) # returning nil means no replace
|
||
|
cpu_instructions << cpu if cpu
|
||
|
nekst = nekst.next
|
||
|
end
|
||
|
Risc::Assembler.new(compiler.callable , cpu_instructions )
|
||
|
end
|
||
|
|
||
|
end
|
||
|
end
|