parsetree19 0.2

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.
data/ext/extconf.rb ADDED
@@ -0,0 +1,8 @@
1
+ require "mkmf"
2
+
3
+ config_file = File.join(File.dirname(__FILE__), 'config_options')
4
+ load config_file if File.exist?(config_file)
5
+
6
+ # Temporary: to turn off optimization
7
+ # $CFLAGS='-fno-strict-aliasing -g -fPIC'
8
+ create_makefile("parse_tree")
data/ext/parse_tree.c ADDED
@@ -0,0 +1,149 @@
1
+ /* What release we got? */
2
+ #define PARSETREE19_VERSION "0.2"
3
+ #include "../include/vm_core_mini.h" /* Pulls in ruby.h and node.h */
4
+ #include "../include/ruby19_externs.h"
5
+
6
+ /* Turn a Ruby node string, e.g. "NODE_FALSE" into a symbol that ParseTree
7
+ uses, e.g. :false. */
8
+ static VALUE
9
+ pt_node_name(const char *name)
10
+ {
11
+ if (0 == strncmp(name, "NODE_", strlen("NODE_"))) {
12
+ const char * name_sans_node = &name[strlen("NODE_")];
13
+ return
14
+ rb_funcall(
15
+ rb_funcall(rb_str_new2(name_sans_node), rb_intern("downcase"),
16
+ 0),
17
+ rb_intern("to_sym"), 0);
18
+ } else {
19
+ rb_bug("pt_node_name: node %s name should start with NODE_", name);
20
+ return Qnil;
21
+ }
22
+ }
23
+
24
+ static VALUE
25
+ wrap_into_node(const char * name, VALUE val)
26
+ {
27
+ VALUE n = rb_ary_new();
28
+ rb_ary_push(n, pt_node_name(name));
29
+ if (val) rb_ary_push(n, val);
30
+ return n;
31
+ }
32
+
33
+ #include "add_to_parse_tree.inc"
34
+
35
+ static VALUE
36
+ parse_tree_for_node(VALUE self, NODE *node, VALUE tree)
37
+ {
38
+ VALUE result = rb_ary_new();
39
+
40
+ if (Qfalse == tree)
41
+ result = rb_parser_dump_tree(node, 0);
42
+ else
43
+ result = add_to_parse_tree(self, result, node, NULL);
44
+ return (result);
45
+ }
46
+
47
+ static VALUE
48
+ parse_tree_for_iseq_internal(VALUE self, rb_iseq_t *iseq, VALUE tree)
49
+ {
50
+ VALUE result = rb_ary_new();
51
+
52
+ if (iseq->tree_node) {
53
+ if (Qfalse == tree)
54
+ result = rb_parser_dump_tree(iseq->tree_node, 0);
55
+ else
56
+ result = add_to_parse_tree(self, result, iseq->tree_node, NULL);
57
+ return (result);
58
+ } else
59
+ return Qnil;
60
+ }
61
+
62
+ static VALUE
63
+ parse_tree_for_iseq(VALUE self, VALUE iseqval, VALUE tree)
64
+ {
65
+ rb_iseq_t *iseq;
66
+ VALUE result = rb_ary_new();
67
+
68
+ GetISeqPtr(iseqval, iseq);
69
+ parse_tree_for_iseq_internal(self, iseq, tree);
70
+ }
71
+
72
+ /* Defined in Ruby 1.9 proc.c */
73
+ extern rb_iseq_t *rb_method_get_iseq(VALUE method);
74
+
75
+ static VALUE
76
+ parse_tree_for_method(VALUE self, VALUE method, VALUE tree)
77
+ {
78
+ rb_iseq_t *iseq = rb_method_get_iseq(method);
79
+ parse_tree_for_iseq_internal(self, iseq, tree);
80
+ }
81
+
82
+ static VALUE
83
+ parse_tree_common(VALUE self, VALUE source, VALUE filename, VALUE line,
84
+ VALUE tree)
85
+ {
86
+ VALUE tmp;
87
+ VALUE result = rb_ary_new();
88
+ NODE *node = NULL;
89
+
90
+ #ifdef FIXED
91
+ rb_thread_t *th = GET_THREAD();
92
+ int critical;
93
+ #endif
94
+
95
+ tmp = rb_check_string_type(filename);
96
+ if (NIL_P(tmp)) {
97
+ filename = rb_str_new2("(string)");
98
+ }
99
+
100
+ if (NIL_P(line)) {
101
+ line = LONG2FIX(1);
102
+ }
103
+
104
+ #ifdef FIXED
105
+ ruby_nerrs = 0;
106
+ critical = rb_thread_critical;
107
+ rb_thread_critical = Qtrue;
108
+ th->parse_in_eval++;
109
+ #endif
110
+
111
+ StringValue(source);
112
+ node = rb_compile_string(StringValuePtr(filename), source, NUM2INT(line));
113
+
114
+ #ifdef FIXED
115
+ th->parse_in_eval--;
116
+ rb_thread_critical = critical;
117
+ if (ruby_nerrs > 0) {
118
+ ruby_nerrs = 0;
119
+ rb_exc_raise(th->errinfo);
120
+ }
121
+ #endif
122
+
123
+ return parse_tree_for_node(self, node, tree);
124
+ }
125
+
126
+ static VALUE
127
+ parse_tree_for_str(VALUE self, VALUE source, VALUE filename, VALUE line)
128
+ {
129
+ return parse_tree_common(self, source, filename, line, Qtrue);
130
+ }
131
+
132
+ static VALUE
133
+ parse_tree_dump(VALUE self, VALUE source, VALUE filename, VALUE line)
134
+ {
135
+ return parse_tree_common(self, source, filename, line, Qfalse);
136
+ }
137
+
138
+ void Init_parse_tree(void)
139
+ {
140
+ VALUE c = rb_define_class("ParseTree19", rb_cObject);
141
+ rb_define_method(c, "parse_tree_for_iseq",
142
+ (VALUE(*)(ANYARGS))parse_tree_for_iseq, 2);
143
+ rb_define_method(c, "parse_tree_for_method",
144
+ (VALUE(*)(ANYARGS))parse_tree_for_method, 2);
145
+ rb_define_method(c, "parse_tree_for_str",
146
+ (VALUE(*)(ANYARGS))parse_tree_for_str, 3);
147
+ rb_define_method(c, "parse_tree_dump",
148
+ (VALUE(*)(ANYARGS))parse_tree_dump, 3);
149
+ }
@@ -0,0 +1,90 @@
1
+ /**********************************************************************
2
+ From Ruby 1.9's method.h.
3
+
4
+ Copyright (C) 2009 Koichi Sasada
5
+
6
+ **********************************************************************/
7
+ #ifndef METHOD_H
8
+ #define METHOD_H
9
+
10
+ typedef enum {
11
+ NOEX_PUBLIC = 0x00,
12
+ NOEX_NOSUPER = 0x01,
13
+ NOEX_PRIVATE = 0x02,
14
+ NOEX_PROTECTED = 0x04,
15
+ NOEX_MASK = 0x06,
16
+ NOEX_BASIC = 0x08,
17
+ NOEX_UNDEF = NOEX_NOSUPER,
18
+ NOEX_MODFUNC = 0x12,
19
+ NOEX_SUPER = 0x20,
20
+ NOEX_VCALL = 0x40,
21
+ NOEX_RESPONDS = 0x80
22
+ } rb_method_flag_t;
23
+
24
+ #define NOEX_SAFE(n) ((int)((n) >> 8) & 0x0F)
25
+ #define NOEX_WITH(n, s) ((s << 8) | (n) | (ruby_running ? 0 : NOEX_BASIC))
26
+ #define NOEX_WITH_SAFE(n) NOEX_WITH(n, rb_safe_level())
27
+
28
+ /* method data type */
29
+
30
+ typedef enum {
31
+ VM_METHOD_TYPE_ISEQ,
32
+ VM_METHOD_TYPE_CFUNC,
33
+ VM_METHOD_TYPE_ATTRSET,
34
+ VM_METHOD_TYPE_IVAR,
35
+ VM_METHOD_TYPE_BMETHOD,
36
+ VM_METHOD_TYPE_ZSUPER,
37
+ VM_METHOD_TYPE_UNDEF,
38
+ VM_METHOD_TYPE_NOTIMPLEMENTED,
39
+ VM_METHOD_TYPE_OPTIMIZED, /* Kernel#send, Proc#call, etc */
40
+ VM_METHOD_TYPE_MISSING /* wrapper for method_missing(id) */
41
+ } rb_method_type_t;
42
+
43
+ typedef struct rb_method_cfunc_struct {
44
+ VALUE (*func)(ANYARGS);
45
+ int argc; /* This should probably be called "arity" since it is based
46
+ on the static prototype, not the supplied arguments
47
+ at runtime. */
48
+ int actual_argc; /* This probably should be called argc. It is the
49
+ argument count at runtime.*/
50
+ } rb_method_cfunc_t;
51
+
52
+ typedef struct rb_method_attr_struct {
53
+ ID id;
54
+ VALUE location;
55
+ } rb_method_attr_t;
56
+
57
+ /* typedef struct rb_iseq_struct rb_iseq_t; */
58
+
59
+ typedef struct rb_method_definition_struct {
60
+ rb_method_type_t type; /* method type */
61
+ ID original_id;
62
+ union {
63
+ rb_iseq_t *iseq; /* should be mark */
64
+ rb_method_cfunc_t cfunc;
65
+ rb_method_attr_t attr;
66
+ VALUE proc; /* should be mark */
67
+ enum method_optimized_type {
68
+ OPTIMIZED_METHOD_TYPE_SEND,
69
+ OPTIMIZED_METHOD_TYPE_CALL
70
+ } optimize_type;
71
+ } body;
72
+ int alias_count;
73
+ } rb_method_definition_t;
74
+
75
+ typedef struct rb_method_entry_struct {
76
+ rb_method_flag_t flag;
77
+ char mark;
78
+ rb_method_definition_t *def;
79
+ ID called_id;
80
+ VALUE klass; /* should be mark */
81
+ } rb_method_entry_t;
82
+
83
+ struct unlinked_method_entry_list_entry {
84
+ struct unlinked_method_entry_list_entry *next;
85
+ rb_method_entry_t *me;
86
+ };
87
+
88
+ #define UNDEFINED_METHOD_ENTRY_P(me) (!(me) || !(me)->def || (me)->def->type == VM_METHOD_TYPE_UNDEF)
89
+
90
+ #endif /* METHOD_H */