Skip to content

Commit

Permalink
Add ability to have static primitives
Browse files Browse the repository at this point in the history
See String::allocate for a simple example.
  • Loading branch information
Evan Phoenix committed Jul 30, 2008
1 parent 3ae4602 commit 6506bea
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 5 deletions.
18 changes: 18 additions & 0 deletions vm/builtin_string.cpp
Expand Up @@ -10,6 +10,24 @@

namespace rubinius {

String* String::allocate(STATE, FIXNUM size) {
String *so;
size_t bytes = size->n2i();

so = (String*)state->om->new_object(G(string), String::fields);

so->num_bytes = Object::i2n(bytes);
so->characters = so->num_bytes;
so->encoding = Qnil;

OBJECT ba = ByteArray::create(state, bytes);
ba->bytes[bytes] = 0;

SET(so, data, ba);

return so;
}

String* String::create(STATE, const char* str, size_t bytes) {
String *so;

Expand Down
3 changes: 3 additions & 0 deletions vm/builtin_string.hpp
Expand Up @@ -15,6 +15,9 @@ namespace rubinius {
INTEGER hash; // slot
OBJECT shared; // slot

// Ruby.primitive :string_allocate
static String* allocate(STATE, FIXNUM size);

static String* create(STATE, const char* str, size_t bytes = 0);
static hashval hash_str(const unsigned char *bp, unsigned int sz);
static int string_equal_p(STATE, OBJECT self, OBJECT other);
Expand Down
57 changes: 52 additions & 5 deletions vm/field_extract.rb
Expand Up @@ -30,6 +30,30 @@ def generate_glue(klass="Primitives")
end
end

class CPPStaticPrimitive < CPPPrimitive
def generate_glue(klass="Primitives")
str = "bool #{klass}::#{@name}(STATE, VMExecutable* exec, Task* task, Message& msg) {\n"
i = -1
if arg_types.empty?
args = ""
else
args = ", " + arg_types.map { |t| "as<#{t}>(msg.get_argument(#{i += 1}))" }.join(", ")
end

str << " OBJECT ret;\n"
str << " try {\n"
str << " ret = #{@type}::#{@cpp_name}(state#{args});\n"
str << " } catch(PrimitiveFailed& e) {\n"
str << " abort(); // FIXME\n"
str << " return true;\n"
str << " }\n"
str << " task->primitive_return(ret, msg);\n"
str << " return false;\n"
str << "}\n"
return str
end
end

class CPPOverloadedPrimitive
def initialize(prim)
@name = prim.name
Expand Down Expand Up @@ -139,6 +163,19 @@ def add_primitive(name, cpp_name, ret, args, overload=false)
end
end

def add_static_primitive(name, cpp_name, ret, args)
prim = CPPStaticPrimitive.new(name, @name)
prim.cpp_name = cpp_name
prim.return_type = ret
prim.arg_types = args

if @primitives[name]
raise "Already defined primitive #{name}"
end

@primitives[name] = prim
end

def generate_gets
str = ""
all_fields.each do |name, idx, flags|
Expand Down Expand Up @@ -262,7 +299,11 @@ def strip_and_map(type, map)
type = type[0..-2]
end

return map[type]
if val = map[type]
return val
end

raise "Unable to resolve type '#{type}'"
end

def parse_stream(f)
Expand All @@ -289,7 +330,6 @@ def parse_stream(f)

idx = 0
while l = f.gets
next if /static/.match(l)
break if /\};/.match(l)
break if /^\s*class/.match(l)

Expand Down Expand Up @@ -325,14 +365,21 @@ def parse_stream(f)
prim = m[2]
prototype = f.gets

m = %r!\s*([\w_\*]+)\s+([\w_]+)\((.*)\)!.match(prototype)
args = m[3].split(/\s*,\s*/)
m = %r!\s*(static\s+)?([\w_\*]+)\s+([\w_]+)\((.*)\)!.match(prototype)
args = m[4].split(/\s*,\s*/)
if args.shift != "STATE"
raise "Invalid primitive #{prim}, STATE is not first argument"
end

arg_types = args.map { |a| strip_and_map(a.split(/\s+/, 2).first, @type_map) }
cpp.add_primitive prim, m[2], @type_map[m[1]], arg_types, overload
if m[1]
if overload
raise "Unable to overload static primitives."
end
cpp.add_static_primitive prim, m[3], @type_map[m[2]], arg_types
else
cpp.add_primitive prim, m[3], @type_map[m[2]], arg_types, overload
end

end
end
Expand Down

1 comment on commit 6506bea

@blullock
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn’t this be for ’alter codes syndrome[?].

Please sign in to comment.