ruby_tree_sitter 0.20.6.3-x86_64-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +152 -0
  4. data/ext/tree_sitter/encoding.c +29 -0
  5. data/ext/tree_sitter/extconf.rb +172 -0
  6. data/ext/tree_sitter/input.c +126 -0
  7. data/ext/tree_sitter/input_edit.c +42 -0
  8. data/ext/tree_sitter/language.c +134 -0
  9. data/ext/tree_sitter/logger.c +212 -0
  10. data/ext/tree_sitter/macros.h +163 -0
  11. data/ext/tree_sitter/node.c +310 -0
  12. data/ext/tree_sitter/parser.c +203 -0
  13. data/ext/tree_sitter/point.c +26 -0
  14. data/ext/tree_sitter/quantifier.c +43 -0
  15. data/ext/tree_sitter/query.c +157 -0
  16. data/ext/tree_sitter/query_capture.c +28 -0
  17. data/ext/tree_sitter/query_cursor.c +103 -0
  18. data/ext/tree_sitter/query_error.c +41 -0
  19. data/ext/tree_sitter/query_match.c +44 -0
  20. data/ext/tree_sitter/query_predicate_step.c +83 -0
  21. data/ext/tree_sitter/range.c +35 -0
  22. data/ext/tree_sitter/symbol_type.c +46 -0
  23. data/ext/tree_sitter/tree.c +145 -0
  24. data/ext/tree_sitter/tree_cursor.c +97 -0
  25. data/ext/tree_sitter/tree_sitter.c +32 -0
  26. data/ext/tree_sitter/tree_sitter.h +107 -0
  27. data/lib/tree_sitter/node.rb +164 -0
  28. data/lib/tree_sitter/tree_sitter.so +0 -0
  29. data/lib/tree_sitter/version.rb +5 -0
  30. data/lib/tree_sitter.rb +13 -0
  31. data/test/README.md +15 -0
  32. data/test/test_helper.rb +9 -0
  33. data/test/tree_sitter/language_test.rb +68 -0
  34. data/test/tree_sitter/logger_test.rb +69 -0
  35. data/test/tree_sitter/node_test.rb +355 -0
  36. data/test/tree_sitter/parser_test.rb +140 -0
  37. data/test/tree_sitter/query_test.rb +153 -0
  38. data/test/tree_sitter/tree_cursor_test.rb +83 -0
  39. data/test/tree_sitter/tree_test.rb +51 -0
  40. data/tree_sitter.gemspec +32 -0
  41. metadata +192 -0
