diff --git a/.travis.yml b/.travis.yml index 679141b..f665446 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,8 @@ language: ruby cache: bundler rvm: - - 2.3.6 - - 2.4.3 - - 2.5.0 + - 2.6.5 + - 2.7.0 git: depth: 10 @@ -22,7 +21,7 @@ os: matrix: include: - script: bundle exec rake rubocop - rvm: 2.5.0 + rvm: 2.6.5 env: -TREE_SITTER_PARSER_DIR=$TRAVIS_BUILD_DIR/test/tree-sitter/fixtures/parsers diff --git a/ext/tree-sitter/document.c b/ext/tree-sitter/document.c index c56ed6c..3cd9b3b 100644 --- a/ext/tree-sitter/document.c +++ b/ext/tree-sitter/document.c @@ -1,5 +1,11 @@ #include "document.h" +#if SIZEOF_VOIDP == SIZEOF_LONG +# define NUM2PTR(x) ((void*)(NUM2ULONG(x))) +#else +# define NUM2PTR(x) ((void*)(NUM2ULL(x))) +#endif + VALUE rb_cDocument; /* @@ -18,66 +24,22 @@ static VALUE rb_document_alloc(VALUE self) } /* - * Public: Creates a new document - * - */ -VALUE rb_document_new(VALUE self, VALUE rb_input_string, VALUE rb_options) -{ - TSDocument *document; - VALUE rb_language; - - Check_Type(rb_input_string, T_STRING); - Check_Type (rb_options, T_HASH); - - rb_language = rb_hash_aref(rb_options, CSTR2SYM("language")); - Check_Type(rb_language, T_STRING); - - Data_Get_Struct(self, TSDocument, document); - - rb_document_set_language(self, rb_language); - rb_document_set_input_string(self, rb_input_string); - rb_document_parse(self); - - return self; -} - - -/* - * Public: Set the language type of a document. + * Private: Set the language type of a document. * - * lang - A {String} identifying the language. + * ptr - A {Numeric} address of the function that returns the data type for treesitter. * * Returns nothing. */ -VALUE rb_document_set_language(VALUE self, VALUE lang) +static VALUE rb_document_set_language(VALUE self, VALUE ptr) { TSDocument *document; - char *language_name; - void *handle; - char *error; - Check_Type(lang, T_STRING); - - language_name = StringValueCStr(lang); - const TSLanguage * (*language_func)(); - handle = dlopen(BUNDLE_PATH, RTLD_LAZY); - if (!handle) { - rb_raise(rb_eDocumentError, "%s", dlerror()); - } - - dlerror(); /* Clear any existing error */ - - *(void **) (&language_func) = dlsym(handle, language_name); - - if ((error = dlerror()) != NULL) { - rb_raise(rb_eDocumentError, "%s", error); - } - Data_Get_Struct(self, TSDocument, document); + language_func = NUM2PTR(ptr); + ts_document_set_language(document, (*language_func)()); - dlclose(handle); return Qnil; } @@ -89,7 +51,7 @@ VALUE rb_document_set_language(VALUE self, VALUE lang) * * Returns nothing. */ -VALUE rb_document_set_input_string(VALUE self, VALUE rb_input_string) +static VALUE rb_document_set_input_string(VALUE self, VALUE rb_input_string) { TSDocument *document; Check_Type(rb_input_string, T_STRING); @@ -107,7 +69,7 @@ VALUE rb_document_set_input_string(VALUE self, VALUE rb_input_string) * * Returns true if successful. */ -VALUE rb_document_parse(VALUE self) +static VALUE rb_document_parse(VALUE self) { TSDocument *document; @@ -123,7 +85,7 @@ VALUE rb_document_parse(VALUE self) * * Returns a {Node}. */ -VALUE rb_document_root_node(VALUE self) +static VALUE rb_document_root_node(VALUE self) { TSDocument *document; @@ -133,16 +95,14 @@ VALUE rb_document_root_node(VALUE self) return rb_new_node(ts_node, document); } -void init_document() +void init_document(VALUE tree_sitter) { - VALUE tree_sitter = rb_define_module("TreeSitter"); - rb_eDocumentError = rb_define_class_under(tree_sitter, "DocumentError", rb_eStandardError); VALUE rb_cDocument = rb_define_class_under(tree_sitter, "Document", rb_cObject); rb_define_alloc_func(rb_cDocument, rb_document_alloc); - rb_define_method(rb_cDocument, "initialize", rb_document_new, 2); - rb_define_method(rb_cDocument, "language=", rb_document_set_language, 1); + rb_define_const(rb_cDocument, "BUNDLE_PATH", rb_str_new2(BUNDLE_PATH)); + rb_define_private_method(rb_cDocument, "set_language", rb_document_set_language, 1); rb_define_method(rb_cDocument, "input_string=", rb_document_set_input_string, 1); rb_define_method(rb_cDocument, "parse", rb_document_parse, 0); rb_define_method(rb_cDocument, "root_node", rb_document_root_node, 0); diff --git a/ext/tree-sitter/document.h b/ext/tree-sitter/document.h index a0c200a..60e5fb2 100644 --- a/ext/tree-sitter/document.h +++ b/ext/tree-sitter/document.h @@ -2,16 +2,10 @@ #define RB_TREE_SITTER_DOCUMENT_H #include "ruby.h" -#include #include "tree-sitter.h" static VALUE rb_eDocumentError; -void init_document(); -static VALUE rb_document_alloc(VALUE self); -VALUE rb_document_new(VALUE self, VALUE rb_str, VALUE rb_options); -VALUE rb_document_set_language(VALUE self, VALUE lang); -VALUE rb_document_set_input_string(VALUE self, VALUE str); -VALUE rb_document_parse(VALUE self); +void init_document(VALUE); #endif diff --git a/ext/tree-sitter/node.c b/ext/tree-sitter/node.c index 751ba1b..b739df9 100644 --- a/ext/tree-sitter/node.c +++ b/ext/tree-sitter/node.c @@ -3,17 +3,12 @@ VALUE rb_cNode; VALUE rb_cPoint; -static void rb_node_free(void *n) -{ - free(n); -} - VALUE rb_new_node(TSNode ts_node, TSDocument *ts_document) { - AstNode *node = malloc(sizeof(AstNode)); + AstNode *node = xmalloc(sizeof(AstNode)); node->ts_node = ts_node; node->ts_document = ts_document; - return Data_Wrap_Struct(rb_cNode, NULL, rb_node_free, node); + return Data_Wrap_Struct(rb_cNode, NULL, xfree, node); } /* @@ -21,7 +16,7 @@ VALUE rb_new_node(TSNode ts_node, TSDocument *ts_document) * * Returns a {String}. */ -VALUE rb_node_to_s(VALUE self) +static VALUE rb_node_to_s(VALUE self) { AstNode *node; Data_Get_Struct(self, AstNode, node); @@ -34,7 +29,7 @@ VALUE rb_node_to_s(VALUE self) * * Returns a {String}. */ -VALUE rb_node_type(VALUE self) +static VALUE rb_node_type(VALUE self) { AstNode *node; Data_Get_Struct(self, AstNode, node); @@ -42,26 +37,21 @@ VALUE rb_node_type(VALUE self) return rb_str_new_cstr(ts_node_type(node->ts_node, node->ts_document)); } -void rb_point_free(void *p) -{ - free(p); -} - /* * Public: Get the starting position for a node. * * Returns a {Point}. */ -VALUE rb_node_start_point(VALUE self) +static VALUE rb_node_start_point(VALUE self) { AstNode *node; Data_Get_Struct(self, AstNode, node); TSPoint start = ts_node_start_point(node->ts_node); - Point *point = malloc(sizeof(Point)); + Point *point = xmalloc(sizeof(Point)); point->ts_point = start; - return Data_Wrap_Struct(rb_cPoint, NULL, rb_point_free, point); + return Data_Wrap_Struct(rb_cPoint, NULL, xfree, point); } /* @@ -69,17 +59,17 @@ VALUE rb_node_start_point(VALUE self) * * Returns a {Point}. */ -VALUE rb_node_end_point(VALUE self) +static VALUE rb_node_end_point(VALUE self) { AstNode *node; Data_Get_Struct(self, AstNode, node); TSPoint start = ts_node_end_point(node->ts_node); - Point *point = malloc(sizeof(Point)); + Point *point = xmalloc(sizeof(Point)); point->ts_point = start; - return Data_Wrap_Struct(rb_cPoint, NULL, rb_point_free, point); + return Data_Wrap_Struct(rb_cPoint, NULL, xfree, point); } /* @@ -87,7 +77,7 @@ VALUE rb_node_end_point(VALUE self) * * Returns a {Boolean}. */ -VALUE rb_node_is_named(VALUE self) +static VALUE rb_node_is_named(VALUE self) { AstNode *node; Data_Get_Struct(self, AstNode, node); @@ -100,7 +90,7 @@ VALUE rb_node_is_named(VALUE self) * * Returns an {Integer}. */ -VALUE rb_node_child_count(VALUE self) +static VALUE rb_node_child_count(VALUE self) { AstNode *node; Data_Get_Struct(self, AstNode, node); @@ -117,7 +107,7 @@ VALUE rb_node_child_count(VALUE self) * * Returns an {Integer}. */ -VALUE rb_node_named_child_count(VALUE self) +static VALUE rb_node_named_child_count(VALUE self) { AstNode *node; Data_Get_Struct(self, AstNode, node); @@ -134,7 +124,7 @@ VALUE rb_node_named_child_count(VALUE self) * * Returns a {Node} or nil. */ -VALUE rb_node_first_child(VALUE self) +static VALUE rb_node_first_child(VALUE self) { AstNode *node; Data_Get_Struct(self, AstNode, node); @@ -153,7 +143,7 @@ VALUE rb_node_first_child(VALUE self) * * Returns a {Node} or nil. */ -VALUE rb_node_first_named_child(VALUE self) +static VALUE rb_node_first_named_child(VALUE self) { AstNode *node; Data_Get_Struct(self, AstNode, node); @@ -172,7 +162,7 @@ VALUE rb_node_first_named_child(VALUE self) * * Returns a {Node} or nil. */ -VALUE rb_node_last_child(VALUE self) +static VALUE rb_node_last_child(VALUE self) { AstNode *node; Data_Get_Struct(self, AstNode, node); @@ -191,7 +181,7 @@ VALUE rb_node_last_child(VALUE self) * * Returns a {Node} or nil. */ -VALUE rb_node_last_named_child(VALUE self) +static VALUE rb_node_last_named_child(VALUE self) { AstNode *node; Data_Get_Struct(self, AstNode, node); @@ -210,7 +200,7 @@ VALUE rb_node_last_named_child(VALUE self) * * Returns a {Node} or nil. */ -VALUE rb_node_child(VALUE self, VALUE child_index) +static VALUE rb_node_child(VALUE self, VALUE child_index) { Check_Type(child_index, T_FIXNUM); uint32_t i = NUM2UINT(child_index); @@ -233,7 +223,7 @@ VALUE rb_node_child(VALUE self, VALUE child_index) * * Returns a {Node} or nil. */ -VALUE rb_node_named_child(VALUE self, VALUE child_index) +static VALUE rb_node_named_child(VALUE self, VALUE child_index) { Check_Type(child_index, T_FIXNUM); uint32_t i = NUM2UINT(child_index); @@ -256,7 +246,7 @@ VALUE rb_node_named_child(VALUE self, VALUE child_index) * * Returns an {Integer}. */ -VALUE rb_point_row(VALUE self) +static VALUE rb_point_row(VALUE self) { Point *point; Data_Get_Struct(self, Point, point); @@ -268,17 +258,15 @@ VALUE rb_point_row(VALUE self) * * Returns an {Integer}. */ -VALUE rb_point_column(VALUE self) +static VALUE rb_point_column(VALUE self) { Point *point; Data_Get_Struct(self, Point, point); return UINT2NUM(point->ts_point.column); } -void init_node() +void init_node(VALUE tree_sitter) { - VALUE tree_sitter = rb_define_module("TreeSitter"); - rb_cNode = rb_define_class_under(tree_sitter, "Node", rb_cObject); rb_define_method(rb_cNode, "to_s", rb_node_to_s, 0); rb_define_method(rb_cNode, "node_type", rb_node_type, 0); diff --git a/ext/tree-sitter/node.h b/ext/tree-sitter/node.h index 1879abc..729ab2b 100644 --- a/ext/tree-sitter/node.h +++ b/ext/tree-sitter/node.h @@ -14,21 +14,8 @@ typedef struct point_type { TSPoint ts_point; } Point; -void init_node(); +void init_node(VALUE); static void rb_node_free(void *n); VALUE rb_new_node(TSNode ts_node, TSDocument *ts_document); -VALUE rb_node_to_s(VALUE self); -VALUE rb_node_type(VALUE self); -VALUE rb_node_start_point(VALUE self); -VALUE rb_node_end_point(VALUE self); -VALUE rb_node_is_named(VALUE self); -VALUE rb_node_child_count(VALUE self); -VALUE rb_node_named_child_count(VALUE self); -VALUE rb_node_first_child(VALUE self); -VALUE rb_node_first_named_child(VALUE self); -VALUE rb_node_last_child(VALUE self); -VALUE rb_node_last_named_child(VALUE self); -VALUE rb_node_child(VALUE self, VALUE child_index); -VALUE rb_node_named_child(VALUE self, VALUE child_index); #endif diff --git a/ext/tree-sitter/tree-sitter.c b/ext/tree-sitter/tree-sitter.c index 2c874f9..79402d2 100644 --- a/ext/tree-sitter/tree-sitter.c +++ b/ext/tree-sitter/tree-sitter.c @@ -4,6 +4,6 @@ __attribute__((visibility("default"))) void Init_treesitter() { VALUE tree_sitter = rb_define_module("TreeSitter"); - init_document(); - init_node(); + init_document(tree_sitter); + init_node(tree_sitter); } diff --git a/lib/tree-sitter.rb b/lib/tree-sitter.rb index ec54410..ddd7742 100644 --- a/lib/tree-sitter.rb +++ b/lib/tree-sitter.rb @@ -4,12 +4,28 @@ require 'tree-sitter/treesitter' require 'tree-sitter/version' require 'tree-sitter/node' - -begin - require 'awesome_print' - require 'pry' -rescue LoadError; end +require 'fiddle' module TreeSitter + class Document + def initialize(input_string, options) + language = options[:language] + self.language = language + self.input_string = input_string + self.parse + end + # Public: Set the language type of a document. + # + # lang - A {String} identifying the language. + # + # Returns nothing. + def language=(lang) + handle = Fiddle.dlopen BUNDLE_PATH + function_address = handle[lang] + set_language function_address + rescue Fiddle::DLError + raise TreeSitter::DocumentError + end + end end diff --git a/tree-sitter.gemspec b/tree-sitter.gemspec index 89bb7dd..79fe7aa 100644 --- a/tree-sitter.gemspec +++ b/tree-sitter.gemspec @@ -24,7 +24,6 @@ Gem::Specification.new do |spec| spec.require_paths = %w(lib ext) spec.add_development_dependency 'awesome_print' - spec.add_development_dependency 'bundler', '~> 1.14' spec.add_development_dependency 'minitest', '~> 5.0' spec.add_development_dependency 'minitest-focus', '~> 1.1' spec.add_development_dependency 'pry-byebug', '~> 3.6'