ruby_tree_sitter 1.6.0-x86_64-darwin
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +213 -0
- data/ext/tree_sitter/encoding.c +29 -0
- data/ext/tree_sitter/extconf.rb +149 -0
- data/ext/tree_sitter/input.c +127 -0
- data/ext/tree_sitter/input_edit.c +42 -0
- data/ext/tree_sitter/language.c +219 -0
- data/ext/tree_sitter/logger.c +228 -0
- data/ext/tree_sitter/macros.h +163 -0
- data/ext/tree_sitter/node.c +623 -0
- data/ext/tree_sitter/parser.c +398 -0
- data/ext/tree_sitter/point.c +26 -0
- data/ext/tree_sitter/quantifier.c +43 -0
- data/ext/tree_sitter/query.c +289 -0
- data/ext/tree_sitter/query_capture.c +28 -0
- data/ext/tree_sitter/query_cursor.c +231 -0
- data/ext/tree_sitter/query_error.c +41 -0
- data/ext/tree_sitter/query_match.c +44 -0
- data/ext/tree_sitter/query_predicate_step.c +83 -0
- data/ext/tree_sitter/range.c +35 -0
- data/ext/tree_sitter/repo.rb +128 -0
- data/ext/tree_sitter/symbol_type.c +46 -0
- data/ext/tree_sitter/tree.c +234 -0
- data/ext/tree_sitter/tree_cursor.c +269 -0
- data/ext/tree_sitter/tree_sitter.c +44 -0
- data/ext/tree_sitter/tree_sitter.h +107 -0
- data/lib/tree_sitter/3.0/tree_sitter.bundle +0 -0
- data/lib/tree_sitter/3.1/tree_sitter.bundle +0 -0
- data/lib/tree_sitter/3.2/tree_sitter.bundle +0 -0
- data/lib/tree_sitter/3.3/tree_sitter.bundle +0 -0
- data/lib/tree_sitter/helpers.rb +23 -0
- data/lib/tree_sitter/mixins/language.rb +167 -0
- data/lib/tree_sitter/node.rb +167 -0
- data/lib/tree_sitter/query.rb +191 -0
- data/lib/tree_sitter/query_captures.rb +30 -0
- data/lib/tree_sitter/query_cursor.rb +27 -0
- data/lib/tree_sitter/query_match.rb +100 -0
- data/lib/tree_sitter/query_matches.rb +39 -0
- data/lib/tree_sitter/query_predicate.rb +14 -0
- data/lib/tree_sitter/text_predicate_capture.rb +37 -0
- data/lib/tree_sitter/version.rb +8 -0
- data/lib/tree_sitter.rb +34 -0
- data/lib/tree_stand/ast_modifier.rb +30 -0
- data/lib/tree_stand/breadth_first_visitor.rb +54 -0
- data/lib/tree_stand/config.rb +19 -0
- data/lib/tree_stand/node.rb +351 -0
- data/lib/tree_stand/parser.rb +87 -0
- data/lib/tree_stand/range.rb +55 -0
- data/lib/tree_stand/tree.rb +123 -0
- data/lib/tree_stand/utils/printer.rb +73 -0
- data/lib/tree_stand/version.rb +7 -0
- data/lib/tree_stand/visitor.rb +127 -0
- data/lib/tree_stand/visitors/tree_walker.rb +37 -0
- data/lib/tree_stand.rb +48 -0
- data/tree_sitter.gemspec +34 -0
- metadata +135 -0
@@ -0,0 +1,219 @@
|
|
1
|
+
#include "tree_sitter.h"
|
2
|
+
#include <dlfcn.h>
|
3
|
+
#include <stdint.h>
|
4
|
+
#include <stdio.h>
|
5
|
+
|
6
|
+
typedef TSLanguage *(tree_sitter_lang)(void);
|
7
|
+
const char *tree_sitter_prefix = "tree_sitter_";
|
8
|
+
|
9
|
+
extern VALUE mTreeSitter;
|
10
|
+
|
11
|
+
VALUE cLanguage;
|
12
|
+
|
13
|
+
DATA_TYPE(TSLanguage *, language)
|
14
|
+
DATA_FREE(language)
|
15
|
+
DATA_MEMSIZE(language)
|
16
|
+
DATA_DECLARE_DATA_TYPE(language)
|
17
|
+
DATA_ALLOCATE(language)
|
18
|
+
DATA_UNWRAP(language)
|
19
|
+
|
20
|
+
TSLanguage *value_to_language(VALUE self) { return SELF; }
|
21
|
+
|
22
|
+
VALUE new_language(const TSLanguage *language) {
|
23
|
+
VALUE res = language_allocate(cLanguage);
|
24
|
+
unwrap(res)->data = (TSLanguage *)language;
|
25
|
+
return res;
|
26
|
+
}
|
27
|
+
|
28
|
+
/**
|
29
|
+
* Load a language parser from disk.
|
30
|
+
*
|
31
|
+
* @raise [RuntimeError] if the parser was not found, or if it's incompatible
|
32
|
+
* with this gem.
|
33
|
+
*
|
34
|
+
* @param name [String] the parser's name.
|
35
|
+
* @param path [String, Pathname] the parser's shared library (so, dylib) path on disk.
|
36
|
+
*
|
37
|
+
* @return [Language]
|
38
|
+
*/
|
39
|
+
static VALUE language_load(VALUE self, VALUE name, VALUE path) {
|
40
|
+
VALUE path_s = rb_funcall(path, rb_intern("to_s"), 0);
|
41
|
+
char *path_cstr = StringValueCStr(path_s);
|
42
|
+
void *lib = dlopen(path_cstr, RTLD_NOW);
|
43
|
+
const char *err = dlerror();
|
44
|
+
if (err != NULL) {
|
45
|
+
rb_raise(rb_eRuntimeError,
|
46
|
+
"Could not load shared library `%s'.\nReason: %s", path_cstr, err);
|
47
|
+
}
|
48
|
+
|
49
|
+
char buf[256];
|
50
|
+
snprintf(buf, sizeof(buf), "tree_sitter_%s", StringValueCStr(name));
|
51
|
+
tree_sitter_lang *make_ts_language = dlsym(lib, buf);
|
52
|
+
err = dlerror();
|
53
|
+
if (err != NULL) {
|
54
|
+
dlclose(lib);
|
55
|
+
rb_raise(rb_eRuntimeError,
|
56
|
+
"Could not load symbol `%s' from library `%s'.\nReason:%s",
|
57
|
+
StringValueCStr(name), path_cstr, err);
|
58
|
+
}
|
59
|
+
|
60
|
+
TSLanguage *lang = make_ts_language();
|
61
|
+
if (lang == NULL) {
|
62
|
+
dlclose(lib);
|
63
|
+
rb_raise(rb_eRuntimeError,
|
64
|
+
"TSLanguage = NULL for language `%s' in library `%s'.\nCall your "
|
65
|
+
"local TSLanguage supplier.",
|
66
|
+
StringValueCStr(name), path_cstr);
|
67
|
+
}
|
68
|
+
|
69
|
+
uint32_t version = ts_language_version(lang);
|
70
|
+
if (version < TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION) {
|
71
|
+
rb_raise(rb_eRuntimeError,
|
72
|
+
"Language %s (v%d) from `%s' is old.\nMinimum supported ABI: "
|
73
|
+
"v%d.\nCurrent ABI: v%d.",
|
74
|
+
StringValueCStr(name), version, path_cstr,
|
75
|
+
TREE_SITTER_MIN_COMPATIBLE_LANGUAGE_VERSION,
|
76
|
+
TREE_SITTER_LANGUAGE_VERSION);
|
77
|
+
}
|
78
|
+
|
79
|
+
return new_language(lang);
|
80
|
+
}
|
81
|
+
|
82
|
+
static VALUE language_equal(VALUE self, VALUE other) {
|
83
|
+
TSLanguage *this = SELF;
|
84
|
+
TSLanguage *that = unwrap(other)->data;
|
85
|
+
return this == that ? Qtrue : Qfalse;
|
86
|
+
}
|
87
|
+
|
88
|
+
/**
|
89
|
+
* Get the number of distinct field names in the language.
|
90
|
+
*
|
91
|
+
* @return [Integer]
|
92
|
+
*/
|
93
|
+
static VALUE language_field_count(VALUE self) {
|
94
|
+
return UINT2NUM(ts_language_field_count(SELF));
|
95
|
+
}
|
96
|
+
|
97
|
+
/**
|
98
|
+
* Get the numerical id for the given field name string.
|
99
|
+
*
|
100
|
+
* @param name [String]
|
101
|
+
*
|
102
|
+
* @return [Integer]
|
103
|
+
*/
|
104
|
+
static VALUE language_field_id_for_name(VALUE self, VALUE name) {
|
105
|
+
TSLanguage *language = SELF;
|
106
|
+
const char *str = StringValuePtr(name);
|
107
|
+
uint32_t length = (uint32_t)RSTRING_LEN(name);
|
108
|
+
return UINT2NUM(ts_language_field_id_for_name(language, str, length));
|
109
|
+
}
|
110
|
+
|
111
|
+
/**
|
112
|
+
* Get the field name string for the given numerical id.
|
113
|
+
*
|
114
|
+
* @param field_id [Integer]
|
115
|
+
*
|
116
|
+
* @return [String]
|
117
|
+
*/
|
118
|
+
static VALUE language_field_name_for_id(VALUE self, VALUE field_id) {
|
119
|
+
return safe_str(ts_language_field_name_for_id(SELF, NUM2UINT(field_id)));
|
120
|
+
}
|
121
|
+
|
122
|
+
/**
|
123
|
+
* Get the next parse state. Combine this with lookahead iterators to generate
|
124
|
+
* completion suggestions or valid symbols in error nodes. Use
|
125
|
+
* {Node#grammar_symbol} for valid symbols.
|
126
|
+
*/
|
127
|
+
static VALUE language_next_state(VALUE self, VALUE state, VALUE symbol) {
|
128
|
+
uint16_t sta = (uint16_t)NUM2UINT(state);
|
129
|
+
uint16_t sym = (uint16_t)NUM2UINT(symbol);
|
130
|
+
return UINT2NUM(ts_language_next_state(SELF, sta, sym));
|
131
|
+
}
|
132
|
+
|
133
|
+
/**
|
134
|
+
* Get the number of distinct node types in the language.
|
135
|
+
*
|
136
|
+
* @return [Integer]
|
137
|
+
*/
|
138
|
+
static VALUE language_symbol_count(VALUE self) {
|
139
|
+
return UINT2NUM(ts_language_symbol_count(SELF));
|
140
|
+
}
|
141
|
+
|
142
|
+
/**
|
143
|
+
* Get a node type string for the given numerical id.
|
144
|
+
*
|
145
|
+
* @param symbol [Integer]
|
146
|
+
*
|
147
|
+
* @return [String]
|
148
|
+
*/
|
149
|
+
static VALUE language_symbol_name(VALUE self, VALUE symbol) {
|
150
|
+
return safe_str(ts_language_symbol_name(SELF, NUM2UINT(symbol)));
|
151
|
+
}
|
152
|
+
|
153
|
+
/**
|
154
|
+
* Get the numerical id for the given node type string.
|
155
|
+
*
|
156
|
+
* @param string [Symbol]
|
157
|
+
* @param is_named [Boolean]
|
158
|
+
*
|
159
|
+
* @return [Integer]
|
160
|
+
*/
|
161
|
+
static VALUE language_symbol_for_name(VALUE self, VALUE string,
|
162
|
+
VALUE is_named) {
|
163
|
+
const char *str = rb_id2name(SYM2ID(string));
|
164
|
+
uint32_t length = (uint32_t)strlen(str);
|
165
|
+
bool named = RTEST(is_named);
|
166
|
+
return UINT2NUM(ts_language_symbol_for_name(SELF, str, length, named));
|
167
|
+
}
|
168
|
+
|
169
|
+
/**
|
170
|
+
* Check whether the given node type id belongs to named nodes, anonymous nodes,
|
171
|
+
* or a hidden nodes.
|
172
|
+
*
|
173
|
+
* Hidden nodes are never returned from the API.
|
174
|
+
*
|
175
|
+
* @see Node#named?
|
176
|
+
*
|
177
|
+
* @param symbol [Integer]
|
178
|
+
*
|
179
|
+
* @return [SymbolType]
|
180
|
+
*/
|
181
|
+
static VALUE language_symbol_type(VALUE self, VALUE symbol) {
|
182
|
+
return new_symbol_type(ts_language_symbol_type(SELF, NUM2UINT(symbol)));
|
183
|
+
}
|
184
|
+
|
185
|
+
/**
|
186
|
+
* Get the ABI version number for this language. This version number is used
|
187
|
+
* to ensure that languages were generated by a compatible version of
|
188
|
+
* Tree-sitter.
|
189
|
+
*
|
190
|
+
* @see Parser#language=
|
191
|
+
*/
|
192
|
+
static VALUE language_version(VALUE self) {
|
193
|
+
return UINT2NUM(ts_language_version(SELF));
|
194
|
+
}
|
195
|
+
|
196
|
+
void init_language(void) {
|
197
|
+
cLanguage = rb_define_class_under(mTreeSitter, "Language", rb_cObject);
|
198
|
+
|
199
|
+
rb_define_alloc_func(cLanguage, language_allocate);
|
200
|
+
|
201
|
+
/* Module methods */
|
202
|
+
rb_define_module_function(cLanguage, "load", language_load, 2);
|
203
|
+
|
204
|
+
/* Operators */
|
205
|
+
rb_define_method(cLanguage, "==", language_equal, 1);
|
206
|
+
|
207
|
+
/* Class methods */
|
208
|
+
rb_define_method(cLanguage, "field_count", language_field_count, 0);
|
209
|
+
rb_define_method(cLanguage, "field_id_for_name", language_field_id_for_name,
|
210
|
+
1);
|
211
|
+
rb_define_method(cLanguage, "field_name_for_id", language_field_name_for_id,
|
212
|
+
1);
|
213
|
+
rb_define_method(cLanguage, "next_state", language_next_state, 2);
|
214
|
+
rb_define_method(cLanguage, "symbol_count", language_symbol_count, 0);
|
215
|
+
rb_define_method(cLanguage, "symbol_for_name", language_symbol_for_name, 2);
|
216
|
+
rb_define_method(cLanguage, "symbol_name", language_symbol_name, 1);
|
217
|
+
rb_define_method(cLanguage, "symbol_type", language_symbol_type, 1);
|
218
|
+
rb_define_method(cLanguage, "version", language_version, 0);
|
219
|
+
}
|
@@ -0,0 +1,228 @@
|
|
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
|
+
/**
|
151
|
+
* Create a new logger.
|
152
|
+
*
|
153
|
+
* By default, it logs to stderr.
|
154
|
+
*
|
155
|
+
* You can provide your proper backend. You have to make sure that it
|
156
|
+
* exposes a +printf+, +puts+, or +write+ (lookup is done in that specific
|
157
|
+
* order). {::StringIO} is a perfect candidate.
|
158
|
+
*
|
159
|
+
* You can also provide a format ({::String}) if your backend supports a +printf+.
|
160
|
+
*
|
161
|
+
* @example
|
162
|
+
* backend = StringIO.new
|
163
|
+
* parser.logger = TreeSitter::Logger.new(backend)
|
164
|
+
*
|
165
|
+
* @param args [Array] The first argument is always a backend. The second
|
166
|
+
* argument is the format.
|
167
|
+
*/
|
168
|
+
static VALUE logger_initialize(int argc, VALUE *argv, VALUE self) {
|
169
|
+
// TODO:
|
170
|
+
// For now, we only take:
|
171
|
+
// argv[0] = stream
|
172
|
+
// argv[1] = format : String
|
173
|
+
// We need to add support for argv[1] : lambda/block
|
174
|
+
// case argv[1]
|
175
|
+
// in lambda => lambda
|
176
|
+
// in String => puts || printf || write
|
177
|
+
// else => write
|
178
|
+
// end
|
179
|
+
logger_t *logger = unwrap(self);
|
180
|
+
|
181
|
+
VALUE payload;
|
182
|
+
VALUE format;
|
183
|
+
rb_scan_args(argc, argv, "02", &payload, &format);
|
184
|
+
|
185
|
+
logger->format = format;
|
186
|
+
|
187
|
+
if (argc == 0) {
|
188
|
+
logger_initialize_stderr(logger);
|
189
|
+
} else {
|
190
|
+
logger_payload_set(logger, payload);
|
191
|
+
}
|
192
|
+
|
193
|
+
return self;
|
194
|
+
}
|
195
|
+
|
196
|
+
static VALUE logger_inspect(VALUE self) {
|
197
|
+
logger_t *logger = unwrap(self);
|
198
|
+
return rb_sprintf("{payload=%+" PRIsVALUE ", format=%+" PRIsVALUE "}",
|
199
|
+
logger->payload, logger->format);
|
200
|
+
}
|
201
|
+
|
202
|
+
DATA_FAST_FORWARD_FNV(logger, write, payload)
|
203
|
+
DATA_FAST_FORWARD_FNV(logger, puts, payload)
|
204
|
+
DATA_FAST_FORWARD_FNV(logger, printf, payload)
|
205
|
+
|
206
|
+
DEFINE_ACCESSOR(logger, format)
|
207
|
+
DEFINE_GETTER(logger, payload)
|
208
|
+
|
209
|
+
static VALUE logger_set_payload(VALUE self, VALUE payload) {
|
210
|
+
logger_payload_set(unwrap(self), payload);
|
211
|
+
return Qnil;
|
212
|
+
}
|
213
|
+
|
214
|
+
void init_logger(void) {
|
215
|
+
cLogger = rb_define_class_under(mTreeSitter, "Logger", rb_cObject);
|
216
|
+
|
217
|
+
rb_define_alloc_func(cLogger, logger_allocate);
|
218
|
+
|
219
|
+
/* Class methods */
|
220
|
+
rb_define_method(cLogger, "initialize", logger_initialize, -1);
|
221
|
+
DECLARE_ACCESSOR(cLogger, logger, format)
|
222
|
+
DECLARE_ACCESSOR(cLogger, logger, payload)
|
223
|
+
rb_define_method(cLogger, "write", logger_write, -1);
|
224
|
+
rb_define_method(cLogger, "puts", logger_puts, -1);
|
225
|
+
rb_define_method(cLogger, "printf", logger_printf, -1);
|
226
|
+
rb_define_method(cLogger, "inspect", logger_inspect, 0);
|
227
|
+
rb_define_method(cLogger, "to_s", logger_inspect, 0);
|
228
|
+
}
|
@@ -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
|