Class: Voodoo::CommonCodeGenerator
- Inherits:
-
Object
- Object
- Voodoo::CommonCodeGenerator
- Defined in:
- lib/voodoo/generators/common_code_generator.rb
Overview
Common base class for code generators.
Code generators are expected to implement the following methods:
-
#new
-
#add
-
#add_function
-
#features
-
#gensym
-
#has_feature?
-
#output_file_name
-
#output_file_suffix
-
#write
This class contains base implementations of some of these methods, which can be used and/or overridden by subclasses.
An example of how to use the code generators provided by this module is provided on the main page of the documentation of the Voodoo module.
Direct Known Subclasses
Defined Under Namespace
Classes: Environment
Instance Method Summary collapse
-
#add(section, *code) ⇒ Object
Adds code to the given section.
-
#add_function(formals, *code) ⇒ Object
Add function.
-
#block(*code) ⇒ Object
Processes code in its own block.
-
#each_statement(statements, &block) ⇒ Object
Invokes block with each statement in the given list of statements.
-
#emit(code) ⇒ Object
Add code to the current section.
-
#features ⇒ Object
Returns a hash describing the features supported by this code generator.
-
#function(formals, *code) ⇒ Object
Add a function to the current section.
-
#gensym ⇒ Object
Generate a new, unused symbol.
-
#has_feature?(name) ⇒ Boolean
Returns true if a feature is supported by this generator, false otherwise.
- #in_section(name, &block) ⇒ Object
-
#initialize(params = {}) ⇒ CommonCodeGenerator
constructor
Initializes the code generator.
-
#output_file_name(input_name) ⇒ Object
Given an input file name, returns the canonical output file name for this code generator.
-
#output_file_suffix ⇒ Object
Returns the canonical output file suffix for this code generator.
-
#real_section_name(name) ⇒ Object
Get the real name of a section.
- #section(name = nil) ⇒ Object
-
#section=(name) ⇒ Object
Set the current section.
-
#section_alias(alias_name, original_name) ⇒ Object
Set up
alias_name
to refer to the same section asoriginal_name
.
Constructor Details
#initialize(params = {}) ⇒ CommonCodeGenerator
Initializes the code generator. params shall be a hash containing parameters to the code generator, and shall at least contain the keys :architecture
and :format
, specifying the target architecture and output format, respectively.
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 28 def initialize params = {} @architecture = params[:architecture] || Config.default_architecture @format = params[:format] || Config.default_format @sections = {} @section_aliases = {} # Default section aliases. Subclasses can start from scratch by # doing @section_aliases = {} section_alias :code, ".text" section_alias :functions, :code section_alias :data, ".data" self.section = :code @top_level = Environment.initial_environment @environment = @top_level @output_file_suffix = '.o' @features = { :voodoo => "1.0" # Voodoo language version } end |
Instance Method Details
#add(section, *code) ⇒ Object
Adds code to the given section.
Examples:
add :code, [:return, 0]
add :data, [:align], [:label, :xyzzy], [:word, 42]
This method implements the required functionality in terms of the following methods, which must be implemented by subclasses:
-
#align
-
#asr
-
#bsr
-
#byte
-
#call
-
#end_if
-
#export
-
#begin_function
-
#block
-
#ifelse
-
#ifeq
-
#ifge
-
#ifgt
-
#ifle
-
#iflt
-
#ifne
-
#import
-
#label
-
#let
-
#ret
-
#rol
-
#ror
-
#set
-
#set_byte
-
#set_word
-
#shl
-
#shr
-
#string
-
#word
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 86 def add section, *code in_section section do code.each do |action| keyword, args = action[0], action[1..-1] case keyword when :block block *args when :function function args[0], *args[1..-1] when :ifeq, :ifge, :ifgt, :ifle, :iflt, :ifne truebody = action[2] falsebody = action[3] send keyword, action[1][0], action[1][1] add section, *truebody if falsebody && !falsebody.empty? ifelse add section, *falsebody end end_if when :return send :ret, *args when :'set-word' send :set_word, *args when :'set-byte' send :set_byte, *args when :'tail-call' send :tail_call, *args else send *action end end end end |
#add_function(formals, *code) ⇒ Object
Add function.
Parameters:
- formals
-
an Array of formal parameter names
- code
-
an Array of actions to be used as the function’s body
Example:
add_function [:n], [:return, :add, :n, 1]
128 129 130 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 128 def add_function formals, *code add :functions, [:function, formals] + code end |
#block(*code) ⇒ Object
Processes code in its own block. Local variables can be introduced inside the block. They will be deleted at the end of the block.
135 136 137 138 139 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 135 def block *code begin_block *code code.each { |action| add section, action } end_block end |
#each_statement(statements, &block) ⇒ Object
Invokes block with each statement in the given list of statements. This iterator also descends into nested statements, calling block first with the outer statement, and then for each inner statement.
145 146 147 148 149 150 151 152 153 154 155 156 157 158 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 145 def each_statement statements, &block statements.each do |statement| yield statement case statement[0] when :block each_statement statement[1..-1], &block when :function each_statement statement[2..-1], &block when :ifeq, :ifle, :iflt, :ifge, :ifgt, :ifne each_statement statement[2], &block each_statement(statement[3], &block) if statement.length > 3 end end end |
#emit(code) ⇒ Object
Add code to the current section
181 182 183 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 181 def emit code @sections[real_section_name(@section)] << code end |
#features ⇒ Object
Returns a hash describing the features supported by this code generator. The keys in this hash are the names of the supported features. The associated values are strings providing additional information about the feature, such as a version number.
164 165 166 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 164 def features @features end |
#function(formals, *code) ⇒ Object
Add a function to the current section
169 170 171 172 173 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 169 def function formals, *code begin_function *formals code.each { |action| add section, action } end_function end |
#gensym ⇒ Object
Generate a new, unused symbol
176 177 178 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 176 def gensym Environment.gensym end |
#has_feature?(name) ⇒ Boolean
Returns true if a feature is supported by this generator, false otherwise.
187 188 189 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 187 def has_feature? name @features.has_key? name end |
#in_section(name, &block) ⇒ Object
226 227 228 229 230 231 232 233 234 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 226 def in_section name, &block oldsection = @section self.section = name begin yield ensure self.section = oldsection end end |
#output_file_name(input_name) ⇒ Object
Given an input file name, returns the canonical output file name for this code generator.
238 239 240 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 238 def output_file_name input_name input_name.sub(/\.voo$/, '') + @output_file_suffix end |
#output_file_suffix ⇒ Object
Returns the canonical output file suffix for this code generator
243 244 245 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 243 def output_file_suffix @output_file_suffix end |
#real_section_name(name) ⇒ Object
Get the real name of a section. Given a section name which may be an alias, this method returns the real name of the section.
194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 194 def real_section_name name given_name = name while true x = @section_aliases[name] break if x == nil # Not an alias, exit loop and return name name = x # If name == given_name, we're back where we started. Continuing # would have us loop forever. Just return what we have now. break if name == given_name end name end |
#section(name = nil) ⇒ Object
216 217 218 219 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 216 def section name = nil self.section = name if name @section end |
#section=(name) ⇒ Object
Set the current section
208 209 210 211 212 213 214 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 208 def section= name real_name = real_section_name name @section = name unless @sections.has_key? real_name @sections[real_name] = '' end end |
#section_alias(alias_name, original_name) ⇒ Object
Set up alias_name
to refer to the same section as original_name
.
222 223 224 |
# File 'lib/voodoo/generators/common_code_generator.rb', line 222 def section_alias alias_name, original_name @section_aliases[alias_name] = original_name end |