parsetree19 0.2

Sign up to get free protection for your applications and to get access to all the features.
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 */