Skip to content

Commit

Permalink
Merge pull request #2175 from Shopify/ruby-based-constant-pool
Browse files Browse the repository at this point in the history
Extract out usages of Ruby IDs
  • Loading branch information
soutaro authored Jan 9, 2025
2 parents b3c00e8 + 94b0308 commit 991bacb
Show file tree
Hide file tree
Showing 9 changed files with 381 additions and 113 deletions.
3 changes: 2 additions & 1 deletion ext/rbs_extension/extconf.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
$INCFLAGS << " -I$(srcdir)/../../include"

$VPATH << "$(srcdir)/../../src"
$VPATH << "$(srcdir)/../../src/util"
$VPATH << "$(srcdir)/ext/rbs_extension"

root_dir = File.expand_path('../../../', __FILE__)
$srcs = Dir.glob("#{root_dir}/src/*.c") +
$srcs = Dir.glob("#{root_dir}/src/**/*.c") +
Dir.glob("#{root_dir}/ext/rbs_extension/*.c")

append_cflags ['-std=gnu99']
Expand Down
34 changes: 24 additions & 10 deletions ext/rbs_extension/location.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,14 @@ static void check_children_cap(rbs_loc *loc) {
}
}

void rbs_loc_add_required_child(rbs_loc *loc, ID name, range r) {
void rbs_loc_add_required_child(rbs_loc *loc, rbs_constant_id_t name, range r) {
rbs_loc_add_optional_child(loc, name, r);

unsigned short last_index = loc->children->len - 1;
loc->children->required_p |= 1 << last_index;
}

void rbs_loc_add_optional_child(rbs_loc *loc, ID name, range r) {
void rbs_loc_add_optional_child(rbs_loc *loc, rbs_constant_id_t name, range r) {
check_children_cap(loc);

unsigned short i = loc->children->len++;
Expand Down Expand Up @@ -168,14 +168,20 @@ static VALUE location_end_pos(VALUE self) {
return INT2FIX(loc->rg.end);
}

static rbs_constant_id_t rbs_find_constant_id_from_ruby_symbol(VALUE symbol) {
VALUE name = rb_sym2str(symbol);

return rbs_constant_pool_find(RBS_GLOBAL_CONSTANT_POOL, (const uint8_t *) RSTRING_PTR(name), RSTRING_LEN(name));
}

static VALUE location_add_required_child(VALUE self, VALUE name, VALUE start, VALUE end) {
rbs_loc *loc = rbs_check_location(self);

range rg;
rg.start = rbs_loc_position(FIX2INT(start));
rg.end = rbs_loc_position(FIX2INT(end));

rbs_loc_add_required_child(loc, SYM2ID(name), rg);
rbs_loc_add_required_child(loc, rbs_find_constant_id_from_ruby_symbol(name), rg);

return Qnil;
}
Expand All @@ -187,15 +193,15 @@ static VALUE location_add_optional_child(VALUE self, VALUE name, VALUE start, VA
rg.start = rbs_loc_position(FIX2INT(start));
rg.end = rbs_loc_position(FIX2INT(end));

rbs_loc_add_optional_child(loc, SYM2ID(name), rg);
rbs_loc_add_optional_child(loc, rbs_find_constant_id_from_ruby_symbol(name), rg);

return Qnil;
}

static VALUE location_add_optional_no_child(VALUE self, VALUE name) {
rbs_loc *loc = rbs_check_location(self);

rbs_loc_add_optional_child(loc, SYM2ID(name), NULL_RANGE);
rbs_loc_add_optional_child(loc, rbs_find_constant_id_from_ruby_symbol(name), NULL_RANGE);

return Qnil;
}
Expand All @@ -221,9 +227,9 @@ static VALUE rbs_new_location_from_loc_range(VALUE buffer, rbs_loc_range rg) {
static VALUE location_aref(VALUE self, VALUE name) {
rbs_loc *loc = rbs_check_location(self);

ID id = SYM2ID(name);
rbs_constant_id_t id = rbs_find_constant_id_from_ruby_symbol(name);

if (loc->children != NULL) {
if (loc->children != NULL && id != RBS_CONSTANT_ID_UNSET) {
for (unsigned short i = 0; i < loc->children->len; i++) {
if (loc->children->entries[i].name == id) {
rbs_loc_range result = loc->children->entries[i].rg;
Expand All @@ -241,6 +247,11 @@ static VALUE location_aref(VALUE self, VALUE name) {
rb_raise(rb_eRuntimeError, "Unknown child name given: %s", RSTRING_PTR(string));
}

static VALUE rbs_constant_to_ruby_symbol(rbs_constant_t *constant) {
// Casts back the Ruby Symbol that was inserted by `rbs_constant_pool_insert_constant()`.
return (VALUE) constant;
}

static VALUE location_optional_keys(VALUE self) {
VALUE keys = rb_ary_new();

Expand All @@ -252,8 +263,9 @@ static VALUE location_optional_keys(VALUE self) {

for (unsigned short i = 0; i < children->len; i++) {
if (RBS_LOC_OPTIONAL_P(loc, i)) {
rb_ary_push(keys, ID2SYM(children->entries[i].name));

rbs_constant_t *key_id = rbs_constant_pool_id_to_constant(RBS_GLOBAL_CONSTANT_POOL, children->entries[i].name);
VALUE key_sym = rbs_constant_to_ruby_symbol(key_id);
rb_ary_push(keys, key_sym);
}
}

Expand All @@ -271,7 +283,9 @@ static VALUE location_required_keys(VALUE self) {

for (unsigned short i = 0; i < children->len; i++) {
if (RBS_LOC_REQUIRED_P(loc, i)) {
rb_ary_push(keys, ID2SYM(children->entries[i].name));
rbs_constant_t *key_id = rbs_constant_pool_id_to_constant(RBS_GLOBAL_CONSTANT_POOL, children->entries[i].name);
VALUE key_sym = rbs_constant_to_ruby_symbol(key_id);
rb_ary_push(keys, key_sym);
}
}

Expand Down
7 changes: 4 additions & 3 deletions ext/rbs_extension/location.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "ruby.h"
#include "lexer.h"
#include "rbs/util/rbs_constant_pool.h"

/**
* RBS::Location class
Expand All @@ -15,7 +16,7 @@ typedef struct {
} rbs_loc_range;

typedef struct {
ID name;
rbs_constant_id_t name;
rbs_loc_range rg;
} rbs_loc_entry;

Expand Down Expand Up @@ -58,14 +59,14 @@ void rbs_loc_alloc_children(rbs_loc *loc, unsigned short cap);
*
* Allocate memory for children with rbs_loc_alloc_children before calling this function.
* */
void rbs_loc_add_required_child(rbs_loc *loc, ID name, range r);
void rbs_loc_add_required_child(rbs_loc *loc, rbs_constant_id_t name, range r);

/**
* Add an optional child range with given name.
*
* Allocate memory for children with rbs_loc_alloc_children before calling this function.
* */
void rbs_loc_add_optional_child(rbs_loc *loc, ID name, range r);
void rbs_loc_add_optional_child(rbs_loc *loc, rbs_constant_id_t name, range r);

/**
* Returns RBS::Location object with start/end positions.
Expand Down
13 changes: 12 additions & 1 deletion ext/rbs_extension/main.c
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
#include "rbs_extension.h"
#include "rbs/util/rbs_constant_pool.h"

#include "ruby/vm.h"

static
void Deinit_rbs_extension(ruby_vm_t *_) {
rbs_constant_pool_free(RBS_GLOBAL_CONSTANT_POOL);
}

void
Init_rbs_extension(void)
{
#ifdef HAVE_RB_EXT_RACTOR_SAFE
rb_ext_ractor_safe(true);
#endif
#endif
rbs__init_constants();
rbs__init_location();
rbs__init_parser();

rbs_constant_pool_init(RBS_GLOBAL_CONSTANT_POOL, 0);
ruby_vm_at_exit(Deinit_rbs_extension);
}
Loading

0 comments on commit 991bacb

Please sign in to comment.