Moved code generators to separate directory.
[voodoo-lang.git] / lib / ruby / voodoo / generators / common_code_generator.rb
blobf523a76ec29c210c2c08fd379046c3e7073c44b0
1 module Voodoo
2   # Common base class for code generators
3   class CommonCodeGenerator
4     def initialize
5       @sections = { 'code' => '' }
6       @section = "code"
7       @top_level = Environment.initial_environment
8       @environment = @top_level
9       #@if_labels = []
10     end
12     # Add code.
13     # Example:
14     #   add_code [:call, :exit, 0]
15     def add_code *actions
16       in_section 'code' do
17         actions.each do |action|
18           keyword, args = action[0], action[1..-1]
19           case keyword
20           when :else
21             send :ifelse, *args
22           when :return
23             send :ret, *args
24           when :'tail-call'
25             send :tail_call, *args
26           when :call, :goto, :let, :set
27             send *action
28           else
29             raise "Invalid action: #{action[0]}"
30           end
31         end
32       end
33     end
35     # Add a label at the current address in the code section.
36     def add_code_label name
37       raise NoSuchMethodError, 'TODO'
38     end
40     # Add data.
41     # Example:
42     #   add_data [:word, 42]
43     def add_data *defs
44       in_section 'data' do
45         defs.each do |defn|
46           keyword, args = defn[0], defn[1..-1]
47           case keyword
48           when :align
49             align_data *args
50           when :byte, :word
51             send *defn
52           else
53             raise "Invalid directive in data section: #{defn[0]}"
54           end
55         end
56       end
57     end
59     # Add a label at the current address in the data section.
60     def add_data_label name
61       raise NoSuchMethodError, 'TODO'
62     end
64     # Add function.
65     # Example:
66     #   add_data [:word, 42]
67     def add_function formals, *code
68       in_section 'code' do
69         begin_function formals
70         add_code *code
71         end_function
72       end
73     end
75     # Add a label at the address where the next function will be generated.
76     def add_function_label name
77       raise NoSuchMethodError, 'TODO'
78     end
80     # Set the current section
81     def section= section
82       @section = section
83       unless @sections.has_key? section
84         @sections[section] = ''
85       end
86     end
88     def section name = nil
89       section = name if name
90       @section
91     end
93     def in_section name, &block
94       oldsection = @section
95       section = name
96       yield
97       section = oldsection
98     end
100     class Environment
101       @@gensym_counter = 0
103       attr_reader :args, :locals, :symbols
105       def initialize parent = nil
106         ## Parent environment
107         @parent = parent
108         ## Symbol lookup table
109         @symbols = parent ? parent.symbols.dup : {}
110         ## Number of arguments
111         @args = parent ? parent.args : 0
112         ## Number of local variables
113         @locals = parent ? parent.locals : 0
114       end
116       def add_arg symbol
117         @symbols[symbol] = [:arg, @args]
118         @args = @args + 1
119       end
121       def add_args symbols
122         symbols.each { |sym| add_arg sym }
123       end
125       def add_local symbol
126         @symbols[symbol] = [:local, @locals]
127         @locals = @locals + 1
128       end
130       def add_locals symbols
131         symbols.each { |sym| add_local sym }
132       end
134       def gensym
135         @@gensym_counter = @@gensym_counter + 1
136         ".G#{@@gensym_counter}"
137       end
139       def [] symbol
140         @symbols[symbol]
141       end
143       def self.initial_environment
144         Environment.new
145       end
146     end
148   end