Class: Emfrp::CodegenContext

Inherits:
Object
  • Object
show all
Defined in:
lib/emfrp/compile/c/codegen_context.rb

Defined Under Namespace

Classes: Block

Constant Summary collapse

SymbolToStr =
{
  "!" => "_exclamation_",
  "#" => "_hash_",
  "$" => "_dollar_",
  "%" => "_parcent_",
  "&" => "_anpersand",
  "*" => "_asterisk_",
  "+" => "_plus_",
  "." => "_dot_",
  "/" => "_slash_",
  "<" => "_lt_",
  "=" => "_eq_",
  ">" => "_gt_",
  "?" => "_question_",
  "@" => "_at_",
  "\\" => "_backslash_",
  "^" => "_caret_",
  "|" => "_vertial_",
  "-" => "_minus_",
  "~" => "_tilde_",
  "(" => "_cpbegin_",
  ")" => "_cpend_",
  "," => "_comma_"
}

Instance Method Summary collapse

Constructor Details

#initialize(top) ⇒ CodegenContext

Returns a new instance of CodegenContext.



28
29
30
31
32
33
34
35
36
37
38
# File 'lib/emfrp/compile/c/codegen_context.rb', line 28

def initialize(top)
  @top = top
  @global_vars = []
  @funcs = []
  @structs = []
  @protos = []
  @static_protos = []
  @macros = []
  @init_stmts = []
  @templates = []
end

Instance Method Details

#code_generate(c_output, h_output, main_output, name) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/emfrp/compile/c/codegen_context.rb', line 40

def code_generate(c_output, h_output, main_output, name)
  #  generate header-file
  h_output << "#ifndef #{name.upcase}_H\n"
  h_output << "#define #{name.upcase}_H\n\n"
  @protos.each do |x|
    h_output.puts x.to_s
  end
  h_output << "\n#endif /* end of include guard */\n"
  # generate library-file
  c_output.puts "#include \"#{name}.h\""
  c_output.puts "/* Primitive functions (Macros) */"
  @macros.each do |x|
    c_output.puts x.to_s
  end
  c_output.puts "/* Data types */"
  @structs.each do |x|
    c_output.puts x.to_s
  end
  c_output.puts "/* Global variables */"
  @global_vars.each do |x|
    c_output.puts x.to_s
  end
  c_output.puts "/* Static prototypes */"
  @static_protos.each do |x|
    c_output.puts x.to_s
  end
  c_output.puts "/* Functions, Constructors, GCMarkers, etc... */"
  @funcs.each do |x|
    c_output.puts x.to_s
  end
  # generate main-file
  main_output << "#include \"#{name}.h\"\n\n"
  main_output << "void Input(#{@top[:inputs].map{|x| "#{tref(x)}* #{x[:name][:desc]}"}.join(", ")}) {\n  /* Your code goes here... */\n}\n"
  main_output << "void Output(#{@top[:outputs].map{|x| "#{tref(x)}* #{x[:name][:desc]}"}.join(", ")}) {\n  /* Your code goes here... */\n}\n"
  main_output << "int main() {\n  Activate#{@top[:module_name][:desc]}();\n}\n"
end

#constructor_name(name, utype) ⇒ Object



93
94
95
96
97
98
99
100
# File 'lib/emfrp/compile/c/codegen_context.rb', line 93

def constructor_name(name, utype)
  @top[:dict][:itype_space][utype.to_uniq_str].get[:tvalues].each do |tval|
    if tval[:name][:desc] == name
      return tval.constructor_name(self)
    end
  end
  raise "Assertion error: #{name} is not found"
end

#define_func(type_str, name_str, params, accessor = :static, with_proto = true, &block) ⇒ Object



148
149
150
151
152
153
154
155
156
157
158
# File 'lib/emfrp/compile/c/codegen_context.rb', line 148

