|
Ruby
1.9.3p537(2014-02-19revision0)
|
00001 #include "ruby/ruby.h" 00002 00003 #include "vm_core.h" 00004 #include "node.h" 00005 00006 #include "node_attr_map.inc" 00007 00008 #include <ctype.h> 00009 00010 static VALUE rb_cNode; 00011 00012 static void 00013 rnode_mark(NODE * node) 00014 { 00015 rb_gc_mark((VALUE)node); 00016 } 00017 00018 static VALUE 00019 node_to_rnode(NODE * node) 00020 { 00021 if (node) return Data_Wrap_Struct(rb_cNode, rnode_mark, 0, node); 00022 else return Qnil; 00023 } 00024 00025 static VALUE 00026 node_type_to_sym(int node) 00027 { 00028 char *node_name = strdup(ruby_node_name(node)); 00029 int i; 00030 VALUE sym; 00031 00032 for(i=0; i < strlen(node_name); i++) 00033 node_name[i] = tolower(node_name[i]); 00034 00035 sym = ID2SYM(rb_intern(node_name + sizeof("NODE_") - 1)); 00036 free(node_name); 00037 return sym; 00038 } 00039 00040 static VALUE 00041 rnode_type(VALUE self) 00042 { 00043 NODE * node; 00044 Data_Get_Struct(self, NODE, node); 00045 return node_type_to_sym(nd_type(node)); 00046 } 00047 00048 static VALUE 00049 rnode_flags(VALUE self) 00050 { 00051 NODE * node; 00052 Data_Get_Struct(self, NODE, node); 00053 return ULONG2NUM(node->flags); 00054 } 00055 00056 static VALUE 00057 rnode_reserved(VALUE self) 00058 { 00059 return Qnil; 00060 } 00061 00062 static VALUE 00063 rnode_line(VALUE self) 00064 { 00065 NODE * node; 00066 Data_Get_Struct(self, NODE, node); 00067 return UINT2NUM(nd_line(node)); 00068 } 00069 00070 static VALUE 00071 id_to_value(ID id) 00072 { 00073 /* some node types store non-ids in an id */ 00074 if (id == 0 || id == 1) return INT2FIX(id); 00075 else if (rb_id2name(id)) return ID2SYM(id); 00076 else return Qnil; 00077 } 00078 00079 static VALUE 00080 node_attr_is_value(enum node_type nd_type, int union_idx) 00081 { 00082 switch(nd_type) 00083 { 00084 #include "node_attr_is_value.inc" 00085 default: 00086 return Qfalse; 00087 } 00088 return Qfalse; 00089 } 00090 00091 00092 static VALUE 00093 value_or_node_to_value(VALUE val, enum node_type nd_type, int union_idx, NODE * node) 00094 { 00095 if (!node_attr_is_value(nd_type, union_idx)) { 00096 /* handle node types that are not handled by 00097 * node_type_attrib_is_value (which is generated 00098 * from gc_mark_children in gc.c) 00099 * 00100 * NODE_ALLOCA is not supported 00101 */ 00102 switch(nd_type) { 00103 case NODE_ARGSCAT: 00104 case NODE_ARGSPUSH: 00105 /* nd_head, nd_body */ 00106 if (union_idx == ND_HEAD_UIDX || union_idx == ND_BODY_UIDX) break; 00107 else return Qnil; 00108 case NODE_ATTRASGN: 00109 /* nd_recv, nd_args */ 00110 if (union_idx == ND_RECV_UIDX || union_idx == ND_ARGS_UIDX) break; 00111 else return Qnil; 00112 case NODE_BEGIN: 00113 /* nd_body */ 00114 if (union_idx == ND_BODY_UIDX) break; 00115 else return Qnil; 00116 case NODE_BMETHOD: 00117 /* nd_cval */ 00118 if (union_idx == ND_CVAL_UIDX) break; 00119 else return Qnil; 00120 case NODE_DSYM: 00121 /* nd_lit, nd_next */ 00122 if (union_idx == ND_LIT_UIDX || union_idx == ND_NEXT_UIDX) break; 00123 else return Qnil; 00124 case NODE_IFUNC: 00125 /* nd_tval */ 00126 if (union_idx == ND_TVAL_UIDX) break; 00127 else return Qnil; 00128 case NODE_LAMBDA: 00129 /* nd_var, nd_body */ 00130 if (union_idx == ND_VAR_UIDX || union_idx == ND_BODY_UIDX) break; 00131 else return Qnil; 00132 case NODE_MEMO: 00133 /* enum.c: u1.value, u2.value 00134 * variabe.c: u1.value (nd_lit), u2.argc (nd_nth) 00135 * eval.c: u1.value 00136 */ 00137 if (union_idx == 1) break; 00138 else return Qnil; 00139 case NODE_OP_ASGN2: 00140 /* either 3 ids: nd_vid, nd_mid, nd_aid (actually nd_mid might be 0 or 1 instead of an id) 00141 * or 3 values: nd_recv, nd_value, nd_next 00142 */ 00143 if (rb_id2name(node->nd_vid) && id_to_value(node->nd_mid) != Qnil && rb_id2name(node->nd_aid)) 00144 return Qnil; 00145 else break; 00146 case NODE_PRELUDE: 00147 /* nd_head, nd_body */ 00148 if (union_idx == ND_HEAD_UIDX || union_idx == ND_BODY_UIDX) break; 00149 else return Qnil; 00150 case NODE_VALUES: 00151 /* nd_head, nd_next */ 00152 if (union_idx == ND_HEAD_UIDX || union_idx == ND_NEXT_UIDX) break; 00153 else return Qnil; 00154 case NODE_CONST: 00155 /* fall through */ 00156 case NODE_LAST: 00157 /* fall through */ 00158 default: 00159 return Qnil; 00160 } 00161 } 00162 if (TYPE(val) == T_NODE) return node_to_rnode((NODE *)val); 00163 else return val; 00164 } 00165 00166 static VALUE 00167 rnode_u1_value_or_node(VALUE self) 00168 { 00169 NODE * node; 00170 Data_Get_Struct(self, NODE, node); 00171 return value_or_node_to_value(node->u1.value, nd_type(node), 1, node); 00172 } 00173 00174 static VALUE 00175 rnode_u2_value_or_node(VALUE self) 00176 { 00177 NODE * node; 00178 Data_Get_Struct(self, NODE, node); 00179 return value_or_node_to_value(node->u2.value, nd_type(node), 2, node); 00180 } 00181 00182 static VALUE 00183 rnode_u3_value_or_node(VALUE self) 00184 { 00185 NODE * node; 00186 Data_Get_Struct(self, NODE, node); 00187 return value_or_node_to_value(node->u3.value, nd_type(node), 3, node); 00188 } 00189 00190 static VALUE 00191 rnode_u1_id(VALUE self) 00192 { 00193 NODE * node; 00194 Data_Get_Struct(self, NODE, node); 00195 return id_to_value(node->u1.id); 00196 } 00197 00198 static VALUE 00199 rnode_u2_id(VALUE self) 00200 { 00201 NODE * node; 00202 Data_Get_Struct(self, NODE, node); 00203 return id_to_value(node->u2.id); 00204 } 00205 00206 static VALUE 00207 rnode_u3_id(VALUE self) 00208 { 00209 NODE * node; 00210 Data_Get_Struct(self, NODE, node); 00211 return id_to_value(node->u3.id); 00212 } 00213 00214 static VALUE 00215 rnode_u1_as_long(VALUE self) 00216 { 00217 NODE * node; 00218 Data_Get_Struct(self, NODE, node); 00219 return LONG2NUM((long)(node->u1.id)); 00220 } 00221 00222 static VALUE 00223 rnode_u1_cfunc(VALUE self) 00224 { 00225 NODE * node; 00226 Data_Get_Struct(self, NODE, node); 00227 return ULONG2NUM((unsigned long)(node->u1.cfunc)); 00228 } 00229 00230 static VALUE 00231 rnode_u2_argc(VALUE self) 00232 { 00233 NODE * node; 00234 Data_Get_Struct(self, NODE, node); 00235 return LONG2NUM(node->u2.argc); 00236 } 00237 00238 static VALUE 00239 rnode_u3_state_or_cnt(VALUE self) 00240 { 00241 NODE * node; 00242 Data_Get_Struct(self, NODE, node); 00243 return LONG2NUM(node->u3.state); 00244 } 00245 00246 static VALUE 00247 rnode_u1_tbl(VALUE self) 00248 { 00249 NODE * node; 00250 Data_Get_Struct(self, NODE, node); 00251 /* only allowed for SCOPE */ 00252 if (nd_type(node) == NODE_SCOPE) { 00253 ID * tbl = node->u1.tbl; 00254 if (tbl) { 00255 size_t i; 00256 VALUE arr = rb_ary_new(); 00257 /* tbl contains the names of local variables. The first 00258 * element is the size of the table. The next two elements 00259 * are $_ and $~. The rest of the elements are the names of 00260 * the variables themselves. 00261 */ 00262 for (i = 3; i <= tbl[0]; ++i) { 00263 if (tbl[i] == 0 || !rb_is_local_id(tbl[i])) 00264 /* flip state */ 00265 rb_ary_push(arr, Qnil); 00266 else 00267 rb_ary_push(arr, ID2SYM(tbl[i])); 00268 } 00269 return arr; 00270 } 00271 } 00272 return Qnil; 00273 } 00274 00275 00276 #if 0 00277 /**************************************************************** 00278 * methods to extract nodes 00279 ****************************************************************/ 00280 00281 static VALUE method_body(VALUE method) { 00282 struct METHOD * m; 00283 Data_Get_Struct(method, struct METHOD, m); 00284 return node_to_rnode(m->body); 00285 } 00286 00287 static VALUE proc_body(VALUE proc) { 00288 struct BLOCK * b; 00289 Data_Get_Struct(proc, struct BLOCK, b); 00290 return node_to_rnode(b->body); 00291 } 00292 00293 static VALUE proc_var(VALUE proc) { 00294 struct BLOCK * b; 00295 Data_Get_Struct(proc, struct BLOCK, b); 00296 return node_to_rnode(b->var); 00297 } 00298 00299 static VALUE proc_cref(VALUE proc) { 00300 struct BLOCK * b; 00301 Data_Get_Struct(proc, struct BLOCK, b); 00302 return node_to_rnode(b->cref); 00303 } 00304 #endif 00305 00306 #if 0 00307 extern NODE * ruby_eval_tree_begin; 00308 #endif 00309 00310 /* 00311 * Parse a string to nodes (the parsing is done in the current context). 00312 * 00313 * Takes file_name and line as optional arguments. They default to "(string)" 00314 * and 1 00315 */ 00316 00317 static NODE * 00318 str_parse(int argc, VALUE *argv, VALUE src) 00319 { 00320 NODE * node; 00321 //int critical; 00322 VALUE file_name, line; 00323 00324 rb_scan_args(argc, argv, "02", &file_name, &line); 00325 if (argc < 1) file_name = rb_str_new2("(string)"); 00326 if (argc < 2) line = LONG2FIX(1); 00327 00328 // ruby_nerrs = 0; 00329 StringValue(src); 00330 // critical = rb_thread_critical; 00331 // rb_thread_critical = Qtrue; 00332 // ruby_in_eval++; 00333 node = rb_compile_string(StringValuePtr(file_name), src, NUM2INT(line)); 00334 // ruby_in_eval--; 00335 // rb_thread_critical = critical; 00336 #if 0 00337 if (ruby_nerrs > 0) { 00338 ruby_nerrs = 0; 00339 #if RUBY_VERSION_CODE < 190 00340 ruby_eval_tree_begin = 0; 00341 #endif 00342 rb_exc_raise(ruby_errinfo); 00343 } 00344 #endif 00345 return node; 00346 } 00347 00348 static VALUE 00349 str_parse_to_nodes(int argc, VALUE *argv, VALUE src) 00350 { 00351 VALUE result; 00352 00353 result = node_to_rnode(str_parse(argc, argv, src)); 00354 00355 #if 0 00356 ruby_eval_tree_begin = 0; 00357 #endif 00358 00359 return result; 00360 } 00361 00362 void 00363 Init_Node() 00364 { 00365 rb_cNode = rb_define_class_under(rb_cRubyVM, "Node", rb_cObject); 00366 00367 rb_undef_alloc_func(rb_cNode); 00368 rb_undef_method(CLASS_OF(rb_cNode), "new"); 00369 00370 rb_define_method(rb_cNode, "type", rnode_type, 0); 00371 rb_define_method(rb_cNode, "flags", rnode_flags, 0); 00372 rb_define_method(rb_cNode, "reserved", rnode_reserved, 0); 00373 rb_define_method(rb_cNode, "line", rnode_line, 0); 00374 00375 rb_define_method(rb_cNode, "u1_value", rnode_u1_value_or_node, 0); 00376 rb_define_method(rb_cNode, "u2_value", rnode_u2_value_or_node, 0); 00377 rb_define_method(rb_cNode, "u3_value", rnode_u3_value_or_node, 0); 00378 rb_define_method(rb_cNode, "u1_node", rnode_u1_value_or_node, 0); 00379 rb_define_method(rb_cNode, "u2_node", rnode_u2_value_or_node, 0); 00380 rb_define_method(rb_cNode, "u3_node", rnode_u3_value_or_node, 0); 00381 rb_define_method(rb_cNode, "u1_id", rnode_u1_id, 0); 00382 rb_define_method(rb_cNode, "u2_id", rnode_u2_id, 0); 00383 rb_define_method(rb_cNode, "u3_id", rnode_u3_id, 0); 00384 rb_define_method(rb_cNode, "u1_as_long", rnode_u1_as_long, 0); 00385 rb_define_method(rb_cNode, "u1_cfunc", rnode_u1_cfunc, 0); 00386 rb_define_method(rb_cNode, "u2_argc", rnode_u2_argc, 0); 00387 rb_define_method(rb_cNode, "u3_state", rnode_u3_state_or_cnt, 0); 00388 rb_define_method(rb_cNode, "u3_cnt", rnode_u3_state_or_cnt, 0); 00389 rb_define_method(rb_cNode, "u1_tbl", rnode_u1_tbl, 0); 00390 00391 #include "node_nd_attr.inc" 00392 00393 #if 0 00394 rb_define_method(rb_define_class("Method", rb_cObject), "body_node", method_body, 0); 00395 rb_define_method(rb_define_class("UnboundMethod", rb_cObject), "body_node", method_body, 0); 00396 00397 rb_define_method(rb_cProc, "body_node", proc_body, 0); 00398 rb_define_method(rb_cProc, "var_node", proc_var, 0); 00399 rb_define_method(rb_cProc, "cref_node", proc_cref, 0); 00400 #endif 00401 00402 rb_define_method(rb_cString, "parse_to_nodes", str_parse_to_nodes, -1); 00403 } 00404
1.7.6.1