yarp 0.7.0 → 0.9.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +54 -2
- data/Makefile +2 -0
- data/README.md +9 -5
- data/config.yml +160 -93
- data/docs/configuration.md +1 -0
- data/docs/ruby_api.md +2 -0
- data/docs/serialization.md +1 -1
- data/docs/testing.md +2 -2
- data/ext/yarp/api_node.c +361 -238
- data/ext/yarp/extension.c +75 -26
- data/ext/yarp/extension.h +2 -2
- data/include/yarp/ast.h +226 -175
- data/include/yarp/defines.h +5 -0
- data/include/yarp/node.h +10 -0
- data/include/yarp/unescape.h +4 -2
- data/include/yarp/util/yp_buffer.h +9 -1
- data/include/yarp/util/yp_constant_pool.h +3 -0
- data/include/yarp/util/yp_list.h +7 -7
- data/include/yarp/util/yp_newline_list.h +7 -0
- data/include/yarp/util/yp_state_stack.h +1 -1
- data/include/yarp/version.h +2 -2
- data/include/yarp.h +10 -0
- data/lib/yarp/desugar_visitor.rb +267 -0
- data/lib/yarp/ffi.rb +89 -48
- data/lib/yarp/lex_compat.rb +93 -25
- data/lib/yarp/mutation_visitor.rb +683 -0
- data/lib/yarp/node.rb +2061 -422
- data/lib/yarp/serialize.rb +162 -120
- data/lib/yarp.rb +54 -8
- data/src/node.c +360 -304
- data/src/prettyprint.c +190 -152
- data/src/serialize.c +382 -340
- data/src/token_type.c +2 -2
- data/src/unescape.c +89 -77
- data/src/util/yp_buffer.c +18 -0
- data/src/util/yp_list.c +7 -16
- data/src/util/yp_newline_list.c +10 -0
- data/src/util/yp_state_stack.c +0 -6
- data/src/yarp.c +941 -596
- data/yarp.gemspec +3 -1
- metadata +4 -2
@@ -12,16 +12,24 @@
|
|
12
12
|
// A yp_buffer_t is a simple memory buffer that stores data in a contiguous
|
13
13
|
// block of memory. It is used to store the serialized representation of a
|
14
14
|
// YARP tree.
|
15
|
-
// NOTE: keep in sync with YARP::LibRubyParser::Buffer in lib/yarp.rb
|
16
15
|
typedef struct {
|
17
16
|
char *value;
|
18
17
|
size_t length;
|
19
18
|
size_t capacity;
|
20
19
|
} yp_buffer_t;
|
21
20
|
|
21
|
+
// Return the size of the yp_buffer_t struct.
|
22
|
+
YP_EXPORTED_FUNCTION size_t yp_buffer_sizeof(void);
|
23
|
+
|
22
24
|
// Initialize a yp_buffer_t with its default values.
|
23
25
|
YP_EXPORTED_FUNCTION bool yp_buffer_init(yp_buffer_t *buffer);
|
24
26
|
|
27
|
+
// Return the value of the buffer.
|
28
|
+
YP_EXPORTED_FUNCTION char * yp_buffer_value(yp_buffer_t *buffer);
|
29
|
+
|
30
|
+
// Return the length of the buffer.
|
31
|
+
YP_EXPORTED_FUNCTION size_t yp_buffer_length(yp_buffer_t *buffer);
|
32
|
+
|
25
33
|
// Append the given amount of space as zeroes to the buffer.
|
26
34
|
void yp_buffer_append_zeroes(yp_buffer_t *buffer, size_t length);
|
27
35
|
|
@@ -51,6 +51,9 @@ typedef struct {
|
|
51
51
|
size_t capacity;
|
52
52
|
} yp_constant_pool_t;
|
53
53
|
|
54
|
+
// Define an empty constant pool.
|
55
|
+
#define YP_CONSTANT_POOL_EMPTY ((yp_constant_pool_t) { .constants = NULL, .size = 0, .capacity = 0 })
|
56
|
+
|
54
57
|
// Initialize a new constant pool with a given capacity.
|
55
58
|
bool yp_constant_pool_init(yp_constant_pool_t *pool, size_t capacity);
|
56
59
|
|
data/include/yarp/util/yp_list.h
CHANGED
@@ -15,9 +15,7 @@
|
|
15
15
|
// int value;
|
16
16
|
// } yp_int_node_t;
|
17
17
|
//
|
18
|
-
// yp_list_t list;
|
19
|
-
// yp_list_init(&list);
|
20
|
-
//
|
18
|
+
// yp_list_t list = YP_LIST_EMPTY;
|
21
19
|
// yp_int_node_t *node = malloc(sizeof(yp_int_node_t));
|
22
20
|
// node->value = 5;
|
23
21
|
//
|
@@ -45,18 +43,20 @@ typedef struct yp_list_node {
|
|
45
43
|
// This represents the overall linked list. It keeps a pointer to the head and
|
46
44
|
// tail so that iteration is easy and pushing new nodes is easy.
|
47
45
|
typedef struct {
|
46
|
+
size_t size;
|
48
47
|
yp_list_node_t *head;
|
49
48
|
yp_list_node_t *tail;
|
50
49
|
} yp_list_t;
|
51
50
|
|
52
|
-
//
|
53
|
-
|
51
|
+
// This represents an empty list. It's used to initialize a stack-allocated list
|
52
|
+
// as opposed to a method call.
|
53
|
+
#define YP_LIST_EMPTY ((yp_list_t) { .size = 0, .head = NULL, .tail = NULL })
|
54
54
|
|
55
55
|
// Returns true if the given list is empty.
|
56
56
|
YP_EXPORTED_FUNCTION bool yp_list_empty_p(yp_list_t *list);
|
57
57
|
|
58
|
-
// Returns the size of the list
|
59
|
-
YP_EXPORTED_FUNCTION
|
58
|
+
// Returns the size of the list.
|
59
|
+
YP_EXPORTED_FUNCTION size_t yp_list_size(yp_list_t *list);
|
60
60
|
|
61
61
|
// Append a node to the given list.
|
62
62
|
void yp_list_append(yp_list_t *list, yp_list_node_t *node);
|
@@ -35,6 +35,10 @@ typedef struct {
|
|
35
35
|
size_t column;
|
36
36
|
} yp_line_column_t;
|
37
37
|
|
38
|
+
#define YP_NEWLINE_LIST_EMPTY ((yp_newline_list_t) { \
|
39
|
+
.start = NULL, .offsets = NULL, .size = 0, .capacity = 0, .last_offset = 0, .last_index = 0 \
|
40
|
+
})
|
41
|
+
|
38
42
|
// Initialize a new newline list with the given capacity. Returns true if the
|
39
43
|
// allocation of the offsets succeeds, otherwise returns false.
|
40
44
|
bool yp_newline_list_init(yp_newline_list_t *list, const char *start, size_t capacity);
|
@@ -43,6 +47,9 @@ bool yp_newline_list_init(yp_newline_list_t *list, const char *start, size_t cap
|
|
43
47
|
// the offsets succeeds (if one was necessary), otherwise returns false.
|
44
48
|
bool yp_newline_list_append(yp_newline_list_t *list, const char *cursor);
|
45
49
|
|
50
|
+
// Conditionally append a new offset to the newline list, if the value passed in is a newline.
|
51
|
+
bool yp_newline_list_check_append(yp_newline_list_t *list, const char *cursor);
|
52
|
+
|
46
53
|
// Returns the line and column of the given offset. If the offset is not in the
|
47
54
|
// list, the line and column of the closest offset less than the given offset
|
48
55
|
// are returned.
|
@@ -10,7 +10,7 @@
|
|
10
10
|
typedef uint32_t yp_state_stack_t;
|
11
11
|
|
12
12
|
// Initializes the state stack to an empty stack.
|
13
|
-
|
13
|
+
#define YP_STATE_STACK_EMPTY ((yp_state_stack_t) 0)
|
14
14
|
|
15
15
|
// Pushes a value onto the stack.
|
16
16
|
void yp_state_stack_push(yp_state_stack_t *stack, bool value);
|
data/include/yarp/version.h
CHANGED
data/include/yarp.h
CHANGED
@@ -13,6 +13,7 @@
|
|
13
13
|
#include "yarp/util/yp_char.h"
|
14
14
|
#include "yarp/util/yp_memchr.h"
|
15
15
|
#include "yarp/util/yp_strpbrk.h"
|
16
|
+
#include "yarp/version.h"
|
16
17
|
|
17
18
|
#include <assert.h>
|
18
19
|
#include <stdarg.h>
|
@@ -30,6 +31,11 @@ void yp_serialize_content(yp_parser_t *parser, yp_node_t *node, yp_buffer_t *buf
|
|
30
31
|
|
31
32
|
void yp_print_node(yp_parser_t *parser, yp_node_t *node);
|
32
33
|
|
34
|
+
void yp_parser_metadata(yp_parser_t *parser, const char *metadata);
|
35
|
+
|
36
|
+
// Generate a scope node from the given node.
|
37
|
+
void yp_scope_node_init(yp_node_t *node, yp_scope_node_t *dest);
|
38
|
+
|
33
39
|
// The YARP version and the serialization format.
|
34
40
|
YP_EXPORTED_FUNCTION const char * yp_version(void);
|
35
41
|
|
@@ -65,6 +71,10 @@ YP_EXPORTED_FUNCTION void yp_parse_serialize(const char *source, size_t size, yp
|
|
65
71
|
// Lex the given source and serialize to the given buffer.
|
66
72
|
YP_EXPORTED_FUNCTION void yp_lex_serialize(const char *source, size_t size, const char *filepath, yp_buffer_t *buffer);
|
67
73
|
|
74
|
+
// Parse and serialize both the AST and the tokens represented by the given
|
75
|
+
// source to the given buffer.
|
76
|
+
YP_EXPORTED_FUNCTION void yp_parse_lex_serialize(const char *source, size_t size, yp_buffer_t *buffer, const char *metadata);
|
77
|
+
|
68
78
|
// Returns a string representation of the given token type.
|
69
79
|
YP_EXPORTED_FUNCTION const char * yp_token_type_to_str(yp_token_type_t token_type);
|
70
80
|
|
@@ -0,0 +1,267 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module YARP
|
4
|
+
class DesugarVisitor < MutationVisitor
|
5
|
+
# @@foo &&= bar
|
6
|
+
#
|
7
|
+
# becomes
|
8
|
+
#
|
9
|
+
# @@foo && @@foo = bar
|
10
|
+
def visit_class_variable_and_write_node(node)
|
11
|
+
AndNode.new(
|
12
|
+
ClassVariableReadNode.new(node.name_loc),
|
13
|
+
ClassVariableWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location),
|
14
|
+
node.operator_loc,
|
15
|
+
node.location
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
# @@foo ||= bar
|
20
|
+
#
|
21
|
+
# becomes
|
22
|
+
#
|
23
|
+
# @@foo || @@foo = bar
|
24
|
+
def visit_class_variable_or_write_node(node)
|
25
|
+
OrNode.new(
|
26
|
+
ClassVariableReadNode.new(node.name_loc),
|
27
|
+
ClassVariableWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location),
|
28
|
+
node.operator_loc,
|
29
|
+
node.location
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
# @@foo += bar
|
34
|
+
#
|
35
|
+
# becomes
|
36
|
+
#
|
37
|
+
# @@foo = @@foo + bar
|
38
|
+
def visit_class_variable_operator_write_node(node)
|
39
|
+
desugar_operator_write_node(node, ClassVariableWriteNode, ClassVariableReadNode)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Foo &&= bar
|
43
|
+
#
|
44
|
+
# becomes
|
45
|
+
#
|
46
|
+
# Foo && Foo = bar
|
47
|
+
def visit_constant_and_write_node(node)
|
48
|
+
AndNode.new(
|
49
|
+
ConstantReadNode.new(node.name_loc),
|
50
|
+
ConstantWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location),
|
51
|
+
node.operator_loc,
|
52
|
+
node.location
|
53
|
+
)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Foo ||= bar
|
57
|
+
#
|
58
|
+
# becomes
|
59
|
+
#
|
60
|
+
# Foo || Foo = bar
|
61
|
+
def visit_constant_or_write_node(node)
|
62
|
+
OrNode.new(
|
63
|
+
ConstantReadNode.new(node.name_loc),
|
64
|
+
ConstantWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location),
|
65
|
+
node.operator_loc,
|
66
|
+
node.location
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Foo += bar
|
71
|
+
#
|
72
|
+
# becomes
|
73
|
+
#
|
74
|
+
# Foo = Foo + bar
|
75
|
+
def visit_constant_operator_write_node(node)
|
76
|
+
desugar_operator_write_node(node, ConstantWriteNode, ConstantReadNode)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Foo::Bar &&= baz
|
80
|
+
#
|
81
|
+
# becomes
|
82
|
+
#
|
83
|
+
# Foo::Bar && Foo::Bar = baz
|
84
|
+
def visit_constant_path_and_write_node(node)
|
85
|
+
AndNode.new(
|
86
|
+
node.target,
|
87
|
+
ConstantPathWriteNode.new(node.target, node.value, node.operator_loc, node.location),
|
88
|
+
node.operator_loc,
|
89
|
+
node.location
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Foo::Bar ||= baz
|
94
|
+
#
|
95
|
+
# becomes
|
96
|
+
#
|
97
|
+
# Foo::Bar || Foo::Bar = baz
|
98
|
+
def visit_constant_path_or_write_node(node)
|
99
|
+
OrNode.new(
|
100
|
+
node.target,
|
101
|
+
ConstantPathWriteNode.new(node.target, node.value, node.operator_loc, node.location),
|
102
|
+
node.operator_loc,
|
103
|
+
node.location
|
104
|
+
)
|
105
|
+
end
|
106
|
+
|
107
|
+
# Foo::Bar += baz
|
108
|
+
#
|
109
|
+
# becomes
|
110
|
+
#
|
111
|
+
# Foo::Bar = Foo::Bar + baz
|
112
|
+
def visit_constant_path_operator_write_node(node)
|
113
|
+
ConstantPathWriteNode.new(
|
114
|
+
node.target,
|
115
|
+
CallNode.new(
|
116
|
+
node.target,
|
117
|
+
nil,
|
118
|
+
node.operator_loc.copy(length: node.operator_loc.length - 1),
|
119
|
+
nil,
|
120
|
+
ArgumentsNode.new([node.value], node.value.location),
|
121
|
+
nil,
|
122
|
+
nil,
|
123
|
+
0,
|
124
|
+
node.operator_loc.slice.chomp("="),
|
125
|
+
node.location
|
126
|
+
),
|
127
|
+
node.operator_loc.copy(start_offset: node.operator_loc.end_offset - 1, length: 1),
|
128
|
+
node.location
|
129
|
+
)
|
130
|
+
end
|
131
|
+
|
132
|
+
# $foo &&= bar
|
133
|
+
#
|
134
|
+
# becomes
|
135
|
+
#
|
136
|
+
# $foo && $foo = bar
|
137
|
+
def visit_global_variable_and_write_node(node)
|
138
|
+
AndNode.new(
|
139
|
+
GlobalVariableReadNode.new(node.name_loc),
|
140
|
+
GlobalVariableWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location),
|
141
|
+
node.operator_loc,
|
142
|
+
node.location
|
143
|
+
)
|
144
|
+
end
|
145
|
+
|
146
|
+
# $foo ||= bar
|
147
|
+
#
|
148
|
+
# becomes
|
149
|
+
#
|
150
|
+
# $foo || $foo = bar
|
151
|
+
def visit_global_variable_or_write_node(node)
|
152
|
+
OrNode.new(
|
153
|
+
GlobalVariableReadNode.new(node.name_loc),
|
154
|
+
GlobalVariableWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location),
|
155
|
+
node.operator_loc,
|
156
|
+
node.location
|
157
|
+
)
|
158
|
+
end
|
159
|
+
|
160
|
+
# $foo += bar
|
161
|
+
#
|
162
|
+
# becomes
|
163
|
+
#
|
164
|
+
# $foo = $foo + bar
|
165
|
+
def visit_global_variable_operator_write_node(node)
|
166
|
+
desugar_operator_write_node(node, GlobalVariableWriteNode, GlobalVariableReadNode)
|
167
|
+
end
|
168
|
+
|
169
|
+
# @foo &&= bar
|
170
|
+
#
|
171
|
+
# becomes
|
172
|
+
#
|
173
|
+
# @foo && @foo = bar
|
174
|
+
def visit_instance_variable_and_write_node(node)
|
175
|
+
AndNode.new(
|
176
|
+
InstanceVariableReadNode.new(node.name_loc),
|
177
|
+
InstanceVariableWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location),
|
178
|
+
node.operator_loc,
|
179
|
+
node.location
|
180
|
+
)
|
181
|
+
end
|
182
|
+
|
183
|
+
# @foo ||= bar
|
184
|
+
#
|
185
|
+
# becomes
|
186
|
+
#
|
187
|
+
# @foo || @foo = bar
|
188
|
+
def visit_instance_variable_or_write_node(node)
|
189
|
+
OrNode.new(
|
190
|
+
InstanceVariableReadNode.new(node.name_loc),
|
191
|
+
InstanceVariableWriteNode.new(node.name_loc, node.value, node.operator_loc, node.location),
|
192
|
+
node.operator_loc,
|
193
|
+
node.location
|
194
|
+
)
|
195
|
+
end
|
196
|
+
|
197
|
+
# @foo += bar
|
198
|
+
#
|
199
|
+
# becomes
|
200
|
+
#
|
201
|
+
# @foo = @foo + bar
|
202
|
+
def visit_instance_variable_operator_write_node(node)
|
203
|
+
desugar_operator_write_node(node, InstanceVariableWriteNode, InstanceVariableReadNode)
|
204
|
+
end
|
205
|
+
|
206
|
+
# foo &&= bar
|
207
|
+
#
|
208
|
+
# becomes
|
209
|
+
#
|
210
|
+
# foo && foo = bar
|
211
|
+
def visit_local_variable_and_write_node(node)
|
212
|
+
AndNode.new(
|
213
|
+
LocalVariableReadNode.new(node.constant_id, node.depth, node.name_loc),
|
214
|
+
LocalVariableWriteNode.new(node.constant_id, node.depth, node.name_loc, node.value, node.operator_loc, node.location),
|
215
|
+
node.operator_loc,
|
216
|
+
node.location
|
217
|
+
)
|
218
|
+
end
|
219
|
+
|
220
|
+
# foo ||= bar
|
221
|
+
#
|
222
|
+
# becomes
|
223
|
+
#
|
224
|
+
# foo || foo = bar
|
225
|
+
def visit_local_variable_or_write_node(node)
|
226
|
+
OrNode.new(
|
227
|
+
LocalVariableReadNode.new(node.constant_id, node.depth, node.name_loc),
|
228
|
+
LocalVariableWriteNode.new(node.constant_id, node.depth, node.name_loc, node.value, node.operator_loc, node.location),
|
229
|
+
node.operator_loc,
|
230
|
+
node.location
|
231
|
+
)
|
232
|
+
end
|
233
|
+
|
234
|
+
# foo += bar
|
235
|
+
#
|
236
|
+
# becomes
|
237
|
+
#
|
238
|
+
# foo = foo + bar
|
239
|
+
def visit_local_variable_operator_write_node(node)
|
240
|
+
desugar_operator_write_node(node, LocalVariableWriteNode, LocalVariableReadNode, arguments: [node.constant_id, node.depth])
|
241
|
+
end
|
242
|
+
|
243
|
+
private
|
244
|
+
|
245
|
+
# Desugar `x += y` to `x = x + y`
|
246
|
+
def desugar_operator_write_node(node, write_class, read_class, arguments: [])
|
247
|
+
write_class.new(
|
248
|
+
*arguments,
|
249
|
+
node.name_loc,
|
250
|
+
CallNode.new(
|
251
|
+
read_class.new(*arguments, node.name_loc),
|
252
|
+
nil,
|
253
|
+
node.operator_loc.copy(length: node.operator_loc.length - 1),
|
254
|
+
nil,
|
255
|
+
ArgumentsNode.new([node.value], node.value.location),
|
256
|
+
nil,
|
257
|
+
nil,
|
258
|
+
0,
|
259
|
+
node.operator_loc.slice.chomp("="),
|
260
|
+
node.location
|
261
|
+
),
|
262
|
+
node.operator_loc.copy(start_offset: node.operator_loc.end_offset - 1, length: 1),
|
263
|
+
node.location
|
264
|
+
)
|
265
|
+
end
|
266
|
+
end
|
267
|
+
end
|
data/lib/yarp/ffi.rb
CHANGED
@@ -70,12 +70,16 @@ module YARP
|
|
70
70
|
"yarp.h",
|
71
71
|
"yp_version",
|
72
72
|
"yp_parse_serialize",
|
73
|
-
"yp_lex_serialize"
|
73
|
+
"yp_lex_serialize",
|
74
|
+
"yp_parse_lex_serialize"
|
74
75
|
)
|
75
76
|
|
76
77
|
load_exported_functions_from(
|
77
78
|
"yarp/util/yp_buffer.h",
|
79
|
+
"yp_buffer_sizeof",
|
78
80
|
"yp_buffer_init",
|
81
|
+
"yp_buffer_value",
|
82
|
+
"yp_buffer_length",
|
79
83
|
"yp_buffer_free"
|
80
84
|
)
|
81
85
|
|
@@ -88,34 +92,49 @@ module YARP
|
|
88
92
|
"yp_string_sizeof"
|
89
93
|
)
|
90
94
|
|
91
|
-
# This object represents a yp_buffer_t.
|
92
|
-
#
|
93
|
-
class YPBuffer
|
94
|
-
|
95
|
+
# This object represents a yp_buffer_t. We only use it as an opaque pointer,
|
96
|
+
# so it doesn't need to know the fields of yp_buffer_t.
|
97
|
+
class YPBuffer
|
98
|
+
SIZEOF = LibRubyParser.yp_buffer_sizeof
|
95
99
|
|
96
|
-
|
97
|
-
|
98
|
-
|
100
|
+
attr_reader :pointer
|
101
|
+
|
102
|
+
def initialize(pointer)
|
103
|
+
@pointer = pointer
|
99
104
|
end
|
100
|
-
end
|
101
105
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
106
|
+
def value
|
107
|
+
LibRubyParser.yp_buffer_value(pointer)
|
108
|
+
end
|
109
|
+
|
110
|
+
def length
|
111
|
+
LibRubyParser.yp_buffer_length(pointer)
|
112
|
+
end
|
113
|
+
|
114
|
+
def read
|
115
|
+
value.read_string(length)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Initialize a new buffer and yield it to the block. The buffer will be
|
119
|
+
# automatically freed when the block returns.
|
120
|
+
def self.with(&block)
|
121
|
+
pointer = FFI::MemoryPointer.new(SIZEOF)
|
122
|
+
|
123
|
+
begin
|
124
|
+
raise unless LibRubyParser.yp_buffer_init(pointer)
|
125
|
+
yield new(pointer)
|
126
|
+
ensure
|
127
|
+
LibRubyParser.yp_buffer_free(pointer)
|
128
|
+
pointer.free
|
129
|
+
end
|
113
130
|
end
|
114
131
|
end
|
115
132
|
|
116
133
|
# This object represents a yp_string_t. We only use it as an opaque pointer,
|
117
134
|
# so it doesn't have to be an FFI::Struct.
|
118
135
|
class YPString
|
136
|
+
SIZEOF = LibRubyParser.yp_string_sizeof
|
137
|
+
|
119
138
|
attr_reader :pointer
|
120
139
|
|
121
140
|
def initialize(pointer)
|
@@ -133,23 +152,18 @@ module YARP
|
|
133
152
|
def read
|
134
153
|
source.read_string(length)
|
135
154
|
end
|
136
|
-
end
|
137
155
|
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
yield YPString.new(string)
|
150
|
-
ensure
|
151
|
-
yp_string_free(string)
|
152
|
-
string.free
|
156
|
+
# Yields a yp_string_t pointer to the given block.
|
157
|
+
def self.with(filepath, &block)
|
158
|
+
pointer = FFI::MemoryPointer.new(SIZEOF)
|
159
|
+
|
160
|
+
begin
|
161
|
+
raise unless LibRubyParser.yp_string_mapped_init(pointer, filepath)
|
162
|
+
yield new(pointer)
|
163
|
+
ensure
|
164
|
+
LibRubyParser.yp_string_free(pointer)
|
165
|
+
pointer.free
|
166
|
+
end
|
153
167
|
end
|
154
168
|
end
|
155
169
|
end
|
@@ -162,10 +176,10 @@ module YARP
|
|
162
176
|
VERSION = LibRubyParser.yp_version.read_string
|
163
177
|
|
164
178
|
def self.dump_internal(source, source_size, filepath)
|
165
|
-
LibRubyParser.
|
179
|
+
LibRubyParser::YPBuffer.with do |buffer|
|
166
180
|
metadata = [filepath.bytesize, filepath.b, 0].pack("LA*L") if filepath
|
167
|
-
LibRubyParser.yp_parse_serialize(source, source_size, buffer, metadata)
|
168
|
-
buffer.
|
181
|
+
LibRubyParser.yp_parse_serialize(source, source_size, buffer.pointer, metadata)
|
182
|
+
buffer.read
|
169
183
|
end
|
170
184
|
end
|
171
185
|
private_class_method :dump_internal
|
@@ -177,35 +191,62 @@ module YARP
|
|
177
191
|
|
178
192
|
# Mirror the YARP.dump_file API by using the serialization API.
|
179
193
|
def self.dump_file(filepath)
|
180
|
-
LibRubyParser.
|
194
|
+
LibRubyParser::YPString.with(filepath) do |string|
|
181
195
|
dump_internal(string.source, string.length, filepath)
|
182
196
|
end
|
183
197
|
end
|
184
198
|
|
185
199
|
# Mirror the YARP.lex API by using the serialization API.
|
186
200
|
def self.lex(code, filepath = nil)
|
187
|
-
LibRubyParser.
|
188
|
-
LibRubyParser.yp_lex_serialize(code, code.bytesize, filepath, buffer)
|
189
|
-
|
190
|
-
source = Source.new(code)
|
191
|
-
Serialize.load_tokens(source, buffer.to_ruby_string).with_source(source)
|
201
|
+
LibRubyParser::YPBuffer.with do |buffer|
|
202
|
+
LibRubyParser.yp_lex_serialize(code, code.bytesize, filepath, buffer.pointer)
|
203
|
+
Serialize.load_tokens(Source.new(code), buffer.read)
|
192
204
|
end
|
193
205
|
end
|
194
206
|
|
195
207
|
# Mirror the YARP.lex_file API by using the serialization API.
|
196
208
|
def self.lex_file(filepath)
|
197
|
-
LibRubyParser.
|
209
|
+
LibRubyParser::YPString.with(filepath) do |string|
|
210
|
+
lex(string.read, filepath)
|
211
|
+
end
|
198
212
|
end
|
199
213
|
|
200
214
|
# Mirror the YARP.parse API by using the serialization API.
|
201
215
|
def self.parse(code, filepath = nil)
|
202
|
-
YARP.load(code, dump(code, filepath))
|
216
|
+
YARP.load(code, dump(code, filepath))
|
203
217
|
end
|
204
218
|
|
205
219
|
# Mirror the YARP.parse_file API by using the serialization API. This uses
|
206
220
|
# native strings instead of Ruby strings because it allows us to use mmap when
|
207
221
|
# it is available.
|
208
222
|
def self.parse_file(filepath)
|
209
|
-
LibRubyParser.
|
223
|
+
LibRubyParser::YPString.with(filepath) do |string|
|
224
|
+
parse(string.read, filepath)
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Mirror the YARP.parse_lex API by using the serialization API.
|
229
|
+
def self.parse_lex(code, filepath = nil)
|
230
|
+
LibRubyParser::YPBuffer.with do |buffer|
|
231
|
+
metadata = [filepath.bytesize, filepath.b, 0].pack("LA*L") if filepath
|
232
|
+
LibRubyParser.yp_parse_lex_serialize(code, code.bytesize, buffer.pointer, metadata)
|
233
|
+
|
234
|
+
source = Source.new(code)
|
235
|
+
loader = Serialize::Loader.new(source, buffer.read)
|
236
|
+
|
237
|
+
tokens = loader.load_tokens
|
238
|
+
node, comments, errors, warnings = loader.load_nodes
|
239
|
+
|
240
|
+
tokens.each { |token,| token.value.force_encoding(loader.encoding) }
|
241
|
+
|
242
|
+
ParseResult.new([node, tokens], comments, errors, warnings, source)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# Mirror the YARP.parse_lex_file API by using the serialization API.
|
247
|
+
def self.parse_lex_file(filepath)
|
248
|
+
LibRubyParser::YPString.with(filepath) do |string|
|
249
|
+
parse_lex(string.read, filepath)
|
250
|
+
end
|
210
251
|
end
|
211
252
|
end
|