Class: RubyToRubyC
- Inherits:
-
RubyToAnsiC
- Object
- SexpProcessor
- RubyToAnsiC
- RubyToRubyC
- Defined in:
- lib/ruby_to_ruby_c.rb
Constant Summary
Constants inherited from RubyToAnsiC
RubyToAnsiC::METHOD_MAP, RubyToAnsiC::VERSION
Instance Attribute Summary
Attributes inherited from RubyToAnsiC
Class Method Summary collapse
- .c_type(x) ⇒ Object
-
.translator ⇒ Object
Lazy initializer for the composite RubytoC translator chain.
Instance Method Summary collapse
-
#initialize ⇒ RubyToRubyC
constructor
:nodoc:.
- #process_call(exp) ⇒ Object
- #process_false(exp) ⇒ Object
- #process_gvar(exp) ⇒ Object
-
#process_iter(exp) ⇒ Object
Iterators for loops.
-
#process_lasgn(exp) ⇒ Object
Assignment to a local variable.
- #process_lit(exp) ⇒ Object
-
#process_nil(exp) ⇒ Object
Nil, currently ruby nil, not C NULL (0).
- #process_str(exp) ⇒ Object
- #process_true(exp) ⇒ Object
Methods inherited from RubyToAnsiC
#no, #preamble, #process_and, #process_arglist, #process_args, #process_array, #process_block, #process_class, #process_const, #process_cvar, #process_dasgn_curr, #process_defn, #process_dummy, #process_dvar, #process_error, #process_hash, #process_iasgn, #process_if, #process_ivar, #process_lvar, #process_not, #process_op_asgn_or, #process_or, #process_return, #process_scope, #process_while, translate, translate_all_of
Constructor Details
#initialize ⇒ RubyToRubyC
:nodoc:
40 41 42 |
# File 'lib/ruby_to_ruby_c.rb', line 40 def initialize # :nodoc: super end |
Class Method Details
.c_type(x) ⇒ Object
36 37 38 |
# File 'lib/ruby_to_ruby_c.rb', line 36 def self.c_type(x) "VALUE" end |
.translator ⇒ Object
Lazy initializer for the composite RubytoC translator chain.
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# File 'lib/ruby_to_ruby_c.rb', line 12 def self.translator # TODO: FIX, but write a test first unless defined? @translator then @translator = CompositeSexpProcessor.new @translator << Rewriter.new @translator << TypeChecker.new @translator << R2CRewriter.new @translator << RubyToRubyC.new @translator.on_error_in(:defn) do |processor, exp, err| result = processor.expected.new case result when Array then result << :error end msg = "// ERROR: #{err.class}: #{err}" msg += " in #{exp.inspect}" unless exp.nil? or $TESTING msg += " from #{caller.join(', ')}" unless $TESTING result << msg result end end @translator end |
Instance Method Details
#process_call(exp) ⇒ Object
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/ruby_to_ruby_c.rb', line 44 def process_call(exp) receiver = process(exp.shift) || "self" name = exp.shift.to_s args = [process(exp.shift)].flatten.compact name = '===' if name =~ /^case_equal_/ # undo the evils of TypeChecker if args.empty? args = "0" else args = "#{args.size}, #{args.join(", ")}" end "rb_funcall(#{receiver}, rb_intern(#{name.inspect}), #{args})" end |
#process_false(exp) ⇒ Object
60 61 62 |
# File 'lib/ruby_to_ruby_c.rb', line 60 def process_false(exp) "Qfalse" end |
#process_gvar(exp) ⇒ Object
64 65 66 67 |
# File 'lib/ruby_to_ruby_c.rb', line 64 def process_gvar(exp) var = exp.shift "rb_gv_get(#{var.to_s.inspect})" end |
#process_iter(exp) ⇒ Object
Iterators for loops. After rewriter nearly all iter nodes should be able to be interpreted as a for loop. If not, then you are doing something not supported by C in the first place.
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
# File 'lib/ruby_to_ruby_c.rb', line 74 def process_iter(exp) out = [] # Only support enums in C-land raise UnsupportedNodeError if exp[0][1].nil? # HACK ugly @env.scope do enum = exp[0][1][1] # HACK ugly t(:iter, t(:call, lhs <-- get lhs call = process exp.shift var = process(exp.shift).intern # semi-HACK-y body = process exp.shift index = "index_#{var}" body += ";" unless body =~ /[;}]\Z/ body.gsub!(/\n\n+/, "\n") out << "unsigned long #{index};" out << "unsigned long arrays_max = FIX2LONG(rb_funcall(arrays, rb_intern(\"size\"), 0));" out << "for (#{index} = 0; #{index} < arrays_max; ++#{index}) {" out << "VALUE x = rb_funcall(arrays, rb_intern(\"at\"), 1, LONG2FIX(index_x));" out << body out << "}" end return out.join("\n") end |
#process_lasgn(exp) ⇒ Object
Assignment to a local variable.
TODO: figure out array issues and clean up.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 |
# File 'lib/ruby_to_ruby_c.rb', line 104 def process_lasgn(exp) out = "" var = exp.shift value = exp.shift # grab the size of the args, if any, before process converts to a string arg_count = 0 arg_count = value.length - 1 if value.first == :array args = value exp_type = exp.sexp_type @env.add var.to_sym, exp_type var_type = self.class.c_type exp_type if exp_type.list? then assert_type args, :array raise "array must be of one type" unless args.sexp_type == Type.homo args.shift # :arglist out << "#{var} = rb_ary_new2(#{args.length});\n" args.each_with_index do |o,i| out << "rb_ary_store(#{var}, #{i}, #{process o});\n" end else out << "#{var} = #{process args}" end out.sub!(/;\n\Z/, '') return out end |
#process_lit(exp) ⇒ Object
137 138 139 140 141 142 143 144 145 146 147 148 149 150 |
# File 'lib/ruby_to_ruby_c.rb', line 137 def process_lit(exp) value = exp.shift case value when Fixnum then "LONG2NUM(#{value})" when Float then "DBL2NUM(#{value})" when Symbol then "rb_intern(#{value.to_s.inspect})" else raise "Bug! no: Unknown literal #{value}:#{value.class}" end end |
#process_nil(exp) ⇒ Object
Nil, currently ruby nil, not C NULL (0).
155 156 157 |
# File 'lib/ruby_to_ruby_c.rb', line 155 def process_nil(exp) return "Qnil" end |
#process_str(exp) ⇒ Object
159 160 161 162 |
# File 'lib/ruby_to_ruby_c.rb', line 159 def process_str(exp) value = exp.shift "rb_str_new2(#{value.inspect})" end |
#process_true(exp) ⇒ Object
164 165 166 |
# File 'lib/ruby_to_ruby_c.rb', line 164 def process_true(exp) "Qtrue" end |