diff options
author | Yukihiro Matsumoto <[email protected]> | 1995-02-01 19:48:24 +0900 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2019-08-17 22:09:31 +0900 |
commit | 897cf066952978ccbae1d57bbc14a03c7b98a1e1 (patch) | |
tree | bc83424954929dc9574e40a0aee874f45965a8ae /eval.c | |
parent | 5d828b25d4ae30a000c054a724ac248dadbb97b3 (diff) |
version 0.65v0_65
https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.65.tar.gz
Wed Feb 1 19:48:24 1995 Yukihiro Matsumoto (matz@ix-02)
* string.c(str_replace): 置き換える文字列の長さが等しい時メモリコ
ピーをしない.
* string.c(rindex): バグ修正.
Mon Jan 30 11:23:05 1995 Yukihiro Matsumoto (matz@ix-02)
* parse.y(value_expr): ifのチェックを追加.
* gc.c(gc_mark): free cellの扱いにバグ.
* parse.y: 文法の変更(よりシンプルに).例外を減らした.
Thu Jan 26 00:52:55 1995 Yukihiro Matsumoto (matz@dyna)
* parse.y: 引数として連想配列を置くことができるように.この場合,
連想配列リテラルが最終引数となる.
* parse.y: 配列参照の`[]'内が空でもよいことにした.
Tue Jan 24 14:45:15 1995 Yukihiro Matsumoto (matz@ix-02)
* class.c(rb_include_module): `-v'を指定した時にはincludeしたモジュー
ルとクラス定数が衝突していないかチェックする.
Mon Jan 23 10:42:09 1995 Yukihiro Matsumoto (matz@ix-02)
* parse.y(rb_class2name): メタクラスに関するbug fix.
* dict.c: Dict[..]で辞書の生成が出来るように.
* array.c: Array[..]で配列の生成が出来るように.
* parse.y: 辞書の表現として{a,b,..}という形式も許すように.
Fri Jan 20 10:28:38 1995 Yukihiro Matsumoto (matz@ix-02)
* re.c(Regexp.quote): 正規表現をエスケープするメソッド.
* 無駄なrb_intern()を減らした.
* parse.y: `!', `!=', `!~'を特殊演算子にする.よってこれらは再定義
できなくなった.
Wed Jan 18 13:20:41 1995 Yukihiro Matsumoto (matz@ix-02)
* parse.y: 文法の整理(unless,untilをなくした).
Tue Jan 17 11:11:27 1995 Yukihiro Matsumoto (matz@ix-02)
* eval.c: defでメソッド再定義時にはスーパークラスのメソッドの可視
性を継承する.最初の定義の時は今までと同じデフォルト(トップレベ
ルで関数的,クラス定義内で通常メソッド).
* object.c(Class::new): オブジェクトの生成時に関数的メ
ソッドinit_objectが必ず呼ばれるように変更.
* eval.c: 未定義のメソッドに対してunknownメソッドが呼ばれるように
なった.エラー表示が今までと同じになるようにenvを調節している.
Fri Jan 13 14:40:30 1995 Yukihiro Matsumoto (matz@ix-02)
* gc.c: gcを若干書き換えて整理した.が,あまり変化はなかったようだ.
* parse.y(yylex): symbolを\symから:symに変更した.
Thu Jan 12 01:39:28 1995 Yukihiro Matsumoto (matz@dyna)
* eval.c: 新規関数 rb_eval_string().
* gc.c: gc_mark()を一部非再帰化.
* variable.c(rb_ivar_{get,set}): インスタンス変数のアクセス周りで
チェックが足りなかった.
* variable.c: クラス定数とインスタンス変数でハッシュテーブルを共有
するようにした.
* ruby.h: iv_tblをRBasicからRObjectとRClassへ移動した.これにより,
ObjectとClass,Moduleしかインスタンス変数を持てなくなる.が,メモ
リ効率は若干向上する.
Diffstat (limited to 'eval.c')
-rw-r--r-- | eval.c | 257 |
1 files changed, 160 insertions, 97 deletions
@@ -3,7 +3,7 @@ eval.c - $Author: matz $ - $Date: 1995/01/10 10:42:34 $ + $Date: 1995/01/12 08:54:45 $ created at: Thu Jun 10 14:22:17 JST 1993 Copyright (C) 1994 Yukihiro Matsumoto @@ -52,7 +52,7 @@ search_method(class, id, origin) if (class == Qnil) return Qnil; } - *origin = class; + if (origin) *origin = class; return body; } @@ -389,6 +389,7 @@ ruby_init(argc, argv, envp) static struct ENVIRON env; the_env = top_env = &env; + init_heap(); PUSH_SCOPE(); the_scope->local_vars = Qnil; the_scope->local_tbl = Qnil; @@ -414,13 +415,14 @@ ruby_init(argc, argv, envp) VALUE rb_readonly_hook(); static VALUE -Eval(toplevel) - int toplevel; +Eval() { VALUE result; NODE *tree; int state; + if (!eval_tree) return Qnil; + tree = eval_tree; eval_tree = Qnil; sourcefile = tree->file; @@ -441,7 +443,7 @@ ruby_run() if (nerrs > 0) exit(nerrs); - Init_stack(); + init_stack(); rb_define_variable("$!", &errstr, Qnil, Qnil, 0); errat = Qnil; /* clear for execution */ @@ -449,7 +451,7 @@ ruby_run() PUSH_ITER(ITER_NOT); if ((state = EXEC_TAG()) == 0) { the_class = (struct RClass*)C_Object; - Eval(1); + Eval(); } POP_ITER(); POP_TAG(); @@ -488,6 +490,38 @@ ruby_run() exit(0); } +static void +syntax_error() +{ + VALUE mesg; + + mesg = errstr; + nerrs = 0; + errstr = str_new2("syntax error in eval():\n"); + str_cat(errstr, RSTRING(mesg)->ptr, RSTRING(mesg)->len); + rb_fail(errstr); +} + +VALUE +rb_eval_string(str) + char *str; +{ + char *oldsrc = sourcefile; + VALUE result; + + lex_setsrc("(eval)", str, strlen(str)); + eval_tree = Qnil; + yyparse(); + sourcefile = oldsrc; + if (nerrs == 0) { + return Eval(); + } + else { + syntax_error(); + } + return Qnil; /* not reached */ +} + void rb_trap_eval(cmd) VALUE cmd; @@ -636,34 +670,9 @@ rb_eval(node) return rb_eval(node); } node = node->nd_next; - } - } - return Qnil; - - case NODE_EXNOT: - { - VALUE res; - - PUSH_TAG(); - switch (state = EXEC_TAG()) { - case 0: - res = rb_eval(node->nd_cond); - go_out = 0; - break; - - case TAG_FAIL: - res = Qnil; - go_out = 0; - break; - - default: - go_out = 1; } - POP_TAG(); - if (go_out) JUMP_TAG(state); - if (res) return FALSE; - return TRUE; } + return Qnil; case NODE_WHILE: PUSH_TAG(); @@ -828,6 +837,10 @@ rb_eval(node) node = node->nd_2nd; goto again; + case NODE_NOT: + if (rb_eval(node->nd_body)) return FALSE; + return TRUE; + case NODE_DOT3: if (node->nd_state == 0) { if (rb_eval(node->nd_beg)) { @@ -943,7 +956,8 @@ rb_eval(node) val = rb_apply(recv, aref, args); val = rb_funcall(val, node->nd_mid, 1, rb_eval(rval)); ary_push(args, val); - return rb_apply(recv, aset, args); + rb_apply(recv, aset, args); + return val; } case NODE_OP_ASGN2: @@ -957,7 +971,8 @@ rb_eval(node) id |= ID_ATTRSET; val = rb_eval(node->nd_value); - return rb_funcall(recv, id, 1, val); + rb_funcall(recv, id, 1, val); + return val; } case NODE_MASGN: @@ -1044,7 +1059,7 @@ rb_eval(node) key = rb_eval(list->nd_head); list = list->nd_next; if (list == Qnil) - Bug("odd number list for hash"); + Bug("odd number list for Dict"); val = rb_eval(list->nd_head); list = list->nd_next; Fdic_aset(hash, key, val); @@ -1122,39 +1137,42 @@ rb_eval(node) return rb_ivar_set(node->nd_vid, the_env->argv[0]); case NODE_DEFN: - { - if (node->nd_defn) { - rb_add_method(the_class,node->nd_mid,node->nd_defn, - node->nd_noex); + if (node->nd_defn) { + NODE *body; + VALUE origin; + int noex; + + body = search_method(the_class, node->nd_mid, &origin); + if (verbose && origin != (VALUE)the_class + && body->nd_noex != node->nd_noex) { + Warning("change method %s's scope", rb_id2name(node->nd_mid)); } + + if (body) noex = body->nd_noex; + else noex = node->nd_noex; /* default(1 for toplevel) */ + + rb_add_method(the_class, node->nd_mid, node->nd_defn, noex); } return Qnil; case NODE_DEFS: - { - if (node->nd_defn) { - VALUE recv = rb_eval(node->nd_recv); + if (node->nd_defn) { + VALUE recv = rb_eval(node->nd_recv); - if (recv == Qnil) { - Fail("Can't define method \"%s\" for nil", - rb_id2name(node->nd_mid)); - } - rb_add_method(rb_single_class(recv), - node->nd_mid, node->nd_defn, 0); + if (recv == Qnil) { + Fail("Can't define method \"%s\" for nil", + rb_id2name(node->nd_mid)); } + rb_add_method(rb_single_class(recv),node->nd_mid,node->nd_defn,0); } return Qnil; case NODE_UNDEF: - { - rb_add_method(the_class, node->nd_mid, Qnil, 0); - } + rb_add_method(the_class, node->nd_mid, Qnil, 0); return Qnil; case NODE_ALIAS: - { - rb_alias(the_class, node->nd_new, node->nd_old); - } + rb_alias(the_class, node->nd_new, node->nd_old); return Qnil; case NODE_CLASS: @@ -1492,7 +1510,7 @@ asign(lhs, val) break; default: - Bug("bug in iterator variable asignment"); + Bug("bug in variable asignment"); break; } } @@ -1614,28 +1632,62 @@ rb_ensure(b_proc, data1, e_proc, data2) return result; } -struct st_table *new_idhash(); +static int last_noex; -static void -rb_undefined(obj, id, noex) +static VALUE +Funknown(argc, argv, obj) + int argc; + VALUE *argv; VALUE obj; - ID id; - int noex; { - VALUE desc = obj_as_string(obj); + VALUE desc; + ID id; char *format; + struct ENVIRON *env; + + id = FIX2INT(argv[0]); + argc--; argv++; + desc = obj_as_string(obj); if (RSTRING(desc)->len > 160) { desc = Fkrn_to_s(obj); } - if (noex) + if (last_noex) format = "method `%s' not available for \"%s\"(%s)"; else format = "undefined method `%s' for \"%s\"(%s)"; + + /* fake environment */ + PUSH_ENV(); + env = the_env->prev; + MEMCPY(the_env, the_env->prev->prev, struct ENVIRON, 1); + the_env->prev = env; + Fail(format, rb_id2name(id), RSTRING(desc)->ptr, rb_class2name(CLASS_OF(obj))); + POP_ENV(); +} + +static VALUE +rb_undefined(obj, id, argc, argv, noex) + VALUE obj; + ID id; + int argc; + VALUE*argv; + int noex; +{ + VALUE *nargv; + + argc; + nargv = ALLOCA_N(VALUE, argc+1); + nargv[0] = INT2FIX(id); + MEMCPY(nargv+1, argv, VALUE, argc); + + last_noex = noex; + + return rb_funcall2(obj, rb_intern("unknown"), argc+1, nargv); } static VALUE @@ -1656,7 +1708,6 @@ rb_call(class, recv, mid, argc, argv, func) /* is it in the method cache? */ ent = cache + EXPR1(class, mid); if (ent->mid == mid && ent->class == class) { - /* if (ent->method == Qnil) rb_undefined(recv, mid, 0); */ class = ent->origin; mid = ent->mid; body = ent->method; @@ -1666,12 +1717,14 @@ rb_call(class, recv, mid, argc, argv, func) ID id = mid; if ((body = rb_get_method_body(&class, &id, &noex)) == Qnil) { - rb_undefined(recv, mid, 0); + return rb_undefined(recv, mid, argc, argv, 0); } mid = id; } - if (!func && noex) rb_undefined(recv, mid, 1); + if (!func && noex) { + return rb_undefined(recv, mid, argc, argv, 1); + } switch (iter->iter) { case ITER_PRE: @@ -1691,7 +1744,7 @@ rb_call(class, recv, mid, argc, argv, func) the_env->argv = argv; switch (nd_type(body)) { - case NODE_CFUNC: + case NODE_CFUNC: { int len = body->nd_argc; @@ -1806,6 +1859,8 @@ rb_call(class, recv, mid, argc, argv, func) /* for attr get/set */ case NODE_ATTRSET: case NODE_IVAR: + /* for exported method */ + case NODE_ZSUPER: return rb_eval(body); default: @@ -1915,17 +1970,19 @@ Fapply(argc, argv, recv) VALUE *argv; VALUE recv; { - VALUE vid, rest; + VALUE vid; ID mid; - rb_scan_args(argc, argv, "1*", &vid, &rest); + if (argc == 0) Fail("no method name given"); + + vid = argv[0]; argc--; argv++; if (TYPE(vid) == T_STRING) { mid = rb_intern(RSTRING(vid)->ptr); } else { mid = NUM2INT(vid); } - return rb_apply(recv, mid, rest); + return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1); } #include <varargs.h> @@ -1958,6 +2015,16 @@ rb_funcall(recv, mid, n, va_alist) return rb_call(CLASS_OF(recv), recv, mid, n, argv, 1); } +VALUE +rb_funcall2(recv, mid, argc, argv) + VALUE recv; + ID mid; + int argc; + VALUE *argv; +{ + return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1); +} + int rb_in_eval = 0; static VALUE @@ -1995,13 +2062,7 @@ Feval(obj, src) if (state) JUMP_TAG(state); if (nerrs > 0) { - VALUE mesg; - - mesg = errstr; - nerrs = 0; - errstr = str_new2("syntax error in eval():\n"); - str_cat(errstr, RSTRING(mesg)->ptr, RSTRING(mesg)->len); - rb_fail(errstr); + syntax_error(); } return result; @@ -2151,6 +2212,24 @@ addpath(path) extern VALUE C_Kernel; + +Init_eval() +{ + match = rb_intern("=~"); + each = rb_intern("each"); + + aref = rb_intern("[]"); + aset = rb_intern("[]="); + + rb_global_variable(&top_scope); + rb_global_variable(&eval_tree); + rb_define_private_method(C_Kernel, "exit", Fexit, -1); + rb_define_private_method(C_Kernel, "eval", Feval, 1); + rb_define_private_method(C_Kernel, "iterator_p", Fiterator_p, 0); + rb_define_method(C_Kernel, "apply", Fapply, -1); + rb_define_method(C_Kernel, "unknown", Funknown, -1); +} + Init_load() { char *path; @@ -2169,22 +2248,6 @@ Init_load() rb_define_private_method(C_Kernel, "require", Frequire, 1); } -Init_eval() -{ - match = rb_intern("=~"); - each = rb_intern("each"); - - aref = rb_intern("[]"); - aset = rb_intern("[]="); - - rb_global_variable(&top_scope); - rb_global_variable(&eval_tree); - rb_define_private_method(C_Kernel, "exit", Fexit, -1); - rb_define_private_method(C_Kernel, "eval", Feval, 1); - rb_define_private_method(C_Kernel, "iterator_p", Fiterator_p, 0); - rb_define_method(C_Kernel, "apply", Fapply, -1); -} - void scope_dup(scope) struct SCOPE *scope; @@ -2239,11 +2302,12 @@ Sblk_new(class) if (the_block->block) return the_block->block; blk = obj_alloc(class); + if (!blkdata) blkdata = rb_intern("blk"); Make_Data_Struct(blk, blkdata, struct BLOCK, Qnil, blk_free, data); MEMCPY(data, the_block, struct BLOCK, 1); data->env.argv = ALLOC_N(VALUE, data->env.argc); - MEMCPY(data->env.argv, the_block->env.argv, VALUE, data->env.argc); + MEMCPY(data->env.argv, the_block->env.argv, VALUE, data->env.argc); scope_dup(data->scope); @@ -2252,13 +2316,13 @@ Sblk_new(class) } VALUE -blk_new() +block_new() { return Sblk_new(C_Block); } static VALUE -Fblk_do(blk, args) +Fblk_call(blk, args) VALUE blk, args; { struct BLOCK *data; @@ -2318,6 +2382,5 @@ Init_Block() rb_define_single_method(C_Block, "new", Sblk_new, 0); - rb_define_method(C_Block, "do", Fblk_do, -2); - blkdata = rb_intern("blk"); + rb_define_method(C_Block, "call", Fblk_call, -2); } |