@@ -0,0 +1,212 @@
1
+ #include "tree_sitter.h"
2
+
3
+ extern VALUE mTreeSitter;
4
+
5
+ VALUE cLogger;
6
+
7
+ // This type is layed out in the DATA_* style.
8
+ // data: the TSLogger object
9
+ // payload: what will be used in TSLogger.log()
10
+ // therefore: data.payload = payload
11
+ // format: optional formatting string. Passed to "printf" if it exists
12
+ typedef struct {
13
+ TSLogger data;
14
+ VALUE payload;
15
+ VALUE format;
16
+ } logger_t;
17
+
18
+ static const char *logger_log_type_str(TSLogType log_type) {
19
+ switch (log_type) {
20
+ case TSLogTypeParse:
21
+ return "Parse:";
22
+ case TSLogTypeLex:
23
+ return "Lex :";
24
+ default:
25
+ return "?????:";
26
+ }
27
+ }
28
+
29
+ static void logger_log_printf(void *ptr, TSLogType log_type,
30
+ const char *message) {
31
+ logger_t *logger = (logger_t *)ptr;
32
+ VALUE type = safe_str(logger_log_type_str(log_type));
33
+ VALUE msg = safe_str(message);
34
+ rb_funcall(logger->payload, rb_intern("printf"), 3, logger->format, type,
35
+ msg);
36
+ }
37
+
38
+ static void logger_log_puts(void *ptr, TSLogType log_type,
39
+ const char *message) {
40
+ logger_t *logger = (logger_t *)ptr;
41
+ const char *format =
42
+ NIL_P(logger->format) ? "%s %s" : StringValueCStr(logger->format);
43
+ VALUE str = rb_sprintf(format, logger_log_type_str(log_type), message);
44
+ rb_funcall(logger->payload, rb_intern("puts"), 1, str);
45
+ }
46
+
47
+ static void logger_log_write(void *ptr, TSLogType log_type,
48
+ const char *message) {
49
+ logger_t *logger = (logger_t *)ptr;
50
+ const char *format =
51
+ NIL_P(logger->format) ? "%s %s\n" : StringValueCStr(logger->format);
52
+ VALUE str = rb_sprintf(format, logger_log_type_str(log_type), message);
53
+ rb_funcall(logger->payload, rb_intern("write"), 1, str);
54
+ }
55
+
56
+ static void logger_payload_set(logger_t *logger, VALUE value) {
57
+ logger->payload = value;
58
+ logger->data.payload = (void *)logger;
59
+
60
+ if (!NIL_P(logger->format) && !NIL_P(logger->payload)) {
61
+ if (rb_respond_to(logger->payload, rb_intern("printf"))) {
62
+ logger->data.log = logger_log_printf;
63
+ } else if (rb_respond_to(logger->payload, rb_intern("puts"))) {
64
+ logger->data.log = &logger_log_puts;
65
+ } else {
66
+ logger->data.log = &logger_log_write;
67
+ }
68
+ } else if (!NIL_P(logger->payload)) {
69
+ logger->data.log = &logger_log_write;
70
+ }
71
+ }
72
+
73
+ static void logger_free(void *ptr) { xfree(ptr); }
74
+
75
+ static size_t logger_memsize(const void *ptr) {
76
+ logger_t *type = (logger_t *)ptr;
77
+ return sizeof(type);
78
+ }
79
+
80
+ static void logger_mark(void *ptr) {
81
+ logger_t *logger = (logger_t *)ptr;
82
+ rb_gc_mark_movable(logger->payload);
83
+ // we don't want format to move because its reference will be
84
+ // consumed by the parser.
85
+ //
86
+ // No funny things please.
87
+ rb_gc_mark(logger->format);
88
+ }
89
+
90
+ static void logger_compact(void *ptr) {
91
+ logger_t *logger = (logger_t *)ptr;
92
+ logger->payload = rb_gc_location(logger->payload);
93
+ }
94
+
95
+ const rb_data_type_t logger_data_type = {
96
+ .wrap_struct_name = "logger",
97
+ .function =
98
+ {
99
+ .dmark = logger_mark,
100
+ .dfree = logger_free,
101
+ .dsize = logger_memsize,
102
+ .dcompact = logger_compact,
103
+ },
104
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY,
105
+ };
106
+
107
+ DATA_UNWRAP(logger)
108
+
109
+ static VALUE logger_allocate(VALUE klass) {
110
+ logger_t *logger;
111
+ return TypedData_Make_Struct(klass, logger_t, &logger_data_type, logger);
112
+ }
113
+
114
+ VALUE new_logger(const TSLogger *ptr) {
115
+ if (ptr != NULL) {
116
+ VALUE res = logger_allocate(cLogger);
117
+ logger_t *logger = unwrap(res);
118
+
119
+ logger->data.payload = logger;
120
+
121
+ VALUE payload = Qnil;
122
+ VALUE format = Qnil;
123
+ if (ptr->payload != NULL) {
124
+ logger_t *old_logger = (logger_t *)ptr->payload;
125
+ payload = old_logger->payload;
126
+ format = old_logger->format;
127
+ }
128
+ logger_payload_set(logger, payload);
129
+ logger->format = format;
130
+
131
+ return res;
132
+ } else {
133
+ return Qnil;
134
+ }
135
+ }
136
+
137
+ VALUE new_logger_by_val(TSLogger val) { return new_logger(&val); }
138
+
139
+ TSLogger value_to_logger(VALUE self) { return SELF; }
140
+
141
+ static void logger_initialize_stderr(logger_t *logger) {
142
+ VALUE stderr = rb_gv_get("$stderr");
143
+ if (!NIL_P(stderr)) {
144
+ logger_payload_set(logger, stderr);
145
+ } else {
146
+ logger_payload_set(logger, Qnil);
147
+ }
148
+ }
149
+
150
+ // For now, we only take:
151
+ // argv[0] = stream
152
+ // argv[1] = format : String
153
+ //
154
+ // We need to add support for argv[1] : lambda/block
155
+ //
156
+ // case argv[1]
157
+ // in lambda => lambda
158
+ // in String => puts || printf || write
159
+ // else => write
160
+ // end
161
+ //
162
+ static VALUE logger_initialize(int argc, VALUE *argv, VALUE self) {
163
+ logger_t *logger = unwrap(self);
164
+
165
+ VALUE payload;
166
+ VALUE format;
167
+ rb_scan_args(argc, argv, "02", &payload, &format);
168
+
169
+ logger->format = format;
170
+
171
+ if (argc == 0) {
172
+ logger_initialize_stderr(logger);
173
+ } else {
174
+ logger_payload_set(logger, payload);
175
+ }
176
+
177
+ return self;
178
+ }
179
+
180
+ static VALUE logger_inspect(VALUE self) {
181
+ logger_t *logger = unwrap(self);
182
+ return rb_sprintf("{payload=%+" PRIsVALUE ", format=%+" PRIsVALUE "}",
183
+ logger->payload, logger->format);
184
+ }
185
+
186
+ DATA_FAST_FORWARD_FNV(logger, write, payload)
187
+ DATA_FAST_FORWARD_FNV(logger, puts, payload)
188
+ DATA_FAST_FORWARD_FNV(logger, printf, payload)
189
+
190
+ DEFINE_ACCESSOR(logger, format)
191
+ DEFINE_GETTER(logger, payload)
192
+
193
+ static VALUE logger_set_payload(VALUE self, VALUE payload) {
194
+ logger_payload_set(unwrap(self), payload);
195
+ return Qnil;
196
+ }
197
+
198
+ void init_logger(void) {
199
+ cLogger = rb_define_class_under(mTreeSitter, "Logger", rb_cObject);
200
+
201
+ rb_define_alloc_func(cLogger, logger_allocate);
202
+
203
+ /* Class methods */
204
+ rb_define_method(cLogger, "initialize", logger_initialize, -1);
205
+ DECLARE_ACCESSOR(cLogger, logger, format)
206
+ DECLARE_ACCESSOR(cLogger, logger, payload)
207
+ rb_define_method(cLogger, "write", logger_write, -1);
208
+ rb_define_method(cLogger, "puts", logger_puts, -1);
209
+ rb_define_method(cLogger, "printf", logger_printf, -1);
210
+ rb_define_method(cLogger, "inspect", logger_inspect, 0);
211
+ rb_define_method(cLogger, "to_s", logger_inspect, 0);
212
+ }
@@ -0,0 +1,163 @@
1
+ #ifndef _RB_TREE_SITTER_MACROS_H
2
+ #define _RB_TREE_SITTER_MACROS_H
3
+
4
+ #define DECLARE_GETTER(klass, type, field) \
5
+ rb_define_method(klass, #field, type##_get_##field, 0);
6
+
7
+ #define DECLARE_SETTER(klass, type, field) \
8
+ rb_define_method(klass, #field "=", type##_set_##field, 1);
9
+
10
+ #define DECLARE_ACCESSOR(klass, type, field) \
11
+ DECLARE_GETTER(klass, type, field) \
12
+ DECLARE_SETTER(klass, type, field)
13
+
14
+ // Plain DEFINE_GETTER/DEFINE_SETTER/etc are for TypedData structs, reaching
15
+ // their top-level fields, and are of type VALUE
16
+ //
17
+ // DATA_* are for TypeData structs, raching their data field
18
+ // which can be of an arbitraty tuype.
19
+
20
+ #define DEFINE_GETTER(type, field) \
21
+ static VALUE type##_get_##field(VALUE self) { return (unwrap(self))->field; }
22
+
23
+ #define DEFINE_SETTER(type, field) \
24
+ static VALUE type##_set_##field(VALUE self, VALUE val) { \
25
+ unwrap(self)->field = val; \
26
+ return Qnil; \
27
+ }
28
+
29
+ #define DEFINE_ACCESSOR(type, field) \
30
+ DEFINE_GETTER(type, field) \
31
+ DEFINE_SETTER(type, field)
32
+
33
+ #define DATA_WRAP(base, type) \
34
+ DATA_TYPE(TS##base, type) \
35
+ DATA_FREE(type) \
36
+ DATA_MEMSIZE(type) \
37
+ DATA_DECLARE_DATA_TYPE(type) \
38
+ DATA_ALLOCATE(type) \
39
+ DATA_UNWRAP(type) \
40
+ DATA_NEW(c##base, TS##base, type) \
41
+ DATA_FROM_VALUE(TS##base, type)
42
+
43
+ #define DATA_PTR_WRAP(base, type) \
44
+ DATA_TYPE(TS##base *, type) \
45
+ DATA_FREE_PTR(type) \
46
+ DATA_MEMSIZE(type) \
47
+ DATA_DECLARE_DATA_TYPE(type) \
48
+ DATA_ALLOCATE(type) \
49
+ DATA_UNWRAP(type) \
50
+ DATA_PTR_NEW(c##base, TS##base, type) \
51
+ DATA_FROM_VALUE(TS##base *, type)
52
+
53
+ #define DATA_TYPE(klass, type) \
54
+ typedef struct { \
55
+ klass data; \
56
+ } type##_t;
57
+
58
+ #define DATA_FREE(type) \
59
+ static void type##_free(void *ptr) { xfree(ptr); }
60
+
61
+ #define DATA_FREE_PTR(type) \
62
+ static void type##_free(void *ptr) { \
63
+ type##_t *type = (type##_t *)ptr; \
64
+ if (type->data != NULL) { \
65
+ ts_##type##_delete(type->data); \
66
+ } \
67
+ xfree(ptr); \
68
+ }
69
+
70
+ #define DATA_MEMSIZE(type) \
71
+ static size_t type##_memsize(const void *ptr) { \
72
+ type##_t *type = (type##_t *)ptr; \
73
+ return sizeof(type); \
74
+ }
75
+
76
+ #define DATA_DECLARE_DATA_TYPE(type) \
77
+ const rb_data_type_t type##_data_type = { \
78
+ .wrap_struct_name = #type "", \
79
+ .function = \
80
+ { \
81
+ .dmark = NULL, \
82
+ .dfree = type##_free, \
83
+ .dsize = type##_memsize, \
84
+ .dcompact = NULL, \
85
+ }, \
86
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY, \
87
+ };
88
+
89
+ #define DATA_ALLOCATE(type) \
90
+ static VALUE type##_allocate(VALUE klass) { \
91
+ type##_t *type; \
92
+ return TypedData_Make_Struct(klass, type##_t, &type##_data_type, type); \
93
+ }
94
+
95
+ #define DATA_UNWRAP(type) \
96
+ static type##_t *unwrap(VALUE self) { \
97
+ type##_t *type; \
98
+ TypedData_Get_Struct(self, type##_t, &type##_data_type, type); \
99
+ return type; \
100
+ }
101
+
102
+ #define SELF unwrap(self)->data
103
+
104
+ #define DATA_NEW(klass, struct, type) \
105
+ VALUE new_##type(const struct *ptr) { \
106
+ if (ptr == NULL) { \
107
+ return Qnil; \
108
+ } \
109
+ VALUE res = type##_allocate(klass); \
110
+ type##_t *type = unwrap(res); \
111
+ type->data = *ptr; \
112
+ return res; \
113
+ } \
114
+ VALUE new_##type##_by_val(struct ptr) { \
115
+ VALUE res = type##_allocate(klass); \
116
+ type##_t *type = unwrap(res); \
117
+ type->data = ptr; \
118
+ return res; \
119
+ }
120
+
121
+ #define DATA_FROM_VALUE(struct, type) \
122
+ struct value_to_##type(VALUE self) { \
123
+ return (unwrap(self))->data; \
124
+ }
125
+
126
+ #define DATA_PTR_NEW(klass, struct, type) \
127
+ VALUE new_##type(struct *ptr) { \
128
+ if (ptr == NULL) { \
129
+ return Qnil; \
130
+ } \
131
+ VALUE res = type##_allocate(klass); \
132
+ type##_t *type = unwrap(res); \
133
+ type->data = ptr; \
134
+ return res; \
135
+ }
136
+
137
+ #define DATA_DEFINE_GETTER(type, field, cast) \
138
+ static VALUE type##_get_##field(VALUE self) { \
139
+ return cast((unwrap(self))->data.field); \
140
+ }
141
+
142
+ #define DATA_DEFINE_SETTER(type, field, cast) \
143
+ static VALUE type##_set_##field(VALUE self, VALUE val) { \
144
+ type##_t *type = unwrap(self); \
145
+ type->data.field = cast(val); \
146
+ return Qnil; \
147
+ }
148
+
149
+ #define DATA_DEFINE_ACCESSOR(type, field, cast_get, cast_set) \
150
+ DATA_DEFINE_GETTER(type, field, cast_get) \
151
+ DATA_DEFINE_SETTER(type, field, cast_set)
152
+
153
+ #define DATA_FAST_FORWARD_FNV(type, fn, field) \
154
+ static VALUE type##_##fn(int argc, VALUE *argv, VALUE self) { \
155
+ type##_t *type = unwrap(self); \
156
+ if (!NIL_P(type->field)) { \
157
+ return rb_funcallv(type->field, rb_intern(#fn ""), argc, argv); \
158
+ } else { \
159
+ return Qnil; \
160
+ } \
161
+ }
162
+
163
+ #endif
@@ -0,0 +1,310 @@
1
+ #include "tree_sitter.h"
2
+ #include "tree_sitter/api.h"
3
+
4
+ extern VALUE mTreeSitter;
5
+
6
+ VALUE cNode;
7
+
8
+ DATA_TYPE(TSNode, node)
9
+
10
+ static void node_free(void *ptr) {
11
+ node_t *type = (node_t *)ptr;
12
+ tree_rc_free(type->data.tree);
13
+ xfree(ptr);
14
+ }
15
+
16
+ DATA_MEMSIZE(node)
17
+ DATA_DECLARE_DATA_TYPE(node)
18
+ DATA_ALLOCATE(node)
19
+ DATA_UNWRAP(node)
20
+
21
+ VALUE new_node(const TSNode *ptr) {
22
+ if (ptr == NULL) {
23
+ return Qnil;
24
+ }
25
+ VALUE res = node_allocate(cNode);
26
+ node_t *type = unwrap(res);
27
+ type->data = *ptr;
28
+ tree_rc_new(type->data.tree);
29
+ return res;
30
+ }
31
+ VALUE new_node_by_val(TSNode ptr) {
32
+ VALUE res = node_allocate(cNode);
33
+ node_t *type = unwrap(res);
34
+ type->data = ptr;
35
+ tree_rc_new(type->data.tree);
36
+ return res;
37
+ }
38
+
39
+ DATA_FROM_VALUE(TSNode, node)
40
+
41
+ static VALUE node_type(VALUE self) { return safe_symbol(ts_node_type(SELF)); }
42
+
43
+ static VALUE node_symbol(VALUE self) { return UINT2NUM(ts_node_symbol(SELF)); }
44
+
45
+ static VALUE node_start_byte(VALUE self) {
46
+ return UINT2NUM(ts_node_start_byte(SELF));
47
+ }
48
+
49
+ static VALUE node_start_point(VALUE self) {
50
+ return new_point_by_val(ts_node_start_point(SELF));
51
+ }
52
+
53
+ static VALUE node_end_byte(VALUE self) {
54
+ return UINT2NUM(ts_node_end_byte(SELF));
55
+ }
56
+
57
+ static VALUE node_end_point(VALUE self) {
58
+ return new_point_by_val(ts_node_end_point(SELF));
59
+ }
60
+
61
+ static VALUE node_string(VALUE self) {
62
+ char *str = ts_node_string(SELF);
63
+ VALUE res = safe_str(str);
64
+ if (str) {
65
+ free(str);
66
+ }
67
+ return res;
68
+ }
69
+
70
+ static VALUE node_is_null(VALUE self) {
71
+ return ts_node_is_null(SELF) ? Qtrue : Qfalse;
72
+ }
73
+
74
+ static VALUE node_is_named(VALUE self) {
75
+ return ts_node_is_named(SELF) ? Qtrue : Qfalse;
76
+ }
77
+
78
+ static VALUE node_is_missing(VALUE self) {
79
+ return ts_node_is_missing(SELF) ? Qtrue : Qfalse;
80
+ }
81
+
82
+ static VALUE node_is_extra(VALUE self) {
83
+ return ts_node_is_extra(SELF) ? Qtrue : Qfalse;
84
+ }
85
+
86
+ static VALUE node_has_changes(VALUE self) {
87
+ return ts_node_has_changes(SELF) ? Qtrue : Qfalse;
88
+ }
89
+
90
+ static VALUE node_has_error(VALUE self) {
91
+ return ts_node_has_error(SELF) ? Qtrue : Qfalse;
92
+ }
93
+
94
+ static VALUE node_parent(VALUE self) {
95
+ return new_node_by_val(ts_node_parent(SELF));
96
+ }
97
+
98
+ static VALUE node_child(VALUE self, VALUE idx) {
99
+ TSNode node = SELF;
100
+ uint32_t index = NUM2UINT(idx);
101
+ uint32_t range = ts_node_child_count(node);
102
+
103
+ if (index < range) {
104
+ return new_node_by_val(ts_node_child(node, index));
105
+ } else {
106
+ rb_raise(rb_eIndexError, "Index %d is out of range (len = %d)", index,
107
+ range);
108
+ }
109
+ }
110
+
111
+ static VALUE node_field_name_for_child(VALUE self, VALUE idx) {
112
+ TSNode node = SELF;
113
+ uint32_t index = NUM2UINT(idx);
114
+ uint32_t range = ts_node_child_count(node);
115
+
116
+ if (index < range) {
117
+ return safe_str(ts_node_field_name_for_child(node, index));
118
+ } else {
119
+ rb_raise(rb_eIndexError, "Index %d is out of range (len = %d)", index,
120
+ range);
121
+ }
122
+ }
123
+
124
+ static VALUE node_child_count(VALUE self) {
125
+ TSNode node = SELF;
126
+ const char *type = ts_node_type(node);
127
+ if (strcmp(type, "end") == 0) {
128
+ return UINT2NUM(0);
129
+ } else {
130
+ return UINT2NUM(ts_node_child_count(SELF));
131
+ }
132
+ }
133
+
134
+ static VALUE node_named_child(VALUE self, VALUE idx) {
135
+ TSNode node = SELF;
136
+ uint32_t index = NUM2UINT(idx);
137
+ uint32_t range = ts_node_named_child_count(node);
138
+
139
+ if (index < range) {
140
+ return new_node_by_val(ts_node_named_child(node, index));
141
+ } else {
142
+ rb_raise(rb_eIndexError, "Index %d is out of range (len = %d)", index,
143
+ range);
144
+ }
145
+ }
146
+
147
+ static VALUE node_named_child_count(VALUE self) {
148
+ return UINT2NUM(ts_node_named_child_count(SELF));
149
+ }
150
+
151
+ static VALUE node_child_by_field_name(VALUE self, VALUE field_name) {
152
+ const char *name = StringValuePtr(field_name);
153
+ uint32_t length = (uint32_t)RSTRING_LEN(field_name);
154
+ return new_node_by_val(ts_node_child_by_field_name(SELF, name, length));
155
+ }
156
+
157
+ static VALUE node_child_by_field_id(VALUE self, VALUE field_id) {
158
+ return new_node_by_val(ts_node_child_by_field_id(SELF, NUM2UINT(field_id)));
159
+ }
160
+
161
+ static VALUE node_next_sibling(VALUE self) {
162
+ return new_node_by_val(ts_node_next_sibling(SELF));
163
+ }
164
+
165
+ static VALUE node_prev_sibling(VALUE self) {
166
+ return new_node_by_val(ts_node_prev_sibling(SELF));
167
+ }
168
+
169
+ static VALUE node_next_named_sibling(VALUE self) {
170
+ return new_node_by_val(ts_node_next_named_sibling(SELF));
171
+ }
172
+
173
+ static VALUE node_prev_named_sibling(VALUE self) {
174
+ return new_node_by_val(ts_node_prev_named_sibling(SELF));
175
+ }
176
+
177
+ static VALUE node_first_child_for_byte(VALUE self, VALUE byte) {
178
+ return new_node_by_val(ts_node_first_child_for_byte(SELF, NUM2UINT(byte)));
179
+ }
180
+
181
+ static VALUE node_first_named_child_for_byte(VALUE self, VALUE byte) {
182
+ return new_node_by_val(
183
+ ts_node_first_named_child_for_byte(SELF, NUM2UINT(byte)));
184
+ }
185
+
186
+ static VALUE node_descendant_for_byte_range(VALUE self, VALUE from, VALUE to) {
187
+ uint32_t from_b = NUM2UINT(from);
188
+ uint32_t to_b = NUM2UINT(to);
189
+
190
+ if (from_b > to_b) {
191
+ rb_raise(rb_eIndexError, "From > To: %d > %d", from_b, to_b);
192
+ } else {
193
+ return new_node_by_val(
194
+ ts_node_descendant_for_byte_range(SELF, from_b, to_b));
195
+ }
196
+ }
197
+
198
+ static VALUE node_descendant_for_point_range(VALUE self, VALUE from, VALUE to) {
199
+ TSNode node = SELF;
200
+ TSPoint start = ts_node_start_point(node);
201
+ TSPoint end = ts_node_end_point(node);
202
+ TSPoint f = value_to_point(from);
203
+ TSPoint t = value_to_point(to);
204
+
205
+ if ((f.row < start.row) || (t.row > end.row) ||
206
+ (f.row == start.row && (f.column < start.column)) ||
207
+ (t.row == end.row && (t.column > end.column))) {
208
+ rb_raise(rb_eIndexError,
209
+ "Invalid point range: [%+" PRIsVALUE ", %+" PRIsVALUE
210
+ "] is not in [%+" PRIsVALUE ", %+" PRIsVALUE "].",
211
+ from, to, new_point(&start), new_point(&end));
212
+ } else {
213
+ return new_node_by_val(ts_node_descendant_for_point_range(node, f, t));
214
+ }
215
+ }
216
+
217
+ static VALUE node_named_descendant_for_byte_range(VALUE self, VALUE from,
218
+ VALUE to) {
219
+ uint32_t from_b = NUM2UINT(from);
220
+ uint32_t to_b = NUM2UINT(to);
221
+
222
+ if (from_b > to_b) {
223
+ rb_raise(rb_eIndexError, "From > To: %d > %d", from_b, to_b);
224
+ } else {
225
+ return new_node_by_val(
226
+ ts_node_named_descendant_for_byte_range(SELF, from_b, to_b));
227
+ }
228
+ }
229
+
230
+ static VALUE node_named_descendant_for_point_range(VALUE self, VALUE from,
231
+ VALUE to) {
232
+ TSNode node = SELF;
233
+ TSPoint start = ts_node_start_point(node);
234
+ TSPoint end = ts_node_end_point(node);
235
+ TSPoint f = value_to_point(from);
236
+ TSPoint t = value_to_point(to);
237
+
238
+ if ((f.row < start.row) || (t.row > end.row) ||
239
+ (f.row == start.row && (f.column < start.column)) ||
240
+ (t.row == end.row && (t.column > end.column))) {
241
+ rb_raise(rb_eIndexError,
242
+ "Invalid point range: [%+" PRIsVALUE ", %+" PRIsVALUE
243
+ "] is not in [%+" PRIsVALUE ", %+" PRIsVALUE "].",
244
+ from, to, new_point(&start), new_point(&end));
245
+ } else {
246
+ return new_node_by_val(
247
+ ts_node_named_descendant_for_point_range(node, f, t));
248
+ }
249
+ }
250
+
251
+ static VALUE node_edit(VALUE self, VALUE input_edit) {
252
+ TSNode node = SELF;
253
+ TSInputEdit edit = value_to_input_edit(input_edit);
254
+ ts_node_edit(&node, &edit);
255
+
256
+ return Qnil;
257
+ }
258
+
259
+ static VALUE node_eq(VALUE self, VALUE other) {
260
+ return ts_node_eq(SELF, unwrap(other)->data) ? Qtrue : Qfalse;
261
+ }
262
+
263
+ void init_node(void) {
264
+ cNode = rb_define_class_under(mTreeSitter, "Node", rb_cObject);
265
+
266
+ rb_undef_alloc_func(cNode);
267
+
268
+ /* Class methods */
269
+ rb_define_method(cNode, "type", node_type, 0);
270
+ rb_define_method(cNode, "symbol", node_symbol, 0);
271
+ rb_define_method(cNode, "start_byte", node_start_byte, 0);
272
+ rb_define_method(cNode, "start_point", node_start_point, 0);
273
+ rb_define_method(cNode, "end_byte", node_end_byte, 0);
274
+ rb_define_method(cNode, "end_point", node_end_point, 0);
275
+ rb_define_method(cNode, "null?", node_is_null, 0);
276
+ rb_define_method(cNode, "named?", node_is_named, 0);
277
+ rb_define_method(cNode, "missing?", node_is_missing, 0);
278
+ rb_define_method(cNode, "extra?", node_is_extra, 0);
279
+ rb_define_method(cNode, "changed?", node_has_changes, 0);
280
+ rb_define_method(cNode, "error?", node_has_error, 0);
281
+ rb_define_method(cNode, "parent", node_parent, 0);
282
+ rb_define_method(cNode, "child", node_child, 1);
283
+ rb_define_method(cNode, "field_name_for_child", node_field_name_for_child, 1);
284
+ rb_define_method(cNode, "child_count", node_child_count, 0);
285
+ rb_define_method(cNode, "named_child", node_named_child, 1);
286
+ rb_define_method(cNode, "named_child_count", node_named_child_count, 0);
287
+ rb_define_method(cNode, "child_by_field_name", node_child_by_field_name, 1);
288
+ rb_define_method(cNode, "child_by_field_id", node_child_by_field_id, 1);
289
+ rb_define_method(cNode, "next_sibling", node_next_sibling, 0);
290
+ rb_define_method(cNode, "prev_sibling", node_prev_sibling, 0);
291
+ rb_define_method(cNode, "next_named_sibling", node_next_named_sibling, 0);
292
+ rb_define_method(cNode, "prev_named_sibling", node_prev_named_sibling, 0);
293
+ rb_define_method(cNode, "first_child_for_byte", node_first_child_for_byte, 1);
294
+ rb_define_method(cNode, "first_named_child_for_byte",
295
+ node_first_named_child_for_byte, 1);
296
+ rb_define_method(cNode, "descendant_for_byte_range",
297
+ node_descendant_for_byte_range, 2);
298
+ rb_define_method(cNode, "descendant_for_point_range",
299
+ node_descendant_for_point_range, 2);
300
+ rb_define_method(cNode, "named_descendant_for_byte_range",
301
+ node_named_descendant_for_byte_range, 2);
302
+ rb_define_method(cNode, "named_descendant_for_point_range",
303
+ node_named_descendant_for_point_range, 2);
304
+ rb_define_method(cNode, "eq?", node_eq, 1);
305
+ rb_define_method(cNode, "edit", node_edit, 1);
306
+ rb_define_method(cNode, "to_s", node_string, 0);
307
+ rb_define_method(cNode, "to_str", node_string, 0);
308
+ rb_define_method(cNode, "inspect", node_string, 0);
309
+ rb_define_method(cNode, "==", node_eq, 1);
310
+ }