diff --git a/ChangeLog b/ChangeLog index 6149a50bf2..8b66569f2b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,39 @@ +Wed Feb 13 17:58:12 2002 Yukihiro Matsumoto + + * parse.y (stmt): local variable declaration order was changed + since 1.6 + + * parse.y (arg): ditto. + + * pack.c (pack_pack): add templates 'q' and 'Q'. + + * pack.c (pack_unpack): ditto. + + * bignum.c (rb_quad_pack): new utility function. + + * bignum.c (rb_quad_unpack): ditto. + +Tue Feb 12 01:21:34 2002 Yukihiro Matsumoto + + * parse.y (assignable): should emit CVASGN within the method + body. + +Mon Feb 11 06:13:53 2002 Matt Armstrong + + * dir.c (dir_s_glob): should not warn even if no match found. + +Mon Feb 11 04:25:54 2002 Yukihiro Matsumoto + + * eval.c (rb_eval): clean up class variable behavior. + + * eval.c (assign): ditto. + + * eval.c (is_defined): ditto. + + * variable.c (rb_mod_class_variables): need not to call rb_cvar_singleton(). + + * variable.c (rb_cvar_singleton): removed. + Sun Feb 10 16:52:53 2002 Nobuyoshi Nakada * ruby.c (load_file): avoid SEGV on '#' only input. diff --git a/bignum.c b/bignum.c index 173c8fb968..c959950e7d 100644 --- a/bignum.c +++ b/bignum.c @@ -185,6 +185,112 @@ rb_int2inum(n) return rb_int2big(n); } +#ifdef HAVE_LONG_LONG + +void +rb_quad_pack(buf, val) + char *buf; + VALUE val; +{ + LONG_LONG q; + + val = rb_to_int(val); + if (FIXNUM_P(val)) { + q = FIX2LONG(val); + } + else { + long len = RBIGNUM(val)->len; + BDIGIT *ds; + + ds = BDIGITS(val); + q = 0; + while (len--) { + q = BIGUP(q); + q += ds[len]; + } + } + memcpy(buf, (char*)&q, sizeof(LONG_LONG)); +} + +VALUE +rb_quad_unpack(buf, sign) + const char *buf; + int sign; +{ + unsigned LONG_LONG q; + long neg = 0; + long i = 0; + BDIGIT *digits; + VALUE big; + + memcpy(&q, buf, sizeof(LONG_LONG)); + if (sign) { + if (FIXABLE((LONG_LONG)q)) return INT2FIX((LONG_LONG)q); + if ((LONG_LONG)q < 0) { + q = -(LONG_LONG)q; + neg = 1; + } + } + else { + if (POSFIXABLE(q)) return INT2FIX(q); + } + + i = 0; + big = bignew(DIGSPERLONGLONG, 1); + digits = BDIGITS(big); + while (i < DIGSPERLONGLONG) { + digits[i++] = BIGLO(q); + q = BIGDN(q); + } + + i = DIGSPERLONGLONG; + while (i-- && !digits[i]) ; + RBIGNUM(big)->len = i+1; + + if (neg) { + RBIGNUM(big)->sign = 0; + } + return bignorm(big); +} + +#else + +#define QUAD_SIZE 8 + +void +rb_quad_pack(buf, val) + char *buf; + VALUE val; +{ + long len; + + memset(buf, 0, QUAD_SIZE); + val = rb_to_int(val); + if (FIXNUM_P(val)) { + val = rb_uint2big(FIX2LONG(val)); + } + len = RBIGNUM(val)->len * sizeof(BDIGIT); + if (len > QUAD_SIZE) len = QUAD_SIZE; + memcpy(buf, (char*)BDIGITS(val), len); +} + +VALUE +rb_quad_unpack(buf, sign) + const char *buf; + int sign; +{ + VALUE big = bignew(QUAD_SIZE/sizeof(BDIGIT), 1); + + memcpy((char*)BDIGITS(big), buf, QUAD_SIZE); + if (sign && (buf[7] & 0x80)) { + RBIGNUM(big)->sign = 0; + } + + return bignorm(big); +} + +#endif + VALUE rb_cstr_to_inum(str, base, badcheck) const char *str; diff --git a/dir.c b/dir.c index 4f283fccfc..13176f4cc5 100644 --- a/dir.c +++ b/dir.c @@ -939,9 +939,6 @@ dir_s_glob(dir, str) if (buf != buffer) free(buf); if (ary) { - if (RARRAY(ary)->len == 0) { - rb_warning("no matches found: %s", RSTRING(str)->ptr); - } return ary; } return Qnil; diff --git a/eval.c b/eval.c index 18dedb61b3..c53889031e 100644 --- a/eval.c +++ b/eval.c @@ -436,7 +436,7 @@ rb_method_boundp(klass, id, ex) return Qfalse; } -static ID init, eqq, each, aref, aset, match, to_ary, missing; +static ID init, alloc, eqq, each, aref, aset, match, to_ary, missing; static ID added, singleton_added; static ID __id__, __send__; @@ -1899,24 +1899,19 @@ is_defined(self, node, buf) break; case NODE_CVAR: - if (!ruby_frame || !ruby_frame->last_class || - !FL_TEST(ruby_frame->last_class, FL_SINGLETON)) { - if (NIL_P(ruby_cbase)) { - if (rb_cvar_defined(CLASS_OF(self), node->nd_vid)) { - return "class variable"; - } - break; - } - if (!FL_TEST(ruby_cbase, FL_SINGLETON)) { - if (rb_cvar_defined(ruby_cbase, node->nd_vid)) { - return "class variable"; - } - break; + if (NIL_P(ruby_cbase)) { + if (rb_cvar_defined(CLASS_OF(self), node->nd_vid)) { + return "class variable"; } + break; } - /* fall through */ - case NODE_CVAR2: - if (rb_cvar_defined(rb_cvar_singleton(self), node->nd_vid)) { + if (!FL_TEST(ruby_cbase, FL_SINGLETON)) { + if (rb_cvar_defined(ruby_cbase, node->nd_vid)) { + return "class variable"; + } + break; + } + if (rb_cvar_defined(rb_iv_get(ruby_cbase, "__attached__"), node->nd_vid)) { return "class variable"; } break; @@ -2866,17 +2861,15 @@ rb_eval(self, n) rb_raise(rb_eTypeError, "no class/module to define class variable"); } result = rb_eval(self, node->nd_value); - if (FL_TEST(ruby_cbase, FL_SINGLETON)) { - rb_cvar_declare(rb_cvar_singleton(rb_iv_get(ruby_cbase, "__attached__")), - node->nd_vid, result); - break; + if (ruby_verbose && FL_TEST(ruby_cbase, FL_SINGLETON)) { + rb_warn("declaring singleton class variable"); } rb_cvar_declare(ruby_cbase, node->nd_vid, result); break; case NODE_CVASGN: result = rb_eval(self, node->nd_value); - rb_cvar_set(rb_cvar_singleton(self), node->nd_vid, result); + rb_cvar_set(ruby_cbase, node->nd_vid, result); break; case NODE_LVAR: @@ -2902,22 +2895,16 @@ rb_eval(self, n) result = ev_const_get(RNODE(ruby_frame->cbase), node->nd_vid, self); break; - case NODE_CVAR: /* normal method */ - if (!ruby_frame || !ruby_frame->last_class || - !FL_TEST(ruby_frame->last_class, FL_SINGLETON)) { - /* non singleton method */ - if (NIL_P(ruby_cbase)) { - result = rb_cvar_get(CLASS_OF(self), node->nd_vid); - break; - } - if (!FL_TEST(ruby_cbase, FL_SINGLETON)) { - result = rb_cvar_get(ruby_cbase, node->nd_vid); - break; - } + case NODE_CVAR: + if (NIL_P(ruby_cbase)) { + result = rb_cvar_get(CLASS_OF(self), node->nd_vid); + break; } - /* fall through */ - case NODE_CVAR2: /* singleton method */ - result = rb_cvar_get(rb_cvar_singleton(self), node->nd_vid); + if (!FL_TEST(ruby_cbase, FL_SINGLETON)) { + result = rb_cvar_get(ruby_cbase, node->nd_vid); + break; + } + result = rb_cvar_get(rb_iv_get(ruby_cbase, "__attached__"), node->nd_vid); break; case NODE_BLOCK_ARG: @@ -3103,6 +3090,9 @@ rb_eval(self, n) if (NIL_P(ruby_class)) { rb_raise(rb_eTypeError, "no class/module to add method"); } + if (ruby_class == rb_cClass && node->nd_mid == alloc) { + rb_raise(rb_eNameError, "redefining Class#allocate will cause infinite loop"); + } if (ruby_class == rb_cObject && node->nd_mid == init) { rb_warn("redefining Object#initialize may cause infinite loop"); } @@ -3922,14 +3912,14 @@ assign(self, lhs, val, pcall) break; case NODE_CVDECL: - if (!FL_TEST(ruby_cbase, FL_SINGLETON)) { - rb_cvar_declare(ruby_cbase, lhs->nd_vid, val); - break; + if (ruby_verbose && FL_TEST(ruby_cbase, FL_SINGLETON)) { + rb_warn("declaring singleton class variable"); } - self = rb_iv_get(ruby_cbase, "__attached__"); - /* fall through */ + rb_cvar_declare(ruby_cbase, lhs->nd_vid, val); + break; + case NODE_CVASGN: - rb_cvar_set(rb_cvar_singleton(self), lhs->nd_vid, val); + rb_cvar_set(ruby_cbase, lhs->nd_vid, val); break; case NODE_MASGN: @@ -6021,6 +6011,7 @@ void Init_eval() { init = rb_intern("initialize"); + alloc = rb_intern("allocate"); eqq = rb_intern("==="); each = rb_intern("each"); diff --git a/gc.c b/gc.c index 89085de921..90e9e5d814 100644 --- a/gc.c +++ b/gc.c @@ -700,7 +700,6 @@ rb_gc_mark_children(ptr) case NODE_DVAR: case NODE_IVAR: case NODE_CVAR: - case NODE_CVAR2: case NODE_NTH_REF: case NODE_BACK_REF: case NODE_ALIAS: diff --git a/intern.h b/intern.h index d41086dfd0..b5d0814527 100644 --- a/intern.h +++ b/intern.h @@ -70,6 +70,8 @@ long rb_big2long _((VALUE)); #define rb_big2int(x) rb_big2long(x) unsigned long rb_big2ulong _((VALUE)); #define rb_big2uint(x) rb_big2ulong(x) +void rb_quad_pack _((char*,VALUE)); +VALUE rb_quad_unpack _((const char*,int)); VALUE rb_dbl2big _((double)); double rb_big2dbl _((VALUE)); VALUE rb_big_plus _((VALUE, VALUE)); @@ -424,7 +426,6 @@ void rb_cvar_declare _((VALUE, ID, VALUE)); VALUE rb_cvar_defined _((VALUE, ID)); void rb_cvar_set _((VALUE, ID, VALUE)); VALUE rb_cvar_get _((VALUE, ID)); -VALUE rb_cvar_singleton _((VALUE)); void rb_cv_set _((VALUE, const char *, VALUE)); VALUE rb_cv_get _((VALUE, const char *)); void rb_define_class_variable _((VALUE, const char *, VALUE)); diff --git a/node.h b/node.h index d39a5a9a93..b7c9daec51 100644 --- a/node.h +++ b/node.h @@ -71,7 +71,6 @@ enum node_type { NODE_IVAR, NODE_CONST, NODE_CVAR, - NODE_CVAR2, NODE_NTH_REF, NODE_BACK_REF, NODE_MATCH, @@ -285,7 +284,6 @@ typedef struct RNode { #define NEW_IVAR(v) rb_node_newnode(NODE_IVAR,v,0,0) #define NEW_CONST(v) rb_node_newnode(NODE_CONST,v,0,0) #define NEW_CVAR(v) rb_node_newnode(NODE_CVAR,v,0,0) -#define NEW_CVAR2(v) rb_node_newnode(NODE_CVAR2,v,0,0) #define NEW_NTH_REF(n) rb_node_newnode(NODE_NTH_REF,0,n,local_cnt('~')) #define NEW_BACK_REF(n) rb_node_newnode(NODE_BACK_REF,0,n,local_cnt('~')) #define NEW_MATCH(c) rb_node_newnode(NODE_MATCH,c,0,0) diff --git a/pack.c b/pack.c index 242a0c7041..316becea40 100644 --- a/pack.c +++ b/pack.c @@ -316,6 +316,11 @@ typedef unsigned int U32; #define NUM2U32(x) NUM2UINT(x) #endif +#ifdef HAVE_LONG_LONG +# define QUAD_SIZE sizeof(LONG_LONG) +#else +# define QUAD_SIZE 8 +#endif static char *toofew = "too few arguments"; static void encodes _((VALUE,char*,int,int)); @@ -594,6 +599,18 @@ pack_pack(ary, fmt) } break; + case 'q': + case 'Q': + while (len-- > 0) { + char tmp[QUAD_SIZE]; + + from = NEXTFROM; + if (NIL_P(from)) from = INT2FIX(0); + rb_quad_pack(tmp, from); + rb_str_buf_cat(res, (char*)&tmp, QUAD_SIZE); + } + break; + case 'n': while (len-- > 0) { unsigned short s; @@ -1007,26 +1024,24 @@ hex2num(c) } } +#define PACK_LENGTH_ADJUST_SIZE(sz) do { \ + tmp = 0; \ + if (len > (send-s)/sz) { \ + if (!star) { \ + tmp = len-(send-s)/sz; \ + } \ + len = (send-s)/sz; \ + } \ +} while (0) + #ifdef NATINT_PACK #define PACK_LENGTH_ADJUST(type,sz) do { \ int t__len = NATINT_LEN(type,(sz)); \ - tmp = 0; \ - if (len > (send-s)/t__len) { \ - if (!star) { \ - tmp = len-(send-s)/t__len; \ - } \ - len = (send-s)/t__len; \ - } \ + PACK_LENGTH_ADJUST_SIZE(t__len); \ } while (0) #else #define PACK_LENGTH_ADJUST(type,sz) do { \ - tmp = 0; \ - if (len > (send-s)/sizeof(type)) { \ - if (!star) { \ - tmp = len - (send-s)/sizeof(type); \ - } \ - len = (send-s)/sizeof(type); \ - } \ + PACK_LENGTH_ADJUST_SIZE(sizeof(type)); \ } while (0) #endif @@ -1294,6 +1309,24 @@ pack_unpack(str, fmt) PACK_ITEM_ADJUST(); break; + case 'q': + PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE); + while (len-- > 0) { + char *tmp = (char*)s; + s += QUAD_SIZE; + rb_ary_push(ary, rb_quad_unpack(tmp, 1)); + } + PACK_ITEM_ADJUST(); + break; + case 'Q': + PACK_LENGTH_ADJUST_SIZE(QUAD_SIZE); + while (len-- > 0) { + char *tmp = (char*)s; + s += QUAD_SIZE; + rb_ary_push(ary, rb_quad_unpack(tmp, 0)); + } + break; + case 'n': PACK_LENGTH_ADJUST(unsigned short,2); while (len-- > 0) { diff --git a/parse.y b/parse.y index 0081e9fa81..da2a093e99 100644 --- a/parse.y +++ b/parse.y @@ -215,7 +215,7 @@ static void top_local_setup(); %type compstmt stmts stmt expr arg primary command command_call method_call %type if_tail opt_else case_body cases rescue exc_list exc_var ensure %type args when_args call_args call_args2 open_args paren_args opt_paren_args -%type command_args aref_args opt_block_arg block_arg var_ref +%type command_args aref_args opt_block_arg block_arg var_ref var_lhs %type mrhs mrhs_basic superclass block_call block_command %type f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg %type assoc_list assocs assoc undef_list backref @@ -425,24 +425,24 @@ stmt : kALIAS fitem {lex_state = EXPR_FNAME;} fitem $1->nd_value = $3; $$ = $1; } - | variable tOP_ASGN command_call + | var_lhs tOP_ASGN command_call { - NODE *n = assignable($1, 0); - if (n) { + ID vid = $1->nd_vid; + if ($1) { if ($2 == tOROP) { - n->nd_value = $3; - $$ = NEW_OP_ASGN_OR(gettable($1), n); - if (is_instance_id($1)) { - $$->nd_aid = $1; + $1->nd_value = $3; + $$ = NEW_OP_ASGN_OR(gettable(vid), $1); + if (is_instance_id(vid)) { + $$->nd_aid = vid; } } else if ($2 == tANDOP) { - n->nd_value = $3; - $$ = NEW_OP_ASGN_AND(gettable($1), n); + $1->nd_value = $3; + $$ = NEW_OP_ASGN_AND(gettable(vid), $1); } else { - $$ = n; - $$->nd_value = call_op(gettable($1),$2,1,$3); + $$ = $1; + $$->nd_value = call_op(gettable(vid),$2,1,$3); } fixpos($$, $3); } @@ -770,24 +770,24 @@ arg : lhs '=' arg value_expr($3); $$ = node_assign($1, $3); } - | variable tOP_ASGN arg + | var_lhs tOP_ASGN arg { - NODE *n = assignable($1, 0); - if (n) { + ID vid = $1->nd_vid; + if ($1) { if ($2 == tOROP) { - n->nd_value = $3; - $$ = NEW_OP_ASGN_OR(gettable($1), n); - if (is_instance_id($1)) { - $$->nd_aid = $1; + $1->nd_value = $3; + $$ = NEW_OP_ASGN_OR(gettable(vid), $1); + if (is_instance_id(vid)) { + $$->nd_aid = vid; } } else if ($2 == tANDOP) { - n->nd_value = $3; - $$ = NEW_OP_ASGN_AND(gettable($1), n); + $1->nd_value = $3; + $$ = NEW_OP_ASGN_AND(gettable(vid), $1); } else { - $$ = n; - $$->nd_value = call_op(gettable($1),$2,1,$3); + $$ = $1; + $$->nd_value = call_op(gettable(vid),$2,1,$3); } fixpos($$, $3); } @@ -1798,6 +1798,11 @@ var_ref : variable $$ = gettable($1); } +var_lhs : variable + { + $$ = assignable($1); + } + backref : tNTH_REF | tBACK_REF @@ -4322,7 +4327,6 @@ gettable(id) return NEW_CONST(id); } else if (is_class_id(id)) { - if (in_single) return NEW_CVAR2(id); return NEW_CVAR(id); } rb_compile_error("identifier %s is not valid", rb_id2name(id)); @@ -4380,7 +4384,7 @@ assignable(id, val) return NEW_CDECL(id, val); } else if (is_class_id(id)) { - if (in_single) return NEW_CVASGN(id, val); + if (in_def || in_single) return NEW_CVASGN(id, val); return NEW_CVDECL(id, val); } else { diff --git a/re.c b/re.c index d587cdbb5c..5e73ddbd8b 100644 --- a/re.c +++ b/re.c @@ -629,7 +629,6 @@ rb_reg_search(re, str, pos, reverse) else { range = RSTRING(str)->len - pos; } - regs.allocated = 0; result = re_search(RREGEXP(re)->ptr,RSTRING(str)->ptr,RSTRING(str)->len, pos, range, ®s); diff --git a/sample/test.rb b/sample/test.rb index fc2eb5ae0f..d3773fe688 100644 --- a/sample/test.rb +++ b/sample/test.rb @@ -1288,6 +1288,43 @@ foobar = "foobar" $_ = foobar test_ok($_ == foobar) +class Gods + @@rule = "Uranus" + def ruler0 + @@rule + end + + def self.ruler1 # <= per method definition style + @@rule + end + class << self # <= multiple method definition style + def ruler2 + @@rule + end + end +end + +module Olympians + @@rule ="Zeus" + def ruler3 + @@rule + end +end + +class Titans < Gods + @@rule = "Cronus" + include Olympians # OK to cause warning (intentional) +end + +test_ok(Gods.new.ruler0 == "Cronus") +test_ok(Gods.ruler1 == "Cronus") +test_ok(Gods.ruler2 == "Cronus") +test_ok(Titans.ruler1 == "Cronus") +test_ok(Titans.ruler2 == "Cronus") +atlas = Titans.new +test_ok(atlas.ruler0 == "Cronus") +test_ok(atlas.ruler3 == "Zeus") + test_check "trace" $x = 1234 $y = 0 diff --git a/variable.c b/variable.c index 1c7a2601e0..656497e742 100644 --- a/variable.c +++ b/variable.c @@ -1411,20 +1411,6 @@ rb_define_global_const(name, val) rb_define_const(rb_cObject, name, val); } -VALUE -rb_cvar_singleton(obj) - VALUE obj; -{ - switch (TYPE(obj)) { - case T_MODULE: - case T_CLASS: - return obj; - default: - break; - } - return CLASS_OF(obj); -} - static VALUE original_module(c) VALUE c; @@ -1613,10 +1599,6 @@ rb_mod_class_variables(obj) { VALUE ary = rb_ary_new(); - if (FL_TEST(obj, FL_SINGLETON)) { - obj = rb_cvar_singleton(rb_iv_get(obj, "__attached__")); - } - for (;;) { if (RCLASS(obj)->iv_tbl) { st_foreach(RCLASS(obj)->iv_tbl, cv_i, ary);