class CRewriter
CRewriter
(should probably move this out to its own file) does rewritings that are language specific to C.
Constants
- REWRITES
REWRITES
maps a function signature to a proc responsible for generating the appropriate sexp for that rewriting.
Attributes
env[R]
extra_methods[R]
Public Instance Methods
free()
click to toggle source
# File lib/crewriter.rb, line 49 def free # REFACTOR: this is a violation of responsibility, should be in Env parent = @env.env[0..-2] bound_in_parent = parent.map { |h| h.keys }.flatten env = @env.all free = env.select { |k, (_, v)| bound_in_parent.include? k or not v } vars = free.map { |k, (t, _)| [k, t] } return vars end
process(exp)
click to toggle source
def rewrite exp
result = super result.c_type ||= exp.c_type if Sexp === exp and exp.c_type result
end
Calls superclass method
# File lib/crewriter.rb, line 43 def process exp result = super result.c_type ||= exp.c_type if Sexp === exp and exp.c_type result end
process_call(exp)
click to toggle source
Rewrites function calls by looking them up in the REWRITES
map. If a match exists, it invokes the block passing in the lhs, rhs, and function name. If one does not exist, it simply repacks the sexp and sends it along.
# File lib/crewriter.rb, line 66 def process_call(exp) lhs = process exp.shift name = exp.shift rhs = process exp.shift lhs_type = lhs.c_type rescue nil type_signature = [lhs_type, name] type_signature += rhs[1..-1].map { |sexp| sexp.c_type }.to_a unless rhs.nil? result = if REWRITES.has_key? type_signature then REWRITES[type_signature].call(lhs, name, rhs) else t(:call, lhs, name, rhs, exp.c_type) end return result end
process_class(exp)
click to toggle source
# File lib/crewriter.rb, line 84 def process_class(exp) klassname = exp.shift superklassname = exp.shift methods = [] until exp.empty? do methods << process(exp.shift) end @extra_methods.reverse_each do |defx| methods.unshift defx end @extra_methods.clear result = t(:class, klassname, superklassname, CType.zclass) result.push(*methods) return result end
process_iter(exp)
click to toggle source
TODO register statics
# File lib/crewriter.rb, line 106 def process_iter(exp) iter_method_name = Unique.next value_var_name = Unique.next value_var_type = CType.unknown memo_var_name = Unique.next call = process exp.shift vars = process exp.shift body = nil free_vars = @env.scope do body = process exp.shift self.free.map { |name, type| [name, :"static_#{Unique.next}", type] } end var_names = var_names_in vars frees = t(:array, CType.void) statics = t(:array, CType.void) defx_body_block = t(:block) # set statics first so block vars can update statics free_vars.each do |name, static_name, type| # free vars go on both sides frees << t(:lvar, name, type) statics << t(:lvar, static_name, type) defx_body_block << t(:lasgn, name, t(:lvar, static_name, type), type) end if var_names.length == 1 then # expand block args to lasgn value_var_type = var_names.first.last defx_body_block << t(:lasgn, var_names.first.first, t(:lvar, value_var_name, var_names.first.last), var_names.first.last) else # expand block args to masgn value_var_type = CType.value dyn_vars = t(:array) var_names.each do |name, type| dyn_vars << t(:lasgn, name, nil, type) end defx_body_block << t(:masgn, dyn_vars, t(:to_ary, t(:lvar, value_var_name, CType.value))) end defx_body_block << body free_vars.each do |name, static_name, type| defx_body_block << t(:lasgn, static_name, t(:lvar, name, type), type) @extra_methods << t(:static, "static VALUE #{static_name};", CType.fucked) end defx_body_block << t(:return, t(:nil, CType.value)) defx = t(:defx, iter_method_name, t(:args, t(value_var_name, value_var_type), t(memo_var_name, CType.value)), t(:scope, defx_body_block), CType.void) @extra_methods << defx args = t(:args, frees, statics, CType.void) return t(:iter, call, args, iter_method_name) end
process_lasgn(exp)
click to toggle source
# File lib/crewriter.rb, line 182 def process_lasgn(exp) name = exp.shift value = process(exp.shift) @env.add name, exp.c_type @env.set_val name, true return t(:lasgn, name, value, exp.c_type) end
process_lvar(exp)
click to toggle source
# File lib/crewriter.rb, line 192 def process_lvar(exp) name = exp.shift @env.add name, CType.value @env.lookup name rescue @env.set_val name, false return t(:lvar, name, exp.c_type) end
var_names_in(exp)
click to toggle source
# File lib/crewriter.rb, line 201 def var_names_in(exp) return [[exp.last, exp.c_type]] if exp.length == 2 and not Sexp === exp.last var_names = [] exp.each_of_type :dasgn_curr do |sexp| var_names << [sexp.sexp_body.first, sexp.c_type] end return var_names end