# Standards

Blogged by Ujihisa. Standard methods of programming and thoughts including Clojure, Vim, LLVM, Haskell, Ruby and Mathematics written by a Japanese programmer. github/ujihisa

## Tuesday, May 12, 2009

### Cryptic infinite recursion in parse.y

When a single quote comes, parse.y will do:

``````case '\'':
lex_strterm = NEW_STRTERM(str_squote, '\'', 0);
return tSTRING_BEG;
``````

This piece of codes is very same as a part of :'aaa'

`NEW_STRTERM` is a macro. It is a wrapper of a macro `rb_node_newnode`, which is a wrapper of a function `node_newnode`

``````#define NEW_STRTERM(func, term, paren) \
rb_node_newnode(NODE_STRTERM, (func), (term) | ((paren) << (CHAR_BIT * 2)), 0)

#define rb_node_newnode(type, a1, a2, a3) node_newnode(parser, type, a1, a2, a3)

static NODE*
node_newnode(struct parser_params *parser, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
{
NODE *n = (rb_node_newnode)(type, a0, a1, a2);
nd_set_line(n, ruby_sourceline);
return n;
}
``````

The last function `node_newnode` calls `rb_node_newnode`, that is `node_newnode` itself, recursively.

Here is the `node_newnode` which macro is expanded:

``````static NODE*
node_newnode(struct parser_params *parser, enum node_type type, VALUE a0, VALUE a1, VALUE a2)
{
NODE *n = node_newnode(parser, type, a0, a1, a2);
nd_set_line(n, ruby_sourceline);
return n;
}
``````

It's mysterious. `node_newnode` seems infinite recursion without any terminate conditions. Why does it work?

1. A function type macro is not expanded in this case.
I think it is a normal function call.
The function rb_node_newnode is defined in node.h.

2. Thank you! I rak'd rb_node_newnode to find where is the definition. The perpetrator is gc.c!

NODE*
rb_node_newnode(enum node_type type, VALUE a0, VALUE a1, VALUE a2)
{
NODE *n = (NODE*)rb_newobj();

n->flags |= T_NODE;
nd_set_type(n, type);

n->u1.value = a0;
n->u2.value = a1;
n->u3.value = a2;

return n;
}