summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog16
-rw-r--r--array.c3
-rw-r--r--bignum.c2
-rw-r--r--class.c3
-rw-r--r--error.c6
-rw-r--r--eval.c158
-rw-r--r--ext/gtk/gtk.c2
-rw-r--r--gc.c5
-rw-r--r--hash.c3
-rw-r--r--io.c7
-rw-r--r--lib/jcode.rb1
-rw-r--r--lib/mathn.rb5
-rw-r--r--node.h4
-rw-r--r--numeric.c4
-rw-r--r--object.c20
-rw-r--r--parse.y265
-rw-r--r--re.c3
-rw-r--r--ruby.h1
-rw-r--r--string.c5
-rw-r--r--struct.c2
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 <matz@netlab.co.jp>
+
+ * eval.c (f_missing): use any_to_s() for stringify.
+
+Wed Mar 4 01:39:52 1998 Yukihiro Matsumoto <matz@netlab.co.jp>
+
+ * 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 <matz@netlab.co.jp>
* 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 <varargs.h>
@@ -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 <node> singleton
%type <val> literal numeric
%type <node> compstmt stmts stmt expr arg primary command_call method_call
-%type <node> if_tail opt_else case_body cases rescue ensure iterator
-%type <node> call_args call_args0 ret_args args mrhs opt_list var_ref
-%type <node> superclass f_arglist f_args f_optarg f_opt
+%type <node> if_tail opt_else case_body cases rescue ensure
+%type <node> opt_call_args call_args ret_args args
+%type <node> aref_args opt_block_arg block_arg
+%type <node> mrhs opt_list superclass iterator var_ref
+%type <node> f_arglist f_args f_optarg f_opt f_block_arg opt_f_block_arg
%type <node> array assoc_list assocs assoc undef_list
%type <node> iter_var opt_iter_var iter_block iter_do_block
%type <node> mlhs mlhs_head mlhs_tail lhs backref
-%type <id> variable symbol operation assoc_kw
-%type <id> cname fname op rest_arg
+%type <id> variable symbol operation
+%type <id> cname fname op f_rest_arg
%type <num> f_arg
%token UPLUS /* unary+ */
%token UMINUS /* unary- */
@@ -196,11 +202,11 @@ static void top_local_setup();
%token COLON3 /* :: at EXPR_BEG */
%token <id> 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(&reg_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);
}