From 369124b0ec6aa0d58ea628339713444c559bfa5f Mon Sep 17 00:00:00 2001 From: matz Date: Tue, 3 Mar 1998 10:16:14 +0000 Subject: shugo's method etc. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/v1_1r@106 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 14 +++ eval.c | 239 ++++++++++++++++++++++++++++++++++++++++------------ ext/curses/curses.c | 22 ++--- io.c | 33 ++++++++ node.h | 2 +- regex.h | 22 ++++- ruby.h | 15 ++-- string.c | 2 +- 8 files changed, 271 insertions(+), 78 deletions(-) diff --git a/ChangeLog b/ChangeLog index cffc1c7b12..ba907f86ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,19 @@ +Tue Mar 3 14:20:15 1998 Yukihiro Matsumoto + + * eval.c (obj_method): returns bound method object. + + * eval.c (rb_call): argument check for empty methods. + + * ruby.h (NUM2CHR): new macro, originally from curses module. + +Tue Mar 3 13:03:35 1998 MAEDA shugo + + * io.c (io_putc): new method. + Tue Mar 3 11:21:28 1998 Yukihiro Matsumoto + * string.c (str_inspect): more strict charcode detection. + * eval.c (thread_stop): stopping only thread raises ThreadError exception. diff --git a/eval.c b/eval.c index bc928bb715..5eca27a224 100644 --- a/eval.c +++ b/eval.c @@ -3051,39 +3051,19 @@ stack_length() } static VALUE -rb_call(klass, recv, mid, argc, argv, scope) +rb_call0(klass, recv, mid, id, argc, argv, scope, body, type) VALUE klass, recv; - ID mid; + ID mid, id; int argc; /* OK */ VALUE *argv; /* OK */ int scope; + NODE *body; + enum node_type type; { - NODE *body, *b2; /* OK */ - int noex; - ID id = mid; - struct cache_entry *ent; + NODE *b2; /* OK */ volatile VALUE result = Qnil; int itr; - enum node_type type; static int tick; - TMP_PROTECT; - - again: - /* is it in the method cache? */ - ent = cache + EXPR1(klass, mid); - if (ent->mid == mid && ent->klass == klass) { - klass = ent->origin; - id = ent->mid0; - noex = ent->noex; - body = ent->method; - } - else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) { - return rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0); - } - - /* receiver specified form for private method */ - if (noex == NOEX_PRIVATE && scope == 0) - return rb_undefined(recv, mid, argc, argv, CSTAT_NOEX); switch (the_iter->iter) { case ITER_PRE: @@ -3095,28 +3075,6 @@ rb_call(klass, recv, mid, argc, argv, scope) break; } - type = nd_type(body); - if (type == NODE_ZSUPER) { - /* for re-scoped/renamed method */ - mid = id; - if (scope == 0) scope = 1; - if (RCLASS(klass)->super == 0) { - /* 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; - } - } - else { - klass = RCLASS(klass)->super; - } - goto again; - } - if ((++tick & 0xfff) == 0 && stack_length() > STACK_LEVEL_MAX) Fatal("stack level too deep"); @@ -3271,15 +3229,22 @@ rb_call(klass, recv, mid, argc, argv, scope) PUSH_VARS(); if ((state = EXEC_TAG()) == 0) { - if (nd_type(body) == NODE_BLOCK) { - NODE *node = body->nd_head; - int i; + NODE *node = 0; + int i; + if (nd_type(body) == NODE_ARGS) { + node = body; + body = 0; + } + else if (nd_type(body) == NODE_BLOCK) { + node = body->nd_head; + body = body->nd_next; + } + if (node) { if (nd_type(node) != NODE_ARGS) { Bug("no argument-node"); } - body = body->nd_next; i = node->nd_cnt; if (i > argc) { ArgError("Wrong # of arguments(%d for %d)", argc, i); @@ -3321,9 +3286,7 @@ rb_call(klass, recv, mid, argc, argv, scope) } } } - else if (nd_type(body) == NODE_ARGS) { - body = 0; - } + if (trace_func) { call_trace_func("call", b2->nd_file, nd_line(b2), recv, the_frame->last_func); @@ -3373,6 +3336,61 @@ rb_call(klass, recv, mid, argc, argv, scope) return result; } +static VALUE +rb_call(klass, recv, mid, argc, argv, scope) + VALUE klass, recv; + ID mid; + int argc; /* OK */ + VALUE *argv; /* OK */ + int scope; +{ + NODE *body; /* OK */ + 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) { + klass = ent->origin; + id = ent->mid0; + noex = ent->noex; + body = ent->method; + } + else if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) { + return rb_undefined(recv, mid, argc, argv, scope==2?CSTAT_VCALL:0); + } + + /* receiver specified form for private method */ + 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); +} + VALUE rb_apply(recv, mid, args) VALUE recv; @@ -4682,6 +4700,113 @@ proc_iterate(proc) return result; } +static VALUE cMethod; +struct METHOD { + VALUE klass; + VALUE recv; + ID id; + NODE *body; +}; + +static void +bm_mark(struct METHOD *data) +{ + gc_mark(data->klass); + gc_mark(data->recv); + gc_mark(data->body); +} + +static VALUE +obj_method(obj, vid) + VALUE obj; + VALUE vid; +{ + VALUE method; + VALUE klass = CLASS_OF(obj); + ID mid, id; + NODE *body; + int noex; + enum node_type type; + struct METHOD *data; + + mid = id = rb_to_id(vid); + + again: + if ((body = rb_get_method_body(&klass, &id, &noex)) == 0) { + return rb_undefined(obj, mid, 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; + } + } + 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; + + return method; +} + +static VALUE +method_call(argc, argv, method) + int argc; + VALUE *argv; + VALUE method; +{ + VALUE result; + struct METHOD *data; + + 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)); + POP_ITER(); + return result; +} + +static VALUE +method_inspect(method) + VALUE method; +{ + struct METHOD *data; + VALUE str; + char *s; + + Data_Get_Struct(method, struct METHOD, data); + str = str_new2("#<"); + s = rb_class2name(CLASS_OF(method)); + str_cat(str, s, strlen(s)); + str_cat(str, ": ", 2); + s = rb_class2name(data->klass); + str_cat(str, s, strlen(s)); + str_cat(str, "#", 1); + s = rb_id2name(data->id); + str_cat(str, s, strlen(s)); + str_cat(str, ">", 1); + + return str; +} + void Init_Proc() { @@ -4695,6 +4820,12 @@ Init_Proc() rb_define_global_function("proc", f_lambda, 0); rb_define_global_function("lambda", f_lambda, 0); rb_define_global_function("binding", f_binding, 0); + + 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(mKernel, "method", obj_method, 1); } #ifdef THREAD diff --git a/ext/curses/curses.c b/ext/curses/curses.c index 9984b50380..0230636c50 100644 --- a/ext/curses/curses.c +++ b/ext/curses/curses.c @@ -32,10 +32,6 @@ struct windata { WINDOW *window; }; -#define NUM2CHAR(x) ((TYPE(x) == T_STRING)&&(RSTRING(x)->len>=1))?\ - RSTRING(x)->ptr[0]:(char)NUM2INT(x) -#define CHAR2FIX(x) INT2FIX((int)x) - static void no_window() { @@ -288,7 +284,7 @@ static VALUE curses_inch(obj) VALUE obj; { - return CHAR2FIX(inch()); + return CHR2FIX(inch()); } /* def addch(ch) */ @@ -297,7 +293,7 @@ curses_addch(obj, ch) VALUE obj; VALUE ch; { - addch(NUM2CHAR(ch)); + addch(NUM2CHR(ch)); return Qnil; } @@ -307,7 +303,7 @@ curses_insch(obj, ch) VALUE obj; VALUE ch; { - insch(NUM2CHAR(ch)); + insch(NUM2CHR(ch)); return Qnil; } @@ -326,7 +322,7 @@ static VALUE curses_getch(obj) VALUE obj; { - return CHAR2FIX(getch()); + return CHR2FIX(getch()); } /* def getstr */ @@ -454,7 +450,7 @@ window_box(obj, vert, hor) struct windata *winp; GetWINDOW(obj, winp); - box(winp->window, NUM2CHAR(vert), NUM2CHAR(hor)); + box(winp->window, NUM2CHR(vert), NUM2CHR(hor)); return Qnil; } @@ -623,7 +619,7 @@ window_inch(obj) struct windata *winp; GetWINDOW(obj, winp); - return CHAR2FIX(winch(winp->window)); + return CHR2FIX(winch(winp->window)); } /* def addch(ch) */ @@ -635,7 +631,7 @@ window_addch(obj, ch) struct windata *winp; GetWINDOW(obj, winp); - waddch(winp->window, NUM2CHAR(ch)); + waddch(winp->window, NUM2CHR(ch)); return Qnil; } @@ -649,7 +645,7 @@ window_insch(obj, ch) struct windata *winp; GetWINDOW(obj, winp); - winsch(winp->window, NUM2CHAR(ch)); + winsch(winp->window, NUM2CHR(ch)); return Qnil; } @@ -686,7 +682,7 @@ window_getch(obj) struct windata *winp; GetWINDOW(obj, winp); - return CHAR2FIX(wgetch(winp->window)); + return CHR2FIX(wgetch(winp->window)); } /* def getstr */ diff --git a/io.c b/io.c index d5b10ee141..d3cbcfc56e 100644 --- a/io.c +++ b/io.c @@ -1313,6 +1313,35 @@ f_print(argc, argv) return Qnil; } +static VALUE +io_putc(io, ch) + VALUE io, ch; +{ + OpenFile *fptr; + FILE *f; + int c = NUM2CHR(ch); + + rb_secure(4); + GetOpenFile(io, fptr); + io_writable(fptr); + + f = GetWriteFile(fptr); + + if (fputc(c, f) == EOF || ferror(f)) + rb_sys_fail(fptr->path); + if (fptr->mode & FMODE_SYNC) + fflush(f); + + return ch; +} + +static VALUE +f_putc(recv, ch) + VALUE recv, ch; +{ + return io_putc(rb_defout, ch); +} + static VALUE io_puts(argc, argv, out) int argc; @@ -2275,6 +2304,7 @@ opt_i_set(val) void Init_IO() { + extern VALUE mKernel; extern VALUE mEnumerable; extern VALUE eException; @@ -2287,6 +2317,8 @@ Init_IO() rb_define_global_function("open", f_open, -1); 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); @@ -2331,6 +2363,7 @@ Init_IO() rb_define_method(cIO, "reopen", io_reopen, 1); rb_define_method(cIO, "print", io_print, -1); + rb_define_method(cIO, "putc", io_putc, 1); rb_define_method(cIO, "puts", io_puts, -1); rb_define_method(cIO, "printf", io_printf, -1); diff --git a/node.h b/node.h index eb94ceb39d..f55ea0f557 100644 --- a/node.h +++ b/node.h @@ -135,7 +135,7 @@ typedef struct RNode { #define RNODE(obj) (R_CAST(RNode)(obj)) -#define nd_type(n) (((RNODE(n))->flags>>FL_USHIFT)&0x7f) +#define nd_type(n) (((RNODE(n))->flags>>FL_USHIFT)&0xff) #define nd_set_type(n,t) \ RNODE(n)->flags=((RNODE(n)->flags&~FL_UMASK)|(((t)<= 0x80) \ - : (re_syntax_options & RE_MBCTYPE_SJIS \ - ? (( 0x80 <= (unsigned char) (c) \ + ? ( 0xa1 <= (unsigned char) (c) \ + && (unsigned char) (c) <= 0xfe) \ + : (re_syntax_options & RE_MBCTYPE_SJIS \ + ? (( 0x81 <= (unsigned char) (c) \ && (unsigned char) (c) <= 0x9f) \ - || (0xe0 <= (unsigned char) (c))) \ + || ((0xe0 <= (unsigned char) (c)) \ + && (unsigned char) (c) <= 0xef)) \ + : 0)) + +#undef ismbchar2 +#define ismbchar2(c) \ + (re_syntax_options & RE_MBCTYPE_EUC \ + ? ( 0xa1 <= (unsigned char) (c) \ + && (unsigned char) (c) <= 0xfe) \ + : (re_syntax_options & RE_MBCTYPE_SJIS \ + ? (( 0x40 <= (unsigned char) (c) \ + && (unsigned char) (c) <= 0x7e) \ + || ((0x80 <= (unsigned char) (c)) \ + && (unsigned char) (c) <= 0xfc)) \ : 0)) /* This data structure is used to represent a compiled pattern. */ diff --git a/ruby.h b/ruby.h index 97c751086a..9f8ede3e13 100644 --- a/ruby.h +++ b/ruby.h @@ -172,6 +172,10 @@ double num2dbl _((VALUE)); char *str2cstr _((VALUE)); #define STR2CSTR(x) str2cstr((VALUE)(x)) +#define NUM2CHR(x) (((TYPE(x) == T_STRING)&&(RSTRING(x)->len>=1))?\ + RSTRING(x)->ptr[0]:(char)NUM2INT(x)) +#define CHR2FIX(x) INT2FIX((int)x) + VALUE rb_newobj _((void)); #define NEWOBJ(obj,type) type *obj = (type*)rb_newobj() #define OBJSETUP(obj,c,t) {\ @@ -290,11 +294,11 @@ struct RBignum { #define RBIGNUM(obj) (R_CAST(RBignum)(obj)) #define RFILE(obj) (R_CAST(RFile)(obj)) -#define FL_SINGLETON (1<<8) -#define FL_MARK (1<<9) -#define FL_FINALIZE (1<<10) +#define FL_SINGLETON FL_USER0 +#define FL_MARK (1<<8) +#define FL_FINALIZE (1<<9) -#define FL_USHIFT 11 +#define FL_USHIFT 10 #define FL_USER0 (1<<(FL_USHIFT+0)) #define FL_USER1 (1<<(FL_USHIFT+1)) @@ -303,8 +307,9 @@ struct RBignum { #define FL_USER4 (1<<(FL_USHIFT+4)) #define FL_USER5 (1<<(FL_USHIFT+5)) #define FL_USER6 (1<<(FL_USHIFT+6)) +#define FL_USER7 (1<<(FL_USHIFT+7)) -#define FL_UMASK (0x7f<flags&(f)):0) diff --git a/string.c b/string.c index 5552e4f9d0..42666eefab 100644 --- a/string.c +++ b/string.c @@ -1375,7 +1375,7 @@ str_inspect(str) while (p < pend) { UCHAR c = *p++; - if (ismbchar(c) && p < pend) { + if (ismbchar(c) && p < pend && ismbchar2(*p)) { CHECK(2); *b++ = c; *b++ = *p++; -- cgit v1.2.3