Ruby  1.9.3p537(2014-02-19revision0)
rubynode.c
Go to the documentation of this file.
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