iMops-forth @Wiki内検索 / 「Forthのわかりにくさ」で検索した結果

検索 :
  • Forthのわかりにくさ
    Forthコード “いかにもfothらしい”コード面に対する嫌悪感を説明してみたい。ただし、“いかにもforthらしい”には引用符をつけておきたい。確かにそれを許しているのはforth自体の特性であるとしても、自由度が高いことは何もかもが正当化されているということではないからだ。プログラマーに責任がかかってくるのである。 “いかにもforthらしい”コードの第一の問題は、何をしようとしているのか解りにくいことだ。ただし、それはスタック状態の変化が追えないからではない。非アルファベット記号が多用されているからでも、人為的な改行記号(C系の ; のような)がないからでもない。そういった初歩的なところで引っ掛かるのは読む側に問題があることも多い(例えば、スタックをどう手なずけるかとか、アレイをどう操作するかという話...
  • Forth言語概説
    プログラミング言語Forth 序章 Forthによるプログラミングは、ワードと呼ばれるサブルーチン(意味的に一定のまとまりのある処理の小部分、関数ともいう)を定義することで行われる。ワードの定義は、コロン記号で始め、次にワード名、そしてそのワードが行うべき処理内容の記述と続き、最後にセミコロンを置く。これが最も基本的なForthワード定義方法であり、コロン定義( -definition)などとも呼ばれる。例えば、 square-sum ( a b -- a^2+b^2 ) dup * swap dup * + ; このコードはsquare-sum という名前のワードを定義している。丸括弧の中はコメントで、実行には関わらない。 コード内の各ワードは、半角空白、タブ、改行、のどれかで区切られた文字列で表示される。 や ; もforthでいうワードなのであり、他のワー...
  • Forthの変数
    序 データスタックが変数の役割を果たすとはいえ、forthでも変数は定義できる。 けれども、構文上は、値はすべて一旦スタックにおかれ、スタックを通じて処理されるような形になる。 変数の種類としては、ワードとして定義するパブリックな変数と、1ワード定義内でだけ有効な局所変数がある。 Mopsにはこれらに加えて Local Section (ローカルセクション)という機構があり、近接する特定範囲の複数のワード定義に渡ってのみ存続する変数を定義することができる。 このページでは長くなり過ぎないようForthコアに属するものだけを説明し、オプションである局所変数とMops特有のローカルセクションはそれぞれ別ページに回すこととする。 パブリック変数(VARIABLE, VALUE) VARIABLE VARIABLE V1 と宣言することで、V1という名前の変...
  • forth讃
    Forthプログラミングは難しい? 当サイトでは標準forthの欠点ばかり書いてきた気もするが、これはforth言語の優れた面の表れでもあるのだ。 弁解ではなく、本当に。 Forthでのプログラミングは、言語の提供している機能を利用する側面と、必要な機能を提供する言語要素を構築する側面がある。他のページにも書いたように、forthでのプログラミングは、初心者を一歩出た段階で言語実装へと立ち入ることになる。forthでいう拡張性はボキャブラリーが増えていくというだけに止まらず、プログラミングの仕方自体を変更するものとなっているのである。 コードや機能それ自体より、アイデアを いわば一種のアプリケーションとして提供されている他言語のハイレベルな機能に相当する手段が、既にforthで提供されているのではないかと、ときおり話題になることがある。しかし、それは微妙にズレた見方の...
  • Forthの変数(続)、定数
    格納値の操作 変数を値の代理というよりも格納庫としてみて、そこに格納されている値に直接に演算を施すワードが定義されている。+! と -! である。 +! ( n addr -- ) \ nをaddrで指された1セル数値に加算する -! ( n addr -- ) \ nをaddrで指された1セル数値から減算する これらは、スタック上の値nを、addrで指定された1セルメモリー領域にある値に対して、それぞれ、足し算、引き算するのである。例えば、 VARIABLE VR1 5 VR1 ! 8 VR1 +! 2 VR1 -! VR1 @ \ 11 とすれば、VR1に格納されている値は11である。 VALUEに関しては、forth標準には同様の機能をもつワードは無いようであるが、多くの環境では ...
  • 一般forth用語の整理
    Forthワードの機能を知る上で知っておくと便利な抽象的な用語をここで整理しておこうと思う。 セマンティクス Forthでセマンティクスというと、ワードの動作の内容を意味する。一般にはセマンティクスというと意味論と訳され、形式的な式とか文の内容構造を表す形式モデルのことを指したり、そのモデルの割り付け操作のことを指したり、文が表している意味そのものを指したりする。かなり多義的に使われる言葉であるが、forth規格で多用されるセマンティクスは、そのうちの、オペレーショナルセマンティクスといわれるものといえるだろう。それはプログラムのエレメント(Forthではワード)に対応する、演算とか、あるいは、もっと広く、コンピュータ上の処理のことを言っている。 セマンティクスと状態 セマンティクスの種類 Forthでは、セマンティクスは通常3つに分類されるが、細かくいうと4つある ...
  • Forth開発環境の初歩的使用法
    コマンドライン、コンソール 現在でも、Forth開発環境の多くは、テキストベースのコマンドラインから操作するものがほとんどである。MacだとTerminal.appから操作することになるし、WindowsだとDOS窓である(近年はなかなか優秀なシェルウィンドウが付いている)。他のLinux等のUNIX系でウィンドウシステムがある場合も、具体的には知らないが、同じようなことになるであろう。要するにシェル内でコマンド操作を実行するのである。 大抵のものは、オプションフラグを許すであろうし、起動時に特定のソースコードを同時にロードする方法もあるであろう。 それぞれの環境にマニュアルがあるはずである。通常は英語と思われるが、それぐらいは自分でドキュメントを探して読むべきである。オープンソースの場合、ソースコードから分ることもある。記憶では、gforthでは、予めコマンドパスを通してgfor...
  • forthとコンパイラ
    Forth言語特性 Forth言語では、古典的には"間接スレッディング方式"という特殊な実行形式が採用され、"コンパイル"というときにも特殊な意味で用いられていた。 しかし、ここでの話はマシン語を生成するネイティブコード・コンパイラを対象とするため、その解説は省く。参照 Forth系の言語ではコンパイラの作成が非常に容易ともいわれる。その第一の理由は構文解析や意味解析のためのコードを書く必要がないからだ。 Forth言語には特殊記号のようなものは、ほとんど — 全くというわけでもないが — ない。記号のように見えるものも、一つ一つが実行上の意味を持っている。その各々はワード(word)と呼ばれる。そのワードが書かれてある順番に実行されていくだけ、というのが原則となる(当然、例外も多くある)。ワードの特定に...
  • THROW CATCH ABORT
    エラーハンドリング 必ずしもエラー(失敗、過誤)といえるものばかりではなくとも、何か予定外の事態が生じて、現在進行中の処理を中止する必要がでてくる場合がある。そういう、中断処理をエラーハンドリングという。 Forthのエラーハンドリング用ワードの代表は、THROWとCATCHであるということになっているようである。 THROWとCATCHは対で用いるが、必ずしも一対一に対応する必要はない。 これ以外にも単独で使う処理中断のためのワードとしてABPORTがある。 THROW CATCH
  • forth環境への問い合わせ
    Forth環境に対して質問するワードについていくつか説明する。 ENVIRONMENT? Forth標準規格でCOREワード規定されているENVIRONMENT?は、当のForth環境で扱える整数の最大値や文字列の長さの制限などについての特性を返す。ただし、何でも分るというわけではなく、規定された事項について回答するのみであり、さらに、回答不能の場合(未定義も含む)はfalseを返すだけの場合もある。回答可能な質問にはtrueとともに該当する値を返す。 質問事項は決まった文字列を用いなければならず、それをENVIRONMENT?の入力として実行する。 ENVIRONMENT? ( c-addr u -- false | i×x true ) 規定されている可能な質問事項は次の通りである。 文字列 値 定数かどうか 意味 /CONUNTED-STRING ...
  • なぜ言語は自己設計しなかったのか
    Forthの融通性 プログラミング言語を自分で設計する気は全くなかった。新しい言語を望むのは既存の言語に不満があるということだろう。Forth言語は非常に古く、Mopsもまた言語として比較的古い。もっとハイカラに飾り付けた言語の方が良いというのもわからないではない。 けれども、forthにしてもMopsにしても、融通が利くことこの上ない言語環境なのだ。そこでのプログラミングは、普通のアプリケーションプログラミングでさえ、どこか言語設計や言語実装に近い発想をする必要がでてくる。問題を解くための言語を実装する、というのがそこでのプログラミングの常道なのだ。プログラミングの過程で、言語そのものが、そのシンタクス(統語法)も含めて変容していくのだ。しかし、既存の部分までつられて変化していくわけではなく、基本部分は不変なままであるから、ある方向への拡張のために他の方向への拡張を制限しなけ...
  • メニュー
    メニュー コンパイラの構築もやもやForthとコンパイラ言語設計はしなかったForthの陥穽 インタープリタの機構 Mopsのオブジェクト指向(総論)(編集中) forth讃 少し技術っぽいことレジスタ割当とノードグラフ 呼び出しコンパイル レジスタ変数の実装 ヒープメモリー上でのコンパイル・実行 Forth言語についてForth言語概説Forth開発環境 一般forth用語の整理 計算Forthの変数 変数(続)、定数 数値演算 拡張数値計算 ビット、論理演算および比較判定 スタック操作 ワード(関数)の定義 ワード定義(続) 文字列・印字・クエリ固定文字列 文字列、文字、印字 数値の表記と印字 文字列操作 質問・探索 特別スタック・小数・局所変数R-, CF-, FP-スタック 小数の処理 局所変数(locals) フロー制御IF、EXIT、CASE 確定ループ 不定ループ 再帰(RE...
  • 確定ループ
    ループは、もちろん、特定区間の実行を何度か繰り返す機構であるが、確定ループ(Definite Loop)とは、その繰り返し回数の限界が、実行開始前に定まっているループである。 DO LOOP Forthの最も基本的な確定ループはDO-LOOPである。このループの巡回区間は、DOで始まりLOOPで終わる部分である。DO-LOOPは、forthにおける他のコントロールフロー制御ワードと同様、ワード定義内でしか利用できない。 DOは実行時にスタックから2つのアイテムを入力として取る。1つは、巡回カウンターの境界値であり、もう1つは巡回カウンターの初期値である。 DO ( n1 n2 -- ) \ n1が境界値、n2がカウンターの初期値。 カウンターはLOOPに至ったときに1加算される。そして、カウンターが境界値に一致するかそれより大きくなったときにループを抜ける。...
  • ワード(関数)の定義(続)
    FORWARD これはMopsでの拡張である。標準forthにはない。おそらく、もっと古いforthにはあったのだろう。 機能としてはDEFERと同じであるが、少し静的である。動的に、あるいは何度も定義内容を変えることは予定していない。むしろ、あるワードの定義を初めから遡及的に入れ替えるという機能が重要である。もっとも、現実には、呼び出しが必要なところでは何らかの理由でまだ定義ができないワードを、もっと後に、ただし実行前に定義する、という目的のために用いる。 FORWARD aWord このように宣言すれば、aWordは他のワードの定義で呼び出すことができる。 callaWord ( n1 n2 -- n ) over aWord ; しかし、このままだと、aWordの内容は何もない。実行前に内容を定義する必要があるが、そのためには f と;fの対を用い...
  • 再帰(RECURSE)
    概念的説明 † 再帰関数をご存知なら、この区画は飛ばしてかまいません。 再帰関数(リカーシブ ファンクション)は計算理論に用いられて、計算機科学でもよく取り上げられるようだ。 このリカーシブ recursiveの日本語訳としては"帰納"もある。数学的帰納法の帰納であるが、これは論理的な推論としての帰納(induction)ではないので混乱する。高校数学で出会う"漸化式"もリカーシブ リレーションである。 名詞の"再帰"は電算系ではrecursion、動詞の"再帰する"はrecurであり、forthのワードrecurseは英単語ではないようである。 これは要するに数列である。数列は、順番を表す整数ないし自然数を定義域とした、ステップ番号値の関数として考えられるわけだが、その場...
  • コンパイラの構築(iMopsの記憶)
    はじめに 逐次拡張型インタラクティブ開発環境を作成しました。iMops (アイ・モップス)という名前です。無料ソフトウェアです。 ここからダウンロードできます。現在のバージョンは2.23です(2022/2/5)。 Macintoshコンピュータ(MacOS[X])専用ですが、相当程度最適化されたx86-64マシンコードを生成します。インタラクティブに一語一語(=各関数毎に)コンパイル-解釈実行できます。JITコンパイラとかいうものになるのでしょうか。Cocoaなど一般の動的フレームワークにリンクできます。単独で起動可能なアプリケーションを作ることもできます。64ビットのみですが動的ライブラリも生成できます。最新のmacOS上でも稼働するようです(確認済)。(なお、Apple社が、Macの全CPUを二年でARM仕様に変更すると宣言したことに対応して、ARM64ビットネイティブのMop...
  • スタック操作
    計算やデータ処理、あるいは外部関数の呼び出しなどを積み重ねていく場合に、スタック上の値の順番がいつも整合的に上手くいくとは限らない。また、同じ値を何度も使いたいときに、いちいち変数に格納するより、スタックアイテムを複製する方が簡便な場合もある。そのような必要に応えるために定義されているのがスタック操作ワードである。dupやswapは既に登場したが、経験上よく使うものをここで一括して説明する。その後、ワードを定義して、それをつなげていくことで行われるforthプログラミングについて、書法上の留意点のようなものを考えてみたい。 スタック操作子 ワード名とそのスタック効果は次の通り: drop ( x -- ) \ トップの値を捨てる。 dup ( x -- x x ) \ トップの値を複製してアイテムを1つ増やす。 ?dup ( x -- 0 | x x ) \ トッ...
  • Abort, Die, および Throw-Catch
    例外処理 プログラムの実行過程で、ユーザーからの予想外の値の入力など、いくつかのあらかじめ予測不能な原因が競合した結果、そのまま処理を続行することができなくなる局面がある。そのような場合に備えて、処理を適切に中断させるためのワードがある。一般的にそのような処理は例外処理(exception)とよばれている。本来ならばその後に継続するはずの複数の処理を無しで済ますものであるため、かなり強引な処理となる。したがって、例外処理は、まさに例外的に予測不能な事態に対して用いるべきもので、通常の条件外のときまで例外処理をすると、ちょっとカッコ悪い。 ABORT ABORTは、以降の処理を全て中止して整理し、入力待機状態に戻す。実行時にはビープ音が出る。通常は、IF構造で囲い、エラーコードフラグを判定して、エラーがある場合にのみABORTが呼ばれるようにする。ABORT自体は、エラーコード-1...
  • 標準Forthワード索引
    説明したForthワード(アルファベット(ASCII)順) !  (Store) #  (number-sign) #   (number-sign-greater) #S  (number-sign S)   (tick) (  (paren) *  (star) */   (star-slash) +  (plus) +!  (plus-store) +LOOP  (plus-loop) ,  (comma) –  (minus) .  (dot) ." &nbs...
  • XT(エグゼキューション・トークン)
    XT 普通は小文字でxtと書くが、これはexecution token(エグゼキューション・トークン)の頭文字である(英語ではex...の頭文字にeではなくxを採ることが普通なのは一般論)。直訳すれば「実行標識」である。数値なのだが、これでワードを識別できる。各ワードについた固有のタグである。イメージとしていえば関数ポインタのようなものである。しかし、関数ポインタとは違って、実装上は必ずしもポインターではないし、関数以外でもパブリックなワードであれば全て、例えば、大域変数などもxtを持っている。 xtは基本的には数値であってデータであるが、データ処理プロセスを意味するデータである。つまり、実行可能ワード(サブルーチン、関数、プロシージャー、他)をデータとして扱う手段を提供する。xtは普通の数値としてスタックに置かれたり、変数に格納されたり、取り出されたりすることもできるし、必要...
  • IF、EXIT、CASE
    IF IFはもちろん条件分岐のためのワードである。ForthのIFは、他のプログラミング言語とも、また英語とも、語順が異なっている。IFは条件をスタックから取る。したがって、判定値はIFの前に定まっていなければならない。IF以下は、スタック上の判定値が偽でないときのみ実行されるのである。「偽でない」とは0でないという意味である。真(TRUE)は-1で表現されるからもちろん0ではない。しかし、真の場合だけでなく、0でない値なら何でも、IF条件は成立したことになるのである。 IF条項はTHENで閉じる。ForthのTHENは、通常の場合のように「IF条件が成り立った場合」を意味しない。ひとつのIFに関わる部分を終了させるのである。IFの判定値が偽であったときには、次のTHENまでのコードは実行されない。THENをEND-IFと改名して用いている環境もある。 IF文は、コンパ...
  • リターンスタックと小数スタック
    リターンスタック Forthにおいてスタックといえば普通はデータスタックを意味する。整数値を受け渡すためのスタックである。しかし、forth環境は、これとは別個の、リターンスタックと呼ばれるスタックも持っている。実は、多少仕様は異なるものの、現代のPCでリターンスタックを使わずに動作しているものはほとんど無い。関数あるいはサブルーチンの呼び出しのとき、内部的にはリターンスタックの機構を使っているのである。しかし、普通の言語では、それはプログラム面からは隠されていて、直接にアクセスすることはできない。Forthにおいてもリターンスタックは内部で自動的に動作する機構であって、プログラマーが操作する必要のあるものではない。しかし、forthでは、値を臨時に一時格納する場所として、プログラマーがリターンスタックに直接アクセスすることを許しているのである。 このリターンスタックへのアクセ...
  • ディクショナリ格納
    ディクショナリー リターンスタックなどもそうであるが、ディクショナリー(辞書)は、言語環境が自動的に保守するメカニズムであって、コードやデータがコンパイルされるときに、暗黙のうちに利用されるものである。けれども、そういう機構もプログラマーが操作できるようにしてしまうのがforthの流儀であるともいえる。 Forth走行中、ディクショナリーはメモリ中にロードされている。そこには、相互にリンクされた既定義ワードのデータとコードが格納されている。インタープリターもコンパイラーも、そこに収められている。 古典的なforthでは、機械命令を含む実行コードも、数値データを格納する変数用フィールドも、全て混在する形で一体としてのディクショナリー領域に格納されていた。かつては、通常の実行可能ファイルもそのような状態であったので、それが自然であった。 その後、CPUが機械命令実行...
  • 数値の表記と印字
    Hex Decimal 数字の表記は、デフォルトでは10進数で解釈される。しかし、モードとして16進数解釈に切り替えられる。そのためのワードがHEXである。 HEX ( -- ) \ 16進数モードに切り替える 数字はすべて16進数で表記されていると解釈される。したがって、HEXを実行しておけば、コード内に、BEEF とかCafeとかdeadなどと書いても、そのような名前のワードを定義していない限り、数字として解釈される。10進数に戻すには、DECIMALを実行する。 DECIMAL ( -- ) \ 10進モードに切り替える なお、モードとしてだけではなく、$を付けることで16進数表記の数字であることを示す方法がある。標準forthにおいてはインタープリタの特性として、$の後に空白なく直接続けて数字を書くやり方が導入されている。例えば、 $ABCD \ -- 4...
  • Mopsのオブジェクト指向(総論)
    Mops言語のオブジェクトシステムにはどんな効果があるのか Forthのオブジェクト指向拡張は数多くある。実は、forthで言語の仕様を変更するのは容易なのである。初心者から一歩踏み出したあたりで、言語実装がforthプログラミングの課題となってくる、とさえいえるほどである。結局は、それでforthにおけるどのような問題が解かれるのかにかかってくる。 Mops言語のオブジェクト指向はNEONモデルといわれる構文を基としている。これは、forthのオブジェクト指向拡張としては最も早期のもののひとつである。実際には現時点でのMopsのオブジェクト指向特性は起源からもうかなり離れてしまっている。とはいえ極めて古い時代の設計が基礎となっていることは否定できない。ところが、偶然ではあろうが、驚くべきことに、比較的近年になって初めて注目された新しい着眼点とみなされている事柄についても、既に...
  • 固定文字列
    序 固定文字列は、内容が固定された文字の系列をデータとして利用するものである。内容も長さも後から変えられることは無いという前提であるから、大抵は、大域データ域にその長さ分のメモリー領域を確保して書き込んでおく。Forthではデータディクショナリーである。 全体としては変化する文字列の、変化しない部分を、固定文字列にしておくという使用法もある。 Forthで固定した文字列を扱う方法は、引用符でリテラル(文字通り)に書き込むやり方と、ワードとして文字列定項を定義するやり方がある。 他方、挿入したり切除したりできる可変的文字列を扱う仕組みは、ほとんどforth標準には入っていない。それぞれの環境ごとに様々な方法が実装されていて、統一できないのである。確かにforth標準中にも文字列に関するワードはオプションとしていくつか規定されているが、あまり便利なものではない。 例えばMo...
  • スレッディング技術 (Threading Technology)
    スレッデド・コード Forthの伝統的なスレッディング技術について説明してみたいと思う(自分はネイティブコード方式しか経験はないが)。 注:全てマシン語におき直すネイティブコード方式では、スレッディング方式は関係がない。 スレッディング技術とは、ワード(サブルーチン、関数)のコンパイルと解釈実行のための技法である。 スレッディング(threading)という言葉は、掲示板等のいわゆる「スレ」と同じ語threadが語源で、"糸"という意味である。 辞書内にコンパイルされたワードの領域は、複数のスレッドのリストであり、イメージとしては、たくさんの糸を等間隔でぶら下げた棒のような感じである。そして、ぶら下がった糸にはそれぞれ実行すべきワードがつながっており、それを順番に引っ張って糸の先のワードを動かしていくことで処理が連続していくわけである。 ...
  • 自己コンパイル、クロスコンパイル
    かつては、forthはforthで構築されているものが多かった。しかし、現在は、forthといえども、中核部分はC言語などの、様々なプラットフォームで利用できるマシン語コンパイル型の言語環境を用いて構築されている例が多いようである。そんな中でMopsは全体がforthで構築されており、現在では特異な存在となっている。その場合、自分自身を自分自身でコンパイルする、ということになる。 自己コンパイルに際しては、ややこんがらがる事態が発生することがある。その混乱の原因は、今コンパイラとして稼働している環境のワード(=関数)と同名のワードを新たに構築しているコンパイラの中にもコンパイルしなければならないことに由来する。特に、現在稼働中の環境の中にあるワードを、コンパイルされているワードの側から呼び出したりしないように注意しなければならない。これをしてしまうと、コンパイル後の関数が、もはや実...
  • 数値演算
    四則演算 + – * / Forthでも普通の四則演算がわからないという人は、ほとんどいないと思う。変数を使わずスタック上で実施するので、コード面は初めは分りにくいということはあるかも知れないが、普通は数分もあれば慣れる。 記号としては、足し算は + 、引き算は - 、掛け算は * 、割り算は / 、なのでごく普通である。これらもワードなので、前後は空白文字で空ける。変数名や数字とつなげてしまってはいけない。これらは整数演算であり、入力も出力も整数である。割り算は余りは捨ててしまう。二つの整数をデータスタックから取り、結果をスタックに置く。"a b -" は"a 引く b"であり、"a b / " は "a 割る b"である。 \ スタックの状態 x y - \ スタック...
  • ワード(関数)の定義
    (コロン) 既に見たように、forthのもっとも典型的なワード(関数)定義方法は、 を用いる方法である。これも1文字名前のワードである。 を用いる標準的な定義方法をコロン定義( -definition)などという。まず、 を置き、続いて、定義しようとしているワードの名前を書く。続いて内容定義に入る。定義には、他のワードで実行内容を記述する。最後にセミコロン ; で閉じる。 定義が終了した後は、その名前で自由に呼び出すことができる。 square-sum ( n1 n2 -- n ) dup * swap dup * + ; 30 VALUE Rect1-X 90 VALUE Rect1-Y 80 VALUE Rect2-X 50 VALUE Rect2-Y ... Compare-diag ( -- b ) \ Rect1の対角線の方が長いときTru...
  • EVALUATE PARSE コンパイルの中断
    EVALUATE EVALUATEは「評価」である。要するに遅延評価である。ソースコード文字列を実行時にインタープリトするのである。 EVALUATE ( i×x c-addr u -- j×x ) 解釈されるソースコードが入力を必要とすれば、それはスタックの、文字列より下の位置に置かれなければならない。また、返される値は、実行後にスタックに残される。 ソースインプットの長さに特に制限はないようだが、通常は、ごく短い(一行)コード断片が予定されている。 このワードは伝統的にインライン定義に利用されてきた。例えば、 displace S" dup @ +" evaluate ; immediate のようにすれば、このdisplaceはimmediateであるから、コンパイル状態でも実行される。そのとき、"dup @ +&qu...
  • 文字列とASCII文字の印字
    文字列の比較 COMPARE オプションであるから定義されているとは限らないが、2つのaddr len文字列について、その内容が一致するかどうかを判定するforth標準ワードがCOMPARE である。 COMPARE ( c-addr1 u1 c-addr2 u2 -- code ) 比較は大文字小文字が区別される(case-sensitive)。 結果は、完全に等しいときには0を返す。文字列の長さが異なり、短い方の内容が長い方の一部として完全に含まれている場合、u1の方がu2より小さいとき-1、それ以外なら1を返す。短い方の文字列についても不一致がある場合には、最初の不一致文字について、c-addr1 u1で特定される文字列に含まれる文字の方が小さいとき-1、そうでないとき1を返す。 出力コードがやや複雑であるので分岐で書くと: 文字列内容が完全に一致 -- 0 文...
  • CREATE DOES>
    CREATE - DOES CREATEとDOES を組み合わせる語法は、forth言語で出会う最初の驚きである。 CREATE - DOES の対は、何かのワード定義の中で用いる。そのようにして定義されたワードは特別なワードとなり、CREATE-DOES ワードなどとも呼ばれる。そのようなワードのどこが特別かというと、あるパターンのワードを定義(というより生産)できるワードになるのである。しかも、そこで生産されるワードは、実行コードの他に当該ワードに固有のデータ領域を持つのである。 CREATEは、変数の説明でも触れた、アレイを作るワードと同じワードである。このワードは宣言的に用いる必要があるわけではなく、通常のワード定義の中から呼び出すこともできる。そうすれば、その定義されたワードが実行されるときにCREATEも実行されるのである。ここで説明するCREATE DO...
  • 局所変数(locals)
    序 Forthでは局所変数機能はオプショナルであって、必ずしも全てのforth環境が、それを備えているとは限らない。しかし、利用可能であれば、一般的な局所変数と同じく、ひとつのワード(サブルーチン)定義内でのみ有効で同一性を保ち、名前によって特定される変数となる。 多くの環境で、局所変数はリターンスタックを用いて実装されているようである。リターンスタックにフレームを作り、その位置と局所変数名を結びつけるのである。Mopsではレジスタを積極的に用いる。 PowerMopsでは10個程度までの局所変数が定義可能で、全てレジスタが利用される。したがって、スタックに値を多く積み込むよりも 局所変数を用いた方が高速処理が期待できる。 iMopsでは、整数は100個以上可能だが、レジスタを利用するのは初めの3つだけで、それを超えた分はリターンスタックを用いる。 また、浮動小数点数に関し...
  • ビット、論理演算および比較判定
    ビット(bit)とは、2進数の1桁のことである。0か1の2つのうちどちらかの値を取る。ビットと命名したのは情報理論で有名なシャノンであるらしい。コンピュータは、内部では2進数で動いていることは有名だが、この2進数の桁そのものに注目した演算操作がある。Forthで定義されているそのようなワードについて、このページでは説明する。 論理演算 プログラムでは、この1桁1桁を標識として使うことがかなりある。フラグ(旗)などという。1だとフラグが立っているといい、0だと立っていないのである。あるいは、1ならオン(on)、0ならオフ(off)である。 この1,0を真理値と捉えて、ビット毎に論理計算をするのが論理演算である。1が真、0が偽である。1セル分の全ビット一斉に行う。32ビットシステムなら32桁分、64ビットシステムなら64桁分、同位置の各ビットについて一回に行うのである。 ...
  • 浮動小数点数の処理
    小数用のワードセットは、対応する整数用ワードの名前の前にFを付けただけのものが多い。 オプションであるので、商品forthかgForthでなければ、規格に含まれた全てのワードが完備されていることは期待できない。Mopsもかなりズレがある。基本的に必要と思われるものについてのみ説明する。 なお、PowerMopsとiMopsでは、浮動小数点数は標準でダブル精度(64ビット)である。 FVARIABLE FVALUE FCONSTANT 浮動小数点数(以下、小数と略す)は、1セル幅が整数と異なる場合もある。そのために、小数用の変数を定義する方法がある。もっとも基本的なものは、FVARIABLEである。このワードと伴に変数名を宣言する。VARIABLEと基本的に同じである。 FVARIABLE ( “ spaces name” -- ) \ 小数変数を定義する 例えば...
  • ワード(サブルーチン)へのリンク
    サブルーチンコール 自分でコンパイラやインタープリタを作ろうとしている人がみるかも知れないということで、思いっきり基本から書いてみる。 マシンインストラクション ネイティブコード方式でサブルーチンを呼び出す場合に用いるのは、基本はCALL(コール)インストラクションである。 インストラクションとは「教示」というような意味だが、「マシン インストラクション」で「機械命令」と訳されるようである。 計算しろとかデータを移動しろとか、コンピュータの基本的動作を命令する符号で、機械の種類毎に違う決まった数値で表されている。 コンピュータの動作に結びつく実行コードはメモリーに配置されているのであるから、要は、実行したいコードのあるメモリーアドレスを取って、そこに実行を飛ばせばよいのである。現在実行している場所のメモリーアドレス値は、IPとかPCと呼ばれる特別なレジスターで管理してい...
  • レジスタ割当とノードグラフ
    レジスタ割当 前提問題 Forth系の言語の場合、構文解析や意味解析はコンパイラをつくる時点では考える必要がない。詳細はプログラミング段階に回せるからだ。すると考えなければならないのは初っ端から最適化ということになる。今日のコンピュータはほとんどがレジスタマシンであるため、レジスタをどのように割り当てるかがまずは最重要課題となる。 レジスタマシンとは、レジスタと呼ばれる小さく高速な内部記憶装置を備えたコンピュータのことと思って良い。レジスタは変数の一種と考えてもよい。数値やメモリ内のデータをできるだけレジスタに保持して処理することで高速な処理が可能となる。64ビットマシンといわれるのは、このレジスタ1本で2進数の64桁まで記憶可能な機械のことである。32ビットなら32桁である。x86は古い汎用機仕様であるため、もともとは、このレジスタは8本しかない。64ビット(8バイト)に拡...
  • 文字列操作
    文字列の操作に関する、Forth標準ワードのいくつかについて説明する。文字列の操作というよりも、文字列バッファの操作という観点から集めた。文字列用ワード群はオプショナルであり、全ての環境で定義されているとは限らない。 文字列の扱いは環境毎に多様化しているようである。したがって、文字列用として標準となっているワードはごく僅かである。 Mopsでも、基本的クラスライブラリとして、ヒープベースの文字列を扱うStringクラスがあり、その拡張としてString+クラスがあるため、文字列操作は専らオブジェクトにメッセージを送ることで行う。 CMOVE CMOVE CMOVEは文字列をバッファにコピーするワードである。パラメターを3つ取り、入力バッファのアドレス、コピー先バッファのアドレス、バイト数の順となる。 CMOVE ( addr1 addr2 u -- ) \ ...
  • 拡張数値計算
    ダブル整数 ダブル整数とは、2セル分を用いて表現される整数のことである。これは、変数の型のようなものではなくて、数値のスタック上への表現の型、といってよい。下の桁を先に、大きい方の桁を後に置く(ある意味、リトルエンディアン)。そうすることで、理論上、2セルビットの範囲(64ビットなら128ビット)の数値が扱えるようになるわけである。1セルの範囲で表せる数値をダブル整数で表現するとすれば、例えば、 1234は 1234 0 と置くことで表現され、 −1234なら、 -1234 -1 と置けば良い。 組み込みマシンのような8ビットや、16ビットの小さなセル単位でしか利用できない窮屈な環境では、今もダブル整数を一般的に使用する意味はあるが、32ビット以上のPC上では、ほとんど使用価値がない。そのため、現在では、ダブル整数一般を扱う規格はオプショナルとさ...
  • レジスタ変数の実装
    Mopsでは、forth一般の傾向に反して、伝統的にLocals(局所変数)に比較的高い優先順位を与えている。Localsを定義した場合、少なくともいくつかはレジスタ変数にすることで、局所変数を効率の良いものにしようとしている(PowerMopsでは全てレジスタ変数で、10個まで可能である)。ここでは、その実装法について説明してみようと思う。コンパイラー作成上での局所変数の実装法一般の話としても意味があるのではないかと思う。 局所変数の実装 一般論 局所変数とは、一般に、1つのサブルーチンの定義の中だけで同一性を保つ変数のことといえると思う。プログラム上は変数名で特定される。数値格納領域は、理屈の上ではどこにあってもよいわけだが、普通は、リターンスタックにメモリー枠を確保する。そして、コンパイル中は、プログラム上の変数名と、スタック内のメモリーフーレム中の特定の場所とが結びつけられ...
  • インタープリタの機構
    iMopsのインタープリタの機構は、PowerMopsのそれを模倣している。INTERPRETという内部ワードが中心となっている。 実行モード 実行モードでインタープリトする場合、INTERPRETは、読み込まれたワードを辞書内検索で探し出し、そのワードのxt(エグゼキューション トークンの略号。forthでは実行可能ワードを識別するタグのようなものを、このように呼ぶ。)をパラメターとして、もう一つの内部ワードEX_GENを呼び出す。EX_GENの名は、もともとあったワード名から踏襲されたものだが、どうも、Execute_Generally(一般実行)の意味らしい。 このEX_GENの内容として、素朴に考えてまず思いつくのはxtからコードアドレスを取ってcall(呼び出し)するやり方だろう。 ここでいうcallはマシン語のcallのことで、現在実行されているコードの終わ...
  • コンパイラ・インタープリタ
    コンパイラの諸形態 コンパイラ型の開発環境の場合、コンパイラアプリケーション自体は、何かファイルを生成するだけで終わり、というのが多い。プログラムをその場で実行してくれる開発環境は、インタラクティブな開発環境、などと言われたりするが、そういうのはインタープリタ型である。 ただ、インタープリタでも、まず機械命令に変換して直後に実行すれば、コンパイラ方式のインタープリタ、というか、インタラクティブなコンパイラ型開発環境になるわけである。そのような方式はJIT(ジャスト インタイム)コンパイラ方式などといわれて、インタープリタ方式の有名なプログラミング言語環境には、最近は大抵ついているようである。現行の商用のパソコン上でのforth環境は、全部この方式になっているらしい。Mopsは68kMac上で動いていた初めからそうである(1988年頃開発されたとか)。インタープリタ環境で、一旦、...
  • POSTPONE IMMEDIATE
    IMMEDIATE IMMEDIATEというワードは、通常は、実行状態で利用される。このワード自体というよりも、このワードを実行したときに他のワードが被る効果が重要である。 IMMEDIATE ( -- ) \ 入出力は何も取らない IMMEDIATEとは、英語で、「間を置かない」とか「直接の」、「即時の」というような意味である。このワードを実行すると、その直前に定義された実行可能ワード — 通常はコロン定義である — が性質を変える。そのような性質の変わったワードはIMMEDIATE(イミディエット)ワードとも呼ばれる。どのように変わるかというと、コンパイル状態でも実行されるワードへと変わるのである。 WORD-I [何かのコード] ; IMMEDIATE \ WORD-Iがイミディエットワードになる。対応が分り易いように普通はセミコロン...
  • ヒープメモリー上へのコンパイルと実行コード領域
    コードをコンパイル後直ちに実行するためのメカニズム コンパイラ型言語環境を作ってみたいという人には参考になるかもしれない話、ということで、iMopsでのコード実行のメカニズム、特に、メモリーの使用法について、説明してみようと思います。 アプリケーションの起動実行 初歩的なことですが、普通のアプリケーションプログラムの実行コードは、実行可能ファイルとして、アプリケーションバンドル(束)の中に紛れ込んでいます。これがダブルクリックで実行されるわけですが、この過程は、見た目は単純ですが、実はかなり複雑な手続きを経た上で実現されています。これについてあまり詳しく知る必要も無いのですが、ともかく、これは、OSのサービスとして提供されているのが一般的です。 実行可能ファイルには、“この中に実行可能コード(マシン語の符号)が入ってるよ”、という符牒が、ヘッダデー...
  • 不定ループ
    不定ループ(Indefinite Loop)とは、繰り返し回数の限界が予め決まっていないループである。ワードBEGINで始まる。繰り返しをやめるか続けるかを判定するには、何らかのフラグを用いるが、その判定の仕方の違いに対応していくつかのバリエーションがある。以下のループも、全て、ワード定義内でしか利用できない。 不定ループは、指標 I を利用できない。もしも繰り返し回数を数える必要があるなら、変数を定義するなどして、明示的にカウントしなければならない。他方で、リターンスタックの配備がないため、途中でEXITする場合でも、UNLOOP等の後処理ワードは必要ない。 BEGIN UNTIL BEGINで始まり、UNTILで終わるループでは、まずBEGIN以降のコードが実行される。そのコードは最後にUNTILに与えるためにスタック上にフラグを残さなければならない。UNTILはこのフ...
  • プラグイン/ニュース
    ニュース @wikiのwikiモードでは #news(興味のある単語) と入力することで、あるキーワードに関連するニュース一覧を表示することができます 詳しくはこちらをご覧ください。 =>http //atwiki.jp/guide/17_174_ja.html たとえば、#news(wiki)と入力すると以下のように表示されます。 SlackからWikiへ!シームレスな文章作成・共有が可能な「GROWIBot」リリース - アットプレス(プレスリリース) 【グランサガ】リセマラ当たりランキング - グランサガ攻略wiki - Gamerch(ゲーマチ) ポケモンBDSP(ダイパリメイク)攻略wiki - AppMedia(アップメディア) 【ひなこい】最強ひな写ランキング - ひなこい攻略Wiki - Gamerch(ゲーマチ) モンハンライズ攻...
  • @wiki全体から「Forthのわかりにくさ」で調べる

更新順にページ一覧表示 | 作成順にページ一覧表示 | ページ名順にページ一覧表示 | wiki内検索