Skip to content

Commit bec4a54

Browse files
committed
Add batch parsing API
1 parent 3acbb70 commit bec4a54

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

benchmarks3.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
require "rbs"
2+
require "benchmark/ips"
3+
require "csv"
4+
require "pathname"
5+
6+
files = {}
7+
ARGV.each do |file|
8+
content = File.read(file)
9+
files[file] = RBS::Buffer.new(content: content, name: Pathname(file))
10+
end
11+
12+
puts "Benchmarking parsing #{files.size} files..."
13+
14+
Benchmark.ips do |x|
15+
x.report("batch parsing") do
16+
RBS::Parser._parse_signatures(files)
17+
end
18+
19+
x.compare!
20+
end

ext/rbs_extension/main.c

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,53 @@ static VALUE rbsparser_lex(VALUE self, VALUE buffer, VALUE end_pos) {
452452
return results;
453453
}
454454

455+
VALUE rbsparser_parse_signatures(VALUE self, VALUE files) {
456+
Check_Type(files, T_HASH);
457+
458+
VALUE result_hash = rb_hash_new();
459+
VALUE keys = rb_funcall(files, rb_intern("keys"), 0);
460+
461+
for (long i = 0; i < RARRAY_LEN(keys); i++) {
462+
VALUE file_path = rb_ary_entry(keys, i);
463+
VALUE buffer = rb_hash_aref(files, file_path);
464+
465+
VALUE string = rb_funcall(buffer, rb_intern("content"), 0);
466+
StringValue(string);
467+
rb_encoding *encoding = rb_enc_get(string);
468+
469+
// Prepare parser
470+
rbs_parser_t *parser = alloc_parser_from_buffer(buffer, 0, RSTRING_LEN(string));
471+
struct parse_signature_arg arg = {
472+
.buffer = buffer,
473+
.encoding = encoding,
474+
.parser = parser,
475+
.require_eof = false
476+
};
477+
478+
VALUE entry = rb_hash_new();
479+
480+
int state = 0;
481+
VALUE ast = rb_protect(parse_signature_try, (VALUE) &arg, &state);
482+
483+
if (state == 0) {
484+
// Success: store AST
485+
rb_hash_aset(entry, ID2SYM(rb_intern("ast")), ast);
486+
} else {
487+
// Error: store exception
488+
VALUE err = rb_errinfo();
489+
rb_set_errinfo(Qnil); // Clear the error info
490+
rb_hash_aset(entry, ID2SYM(rb_intern("error")), err);
491+
}
492+
493+
rb_hash_aset(result_hash, file_path, entry);
494+
495+
ensure_free_parser((VALUE) parser);
496+
RB_GC_GUARD(string);
497+
}
498+
499+
return result_hash;
500+
}
501+
455502
void rbs__init_parser(void) {
456503
RBS_Parser = rb_define_class_under(RBS, "Parser", rb_cObject);
457504
rb_gc_register_mark_object(RBS_Parser);
@@ -471,6 +518,7 @@ void rbs__init_parser(void) {
471518
rb_define_singleton_method(RBS_Parser, "_parse_inline_leading_annotation", rbsparser_parse_inline_leading_annotation, 4);
472519
rb_define_singleton_method(RBS_Parser, "_parse_inline_trailing_annotation", rbsparser_parse_inline_trailing_annotation, 4);
473520
rb_define_singleton_method(RBS_Parser, "_lex", rbsparser_lex, 2);
521+
rb_define_singleton_method(RBS_Parser, "_parse_signatures", rbsparser_parse_signatures, 1);
474522
}
475523

476524
static void Deinit_rbs_extension(ruby_vm_t *_) {

0 commit comments

Comments
 (0)