1 require 'voodoo/generators/generator_api1'
4 # Common base class for code generators.
6 # Code generators are expected to implement the following methods:
13 # - #output_file_suffix
17 # This class contains base implementations of some of these methods,
18 # which can be used and/or overridden by subclasses.
20 # An example of how to use the code generators provided by this module
21 # is provided on the main page of the documentation of the Voodoo module.
23 class CommonCodeGenerator
24 # Provide compatibility with old API
27 # Initializes the code generator.
28 # _params_ shall be a hash containing parameters to the code generator,
29 # and shall at least contain the keys <tt>:architecture</tt> and
30 # <tt>:format</tt>, specifying the target architecture and output
31 # format, respectively.
32 def initialize params = {}
33 @architecture = params[:architecture] || Config.default_architecture
34 @format = params[:format] || Config.default_format
37 # Default section aliases. Subclasses can start from scratch by
38 # doing @section_aliases = {}
39 section_alias :code, ".text"
40 section_alias :functions, :code
41 section_alias :data, ".data"
43 @top_level = Environment.initial_environment
44 @environment = @top_level
45 @output_file_suffix = '.o'
48 # Adds code to the given section.
51 # add :code, [:return, 0]
52 # add :data, [:align], [:label, :xyzzy], [:word, 42]
54 # This method implements the required functionality in terms
55 # of the following methods, which must be implemented by subclasses:
80 def add section, *code
83 keyword, args = action[0], action[1..-1]
86 function args[0], *args[1..-1]
87 when :ifeq, :ifge, :ifgt, :ifle, :iflt, :ifne
90 send keyword, action[1][0], action[1][1]
91 add section, *truebody
92 if falsebody && !falsebody.empty?
94 add section, *falsebody
100 send :set_word, *args
102 send :set_byte, *args
104 send :tail_call, *args
115 # [formals] an Array of formal parameter names
116 # [code] an Array of actions to be used as the function's body
119 # add_function [:n], [:return, :add, :n, 1]
120 def add_function formals, *code
121 add :functions, [:function, formals] + code
124 # Add a function to the current section
125 def function formals, *code
126 begin_function *formals
127 code.each { |action| add section, action }
131 # Generate a new, unused symbol
136 # Add code to the current section
138 @sections[real_section_name(@section)] << code
141 # Get the real name of a section.
142 # Given a section name which may be an alias, this method returns the
143 # real name of the section.
144 def real_section_name name
147 x = @section_aliases[name]
148 break if x == nil # Not an alias, exit loop and return name
150 # If name == given_name, we're back where we started. Continuing
151 # would have us loop forever. Just return what we have now.
152 break if name == given_name
157 # Set the current section
159 real_name = real_section_name name
161 unless @sections.has_key? real_name
162 @sections[real_name] = ''
166 def section name = nil
167 self.section = name if name
171 # Set up +alias_name+ to refer to the same section as +original_name+.
172 def section_alias alias_name, original_name
173 @section_aliases[alias_name] = original_name
176 def in_section name, &block
177 oldsection = @section
182 self.section = oldsection
186 # Given an input file name, returns the canonical output file name
187 # for this code generator.
188 def output_file_name input_name
189 input_name.sub(/\.voo$/, '') + @output_file_suffix
192 # Returns the canonical output file suffix for this code generator
193 def output_file_suffix
200 attr_reader :args, :locals, :symbols
202 def initialize parent = nil
203 ## Parent environment
205 ## Symbol lookup table
206 @symbols = parent ? parent.symbols.dup : {}
207 ## Number of arguments
208 @args = parent ? parent.args : 0
209 ## Number of local variables
210 @locals = parent ? parent.locals : 0
214 @symbols[symbol] = [:arg, @args]
219 symbols.each { |sym| add_arg sym }
223 @symbols[symbol] = [:local, @locals]
224 @locals = @locals + 1
227 def add_locals symbols
228 symbols.each { |sym| add_local sym }
240 @@gensym_counter = @@gensym_counter + 1
241 "_G#{@@gensym_counter}".to_sym
244 def self.initial_environment