From f70ffbee2120cbbb8c6b0a15dfc693a69ac0d7d4 Mon Sep 17 00:00:00 2001 From: matz Date: Thu, 5 Mar 1998 06:37:50 +0000 Subject: block arg etc. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/v1_1r@107 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 16 ++++ array.c | 3 + bignum.c | 2 + class.c | 3 + error.c | 6 +- eval.c | 158 ++++++++++++++-------------------- ext/gtk/gtk.c | 2 +- gc.c | 5 +- hash.c | 3 + io.c | 7 +- lib/jcode.rb | 1 + lib/mathn.rb | 5 +- node.h | 4 + numeric.c | 4 + object.c | 20 ++++- parse.y | 265 ++++++++++++++++++++++++++++++++++++++++------------------ re.c | 3 + ruby.h | 1 + string.c | 5 ++ struct.c | 2 + 20 files changed, 326 insertions(+), 189 deletions(-) diff --git a/ChangeLog b/ChangeLog index ba907f86ad..204cf914a3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,19 @@ +Thu Mar 5 13:47:39 1998 Yukihiro Matsumoto + + * eval.c (f_missing): use any_to_s() for stringify. + +Wed Mar 4 01:39:52 1998 Yukihiro Matsumoto + + * parse.y (block_arg): new syntax - block argument in the + calling arglist. + + * eval.c (rb_call): no module search. simplified a lot. + + * eval.c (rb_eval): block arg support. + + * parse.y (f_block_arg): new syntax - block argument in the + formal arglist. + Tue Mar 3 14:20:15 1998 Yukihiro Matsumoto * eval.c (obj_method): returns bound method object. diff --git a/array.c b/array.c index 9ef50cfee7..0eafbf01f3 100644 --- a/array.c +++ b/array.c @@ -1229,4 +1229,7 @@ Init_Array() rb_define_method(cArray, "nitems", ary_nitems, 0); cmp = rb_intern("<=>"); + + /* turn on premitive flag for the class */ + FL_SET(cArray, FL_PRIMITIVE); } diff --git a/bignum.c b/bignum.c index 8a6e54a9da..937d5ba8f4 100644 --- a/bignum.c +++ b/bignum.c @@ -1248,4 +1248,6 @@ Init_Bignum() rb_define_method(cBignum, "to_f", big_to_f, 0); rb_define_method(cBignum, "abs", big_abs, 0); rb_define_method(cBignum, "size", big_size, 0); + + FL_SET(cBignum, FL_PRIMITIVE); } diff --git a/class.c b/class.c index 383df43dae..87842c3d3b 100644 --- a/class.c +++ b/class.c @@ -98,6 +98,9 @@ rb_define_class_id(id, super) RBASIC(klass)->klass = singleton_class_new(RBASIC(super)->klass); singleton_class_attached(RBASIC(klass)->klass, klass); rb_funcall(super, rb_intern("inherited"), 1, klass); + if (FL_TEST(super, FL_PRIMITIVE)) { + FL_SET(klass, FL_PRIMITIVE); + } return klass; } diff --git a/error.c b/error.c index 1cdf4692f0..cb56c4e163 100644 --- a/error.c +++ b/error.c @@ -164,8 +164,9 @@ rb_check_type(x, t) int t; { struct types *type = builtin_types; + int tt = TYPE(x); - if (TYPE(x)!=(t)) { + if (tt != t) { while (type->type >= 0) { if (type->type == t) { char *etype; @@ -173,6 +174,9 @@ rb_check_type(x, t) if (NIL_P(x)) { etype = "nil"; } + else if (FIXNUM_P(x)) { + etype = "Fixnum"; + } else if (rb_special_const_p(x)) { etype = RSTRING(obj_as_string(x))->ptr; } diff --git a/eval.c b/eval.c index 5eca27a224..25402e68ce 100644 --- a/eval.c +++ b/eval.c @@ -38,9 +38,12 @@ char *strrchr(); extern VALUE cData; VALUE cProc; +static VALUE cBinding; static VALUE proc_call _((VALUE,VALUE)); static VALUE f_binding _((VALUE)); static void f_END _((void)); +static VALUE f_iterator_p _((void)); +static VALUE block_pass _((VALUE,NODE*)); #define SCOPE_PRIVATE FL_USER4 #define SCOPE_MODFUNC FL_USER5 @@ -1580,6 +1583,10 @@ rb_eval(self, node) } RETURN(Qnil); + case NODE_BLOCK_PASS: + result = block_pass(self, node); + break; + case NODE_ITER: case NODE_FOR: { @@ -1895,8 +1902,8 @@ rb_eval(self, node) case NODE_LASGN: if (the_scope->local_vars == 0) Bug("unexpected local variable assignment"); - the_scope->local_vars[node->nd_cnt] = rb_eval(self, node->nd_value); - result = the_scope->local_vars[node->nd_cnt]; + result = rb_eval(self, node->nd_value); + the_scope->local_vars[node->nd_cnt] = result; break; case NODE_DASGN: @@ -1962,6 +1969,18 @@ rb_eval(self, node) result = ev_const_get(the_frame->cbase, node->nd_vid); break; + case NODE_BLOCK_ARG: + if (the_scope->local_vars == 0) + Bug("unexpected block argument"); + if (iterator_p()) { + result = f_lambda(); + the_scope->local_vars[node->nd_cnt] = result; + } + else { + result = Qnil; + } + break; + case NODE_COLON2: { VALUE klass; @@ -2946,8 +2965,8 @@ f_missing(argc, argv, obj) VALUE *argv; VALUE obj; { - VALUE desc = 0; ID id; + VALUE desc = 0; char *format = 0; char *file = sourcefile; int line = sourceline; @@ -2966,7 +2985,7 @@ f_missing(argc, argv, obj) format = "undefined method `%s' for FALSE"; break; case T_OBJECT: - desc = obj_as_string(obj); + desc = any_to_s(obj); break; default: desc = rb_inspect(obj); @@ -3051,19 +3070,19 @@ stack_length() } static VALUE -rb_call0(klass, recv, mid, id, argc, argv, scope, body, type) +rb_call0(klass, recv, id, argc, argv, scope, body) VALUE klass, recv; - ID mid, id; + ID id; int argc; /* OK */ VALUE *argv; /* OK */ int scope; NODE *body; - enum node_type type; { NODE *b2; /* OK */ volatile VALUE result = Qnil; int itr; static int tick; + TMP_PROTECT; switch (the_iter->iter) { case ITER_PRE: @@ -3085,7 +3104,7 @@ rb_call0(klass, recv, mid, id, argc, argv, scope, body, type) the_frame->argc = argc; the_frame->argv = argv; - switch (type) { + switch (nd_type(body)) { case NODE_CFUNC: { int len = body->nd_argc; @@ -3188,7 +3207,7 @@ rb_call0(klass, recv, mid, id, argc, argv, scope, body, type) default: if (len < 0) { Bug("bad argc(%d) specified for `%s(%s)'", - len, rb_class2name(klass), rb_id2name(mid)); + len, rb_class2name(klass), rb_id2name(id)); } else { ArgError("too many arguments(%d)", len); @@ -3198,6 +3217,8 @@ rb_call0(klass, recv, mid, id, argc, argv, scope, body, type) } break; + /* for re-scoped/renamed method */ + case NODE_ZSUPER: /* for attr get/set */ case NODE_ATTRSET: case NODE_IVAR: @@ -3348,10 +3369,7 @@ rb_call(klass, recv, mid, argc, argv, scope) int noex; ID id = mid; struct cache_entry *ent; - enum node_type type; - TMP_PROTECT; - again: /* is it in the method cache? */ ent = cache + EXPR1(klass, mid); if (ent->mid == mid && ent->klass == klass) { @@ -3368,27 +3386,7 @@ rb_call(klass, recv, mid, argc, argv, scope) if (noex == NOEX_PRIVATE && scope == 0) return rb_undefined(recv, mid, argc, argv, CSTAT_NOEX); - type = nd_type(body); - if (type == NODE_ZSUPER) { - /* for re-scoped/renamed method */ - mid = id; - if (scope == 0) scope = 1; - if (BUILTIN_TYPE(klass) == T_MODULE) { - /* origin is the Module, so need to scan superclass hierarchy. */ - struct RClass *cl = RCLASS(klass); - - klass = RBASIC(recv)->klass; - while (klass) { - if (RCLASS(klass)->m_tbl == cl->m_tbl) - break; - klass = RCLASS(klass)->super; - } - } - klass = RCLASS(klass)->super; - goto again; - } - - return rb_call0(klass, recv, mid, id, argc, argv, scope, body, type); + return rb_call0(klass, recv, id, argc, argv, scope, body); } VALUE @@ -3424,27 +3422,6 @@ f_send(argc, argv, recv) return vid; } -static VALUE -f_pass_block(argc, argv, recv) - int argc; - VALUE *argv; - VALUE recv; -{ - VALUE vid; - - if (argc == 0) ArgError("no iterator name given"); - if (iterator_p()) - ArgError("iterator block given to pass_block"); - if (!f_iterator_p()) - ArgError("pass_block called out of iterator"); - - vid = *argv++; argc--; - PUSH_ITER(ITER_PRE); - vid = rb_call(CLASS_OF(recv), recv, rb_to_id(vid), argc, argv, 1); - POP_ITER(); - - return vid; -} #include @@ -4319,7 +4296,6 @@ Init_eval() rb_define_global_function("global_variables", f_global_variables, 0); rb_define_method(mKernel, "send", f_send, -1); - rb_define_method(mKernel, "pass_block", f_pass_block, -1); rb_define_method(mKernel, "instance_eval", obj_instance_eval, 1); rb_define_private_method(cModule, "append_features", mod_append_features, 1); @@ -4447,7 +4423,7 @@ f_binding(self) VALUE bind; PUSH_BLOCK(0,0); - bind = Data_Make_Struct(cData, struct BLOCK, blk_mark, blk_free, data); + bind = Data_Make_Struct(cBinding, struct BLOCK, blk_mark,blk_free,data); MEMCPY(data, the_block, struct BLOCK, 1); #ifdef THREAD @@ -4631,29 +4607,33 @@ proc_call(proc, args) } static VALUE -proc_iterate(proc) - VALUE proc; +block_pass(self, node) + VALUE self; + NODE *node; { - VALUE lambda = f_lambda(); + VALUE block = rb_eval(self, node->nd_body); struct BLOCK *data; volatile VALUE result = Qnil; int state; volatile int orphan; volatile int safe = safe_level; - Data_Get_Struct(lambda, struct BLOCK, data); - data->frame.iter = ITER_PRE; - data->iter = ITER_PRE; + if (TYPE(block) != T_DATA + || RDATA(block)->dfree != blk_free + || !obj_is_kind_of(block, cProc)) { + TypeError("wrong argument type %s (expected Proc)", + rb_class2name(CLASS_OF(block))); + } - Data_Get_Struct(proc, struct BLOCK, data); + Data_Get_Struct(block, struct BLOCK, data); orphan = blk_orphan(data); /* PUSH BLOCK from data */ PUSH_BLOCK2(data); PUSH_ITER(ITER_PRE); the_frame->iter = ITER_PRE; - if (FL_TEST(proc, PROC_TAINT)) { - switch (RBASIC(proc)->flags & PROC_TMASK) { + if (FL_TEST(block, PROC_TAINT)) { + switch (RBASIC(block)->flags & PROC_TMASK) { case PROC_T3: safe_level = 3; break; @@ -4669,7 +4649,7 @@ proc_iterate(proc) PUSH_TAG(PROT_NONE); state = EXEC_TAG(); if (state == 0) { - result = proc_call(lambda, Qnil); + result = rb_eval(self, node->nd_iter); } POP_TAG(); @@ -4701,16 +4681,18 @@ proc_iterate(proc) } static VALUE cMethod; + struct METHOD { - VALUE klass; + VALUE klass, oklass; VALUE recv; - ID id; + ID id, oid; NODE *body; }; static void bm_mark(struct METHOD *data) { + gc_mark(data->oklass); gc_mark(data->klass); gc_mark(data->recv); gc_mark(data->body); @@ -4729,40 +4711,25 @@ obj_method(obj, vid) enum node_type type; struct METHOD *data; - mid = id = rb_to_id(vid); + id = rb_to_id(vid); again: if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) { - return rb_undefined(obj, mid, 0, 0, 0); + return rb_undefined(obj, rb_to_id(vid), 0, 0, 0); } - type = nd_type(body); - if (type == NODE_ZSUPER) { - /* for re-scoped/renamed method */ - mid = id; - if (BUILTIN_TYPE(klass) == T_MODULE) { - /* origin is the Module, so need to scan superclass hierarchy. */ - struct RClass *cl = RCLASS(klass); - - klass = RBASIC(obj)->klass; - while (klass) { - if (RCLASS(klass)->m_tbl == cl->m_tbl) - break; - klass = RCLASS(klass)->super; - } - } + if (nd_type(body) == NODE_ZSUPER) { klass = RCLASS(klass)->super; goto again; } - if (BUILTIN_TYPE(klass) == T_ICLASS) { - klass = RBASIC(klass)->klass; - } method = Data_Make_Struct(cMethod, struct METHOD, bm_mark, free, data); data->klass = klass; data->recv = obj; data->id = id; data->body = body; + data->oklass = CLASS_OF(obj); + data->oid = rb_to_id(vid); return method; } @@ -4778,8 +4745,8 @@ method_call(argc, argv, method) Data_Get_Struct(method, struct METHOD, data); PUSH_ITER(iterator_p()?ITER_PRE:ITER_NOT); - result = rb_call0(data->klass, data->recv, data->id, data->id, - argc, argv, 1, data->body, nd_type(data->body)); + result = rb_call0(data->klass, data->recv, data->id, + argc, argv, 1, data->body); POP_ITER(); return result; } @@ -4797,10 +4764,10 @@ method_inspect(method) s = rb_class2name(CLASS_OF(method)); str_cat(str, s, strlen(s)); str_cat(str, ": ", 2); - s = rb_class2name(data->klass); + s = rb_class2name(data->oklass); str_cat(str, s, strlen(s)); str_cat(str, "#", 1); - s = rb_id2name(data->id); + s = rb_id2name(data->oid); str_cat(str, s, strlen(s)); str_cat(str, ">", 1); @@ -4816,15 +4783,16 @@ Init_Proc() rb_define_singleton_method(cProc, "new", proc_s_new, 0); rb_define_method(cProc, "call", proc_call, -2); - rb_define_method(cProc, "iterate", proc_iterate, 0); rb_define_global_function("proc", f_lambda, 0); rb_define_global_function("lambda", f_lambda, 0); rb_define_global_function("binding", f_binding, 0); + cBinding = rb_define_class("Binding", cData); cMethod = rb_define_class("Method", cObject); rb_undef_method(CLASS_OF(cMethod), "new"); rb_define_method(cMethod, "call", method_call, -1); rb_define_method(cMethod, "inspect", method_inspect, 0); + rb_define_method(cMethod, "to_s", method_inspect, 0); rb_define_method(mKernel, "method", obj_method, 1); } @@ -5858,7 +5826,7 @@ thread_status(thread) } static VALUE -thread_stopped(thread) +thread_stop_p(thread) VALUE thread; { thread_t th = thread_check(thread); @@ -6015,7 +5983,7 @@ Init_Thread() rb_define_method(cThread, "value", thread_value, 0); rb_define_method(cThread, "status", thread_status, 0); rb_define_method(cThread, "alive?", thread_status, 0); - rb_define_method(cThread, "stop?", thread_stopped, 0); + rb_define_method(cThread, "stop?", thread_stop_p, 0); rb_define_method(cThread, "raise", thread_raise, -1); rb_define_method(cThread, "abort_on_exception", thread_abort_exc, 0); diff --git a/ext/gtk/gtk.c b/ext/gtk/gtk.c index b7b69ddb70..69e9b793eb 100644 --- a/ext/gtk/gtk.c +++ b/ext/gtk/gtk.c @@ -408,7 +408,7 @@ make_tobj(obj, klass, size) copy = xmalloc(size); memcpy(copy, obj, size); - data = Data_Wrap_Struct(klass, 0, (void*)-1, copy); + data = Data_Wrap_Struct(klass, 0, free, copy); rb_funcall(data, id_init, 0, 0); return data; diff --git a/gc.c b/gc.c index 4dbc59475b..8076d8f7ee 100644 --- a/gc.c +++ b/gc.c @@ -261,6 +261,9 @@ data_object_alloc(klass, datap, dmark, dfree) data->dfree = dfree; data->dmark = dmark; + /* turn on premitive flag for the class */ + FL_SET(klass, FL_PRIMITIVE); + return (VALUE)data; } @@ -370,7 +373,7 @@ gc_mark(ptr) if (FIXNUM_P(obj)) return; /* fixnum not marked */ if (rb_special_const_p((VALUE)obj)) return; /* special const not marked */ if (obj->as.basic.flags == 0) return; /* free cell */ - if (obj->as.basic.flags & FL_MARK) return; /* marked */ + if (obj->as.basic.flags & FL_MARK) return; /* already marked */ obj->as.basic.flags |= FL_MARK; diff --git a/hash.c b/hash.c index 0e5abb78ef..31f22e74d6 100644 --- a/hash.c +++ b/hash.c @@ -1172,4 +1172,7 @@ Init_Hash() rb_define_singleton_method(envtbl,"value?", env_has_value, 1); rb_define_global_const("ENV", envtbl); + + /* turn on premitive flag for the class */ + FL_SET(cHash, FL_PRIMITIVE); } diff --git a/io.c b/io.c index d3cbcfc56e..7ab24b9900 100644 --- a/io.c +++ b/io.c @@ -149,6 +149,7 @@ io_write(io, str) if (RSTRING(str)->len == 0) return INT2FIX(0); if (BUILTIN_TYPE(io) != T_FILE) { + /* port is not IO, call write method for it. */ return rb_funcall(io, id_write, 1, str); } @@ -2318,7 +2319,6 @@ Init_IO() rb_define_global_function("printf", f_printf, -1); rb_define_global_function("print", f_print, -1); rb_define_global_function("putc", f_putc, 1); - rb_define_global_function("putchar", f_putc, 1); rb_define_global_function("puts", f_puts, -1); rb_define_global_function("gets", f_gets_method, -1); rb_define_global_function("readline", f_readline, -1); @@ -2453,9 +2453,12 @@ Init_IO() rb_global_variable(&file); rb_define_virtual_variable("$-i", opt_i_get, opt_i_set); - Init_File(); #if defined (NT) || defined(DJGPP) || defined(__CYGWIN32__) || defined(__human68k__) atexit(pipe_atexit); #endif + + /* turn on premitive flag for the class */ + FL_SET(cIO, FL_PRIMITIVE); + Init_File(); } diff --git a/lib/jcode.rb b/lib/jcode.rb index 40ab48ddac..34d3ebb453 100644 --- a/lib/jcode.rb +++ b/lib/jcode.rb @@ -31,6 +31,7 @@ class String original_succ end end + alias next succ def upto(to) return if self > to diff --git a/lib/mathn.rb b/lib/mathn.rb index b5cc9b818b..265ef1337f 100644 --- a/lib/mathn.rb +++ b/lib/mathn.rb @@ -1,8 +1,8 @@ # # mathn.rb - # $Release Version: 0.5 $ -# $Revision: 1.1.1.1 $ -# $Date: 1998/01/16 04:05:49 $ +# $Revision: 1.1.1.1.4.1 $ +# $Date: 1998/01/16 12:36:05 $ # by Keiju ISHITSUKA(SHL Japan Inc.) # # -- @@ -96,6 +96,7 @@ class Prime @counts.push @seed + @seed return @seed end + alias next succ def each loop do diff --git a/node.h b/node.h index f55ea0f557..9c29fac7f3 100644 --- a/node.h +++ b/node.h @@ -77,6 +77,8 @@ enum node_type { NODE_DREGX, NODE_DREGX_ONCE, NODE_ARGS, + NODE_BLOCK_ARG, + NODE_BLOCK_PASS, NODE_DEFN, NODE_DEFS, NODE_ALIAS, @@ -275,6 +277,8 @@ typedef struct RNode { #define NEW_SUPER(a) node_newnode(NODE_SUPER,0,0,a) #define NEW_ZSUPER() node_newnode(NODE_ZSUPER,0,0,0) #define NEW_ARGS(f,o,r) node_newnode(NODE_ARGS,o,r,f) +#define NEW_BLOCK_ARG(v) node_newnode(NODE_BLOCK_ARG,v,0,local_cnt(v)) +#define NEW_BLOCK_PASS(b) node_newnode(NODE_BLOCK_PASS,0,b,0) #define NEW_ALIAS(n,o) node_newnode(NODE_ALIAS,0,n,o) #define NEW_VALIAS(n,o) node_newnode(NODE_VALIAS,0,n,o) #define NEW_UNDEF(i) node_newnode(NODE_UNDEF,0,i,0) diff --git a/numeric.c b/numeric.c index e61f15d7c3..7e69386dfd 100644 --- a/numeric.c +++ b/numeric.c @@ -1097,6 +1097,7 @@ Init_Numeric() cInteger = rb_define_class("Integer", cNumeric); rb_define_method(cInteger, "integer?", int_int_p, 0); rb_define_method(cInteger, "succ", int_succ, 0); + rb_define_method(cInteger, "next", int_succ, 0); cFixnum = rb_define_class("Fixnum", cInteger); @@ -1137,12 +1138,14 @@ Init_Numeric() rb_define_method(cFixnum, "to_f", fix_to_f, 0); rb_define_method(cFixnum, "succ", fix_succ, 0); + rb_define_method(cFixnum, "next", fix_succ, 0); rb_define_method(cFixnum, "size", fix_size, 0); rb_define_method(cFixnum, "upto", fix_upto, 1); rb_define_method(cFixnum, "downto", fix_downto, 1); rb_define_method(cFixnum, "step", fix_step, 2); rb_define_method(cFixnum, "times", fix_dotimes, 0); + FL_SET(cFixnum, FL_PRIMITIVE); cFloat = rb_define_class("Float", cNumeric); @@ -1164,4 +1167,5 @@ Init_Numeric() rb_define_method(cFloat, "to_i", flo_to_i, 0); rb_define_method(cFloat, "to_f", flo_to_f, 0); rb_define_method(cFloat, "abs", flo_abs, 0); + FL_SET(cFloat, FL_PRIMITIVE); } diff --git a/object.c b/object.c index 9be43985e5..d23264d9c0 100644 --- a/object.c +++ b/object.c @@ -369,11 +369,16 @@ VALUE obj_alloc(klass) VALUE klass; { - NEWOBJ(obj, struct RObject); - OBJSETUP(obj, klass, T_OBJECT); - obj->iv_tbl = 0; + if (FL_TEST(klass, FL_PRIMITIVE)) { + TypeError("allocating normal object for primitive class"); + } + else { + NEWOBJ(obj, struct RObject); + OBJSETUP(obj, klass, T_OBJECT); + obj->iv_tbl = 0; - return (VALUE)obj; + return (VALUE)obj; + } } static VALUE @@ -820,6 +825,9 @@ Init_Object() rb_include_module(cObject, mKernel); rb_define_private_method(cClass, "inherited", obj_dummy, 1); + FL_SET(cModule, FL_PRIMITIVE); + FL_SET(cClass, FL_PRIMITIVE); + /* * Ruby's Class Hierarchy Chart * @@ -891,6 +899,7 @@ Init_Object() rb_define_method(cNilClass, "nil?", rb_true, 0); rb_undef_method(CLASS_OF(cNilClass), "new"); rb_define_global_const("NIL", Qnil); + FL_SET(cNilClass, FL_PRIMITIVE); /* default addition */ rb_define_method(cNilClass, "+", nil_plus, 1); @@ -934,6 +943,7 @@ Init_Object() rb_define_singleton_method(cClass, "new", class_s_new, -1); cData = rb_define_class("Data", cObject); + rb_undef_method(CLASS_OF(cData), "new"); TopSelf = obj_alloc(cObject); rb_global_variable(&TopSelf); @@ -945,6 +955,7 @@ Init_Object() rb_define_method(cTrueClass, "type", true_type, 0); rb_undef_method(CLASS_OF(cTrueClass), "new"); rb_define_global_const("TRUE", TRUE); + FL_SET(cTrueClass, FL_PRIMITIVE); cFalseClass = rb_define_class("FalseClass", cObject); rb_define_method(cFalseClass, "to_s", false_to_s, 0); @@ -952,6 +963,7 @@ Init_Object() rb_define_method(cFalseClass, "type", false_type, 0); rb_undef_method(CLASS_OF(cFalseClass), "new"); rb_define_global_const("FALSE", FALSE); + FL_SET(cFalseClass, FL_PRIMITIVE); eq = rb_intern("=="); eql = rb_intern("eql?"); diff --git a/parse.y b/parse.y index e9f0a51e26..e3d9cbafdf 100644 --- a/parse.y +++ b/parse.y @@ -81,6 +81,10 @@ static NODE *arg_add(); static NODE *call_op(); static int in_defined = 0; +static NODE *arg_blk_pass(); +static NODE *new_call(); +static NODE *new_fcall(); + static NODE *gettable(); static NODE *assignable(); static NODE *aryset(); @@ -169,14 +173,16 @@ static void top_local_setup(); %type singleton %type literal numeric %type compstmt stmts stmt expr arg primary command_call method_call -%type if_tail opt_else case_body cases rescue ensure iterator -%type call_args call_args0 ret_args args mrhs opt_list var_ref -%type superclass f_arglist f_args f_optarg f_opt +%type if_tail opt_else case_body cases rescue ensure +%type opt_call_args call_args ret_args args +%type aref_args opt_block_arg block_arg +%type mrhs opt_list superclass iterator var_ref +%type f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg %type array assoc_list assocs assoc undef_list %type iter_var opt_iter_var iter_block iter_do_block %type mlhs mlhs_head mlhs_tail lhs backref -%type variable symbol operation assoc_kw -%type cname fname op rest_arg +%type variable symbol operation +%type cname fname op f_rest_arg %type f_arg %token UPLUS /* unary+ */ %token UMINUS /* unary- */ @@ -196,11 +202,11 @@ static void top_local_setup(); %token COLON3 /* :: at EXPR_BEG */ %token OP_ASGN /* +=, -= etc. */ %token ASSOC /* => */ -%token KW_ASSOC /* -> */ %token LPAREN /* ( */ %token LBRACK /* [ */ %token LBRACE /* { */ %token STAR /* * */ +%token AMPER /* & */ %token SYMBEG /* @@ -265,6 +271,9 @@ stmts : /* none */ stmt : iterator iter_do_block { + if ($1 && nd_type($1) == NODE_BLOCK_PASS) { + Error("both block arg and actual block given"); + } $2->nd_iter = $1; $$ = $2; fixpos($$, $2); @@ -396,24 +405,24 @@ expr : mlhs '=' mrhs } | arg -command_call : operation call_args0 +command_call : operation call_args { - $$ = NEW_FCALL($1, $2); + $$ = new_fcall($1, $2); fixpos($$, $2); } - | primary '.' operation call_args0 + | primary '.' operation call_args { value_expr($1); - $$ = NEW_CALL($1, $3, $4); + $$ = new_call($1, $3, $4); fixpos($$, $1); } - | primary COLON2 operation call_args0 + | primary COLON2 operation call_args { value_expr($1); - $$ = NEW_CALL($1, $3, $4); + $$ = new_call($1, $3, $4); fixpos($$, $1); } - | kSUPER call_args0 + | kSUPER call_args { if (!cur_mid && !in_single && !in_defined) yyerror("super called outside of method"); @@ -457,7 +466,7 @@ lhs : variable { $$ = assignable($1, 0); } - | primary '[' call_args ']' + | primary '[' aref_args ']' { $$ = aryset($1, $3, 0); } @@ -542,7 +551,7 @@ arg : variable '=' arg $$ = assignable($1, $3); fixpos($$, $3); } - | primary '[' call_args ']' '=' arg + | primary '[' aref_args ']' '=' arg { $$ = aryset($1, $3, $6); fixpos($$, $1); @@ -566,7 +575,7 @@ arg : variable '=' arg $$ = assignable($1, call_op(gettable($1), $2, 1, $3)); fixpos($$, $3); } - | primary '[' call_args ']' OP_ASGN arg + | primary '[' aref_args ']' OP_ASGN arg { NODE *args = NEW_LIST($6); @@ -723,51 +732,81 @@ arg : variable '=' arg $$ = $1; } -call_args : /* none */ +aref_args : opt_call_args + { + if ($1 && nd_type($1) == NODE_BLOCK_PASS) { + Error("block argument should not be given"); + } + $$ = $1; + } + +opt_call_args : /* none */ { $$ = 0; } - | call_args0 opt_nl + | call_args opt_nl -call_args0 : command_call +call_args : command_call { value_expr($1); $$ = NEW_LIST($1); } - | args - | args ',' STAR arg + | args opt_block_arg + { + $$ = arg_blk_pass($1, $2); + } + | args ',' STAR arg opt_block_arg { $$ = arg_add($1, $4); + $$ = arg_blk_pass($$, $5); } - | assocs + | assocs opt_block_arg { $$ = NEW_LIST(NEW_HASH($1)); + $$ = arg_blk_pass($$, $2); } - | assocs ',' STAR arg + | assocs ',' STAR arg opt_block_arg { - $$ = NEW_LIST(NEW_HASH($1)); - $$ = arg_add($$, $4); + $$ = arg_add(NEW_LIST(NEW_HASH($1)), $4); + $$ = arg_blk_pass($$, $5); } - | args ',' assocs + | args ',' assocs opt_block_arg { $$ = list_append($1, NEW_HASH($3)); + $$ = arg_blk_pass($$, $4); } - | args ',' assocs ',' STAR arg + | args ',' assocs ',' STAR arg opt_block_arg { - $$ = list_append($1, NEW_HASH($3)); - $$ = arg_add($$, $6); + $$ = arg_add(list_append($1, NEW_HASH($3)), $6); + $$ = arg_blk_pass($$, $7); } - | STAR arg + | STAR arg opt_block_arg + { + value_expr($2); + $$ = arg_blk_pass($2, $3); + } + | block_arg + +block_arg : AMPER arg { value_expr($2); + $$ = NEW_BLOCK_PASS($2); + } + +opt_block_arg : ',' block_arg + { $$ = $2; } + | /* none */ + { + $$ = 0; + } -opt_list : /* none */ +opt_list : args + | /* none */ { $$ = 0; } - | args args : arg { @@ -801,15 +840,17 @@ mrhs : args $$ = $2; } -ret_args : call_args0 +ret_args : call_args { - if ($1 && - nd_type($1) == NODE_ARRAY && - $1->nd_next == 0) { - $$ = $1->nd_head; - } - else { - $$ = $1; + $$ = $1; + if ($1) { + if (nd_type($1) == NODE_ARRAY && + $1->nd_next == 0) { + $$ = $1->nd_head; + } + else if (nd_type($1) == NODE_BLOCK_PASS) { + Error("block argument should not be given"); + } } } @@ -845,7 +886,7 @@ primary : literal | DREGEXP | var_ref | backref - | primary '[' call_args ']' + | primary '[' aref_args ']' { value_expr($1); $$ = NEW_CALL($1, AREF, $3); @@ -901,7 +942,7 @@ primary : literal } | FID { - $$ = NEW_FCALL($1, 0); + $$ = NEW_VCALL($1); } | operation iter_block { @@ -911,6 +952,9 @@ primary : literal | method_call | method_call iter_block { + if ($1 && nd_type($1) == NODE_BLOCK_PASS) { + Error("both block arg and actual block given"); + } $2->nd_iter = $1; $$ = $2; fixpos($$, $1); @@ -1158,42 +1202,42 @@ iter_block : '{' iterator : IDENTIFIER { - $$ = NEW_FCALL($1, 0); + $$ = NEW_VCALL($1); } | CONSTANT { - $$ = NEW_FCALL($1, 0); + $$ = NEW_VCALL($1); } | FID { - $$ = NEW_FCALL($1, 0); + $$ = NEW_VCALL($1); } | method_call | command_call -method_call : operation '(' call_args ')' +method_call : operation '(' opt_call_args ')' { - $$ = NEW_FCALL($1, $3); + $$ = new_fcall($1, $3); fixpos($$, $3); } - | primary '.' operation '(' call_args ')' + | primary '.' operation '(' opt_call_args ')' { value_expr($1); - $$ = NEW_CALL($1, $3, $5); + $$ = new_call($1, $3, $5); fixpos($$, $1); } | primary '.' operation { value_expr($1); - $$ = NEW_CALL($1, $3, 0); + $$ = new_call($1, $3, 0); } - | primary COLON2 operation '(' call_args ')' + | primary COLON2 operation '(' opt_call_args ')' { value_expr($1); - $$ = NEW_CALL($1, $3, $5); + $$ = new_call($1, $3, $5); fixpos($$, $1); } - | kSUPER '(' call_args ')' + | kSUPER '(' opt_call_args ')' { if (!cur_mid && !in_single && !in_defined) yyerror("super called outside of method"); @@ -1295,37 +1339,41 @@ f_arglist : '(' f_args ')' $$ = $1; } -f_args : /* no arg */ +f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg { - $$ = NEW_ARGS(0, 0, -1); + $$ = block_append(NEW_ARGS($1, $3, $5), $6); } - | f_arg + | f_arg ',' f_optarg opt_f_block_arg { - $$ = NEW_ARGS($1, 0, -1); + $$ = block_append(NEW_ARGS($1, $3, -1), $4); } - | f_arg ',' rest_arg + | f_arg ',' f_rest_arg opt_f_block_arg { - $$ = NEW_ARGS($1, 0, $3); + $$ = block_append(NEW_ARGS($1, 0, $3), $4); } - | f_arg ',' f_optarg + | f_arg opt_f_block_arg { - $$ = NEW_ARGS($1, $3, -1); + $$ = block_append(NEW_ARGS($1, 0, -1), $2); } - | f_arg ',' f_optarg ',' rest_arg + | f_optarg ',' f_rest_arg opt_f_block_arg { - $$ = NEW_ARGS($1, $3, $5); + $$ = block_append(NEW_ARGS(0, $1, $3), $4); } - | f_optarg + | f_optarg opt_f_block_arg { - $$ = NEW_ARGS(0, $1, -1); + $$ = block_append(NEW_ARGS(0, $1, -1), $2); } - | f_optarg ',' rest_arg + | f_rest_arg opt_f_block_arg { - $$ = NEW_ARGS(0, $1, $3); + $$ = block_append(NEW_ARGS(0, 0, $1), $2); } - | rest_arg + | f_block_arg { - $$ = NEW_ARGS(0, 0, $1); + $$ = block_append(NEW_ARGS(0, 0, -1), $1); + } + | /* none */ + { + $$ = NEW_ARGS(0, 0, -1); } f_arg : IDENTIFIER @@ -1360,13 +1408,27 @@ f_optarg : f_opt $$ = block_append($1, $3); } -rest_arg : STAR IDENTIFIER +f_rest_arg : STAR IDENTIFIER { if (!is_local_id($2)) yyerror("rest argument must be local variable"); $$ = local_cnt($2); } +f_block_arg : AMPER IDENTIFIER + { + $$ = NEW_BLOCK_ARG($2); + } + +opt_f_block_arg : ',' f_block_arg + { + $$ = $2; + } + | /* none */ + { + $$ = 0; + } + singleton : var_ref { if (nd_type($1) == NODE_SELF) { @@ -1424,13 +1486,6 @@ assoc : arg ASSOC arg { $$ = list_append(NEW_LIST($1), $3); } - | assoc_kw KW_ASSOC arg - { - $$ = list_append(NEW_LIST(NEW_STR(str_new2(rb_id2name($1)))), $3); - } - -assoc_kw : IDENTIFIER - | CONSTANT operation : IDENTIFIER | CONSTANT @@ -2226,6 +2281,7 @@ retry: return STAR; } if (lex_state == EXPR_BEG || lex_state == EXPR_MID) { + lex_state = EXPR_BEG; return STAR; } lex_state = EXPR_BEG; @@ -2364,15 +2420,26 @@ retry: return INTEGER; case '&': - lex_state = EXPR_BEG; if ((c = nextc()) == '&') { + lex_state = EXPR_BEG; return ANDOP; } else if (c == '=') { yylval.id = '&'; + lex_state = EXPR_BEG; return OP_ASGN; } pushback(c); + if (lex_state == EXPR_ARG && space_seen && !isspace(c)){ + arg_ambiguous(); + lex_state = EXPR_BEG; + return AMPER; + } + if (lex_state == EXPR_BEG || lex_state == EXPR_MID) { + lex_state = EXPR_BEG; + return AMPER; + } + lex_state = EXPR_BEG; return '&'; case '|': @@ -2435,11 +2502,6 @@ retry: yylval.id = '-'; return OP_ASGN; } - if (c == '>') { - Warning("-> is undocumented feature ^^;;;"); - lex_state = EXPR_BEG; - return KW_ASSOC; - } if (lex_state == EXPR_ARG) { if (space_seen && !isspace(c)) { arg_ambiguous(); @@ -3587,6 +3649,43 @@ logop(type, left, right) return node_newnode(type, cond(left), cond(right)); } +static NODE * +arg_blk_pass(node1, node2) + NODE *node1; + NODE *node2; +{ + if (node2) { + node2->nd_head = node1; + return node2; + } + return node1; +} + +static NODE* +new_call(r,m,a) + NODE *r; + ID m; + NODE *a; +{ + if (a && nd_type(a) == NODE_BLOCK_PASS) { + a->nd_iter = NEW_CALL(r,m,a->nd_head); + return a; + } + return NEW_CALL(r,m,a); +} + +static NODE* +new_fcall(m,a) + ID m; + NODE *a; +{ + if (a && nd_type(a) == NODE_BLOCK_PASS) { + a->nd_iter = NEW_FCALL(m,a->nd_head); + return a; + } + return NEW_FCALL(m,a); +} + st_table *new_idhash(); static struct local_vars { diff --git a/re.c b/re.c index a7b6d69f42..5f2b981c68 100644 --- a/re.c +++ b/re.c @@ -1090,6 +1090,9 @@ Init_Regexp() rb_global_variable(®_cache); rb_global_variable(&matchcache); + /* turn on premitive flag for the class */ + FL_SET(cRegexp, FL_PRIMITIVE); + cMatch = rb_define_class("MatchingData", cData); rb_define_method(cMatch, "to_a", match_to_a, 0); rb_define_method(cMatch, "[]", match_aref, -1); diff --git a/ruby.h b/ruby.h index 9f8ede3e13..f9bb2585f3 100644 --- a/ruby.h +++ b/ruby.h @@ -295,6 +295,7 @@ struct RBignum { #define RFILE(obj) (R_CAST(RFile)(obj)) #define FL_SINGLETON FL_USER0 +#define FL_PRIMITIVE FL_USER1 #define FL_MARK (1<<8) #define FL_FINALIZE (1<<9) diff --git a/string.c b/string.c index 42666eefab..2b6295cfbc 100644 --- a/string.c +++ b/string.c @@ -2423,6 +2423,8 @@ Init_String() rb_define_method(cString, "~", str_match2, 0); rb_define_method(cString, "succ", str_succ, 0); rb_define_method(cString, "succ!", str_succ_bang, 0); + rb_define_method(cString, "next", str_succ, 0); + rb_define_method(cString, "next!", str_succ_bang, 0); rb_define_method(cString, "upto", str_upto, 1); rb_define_method(cString, "index", str_index_method, -1); rb_define_method(cString, "rindex", str_rindex, -1); @@ -2510,4 +2512,7 @@ Init_String() rb_define_global_function("split", f_split, -1); pr_str = rb_intern("to_s"); + + /* turn on premitive flag for the class */ + FL_SET(cString, FL_PRIMITIVE); } diff --git a/struct.c b/struct.c index 1819c3c1dc..9fcee02ab9 100644 --- a/struct.c +++ b/struct.c @@ -149,6 +149,7 @@ make_struct(name, member) } rb_define_method_id(nstr, id_attrset(id), struct_set, 1); } + FL_SET(nstr, FL_PRIMITIVE); return nstr; } @@ -429,4 +430,5 @@ Init_Struct() rb_define_method(cStruct, "[]=", struct_aset, 2); rb_define_method(cStruct, "members", struct_members, 0); + FL_SET(cStruct, FL_PRIMITIVE); } -- cgit v1.2.3