Here's a little toy I messed with today for patching Rubinius's primitives.rb build-time script to produce JRuby-compatible Java code instead of C. Given that Evan's new C++-based VM is probably going to eliminate or drastically change the way primitives work, this probably won't see any real use...but I think if we could provide all of Rubinius's primitives, we'd be most of the way to reusing their entire collection of core class impls.

If, of course, that's something we want to do.

- Charlie
class ShotgunPrimitives
  def generate_select(fd, op="prim")
    primitives = @@primitives

    File.open("RubiniusPrimitives.java", "w") do |f|
      primitives.each do |prim_name|
        f.puts "public static IRubyObject 
cpu_primitive_#{prim_name}(ThreadContext context, IRubyObject self, 
IRubyObject[] args, Block block) {"
        f.puts send(prim_name)
        f.puts "}"
      end

      f.puts "\npublic static abstract class PrimFunc {"
      f.puts "    public abstract IRubyObject call(ThreadContext context, 
IRubyObject self, IRubyObject[] args, Block bloc);"
      f.puts "}"
      f.puts "\npublic static final PrimFunc[] funcs = { NULL, "
      
      primitives.each do |prim_name|
        f.puts "    new PrimFunc() {"
        f.puts "        public IRubyObject call(ThreadContext context, 
IRubyObject self, IRubyObject[] args, Block bloc) {"
        f.puts "            return #{prim_name}(context, self, args, block);"
        f.puts "        }"
        f.puts "    },"
      end
      
      f.puts "\npublic static PrimFunc cpu_lookup_primitive(int index) {"
      f.puts "  return funcs[index];"
      f.puts "}"

      f.puts "public static Map cpu_populate_prim_names() {"
      f.puts "    Map tbl = new HashMap();"
      primitives.each_with_index do |prim_name,i|
        f.puts "    tbl.put(#{i + 1}, \"#{prim_name}\");"
        f.puts "    tbl.put(\"#{prim_name}\", #{i + 1});"
      end
      f.puts "return tbl;"
      f.puts "}"
    end
  end
  
  def add
    <<-CODE
    #{check_arity(1)};
    IRubyObject arg = args[0];
    #{guard(fixnum?('arg'))};
    if (#{fixnum?('arg')}) {
        return #{to_fixnum('arg')}.op_plus(context, arg);
    } else if (#{bignum?('arg')}) {
        return #{to_bignum('arg')}.op_plus(context, arg);
    } else if (#{float?('arg')}) {
        return #{to_float('arg')}.op_plus(context, arg);
    } else {
        throw new RuntimeException(\"primitive :add failed to find a type 
match\");
    }
    CODE
  end
  
  private
  
  def check_arity(n)
    "Arity.checkArgumentCount(context.getRuntime(), args, #{n}, #{n})"
  end
  
  def guard(expr)
    "assert #{expr} : \"'#{expr}' failed\""
  end
  
  def fixnum?(value_expr)
    "#{value_expr} instanceof RubyFixnum"
  end
  
  def to_fixnum(value_expr)
    "(RubyFixnum(#{value_expr}))"
  end
  
  def bignum?(value_expr)
    "#{value_expr} instanceof RubyBignum"
  end
  
  def to_bignum(value_expr)
    "(RubyBignum(#{value_expr}))"
  end
  
  def float?(value_expr)
    "#{value_expr} instanceof RubyFloat"
  end
  
  def to_float(value_expr)
    "(RubyFloat(#{value_expr}))"
  end
end

---------------------------------------------------------------------
To unsubscribe from this list, please visit:

    http://xircles.codehaus.org/manage_email

Reply via email to