parsetree19 0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/ChangeLog +155 -0
- data/NEWS +2 -0
- data/README.md +8 -0
- data/Rakefile +158 -0
- data/ext/add_to_parse_tree.inc +906 -0
- data/ext/extconf.rb +8 -0
- data/ext/parse_tree.c +149 -0
- data/include/method_mini.h +90 -0
- data/include/node.h +483 -0
- data/include/ruby19_externs.h +36 -0
- data/include/thread_pthread.h +24 -0
- data/include/vm_core_mini.h +369 -0
- data/test/unit/test_parse_tree_for_meth.rb +33 -0
- data/test/unit/test_parse_tree_for_str.rb +162 -0
- metadata +80 -0
@@ -0,0 +1,369 @@
|
|
1
|
+
/* Headers Exposing a little more of the 1.9 runtime and some
|
2
|
+
method prototypes for extensions to the Thread class.
|
3
|
+
*/
|
4
|
+
#include <ruby.h>
|
5
|
+
#include <signal.h>
|
6
|
+
#include "thread_pthread.h"
|
7
|
+
#include "node.h"
|
8
|
+
|
9
|
+
/* From vm_core.h: */
|
10
|
+
|
11
|
+
/* Frame information: */
|
12
|
+
#define VM_FRAME_MAGIC_METHOD 0x11
|
13
|
+
#define VM_FRAME_MAGIC_BLOCK 0x21
|
14
|
+
#define VM_FRAME_MAGIC_CLASS 0x31
|
15
|
+
#define VM_FRAME_MAGIC_TOP 0x41
|
16
|
+
#define VM_FRAME_MAGIC_FINISH 0x51
|
17
|
+
#define VM_FRAME_MAGIC_CFUNC 0x61
|
18
|
+
#define VM_FRAME_MAGIC_PROC 0x71
|
19
|
+
#define VM_FRAME_MAGIC_IFUNC 0x81
|
20
|
+
#define VM_FRAME_MAGIC_EVAL 0x91
|
21
|
+
#define VM_FRAME_MAGIC_LAMBDA 0xa1
|
22
|
+
#define VM_FRAME_MAGIC_MASK_BITS 8
|
23
|
+
#define VM_FRAME_MAGIC_MASK (~(~0<<VM_FRAME_MAGIC_MASK_BITS))
|
24
|
+
|
25
|
+
#define VM_FRAME_TYPE(cfp) ((cfp)->flag & VM_FRAME_MAGIC_MASK)
|
26
|
+
|
27
|
+
#define VM_FRAME_TRACE_RETURN 0x01 /* Call trace hook on return. */
|
28
|
+
#define VM_FRAME_TRACE_OFF 0x02 /* Turn of event hook tracing in this frame
|
29
|
+
and any frames created from this one. */
|
30
|
+
|
31
|
+
/* other frame flag */
|
32
|
+
#define VM_FRAME_FLAG_PASSED 0x0100
|
33
|
+
|
34
|
+
#define RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp) (cfp+1)
|
35
|
+
#define RUBYVM_CFUNC_FRAME_P(cfp) \
|
36
|
+
(VM_FRAME_TYPE(cfp) == VM_FRAME_MAGIC_CFUNC)
|
37
|
+
#define RUBY_VM_NEXT_CONTROL_FRAME(cfp) (cfp-1)
|
38
|
+
#define RUBY_VM_END_CONTROL_FRAME(th) \
|
39
|
+
((rb_control_frame_t *)((th)->stack + (th)->stack_size))
|
40
|
+
#define RUBY_VM_VALID_CONTROL_FRAME_P(cfp, ecfp) \
|
41
|
+
((void *)(ecfp) > (void *)(cfp))
|
42
|
+
#define RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(th, cfp) \
|
43
|
+
(!RUBY_VM_VALID_CONTROL_FRAME_P((cfp), RUBY_VM_END_CONTROL_FRAME(th)))
|
44
|
+
|
45
|
+
#define RUBY_VM_IFUNC_P(ptr) (BUILTIN_TYPE(ptr) == T_NODE)
|
46
|
+
#define RUBY_VM_NORMAL_ISEQ_P(ptr) \
|
47
|
+
(ptr && !RUBY_VM_IFUNC_P(ptr))
|
48
|
+
|
49
|
+
|
50
|
+
#if 1
|
51
|
+
#define GetCoreDataFromValue(obj, type, ptr) do { \
|
52
|
+
ptr = (type*)DATA_PTR(obj); \
|
53
|
+
} while (0)
|
54
|
+
#else
|
55
|
+
#define GetCoreDataFromValue(obj, type, ptr) Data_Get_Struct(obj, type, ptr)
|
56
|
+
#endif
|
57
|
+
#if 1
|
58
|
+
#define GetCoreDataFromValue(obj, type, ptr) do { \
|
59
|
+
ptr = (type*)DATA_PTR(obj); \
|
60
|
+
} while (0)
|
61
|
+
#else
|
62
|
+
#define GetCoreDataFromValue(obj, type, ptr) Data_Get_Struct(obj, type, ptr)
|
63
|
+
#endif
|
64
|
+
#define GetISeqPtr(obj, ptr) \
|
65
|
+
GetCoreDataFromValue(obj, rb_iseq_t, ptr)
|
66
|
+
|
67
|
+
/* Opaque types (for now at least) */
|
68
|
+
typedef struct iseq_catch_table_entry iseq_catch_table_entry_t;
|
69
|
+
|
70
|
+
#ifndef NSIG
|
71
|
+
# define NSIG (_SIGMAX + 1) /* For QNX */
|
72
|
+
#endif
|
73
|
+
|
74
|
+
#define RUBY_NSIG NSIG
|
75
|
+
|
76
|
+
typedef struct rb_compile_option_struct {
|
77
|
+
int inline_const_cache;
|
78
|
+
int peephole_optimization;
|
79
|
+
int tailcall_optimization;
|
80
|
+
int specialized_instruction;
|
81
|
+
int operands_unification;
|
82
|
+
int instructions_unification;
|
83
|
+
int stack_caching;
|
84
|
+
int trace_instruction;
|
85
|
+
int save_tree_node;
|
86
|
+
int save_compile_opts;
|
87
|
+
int debug_level;
|
88
|
+
} rb_compile_option_t;
|
89
|
+
|
90
|
+
/* Instruction sequence */
|
91
|
+
typedef struct rb_iseq_struct {
|
92
|
+
/***************/
|
93
|
+
/* static data */
|
94
|
+
/***************/
|
95
|
+
|
96
|
+
VALUE type; /* instruction sequence type */
|
97
|
+
VALUE name; /* String: iseq name */
|
98
|
+
VALUE filename; /* file information where this sequence from */
|
99
|
+
VALUE filepath; /* real file path or nil */
|
100
|
+
VALUE *iseq; /* iseq (insn number and operands) */
|
101
|
+
VALUE *iseq_encoded; /* encoded iseq */
|
102
|
+
unsigned long iseq_size;
|
103
|
+
VALUE mark_ary; /* Array: includes operands which should be GC marked */
|
104
|
+
VALUE coverage; /* coverage array */
|
105
|
+
unsigned short line_no;
|
106
|
+
|
107
|
+
/* insn info, must be freed */
|
108
|
+
struct iseq_insn_info_entry *insn_info_table;
|
109
|
+
size_t insn_info_size;
|
110
|
+
|
111
|
+
ID *local_table; /* must free */
|
112
|
+
int local_table_size;
|
113
|
+
|
114
|
+
/* method, class frame: sizeof(vars) + 1, block frame: sizeof(vars) */
|
115
|
+
int local_size;
|
116
|
+
|
117
|
+
struct iseq_inline_cache_entry *ic_entries;
|
118
|
+
int ic_size;
|
119
|
+
|
120
|
+
/**
|
121
|
+
* argument information
|
122
|
+
*
|
123
|
+
* def m(a1, a2, ..., aM, # mandatory
|
124
|
+
* b1=(...), b2=(...), ..., bN=(...), # optional
|
125
|
+
* *c, # rest
|
126
|
+
* d1, d2, ..., dO, # post
|
127
|
+
* &e) # block
|
128
|
+
* =>
|
129
|
+
*
|
130
|
+
* argc = M
|
131
|
+
* arg_rest = M+N+1 // or -1 if no rest arg
|
132
|
+
* arg_opts = N
|
133
|
+
* arg_opts_tbl = [ (N entries) ]
|
134
|
+
* arg_post_len = O // 0 if no post arguments
|
135
|
+
* arg_post_start = M+N+2
|
136
|
+
* arg_block = M+N + 1 + O + 1 // -1 if no block arg
|
137
|
+
* arg_simple = 0 if not simple arguments.
|
138
|
+
* = 1 if no opt, rest, post, block.
|
139
|
+
* = 2 if ambiguous block parameter ({|a|}).
|
140
|
+
* arg_size = argument size.
|
141
|
+
*/
|
142
|
+
|
143
|
+
int argc;
|
144
|
+
int arg_simple;
|
145
|
+
int arg_rest;
|
146
|
+
int arg_block;
|
147
|
+
int arg_opts;
|
148
|
+
int arg_post_len;
|
149
|
+
int arg_post_start;
|
150
|
+
int arg_size;
|
151
|
+
VALUE *arg_opt_table;
|
152
|
+
|
153
|
+
size_t stack_max; /* for stack overflow check */
|
154
|
+
|
155
|
+
/* catch table */
|
156
|
+
iseq_catch_table_entry_t *catch_table;
|
157
|
+
int catch_table_size;
|
158
|
+
|
159
|
+
/* for child iseq */
|
160
|
+
struct rb_iseq_struct *parent_iseq;
|
161
|
+
struct rb_iseq_struct *local_iseq;
|
162
|
+
|
163
|
+
/****************/
|
164
|
+
/* dynamic data */
|
165
|
+
/****************/
|
166
|
+
|
167
|
+
VALUE self;
|
168
|
+
VALUE orig; /* non-NULL if its data have origin */
|
169
|
+
|
170
|
+
/* block inlining */
|
171
|
+
/*
|
172
|
+
* NODE *node;
|
173
|
+
* void *special_block_builder;
|
174
|
+
* void *cached_special_block_builder;
|
175
|
+
* VALUE cached_special_block;
|
176
|
+
*/
|
177
|
+
|
178
|
+
/* klass/module nest information stack (cref) */
|
179
|
+
NODE *cref_stack;
|
180
|
+
VALUE klass;
|
181
|
+
|
182
|
+
/* misc */
|
183
|
+
ID defined_method_id; /* for define_method */
|
184
|
+
|
185
|
+
/* used at compile time */
|
186
|
+
struct iseq_compile_data *compile_data;
|
187
|
+
/* Used to set a breakpoint at a VM instruction */
|
188
|
+
unsigned char *breakpoints;
|
189
|
+
|
190
|
+
/* If this instruction sequence came from eval, the string of the
|
191
|
+
source as a String. */
|
192
|
+
VALUE source;
|
193
|
+
|
194
|
+
/* If we are saving tree nodes (a compile option), then tree_node
|
195
|
+
is the internal parse tree node representation for this
|
196
|
+
instruction sequence.
|
197
|
+
*/
|
198
|
+
NODE *tree_node;
|
199
|
+
} rb_iseq_t;
|
200
|
+
|
201
|
+
enum ruby_special_exceptions {
|
202
|
+
ruby_error_reenter,
|
203
|
+
ruby_error_nomemory,
|
204
|
+
ruby_error_sysstack,
|
205
|
+
ruby_special_error_count
|
206
|
+
};
|
207
|
+
|
208
|
+
typedef struct rb_vm_struct {
|
209
|
+
VALUE self;
|
210
|
+
|
211
|
+
rb_thread_lock_t global_vm_lock;
|
212
|
+
|
213
|
+
struct rb_thread_struct *main_thread;
|
214
|
+
struct rb_thread_struct *running_thread;
|
215
|
+
|
216
|
+
st_table *living_threads;
|
217
|
+
VALUE thgroup_default;
|
218
|
+
|
219
|
+
int running;
|
220
|
+
int thread_abort_on_exception;
|
221
|
+
unsigned long trace_flag;
|
222
|
+
volatile int sleeper;
|
223
|
+
|
224
|
+
/* object management */
|
225
|
+
VALUE mark_object_ary;
|
226
|
+
|
227
|
+
VALUE special_exceptions[ruby_special_error_count];
|
228
|
+
|
229
|
+
/* load */
|
230
|
+
VALUE top_self;
|
231
|
+
VALUE load_path;
|
232
|
+
VALUE loaded_features;
|
233
|
+
struct st_table *loading_table;
|
234
|
+
|
235
|
+
/* signal */
|
236
|
+
struct {
|
237
|
+
VALUE cmd;
|
238
|
+
int safe;
|
239
|
+
} trap_list[RUBY_NSIG];
|
240
|
+
|
241
|
+
/* hook */
|
242
|
+
rb_event_hook_t *event_hooks;
|
243
|
+
|
244
|
+
int src_encoding_index;
|
245
|
+
|
246
|
+
VALUE verbose, debug, progname;
|
247
|
+
VALUE coverages;
|
248
|
+
|
249
|
+
struct unlinked_method_entry_list_entry *unlinked_method_entry_list;
|
250
|
+
|
251
|
+
#if defined(ENABLE_VM_OBJSPACE) && ENABLE_VM_OBJSPACE
|
252
|
+
struct rb_objspace *objspace;
|
253
|
+
#endif
|
254
|
+
} rb_vm_t;
|
255
|
+
|
256
|
+
#include "method_mini.h"
|
257
|
+
|
258
|
+
typedef struct {
|
259
|
+
VALUE *pc; /* cfp[0] */
|
260
|
+
VALUE *sp; /* cfp[1] */
|
261
|
+
VALUE *bp; /* cfp[2] */
|
262
|
+
rb_iseq_t *iseq; /* cfp[3] */
|
263
|
+
VALUE flag; /* cfp[4] */
|
264
|
+
VALUE self; /* cfp[5] / block[0] */
|
265
|
+
VALUE *lfp; /* cfp[6] / block[1] */
|
266
|
+
VALUE *dfp; /* cfp[7] / block[2] */
|
267
|
+
rb_iseq_t *block_iseq; /* cfp[8] / block[3] */
|
268
|
+
VALUE proc; /* cfp[9] / block[4] */
|
269
|
+
const rb_method_entry_t *me;/* cfp[10] */
|
270
|
+
short int tracing; /* Bits to control per-frame event tracing.
|
271
|
+
See VM_FRAME_TRACE_xxx defines.
|
272
|
+
*/
|
273
|
+
} rb_control_frame_t;
|
274
|
+
|
275
|
+
typedef struct rb_block_struct {
|
276
|
+
VALUE self; /* share with method frame if it's only block */
|
277
|
+
VALUE *lfp; /* share with method frame if it's only block */
|
278
|
+
VALUE *dfp; /* share with method frame if it's only block */
|
279
|
+
rb_iseq_t *iseq;
|
280
|
+
VALUE proc;
|
281
|
+
} rb_block_t;
|
282
|
+
|
283
|
+
#define GetThreadPtr(obj, ptr) \
|
284
|
+
GetCoreDataFromValue(obj, rb_thread_t, ptr)
|
285
|
+
|
286
|
+
#define GetProcPtr(obj, ptr) \
|
287
|
+
GetCoreDataFromValue(obj, rb_proc_t, ptr)
|
288
|
+
|
289
|
+
typedef struct rb_thread_struct
|
290
|
+
{
|
291
|
+
VALUE self;
|
292
|
+
rb_vm_t *vm;
|
293
|
+
|
294
|
+
/* execution information */
|
295
|
+
VALUE *stack; /* must free, must mark. rb: seems to be nil. */
|
296
|
+
unsigned long stack_size; /* Number of stack (or rb_control_frame_t) entries */
|
297
|
+
rb_control_frame_t *cfp;
|
298
|
+
|
299
|
+
int safe_level;
|
300
|
+
int raised_flag;
|
301
|
+
VALUE last_status; /* $? */
|
302
|
+
|
303
|
+
/* passing state */
|
304
|
+
int state;
|
305
|
+
|
306
|
+
/* tracer */
|
307
|
+
rb_event_hook_t *event_hooks;
|
308
|
+
rb_event_flag_t event_flags;
|
309
|
+
int tracing; /* 0 if not tracing. If less than 0, skip that many
|
310
|
+
C call/return pairs */
|
311
|
+
int exec_event_tracing; /* 0 if not in rb_threadptr_evec_event_hooks. */
|
312
|
+
int trace_skip_insn_count; /* # of VM instructions to skip */
|
313
|
+
|
314
|
+
/* misc */
|
315
|
+
int method_missing_reason;
|
316
|
+
int abort_on_exception;
|
317
|
+
|
318
|
+
/* for rb_iterate */
|
319
|
+
const rb_block_t *passed_block;
|
320
|
+
|
321
|
+
/* for bmethod */
|
322
|
+
const rb_method_entry_t *passed_me;
|
323
|
+
|
324
|
+
/* for load(true) */
|
325
|
+
VALUE top_self;
|
326
|
+
VALUE top_wrapper;
|
327
|
+
|
328
|
+
/* eval env */
|
329
|
+
rb_block_t *base_block;
|
330
|
+
|
331
|
+
VALUE *local_lfp;
|
332
|
+
VALUE local_svar;
|
333
|
+
|
334
|
+
/* Lot's of other stuff ...
|
335
|
+
thread control ... */
|
336
|
+
} rb_thread_t;
|
337
|
+
|
338
|
+
typedef struct {
|
339
|
+
rb_block_t block;
|
340
|
+
|
341
|
+
VALUE envval; /* for GC mark */
|
342
|
+
VALUE blockprocval;
|
343
|
+
int safe_level;
|
344
|
+
int is_from_method;
|
345
|
+
int is_lambda;
|
346
|
+
} rb_proc_t;
|
347
|
+
|
348
|
+
#define GetEnvPtr(obj, ptr) \
|
349
|
+
GetCoreDataFromValue(obj, rb_env_t, ptr)
|
350
|
+
|
351
|
+
typedef struct {
|
352
|
+
VALUE *env;
|
353
|
+
int env_size;
|
354
|
+
int local_size;
|
355
|
+
VALUE prev_envval; /* for GC mark */
|
356
|
+
rb_block_t block;
|
357
|
+
} rb_env_t;
|
358
|
+
|
359
|
+
#define GetBindingPtr(obj, ptr) \
|
360
|
+
GetCoreDataFromValue(obj, rb_binding_t, ptr)
|
361
|
+
|
362
|
+
typedef struct {
|
363
|
+
VALUE env;
|
364
|
+
VALUE filename;
|
365
|
+
unsigned short line_no;
|
366
|
+
} rb_binding_t;
|
367
|
+
|
368
|
+
#define GET_THREAD() ruby_current_thread
|
369
|
+
extern rb_thread_t *ruby_current_thread;
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../../ext/parse_tree'
|
3
|
+
|
4
|
+
def five; 5 end
|
5
|
+
|
6
|
+
class TestParseTree < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
@processor = ParseTree19.new(false)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_parse_tree_for_method
|
12
|
+
|
13
|
+
def six
|
14
|
+
x = 2
|
15
|
+
y = 3
|
16
|
+
return x * y
|
17
|
+
end
|
18
|
+
|
19
|
+
[
|
20
|
+
[:five,
|
21
|
+
[:scope, [:args, 0, [:args_aux]], [:lit, 5]]],
|
22
|
+
|
23
|
+
[:six,
|
24
|
+
[:scope, [:args, 0, [:args_aux]],
|
25
|
+
[:block, [:lasgn, :x, [:lit, 2]],
|
26
|
+
[:block, [:lasgn, :y, [:lit, 3]],
|
27
|
+
[:block, [:call, :*, [:lvar, :x], [:array, 1, [:lvar, :y]]]]]]]]
|
28
|
+
].each do |meth, expected|
|
29
|
+
actual = @processor.parse_tree_for_method(method(meth), true)
|
30
|
+
assert_equal expected, actual
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../../ext/parse_tree'
|
3
|
+
|
4
|
+
class TestParseTree < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@processor = ParseTree19.new(false)
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_parse_tree_for_str
|
10
|
+
# The order of the ops below is the order they appear in
|
11
|
+
# add_to_parse_tree.inc/node.c
|
12
|
+
# Note: if you ever wanted have a Ruby expression that causes
|
13
|
+
# a given parse node to be created, see below.
|
14
|
+
[
|
15
|
+
# block:
|
16
|
+
['foo; bar', [:scope, [:block, [:vcall, :foo],
|
17
|
+
[:block, [:vcall, :bar]]]]],
|
18
|
+
|
19
|
+
# if:
|
20
|
+
['true if nil', [:scope, [:if, [:nil], [:true]]]],
|
21
|
+
['if nil then true else false end',
|
22
|
+
[:scope, [:if, [:nil], [:true], [:false]]]],
|
23
|
+
|
24
|
+
# Need case, when, opt_n
|
25
|
+
|
26
|
+
['5 while false', [:scope, [:while, [:false], [:lit, 5]]]],
|
27
|
+
['4 until true', [:scope, [:until, [:true], [:lit, 4]]]],
|
28
|
+
|
29
|
+
# iter:
|
30
|
+
['x { 5 }',
|
31
|
+
[:scope, [:iter, [:fcall, :x], [:scope, [:lit, 5]]]]],
|
32
|
+
|
33
|
+
# Need for
|
34
|
+
|
35
|
+
['break', [:scope, [:break]]],
|
36
|
+
['break 1', [:scope, [:break, [:lit, 1]]]],
|
37
|
+
['next', [:scope, [:next]]],
|
38
|
+
['next 1', [:scope, [:next, [:lit, 1]]]],
|
39
|
+
['return', [:scope, [:return]]],
|
40
|
+
['return 4', [:scope, [:return, [:lit, 4]]]],
|
41
|
+
|
42
|
+
['redo', [:scope, [:redo]]],
|
43
|
+
['retry', [:scope, [:retry]]],
|
44
|
+
|
45
|
+
# begin
|
46
|
+
['begin; 1 ; end',
|
47
|
+
[:scope, [:block, [:begin], [:block, [:lit, 1]]]]],
|
48
|
+
|
49
|
+
# rescue and resbody
|
50
|
+
['begin; 1 ; rescue; 2; else 3; end',
|
51
|
+
[:scope, [:rescue, [:block, [:begin], [:block, [:lit, 1]]],
|
52
|
+
[:resbody, [:lit, 2]], [:lit, 3]]]],
|
53
|
+
|
54
|
+
# ensure
|
55
|
+
['begin; 1 ; ensure; 2; end',
|
56
|
+
[:scope, [:ensure, [:block, [:begin], [:block, [:lit, 1]]],
|
57
|
+
[:block, [:begin], [:block, [:lit, 2]]]]]],
|
58
|
+
|
59
|
+
# and
|
60
|
+
['true and nil', [:scope, [:and, [:true], [:nil]]]],
|
61
|
+
# or
|
62
|
+
['true or false', [:scope, [:or, [:true], [:false]]]],
|
63
|
+
|
64
|
+
# lasgn
|
65
|
+
['x = 5', [:scope, [:lasgn, :x, [:lit, 5]]]],
|
66
|
+
# dasgn:
|
67
|
+
['x = nil; 1.times { x = 5 }',
|
68
|
+
[:scope, [:block, [:lasgn, :x, [:nil]],
|
69
|
+
[:block, [:iter, [:call, :times, [:lit, 1]],
|
70
|
+
[:scope, [:dasgn, :x, [:lit, 5]]]]]]]],
|
71
|
+
# dasgn_cur:
|
72
|
+
['1.times { x = 5 }',
|
73
|
+
[:scope, [:iter, [:call, :times, [:lit, 1]],
|
74
|
+
[:scope, [:dasgn_curr, :x, [:lit, 5]]]]]],
|
75
|
+
|
76
|
+
['@x = 5', [:scope, [:iasgn, :@x, [:lit, 5]]]],
|
77
|
+
['@@x = 5', [:scope, [:cvasgn, :@@x, [:lit, 5]]]],
|
78
|
+
|
79
|
+
['$x = 5', [:scope, [:gasgn, :$x, [:lit, 5]]]],
|
80
|
+
|
81
|
+
['x &&= 1', [:scope, [:op_asgn_and,
|
82
|
+
[:lvar, :x], [:lasgn, :x, [:lit, 1]]]]],
|
83
|
+
['x ||= 1', [:scope, [:op_asgn_or,
|
84
|
+
[:lvar, :x], [:lasgn, :x, [:lit, 1]]]]],
|
85
|
+
|
86
|
+
# op_asgn1
|
87
|
+
# 'ary[1] += 2'
|
88
|
+
|
89
|
+
# call:
|
90
|
+
['x.foo', [:scope, [:call, :foo, [:vcall, :x]]]],
|
91
|
+
|
92
|
+
# For fcall, see iter above.
|
93
|
+
|
94
|
+
['foo', [:scope, [:vcall, :foo]]],
|
95
|
+
|
96
|
+
['super', [:scope, [:zsuper]]],
|
97
|
+
|
98
|
+
# array
|
99
|
+
['[1]', [:scope, [:array, 1, [:lit, 1]]]],
|
100
|
+
|
101
|
+
# values array 1st item is not predictable.
|
102
|
+
|
103
|
+
# zarray
|
104
|
+
['[]', [:scope, [:zarray]]],
|
105
|
+
|
106
|
+
# hash
|
107
|
+
['{}', [:scope, [:hash]]],
|
108
|
+
|
109
|
+
['yield', [:scope, [:yield]]],
|
110
|
+
|
111
|
+
# For lvar, see x ||= 1
|
112
|
+
|
113
|
+
# dvar:
|
114
|
+
['1.times { x = 1; x }',
|
115
|
+
[:scope, [:iter, [:call, :times, [:lit, 1]],
|
116
|
+
[:scope, [:block, [:dasgn_curr, :x, [:lit, 1]],
|
117
|
+
[:block, [:dvar, :x]]]]]]],
|
118
|
+
|
119
|
+
['@x', [:scope, [:ivar, :@x]]],
|
120
|
+
['X', [:scope, [:const, :X]]],
|
121
|
+
['@@X', [:scope, [:cvar, :@@X]]],
|
122
|
+
['$x', [:scope, [:gvar, :$x]]],
|
123
|
+
|
124
|
+
["5", [:scope, [:lit, 5]]],
|
125
|
+
["'5'", [:scope, [:str, '5']]],
|
126
|
+
['%x(5)', [:scope, [:xstr, '5']]],
|
127
|
+
['"#{5}"', [:scope, [:dstr, nil, [:evstr, [:lit, 5]]]]],
|
128
|
+
['`#{5}`', [:scope, [:dxstr, nil, [:evstr, [:lit, 5]]]]],
|
129
|
+
['/#{5}/', [:scope, [:dregx, '', [:evstr, [:lit, 5]]]]],
|
130
|
+
['/#{5}/o', [:scope, [:dregx_once, '', [:evstr, [:lit, 5]]]]],
|
131
|
+
[':"#{5}"', [:scope, [:dsym, nil, [:evstr, [:lit, 5]]]]],
|
132
|
+
|
133
|
+
['alias a b', [:scope, [:alias, [:lit, :a], [:lit, :b]]]],
|
134
|
+
['alias $a $b', [:scope, [:valias, :$a, :$b]]],
|
135
|
+
|
136
|
+
['undef foo', [:scope, [:undef, [:lit, :foo]]]],
|
137
|
+
|
138
|
+
# dot2
|
139
|
+
['1..5.each{ 5 }',
|
140
|
+
[:scope, [:dot2, [:lit, 1],
|
141
|
+
[:iter, [:call, :each, [:lit, 5]], [:scope, [:lit, 5]]]]]],
|
142
|
+
# dot3
|
143
|
+
['1...5.each{ 5 }',
|
144
|
+
[:scope, [:dot3, [:lit, 1],
|
145
|
+
[:iter, [:call, :each, [:lit, 5]], [:scope, [:lit, 5]]]]]],
|
146
|
+
|
147
|
+
# Need flip2 and flip3
|
148
|
+
|
149
|
+
['self', [:scope, [:self]]],
|
150
|
+
['nil', [:scope, [:nil]]],
|
151
|
+
['true', [:scope, [:true]]],
|
152
|
+
['false', [:scope, [:false]]],
|
153
|
+
|
154
|
+
['M::Foo', [:scope, [:colon2, :Foo, [:const, :M]]]],
|
155
|
+
['::Foo', [:scope, [:colon3, :Foo]]],
|
156
|
+
['defined?(5)', [:scope, [:defined, [:lit, 5]]]],
|
157
|
+
].each do |test_str, expected|
|
158
|
+
actual = @processor.parse_tree_for_str test_str, '(string)', 1
|
159
|
+
assert_equal expected, actual
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: parsetree19
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
version: "0.2"
|
9
|
+
platform: ruby
|
10
|
+
authors:
|
11
|
+
- R. Bernstein
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
|
16
|
+
date: 2010-12-25 00:00:00 -05:00
|
17
|
+
default_executable:
|
18
|
+
dependencies: []
|
19
|
+
|
20
|
+
description: "\n\
|
21
|
+
rb-parsetree is the C extension part of ParseTree for Ruby 1.9.\n"
|
22
|
+
email: rockyb@rubyforge.org
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions:
|
26
|
+
- ext/extconf.rb
|
27
|
+
extra_rdoc_files:
|
28
|
+
- README.md
|
29
|
+
- ext/parse_tree.c
|
30
|
+
files:
|
31
|
+
- README.md
|
32
|
+
- Rakefile
|
33
|
+
- NEWS
|
34
|
+
- ChangeLog
|
35
|
+
- include/thread_pthread.h
|
36
|
+
- include/node.h
|
37
|
+
- include/method_mini.h
|
38
|
+
- include/ruby19_externs.h
|
39
|
+
- include/vm_core_mini.h
|
40
|
+
- ext/parse_tree.c
|
41
|
+
- ext/add_to_parse_tree.inc
|
42
|
+
- test/unit/test_parse_tree_for_str.rb
|
43
|
+
- test/unit/test_parse_tree_for_meth.rb
|
44
|
+
- ext/extconf.rb
|
45
|
+
has_rdoc: true
|
46
|
+
homepage: http://github.com/rocky/rb-parsetree19/tree/master
|
47
|
+
licenses: []
|
48
|
+
|
49
|
+
post_install_message:
|
50
|
+
rdoc_options: []
|
51
|
+
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
segments:
|
60
|
+
- 1
|
61
|
+
- 9
|
62
|
+
- 2frame
|
63
|
+
version: 1.9.2frame
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - ">="
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
segments:
|
70
|
+
- 0
|
71
|
+
version: "0"
|
72
|
+
requirements: []
|
73
|
+
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.3.7
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: Frame introspection
|
79
|
+
test_files: []
|
80
|
+
|