summaryrefslogtreecommitdiff
path: root/eval.c
diff options
context:
space:
mode:
authorYukihiro Matsumoto <matz@ruby-lang.org>1995-12-21 00:56:57 +0900
committerTakashi Kokubun <takashikkbn@gmail.com>2019-08-17 22:09:32 +0900
commitfca49a8a69a0f6bb4feae74c6cd0e93d7fac8b36 (patch)
tree590a6d2ffcfa31212c1595e34a01d9cda56ba308 /eval.c
parent8bf1c909dc31fd4bcdc1488cda9fe89a62bc2830 (diff)
version 0.95v0_95
https://cache.ruby-lang.org/pub/ruby/1.0/ruby-0.95.tar.gz Thu Dec 21 00:56:57 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.95 - fj.sourcesに * eval.c (rb_eval): rescueのロジックをrb_rescue()に一元化. Wed Dec 20 19:30:58 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * Makefile.in: 不要なコンパイルの回避(より完全に). * class.c (singleton_class_new): `single'->`singleton' Tue Dec 19 07:14:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * io.c (closed?): IOがcloseされているかどうかを知る述語. * parse.y (primary): 特異メソッドの引数のlex_stateが不適切. * lib/tk.rb: tcl->rubyの変換関数の用意. * ext/extmk.rb.in (install): installの2重コンパイルの回避. * array.c (range_beg_len): range指定の不適切なエラーを訂正. * string.c (str_aref): range指定のバグを削除. * lib/tk.rb (tk_split_list): Tclのリストに対応. Mon Dec 18 09:58:12 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.94 * dln.c (dln_load): HP対応(未確認) * eval.c (Init_Proc): BlockをProcに改名. Sat Dec 16 13:46:14 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_eval): retryでイテレータの再実行ができるように. Fri Dec 15 17:14:30 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c: proc:lambdaの親しみやすい別名 Thu Dec 14 17:21:55 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (dyna_var_asgn): イテレータブロック内で最初に初期化された ローカル変数の有効範囲をそのブロック内に限定.これでlambdaと呼べ ないことはない. Wed Dec 13 02:30:58 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * gc.c: autoloadのマークミス. * lib/tk.rb: wishからの複数行の戻り値に対応 * lib/tkcomposite.rb: 複合widget * variable.c (rb_class2path): ICLASSに対応してなかった. * eval.c (ruby_run): exit(0)のバグ Sat Dec 9 01:21:24 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * ext/marshal/marshal.c (dumps|load): 文字列に対する入出力を可能に した(ただし実はファイル経由なのだ). Fri Dec 8 18:29:11 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * ext/marshal/marshal.c: シンボルを一度だけ初期化する. Thu Dec 7 07:58:50 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (yylex): 第1引数の正規表現の認識にエラーがあった.同時に 状態数を減らした. * string.c (str_sub): 置換でスキップ幅が大きすぎた. Wed Dec 6 15:14:23 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (str_sub_method): sub/gsub(!なし)は置換が行なわれなかっ た時,置換前の文字列を返す. Tue Dec 5 00:55:15 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (yylex): 括弧を省略した時の引数展開の`*'に対応. * eval.c (ruby_run): EXITハンドラ内での例外に対応. * bignum.c (big_cmp): BignumとFixnumの比較で落ちる. Mon Dec 4 14:21:18 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (call_op): コンパイル時の定数式の展開をやめた.労多くし て益少ないと判断したので. Thu Nov 30 01:35:15 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * lib/tk.rb: {Radio,Check}Buttonのvariableの実装. * eval.c (rb_yield_0): Block.callがネストした時のバグ. * io.c (f_select): 常に配列3つをふくむ配列を返すように * lib/tk.rb: fileeventをruby側で実装. Wed Nov 29 17:53:23 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * variable.c (rb_ivar_get): selfを常に指定するように. Tue Nov 14 00:07:29 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * lib/tk.rb: Tk4.0対応 Mon Nov 13 16:23:32 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.93 Thu Nov 9 23:26:01 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * gc.c (gc_mark): モジュールのMixinのマーク忘れ. * parse.y (f_arglist): メソッド定義の引数を括弧で括らなくても良い ようにした. Wed Nov 8 00:17:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_yield_0): 未初期化のローカル変数があった. * eval.c (rb_eval): pendig signalのチェックをeval実行後に行うよう にした.でないとシグナルの発生と検出が遠く離れてしまう事がある. * parse.y: class文のsuperclass部を定数から式に拡張した. * lib/tk.rb: Tkのほぼ全ウィンドウクラスに対応.キャンバスとテキス ト上のオブジェクトが残っている. Tue Nov 7 08:18:37 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * signal.c (trap): ブロックを指定できるように. Mon Nov 6 16:44:00 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (f_caller): 呼出元の情報を得る. * ext/tkutil/tkutil.c: wishのstderr出力を監視することで,エラー処 理を行う. * ext/tkutil/tkutil.c: wishとの通信部をCで記述. Sat Nov 4 01:12:59 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * sample/ruby-mode.el (ruby-calculate-indent): インデントの計算を もう少しスマートにした(正規表現のチェック,継続行のチェック). * eval.c (rb_call): 無限再帰を避けるため,関数のネストレベルの制限 を行なう. * lib/tk.rb: Tkインターフェース.まだ不完全だが. * eval.c (rb_yield_0): 空のBlockのバグ. * sample/ruby-mode.el (ruby-calculate-indent): 行末の演算子による 行継続に対応. Fri Nov 3 12:56:21 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_call): 本体が空の関数の実行にバグ. * parse.y (var_extend): 文字列の末尾の変数展開のバグ. * variable.c (rb_gvar_set): traceの評価時にに変数値を与えるように. * eval.c (f_require): ruby scriptのrequireにbug. * variable.c (rb_const_get): モジュールのinclude対策. Thu Oct 19 13:56:06 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * dln.c (dln_load): HP対応でのtypo. Wed Oct 18 17:39:39 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.92 * object.c (krn_type): オブジェクトの動的な型を返すメソッド. Tue Oct 17 00:48:18 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * ruby.c (proc_options): -X オプション.chdirだけを行う. * re.c (reg_search): 漢字コードを途中で変更できるように.コンパイ ル時のコードが変更された時にはマッチの直前に正規表現の再コンパイ ルを行う.定数KCODEから変数$KCODEへ. * parse.y: ()のなかにcompexprを許す. * re.c (reg_search): メモリリークを直した. Fri Oct 13 13:19:19 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (str_sub): 文字列置換にバグ. * string.c (str_strip_bang): 文字列の後ろの長さの調整が行われてい なかった. * re.c (reg_search): $&, $1...のはローカルに束縛するようになった. 呼び出したメソッドでのマッチは現スコープの$&などの値に影響しない. マッチの情報をスコープ外で得たいときには$~を使って束縛情報を持ち 出す必要がある. Thu Oct 12 00:33:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * re.c (reg_search): String:split, String:indexでは$&, $1...が変化 しないようにした. * io.c (rb_str_setter): setterの仕様が変更になっていた. * variable.c (f_trace_var): 第2引数を省略してイテレータとして呼べ るように. Wed Oct 11 11:50:59 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.91 * variable.c (var_setter): 引数が間違っていた.致命的バグ. * io.c (pipe_open): $stderrの値が変更されている時にはそちらを 子プロセスのstderrに設定する. Mon Oct 9 13:06:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * object.c (mod_to_s): モジュール内のモジュールは`::'を使った表現 で表示されるように. * variable.c (rb_gvar_set): 代入によるループが発生しないように, trace内での代入ではtraceを評価しない. * struct.c (struct_equal): structのequal判定にクラスの一致を含めた. Sat Oct 7 00:18:32 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_eval): defined?の機能を拡張(yieldのチェック,superの 存在など). Fri Oct 6 12:06:47 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.90 * st.c (st_foreach): 要素を削除した時に要素数が変化していなかった. * hash.c (hash_values): バグ修正.keysを返していた…. * parse.y (call_op): defined? の引数では定数の畳み込みを行わない (チェックする前にコンパイルエラーになっては困る). * スコープ生成の一部見直し. Thu Oct 5 00:29:43 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * 関数とクラスの命名規則を変更した.関数名,変数名の全面書き換え. * gc.c (looks_pointerp): ヒープチェックの高速化. * struct.c (Fstruct_aset): 構造体に対する`[]='. (struct_set): 構造体メンバに対する代入. Wed Oct 4 09:54:07 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.89 * eval.c (Frequire): ダイナミックロードのエラーチェックを厳しく. * struct.c: structの構造を完全に書き換えた.以前は順序付きの id->valueの連想配列であったが,今度は構造体毎に新しいクラスを生 成するようにした. * parse.y: `::'の意味をAssocの生成からクラス(モジュール)内の定数ア クセスへ変更. * assoc.c: なくす. Tue Oct 3 13:31:08 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * variable.c (Ftrace_var): trace_var, 大域変数への書き込みhookを設 定する. * variable.c: global_entryの構成を書き換えた.これでtrace_varを実 装できる. * file.c (Ffile_stat): "&"で直前のfstatの結果も参照できるように. Fri Sep 29 14:15:13 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.88 * dln.c (dln_load): AIXとHPに対応したコードを入れた(動作は未確認). * ext/extmk.rb.in: 必要に応じて,定数EXTLIBを定義するように. * dln.c (dln_load): dln独立に書き換える.将来の拡張用. (load_1): dln_a_outにおいてソースコードでライブラリを明示的にロー ドする必要がないように変更した. Thu Sep 28 13:31:37 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * sample/ruby-mode.el: もっとましなhilit19対応(正規表現). Wed Sep 27 04:12:44 1995 Takahasi Mamoru <taka@soum.co.jp> * sample/test.rb: echoで-nを使わないように(SysV対策). * ext/extmk.rb.in: sub -> sub! Tue Sep 26 19:12:42 1995 Yasuo OHBA <jammy@csg.mes.co.jp> * dln.c (dln_find_1): `.', `..'から始まるパスに対応した. Mon Sep 25 12:33:03 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.87 Sat Sep 23 10:00:18 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (Fmod_modfunc): メソッドをprivateにし,同時に特異メソッド も定義するメソッド.パッケージ的使い方のモジュール用. Fri Sep 22 11:02:44 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * lib/find.rb: findを提供するライブラリ * variable.c (rb_define_variable): hookの設定を分離. (add_hook): 1変数に対して複数のhookを設定できるように. Thu Sep 21 00:22:11 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (Fstr_frozen): 文字列が更新不可かどうかをチェックする述 語メソッド. * hash.c (Fhash_aset): keyが文字列の時,キーの内容が変化しないよう に,dupしてfreezeする. Wed Sep 20 16:12:44 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.86 * ext/extmk.rb.in (have_header): キャッシュにバグ. * ext/extmk.rb.in (have_library): 引数の順序が変わった. Thu Sep 14 18:00:59 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * object.c (obj_is_instance_of): is_member_ofから名称変更. Wed Sep 13 15:44:35 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (Fstr_tr_bang): 範囲外の文字に対する変換バグ. Tue Sep 12 14:27:58 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * file.c (Sfile_expand_path): expand_file_name -> expand_pathに名 称変更. * enum.c (Fenum_member): includes? -> member? に名称変更. * string.c (Fstr_each_byte): StringはByteArrayであるという基本に戻っ て,eachの定義をeach_byteに変更した.今までのeachはeach_lineでア クセスできる. Mon Sep 11 18:31:17 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * file.c (cache_stat): ファイル名として"&"を指定すると直前の stat(2)の結果を再利用するように. Fri Sep 8 14:18:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * ruby.texi: `!', `?'に対応してアップデート. * parse.y: defined -> defined? * file.c: FileOpの一文字メソッドをなくす.一文字テストはtestメソッ ドにまかせる. * parse.y (yylex): 変数名の後ろに`?'も許す.述語メソッドの後ろに `?'を追加する. Thu Sep 7 20:01:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c: 文字列の中身を更新するメソッドの名前の終りに`!'を付加. `!'の無いバージョンも用意した. * parse.y: 変数名の後ろに`!'を許す. Wed Sep 6 14:12:19 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.85 * string.c (Fstr_dup): 文字列の複製を作る (Fstr_freeze): 文字列の更新不可属性を設定できるように. (Fsub/Fgsub): $_の内容をdupしてから置換を行うように. * ruby.h (CLONESETUP): flagsの状態もコピー Tue Sep 5 01:27:50 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * sample/test.rb: 失敗の検出を厳しく. Fri Aug 25 14:31:02 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * process.c (Ffork): イテレータとしても動作するように. * version 0.84 * signal.c (sig_beg): ハンドラが設定されている時には再設定しない. * ext/extmk.rb.in (create_makefile): shared objectのリンクの際に `-l'オプションを指定するように. * signal.c (trap): `EXIT'で終了処理を行う設定が出来る. Wed Aug 16 00:13:22 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * signal.c (sig_beg): デフォルトではbegin節の中でだけSIGINTを捕捉 するように変更. * io.c (io_ctl): fcntlを持たないシステムにも対応. * 各ディレクトリに分散していたMANIFESTをまとめた.拡張モジュール毎 には必要. * string.c (Sstr_new,str_sub,Fstr_crypt): 引数を自動的に文字列に変 換するように. Sat Aug 12 00:44:02 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * string.c (Fstr_crypt): PD cryptを用意した. Fri Aug 11 14:37:03 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * assoc.c (Fassoc_clone): assocもcloneできるように. * io.c: マクロREAD_DATA_PENDINGの定義を変更(Linux対応) * io.c (io_fptr_finalize): ftprの開放時の処理を指定できるように. Wed Aug 9 16:52:41 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * eval.c (rb_provided): 複数のfeatureをロードすると無限ループに落 ちるという単純な(しかし凶悪な)ミス. * ext/extmk.rb.in (install): dlopen対応を行った.今までdlnにしか十 分に対応していなかった. Tue Aug 8 14:17:06 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.83 Mon Aug 7 12:47:41 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y: resque -> rescue.恥ずかしいがtypoを残しておくわけには いかないよなあ.なんで今まで気がつかなかったのか…. Thu Aug 3 18:18:05 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * missing/nt.c: NT移植用の関数群をまとめた. * variable.c (rb_const_get): また例外を発生するようにした.defined がある以上例外を発生させない理由がないので(例外が発生した方がタ イプミスの検出などの点で有利). * variable.c (Fautoload): autoloadを実装.今度は使えるか. Mon Jul 31 15:44:21 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (arg_ambiguous): 第1引数のあいまいさを警告(-vオプション で有効). * eval.c (rb_eval): `-v'オプションをつけて`def'が呼ばれると不必要 なエラーメッセージが出た. * parse.y (yylex): メソッドの第1引数の判定をもうちょっと賢くした. Fri Jul 28 19:04:43 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (yylex): `+/-/['の直前に空白が来るかどうかで動作を変更し た(混乱のもとか?) Wed Jul 26 09:21:23 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.82a * sprintf.c (Fsprintf): `%s'で'\0'を含む文字列に対応. * pack.c (Fpck_pack): packの要素確保のバグ. * eval.c (Floop): 無限ループのイテレータ. * io.c (next_argv): 存在しないファイル名が指定された時のエラー処理 が行われていなかった. Mon Jul 24 17:37:34 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.82 * ext/extmk.rb.in (install): 拡張モジュールをstatic linkする場合は そのモジュールが既にrequireされたのと同じようにfeatureを設定する. これで拡張モジュールの機能が必要な時には(static linkされているか どうかにかかわらず)requireすればよくなる. * eval.c (Frequire): `$"'に格納する文字列をフルパスでなくフィーチャ 名とする.rubyスクリプトをロードした時には`.rb',オブジェクトを ロードした時には`.o'をフィーチャ名に付加する.lispのrequireと provideの働きに(少し)近い. Thu Jul 20 12:50:05 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * Makefile.in (test): make testができるように. * struct.c (struct_new): typo. * eval.c (rb_eval): `defined'を追加.メソッド/変数/定数の定義状態 を知る事が出来る. Wed Jul 19 18:04:01 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.81 Mon Jul 17 14:53:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * variable.c (rb_const_get): 未初期化のCONSTANTの値をnilにした.し かし,今後また例外に戻す可能性はある.要はoptionalなクラス/モジュー ルが存在するかチェックしたいだけなんだな. * st.c (int): grow_factorを固定にした(大嶋さんのマシンに対応). Fri Jul 14 00:48:40 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * ext/extmk.rb.in: キャッシュのバグを修正. * parse.y (var_extend): #{$数字}に対応した. * dln.c (dln_load_1): `Init_FILENAME'だけを有効に.`init_*'は今後 実行しない. * ext/etc/etc.c : Etcモジュールを拡張モジュールとして分離.実はNT 対応への布石だったりするかもしれない. Tue Jul 11 17:12:48 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * gcc -Wallで出たwarningを元にソースを変更. * signal.c (trap): typo. Fri Jul 7 10:08:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.80 * ruby.texi: texinfo documentを提供.specとruby.1は無くなった. * signal.c (Ftrap): 割込み禁止中の例外発生に対応. * eval.c (Flambda): Blockオブジェクトを返す.Block.newと同義. Thu Jul 6 00:35:03 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * signal.c (Ftrap): SIG_DFLの処理を変更.SIGINTへのデフォルトハン ドラを用意(例外を発生する). * file.c (Sfile_expand_fname): パス名を絶対パスに展開するメソッド. (Sfile_basename): basenameを得るメソッド.拡張子も外せる. (Sfile_dirname): basenameの反対. * eval.c (rb_call): argument評価中の例外発生に対応. * file.c (Ftest): `M', `A', `C'を追加. Tue Jul 4 12:36:33 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * file.c (Ftest): ファイルテスト用メソッド. * ruby.c (proc_options): `-r'オプションを追加. * parse.y (f_args): デフォルト引数を追加. * eval.c (rb_call): 該当する引数が無い時,rest引数の値をnilに. * numeric.c (num_equal): 数値以外との比較で例外が発生していた. FALSEを返すように. * eval.c (masign): 多重代入のrest部の動作がおかしかった. Sat Jun 17 01:03:16 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * parse.y (gettable): 未初期化のローカル変数の参照(独立した識別子) は正式にメソッド呼び出しとした. * parse.y (read_escape): tokenbufを使わないように修正.それにとも ない,`\C-x',`\M-x'などのエスケープ表現を復活.これでドキュメン トと実際の処理系が一致した. Thu Jun 15 15:42:00 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * re.c (re_regcomp): cacheのチェックを改善. Mon Jun 12 18:50:51 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * version 0.79 Sat Jun 10 00:25:01 1995 Yukihiro Matsumoto <matz@caelum.co.jp> * re.c (re_regcomp): cache判定に`$='の値も反映させた. * sample/test.rb: test suite作成. Fri Jun 9 15:58:34 1995 Yukihiro Matsumoto <matz@ix-02> * re.c (re_regcomp): cacheの判定が間違っていた. Fri Jun 9 00:01:35 1995 Yukihiro Matsumoto (matz@dyna) * eval.c (rb_yield): block構造体に初期化していないメンバ(iter)があっ たのでイテレータのネストが正しく動作しなかった. Thu Jun 8 00:59:03 1995 Yukihiro Matsumoto (matz@dyna) * re.c (=~): String以外との比較がFALSEを返すように(例外を発生して いた). * extmk.rb.in: 判定した値をファイルにキャッシュするようにした. * assoc.c (to_a): to_aメソッドが再定義されていなかった. * eval.c (rb_eval): 初期化されていないローカル変数へのアクセスを引 数の無いメソッド呼び出しと解釈する.ただし,(現状では)メソッドが 定義されていない場合,エラーにせず変数未初期化のwaringを出して nilを返している.「ruby -pe print」などが実行できるという意味で はありがたいこの仕様は,しかし今後の検討が必要である.-- メソッ ド呼び出しとするのを止めるか(以前の仕様),いつもメソッド呼び出し とする(未定義ならばエラー)か,今の仕様で行くか. * eval.c (rb_eval): 初期化されていないローカル変数へのアクセスで (evalなどで)初期化された事が分かった時には以後初期化されたローカ ル変数とみなす. Wed Jun 7 11:58:12 1995 Yukihiro Matsumoto <matz@ix-02> * eval.c (rb_fail): 例外処理後も`$!'をクリアしないように. (rb_fail): `$!'変数に最後に改行を追加しない. * io.c (Fprint): privateメソッドに変更.引数を取らない時の動作を変 更(`$_'を出力する). (Fio_print): 出力先指定のprintメソッド. (Fio_printf): 出力先指定のprintfメソッド. * parse.y: not演算子の追加.優先順位の低い`!'演算子. Mon Jun 5 19:00:55 1995 Yukihiro Matsumoto <matz@ix-02> * version 0.78 Fri Jun 2 17:52:03 1995 Yukihiro Matsumoto <matz@ix-02> * ruby.c (proc_options): -Iオプションで`$:'への追加される順番を修 正した. Fri Jun 2 00:36:34 1995 Yukihiro Matsumoto (matz@dyna) * parse.y: while修飾子の動作を通常のwhileと同じにした.ただし, begin式へのwhile修飾子だけはdo..while型のループとなる. Wed May 31 18:36:30 1995 Yukihiro Matsumoto <matz@ix-02> * version 0.77 Mon May 29 18:39:37 1995 Yukihiro Matsumoto <matz@ix-02> * ext/extmk.rb.in (install): 拡張モジュールもインストールできるよ うに. Fri May 26 14:43:01 1995 Yukihiro Matsumoto <matz@ix-02> * process.c (Fsystem): 戻り値をサブプロセスの失敗/成功を表す真偽値 にした.終了ステータスは`$?'で得る. Tue May 23 10:58:11 1995 Yukihiro Matsumoto <matz@ix-02> * string.c (Fstr_upto): 無限ループに陥らないように. * parse.y (cond): `||'などの右辺に制御式が書けるように,条件式がか ならずしも値を持たなくても良いようにした. * ext/marshal/marshal.c: オブジェクトの読み書きをメソッドの再定義 でコントロールできるように.インスタンスが`_dump_to'というメソッ ドを定義している時はそちらを使うように. * ext/extmk.rb.in: static linkも設定できるような仕様にした. ext/Setupというファイルにディレクトリ名を記述するとそのディレク トリに存在するモジュールはstatic linkされる(はず). * eval.c (rb_eval): `..'を文法に組み込み,`..'と`...'の動作をperl に合わせた. Sat May 20 01:22:48 1995 Yukihiro Matsumoto (matz@dyna) * io.c (select): timeout時と割込み時の動作の明確化. Co-authored-by: Takahasi Mamoru <taka@soum.co.jp> Co-authored-by: Yasuo OHBA <jammy@csg.mes.co.jp>
Diffstat (limited to 'eval.c')
-rw-r--r--eval.c1537
1 files changed, 1001 insertions, 536 deletions
diff --git a/eval.c b/eval.c
index a96e84e..c1363a6 100644
--- a/eval.c
+++ b/eval.c
@@ -11,9 +11,9 @@
************************************************/
#include "ruby.h"
-#include "ident.h"
#include "env.h"
#include "node.h"
+#include "sig.h"
#include <stdio.h>
#include <setjmp.h>
@@ -24,13 +24,11 @@
# include <string.h>
#else
char *strchr();
+char *strrchr();
#endif
-#ifdef HAVE_STDLIB_H
-#include <stdlib.h>
-#else
-char *getenv();
-#endif
+VALUE cProc;
+static VALUE proc_call();
static void rb_clear_cache_body();
static void rb_clear_cache_entry();
@@ -48,6 +46,7 @@ struct cache_entry { /* method hash table. */
ID mid; /* method's id */
struct RClass *class; /* receiver's class */
struct RClass *origin; /* where method defined */
+ int nargs; /* # of args */
NODE *method;
int noex;
};
@@ -63,7 +62,7 @@ rb_add_method(class, mid, node, noex)
{
NODE *body;
- if (class == Qnil) class = (struct RClass*)C_Object;
+ if (class == Qnil) class = (struct RClass*)cObject;
if (st_lookup(class->m_tbl, mid, &body)) {
Warning("redefine %s", rb_id2name(mid));
rb_clear_cache_body(body);
@@ -97,14 +96,13 @@ rb_get_method_body(classp, idp, noexp)
ID *idp;
int *noexp;
{
- int pos, i;
ID id = *idp;
struct RClass *class = *classp;
NODE *body;
struct RClass *origin;
struct cache_entry *ent;
- if ((body = search_method(class, id, &origin)) == Qnil) {
+ if ((body = search_method(class, id, &origin)) == FALSE) {
return Qnil;
}
if (body->nd_body == Qnil) return Qnil;
@@ -186,16 +184,30 @@ rb_export_method(class, name, noex)
}
}
-VALUE
-rb_method_boundp(class, id)
+static VALUE
+method_boundp(class, id, ex)
struct RClass *class;
ID id;
+ int ex;
{
- if (rb_get_method_body(&class, &id, 0))
+ int noex;
+
+ if (rb_get_method_body(&class, &id, &noex)) {
+ if (ex && noex == NOEX_PRIVATE)
+ return FALSE;
return TRUE;
+ }
return FALSE;
}
+VALUE
+rb_method_boundp(class, id)
+ struct RClass *class;
+ ID id;
+{
+ return method_boundp(class, id, 0);
+}
+
static void
rb_clear_cache_body(body)
NODE *body;
@@ -251,44 +263,51 @@ extern int nerrs;
extern VALUE TopSelf;
VALUE Qself;
-#define PUSH_SELF(s) { \
- VALUE __saved_self__ = Qself; \
- Qself = s; \
+#define PUSH_SELF(s) { \
+ VALUE __saved_self__ = Qself; \
+ Qself = s; \
#define POP_SELF() Qself = __saved_self__; }
-struct ENVIRON *the_env, *top_env;
-struct SCOPE *the_scope, *top_scope;
+struct FRAME *the_frame;
+struct SCOPE *the_scope;
+static struct FRAME *top_frame;
+static struct SCOPE *top_scope;
-#define PUSH_ENV() { \
- struct ENVIRON _env; \
- _env.prev = the_env; \
- the_env = &_env; \
+#define PUSH_FRAME() { \
+ struct FRAME _frame; \
+ _frame.prev = the_frame; \
+ _frame.file = sourcefile; \
+ _frame.line = sourceline; \
+ the_frame = &_frame; \
-#define POP_ENV() the_env = _env.prev; }
+#define POP_FRAME() the_frame = _frame.prev; }
struct BLOCK {
NODE *var;
NODE *body;
VALUE self;
- struct ENVIRON env;
+ struct FRAME frame;
struct SCOPE *scope;
int level;
- VALUE block;
int iter;
+ struct RVarmap *d_vars;
struct BLOCK *prev;
} *the_block;
#define PUSH_BLOCK(v,b) { \
struct BLOCK _block; \
_block.level = tag_level; \
- _block.var=v; \
+ _block.var = v; \
_block.body = b; \
_block.self = Qself; \
- _block.env = *the_env; \
+ _block.frame = *the_frame; \
+ _block.frame.file = sourcefile; \
+ _block.frame.line = sourceline; \
_block.scope = the_scope; \
- _block.block = Qnil; \
+ _block.d_vars = the_dyna_vars; \
_block.prev = the_block; \
+ _block.iter = iter->iter; \
the_block = &_block; \
#define PUSH_BLOCK2(b) { \
@@ -297,6 +316,51 @@ struct BLOCK {
#define POP_BLOCK() the_block = the_block->prev; }
+struct RVarmap *the_dyna_vars;
+#define PUSH_VARS() { \
+ struct RVarmap *_old; \
+ _old = the_dyna_vars;
+
+#define POP_VARS() the_dyna_vars = _old; }
+
+VALUE
+dyna_var_ref(id)
+ ID id;
+{
+ struct RVarmap *vars = the_dyna_vars;
+
+ while (vars) {
+ if (vars->id == id) return vars->val;
+ vars = vars->next;
+ }
+ return Qnil;
+}
+
+VALUE
+dyna_var_asgn(id, value)
+ ID id;
+ VALUE value;
+{
+ struct RVarmap *vars = the_dyna_vars;
+
+ while (vars) {
+ if (vars->id == id) {
+ vars->val = value;
+ return;
+ }
+ vars = vars->next;
+ }
+ {
+ NEWOBJ(_vars, struct RVarmap);
+ OBJSETUP(_vars, Qnil, T_VARMAP);
+ _vars->id = id;
+ _vars->val = value;
+ _vars->next = the_dyna_vars;
+ the_dyna_vars = _vars;
+ }
+ return value;
+}
+
static struct iter {
int iter;
struct iter *prev;
@@ -322,7 +386,7 @@ static struct tag {
jmp_buf buf;
struct gc_list *gclist;
VALUE self;
- struct ENVIRON *env;
+ struct FRAME *frame;
struct iter *iter;
struct tag *prev;
} *prot_tag;
@@ -331,15 +395,16 @@ static struct tag {
struct tag _tag; \
_tag.level= ++tag_level; \
_tag.self = Qself; \
- _tag.env = the_env; \
+ _tag.frame = the_frame; \
_tag.iter = iter; \
_tag.prev = prot_tag; \
prot_tag = &_tag; \
#define EXEC_TAG() (setjmp(prot_tag->buf))
+
#define JUMP_TAG(val) { \
Qself = prot_tag->self; \
- the_env = prot_tag->env; \
+ the_frame = prot_tag->frame; \
iter = prot_tag->iter; \
longjmp(prot_tag->buf,(val)); \
}
@@ -372,8 +437,8 @@ struct class_link {
class_link = &_link \
#define POP_CLASS() \
- the_class = class_link->class; \
- class_link = _link.prev; }
+ the_class = class_link->class; \
+ class_link = _link.prev; }
#define PUSH_SCOPE() { \
struct SCOPE *_old; \
@@ -382,16 +447,24 @@ struct class_link {
_old = the_scope; \
the_scope = _scope; \
-#define POP_SCOPE() the_scope = _old; }
+#define POP_SCOPE() \
+ if (the_scope->flag == SCOPE_ALLOCA) {\
+ the_scope->local_vars = 0;\
+ the_scope->local_tbl = 0;\
+ }\
+ the_scope = _old;\
+}
static VALUE rb_eval();
-static VALUE Feval();
+static VALUE f_eval();
static VALUE rb_call();
VALUE rb_apply();
VALUE rb_xstring();
void rb_fail();
+VALUE rb_rescue();
+
static void module_setup();
static VALUE masign();
@@ -404,20 +477,15 @@ extern VALUE rb_stderr;
extern int sourceline;
extern char *sourcefile;
-VALUE
-rb_self()
-{
- return Qself;
-}
-
static ID last_func;
static void
-error_print()
+error_print(last_func)
+ ID last_func;
{
if (errat) {
fwrite(RSTRING(errat)->ptr, 1, RSTRING(errat)->len, stderr);
if (last_func) {
- fprintf(stderr, ":in method `%s': ", rb_id2name(last_func));
+ fprintf(stderr, ":in `%s': ", rb_id2name(last_func));
}
else {
fprintf(stderr, ": ");
@@ -426,34 +494,43 @@ error_print()
if (errstr) {
fwrite(RSTRING(errstr)->ptr, 1, RSTRING(errstr)->len, stderr);
+ if (RSTRING(errstr)->ptr[RSTRING(errstr)->len - 1] != '\n') {
+ putc('\n', stderr);
+ }
}
else {
fprintf(stderr, "unhandled failure.\n");
}
- rb_trap_exit();
- exit(1);
}
+extern char **environ;
+char **origenviron;
+
void
ruby_init(argc, argv, envp)
int argc;
char **argv, **envp;
{
int state;
- static struct ENVIRON env;
- the_env = top_env = &env;
+ static struct FRAME frame;
+ the_frame = top_frame = &frame;
+
+ origenviron = environ;
+#ifdef NT
+ NtInitialize(&argc, &argv);
+#endif
init_heap();
PUSH_SCOPE();
- the_scope->local_vars = Qnil;
- the_scope->local_tbl = Qnil;
+ the_scope->local_vars = 0;
+ the_scope->local_tbl = 0;
top_scope = the_scope;
PUSH_TAG();
PUSH_ITER(ITER_NOT);
if ((state = EXEC_TAG()) == 0) {
rb_call_inits();
- the_class = (struct RClass*)C_Object;
+ the_class = (struct RClass*)cObject;
ruby_options(argc, argv, envp);
}
POP_ITER();
@@ -466,37 +543,27 @@ ruby_init(argc, argv, envp)
exit(FIX2UINT(last_val));
}
if (state) {
- PUSH_TAG();
- error_print();
- POP_TAG();
+ error_print(last_func);
}
}
-VALUE rb_readonly_hook();
-
static VALUE
Eval()
{
- VALUE result;
+ VALUE result = Qnil;
NODE *tree;
int state;
if (!eval_tree) return Qnil;
tree = eval_tree;
- eval_tree = Qnil;
- sourcefile = tree->file;
-
- PUSH_TAG();
- if ((state = EXEC_TAG()) == 0) {
- result = rb_eval(tree);
- }
- POP_TAG();
- if (state) JUMP_TAG(state);
+ eval_tree = 0;
+ result = rb_eval(tree);
return result;
}
+void
ruby_run()
{
int state;
@@ -504,13 +571,14 @@ ruby_run()
if (nerrs > 0) exit(nerrs);
init_stack();
- rb_define_variable("$!", &errstr, Qnil, Qnil, 0);
+ rb_define_variable("$!", &errstr);
errat = Qnil; /* clear for execution */
PUSH_TAG();
PUSH_ITER(ITER_NOT);
if ((state = EXEC_TAG()) == 0) {
Eval();
+ rb_trap_exit();
}
POP_ITER();
POP_TAG();
@@ -534,12 +602,10 @@ ruby_run()
Fatal("retry outside of protect clause");
break;
case TAG_FAIL:
- PUSH_TAG();
- error_print();
- POP_TAG();
+ error_print(last_func);
+ exit(1);
break;
case TAG_EXIT:
- rb_trap_exit();
exit(FIX2UINT(last_val));
break;
default:
@@ -566,11 +632,12 @@ rb_eval_string(str)
char *str;
{
char *oldsrc = sourcefile;
- VALUE result;
lex_setsrc("(eval)", str, strlen(str));
- eval_tree = Qnil;
+ eval_tree = 0;
+ PUSH_VARS();
yyparse();
+ POP_VARS();
sourcefile = oldsrc;
if (nerrs == 0) {
return Eval();
@@ -582,22 +649,30 @@ rb_eval_string(str)
}
void
-rb_trap_eval(cmd)
- VALUE cmd;
+rb_eval_cmd(cmd, arg)
+ VALUE cmd, arg;
{
int state;
struct SCOPE *saved_scope;
+ if (TYPE(cmd) != T_STRING) {
+ if (TYPE(cmd) == T_OBJECT
+ && obj_is_kind_of(cmd, cProc)) {
+ proc_call(cmd, arg);
+ return;
+ }
+ }
+
PUSH_SELF(TopSelf);
PUSH_CLASS();
PUSH_TAG();
saved_scope = the_scope;
the_scope = top_scope;
- the_class = (struct RClass*)C_Object;
+ the_class = (struct RClass*)cObject;
if ((state = EXEC_TAG()) == 0) {
- Feval(Qself, cmd);
+ f_eval(Qself, cmd);
}
the_scope = saved_scope;
@@ -624,21 +699,40 @@ rb_trap_eval(cmd)
Fatal("retry outside of protect clause");
break;
default:
+ JUMP_TAG(state);
+ break;
+ }
+}
+
+void
+rb_trap_eval(cmd, sig)
+ VALUE cmd;
+ int sig;
+{
#ifdef SAFE_SIGHANDLE
+ int state;
+
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+ rb_eval_cmd(cmd, ary_new3(1, INT2FIX(sig)));
+ }
+ POP_TAG();
+ if (state) {
trap_immediate = 0;
-#endif
JUMP_TAG(state);
- break;
}
+#else
+ rb_eval_cmd(cmd, ary_new3(1, INT2FIX(sig)));
+#endif
}
-#define SETUP_ARGS do {\
+#define SETUP_ARGS {\
NODE *n = node->nd_args;\
if (!n) {\
argc = 0;\
- argv = Qnil;\
+ argv = 0;\
}\
- else if (/*nd_type(n) == NODE_LIST ||*/ nd_type(n) == NODE_ARRAY) {\
+ else if (nd_type(n) == NODE_ARRAY) {\
argc=n->nd_alen;\
if (argc > 0) {\
int i;\
@@ -649,6 +743,10 @@ rb_trap_eval(cmd)
n=n->nd_next;\
}\
}\
+ else {\
+ argc = 0;\
+ argv = 0;\
+ }\
}\
else {\
VALUE args = rb_eval(n);\
@@ -658,45 +756,36 @@ rb_trap_eval(cmd)
argv = ALLOCA_N(VALUE, argc);\
MEMCPY(argv, RARRAY(args)->ptr, VALUE, argc);\
}\
-} while (0)
+}
+
+#define RETURN(v) do { result = (v); goto finish; } while (0)
static VALUE
rb_eval(node)
register NODE *node;
{
int state;
- int go_out;
- VALUE result;
+ VALUE result = Qnil;
again:
- if (node == Qnil) return Qnil;
+ if (node == Qnil) RETURN(Qnil);
sourceline = node->line;
-
-#ifdef SAFE_SIGHANDLE
- {
- extern int trap_pending;
-
- if (trap_pending) {
- rb_trap_exec();
- }
- }
-#endif
+ sourcefile = node->file;
switch (nd_type(node)) {
case NODE_BLOCK:
- while (node->nd_next) {
- rb_eval(node->nd_head);
+ while (node) {
+ result = rb_eval(node->nd_head);
node = node->nd_next;
}
- node = node->nd_head;
- goto again;
+ break;
case NODE_SELF:
- return Qself;
+ RETURN(Qself);
case NODE_NIL:
- return Qnil;
+ RETURN(Qnil);
case NODE_IF:
if (rb_eval(node->nd_cond)) {
@@ -706,7 +795,7 @@ rb_eval(node)
node = node->nd_else;
}
if (node) goto again;
- return Qnil;
+ RETURN(Qnil);
case NODE_CASE:
{
@@ -720,18 +809,18 @@ rb_eval(node)
while (tag) {
if (rb_funcall(rb_eval(tag->nd_head), match, 1, val)){
- return rb_eval(node->nd_body);
+ RETURN(rb_eval(node->nd_body));
}
tag = tag->nd_next;
}
}
else {
- return rb_eval(node);
+ RETURN(rb_eval(node));
}
node = node->nd_next;
}
}
- return Qnil;
+ RETURN(Qnil);
case NODE_WHILE:
PUSH_TAG();
@@ -742,23 +831,26 @@ rb_eval(node)
while_redo:
rb_eval(node->nd_body);
}
- go_out = 0;
break;
case TAG_REDO:
+ state = 0;
goto while_redo;
case TAG_CONTINUE:
+ state = 0;
goto while_cont;
default:
- go_out = 1;
break;
+ }
+ POP_TAG();
+ switch (state) {
+ case 0:
case TAG_BREAK:
- go_out = 0;
+ break;
+ default:
+ JUMP_TAG(state);
break;
}
- while_out:
- POP_TAG();
- if (go_out) JUMP_TAG(state);
- return Qnil;
+ RETURN(Qnil);
case NODE_WHILE2:
PUSH_TAG();
@@ -769,25 +861,31 @@ rb_eval(node)
while2_redo:
rb_eval(node->nd_body);
} while (rb_eval(node->nd_cond));
- go_out = 0;
break;
case TAG_REDO:
+ state = 0;
goto while2_redo;
case TAG_CONTINUE:
+ state = 0;
goto while2_cont;
default:
- go_out = 1;
case TAG_BREAK:
break;
}
- while2_out:
POP_TAG();
- if (go_out) JUMP_TAG(state);
- return Qnil;
+ switch (state) {
+ case 0:
+ case TAG_BREAK:
+ break;
+ default:
+ JUMP_TAG(state);
+ }
+ RETURN(Qnil);
case NODE_ITER:
case NODE_FOR:
{
+ iter_retry:
PUSH_BLOCK(node->nd_var, node->nd_body);
PUSH_TAG();
@@ -803,7 +901,7 @@ rb_eval(node)
recv = rb_eval(node->nd_iter);
PUSH_ITER(ITER_PRE);
- result = rb_call(CLASS_OF(recv),recv,each,0,Qnil,0);
+ result = rb_call(CLASS_OF(recv),recv,each,0,0,0);
POP_ITER();
}
}
@@ -812,13 +910,16 @@ rb_eval(node)
switch (state) {
case 0:
break;
+
+ case TAG_RETRY:
+ goto iter_retry;
+
case IN_BLOCK|TAG_BREAK:
if (target_level != tag_level) {
JUMP_TAG(state);
}
result = Qnil;
break;
- case IN_BLOCK|TAG_RETRY:
case IN_BLOCK|TAG_RETURN:
if (target_level == tag_level) {
state &= ~IN_BLOCK;
@@ -828,91 +929,100 @@ rb_eval(node)
JUMP_TAG(state);
}
}
- return result;
+ break;
case NODE_FAIL:
{
VALUE mesg = rb_eval(node->nd_stts);
if (mesg) Check_Type(mesg, T_STRING);
rb_fail(mesg);
- return Qnil; /* not reached */
}
+ break;
case NODE_YIELD:
- {
- VALUE val;
-
- val = rb_eval(node->nd_stts);
- result = rb_yield(val);
- }
- return result;
+ result = rb_yield(rb_eval(node->nd_stts));
+ break;
case NODE_BEGIN:
- PUSH_TAG();
- switch (state = EXEC_TAG()) {
- case 0:
- retry_entry:
- result = rb_eval(node->nd_head);
- break;
+ if (node->nd_resq == Qnil && node->nd_ensr == Qnil) {
+ node = node->nd_head;
+ goto again;
+ }
+ else {
+ VALUE (*r_proc)();
- case TAG_FAIL:
- if (node->nd_resq) {
- if (node->nd_resq == (NODE*)1) {
- state = 0;
- }
- else {
- PUSH_TAG();
- state = EXEC_TAG();
- if (state == 0) result = rb_eval(node->nd_resq);
- POP_TAG();
- if (state == TAG_RETRY) {
- goto retry_entry;
- }
+ if (node->nd_resq == (NODE*)1) {
+ r_proc = 0;
+ }
+ else {
+ r_proc = rb_eval;
+ }
+ if (node->nd_ensr) {
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+ result = rb_rescue(rb_eval, node->nd_head, r_proc, node->nd_resq);
}
- if (state == 0) {
- errstr = errat = Qnil;
- last_func = 0;
+ POP_TAG();
+ /* ensure clause */
+ rb_eval(node->nd_ensr);
+ if (state) {
+ JUMP_TAG(state);
}
}
- break;
- }
- POP_TAG();
-
- /* ensure clause */
- rb_eval(node->nd_ensr);
-
- if (state != 0) {
- JUMP_TAG(state);
+ else {
+ result = rb_rescue(rb_eval, node->nd_head, r_proc, node->nd_resq);
+ }
}
- return result;
+ break;
case NODE_AND:
- if ((result = rb_eval(node->nd_1st)) == Qnil) return result;
+ if ((result = rb_eval(node->nd_1st)) == FALSE) RETURN(result);
node = node->nd_2nd;
goto again;
case NODE_OR:
- if ((result = rb_eval(node->nd_1st)) != Qnil) return result;
+ if ((result = rb_eval(node->nd_1st)) != FALSE) RETURN(result);
node = node->nd_2nd;
goto again;
case NODE_NOT:
- if (rb_eval(node->nd_body)) return FALSE;
- return TRUE;
+ if (rb_eval(node->nd_body)) result = FALSE;
+ else result = TRUE;
+ break;
+ case NODE_DOT2:
case NODE_DOT3:
+ RETURN(range_new(rb_eval(node->nd_beg), rb_eval(node->nd_end)));
+
+ case NODE_FLIP2: /* like AWK */
+ if (node->nd_state == 0) {
+ if (rb_eval(node->nd_beg)) {
+ node->nd_state = rb_eval(node->nd_end)?0:1;
+ result = TRUE;
+ }
+ result = FALSE;
+ }
+ else {
+ if (rb_eval(node->nd_end)) {
+ node->nd_state = 0;
+ }
+ result = TRUE;
+ }
+ break;
+
+ case NODE_FLIP3: /* like SED */
if (node->nd_state == 0) {
if (rb_eval(node->nd_beg)) {
node->nd_state = 1;
- return TRUE;
+ result = TRUE;
}
- return FALSE;
+ result = FALSE;
}
else {
if (rb_eval(node->nd_end)) {
node->nd_state = 0;
}
- return TRUE;
+ result = TRUE;
}
break;
@@ -946,7 +1056,7 @@ rb_eval(node)
recv = rb_eval(node->nd_recv);
SETUP_ARGS;
POP_ITER();
- return rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0);
+ result = rb_call(CLASS_OF(recv),recv,node->nd_mid,argc,argv,0);
}
break;
@@ -957,19 +1067,18 @@ rb_eval(node)
PUSH_ITER(ITER_NOT);
SETUP_ARGS;
POP_ITER();
- return rb_call(CLASS_OF(Qself),Qself,node->nd_mid,argc,argv,1);
+ result = rb_call(CLASS_OF(Qself),Qself,node->nd_mid,argc,argv,1);
}
break;
case NODE_SUPER:
case NODE_ZSUPER:
{
- int i;
int argc; VALUE *argv; /* used in SETUP_ARGS */
if (nd_type(node) == NODE_ZSUPER) {
- argc = the_env->argc;
- argv = the_env->argv;
+ argc = the_frame->argc;
+ argv = the_frame->argv;
}
else {
PUSH_ITER(ITER_NOT);
@@ -978,16 +1087,14 @@ rb_eval(node)
}
PUSH_ITER(iter->iter?ITER_PRE:ITER_NOT);
- result = rb_call(the_env->last_class->super, Qself,
- the_env->last_func, argc, argv, 1);
+ result = rb_call(the_frame->last_class->super, Qself,
+ the_frame->last_func, argc, argv, 1);
POP_ITER();
}
- return result;
+ break;
case NODE_SCOPE:
{
- VALUE result;
-
PUSH_SCOPE();
PUSH_TAG();
if (node->nd_cnt > 0) {
@@ -996,22 +1103,17 @@ rb_eval(node)
the_scope->local_tbl = node->nd_tbl;
}
else {
- the_scope->local_vars = Qnil;
- the_scope->local_tbl = Qnil;
+ the_scope->local_vars = 0;
+ the_scope->local_tbl = 0;
}
if ((state = EXEC_TAG()) == 0) {
result = rb_eval(node->nd_body);
}
POP_TAG();
- if (!(the_scope->flags & SCOPE_MALLOCED)) {
- the_scope->local_vars = Qnil;
- the_scope->local_tbl = Qnil;
- }
POP_SCOPE();
if (state != 0) JUMP_TAG(state);
-
- return result;
}
+ break;
case NODE_OP_ASGN1:
{
@@ -1026,8 +1128,9 @@ rb_eval(node)
val = rb_funcall(val, node->nd_mid, 1, rb_eval(rval));
ary_push(args, val);
rb_apply(recv, aset, args);
- return val;
+ result = val;
}
+ break;
case NODE_OP_ASGN2:
{
@@ -1036,24 +1139,27 @@ rb_eval(node)
recv = rb_funcall(rb_eval(node->nd_recv), id, 0);
- id &= ~ID_SCOPE_MASK;
- id |= ID_ATTRSET;
+ id = id_attrset(id);
val = rb_eval(node->nd_value);
rb_funcall(recv, id, 1, val);
- return val;
+ result = val;
}
+ break;
case NODE_MASGN:
- {
- VALUE val = rb_eval(node->nd_value);
- return masign(node, val);
- }
+ result = masign(node, rb_eval(node->nd_value));
+ break;
case NODE_LASGN:
- if (the_scope->local_vars == Qnil)
+ if (the_scope->local_vars == 0)
Bug("unexpected local variable asignment");
- return the_scope->local_vars[node->nd_cnt] = rb_eval(node->nd_value);
+ result = the_scope->local_vars[node->nd_cnt] = rb_eval(node->nd_value);
+ break;
+
+ case NODE_DASGN:
+ result = dyna_var_asgn(node->nd_vid, rb_eval(node->nd_value));
+ break;
case NODE_GASGN:
{
@@ -1061,51 +1167,47 @@ rb_eval(node)
val = rb_eval(node->nd_value);
rb_gvar_set(node->nd_entry, val);
- return val;
+ result = val;
}
+ break;
+
case NODE_IASGN:
{
VALUE val;
val = rb_eval(node->nd_value);
- rb_ivar_set(node->nd_vid, val);
- return val;
+ rb_ivar_set(Qself, node->nd_vid, val);
+ result = val;
}
+ break;
+
case NODE_CASGN:
{
VALUE val;
val = rb_eval(node->nd_value);
rb_const_set(the_class, node->nd_vid, val);
- return val;
+ result = val;
}
break;
case NODE_LVAR:
- if (the_scope->local_vars == Qnil)
+ if (the_scope->local_vars == 0)
Bug("unexpected local variable");
- return the_scope->local_vars[node->nd_cnt];
-
- case NODE_LVAR2:
- if (the_scope->flags & SCOPE_MALLOCED) {
- ID id = node->nd_vid, *tbl = the_scope->local_tbl;
- int i, len = tbl[0];
+ result = the_scope->local_vars[node->nd_cnt];
+ break;
- tbl++;
- for (i=0; i<len; i++) {
- if (id == tbl[i]) break;
- }
- if (i<len) {
- return the_scope->local_vars[i];
- }
- }
- Warning("local var %s not initialized", rb_id2name(node->nd_vid));
- return Qnil;
+ case NODE_DVAR:
+ result = dyna_var_ref(node->nd_vid);
+ break;
case NODE_GVAR:
- return rb_gvar_get(node->nd_entry);
+ result = rb_gvar_get(node->nd_entry);
+ break;
+
case NODE_IVAR:
- return rb_ivar_get(node->nd_vid);
+ result = rb_ivar_get(Qself, node->nd_vid);
+ break;
case NODE_CVAR:
{
@@ -1114,14 +1216,54 @@ rb_eval(node)
val = rb_const_get(node->nd_rval->nd_clss, node->nd_vid);
nd_set_type(node, NODE_CONST);
node->nd_cval = val;
- return val;
+ result = val;
}
+ break;
case NODE_CONST:
- return node->nd_cval;
+ result = node->nd_cval;
+ break;
+
+ case NODE_COLON2:
+ {
+ VALUE cls;
+
+ cls = rb_eval(node->nd_head);
+ switch (TYPE(cls)) {
+ case T_CLASS:
+ case T_MODULE:
+ break;
+ default:
+ Check_Type(cls, T_CLASS);
+ break;
+ }
+ result = rb_const_get(cls, node->nd_mid);
+ }
+ break;
+#define MATCH_DATA the_scope->local_vars[node->nd_cnt]
case NODE_NTH_REF:
- return re_nth_match(node->nd_nth);
+ result = reg_nth_match(node->nd_nth, MATCH_DATA);
+ break;
+
+ case NODE_BACK_REF:
+ switch (node->nd_nth) {
+ case '&':
+ result = reg_last_match(MATCH_DATA);
+ break;
+ case '`':
+ result = reg_match_pre(MATCH_DATA);
+ break;
+ case '\'':
+ result = reg_match_post(MATCH_DATA);
+ break;
+ case '+':
+ result = reg_match_last(MATCH_DATA);
+ break;
+ default:
+ Bug("unexpected back-ref");
+ }
+ break;
case NODE_HASH:
{
@@ -1133,24 +1275,24 @@ rb_eval(node)
while (list) {
key = rb_eval(list->nd_head);
list = list->nd_next;
- if (list == Qnil)
+ if (list == 0)
Bug("odd number list for Hash");
val = rb_eval(list->nd_head);
list = list->nd_next;
- Fhash_aset(hash, key, val);
+ hash_aset(hash, key, val);
}
- return hash;
+ result = hash;
}
break;
case NODE_ZARRAY: /* zero length list */
- return ary_new();
+ result = ary_new();
+ break;
case NODE_ARRAY:
{
VALUE ary;
int i;
- NODE *list;
i = node->nd_alen;
ary = ary_new2(i);
@@ -1159,12 +1301,13 @@ rb_eval(node)
RARRAY(ary)->len = i;
}
- return ary;
+ result = ary;
}
break;
case NODE_STR:
- return str_new3(node->nd_lit);
+ result = str_new3(node->nd_lit);
+ break;
case NODE_STR2:
case NODE_XSTR2:
@@ -1188,26 +1331,32 @@ rb_eval(node)
list = list->nd_next;
}
if (nd_type(node) == NODE_DREGX) {
- VALUE re = regexp_new(RSTRING(str)->ptr, RSTRING(str)->len,
- node->nd_cflag);
- return re;
+ VALUE re = reg_new(RSTRING(str)->ptr, RSTRING(str)->len,
+ node->nd_cflag);
+ result = re;
+ }
+ else if (nd_type(node) == NODE_XSTR2) {
+ result = rb_xstring(str);
}
- if (nd_type(node) == NODE_XSTR2) {
- return rb_xstring(str);
+ else {
+ result = str;
}
- return str;
}
+ break;
case NODE_XSTR:
- return rb_xstring(node->nd_lit);
+ result = rb_xstring(node->nd_lit);
+ break;
case NODE_LIT:
- return node->nd_lit;
+ result = node->nd_lit;
+ break;
case NODE_ATTRSET:
- if (the_env->argc != 1)
- Fail("Wrong # of arguments(%d for 1)", the_env->argc);
- return rb_ivar_set(node->nd_vid, the_env->argv[0]);
+ if (the_frame->argc != 1)
+ Fail("Wrong # of arguments(%d for 1)", the_frame->argc);
+ result = rb_ivar_set(Qself, node->nd_vid, the_frame->argv[0]);
+ break;
case NODE_DEFN:
if (node->nd_defn) {
@@ -1216,7 +1365,7 @@ rb_eval(node)
int noex;
body = search_method(the_class, node->nd_mid, &origin);
- if (verbose && origin != (VALUE)the_class
+ if (body && verbose && origin != (VALUE)the_class
&& body->nd_noex != node->nd_noex) {
Warning("change method %s's scope", rb_id2name(node->nd_mid));
}
@@ -1225,8 +1374,9 @@ rb_eval(node)
else noex = node->nd_noex; /* default(1 for toplevel) */
rb_add_method(the_class, node->nd_mid, node->nd_defn, noex);
+ result = Qnil;
}
- return Qnil;
+ break;
case NODE_DEFS:
if (node->nd_defn) {
@@ -1236,20 +1386,23 @@ rb_eval(node)
Fail("Can't define method \"%s\" for nil",
rb_id2name(node->nd_mid));
}
- rb_funcall(recv, rb_intern("single_method_added"),
+ rb_funcall(recv, rb_intern("singleton_method_added"),
1, INT2FIX(node->nd_mid));
- rb_add_method(rb_single_class(recv),node->nd_mid,node->nd_defn,
+ rb_add_method(rb_singleton_class(recv),node->nd_mid,node->nd_defn,
NOEX_PUBLIC);
+ result = Qnil;
}
- return Qnil;
+ break;
case NODE_UNDEF:
rb_add_method(the_class, node->nd_mid, Qnil, NOEX_PUBLIC);
- return Qnil;
+ result = Qnil;
+ break;
case NODE_ALIAS:
rb_alias(the_class, node->nd_new, node->nd_old);
- return Qnil;
+ result = Qnil;
+ break;
case NODE_CLASS:
{
@@ -1257,17 +1410,16 @@ rb_eval(node)
struct RClass *tmp;
if (node->nd_super) {
- super = rb_const_get(the_class, node->nd_super);
- if (super == Qnil) {
- Fail("undefined superclass %s",
- rb_id2name(node->nd_super));
+ super = rb_eval(node->nd_super);
+ if (super == Qnil || TYPE(super) != T_CLASS) {
+ Fail("superclass undefined");
}
}
else {
super = Qnil;
}
- if (rb_const_bound(the_class, node->nd_cname)) {
+ if (rb_const_defined(the_class, node->nd_cname)) {
class = rb_const_get(the_class, node->nd_cname);
if (super) {
if (TYPE(class) != T_CLASS)
@@ -1280,27 +1432,28 @@ rb_eval(node)
tmp = RCLASS(tmp)->super;
}
if (tmp != RCLASS(super))
- Fail("%s's superclass differs",
+ Fail("superclass mismatch for %s",
rb_id2name(node->nd_cname));
}
Warning("extending class %s", rb_id2name(node->nd_cname));
}
else {
- if (super == Qnil) super = C_Object;
+ if (super == Qnil) super = cObject;
class = rb_define_class_id(node->nd_cname, super);
rb_const_set(the_class, node->nd_cname, class);
rb_set_class_path(class,the_class,rb_id2name(node->nd_cname));
}
module_setup(class, node->nd_body);
- return class;
+ result = class;
}
+ break;
case NODE_MODULE:
{
VALUE module;
- if (rb_const_bound(the_class, node->nd_cname)) {
+ if (rb_const_defined(the_class, node->nd_cname)) {
module = rb_const_get(the_class, node->nd_cname);
if (TYPE(module) != T_MODULE)
Fail("%s is not a module", rb_id2name(node->nd_cname));
@@ -1313,13 +1466,141 @@ rb_eval(node)
}
module_setup(module, node->nd_body);
- return module;
+ result = module;
}
+ break;
+
+ case NODE_DEFINED:
+ {
+ VALUE obj;
+
+ node = node->nd_head;
+ switch (nd_type(node)) {
+ case NODE_SUPER:
+ case NODE_ZSUPER:
+ if (the_frame->last_func == 0) result = FALSE;
+ else {
+ result = method_boundp(the_frame->last_class->super,
+ the_frame->last_func, 1);
+ }
+ break;
+
+ case NODE_FCALL:
+ obj = CLASS_OF(Qself);
+ goto check_bound;
+
+ case NODE_CALL:
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+ obj = rb_eval(node->nd_recv);
+ }
+ POP_TAG();
+ if (state == TAG_FAIL) {
+ result = FALSE;
+ break;
+ }
+ else {
+ if (state) JUMP_TAG(state);
+ obj = CLASS_OF(obj);
+ check_bound:
+ if (method_boundp(obj, node->nd_mid,
+ nd_type(node)== NODE_CALL)) {
+ result = TRUE;
+ }
+ else result = FALSE;
+ }
+ break;
+
+ case NODE_YIELD:
+ result = iterator_p();
+ break;
+
+ case NODE_BREAK:
+ case NODE_CONTINUE:
+ case NODE_REDO:
+ case NODE_RETRY:
+
+ case NODE_SELF:
+ case NODE_NIL:
+ case NODE_FAIL:
+ case NODE_ATTRSET:
+ case NODE_DEFINED:
+
+ case NODE_OP_ASGN1:
+ case NODE_OP_ASGN2:
+ case NODE_MASGN:
+ case NODE_LASGN:
+ case NODE_DASGN:
+ case NODE_GASGN:
+ case NODE_IASGN:
+ case NODE_CASGN:
+ case NODE_LVAR:
+ case NODE_DVAR:
+ result = TRUE;
+ break;
+
+ case NODE_GVAR:
+ result = rb_gvar_defined(node->nd_entry);
+ break;
+
+ case NODE_IVAR:
+ result = rb_ivar_defined(node->nd_vid);
+ break;
+
+ case NODE_CVAR:
+ result = rb_const_defined(node->nd_rval->nd_clss, node->nd_vid);
+ break;
+
+ case NODE_CONST:
+ result = TRUE;
+ break;
+
+ case NODE_COLON2:
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+ obj = rb_eval(node->nd_head);
+ }
+ POP_TAG();
+ if (state == TAG_FAIL) result = FALSE;
+ else {
+ if (state) JUMP_TAG(state);
+ result = rb_const_defined(obj, node->nd_mid);
+ }
+ break;
+
+ case NODE_NTH_REF:
+ result = reg_nth_defined(node->nd_nth, MATCH_DATA);
+ break;
+
+ case NODE_BACK_REF:
+ result = reg_nth_defined(0, MATCH_DATA);
+ break;
+
+ default:
+ PUSH_TAG();
+ if ((state = EXEC_TAG()) == 0) {
+ rb_eval(node);
+ }
+ POP_TAG();
+ if (state == TAG_FAIL) result = FALSE;
+ else {
+ if (state) JUMP_TAG(state);
+ result = TRUE;
+ }
+ }
+ }
+ break;
default:
Bug("unknown node type %d", nd_type(node));
}
- return Qnil; /* not reached */
+ finish:
+#ifdef SAFE_SIGHANDLE
+ if (trap_pending) {
+ rb_trap_exec();
+ }
+#endif
+ return result; /* not reached */
}
static void
@@ -1337,7 +1618,6 @@ module_setup(module, node)
the_class = (struct RClass*)module;
PUSH_SELF((VALUE)the_class);
PUSH_SCOPE();
- PUSH_TAG();
if (node->nd_cnt > 0) {
the_scope->local_vars = ALLOCA_N(VALUE, node->nd_cnt);
@@ -1345,20 +1625,15 @@ module_setup(module, node)
the_scope->local_tbl = node->nd_tbl;
}
else {
- the_scope->local_vars = Qnil;
- the_scope->local_tbl = Qnil;
+ the_scope->local_vars = 0;
+ the_scope->local_tbl = 0;
}
+ PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
rb_eval(node->nd_body);
}
-
POP_TAG();
- if (!(the_scope->flags & SCOPE_MALLOCED)) {
- the_scope->local_vars = Qnil;
- the_scope->local_tbl = Qnil;
- }
- if (state != 0) JUMP_TAG(state);
POP_SCOPE();
POP_SELF();
POP_CLASS();
@@ -1366,20 +1641,10 @@ module_setup(module, node)
}
VALUE
-obj_responds_to(obj, msg)
+rb_responds_to(obj, id)
VALUE obj;
- struct RString *msg;
-{
ID id;
-
- if (FIXNUM_P(msg)) {
- id = FIX2INT(msg);
- }
- else {
- Check_Type(msg, T_STRING);
- id = rb_intern(msg->ptr);
- }
-
+{
if (rb_method_boundp(CLASS_OF(obj), id)) {
return TRUE;
}
@@ -1393,11 +1658,12 @@ rb_exit(status)
last_val = INT2FIX(status);
if (prot_tag)
JUMP_TAG(TAG_EXIT);
+ rb_trap_exit();
exit(FIX2UINT(last_val));
}
static VALUE
-Fexit(argc, argv, obj)
+f_exit(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -1440,25 +1706,22 @@ rb_fail(mesg)
{
char buf[BUFSIZ];
- if (errat == Qnil || sourcefile) {
- if (the_env->last_func) {
- last_func = the_env->last_func;
+ if (errat == Qnil && mesg == Qnil) {
+ errstr = Qnil;
+ }
+
+ if (errat == Qnil && sourcefile) {
+ if (the_frame->last_func) {
+ last_func = the_frame->last_func;
}
sprintf(buf, "%s:%d", sourcefile, sourceline);
errat = str_new2(buf);
}
if (mesg) {
- if (RSTRING(mesg)->ptr[RSTRING(mesg)->len - 1] == '\n') {
- errstr = mesg;
- }
- else {
- errstr = str_clone(mesg);
- str_cat(errstr, "\n", 1);
- }
+ errstr = mesg;
}
-
- if (prot_tag->level == 0) error_print();
+ if (prot_tag->level == 0) error_print(last_func);
JUMP_TAG(TAG_FAIL);
}
@@ -1470,48 +1733,54 @@ iterator_p()
}
static VALUE
-Fiterator_p()
+f_iterator_p()
{
if (iter->prev && iter->prev->iter) return TRUE;
return FALSE;
}
VALUE
-rb_yield(val)
- VALUE val;
+rb_yield_0(val, self)
+ VALUE val, self;
{
struct BLOCK *block;
NODE *node;
int state;
- VALUE result;
- struct ENVIRON *old_env;
- struct SCOPE *old_scope;
+ VALUE result = Qnil;
+ struct SCOPE *old_scope;
+ struct FRAME frame;
if (!iterator_p()) {
Fail("yield called out of iterator");
}
+ PUSH_VARS();
block = the_block;
- old_env = the_env;
- the_env = &(block->env);
+ frame = block->frame;
+ frame.prev = the_frame;
+ the_frame = &(frame);
old_scope = the_scope;
the_scope = block->scope;
the_block = block->prev;
+ the_dyna_vars = block->d_vars;
if (block->var) {
if (nd_type(block->var) == NODE_MASGN)
masign(block->var, val);
else
asign(block->var, val);
}
+ node = block->body;
PUSH_ITER(block->iter);
- PUSH_SELF(block->self);
+ PUSH_SELF(self?self:block->self);
PUSH_TAG();
- node = block->body;
switch (state = EXEC_TAG()) {
redo:
case 0:
- if (nd_type(node) == NODE_CFUNC) {
+ if (!node) {
+ result = Qnil;
+ }
+ else if (nd_type(node) == NODE_CFUNC) {
result = (*node->nd_cfnc)(val,node->nd_argc);
}
else {
@@ -1523,24 +1792,40 @@ rb_yield(val)
case TAG_CONTINUE:
state = 0;
break;
- case TAG_RETRY:
case TAG_BREAK:
case TAG_RETURN:
target_level = block->level;
state = IN_BLOCK|state;
break;
+ default:
+ break;
}
POP_TAG();
POP_SELF();
POP_ITER();
+ POP_VARS();
the_block = block;
- the_env = old_env;
+ the_frame = the_frame->prev;
the_scope = old_scope;
if (state) JUMP_TAG(state);
return result;
}
+VALUE
+rb_yield(val)
+ VALUE val;
+{
+ return rb_yield_0(val, 0);
+}
+
+static VALUE
+f_loop()
+{
+ for (;;) { rb_yield(Qnil); }
+ return Qnil;
+}
+
static VALUE
masign(node, val)
NODE *node;
@@ -1590,15 +1875,19 @@ asign(lhs, val)
break;
case NODE_IASGN:
- rb_ivar_set(lhs->nd_vid, val);
+ rb_ivar_set(Qself, lhs->nd_vid, val);
break;
case NODE_LASGN:
- if (the_scope->local_vars == Qnil)
+ if (the_scope->local_vars == 0)
Bug("unexpected iterator variable asignment");
the_scope->local_vars[lhs->nd_cnt] = val;
break;
+ case NODE_DASGN:
+ dyna_var_asgn(lhs->nd_vid, val);
+ break;
+
case NODE_CASGN:
rb_const_set(the_class, lhs->nd_vid, val);
break;
@@ -1631,13 +1920,13 @@ asign(lhs, val)
VALUE
rb_iterate(it_proc, data1, bl_proc, data2)
VALUE (*it_proc)(), (*bl_proc)();
- char *data1, *data2;
+ void *data1, *data2;
{
int state;
- VALUE retval;
+ VALUE retval = Qnil;
NODE *node = NEW_CFUNC(bl_proc, data2);
- struct BLOCK block;
+ iter_retry:
PUSH_ITER(ITER_PRE);
PUSH_BLOCK(Qnil, node);
PUSH_TAG();
@@ -1654,13 +1943,17 @@ rb_iterate(it_proc, data1, bl_proc, data2)
switch (state) {
case 0:
break;
+
+ case TAG_RETRY:
+ goto iter_retry;
+
case IN_BLOCK|TAG_BREAK:
if (target_level != tag_level) {
JUMP_TAG(state);
}
retval = Qnil;
break;
- case IN_BLOCK|TAG_RETRY:
+
case IN_BLOCK|TAG_RETURN:
if (target_level == tag_level) {
state &= ~IN_BLOCK;
@@ -1674,23 +1967,24 @@ rb_iterate(it_proc, data1, bl_proc, data2)
}
VALUE
-rb_resque(b_proc, data1, r_proc, data2)
+rb_rescue(b_proc, data1, r_proc, data2)
VALUE (*b_proc)(), (*r_proc)();
- char *data1, *data2;
+ void *data1, *data2;
{
int state;
- int go_out;
- VALUE result;
+ VALUE result = Qnil;
+ volatile SIGHANDLE handle;
PUSH_TAG();
switch (state = EXEC_TAG()) {
case 0:
+ handle = sig_beg();
retry_entry:
result = (*b_proc)(data1);
- go_out = 0;
break;
case TAG_FAIL:
+ sig_end(handle);
if (r_proc) {
PUSH_TAG();
state = EXEC_TAG();
@@ -1698,28 +1992,25 @@ rb_resque(b_proc, data1, r_proc, data2)
result = (*r_proc)(data2);
}
POP_TAG();
- switch (state) {
- case TAG_RETRY:
+ if (state == TAG_RETRY) {
goto retry_entry;
- case 0:
- go_out = 0;
- break;
- default:
- go_out = 1;
- break;
}
}
+ else {
+ state = 0;
+ }
if (state == 0) {
- errstr = errat = Qnil;
+ errat = Qnil;
+ last_func = 0;
}
break;
default:
- go_out = 1;
+ sig_end(handle);
break;
}
POP_TAG();
- if (go_out) JUMP_TAG(state);
+ if (state) JUMP_TAG(state);
return result;
}
@@ -1727,10 +2018,10 @@ rb_resque(b_proc, data1, r_proc, data2)
VALUE
rb_ensure(b_proc, data1, e_proc, data2)
VALUE (*b_proc)(), (*e_proc)();
- char *data1, *data2;
+ void *data1, *data2;
{
int state;
- VALUE result;
+ VALUE result = Qnil;
PUSH_TAG();
if ((state = EXEC_TAG()) == 0) {
@@ -1748,7 +2039,7 @@ rb_ensure(b_proc, data1, e_proc, data2)
static int last_noex;
static VALUE
-Fmissing(argc, argv, obj)
+f_missing(argc, argv, obj)
int argc;
VALUE *argv;
VALUE obj;
@@ -1756,31 +2047,33 @@ Fmissing(argc, argv, obj)
VALUE desc;
ID id;
char *format;
- struct ENVIRON *env;
+ struct FRAME *frame;
id = FIX2INT(argv[0]);
argc--; argv++;
- desc = obj_as_string(obj);
- if (RSTRING(desc)->len > 160) {
- desc = Fkrn_to_s(obj);
+ if (TYPE(obj) == T_STRING) {
+ desc = krn_inspect(obj);
+ }
+ else {
+ desc = obj_as_string(obj);
}
if (last_noex)
- format = "method `%s' not available for \"%s\"(%s)";
+ format = "method `%s' not available for %s(%s)";
else
- format = "undefined method `%s' for \"%s\"(%s)";
+ format = "undefined method `%s' for %s(%s)";
- /* fake environment */
- PUSH_ENV();
- env = the_env->prev;
- MEMCPY(the_env, env->prev, struct ENVIRON, 1);
- the_env->prev = env;
+ /* fake frame */
+ PUSH_FRAME();
+ frame = the_frame->prev;
+ *the_frame = *frame->prev;
+ the_frame->prev = frame;
Fail(format,
rb_id2name(id),
RSTRING(desc)->ptr,
rb_class2name(CLASS_OF(obj)));
- POP_ENV();
+ POP_FRAME();
}
static VALUE
@@ -1793,7 +2086,6 @@ rb_undefined(obj, id, argc, argv, noex)
{
VALUE *nargv;
- argc;
nargv = ALLOCA_N(VALUE, argc+1);
nargv[0] = INT2FIX(id);
MEMCPY(nargv+1, argv, VALUE, argc);
@@ -1803,6 +2095,9 @@ rb_undefined(obj, id, argc, argv, noex)
return rb_funcall2(obj, rb_intern("method_missing"), argc+1, nargv);
}
+#define STACK_LEVEL_MAX 10000
+static int stack_level;
+
static VALUE
rb_call(class, recv, mid, argc, argv, scope)
struct RClass *class;
@@ -1814,7 +2109,7 @@ rb_call(class, recv, mid, argc, argv, scope)
{
NODE *body;
int noex;
- VALUE result;
+ VALUE result = Qnil;
struct cache_entry *ent;
int itr;
enum node_type type;
@@ -1830,7 +2125,7 @@ rb_call(class, recv, mid, argc, argv, scope)
else {
ID id = mid;
- if ((body = rb_get_method_body(&class, &id, &noex)) == Qnil) {
+ if ((body = rb_get_method_body(&class, &id, &noex)) == FALSE) {
return rb_undefined(recv, mid, argc, argv, 0);
}
mid = id;
@@ -1861,13 +2156,16 @@ rb_call(class, recv, mid, argc, argv, scope)
return rb_call(class->super, recv, mid, argc, argv, scope?scope:1);
}
+ if (stack_level++ > STACK_LEVEL_MAX)
+ Fail("stack level too deep");
+
PUSH_ITER(itr);
PUSH_SELF(recv);
- PUSH_ENV();
- the_env->last_func = mid;
- the_env->last_class = class;
- the_env->argc = argc;
- the_env->argv = argv;
+ PUSH_FRAME();
+ the_frame->last_func = mid;
+ the_frame->last_class = class;
+ the_frame->argc = argc;
+ the_frame->argv = argv;
switch (type) {
case NODE_CFUNC:
@@ -1985,14 +2283,14 @@ rb_call(class, recv, mid, argc, argv, scope)
/* for attr get/set */
case NODE_ATTRSET:
case NODE_IVAR:
- return rb_eval(body);
+ result = rb_eval(body);
+ break;
default:
{
int state;
VALUE *local_vars;
- sourcefile = body->file;
PUSH_SCOPE();
if (body->nd_cnt > 0) {
@@ -2002,47 +2300,59 @@ rb_call(class, recv, mid, argc, argv, scope)
the_scope->local_vars = local_vars;
}
else {
- local_vars = the_scope->local_vars = Qnil;
- the_scope->local_tbl = Qnil;
+ local_vars = the_scope->local_vars = 0;
+ the_scope->local_tbl = 0;
}
body = body->nd_body;
- if (nd_type(body) == NODE_BLOCK) {
- NODE *node = body->nd_head;
- NODE *local;
- int i;
-
- if (nd_type(node) != NODE_ARGS) {
- Bug("no argument-node");
- }
+ PUSH_TAG();
+ state = EXEC_TAG();
+ if (state == 0) {
+ if (nd_type(body) == NODE_BLOCK) {
+ NODE *node = body->nd_head;
+ int i;
- body = body->nd_next;
- i = node->nd_cnt;
- if (i > argc || (node->nd_rest == -1 && i < argc))
- Fail("Wrong # of arguments(%d for %d)", argc, i);
+ if (nd_type(node) != NODE_ARGS) {
+ Bug("no argument-node");
+ }
- if (local_vars) {
- if (i > 0) {
- MEMCPY(local_vars, argv, VALUE, i);
+ body = body->nd_next;
+ i = node->nd_cnt;
+ if (i > argc
+ || (node->nd_rest == -1
+ && i+(node->nd_opt?node->nd_opt->nd_alen:0)<argc)){
+ Fail("Wrong # of arguments(%d for %d)", argc, i);
}
- if (node->nd_rest >= 0) {
- if (argc == 0)
- local_vars[node->nd_rest] = ary_new();
- else
- local_vars[node->nd_rest] = ary_new4(argc-i, argv+i);
+
+ if (local_vars) {
+ if (i > 0) {
+ MEMCPY(local_vars, argv, VALUE, i);
+ }
+ argv += i; argc -= i;
+ if (node->nd_opt) {
+ NODE *opt = node->nd_opt;
+
+ while (opt && argc) {
+ asign(opt->nd_head, *argv);
+ argv++; argc--;
+ opt = opt->nd_next;
+ }
+ rb_eval(opt);
+ }
+ if (node->nd_rest >= 0) {
+ if (argc > 0)
+ local_vars[node->nd_rest]=ary_new4(argc,argv);
+ else
+ local_vars[node->nd_rest] = ary_new2(0);
+ }
}
}
- }
- PUSH_TAG();
- state = EXEC_TAG();
- if (state == 0) {
+ else if (nd_type(body) == NODE_ARGS) {
+ body = 0;
+ }
result = rb_eval(body);
}
POP_TAG();
- if (!(the_scope->flags & SCOPE_MALLOCED)) {
- the_scope->local_vars = Qnil;
- the_scope->local_tbl = Qnil;
- }
POP_SCOPE();
switch (state) {
case 0:
@@ -2056,20 +2366,23 @@ rb_call(class, recv, mid, argc, argv, scope)
case TAG_REDO:
Fatal("unexpected redo");
break;
- case TAG_RETRY:
- Fatal("retry outside of resque clause");
- break;
case TAG_RETURN:
result = last_val;
break;
+ case TAG_RETRY:
+ if (!iterator_p()) {
+ Fatal("retry outside of rescue clause");
+ }
default:
+ stack_level--;
JUMP_TAG(state);
}
}
}
- POP_ENV();
+ POP_FRAME();
POP_SELF();
POP_ITER();
+ stack_level--;
return result;
}
@@ -2089,7 +2402,7 @@ rb_apply(recv, mid, args)
}
static VALUE
-Fapply(argc, argv, recv)
+f_send(argc, argv, recv)
int argc;
VALUE *argv;
VALUE recv;
@@ -2133,7 +2446,7 @@ rb_funcall(recv, mid, n, va_alist)
va_end(ar);
}
else {
- argv = Qnil;
+ argv = 0;
}
return rb_call(CLASS_OF(recv), recv, mid, n, argv, 1);
@@ -2149,17 +2462,69 @@ rb_funcall2(recv, mid, argc, argv)
return rb_call(CLASS_OF(recv), recv, mid, argc, argv, 1);
}
+static VALUE
+f_caller(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ VALUE level;
+ struct FRAME *frame = the_frame;
+ int lev, n;
+ char buf[BUFSIZ];
+
+ rb_scan_args(argc, argv, "01", &level);
+ if (level == Qnil) lev = 1;
+ else lev = NUM2INT(level);
+ n = lev;
+ if (n < 0) Fail("negative level(%d)", n);
+ else {
+ while (n-- > 0) {
+ frame = frame->prev;
+ if (!frame) return Qnil;
+ }
+ if (!frame->file) return Qnil;
+ if (frame->prev && frame->prev->last_func) {
+ sprintf(buf, "%s:%d:in `%s'",
+ frame->file, frame->line,
+ rb_id2name(frame->prev->last_func));
+ }
+ else {
+ sprintf(buf, "%s:%d", frame->file, frame->line);
+ }
+ }
+ return str_new2(buf);
+}
+
+void
+rb_backtrace()
+{
+ VALUE c, lev;
+ int n = 0;
+
+ lev = INT2FIX(n);
+ while (c = f_caller(1, &lev)) {
+ printf("%s\n", RSTRING(c)->ptr);
+ n++;
+ lev = INT2FIX(n);
+ }
+}
+
+ID
+rb_frame_last_func()
+{
+ return the_frame->last_func;
+}
+
int rb_in_eval = 0;
static VALUE
-Feval(obj, src)
+f_eval(obj, src)
VALUE obj;
struct RString *src;
{
- VALUE result;
+ VALUE result = Qnil;
int state;
NODE *node;
- char *oldsrc = sourcefile;
Check_Type(src, T_STRING);
PUSH_TAG();
@@ -2173,11 +2538,12 @@ Feval(obj, src)
if ((state = EXEC_TAG()) == 0) {
lex_setsrc("(eval)", src->ptr, src->len);
- eval_tree = Qnil;
+ eval_tree = 0;
+ PUSH_VARS();
yyparse();
- sourcefile = oldsrc;
+ POP_VARS();
if (nerrs == 0) {
- result = Eval(0);
+ result = Eval();
}
}
eval_tree = node;
@@ -2221,22 +2587,22 @@ find_file(file)
}
VALUE
-Fload(obj, fname)
+f_load(obj, fname)
VALUE obj;
struct RString *fname;
{
int state, in_eval = rb_in_eval;
- NODE *node;
- char *file;
+ char *file, *src;
Check_Type(fname, T_STRING);
file = find_file(fname->ptr);
- if (!file) Fail("No such file to load -- %s", file);
+ if (!file) Fail("No such file to load -- %s", fname->ptr);
PUSH_SELF(TopSelf);
PUSH_TAG();
PUSH_CLASS();
- the_class = (struct RClass*)C_Object;
+ the_class = (struct RClass*)cObject;
+ PUSH_SCOPE();
the_scope->local_vars = top_scope->local_vars;
the_scope->local_tbl = top_scope->local_tbl;
rb_in_eval = 1;
@@ -2244,9 +2610,11 @@ Fload(obj, fname)
if (state == 0) {
rb_load_file(file);
if (nerrs == 0) {
- Eval(0);
+ Eval();
}
}
+ top_scope->flag = the_scope->flag;
+ POP_SCOPE();
POP_CLASS();
POP_TAG();
POP_SELF();
@@ -2259,98 +2627,175 @@ Fload(obj, fname)
return TRUE;
}
-static VALUE rb_loadfiles;
+static VALUE rb_features;
-Frequire(obj, fname)
- VALUE obj;
- struct RString *fname;
+static VALUE
+rb_provided(feature)
+ char *feature;
{
- char *file;
VALUE *p, *pend;
+ char *f;
+ int len;
- Check_Type(fname, T_STRING);
- file = find_file(fname->ptr);
- if (!file) {
- char *buf = ALLOCA_N(char, strlen(fname->ptr) + 4);
- sprintf(buf, "%s.rb", fname->ptr);
- file = find_file(buf);
-#ifdef USE_DL
- if (!file) {
- sprintf(buf, "%s%s", fname->ptr, DLEXT);
- file = find_file(buf);
- }
-#endif
- if (!file) Fail("No such file to load -- %s", file);
- }
-
- p = RARRAY(rb_loadfiles)->ptr;
- pend = p + RARRAY(rb_loadfiles)->len;
+ p = RARRAY(rb_features)->ptr;
+ pend = p + RARRAY(rb_features)->len;
while (p < pend) {
Check_Type(*p, T_STRING);
- if (strcmp(RSTRING(*p)->ptr, file) == 0) return FALSE;
+ f = RSTRING(*p)->ptr;
+ if (strcmp(f, feature) == 0) return TRUE;
+ len = strlen(feature);
+ if (strncmp(f, feature, len) == 0
+ && (strcmp(f+len, ".rb") == 0 ||strcmp(f+len, ".o") == 0)) {
+ return TRUE;
+ }
+ p++;
}
- fname = (struct RString*)str_new2(file);
- ary_push(rb_loadfiles, fname);
- file = fname->ptr;
+ return FALSE;
+}
-#ifdef USE_DL
- {
- int len = strlen(file), extsiz = sizeof(DLEXT);
+void
+rb_provide(feature)
+ char *feature;
+{
+ if (!rb_provided(feature))
+ ary_push(rb_features, str_new2(feature));
+}
- if (len > extsiz) {
- int i;
- for (i=1;i<extsiz;i++) {
- if (file[len-i] != DLEXT[extsiz-i-1]) break;
+VALUE
+f_require(obj, fname)
+ VALUE obj;
+ struct RString *fname;
+{
+ char *ext, *file, *feature, *buf;
+ VALUE load;
+
+ Check_Type(fname, T_STRING);
+ if (rb_provided(fname->ptr)) return FALSE;
+
+ ext = strrchr(fname->ptr, '.');
+ if (ext) {
+ if (strcmp(".rb", ext) == 0) {
+ feature = file = fname->ptr;
+ file = find_file(file);
+ if (file) goto rb_load;
+ }
+ else if (strcmp(".o", ext) == 0) {
+ feature = fname->ptr;
+ if (strcmp(".o", DLEXT) != 0) {
+ buf = ALLOCA_N(char, strlen(fname->ptr) + 3);
+ strcpy(buf, feature);
+ ext = strrchr(buf, '.');
+ strcpy(ext, DLEXT);
+ file = find_file(buf);
}
- if (i==extsiz) {
- static int rb_dln_init = 0;
- extern char *rb_dln_argv0;
+ if (file) goto dyna_load;
+ }
+ else if (strcmp(DLEXT, ext) == 0) {
+ feature = fname->ptr;
+ file = find_file(feature);
+ if (file) goto dyna_load;
+ }
+ }
+ buf = ALLOCA_N(char, strlen(fname->ptr) + 4);
+ sprintf(buf, "%s.rb", fname->ptr);
+ file = find_file(buf);
+ if (file) {
+ fname = (struct RString*)str_new2(file);
+ feature = buf;
+ goto rb_load;
+ }
+ sprintf(buf, "%s%s", fname->ptr, DLEXT);
+ file = find_file(buf);
+ if (file) {
+ feature = buf;
+ goto dyna_load;
+ }
+ Fail("No such file to load -- %s", fname->ptr);
+
+ dyna_load:
+ load = str_new2(file);
+ file = RSTRING(load)->ptr;
+ dln_load(file);
+ rb_provide(feature);
+ return TRUE;
- if (rb_dln_init == 0 && dln_init(rb_dln_argv0) == -1) {
- Fail("%s: %s", rb_dln_argv0, dln_strerror());
- }
+ rb_load:
+ f_load(obj, fname);
+ rb_provide(feature);
+ return TRUE;
+}
- if (dln_load(file) == -1)
- Fail(dln_strerror());
+static void
+set_method_visibility(argc, argv, ex)
+ int argc;
+ VALUE *argv;
+ int ex;
+{
+ VALUE self = Qself;
+ int i;
+ ID id;
- return TRUE;
- }
+ for (i=0; i<argc; i++) {
+ if (FIXNUM_P(argv[i])) {
+ id = FIX2INT(argv[i]);
}
+ else {
+ Check_Type(argv[i], T_STRING);
+ id = rb_intern(RSTRING(argv[i])->ptr);
+ }
+ rb_export_method(self, id, ex);
}
-#endif
- return Fload(obj, fname);
}
-#ifndef RUBY_LIB
-#define RUBY_LIB "/usr/local/lib/ruby:."
-#endif
-
-#define RUBY_LIB_SEP ':'
+static VALUE
+mod_public(argc, argv)
+ int argc;
+ VALUE *argv;
+{
+ set_method_visibility(argc, argv, NOEX_PUBLIC);
+ return Qnil;
+}
-static void
-addpath(path)
- char *path;
+static VALUE
+mod_private(argc, argv)
+ int argc;
+ VALUE *argv;
{
- char *p, *s;
+ set_method_visibility(argc, argv, NOEX_PRIVATE);
+ return Qnil;
+}
- if (path == Qnil) return;
+static VALUE
+mod_modfunc(argc, argv, module)
+ int argc;
+ VALUE *argv;
+ VALUE module;
+{
+ int i;
+ ID id;
+ NODE *body, *old;
- p = s = path;
- while (*p) {
- while (*p == RUBY_LIB_SEP) p++;
- if (s = strchr(p, RUBY_LIB_SEP)) {
- ary_push(rb_load_path, str_new(p, (int)(s-p)));
- p = s + 1;
+ set_method_visibility(argc, argv, NOEX_PRIVATE);
+ for (i=0; i<argc; i++) {
+ if (FIXNUM_P(argv[i])) {
+ id = FIX2INT(argv[i]);
}
else {
- ary_push(rb_load_path, str_new2(p));
- break;
+ Check_Type(argv[i], T_STRING);
+ id = rb_intern(RSTRING(argv[i])->ptr);
}
+ body = search_method(module, id, 0);
+ if (body == 0 || body->nd_body == 0) {
+ Fail("undefined method `%s' for module `%s'",
+ rb_id2name(id), rb_class2name(module));
+ }
+ rb_add_method(rb_singleton_class(module), id, body->nd_body, NOEX_PUBLIC);
}
+ return Qnil;
}
static VALUE
-Fmod_include(argc, argv, module)
+mod_include(argc, argv, module)
int argc;
VALUE *argv;
struct RClass *module;
@@ -2358,33 +2803,43 @@ Fmod_include(argc, argv, module)
int i;
for (i=0; i<argc; i++) {
+ Check_Type(argv[i], T_MODULE);
rb_include_module(module, argv[i]);
}
return (VALUE)module;
}
static VALUE
-Ftop_include(argc, argv)
+top_include(argc, argv)
+ int argc;
+ VALUE *argv;
{
- return Fmod_include(argc, argv, C_Object);
+ return mod_include(argc, argv, cObject);
}
static VALUE
-Fobj_extend(argc, argv, obj)
+obj_extend(argc, argv, obj)
+ int argc;
+ VALUE *argv;
+ VALUE obj;
{
- return Fmod_include(argc, argv, rb_single_class(obj));
+ return mod_include(argc, argv, rb_singleton_class(obj));
}
void
rb_extend_object(obj, module)
VALUE obj, module;
{
- rb_include_module(rb_single_class(obj), module);
+ rb_include_module(rb_singleton_class(obj), module);
}
-extern VALUE C_Kernel;
-extern VALUE C_Module;
+extern VALUE cKernel;
+extern VALUE cModule;
+VALUE f_trace_var();
+VALUE f_untrace_var();
+
+void
Init_eval()
{
match = rb_intern("=~");
@@ -2395,126 +2850,137 @@ Init_eval()
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, "method_missing", Fmissing, -1);
-
- rb_define_method(C_Module, "include", Fmod_include, -1);
- rb_define_method(CLASS_OF(TopSelf), "include", Ftop_include, -1);
- rb_define_method(C_Object, "extend", Fobj_extend, -1);
+ rb_global_variable(&the_dyna_vars);
+ rb_define_private_method(cKernel, "exit", f_exit, -1);
+ rb_define_private_method(cKernel, "eval", f_eval, 1);
+ rb_define_private_method(cKernel, "iterator?", f_iterator_p, 0);
+ rb_define_private_method(cKernel, "method_missing", f_missing, -1);
+ rb_define_private_method(cKernel, "loop", f_loop, 0);
+ rb_define_private_method(cKernel, "caller", f_caller, -1);
+
+ rb_define_method(cKernel, "send", f_send, -1);
+
+ rb_define_method(cModule, "include", mod_include, -1);
+ rb_define_method(cModule, "public", mod_public, -1);
+ rb_define_method(cModule, "private", mod_private, -1);
+ rb_define_method(cModule, "module_function", mod_modfunc, -1);
+
+ rb_define_method(CLASS_OF(TopSelf), "include", top_include, -1);
+ rb_define_method(cObject, "extend", obj_extend, -1);
+
+ rb_define_private_method(cKernel, "trace_var", f_trace_var, -1);
+ rb_define_private_method(cKernel, "untrace_var", f_untrace_var, 1);
}
+VALUE f_autoload();
+
+void
Init_load()
{
- char *path;
-
rb_load_path = ary_new();
- rb_define_variable("$:", &rb_load_path, Qnil, rb_readonly_hook, 0);
- rb_define_variable("$LOAD_PATH", &rb_load_path, Qnil, rb_readonly_hook, 0);
+ rb_define_readonly_variable("$:", &rb_load_path);
+ rb_define_readonly_variable("$LOAD_PATH", &rb_load_path);
- rb_loadfiles = ary_new();
- rb_define_variable("$\"", &rb_load_path, Qnil, rb_readonly_hook, 0);
- rb_define_variable("$LOAD_FILES", &rb_load_path, Qnil, rb_readonly_hook,0);
- addpath(getenv("RUBYLIB"));
- addpath(RUBY_LIB);
+ rb_features = ary_new();
+ rb_define_readonly_variable("$\"", &rb_features);
- rb_define_private_method(C_Kernel, "load", Fload, 1);
- rb_define_private_method(C_Kernel, "require", Frequire, 1);
+ rb_define_private_method(cKernel, "load", f_load, 1);
+ rb_define_private_method(cKernel, "require", f_require, 1);
+ rb_define_private_method(cKernel, "autoload", f_autoload, 2);
}
-void
+static void
scope_dup(scope)
struct SCOPE *scope;
{
ID *tbl;
VALUE *vars;
- if (scope->flags & SCOPE_MALLOCED) return;
- if (!scope->local_tbl) return;
+ if (scope->flag == SCOPE_MALLOC) return;
- tbl = scope->local_tbl;
- scope->local_tbl = ALLOC_N(ID, tbl[0]+1);
- MEMCPY(scope->local_tbl, tbl, ID, tbl[0]+1);
- vars = scope->local_vars;
- scope->local_vars = ALLOC_N(VALUE, tbl[0]);
- MEMCPY(scope->local_vars, vars, VALUE, tbl[0]);
- scope->flags |= SCOPE_MALLOCED;
+ if (scope->local_tbl) {
+ tbl = scope->local_tbl;
+ scope->local_tbl = ALLOC_N(ID, tbl[0]+1);
+ MEMCPY(scope->local_tbl, tbl, ID, tbl[0]+1);
+ vars = scope->local_vars;
+ scope->local_vars = ALLOC_N(VALUE, tbl[0]);
+ MEMCPY(scope->local_vars, vars, VALUE, tbl[0]);
+ scope->flag = SCOPE_MALLOC;
+ }
}
-VALUE C_Block;
static ID blkdata;
static void
blk_mark(data)
struct BLOCK *data;
{
- gc_mark_env(&data->env);
+ gc_mark_frame(&data->frame);
gc_mark(data->scope);
gc_mark(data->var);
gc_mark(data->body);
gc_mark(data->self);
+ gc_mark(data->d_vars);
}
static void
blk_free(data)
struct BLOCK *data;
{
- free(data->env.argv);
+ free(data->frame.argv);
}
static VALUE
-Sblk_new(class)
+proc_s_new(class)
+ VALUE class;
{
- VALUE blk;
+ VALUE proc;
struct BLOCK *data;
- struct SCOPE *scope;
- if (!iterator_p() && !Fiterator_p()) {
- Fail("tryed to create Block out of iterator");
+ if (!iterator_p() && !f_iterator_p()) {
+ Fail("tryed to create Procedure-Object out of iterator");
}
- if (the_block->block) return the_block->block;
- blk = obj_alloc(class);
+ proc = obj_alloc(class);
if (!blkdata) blkdata = rb_intern("blk");
- Make_Data_Struct(blk, blkdata, struct BLOCK, Qnil, blk_free, data);
+ Make_Data_Struct(proc, blkdata, struct BLOCK, blk_mark, 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);
+ data->frame.argv = ALLOC_N(VALUE, data->frame.argc);
+ MEMCPY(data->frame.argv, the_block->frame.argv, VALUE, data->frame.argc);
scope_dup(data->scope);
- the_block->block = blk;
- return blk;
+ return proc;
}
VALUE
-block_new()
+f_lambda()
{
- return Sblk_new(C_Block);
+ return proc_s_new(cProc);
}
static VALUE
-Fblk_call(blk, args)
- VALUE blk, args;
+proc_call(proc, args)
+ VALUE proc, args;
{
struct BLOCK *data;
- VALUE result;
+ VALUE result = Qnil;
int state;
- switch (RARRAY(args)->len) {
- case 0:
- args = Qnil;
- break;
- case 1:
- args = RARRAY(args)->ptr[0];
- break;
+ if (TYPE(args) == T_ARRAY) {
+ switch (RARRAY(args)->len) {
+ case 0:
+ args = 0;
+ break;
+ case 1:
+ args = RARRAY(args)->ptr[0];
+ break;
+ }
}
- Get_Data_Struct(blk, blkdata, struct BLOCK, data);
+ Get_Data_Struct(proc, blkdata, struct BLOCK, data);
/* PUSH BLOCK from data */
PUSH_BLOCK2(data);
@@ -2525,18 +2991,14 @@ Fblk_call(blk, args)
if (state == 0) {
result = rb_yield(args);
}
-
POP_TAG();
+
POP_ITER();
POP_BLOCK();
switch (state) {
case 0:
break;
- case TAG_RETRY:
- case IN_BLOCK|TAG_RETRY:
- Fail("retry from block-closure");
- break;
case TAG_BREAK:
case IN_BLOCK|TAG_BREAK:
Fail("break from block-closure");
@@ -2552,11 +3014,14 @@ Fblk_call(blk, args)
return result;
}
-Init_Block()
+void
+Init_Proc()
{
- C_Block = rb_define_class("Block", C_Object);
+ cProc = rb_define_class("Proc", cObject);
- rb_define_single_method(C_Block, "new", Sblk_new, 0);
+ rb_define_singleton_method(cProc, "new", proc_s_new, 0);
- rb_define_method(C_Block, "call", Fblk_call, -2);
+ rb_define_method(cProc, "call", proc_call, -2);
+ rb_define_private_method(cKernel, "lambda", f_lambda, 0);
+ rb_define_private_method(cKernel, "proc", f_lambda, 0);
}