Project

General

Profile

Feature #1866 ยป redefinable_not.patch

implementation of redefinable not, against ruby_1_8 - shyouhei (Shyouhei Urabe), 08/03/2009 03:47 PM

View differences:

ChangeLog
1
Mon Aug  3 15:04:01 2009  URABE Shyouhei  <shyouhei@ruby-lang.org>
2

  
3
	* parse.y (expr): bug fix to prevent SEGV
4

  
5
Sun Aug  2 21:23:49 2009  URABE Shyouhei  <shyouhei@ruby-lang.org>
6

  
7
	* parse.y (expr): redefinable not operators. Backport from trunk.
8

  
9
	* parse.y (op): ditto.
10

  
11
	* parse.y (arg): ditto.
12

  
13
	* object.c (rb_obj_not_match): new method.
14

  
15
	* object.c (rb_obj_not_equal): ditto.
16

  
17
	* object.c (rb_obj_not): ditto.
18

  
1 19
Sun Aug  2 06:08:17 2009  URABE Shyouhei  <shyouhei@ruby-lang.org>
2 20

  
3 21
	* node.h (rb_thread_status): ISO C89 do not allow a comma at the end of enum.
object.c
31 31
VALUE rb_cFalseClass;
32 32
VALUE rb_cSymbol;
33 33

  
34
static ID id_eq, id_eql, id_inspect, id_init_copy;
34
static ID id_eq, id_eql, id_match, id_inspect, id_init_copy;
35 35

  
36 36
/*
37 37
 *  call-seq:
......
113 113
    return rb_obj_id(obj);
114 114
}
115 115

  
116
/*
117
 *  call-seq:
118
 *     !obj    => true or false
119
 *
120
 *  Boolean negate.
121
 */
122

  
123
VALUE
124
rb_obj_not(VALUE obj)
125
{
126
    return RTEST(obj) ? Qfalse : Qtrue;
127
}
128

  
129
/*
130
 *  call-seq:
131
 *     obj != other        => true or false
132
 *
133
 *  Returns true if two objects are not-equal, otherwise false.
134
 */
135

  
136
VALUE
137
rb_obj_not_equal(VALUE obj1, VALUE obj2)
138
{
139
    VALUE result = rb_funcall(obj1, id_eq, 1, obj2);
140
    return RTEST(result) ? Qfalse : Qtrue;
141
}
142

  
116 143
VALUE
117 144
rb_class_real(cl)
118 145
    VALUE cl;
......
1081 1108
    return Qfalse;
1082 1109
}
1083 1110

  
1111
/*
1112
 *  call-seq:
1113
 *     obj !~ other  => true or false
1114
 *
1115
 *  Returns true if two objects do not match (using the <i>=~</i>
1116
 *  method), otherwise false.
1117
 */
