summaryrefslogtreecommitdiff
path: root/parse.y
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-02-03 02:23:20 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2004-02-03 02:23:20 +0000
commit3f19bbb09404aedf7dd8c653eff1ef0bd1c6e4a2 (patch)
tree35554b712c3311b6dfdc2da550ba8944f4ff12e8 /parse.y
parent05172c42117ce60275d36e515c9ad7b9511b9c22 (diff)
* parse.y (reduce_nodes): remove tail returns. [ruby-talk:90934]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@5616 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'parse.y')
-rw-r--r--parse.y92
1 files changed, 76 insertions, 16 deletions
diff --git a/parse.y b/parse.y
index 079c481db6..265450bbfe 100644
--- a/parse.y
+++ b/parse.y
@@ -119,6 +119,7 @@ static void void_stmts();
static NODE *remove_begin();
#define value_expr(node) value_expr0((node) = remove_begin(node))
#define void_expr(node) void_expr0((node) = remove_begin(node))
+static void reduce_nodes();
static NODE *block_append();
static NODE *list_append();
@@ -364,7 +365,12 @@ bodystmt : compstmt
$$ = block_append($$, $3);
}
if ($4) {
- $$ = NEW_ENSURE($$, $4);
+ if ($$) {
+ $$ = NEW_ENSURE($$, $4);
+ }
+ else {
+ $$ = block_append($4, NEW_NIL());
+ }
}
fixpos($$, $1);
}
@@ -1649,7 +1655,9 @@ primary : literal
bodystmt
kEND
{
- $$ = NEW_DEFN($2, $4, $5, NOEX_PRIVATE);
+ NODE *body = remove_begin($5);
+ reduce_nodes(&body);
+ $$ = NEW_DEFN($2, $4, body, NOEX_PRIVATE);
fixpos($$, $4);
local_pop();
in_def--;
@@ -1665,7 +1673,9 @@ primary : literal
bodystmt
kEND
{
- $$ = NEW_DEFS($2, $5, $7, $8);
+ NODE *body = remove_begin($8);
+ reduce_nodes(&body);
+ $$ = NEW_DEFS($2, $5, $7, body);
fixpos($$, $2);
local_pop();
in_single--;
@@ -4497,7 +4507,7 @@ static NODE*
block_append(head, tail)
NODE *head, *tail;
{
- NODE *end, *h = head;
+ NODE *end, *h = head, *nd;
if (tail == 0) return head;
@@ -4518,20 +4528,20 @@ block_append(head, tail)
break;
}
- if (RTEST(ruby_verbose)) {
- NODE *nd = end->nd_head;
- switch (nd_type(nd)) {
- case NODE_RETURN:
- case NODE_BREAK:
- case NODE_NEXT:
- case NODE_REDO:
- case NODE_RETRY:
+ nd = end->nd_head;
+ switch (nd_type(nd)) {
+ case NODE_RETURN:
+ case NODE_BREAK:
+ case NODE_NEXT:
+ case NODE_REDO:
+ case NODE_RETRY:
+ if (RTEST(ruby_verbose)) {
parser_warning(nd, "statement not reached");
- break;
-
- default:
- break;
}
+ break;
+
+ default:
+ break;
}
if (nd_type(tail) != NODE_BLOCK) {
@@ -5104,6 +5114,56 @@ remove_begin(node)
return node;
}
+static void
+reduce_nodes(body)
+ NODE **body;
+{
+ NODE *node = *body;
+
+#define subnodes(n1, n2) \
+ ((!node->n1) ? (node->n2 ? (body = &node->n2, 1) : 0) : \
+ (!node->n2) ? (body = &node->n1, 1) : \
+ (reduce_nodes(&node->n1), body = &node->n2, 1))
+
+ while (node) {
+ switch (nd_type(node)) {
+ end:
+ case NODE_NIL:
+ *body = 0;
+ return;
+ case NODE_RETURN:
+ *body = node = node->nd_stts;
+ continue;
+ case NODE_BEGIN:
+ *body = node = node->nd_body;
+ continue;
+ case NODE_BLOCK:
+ body = &node->nd_end->nd_head;
+ break;
+ case NODE_IF:
+ if (subnodes(nd_body, nd_else)) break;
+ return;
+ case NODE_CASE:
+ body = &node->nd_body;
+ break;
+ case NODE_WHEN:
+ if (!subnodes(nd_body, nd_next)) goto end;
+ break;
+ case NODE_ENSURE:
+ if (!subnodes(nd_head, nd_resq)) goto end;
+ break;
+ case NODE_RESCUE:
+ if (!subnodes(nd_head, nd_resq)) goto end;
+ break;
+ default:
+ return;
+ }
+ node = *body;
+ }
+
+#undef subnodes
+}
+
static int
assign_in_cond(node)
NODE *node;