summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-08-12 08:13:28 +0000
committermatz <matz@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2005-08-12 08:13:28 +0000
commite439bc27dc5f6814b49309b4ad32b8d3ca54e9a4 (patch)
tree127adbc9559d0dd3f365f14a9ce9b5bc778f34e6
parentec14c2c9b925f6add71f7f4d25e0a281f8adb252 (diff)
* parse.y (f_larglist): allow optional arguments even when
parentheses are omitted. based on Nobu's patch from http://www.rubyist.net/~nobu/t/20050805.html * parse.y (parser_yylex): update & maintain lpar_beg for detect lambda parameters. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@8971 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog9
-rw-r--r--bignum.c4
-rw-r--r--gc.c2
-rw-r--r--intern.h2
-rw-r--r--numeric.c42
-rw-r--r--parse.y54
6 files changed, 73 insertions, 40 deletions
diff --git a/ChangeLog b/ChangeLog
index f1635fd713..3e48fa35f4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Fri Aug 12 17:06:53 2005 Yukihiro Matsumoto <matz@ruby-lang.org>
+
+ * parse.y (f_larglist): allow optional arguments even when
+ parentheses are omitted. based on Nobu's patch from
+ http://www.rubyist.net/~nobu/t/20050805.html
+
+ * parse.y (parser_yylex): update & maintain lpar_beg for detect
+ lambda parameters.
+
Thu Aug 11 23:29:03 2005 Nobuyoshi Nakada <nobu@ruby-lang.org>
* ext/stringio/stringio.c: keep holding string after closed.
diff --git a/bignum.c b/bignum.c
index 63ad2712bd..38254534ad 100644
--- a/bignum.c
+++ b/bignum.c
@@ -922,7 +922,7 @@ rb_big_to_f(x)
*
*/
-static VALUE
+VALUE
rb_big_cmp(x, y)
VALUE x, y;
{
@@ -968,7 +968,7 @@ rb_big_cmp(x, y)
* 68719476736 == 68719476736.0 #=> true
*/
-static VALUE
+VALUE
rb_big_eq(x, y)
VALUE x, y;
{
diff --git a/gc.c b/gc.c
index 9929eaf328..7ae10fba9f 100644
--- a/gc.c
+++ b/gc.c
@@ -1802,8 +1802,8 @@ rb_gc_finalize_deferred()
deferred_final_list = 0;
if (p) {
finalize_list(p);
- free_unused_heaps();
}
+ free_unused_heaps();
}
void
diff --git a/intern.h b/intern.h
index cb16a81eb1..113be3f985 100644
--- a/intern.h
+++ b/intern.h
@@ -95,6 +95,8 @@ void rb_quad_pack _((char*,VALUE));
VALUE rb_quad_unpack _((const char*,int));
VALUE rb_dbl2big _((double));
double rb_big2dbl _((VALUE));
+VALUE rb_big_cmp _((VALUE, VALUE));
+VALUE rb_big_eq _((VALUE, VALUE));
VALUE rb_big_plus _((VALUE, VALUE));
VALUE rb_big_minus _((VALUE, VALUE));
VALUE rb_big_mul _((VALUE, VALUE));
diff --git a/numeric.c b/numeric.c
index 88f4109c2f..671b4055d6 100644
--- a/numeric.c
+++ b/numeric.c
@@ -2289,7 +2289,12 @@ fix_equal(x, y)
if (FIXNUM_P(y)) {
return (FIX2LONG(x) == FIX2LONG(y))?Qtrue:Qfalse;
}
- else {
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ return rb_big_eq(y, x);
+ case T_FLOAT:
+ return (double)FIX2LONG(x) == RFLOAT(y)->value ? Qtrue : Qfalse;
+ default:
return num_equal(x, y);
}
}
@@ -2314,7 +2319,12 @@ fix_cmp(x, y)
if (a > b) return INT2FIX(1);
return INT2FIX(-1);
}
- else {
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ return rb_big_cmp(rb_int2big(FIX2LONG(x)), y);
+ case T_FLOAT:
+ return rb_dbl_cmp((double)FIX2LONG(x), RFLOAT(y)->value);
+ default:
return rb_num_coerce_cmp(x, y);
}
}
@@ -2337,7 +2347,12 @@ fix_gt(x, y)
if (a > b) return Qtrue;
return Qfalse;
}
- else {
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) > 0 ? Qtrue : Qfalse;
+ case T_FLOAT:
+ return (double)FIX2LONG(x) > RFLOAT(y)->value ? Qtrue : Qfalse;
+ default:
return rb_num_coerce_relop(x, y);
}
}
@@ -2360,7 +2375,12 @@ fix_ge(x, y)
if (a >= b) return Qtrue;
return Qfalse;
}
- else {
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) >= 0 ? Qtrue : Qfalse;
+ case T_FLOAT:
+ return (double)FIX2LONG(x) >= RFLOAT(y)->value ? Qtrue : Qfalse;
+ default:
return rb_num_coerce_relop(x, y);
}
}
@@ -2383,7 +2403,12 @@ fix_lt(x, y)
if (a < b) return Qtrue;
return Qfalse;
}
- else {
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) < 0 ? Qtrue : Qfalse;
+ case T_FLOAT:
+ return (double)FIX2LONG(x) < RFLOAT(y)->value ? Qtrue : Qfalse;
+ default:
return rb_num_coerce_relop(x, y);
}
}
@@ -2406,7 +2431,12 @@ fix_le(x, y)
if (a <= b) return Qtrue;
return Qfalse;
}
- else {
+ switch (TYPE(y)) {
+ case T_BIGNUM:
+ return FIX2INT(rb_big_cmp(rb_int2big(FIX2LONG(x)), y)) <= 0 ? Qtrue : Qfalse;
+ case T_FLOAT:
+ return (double)FIX2LONG(x) <= RFLOAT(y)->value ? Qtrue : Qfalse;
+ default:
return rb_num_coerce_relop(x, y);
}
}
diff --git a/parse.y b/parse.y
index 94f2b38b6b..1c5fb18f67 100644
--- a/parse.y
+++ b/parse.y
@@ -126,6 +126,8 @@ struct parser_params {
stack_type parser_cond_stack;
stack_type parser_cmdarg_stack;
int parser_class_nest;
+ int parser_paren_nest;
+ int parser_lpar_beg;
int parser_in_single;
int parser_in_def;
int parser_compile_for_eval;
@@ -182,6 +184,8 @@ static int parser_yyerror _((struct parser_params*, const char*));
#define cond_stack (parser->parser_cond_stack)
#define cmdarg_stack (parser->parser_cmdarg_stack)
#define class_nest (parser->parser_class_nest)
+#define paren_nest (parser->parser_paren_nest)
+#define lpar_beg (parser->parser_lpar_beg)
#define in_single (parser->parser_in_single)
#define in_def (parser->parser_in_def)
#define compile_for_eval (parser->parser_compile_for_eval)
@@ -476,6 +480,7 @@ static void ripper_compile_error _((struct parser_params*, const char *fmt, ...)
kDO
kDO_COND
kDO_BLOCK
+ kDO_LAMBDA
kRETURN
kYIELD
kSUPER
@@ -555,7 +560,7 @@ static void ripper_compile_error _((struct parser_params*, const char *fmt, ...)
%token tLAMBDA /* -> */
%token tLAMBDA_ARG /* -> */
%token tSYMBEG tSTRING_BEG tXSTRING_BEG tREGEXP_BEG tWORDS_BEG tQWORDS_BEG
-%token tSTRING_DBEG tSTRING_DVAR tSTRING_END
+%token tSTRING_DBEG tSTRING_DVAR tSTRING_END tLAMBEG
/*
* precedence table
@@ -3173,6 +3178,8 @@ bv_decl : tIDENTIFIER
;
lambda : {
+ $<num>$ = lpar_beg;
+ lpar_beg = ++paren_nest;
/*%%%*/
$<vars>$ = dyna_push();
/*%
@@ -3202,47 +3209,23 @@ f_larglist : '(' f_args opt_bv_decl rparen
$$ = dispatch1(paren, $2);
%*/
}
- | f_arg opt_f_block_arg opt_bv_decl
+ | f_args opt_bv_decl
{
/*%%%*/
- $$ = NEW_LAMBDA(new_args($1, 0, 0, $2), $3);
+ $$ = NEW_LAMBDA($1, $2);
/*%
- $$ = dispatch4(params, $1, Qnil, Qnil, Qnil);
- %*/
- }
- | f_arg ',' f_rest_arg opt_f_block_arg opt_bv_decl
- {
- /*%%%*/
- $$ = NEW_LAMBDA(new_args($1, 0, $3, $4), $5);
- /*%
- $$ = dispatch4(params, $1, Qnil, $3, Qnil);
- %*/
- }
- | f_rest_arg opt_f_block_arg opt_bv_decl
- {
- /*%%%*/
- $$ = NEW_LAMBDA(new_args(0, 0, $1, $2), $3);
- /*%
- $$ = dispatch4(params, Qnil, Qnil, $1, Qnil);
- %*/
- }
- | opt_f_block_arg opt_bv_decl
- {
- /*%%%*/
- $$ = NEW_LAMBDA(new_args(0, 0, 0, $1), $2);
- /*%
- $$ = dispatch4(params, Qnil, Qnil, Qnil, Qnil);
+ $$ = $1;
%*/
}
;
-lambda_body : '{'
+lambda_body : tLAMBEG
compstmt
'}'
{
$$ = $2;
}
- | kDO
+ | kDO_LAMBDA
compstmt
kEND
{
@@ -6348,9 +6331,10 @@ parser_yylex(parser)
return tINTEGER;
}
+ case ')':
+ paren_nest--;
case ']':
case '}':
- case ')':
COND_LEXPOP();
CMDARG_LEXPOP();
lex_state = EXPR_END;
@@ -6468,6 +6452,7 @@ parser_yylex(parser)
c = '(';
}
}
+ paren_nest++;
COND_PUSH(0);
CMDARG_PUSH(0);
lex_state = EXPR_BEG;
@@ -6498,6 +6483,10 @@ parser_yylex(parser)
return c;
case '{':
+ if (lpar_beg && lpar_beg == paren_nest) {
+ lex_state = EXPR_BEG;
+ return tLAMBEG;
+ }
if (IS_ARG() || lex_state == EXPR_END || lex_state == EXPR_END2)
c = '{'; /* block (primary) */
else if (lex_state == EXPR_ENDARG)
@@ -6815,6 +6804,9 @@ parser_yylex(parser)
set_yylval_id(rb_intern(kw->name));
}
if (kw->id[0] == kDO) {
+ if (lpar_beg && lpar_beg == paren_nest) {
+ return kDO_LAMBDA;
+ }
if (COND_P()) return kDO_COND;
if (CMDARG_P() && state != EXPR_CMDARG)
return kDO_BLOCK;