Class: Yadriggy::C::CodeGen
- Inherits:
-
Yadriggy::Checker
- Object
- Yadriggy::Checker
- Yadriggy::C::CodeGen
- Defined in:
- lib/yadriggy/c/codegen.rb
Overview
C-code generator
Since Checker implements Visitor pattern, use it for code generation.
Direct Known Subclasses
Constant Summary
Constants included from Yadriggy
Class Method Summary collapse
-
.c_src_file(dir, lib_name) ⇒ String
Obtains the file name of the generated source code.
Instance Method Summary collapse
-
#build_cmd ⇒ String
Obtains compiler command.
-
#build_lib(lib_name, dir = './') ⇒ void
Runs a compiler.
-
#c_function(expr) ⇒ void
Prints a function implementation.
-
#c_function_name(expr) ⇒ String
Gets the function name in C after the translation from a Ruby method into a C function.
- #call_with_block(call_ast) ⇒ Object
-
#expand_functions(func_names, func_types) ⇒ Array<String>, Array<Type>
Appends implicitly generated functions.
-
#headers ⇒ void
Prints
#include
derectives. -
#initialize(printer, typechecker, public_methods) ⇒ CodeGen
constructor
printer is a Printer object.
-
#name_global_variables ⇒ void
Gives a name to each global variable.
-
#preamble ⇒ Object
Prints a preamble.
-
#printer ⇒ Object
Gets the printer given when object construction.
-
#prototype(expr) ⇒ void
Prints a function prototype.
-
#typechecker ⇒ Object
Gets the type checker.
-
#variable_declarations ⇒ void
Prints variable declarations.
Methods inherited from Yadriggy::Checker
#ast, #ast_env, #check, #check_all, #check_later, #error!, #error_found!, #error_messages, #errors?, #last_error, #make_base_env, #proceed, rule
Methods included from Yadriggy
debug, debug=, define_syntax, reify, reset_pry
Constructor Details
#initialize(printer, typechecker, public_methods) ⇒ CodeGen
printer is a Printer object. Only main_method is converted into an extern function. Other methods are converted into static functions.
20 21 22 23 24 25 26 27 28 29 |
# File 'lib/yadriggy/c/codegen.rb', line 20 def initialize(printer, typechecker, public_methods) super() @printer = printer @typechecker = typechecker @func_counter = 0 @func_names = {} @public_methods = {} public_methods.each {|m| @public_methods[m.tree] = m.tree } @gvariables = {} end |
Class Method Details
.c_src_file(dir, lib_name) ⇒ String
Obtains the file name of the generated source code. A subclass can redefine this method.
270 271 272 |
# File 'lib/yadriggy/c/codegen.rb', line 270 def self.c_src_file(dir, lib_name) "#{dir}#{lib_name}.c" end |
Instance Method Details
#build_cmd ⇒ String
Obtains compiler command. A subclass can redefine this method.
293 294 295 |
# File 'lib/yadriggy/c/codegen.rb', line 293 def build_cmd Config::Compiler end |
#build_lib(lib_name, dir = './') ⇒ void
This method returns an undefined value.
Runs a compiler. A subclass can redefine this method.
280 281 282 283 284 285 286 287 |
# File 'lib/yadriggy/c/codegen.rb', line 280 def build_lib(lib_name, dir='./') file_name = self.class.c_src_file(dir, lib_name) lib_file_name = "#{dir}lib#{lib_name}#{Config::LibExtension}" cmd = "#{build_cmd} #{Config::CoptOutput}#{lib_file_name} #{file_name}" system(cmd) status = $?.exitstatus raise BuildError.new(["exit #{status}"]) if status > 0 end |
#c_function(expr) ⇒ void
This method returns an undefined value.
Prints a function implementation.
372 373 374 |
# File 'lib/yadriggy/c/codegen.rb', line 372 def c_function(expr) check(expr) end |
#c_function_name(expr) ⇒ String
Gets the function name in C after the translation from a Ruby method into a C function.
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
# File 'lib/yadriggy/c/codegen.rb', line 381 def c_function_name(expr) return expr.name.name if expr.is_a?(Def) && @public_methods.include?(expr) fname_str = @func_names[expr] if fname_str.nil? @func_counter += 1 fname_str = if expr.is_a?(Block) "yadriggy_blk#{@func_counter}" else "#{expr.name.name}_#{@func_counter}" end @func_names[expr] = fname_str end fname_str end |
#call_with_block(call_ast) ⇒ Object
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/yadriggy/c/codegen.rb', line 166 def call_with_block(call_ast) loop_param = call_ast.block.params[0] @printer << 'for (' << c_type(RubyClass::Integer) << ' ' check(loop_param) @printer << ' = (' check(ast.receiver) @printer << ') - 1; ' check(loop_param) @printer << ' >= 0; ' check(loop_param) @printer << '--) {' @printer.down local_var_declarations(ast.block) check(ast.block.body) @printer << ';' unless ast.block.body.is_a?(Exprs) @printer.up @printer << '}' << :nl end |
#expand_functions(func_names, func_types) ⇒ Array<String>, Array<Type>
Appends implicitly generated functions. A subclass can override this method. The original implementation does not append any.
364 365 366 |
# File 'lib/yadriggy/c/codegen.rb', line 364 def (func_names, func_types) return func_names, func_types end |
#headers ⇒ void
This method returns an undefined value.
Prints #include
derectives.
300 301 302 303 |
# File 'lib/yadriggy/c/codegen.rb', line 300 def headers() Config::Headers.each {|h| @printer << h << :nl } @printer << :nl end |
#name_global_variables ⇒ void
This method returns an undefined value.
Gives a name to each global variable.
307 308 309 310 311 312 313 |
# File 'lib/yadriggy/c/codegen.rb', line 307 def name_global_variables() id = 0 @typechecker.instance_variables.each do |obj| @gvariables[obj] = "_gvar_#{id}_" id += 1 end end |
#preamble ⇒ Object
Prints a preamble. This method is invoked right after printing function prototypes. A subclass can override this method. The original implementation does not print anything.
353 354 |
# File 'lib/yadriggy/c/codegen.rb', line 353 def preamble end |
#printer ⇒ Object
Gets the printer given when object construction.
39 40 41 |
# File 'lib/yadriggy/c/codegen.rb', line 39 def printer @printer end |
#prototype(expr) ⇒ void
This method returns an undefined value.
Prints a function prototype.
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 |
# File 'lib/yadriggy/c/codegen.rb', line 332 def prototype(expr) t = @typechecker.type(expr) return if ForeignMethodType.role(t) @printer << 'static ' if @public_methods[expr].nil? fname_str = c_function_name(expr) mt = MethodType.role(t) if mt parameters(expr, fname_str, mt) @printer << ';' << :nl else error!(expr, "bad method #{fname_str}") end self end |
#typechecker ⇒ Object
Gets the type checker.
33 34 35 |
# File 'lib/yadriggy/c/codegen.rb', line 33 def typechecker @typechecker end |
#variable_declarations ⇒ void
This method returns an undefined value.
Prints variable declarations.
317 318 319 320 321 322 323 324 325 326 |
# File 'lib/yadriggy/c/codegen.rb', line 317 def variable_declarations() @gvariables.each do |obj, name| if obj.is_a?(CType::CArray) @printer << 'static ' << c_type(obj.type) << ' ' << name obj.sizes.each {|s| @printer << '[' << s << ']' } @printer << ';' << :nl end end @printer << :nl end |