summaryrefslogtreecommitdiff
path: root/parse.y
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 /parse.y
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 'parse.y')
-rw-r--r--parse.y963
1 files changed, 574 insertions, 389 deletions
diff --git a/parse.y b/parse.y
index 9ea1fb1622..cdecb958bc 100644
--- a/parse.y
+++ b/parse.y
@@ -24,21 +24,27 @@
# undef const
#endif
-#include "ident.h"
+#define ID_SCOPE_SHIFT 3
+#define ID_SCOPE_MASK 0x07
+#define ID_LOCAL 0x00
+#define ID_INSTANCE 0x01
+#define ID_GLOBAL 0x02
+#define ID_ATTRSET 0x03
+#define ID_CONST 0x04
+
#define is_id_nonop(id) ((id)>LAST_TOKEN)
#define is_local_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_LOCAL)
#define is_global_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_GLOBAL)
#define is_instance_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_INSTANCE)
#define is_attrset_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_ATTRSET)
#define is_const_id(id) (is_id_nonop(id)&&((id)&ID_SCOPE_MASK)==ID_CONST)
-#define is_nthref_id(id) (((id)&ID_SCOPE_MASK)==ID_NTHREF)
struct op_tbl {
ID token;
char *name;
};
-NODE *eval_tree = Qnil;
+NODE *eval_tree = 0;
char *sourcefile; /* current source file */
int sourceline; /* current line no. */
@@ -49,16 +55,16 @@ static enum lex_state {
EXPR_BEG, /* ignore newline, +/- is a sign. */
EXPR_MID, /* newline significant, +/- is a sign. */
EXPR_END, /* newline significant, +/- is a operator. */
+ EXPR_ARG, /* newline significant, +/- is a sign(meybe). */
EXPR_FNAME, /* ignore newline, +/- is a operator. */
} lex_state;
static int class_nest = 0;
static int in_single = 0;
-static ID cur_mid = Qnil;
+static ID cur_mid = 0;
static int value_expr();
static NODE *cond();
-static NODE *cond2();
static NODE *block_append();
static NODE *list_append();
@@ -66,11 +72,13 @@ static NODE *list_concat();
static NODE *list_copy();
static NODE *expand_op();
static NODE *call_op();
+static int in_defined = 0;
static NODE *gettable();
static NODE *asignable();
static NODE *aryset();
static NODE *attrset();
+static void backref_error();
static void local_push();
static void local_pop();
@@ -78,12 +86,17 @@ static int local_cnt();
static int local_id();
static ID *local_tbl();
+static struct RVarmap *dyna_push();
+static void dyna_pop();
+static int dyna_in_block();
+
+VALUE dyna_var_ref();
+#define dyna_id(id) dyna_var_ref(id)
+
#define cref_push() NEW_CREF(0)
static void cref_pop();
static NODE *cref_list;
-struct global_entry* rb_global_entry();
-
static void top_local_init();
static void top_local_setup();
%}
@@ -93,6 +106,7 @@ static void top_local_setup();
VALUE val;
ID id;
int num;
+ struct RVarmap *vars;
}
%token CLASS
@@ -100,7 +114,7 @@ static void top_local_setup();
DEF
UNDEF
BEGIN
- RESQUE
+ RESCUE
ENSURE
END
IF
@@ -124,24 +138,27 @@ static void top_local_setup();
NIL
AND
OR
+ NOT
_FILE_
_LINE_
IF_MOD
WHILE_MOD
ALIAS
+ DEFINED
-%token <id> IDENTIFIER GVAR IVAR CONSTANT NTH_REF
+%token <id> IDENTIFIER FID GVAR IVAR CONSTANT
%token <val> INTEGER FLOAT STRING XSTRING REGEXP
-%token <node> STRING2 XSTRING2 DREGEXP
+%token <node> STRING2 XSTRING2 DREGEXP NTH_REF BACK_REF
%type <node> singleton
%type <val> literal numeric
%type <node> compexpr exprs expr arg primary var_ref
-%type <node> if_tail opt_else case_body cases resque ensure
+%type <node> if_tail opt_else case_body cases rescue ensure
%type <node> call_args call_args0 args args2 opt_args
-%type <node> f_arglist f_args array assoc_list assocs assoc
-%type <node> mlhs mlhs_head mlhs_tail lhs iter_var opt_iter_var
-%type <id> superclass variable symbol
+%type <node> superclass f_arglist f_args f_optarg f_opt
+%type <node> array assoc_list assocs assoc undef_list
+%type <node> mlhs mlhs_head mlhs_tail lhs iter_var opt_iter_var backref
+%type <id> variable symbol operation
%type <id> cname fname op rest_arg
%type <num> f_arg
%token UPLUS /* unary+ */
@@ -160,7 +177,10 @@ static void top_local_setup();
%token COLON2 /* :: */
%token <id> OP_ASGN /* +=, -= etc. */
%token ASSOC /* => */
-%token LPAREN LBRACK LBRACE
+%token LPAREN /* ( */
+%token LBRACK /* [ */
+%token LBRACE /* { */
+%token STAR /* * */
%token SYMBEG
/*
@@ -168,10 +188,9 @@ static void top_local_setup();
*/
%left IF_MOD WHILE_MOD
+%right NOT
%left OR AND
-%left YIELD RETURN FAIL
%right '=' OP_ASGN
-%right COLON2
%nonassoc DOT2 DOT3
%left OROP
%left ANDOP
@@ -184,6 +203,7 @@ static void top_local_setup();
%left '*' '/' '%'
%right '!' '~' UPLUS UMINUS
%right POW
+%left COLON2
%token LAST_TOKEN
@@ -246,24 +266,29 @@ expr : mlhs '=' args2
value_expr($2);
$$ = NEW_YIELD($2);
}
- | IDENTIFIER call_args0
+ | DEFINED {in_defined = 1;} arg
+ {
+ in_defined = 0;
+ $$ = NEW_DEFINED($3);
+ }
+ | operation call_args0
{
$$ = NEW_FCALL($1, $2);
}
- | primary '.' IDENTIFIER call_args0
+ | primary '.' operation call_args0
{
value_expr($1);
$$ = NEW_CALL($1, $3, $4);
}
| SUPER call_args0
{
- if (!cur_mid && !in_single)
+ if (!cur_mid && !in_single && !in_defined)
Error("super called outside of method");
$$ = NEW_SUPER($2);
}
- | UNDEF fname
+ | UNDEF undef_list
{
- $$ = NEW_UNDEF($2);
+ $$ = $2;
}
| ALIAS fname {lex_state = EXPR_FNAME;} fname
{
@@ -271,27 +296,41 @@ expr : mlhs '=' args2
}
| expr IF_MOD expr
{
+ value_expr($3);
$$ = NEW_IF(cond($3), $1, Qnil);
}
| expr WHILE_MOD expr
{
- $$ = NEW_WHILE2(cond($3), $1);
+ value_expr($3);
+ if (nd_type($1) == NODE_BEGIN) {
+ $$ = NEW_WHILE2(cond($3), $1);
+ }
+ else {
+ $$ = NEW_WHILE(cond($3), $1);
+ }
}
| expr AND expr
{
+ value_expr($1);
$$ = NEW_AND(cond($1), cond($3));
}
| expr OR expr
{
+ value_expr($1);
$$ = NEW_OR(cond($1), cond($3));
}
+ | NOT expr
+ {
+ value_expr($2);
+ $$ = NEW_NOT(cond($2));
+ }
| arg
mlhs : mlhs_head
{
$$ = NEW_MASGN(NEW_LIST($1), Qnil);
}
- | mlhs_head '*' lhs
+ | mlhs_head STAR lhs
{
$$ = NEW_MASGN(NEW_LIST($1), $3);
}
@@ -299,7 +338,7 @@ mlhs : mlhs_head
{
$$ = NEW_MASGN(list_concat(NEW_LIST($1),$2),Qnil);
}
- | mlhs_head mlhs_tail comma '*' lhs
+ | mlhs_head mlhs_tail comma STAR lhs
{
$$ = NEW_MASGN(list_concat(NEW_LIST($1),$2),$5);
}
@@ -327,6 +366,11 @@ lhs : variable
{
$$ = attrset($1, $3, Qnil);
}
+ | backref
+ {
+ backref_error($1);
+ $$ = Qnil;
+ }
cname : IDENTIFIER
{
@@ -335,6 +379,7 @@ cname : IDENTIFIER
| CONSTANT
fname : IDENTIFIER
+ | FID
| CONSTANT
| op
{
@@ -342,8 +387,16 @@ fname : IDENTIFIER
$$ = $1;
}
-op : COLON2 { $$ = COLON2; }
- | DOT2 { $$ = DOT2; }
+undef_list : fname
+ {
+ $$ = NEW_UNDEF($1);
+ }
+ | undef_list ',' fname
+ {
+ $$ = block_append($1, NEW_UNDEF($3));
+ }
+
+op : DOT2 { $$ = DOT2; }
| '|' { $$ = '|'; }
| '^' { $$ = '^'; }
| '&' { $$ = '&'; }
@@ -359,6 +412,7 @@ op : COLON2 { $$ = COLON2; }
| '+' { $$ = '+'; }
| '-' { $$ = '-'; }
| '*' { $$ = '*'; }
+ | STAR { $$ = '*'; }
| '/' { $$ = '/'; }
| '%' { $$ = '%'; }
| POW { $$ = POW; }
@@ -381,13 +435,20 @@ arg : variable '=' arg
{
$$ = attrset($1, $3, $5);
}
+ | backref '=' arg
+ {
+ value_expr($3);
+ backref_error($1);
+ $$ = Qnil;
+ }
| variable OP_ASGN arg
{
NODE *val;
value_expr($3);
if (is_local_id($1)) {
- val = NEW_LVAR($1);
+ if (local_id($1)) val = NEW_LVAR($1);
+ else val = NEW_DVAR($1);
}
else if (is_global_id($1)) {
val = NEW_GVAR($1);
@@ -411,33 +472,22 @@ arg : variable '=' arg
{
$$ = NEW_OP_ASGN2($1, $4, $5);
}
+ | backref OP_ASGN arg
+ {
+ backref_error($1);
+ $$ = Qnil;
+ }
| arg DOT2 arg
{
- $$ = call_op($1, DOT2, 1, $3);
+ $$ = NEW_DOT2($1, $3);
}
| arg DOT3 arg
{
- $$ = NEW_DOT3(cond2($1), cond2($3));
+ $$ = NEW_DOT3($1, $3);
}
| arg '+' arg
{
- $$ = Qnil;
- if ($1 && $3
- && (nd_type($3) == NODE_LIT
- || nd_type($3) == NODE_STR)
- && nd_type($1) == NODE_CALL && $1->nd_mid == '+') {
- if ($1->nd_args->nd_head == Qnil)
- Bug("bad operand for `+'");
- if (nd_type($1->nd_args->nd_head) == NODE_LIT
- || nd_type($1->nd_args->nd_head) == NODE_STR) {
- $1->nd_args->nd_head =
- expand_op($1->nd_args->nd_head, '+', $3);
- $$ = $1;
- }
- }
- if ($$ == Qnil) {
- $$ = call_op($1, '+', 1, $3);
- }
+ $$ = call_op($1, '+', 1, $3);
}
| arg '-' arg
{
@@ -517,20 +567,12 @@ arg : variable '=' arg
}
| '!' arg
{
+ value_expr($2);
$$ = NEW_NOT(cond($2));
}
| '~' arg
{
- if ($2
- && (nd_type($2) == NODE_STR
- || (nd_type($2) == NODE_LIT
- && (TYPE($2->nd_lit) == T_REGEXP
- || TYPE($2->nd_lit) == T_STRING)))) {
- $$ = NEW_CALL($2, '~', Qnil);
- }
- else {
- $$ = call_op($2, '~', 0);
- }
+ $$ = call_op($2, '~', 0);
}
| arg LSHFT arg
{
@@ -540,16 +582,18 @@ arg : variable '=' arg
{
$$ = call_op($1, RSHFT, 1, $3);
}
- | arg COLON2 arg
+ | arg COLON2 cname
{
- $$ = call_op($1, COLON2, 1, $3);
+ $$ = NEW_COLON2($1, $3);
}
| arg ANDOP arg
{
+ value_expr($1);
$$ = NEW_AND(cond($1), cond($3));
}
| arg OROP arg
{
+ value_expr($1);
$$ = NEW_OR(cond($1), cond($3));
}
| primary
@@ -562,10 +606,6 @@ call_args : /* none */
$$ = Qnil;
}
| call_args0 opt_nl
- | '*' arg opt_nl
- {
- $$ = $2;
- }
call_args0 : args
| assocs
@@ -576,10 +616,19 @@ call_args0 : args
{
$$ = list_append($1, NEW_HASH($3));
}
- | args comma '*' arg
+ | args comma assocs comma STAR arg
+ {
+ $$ = list_append($1, NEW_HASH($3));
+ $$ = call_op($$, '+', 1, $6);
+ }
+ | args comma STAR arg
{
$$ = call_op($1, '+', 1, $4);
}
+ | STAR arg
+ {
+ $$ = $2;
+ }
opt_args : /* none */
{
@@ -630,15 +679,16 @@ primary : literal
| XSTRING2
| DREGEXP
| var_ref
+ | backref
| SUPER '(' call_args rparen
{
- if (!cur_mid && !in_single)
+ if (!cur_mid && !in_single && !in_defined)
Error("super called outside of method");
$$ = NEW_SUPER($3);
}
| SUPER
{
- if (!cur_mid && !in_single)
+ if (!cur_mid && !in_single && !in_defined)
Error("super called outside of method");
$$ = NEW_ZSUPER();
}
@@ -710,25 +760,39 @@ primary : literal
{
$$ = NEW_YIELD(Qnil);
}
- | primary '{' opt_iter_var compexpr rbrace
+ | DEFINED '(' {in_defined = 1;} arg ')'
+ {
+ in_defined = 0;
+ $$ = NEW_DEFINED($4);
+ }
+ | primary '{'
+ {
+ $<vars>$ = dyna_push();
+ }
+ opt_iter_var
+ compexpr rbrace
{
if (nd_type($1) == NODE_LVAR
- || nd_type($1) == NODE_LVAR2
|| nd_type($1) == NODE_CVAR) {
$1 = NEW_FCALL($1->nd_vid, Qnil);
}
- $$ = NEW_ITER($3, $1, $4);
+ $$ = NEW_ITER($4, $1, $5);
+ dyna_pop($<vars>3);
+ }
+ | FID
+ {
+ $$ = NEW_FCALL($1, Qnil);
}
- | IDENTIFIER '(' call_args rparen
+ | operation '(' call_args rparen
{
$$ = NEW_FCALL($1, $3);
}
- | primary '.' IDENTIFIER '(' call_args rparen
+ | primary '.' operation '(' call_args rparen
{
value_expr($1);
$$ = NEW_CALL($1, $3, $5);
}
- | primary '.' IDENTIFIER
+ | primary '.' operation
{
value_expr($1);
$$ = NEW_CALL($1, $3, Qnil);
@@ -738,10 +802,12 @@ primary : literal
if_tail
END
{
+ value_expr($2);
$$ = NEW_IF(cond($2), $4, $5);
}
| WHILE expr term compexpr END
{
+ value_expr($2);
$$ = NEW_WHILE(cond($2), $4);
}
| CASE compexpr
@@ -751,29 +817,20 @@ primary : literal
value_expr($2);
$$ = NEW_CASE($2, $3);
}
- | FOR iter_var IN expr term
- compexpr
- END
+ | FOR iter_var IN expr term compexpr END
{
- value_expr($4);
+ value_expr($2);
$$ = NEW_FOR($2, $4, $6);
}
| BEGIN
compexpr
- resque
+ rescue
ensure
END
{
- if ($3 == Qnil && $4 == Qnil) {
- $$ = $2;
- }
- else {
- $$ = NEW_BEGIN($2, $3, $4);
- }
+ $$ = NEW_BEGIN($2, $3, $4);
}
- | LPAREN expr
- opt_nl
- rparen
+ | LPAREN exprs opt_nl rparen
{
$$ = $2;
}
@@ -823,13 +880,14 @@ primary : literal
{
$$ = NEW_DEFN($2, $4, $5, class_nest?0:1);
local_pop();
- cur_mid = Qnil;
+ cur_mid = 0;
}
| DEF singleton '.' fname
{
value_expr($2);
in_single++;
local_push();
+ lex_state = EXPR_END; /* force for args */
}
f_arglist
compexpr
@@ -849,6 +907,7 @@ if_tail : opt_else
compexpr
if_tail
{
+ value_expr($2);
$$ = NEW_IF(cond($2), $4, $5);
}
@@ -864,7 +923,11 @@ opt_else : /* none */
iter_var : lhs
| mlhs
-opt_iter_var : '|' /* none */ '|'
+opt_iter_var : /* node */
+ {
+ $$ = Qnil;
+ }
+ | '|' /* none */ '|'
{
$$ = Qnil;
}
@@ -887,11 +950,11 @@ case_body : WHEN args then
cases : opt_else
| case_body
-resque : /* none */
+rescue : /* none */
{
$$ = Qnil;
}
- | RESQUE compexpr
+ | RESCUE compexpr
{
if ($2 == Qnil)
$$ = (NODE*)1;
@@ -926,7 +989,6 @@ variable : IDENTIFIER
| IVAR
| GVAR
| CONSTANT
- | NTH_REF
| NIL
{
$$ = NIL;
@@ -941,6 +1003,9 @@ var_ref : variable
$$ = gettable($1);
}
+backref : NTH_REF
+ | BACK_REF
+
superclass : term
{
$$ = Qnil;
@@ -949,7 +1014,7 @@ superclass : term
{
lex_state = EXPR_BEG;
}
- CONSTANT
+ expr term
{
$$ = $3;
}
@@ -958,36 +1023,47 @@ f_arglist : '(' f_args rparen
{
$$ = $2;
}
- | term
+ | f_args term
{
- $$ = NEW_ARGS(0, -1);
+ $$ = $1;
}
f_args : /* no arg */
{
- $$ = NEW_ARGS(0, -1);
+ $$ = NEW_ARGS(0, 0, -1);
}
| f_arg
{
- $$ = NEW_ARGS($1, -1);
+ $$ = NEW_ARGS($1, 0, -1);
}
| f_arg comma rest_arg
{
- $$ = NEW_ARGS($1, $3);
+ $$ = NEW_ARGS($1, 0, $3);
}
- | rest_arg
+ | f_arg comma f_optarg
{
- $$ = NEW_ARGS(Qnil, $1);
+ $$ = NEW_ARGS($1, $3, -1);
}
- | f_arg error
+ | f_arg comma f_optarg comma rest_arg
{
- lex_state = EXPR_BEG;
- $$ = NEW_ARGS($1, -1);
+ $$ = NEW_ARGS($1, $3, $5);
+ }
+ | f_optarg
+ {
+ $$ = NEW_ARGS(0, $1, -1);
+ }
+ | f_optarg comma rest_arg
+ {
+ $$ = NEW_ARGS(0, $1, $3);
+ }
+ | rest_arg
+ {
+ $$ = NEW_ARGS(0, 0, $1);
}
| error
{
lex_state = EXPR_BEG;
- $$ = NEW_ARGS(0, -1);
+ $$ = NEW_ARGS(0, 0, -1);
}
f_arg : IDENTIFIER
@@ -1005,7 +1081,23 @@ f_arg : IDENTIFIER
$$ += 1;
}
-rest_arg : '*' IDENTIFIER
+f_opt : IDENTIFIER '=' arg
+ {
+ if (!is_local_id($1))
+ Error("formal argument must be local variable");
+ $$ = asignable($1, $3);
+ }
+
+f_optarg : f_opt
+ {
+ $$ = NEW_BLOCK($1);
+ }
+ | f_optarg comma f_opt
+ {
+ $$ = block_append($1, $3);
+ }
+
+rest_arg : STAR IDENTIFIER
{
if (!is_local_id($2))
Error("rest argument must be local variable");
@@ -1025,7 +1117,7 @@ singleton : var_ref
$$ = $1;
}
}
- | LPAREN compexpr rparen
+ | LPAREN expr opt_nl rparen
{
switch (nd_type($2)) {
case NODE_STR:
@@ -1048,6 +1140,9 @@ assoc_list : /* none */
$$ = Qnil;
}
| assocs trailer
+ {
+ $$ = $1;
+ }
| args trailer
{
if ($1->nd_alen%2 != 0) {
@@ -1067,6 +1162,9 @@ assoc : arg ASSOC arg
$$ = list_append(NEW_LIST($1), $3);
}
+operation : IDENTIFIER
+ | FID
+
opt_term : /* none */
| term
@@ -1109,7 +1207,6 @@ VALUE newinteger();
char *strdup();
static NODE *var_extend();
-static void read_escape();
#define LEAVE_BS 1
@@ -1122,7 +1219,7 @@ lex_setsrc(src, ptr, len)
char *ptr;
int len;
{
- sourcefile = (char*)strdup(src);
+ sourcefile = strdup(src);
sourceline = 1;
lex_p = ptr;
@@ -1151,7 +1248,7 @@ do { \
#define tokfix() (tokenbuf[tokidx]='\0')
#define tok() tokenbuf
#define toklen() tokidx
-#define toknow() &toknbuf[tokidx]
+#define toklast() (tokidx>0?tokenbuf[tokidx-1]:0)
char *
newtok()
@@ -1179,6 +1276,88 @@ tokadd(c)
}
static int
+read_escape()
+{
+ int c;
+
+ switch (c = nextc()) {
+ case '\\': /* Backslash */
+ return c;
+
+ case 'n': /* newline */
+ return '\n';
+
+ case 't': /* horizontal tab */
+ return '\t';
+
+ case 'r': /* carriage-return */
+ return '\r';
+
+ case 'f': /* form-feed */
+ return '\f';
+
+ case 'v': /* vertical tab */
+ return '\13';
+
+ case 'a': /* alarm(bell) */
+ return '\007';
+
+ case 'e': /* escape */
+ return 033;
+
+ case '0': case '1': case '2': case '3': /* octal constant */
+ case '4': case '5': case '6': case '7':
+ pushback();
+ SCAN_OCT(c);
+ return c;
+
+ case 'x': /* hex constant */
+ SCAN_HEX(c);
+ return c;
+
+ case 'b': /* backspace */
+ return '\b';
+
+ case 'M':
+ if ((c = nextc()) != '-') {
+ Error("Invalid escape character syntax");
+ return '\0';
+ }
+ if ((c = nextc()) == '\\') {
+ return read_escape() | 0x80;
+ }
+ else if (c == -1) goto eof;
+ else {
+ return ((c & 0xff) | 0x80);
+ }
+
+ case 'C':
+ if ((c = nextc()) != '-') {
+ Error("Invalid escape character syntax");
+ return '\0';
+ }
+ case 'c':
+ case '^':
+ if ((c = nextc())== '\\') {
+ c = read_escape();
+ }
+ else if (c == '?')
+ return 0177;
+ else if (c == -1) goto eof;
+ return c & 0x9f;
+
+ eof:
+ case -1:
+ Error("Invalid escape character syntax");
+ pushback();
+ return '\0';
+
+ default:
+ return c;
+ }
+}
+
+static int
parse_regx()
{
register int c;
@@ -1188,7 +1367,7 @@ parse_regx()
NODE *list = Qnil;
newtok();
- while (c = nextc()) {
+ while ((c = nextc()) != -1) {
switch (c) {
case '[':
in_brack = 1;
@@ -1235,7 +1414,8 @@ parse_regx()
/* fall through */
default:
pushback();
- read_escape(LEAVE_BS);
+ tokadd('\\');
+ tokadd(read_escape());
}
continue;
@@ -1247,6 +1427,7 @@ parse_regx()
casefold = 1;
}
else {
+ casefold = 0;
pushback();
}
@@ -1263,7 +1444,7 @@ parse_regx()
return DREGEXP;
}
else {
- yylval.val = regexp_new(tok(), toklen(), casefold);
+ yylval.val = reg_new(tok(), toklen(), casefold);
return REGEXP;
}
case -1:
@@ -1279,6 +1460,8 @@ parse_regx()
}
tokadd(c);
}
+ Error("unterminated regexp");
+ return 0;
}
static int
@@ -1287,7 +1470,6 @@ parse_string(term)
{
int c;
NODE *list = Qnil;
- ID id;
int strstart;
strstart = sourceline;
@@ -1320,10 +1502,9 @@ parse_string(term)
tokadd(c);
}
else {
- int flags = 0;
- if (term != '"') flags = LEAVE_BS;
pushback();
- read_escape(flags);
+ if (term != '"') tokadd('\\');
+ tokadd(read_escape());
}
continue;
}
@@ -1369,6 +1550,7 @@ static struct kwtable {
"class", CLASS, EXPR_BEG,
"continue", CONTINUE, EXPR_END,
"def", DEF, EXPR_FNAME,
+ "defined?", DEFINED, EXPR_END,
"else", ELSE, EXPR_BEG,
"elsif", ELSIF, EXPR_BEG,
"end", END, EXPR_END,
@@ -1379,9 +1561,10 @@ static struct kwtable {
"in", IN, EXPR_BEG,
"module", MODULE, EXPR_BEG,
"nil", NIL, EXPR_END,
+ "not", NOT, EXPR_BEG,
"or", OR, EXPR_BEG,
"redo", REDO, EXPR_END,
- "resque", RESQUE, EXPR_BEG,
+ "rescue", RESCUE, EXPR_BEG,
"retry", RETRY, EXPR_END,
"return", RETURN, EXPR_MID,
"self", SELF, EXPR_END,
@@ -1393,10 +1576,17 @@ static struct kwtable {
"yield", YIELD, EXPR_END,
};
+static void
+arg_ambiguous()
+{
+ Warning("ambiguous first argument; make sure");
+}
+
static int
yylex()
{
register int c;
+ int space_seen = 0;
struct kwtable *low = kwtable, *mid, *high = LAST(kwtable);
retry:
@@ -1410,6 +1600,7 @@ retry:
/* white spaces */
case ' ': case '\t': case '\f': case '\r':
case '\13': /* '\v' */
+ space_seen = 1;
goto retry;
case '#': /* it's a comment */
@@ -1424,14 +1615,15 @@ retry:
/* fall through */
case '\n':
sourceline++;
- if (lex_state == EXPR_BEG || lex_state == EXPR_FNAME)
+ if (lex_state == EXPR_BEG
+ || lex_state == EXPR_FNAME)
goto retry;
lex_state = EXPR_BEG;
return '\n';
case '*':
- lex_state = EXPR_BEG;
if ((c = nextc()) == '*') {
+ lex_state = EXPR_BEG;
if (nextc() == '=') {
yylval.id = POW;
return OP_ASGN;
@@ -1439,11 +1631,21 @@ retry:
pushback();
return POW;
}
- else if (c == '=') {
+ if (c == '=') {
yylval.id = '*';
+ lex_state = EXPR_BEG;
return OP_ASGN;
}
pushback();
+ if (lex_state == EXPR_ARG && space_seen && !isspace(c)){
+ arg_ambiguous();
+ lex_state = EXPR_BEG;
+ return STAR;
+ }
+ if (lex_state == EXPR_BEG) {
+ return STAR;
+ }
+ lex_state = EXPR_BEG;
return '*';
case '!':
@@ -1558,9 +1760,7 @@ retry:
case '?':
if ((c = nextc()) == '\\') {
- newtok();
- read_escape(0);
- c = tok()[0];
+ c = read_escape();
}
c &= 0xff;
yylval.val = INT2FIX(c);
@@ -1592,21 +1792,27 @@ retry:
return '|';
case '+':
+ c = nextc();
if (lex_state == EXPR_FNAME) {
- if ((c = nextc()) == '@') {
+ if (c == '@') {
return UPLUS;
}
pushback();
return '+';
}
- c = nextc();
+ if (lex_state == EXPR_ARG) {
+ if (!space_seen || c == '=' || isspace(c)) {
+ arg_ambiguous();
+ lex_state = EXPR_END;
+ }
+ }
if (lex_state != EXPR_END) {
pushback();
if (isdigit(c)) {
goto start_num;
}
lex_state = EXPR_BEG;
- return UMINUS;
+ return UPLUS;
}
lex_state = EXPR_BEG;
if (c == '=') {
@@ -1617,21 +1823,28 @@ retry:
return '+';
case '-':
+ c = nextc();
if (lex_state == EXPR_FNAME) {
- if ((c = nextc()) == '@') {
+ if (c == '@') {
return UMINUS;
}
pushback();
return '-';
}
- c = nextc();
+ if (lex_state == EXPR_ARG) {
+ if (!space_seen || c == '=' || isspace(c)) {
+ arg_ambiguous();
+ lex_state = EXPR_END;
+ }
+ }
if (lex_state != EXPR_END) {
- pushback();
if (isdigit(c)) {
+ pushback();
c = '-';
goto start_num;
}
lex_state = EXPR_BEG;
+ pushback();
return UMINUS;
}
lex_state = EXPR_BEG;
@@ -1774,16 +1987,25 @@ retry:
return SYMBEG;
case '/':
- if (lex_state == EXPR_BEG || lex_state == EXPR_MID) {
+ if (lex_state == EXPR_BEG
+ || lex_state == EXPR_MID) {
return parse_regx();
}
+ c = nextc();
+ if (lex_state == EXPR_ARG) {
+ if (space_seen && c != '=' && !isspace(c)) {
+ pushback();
+ arg_ambiguous();
+ return parse_regx();
+ }
+ }
lex_state = EXPR_BEG;
- if (nextc() == '=') {
+ if (c == '=') {
yylval.id = '/';
return OP_ASGN;
}
pushback();
- return c;
+ return '/';
case '^':
lex_state = EXPR_BEG;
@@ -1795,6 +2017,9 @@ retry:
return c;
case ',':
+ lex_state = EXPR_BEG;
+ return c;
+
case ';':
lex_state = EXPR_BEG;
return c;
@@ -1809,15 +2034,23 @@ retry:
return c;
case '(':
- if (lex_state != EXPR_END)
+ if (lex_state == EXPR_BEG
+ || lex_state == EXPR_MID) {
c = LPAREN;
- lex_state = EXPR_BEG;
+ lex_state = EXPR_BEG;
+ }
+ else if (lex_state == EXPR_ARG && space_seen) {
+ arg_ambiguous();
+ c = LPAREN;
+ lex_state = EXPR_BEG;
+ }
+ else {
+ lex_state = EXPR_BEG;
+ }
return c;
case '[':
- if (lex_state == EXPR_BEG || lex_state == EXPR_MID)
- c = LBRACK;
- else if (lex_state == EXPR_FNAME) {
+ if (lex_state == EXPR_FNAME) {
if ((c = nextc()) == ']') {
if ((c = nextc()) == '=') {
return ASET;
@@ -1828,11 +2061,19 @@ retry:
pushback();
return '[';
}
+ else if (lex_state == EXPR_BEG
+ || lex_state == EXPR_MID) {
+ c = LBRACK;
+ }
+ else if (lex_state == EXPR_ARG && space_seen) {
+ arg_ambiguous();
+ c = LBRACK;
+ }
lex_state = EXPR_BEG;
return c;
case '{':
- if (lex_state != EXPR_END)
+ if (lex_state != EXPR_END && lex_state != EXPR_ARG)
c = LBRACE;
lex_state = EXPR_BEG;
return c;
@@ -1841,6 +2082,7 @@ retry:
c = nextc();
if (c == '\n') {
sourceline++;
+ space_seen = 1;
goto retry; /* skip \\n */
}
pushback();
@@ -1860,6 +2102,9 @@ retry:
newtok();
c = nextc();
switch (c) {
+ case '~': /* $~: match-data */
+ local_cnt('~');
+ /* fall through */
case '*': /* $*: argv */
case '$': /* $$: pid */
case '?': /* $?: last status */
@@ -1870,51 +2115,42 @@ retry:
case ',': /* $,: output field separator */
case '.': /* $.: last read line number */
case '_': /* $_: last read line string */
- case '&': /* $&: last match */
- case '`': /* $&: string before last match */
- case '\'': /* $&: string after last match */
- case '+': /* $&: string matches last paren. */
- case '~': /* $~: match-data */
case '=': /* $=: ignorecase */
case ':': /* $:: load path */
case '<': /* $<: reading filename */
case '>': /* $>: default output handle */
- case '"': /* $": already loaded files */
+ case '\"': /* $": already loaded files */
tokadd('$');
tokadd(c);
tokfix();
yylval.id = rb_intern(tok());
return GVAR;
- case '1':
- case '2':
- case '3':
- case '4':
- case '5':
- case '6':
- case '7':
- case '8':
- case '9':
+ case '&': /* $&: last match */
+ case '`': /* $`: string before last match */
+ case '\'': /* $': string after last match */
+ case '+': /* $+: string matches last paren. */
+ yylval.node = NEW_BACK_REF(c);
+ return BACK_REF;
+
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
while (isdigit(c)) {
tokadd(c);
c = nextc();
}
pushback();
tokfix();
- {
- ID id = atoi(tok());
- id <<= ID_SCOPE_SHIFT;
- id |= ID_NTHREF;
- yylval.id = id;
- return NTH_REF;
- }
+ yylval.node = NEW_NTH_REF(atoi(tok()));
+ return NTH_REF;
- case '0':
default:
if (!is_identchar(c)) {
pushback();
return '$';
}
+ case '0':
tokadd('$');
}
break;
@@ -1947,7 +2183,12 @@ retry:
}
c = nextc();
}
- pushback();
+ if (c == '!' || c == '?') {
+ tokadd(c);
+ }
+ else {
+ pushback();
+ }
tokfix();
{
@@ -1955,9 +2196,11 @@ retry:
switch (tok()[0]) {
case '$':
+ lex_state = EXPR_END;
result = GVAR;
break;
case '@':
+ lex_state = EXPR_END;
result = IVAR;
break;
default:
@@ -1967,7 +2210,8 @@ retry:
if (( c = strcmp(mid->name, tok())) == 0) {
enum lex_state state = lex_state;
lex_state = mid->state;
- if (state != EXPR_BEG) {
+ if (state != EXPR_BEG
+ && state != EXPR_BEG) {
if (mid->id == IF) return IF_MOD;
if (mid->id == WHILE) return WHILE_MOD;
}
@@ -1982,6 +2226,7 @@ retry:
}
if (lex_state == EXPR_FNAME) {
+ lex_state = EXPR_END;
if ((c = nextc()) == '=') {
tokadd(c);
}
@@ -1989,14 +2234,21 @@ retry:
pushback();
}
}
+ else if (lex_state == EXPR_BEG){
+ lex_state = EXPR_ARG;
+ }
+ else {
+ lex_state = EXPR_END;
+ }
if (isupper(tok()[0])) {
result = CONSTANT;
}
- else {
+ else if (toklast() == '!' || toklast() == '?') {
+ result = FID;
+ } else {
result = IDENTIFIER;
}
}
- lex_state = EXPR_END;
yylval.id = rb_intern(tok());
return result;
}
@@ -2007,16 +2259,16 @@ var_extend(list, term)
NODE *list;
char term;
{
- int c, t;
+ int c, t, brace;
VALUE ss;
+ NODE *node;
ID id;
c = nextc();
switch (c) {
- default:
- tokadd('#');
- pushback();
- return list;
+ case '$':
+ case '{':
+ break;
case '@':
t = nextc();
pushback();
@@ -2025,9 +2277,10 @@ var_extend(list, term)
tokadd(c);
return list;
}
- case '$':
- case '{':
- break;
+ default:
+ tokadd('#');
+ pushback();
+ return list;
}
ss = str_new(tok(), toklen());
@@ -2038,49 +2291,64 @@ var_extend(list, term)
list_append(list, NEW_STR(ss));
}
newtok();
- if (c == '{') {
- while ((c = nextc()) != '}') {
- if (c == -1) {
- return (NODE*)-1;
- }
- if (isspace(c)) {
- Error("Invalid variable name in string");
- break;
- }
- if (c == term) {
- Error("Inmature variable name in string");
- pushback();
- return list;
- }
- tokadd(c);
- }
+ if (c == '{') {
+ brace = 1;
+ c = nextc();
}
else {
+ brace = 0;
+ }
+
+ switch (c) {
+ case '$':
+ c = nextc();
+ if (c == -1) return (NODE*)-1;
switch (c) {
- case '$':
- tokadd(c);
+ case '&':
+ case '`':
+ case '\'':
+ case '+':
+ node = NEW_BACK_REF(c);
c = nextc();
- if (c == -1) return (NODE*)-1;
- if (!is_identchar(c)) {
+ goto append_node;
+
+ case '~':
+ local_cnt('~');
+ id = '~';
+ goto id_node;
+
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ while (isdigit(c)) {
tokadd(c);
- goto fetch_id;
+ c = nextc();
}
- /* through */
- case '@':
- tokadd(c);
- c = nextc();
- break;
+ tokfix();
+ node = NEW_NTH_REF(atoi(tok()));
+ goto append_node;
}
- while (is_identchar(c)) {
+
+ tokadd('$');
+ if (!is_identchar(c)) {
tokadd(c);
- if (ismbchar(c)) {
- c = nextc();
- tokadd(c);
- }
+ goto fetch_id;
+ }
+ /* through */
+ case '@':
+ tokadd(c);
+ c = nextc();
+ break;
+ }
+ while (is_identchar(c)) {
+ tokadd(c);
+ if (ismbchar(c)) {
c = nextc();
+ tokadd(c);
}
- pushback();
+ c = nextc();
}
+
fetch_id:
tokfix();
if (strcmp("__LINE__", tok()) == 0)
@@ -2089,90 +2357,21 @@ var_extend(list, term)
id = _FILE_;
else
id = rb_intern(tok());
- list_append(list, gettable(id));
+ id_node:
+ node = gettable(id);
+
+ append_node:
+ if (brace) {
+ if (c != '}')
+ Error("Invalid variable name in string");
+ }
+ else pushback();
+
+ list_append(list, node);
newtok();
return list;
}
-static void
-read_escape(flag)
- int flag;
-{
- char c;
-
- switch (c = nextc()) {
- case '\\': /* Backslash */
- tokadd('\\');
- break;
-
- case 'n': /* newline */
- tokadd('\n');
- break;
-
- case 't': /* horizontal tab */
- tokadd('\t');
- break;
-
- case 'r': /* carriage-return */
- tokadd('\r');
- break;
-
- case 'f': /* form-feed */
- tokadd('\f');
- break;
-
- case 'v': /* vertical tab */
- tokadd('\13');
- break;
-
- case 'a': /* alarm(bell) */
- tokadd('\007');
- break;
-
- case 'e': /* escape */
- tokadd(033);
- break;
-
- case 'c':
- if ((c = nextc()) == '?')
- tokadd(0177);
- else {
- if (islower(c))
- c = toupper(c);
- c = c - '@';
- tokadd(c);
- }
- break;
-
- case '0': case '1': case '2': case '3':
- case '4': case '5': case '6': case '7':
- { /* octal constant */
- pushback();
- SCAN_OCT(c);
- tokadd(c);
- }
- break;
-
- case 'x': /* hex constant */
- {
- SCAN_HEX(c);
- tokadd(c);
- }
- break;
-
- case 'b': /* backspace */
- tokadd('\b');
- return;
-
- default:
- if (flag & LEAVE_BS) {
- tokadd('\\');
- }
- case '#':
- tokadd(c);
- break;
- }
-}
NODE*
newnode(type, a0, a1, a2)
@@ -2282,72 +2481,6 @@ list_concat(head, tail)
return head;
}
-static NODE*
-list_copy(list)
- NODE *list;
-{
- NODE *tmp;
-
- if (list == Qnil) return Qnil;
-
- tmp = Qnil;
- while(list) {
- tmp = list_append(tmp, list->nd_head);
- list = list->nd_next;
- }
- return tmp;
-}
-
-struct call_arg {
- ID id;
- VALUE recv;
- int narg;
- VALUE arg;
-};
-
-static VALUE
-call_lit(arg)
- struct call_arg *arg;
-{
- return rb_funcall(arg->recv, arg->id, arg->narg, arg->arg);
-}
-
-static VALUE
-except_lit()
-{
- extern VALUE errstr;
-
- Error("%s", RSTRING(errstr)->ptr);
- return Qnil;
-}
-
-static NODE *
-expand_op(recv, id, arg)
- NODE *recv, *arg;
- ID id;
-{
- struct call_arg arg_data;
- VALUE val;
- NODE *result;
-
- arg_data.recv = recv->nd_lit;
- arg_data.id = id;
- arg_data.narg = arg?1:0;
- arg_data.arg = arg->nd_lit;
-
- val = rb_resque(call_lit, &arg_data, except_lit, Qnil);
- if (TYPE(val) == T_STRING) {
- result = NEW_STR(val);
- }
- else {
- result = NEW_LIT(val);
- }
-
- return result;
-}
-
-#define NODE_IS_CONST(n) (nd_type(n) == NODE_LIT || nd_type(n) == NODE_STR)
-
static NODE *
call_op(recv, id, narg, arg1)
NODE *recv;
@@ -2360,9 +2493,6 @@ call_op(recv, id, narg, arg1)
value_expr(arg1);
}
- if (NODE_IS_CONST(recv) && (narg == 0 || NODE_IS_CONST(arg1))) {
- return expand_op(recv, id, (narg == 1)?arg1:Qnil);
- }
return NEW_CALL(recv, id, narg==1?NEW_LIST(arg1):Qnil);
}
@@ -2385,10 +2515,10 @@ gettable(id)
return NEW_STR(s);
}
else if (is_local_id(id)) {
- if (local_id(id))
- return NEW_LVAR(id);
- else
- return NEW_LVAR2(id);
+ if (local_id(id)) return NEW_LVAR(id);
+ if (dyna_id(id)) return NEW_DVAR(id);
+ /* method call without arguments */
+ return NEW_FCALL(id, Qnil);
}
else if (is_global_id(id)) {
return NEW_GVAR(id);
@@ -2399,9 +2529,8 @@ gettable(id)
else if (is_const_id(id)) {
return NEW_CVAR(id);
}
- else if (is_nthref_id(id)) {
- return NEW_NTH_REF(id>>ID_SCOPE_SHIFT);
- }
+ Bug("invalid id for gettable");
+ return Qnil;
}
static NODE*
@@ -2409,6 +2538,7 @@ asignable(id, val)
ID id;
NODE *val;
{
+ extern VALUE dyna_var_asgn();
NODE *lhs = Qnil;
if (id == SELF) {
@@ -2421,7 +2551,12 @@ asignable(id, val)
Error("Can't asign to special identifier");
}
else if (is_local_id(id)) {
- lhs = NEW_LASGN(id, val);
+ if (local_id(id) || !dyna_in_block())
+ lhs = NEW_LASGN(id, val);
+ else{
+ dyna_var_asgn(id, TRUE);
+ lhs = NEW_DASGN(id, val);
+ }
}
else if (is_global_id(id)) {
lhs = NEW_GASGN(id, val);
@@ -2434,9 +2569,6 @@ asignable(id, val)
Error("class constant asigned in method body");
lhs = NEW_CASGN(id, val);
}
- else if (is_nthref_id(id)) {
- Error("Can't set variable $%d", id>>ID_SCOPE_SHIFT);
- }
else {
Bug("bad id for variable");
}
@@ -2452,6 +2584,15 @@ aryset(recv, idx, val)
return NEW_CALL(recv, ASET, list_append(idx, val));
}
+ID
+id_attrset(id)
+ ID id;
+{
+ id &= ~ID_SCOPE_MASK;
+ id |= ID_ATTRSET;
+ return id;
+}
+
static NODE *
attrset(recv, id, val)
NODE *recv, *val;
@@ -2460,12 +2601,26 @@ attrset(recv, id, val)
value_expr(recv);
value_expr(val);
- id &= ~ID_SCOPE_MASK;
+ id &= ~ID_SCOPE_MASK;
id |= ID_ATTRSET;
return NEW_CALL(recv, id, NEW_LIST(val));
}
+static void
+backref_error(node)
+ NODE *node;
+{
+ switch (nd_type(node)) {
+ case NODE_NTH_REF:
+ Error("Can't set variable $%d", node->nd_nth);
+ break;
+ case NODE_BACK_REF:
+ Error("Can't set variable $%c", node->nd_nth);
+ break;
+ }
+}
+
static int
value_expr(node)
NODE *node;
@@ -2503,6 +2658,8 @@ value_expr(node)
}
}
+static NODE *cond2();
+
static NODE*
cond0(node)
NODE *node;
@@ -2515,6 +2672,12 @@ cond0(node)
else if (type == NODE_LIT && TYPE(node->nd_lit) == T_REGEXP) {
return call_op(node,MATCH,1,NEW_GVAR(rb_intern("$_")));
}
+ else if (type == NODE_DOT2 || type == NODE_DOT3) {
+ node->nd_beg = cond2(node->nd_beg);
+ node->nd_end = cond2(node->nd_end);
+ if (type == NODE_DOT2) nd_set_type(node,NODE_FLIP2);
+ else if (type == NODE_DOT3) nd_set_type(node, NODE_FLIP3);
+ }
return node;
}
@@ -2524,10 +2687,10 @@ cond(node)
{
enum node_type type = nd_type(node);
- value_expr(node);
switch (type) {
case NODE_MASGN:
case NODE_LASGN:
+ case NODE_DASGN:
case NODE_GASGN:
case NODE_IASGN:
case NODE_CASGN:
@@ -2561,6 +2724,7 @@ st_table *new_idhash();
static struct local_vars {
ID *tbl;
int cnt;
+ int dlev;
struct local_vars *prev;
} *lvtbl;
@@ -2572,7 +2736,8 @@ local_push()
local = ALLOC(struct local_vars);
local->prev = lvtbl;
local->cnt = 0;
- local->tbl = Qnil;
+ local->tbl = 0;
+ local->dlev = 0;
lvtbl = local;
}
@@ -2600,11 +2765,11 @@ local_cnt(id)
if (id == 0) return lvtbl->cnt;
- for (cnt=0, max=lvtbl->cnt; cnt<max ;cnt++) {
- if (lvtbl->tbl[cnt+1] == id) return cnt;
+ for (cnt=1, max=lvtbl->cnt+1; cnt<max ;cnt++) {
+ if (lvtbl->tbl[cnt] == id) return cnt-1;
}
- if (lvtbl->tbl == Qnil) {
+ if (lvtbl->tbl == 0) {
lvtbl->tbl = ALLOC_N(ID, 2);
lvtbl->tbl[0] = 0;
}
@@ -2622,7 +2787,7 @@ local_id(id)
{
int i, max;
- if (lvtbl == Qnil) return FALSE;
+ if (lvtbl == 0) return FALSE;
for (i=1, max=lvtbl->cnt+1; i<max; i++) {
if (lvtbl->tbl[i] == id) return TRUE;
}
@@ -2632,7 +2797,7 @@ local_id(id)
static void
top_local_init()
{
- if (lvtbl == Qnil) {
+ if (lvtbl == 0) {
local_push();
}
else if (the_scope->local_tbl) {
@@ -2643,12 +2808,13 @@ top_local_init()
}
if (lvtbl->cnt > 0) {
lvtbl->tbl = ALLOC_N(ID, lvtbl->cnt+1);
- MEMCPY(lvtbl->tbl, the_scope->local_tbl, ID, lvtbl->cnt);
+ MEMCPY(lvtbl->tbl, the_scope->local_tbl, ID, lvtbl->cnt+1);
}
else {
- lvtbl->tbl = Qnil;
+ lvtbl->tbl = 0;
}
NEW_CREF0(); /* initialize constant c-ref */
+ lvtbl->dlev = (the_dyna_vars?1:0);
}
static void
@@ -2661,14 +2827,7 @@ top_local_setup()
i = lvtbl->tbl[0];
if (i < len) {
- if (the_scope->flags & SCOPE_MALLOCED) {
- VALUE *vars = the_scope->local_vars;
-
- REALLOC_N(the_scope->local_vars, VALUE, len);
- MEMZERO(the_scope->local_vars+i, VALUE, len-i);
- free(the_scope->local_tbl);
- }
- else {
+ if (the_scope->flag == SCOPE_ALLOCA) {
VALUE *vars = the_scope->local_vars;
the_scope->local_vars = ALLOC_N(VALUE, len);
if (vars) {
@@ -2678,10 +2837,15 @@ top_local_setup()
else {
MEMZERO(the_scope->local_vars, VALUE, len);
}
+ the_scope->flag = SCOPE_MALLOC;
+ }
+ else {
+ REALLOC_N(the_scope->local_vars, VALUE, len);
+ MEMZERO(the_scope->local_vars+i, VALUE, len-i);
+ free(the_scope->local_tbl);
}
lvtbl->tbl[0] = len;
the_scope->local_tbl = lvtbl->tbl;
- the_scope->flags |= SCOPE_MALLOCED;
}
else if (lvtbl->tbl) {
free(lvtbl->tbl);
@@ -2690,6 +2854,27 @@ top_local_setup()
cref_list = Qnil;
}
+static struct RVarmap*
+dyna_push()
+{
+ lvtbl->dlev++;
+ return the_dyna_vars;
+}
+
+static void
+dyna_pop(vars)
+ struct RVarmap* vars;
+{
+ lvtbl->dlev--;
+ the_dyna_vars = vars;
+}
+
+static int
+dyna_in_block()
+{
+ return (lvtbl->dlev > 0);
+}
+
static void
cref_pop()
{
@@ -2721,7 +2906,7 @@ yywhole_loop(chop, split)
if (chop) {
eval_tree =
block_append(NEW_CALL(NEW_GVAR(rb_intern("$_")),
- rb_intern("chop"), Qnil), eval_tree);
+ rb_intern("chop!"), Qnil), eval_tree);
}
eval_tree = NEW_WHILE(NEW_FCALL(rb_intern("gets"),0),eval_tree);
}
@@ -2808,14 +2993,14 @@ rb_intern(name)
/* operator */
int i;
- id = Qnil;
+ id = 0;
for (i=0; rb_op_tbl[i].token; i++) {
if (strcmp(rb_op_tbl[i].name, name) == 0) {
id = rb_op_tbl[i].token;
break;
}
}
- if (id == Qnil) Bug("Unknown operator `%s'", name);
+ if (id == 0) Bug("Unknown operator `%s'", name);
break;
}
@@ -2844,7 +3029,7 @@ rb_intern(name)
static char *find_ok;
-static
+static int
id_find(name, id1, id2)
char *name;
ID id1, id2;
@@ -2860,7 +3045,7 @@ char *
rb_id2name(id)
ID id;
{
- find_ok = Qnil;
+ find_ok = 0;
if (id < LAST_TOKEN) {
int i = 0;
@@ -2897,7 +3082,7 @@ const_check(id, val, class)
VALUE val;
struct RClass *class;
{
- if (is_const_id(id) && rb_const_bound(class, id)) {
+ if (is_const_id(id) && rb_const_defined(class, id)) {
Warning("constant redefined for %s", rb_class2name(class));
return ST_STOP;
}