rubyx/lib/slot_language/macro_maker.rb
2020-02-12 15:41:16 +07:00

66 lines
2.4 KiB
Ruby

module SlotLanguage
# MacroMaker instances represent Macros at the Slot level
#
# Macros are like SlotInstruction instances in that they transform to Risc
# But all SlotInstructions form a whole that lets us reduce Sol to Slot to risc.
# Each Macro on the other hand represents a functionality (kind of method)
# that can not be coded in sol. It transforms to a sequence of risc Instructions
# that can not be coded any other way. They are not Methods, as they have no
# scope, hence the name Macro.
#
# This MacroMaker is an attempt to code these kind of sequences in SlotLanguage
# The SlotCompiler is used to transform a file of SlotLanguage code into and
# array of SlotLanguage constructs, which in turn can be transformed into
# SlotInstructions.
# To start with we work backwards from existing large SlotInstructions, to
# get a list of constructs that will transform to the same SlotInstructions
# that transform to the same risc as the current large instruction (+ some redundandency)
class MacroMaker
# an array of Makers
attr_reader :source
# load slot code from a file, in a subdir code/ + filename
# use load_string to compile the content
def self.load_file(relative_name)
path = File.expand_path( "../code/#{relative_name}" , __FILE__)
load_string( File.read(path))
end
# compile the given SlotLanguage source
# the compiler returns an array of Makers which a new MacroMaker
# instance stores
# return the MacroMaker that represents the source
def self.load_string(source_code)
MacroMaker.new( SlotCompiler.compile(source_code) )
end
# must initialize with an array of Makers, which is stored
def initialize( source )
@source = source
raise "undefined source #{source}" unless source.is_a?(Array)
end
# Basically calls to_slot on each Element of the source array
#
# Thus transforming an array of Makers into a linked list of
# SlotInstructions.
# Return the head of the linked list.
def to_slot(compiler)
chain = do_link( @source.first , compiler)
rest = @source.dup
rest.shift
rest.each do |link|
chain << do_link(link , compiler)
end
chain
end
private
def do_link(link,compiler)
return link if link.is_a?(SlotMachine::Instruction)
link.to_slot(compiler)
end
end
end