1118

  
1119
static VALUE
1120
rb_obj_not_match(VALUE obj1, VALUE obj2)
1121
{
1122
    VALUE result = rb_funcall(obj1, id_match, 1, obj2);
1123
    return RTEST(result) ? Qfalse : Qtrue;
1124
}
1125

  
1084 1126
/**********************************************************************
1085 1127
 * Document-class: Symbol
1086 1128
 *
......
2734 2776

  
2735 2777
    rb_define_method(rb_mKernel, "nil?", rb_false, 0);
2736 2778
    rb_define_method(rb_mKernel, "==", rb_obj_equal, 1);
2779
    rb_define_method(rb_mKernel, "!", rb_obj_not, 0);
2780
    rb_define_method(rb_mKernel, "!=", rb_obj_not_equal, 1);
2737 2781
    rb_define_method(rb_mKernel, "equal?", rb_obj_equal, 1);
2738 2782
    rb_define_method(rb_mKernel, "===", rb_equal, 1); 
2739 2783
    rb_define_method(rb_mKernel, "=~", rb_obj_pattern_match, 1);
2784
    rb_define_method(rb_mKernel, "!~", rb_obj_not_match, 1);
2740 2785

  
2741 2786
    rb_define_method(rb_mKernel, "eql?", rb_obj_equal, 1);
2742 2787

  
......
2904 2949

  
2905 2950
    id_eq = rb_intern("==");
2906 2951
    id_eql = rb_intern("eql?");
2952
    id_match = rb_intern("match");
2907 2953
    id_inspect = rb_intern("inspect");
2908 2954
    id_init_copy = rb_intern("initialize_copy");
2909 2955
}
parse.y
129 129

  
130 130
static NODE *cond();
131 131
static NODE *logop();
132
static int cond_negative();
133 132

  
134 133
static NODE *newline_node();
135 134
static void fixpos();
......
447 446
		    {
448 447
			$$ = NEW_IF(cond($3), remove_begin($1), 0);
449 448
		        fixpos($$, $3);
450
			if (cond_negative(&$$->nd_cond)) {
451
		            $$->nd_else = $$->nd_body;
452
		            $$->nd_body = 0;
453
			}
454 449
		    }
455 450
		| stmt kUNLESS_MOD expr_value
456 451
		    {
457 452
			$$ = NEW_UNLESS(cond($3), remove_begin($1), 0);
458 453
		        fixpos($$, $3);
459
			if (cond_negative(&$$->nd_cond)) {
460
		            $$->nd_body = $$->nd_else;
461
		            $$->nd_else = 0;
462
			}
463 454
		    }
464 455
		| stmt kWHILE_MOD expr_value
465 456
		    {
......
469 460
			else {
470 461
			    $$ = NEW_WHILE(cond($3), $1, 1);
471 462
			}
472
			if (cond_negative(&$$->nd_cond)) {
473
			    nd_set_type($$, NODE_UNTIL);
474
			}
475 463
		    }
476 464
		| stmt kUNTIL_MOD expr_value
477 465
		    {
......
481 469
			else {
482 470
			    $$ = NEW_UNTIL(cond($3), $1, 1);
483 471
			}
484
			if (cond_negative(&$$->nd_cond)) {
485
			    nd_set_type($$, NODE_WHILE);
486
			}
487 472
		    }
488 473
		| stmt kRESCUE_MOD stmt
489 474
		    {
......
632 617
		    }
633 618
		| kNOT expr
634 619
		    {
635
			$$ = NEW_NOT(cond($2));
620
			$$ = call_op($2, '!', 0, 0);
636 621
		    }
637 622
		| '!' command_call
638 623
		    {
639
			$$ = NEW_NOT(cond($2));
624
			$$ = call_op($2, '!', 0, 0);
640 625
		    }
641 626
		| arg
642 627
		;
......
952 937
		| tEQ		{ $$ = tEQ; }
953 938
		| tEQQ		{ $$ = tEQQ; }
954 939
		| tMATCH	{ $$ = tMATCH; }
940
		| tNMATCH	{ $$ = tNMATCH; }
955 941
		| '>'		{ $$ = '>'; }
956 942
		| tGEQ		{ $$ = tGEQ; }
957 943
		| '<'		{ $$ = '<'; }
958 944
		| tLEQ		{ $$ = tLEQ; }
945
		| tNEQ		{ $$ = tNEQ; }
959 946
		| tLSHFT	{ $$ = tLSHFT; }
960 947
		| tRSHFT	{ $$ = tRSHFT; }
961 948
		| '+'		{ $$ = '+'; }
......
965 952
		| '/'		{ $$ = '/'; }
966 953
		| '%'		{ $$ = '%'; }
967 954
		| tPOW		{ $$ = tPOW; }
955
		| '!'		{ $$ = '!'; }
968 956
		| '~'		{ $$ = '~'; }
969 957
		| tUPLUS	{ $$ = tUPLUS; }
970 958
		| tUMINUS	{ $$ = tUMINUS; }
......
1189 1177
		    }
1190 1178
		| arg tNEQ arg
1191 1179
		    {
1192
			$$ = NEW_NOT(call_op($1, tEQ, 1, $3));
1180
			$$ = call_op($1, tNEQ, 1, $3);
1193 1181
		    }
1194 1182
		| arg tMATCH arg
1195 1183
		    {
......
1197 1185
		    }
1198 1186
		| arg tNMATCH arg
1199 1187
		    {
1200
			$$ = NEW_NOT(match_gen($1, $3));
1188
			$$ = call_op($1, tNMATCH, 1, $3);
1201 1189
		    }
1202 1190
		| '!' arg
1203 1191
		    {
1204
			$$ = NEW_NOT(cond($2));
1192
			$$ = call_op($2, '!', 0, 0);
1205 1193
		    }
1206 1194
		| '~' arg
1207 1195
		    {
......
1559 1547
		    {
1560 1548
			$$ = NEW_IF(cond($2), $4, $5);
1561 1549
		        fixpos($$, $2);
1562
			if (cond_negative(&$$->nd_cond)) {
1563
		            NODE *tmp = $$->nd_body;
1564
		            $$->nd_body = $$->nd_else;
1565
		            $$->nd_else = tmp;
1566
			}
1567 1550
		    }
1568 1551
		| kUNLESS expr_value then
1569 1552
		  compstmt
......
1572 1555
		    {
1573 1556
			$$ = NEW_UNLESS(cond($2), $4, $5);
1574 1557
		        fixpos($$, $2);
1575
			if (cond_negative(&$$->nd_cond)) {
1576
		            NODE *tmp = $$->nd_body;
1577
		            $$->nd_body = $$->nd_else;
1578
		            $$->nd_else = tmp;
1579
			}
1580 1558
		    }
1581 1559
		| kWHILE {COND_PUSH(1);} expr_value do {COND_POP();}
1582 1560
		  compstmt
......
1584 1562
		    {
1585 1563
			$$ = NEW_WHILE(cond($3), $6, 1);
1586 1564
		        fixpos($$, $3);
1587
			if (cond_negative(&$$->nd_cond)) {
1588
			    nd_set_type($$, NODE_UNTIL);
1589
			}
1590 1565
		    }
1591 1566
		| kUNTIL {COND_PUSH(1);} expr_value do {COND_POP();}
1592 1567
		  compstmt
......
1594 1569
		    {
1595 1570
			$$ = NEW_UNTIL(cond($3), $6, 1);
1596 1571
		        fixpos($$, $3);
1597
			if (cond_negative(&$$->nd_cond)) {
1598
			    nd_set_type($$, NODE_WHILE);
1599
			}
1600 1572
		    }
1601 1573
		| kCASE expr_value opt_terms
1602 1574
		  case_body
......
3547 3519
	return c;
3548 3520

  
3549 3521
      case '!':
3550
	lex_state = EXPR_BEG;
3551
	if ((c = nextc()) == '=') {
3522
	c = nextc();
3523
	if (lex_state == EXPR_FNAME || lex_state == EXPR_DOT) {
3524
	    lex_state = EXPR_ARG;
3525
	    if (c == '@') {
3526
		return '!';
3527
	    }
3528
	}
3529
	else {
3530
	    lex_state = EXPR_BEG;
3531
	}
3532
	if (c == '=') {
3552 3533
	    return tNEQ;
3553 3534
	}
3554 3535
	if (c == '~') {
......
5568 5549
    return NEW_NODE(type, left, right, 0);
5569 5550
}
5570 5551

  
5571
static int
5572
cond_negative(nodep)
5573
    NODE **nodep;
5574
{
5575
    NODE *c = *nodep;
5576

  
5577
    if (!c) return 0;
5578
    switch (nd_type(c)) {
5579
      case NODE_NOT:
5580
	*nodep = c->nd_body;
5581
	return 1;
5582
      case NODE_NEWLINE:
5583
	if (c->nd_next && nd_type(c->nd_next) == NODE_NOT) {
5584
	    c->nd_next = c->nd_next->nd_body;
5585
	    return 1;
5586
	}
5587
    }
5588
    return 0;
5589
}
5590

  
5591 5552
static void
5592 5553
no_blockarg(node)
5593 5554
    NODE *node;
......
6023 5984
    {'|',	"|"},
6024 5985
    {'^',	"^"},
6025 5986
    {'&',	"&"},
5987
    {'!',	"!"},
6026 5988
    {tCMP,	"<=>"},
6027 5989
    {'>',	">"},
6028 5990
    {tGEQ,	">="},
......
6033 5995
    {tNEQ,	"!="},
6034 5996
    {tMATCH,	"=~"},
6035 5997
    {tNMATCH,	"!~"},
6036
    {'!',	"!"},
6037 5998
    {'~',	"~"},
6038
    {'!',	"!(unary)"},
6039 5999
    {'~',	"~(unary)"},
6040
    {'!',	"!@"},
6041 6000
    {'~',	"~@"},
6001
    {'!',	"!"},
6002
    {'!',	"!(unary)"},
6003
    {'!',	"!@"},
6042 6004
    {tAREF,	"[]"},
6043 6005
    {tASET,	"[]="},
6044 6006
    {tLSHFT,	"<<"},