1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

block arg etc.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/v1_1r@107 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
matz 1998-03-05 06:37:50 +00:00
parent 369124b0ec
commit f70ffbee21
20 changed files with 340 additions and 203 deletions

View file

@ -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.

View file

@ -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);
}

View file

@ -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);
}

View file

@ -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;
}

View file

@ -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;
}

158
eval.c
View file

@ -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);

View file

@ -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;

5
gc.c
View file

@ -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;

3
hash.c
View file

@ -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);
}

7
io.c
View file

@ -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();
}

View file

@ -31,6 +31,7 @@ class String
original_succ
end
end
alias next succ
def upto(to)
return if self > to

View file

@ -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

4
node.h
View file

@ -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)

View file

@ -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);
}

View file

@ -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?");

293
parse.y
View file

@ -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);
$$ = $2;
$$ = arg_blk_pass($2, $3);
}
| block_arg
block_arg : AMPER arg
{
value_expr($2);
$$ = NEW_BLOCK_PASS($2);
}
opt_list : /* none */
opt_block_arg : ',' block_arg
{
$$ = $2;
}
| /* none */
{
$$ = 0;
}
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,38 +1339,42 @@ f_arglist : '(' f_args ')'
$$ = $1;
}
f_args : /* no arg */
f_args : f_arg ',' f_optarg ',' f_rest_arg opt_f_block_arg
{
$$ = block_append(NEW_ARGS($1, $3, $5), $6);
}
| f_arg ',' f_optarg opt_f_block_arg
{
$$ = block_append(NEW_ARGS($1, $3, -1), $4);
}
| f_arg ',' f_rest_arg opt_f_block_arg
{
$$ = block_append(NEW_ARGS($1, 0, $3), $4);
}
| f_arg opt_f_block_arg
{
$$ = block_append(NEW_ARGS($1, 0, -1), $2);
}
| f_optarg ',' f_rest_arg opt_f_block_arg
{
$$ = block_append(NEW_ARGS(0, $1, $3), $4);
}
| f_optarg opt_f_block_arg
{
$$ = block_append(NEW_ARGS(0, $1, -1), $2);
}
| f_rest_arg opt_f_block_arg
{
$$ = block_append(NEW_ARGS(0, 0, $1), $2);
}
| f_block_arg
{
$$ = block_append(NEW_ARGS(0, 0, -1), $1);
}
| /* none */
{
$$ = NEW_ARGS(0, 0, -1);
}
| f_arg
{
$$ = NEW_ARGS($1, 0, -1);
}
| f_arg ',' rest_arg
{
$$ = NEW_ARGS($1, 0, $3);
}
| f_arg ',' f_optarg
{
$$ = NEW_ARGS($1, $3, -1);
}
| f_arg ',' f_optarg ',' rest_arg
{
$$ = NEW_ARGS($1, $3, $5);
}
| f_optarg
{
$$ = NEW_ARGS(0, $1, -1);
}
| f_optarg ',' rest_arg
{
$$ = NEW_ARGS(0, $1, $3);
}
| rest_arg
{
$$ = 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 {

3
re.c
View file

@ -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);

1
ruby.h
View file

@ -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)

View file

@ -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);
}

View file

@ -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);
}