Class: Voodoo::CommonCodeGenerator

Inherits:
Object
  • Object
show all
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

ARMGasGenerator, MIPSGasGenerator, NasmGenerator

Defined Under Namespace

Classes: Environment

Instance Method Summary collapse

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

#featuresObject

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

#gensymObject

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.

Returns:

  • (Boolean)


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_suffixObject

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