def define_func(type_str, name_str, params, accessor=:static, with_proto=true, &block)
  elements = []
  block.call(elements)
  case accessor
  when :none then deco = ""
  when :static then deco = "static "
  end
  define_proto(type_str, name_str, params.map(&:first), accessor) if with_proto
  @funcs << Block.new("#{deco}#{type_str} #{name_str}(#{params.map{|a, b| "#{a} #{b}"}.join(", ")}) {", elements, "}")
  return nil
end

#define_global_var(type_str, name_str, initial_value_str = nil) ⇒ Object



140
141
142
# File 'lib/emfrp/compile/c/codegen_context.rb', line 140

def define_global_var(type_str, name_str, initial_value_str=nil)
  @global_vars << "#{type_str} #{name_str}" + (initial_value_str ? " = #{initial_value_str}" : "") + ";"
end

#define_init_stmt(stmt) ⇒ Object



175
176
177
# File 'lib/emfrp/compile/c/codegen_context.rb', line 175

def define_init_stmt(stmt)
  @init_stmts << stmt
end

#define_macro(name_str, params, body_str) ⇒ Object



144
145
146
# File 'lib/emfrp/compile/c/codegen_context.rb', line 144

def define_macro(name_str, params, body_str)
  @macros << "#define #{name_str}(#{params.join(", ")}) (#{body_str})"
end

#define_proto(type_str, name_str, param_types, accessor = :static) ⇒ Object



160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/emfrp/compile/c/codegen_context.rb', line 160

def define_proto(type_str, name_str, param_types, accessor=:static)
  case accessor
  when :none then deco = ""
  when :static then deco = "static "
  when :extern then deco = "extern "
  end
  proto = "#{deco}#{type_str} #{name_str}(#{param_types.join(", ")});"
  if accessor == :static || accessor == :extern
    @static_protos << proto
  else
    @protos << proto
  end
  return nil
end

#define_struct(kind_str, name_str, var_name_str, &block) ⇒ Object



179
180
181
182
183
184
185
186
187
188
189
# File 'lib/emfrp/compile/c/codegen_context.rb', line 179

def define_struct(kind_str, name_str, var_name_str, &block)
  elements = []
  block.call(elements)
  x = Block.new("#{kind_str} #{name_str}{", elements, "}#{var_name_str};")
  if name_str
    @structs << x
    return nil
  else
    return x
  end
end

#escape_name(name) ⇒ Object



102
103
104
105
# File 'lib/emfrp/compile/c/codegen_context.rb', line 102

def escape_name(name)
  rexp = Regexp.new("[" + Regexp.escape(SymbolToStr.keys.join) + "]")
  name.gsub(rexp, SymbolToStr)
end

#func_name(name, ret_utype, arg_utypes) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
# File 'lib/emfrp/compile/c/codegen_context.rb', line 81

def func_name(name, ret_utype, arg_utypes)
  case f = @top[:dict][:func_space][name].get
  when PrimFuncDef
    f.func_name(self)
  when FuncDef
    key = [ret_utype, *arg_utypes].map(&:to_uniq_str) + [name]
    @top[:dict][:ifunc_space][key].get.func_name(self)
  else
    raise "Assertion error: unexpected func type #{f.class}"
  end
end

#init_stmtsObject



77
78
79
# File 'lib/emfrp/compile/c/codegen_context.rb', line 77

def init_stmts
  @init_stmts
end

#make_block(head_str, elements, foot_str) ⇒ Object



191
192
193
# File 'lib/emfrp/compile/c/codegen_context.rb', line 191

def make_block(head_str, elements, foot_str)
  Block.new(head_str, elements, foot_str)
end

#serial(key, id) ⇒ Object



129
130
131
132
133
# File 'lib/emfrp/compile/c/codegen_context.rb', line 129

def serial(key, id)
  @serials ||= Hash.new{|h, k| h[k] = []}
  @serials[key] << id unless @serials[key].find{|x| x == id}
  return @serials[key].index{|x| x == id}
end

#tdef(x) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/emfrp/compile/c/codegen_context.rb', line 107

def tdef(x)
  case x
  when Typing::UnionType
    key = x.to_uniq_str
    if @top[:dict][:type_space][key] && @top[:dict][:type_space][key].get.is_a?(PrimTypeDef)
      @top[:dict][:type_space][key].get
    elsif @top[:dict][:itype_space][key]
      @top[:dict][:itype_space][key].get
    else
      raise "Assertion error: itype #{x.to_uniq_str} is undefined"
    end
  when Syntax
    tdef(x[:typing])
  else
    raise "Assertion error"
  end
end

#tref(x) ⇒ Object



125
126
127
# File 'lib/emfrp/compile/c/codegen_context.rb', line 125

def tref(x)
  tdef(x).ref_name(self)
end

#uniq_id_genObject



135
136
137
138
# File 'lib/emfrp/compile/c/codegen_context.rb', line 135

def uniq_id_gen
  @uniq_ids ||= (0..1000).to_a
  @uniq_ids.shift
end