2 ポイント 投稿者 GN⁺ 2023-07-18 | 1件のコメント | WhatsAppで共有
  • Forth は、Chuck Moore が長いコンパイル・パンチカードの流れを減らすために作った小さなインタプリタから出発し、エディタ・オペレーティングシステム・コンパイラまで取り込んだシステムへと成長した
  • 後置記法(RPN)、データスタック、単語(dictionary)は見慣れない文法ではなく、制約の多いハードウェアで無駄や反復作業を減らすための設計だった
  • Forth の核心は、:, ;, IF, コメント、変数のような要素まで言語の中で定義・再定義できるブートストラップ可能な構造にある
  • JonesForth, nasmjf, PlanckForth, sectorforth のような実装は、Forth が数十〜数百バイト、あるいは少数の primitive から出発して、インタプリタ・コンパイラ・アセンブラ・DSL へ拡張できることを示している
  • 宇宙船、Open Firmware、Jupiter Ace、Canon Cat、Harris RTX2010、GreenArrays の事例は、Forth が対話的開発、小さなコード、ハードウェア親和性、低消費電力コンピューティングと強く結びついていることを示している

Usenet の伝説から Forth 探究へと続く出発点

  • Dave Gauer は、Forth を発見し、それをコンピューティングの歴史の中に位置づけてみる個人的な旅路を整理しており、このページは短い発表スライドをもとに翻案されたもの
  • 1990年代の Usenet の comp.*、とくに comp.lang.* グループは、プログラミングを学び議論する重要な場所だった
    • Linus Torvalds による Linux の最初の発表も、1991年に comp.os.minix へ投稿された事例として言及される
    • 1990年代後半の Perl は、初期 Web において CGI を通じた動的ページやフォーム処理の言語として大きな比重を占めていた
  • Usenet 時代に触れた Lisp 系言語、Y combinator、The Little Schemer、The Story of Mel のような伝説が、Forth への好奇心へとつながった
  • Forth は当初、「整数の値を変えられるほど柔軟な言語」という話として受け取られ、Chuck Moore は数画面分のコードでどんなプログラムでも書ける「mad wizard」のように記憶された
  • James Hague の programming in the twenty-first century ブログシリーズが、Forth 探究の最後のきっかけになった

RPN とスタックは出発点にすぎない

  • Forth の第一印象は後置記法、すなわち Reverse Polish Notation(RPN)である
    • 一般的な中置記法 3 + 4 とは異なり、Forth では 3 4 + のように演算子を被演算子の後ろに置く
    • Forth の例 3 4 * 5 6 * + .42 を出力する
    • dc では同じ計算を 3 4 * 5 6 * + p と表現する
  • RPN は、括弧なしで入れ子の式を望む順序で計算できるようにする
    • 3 4 * が 12 を作り、5 6 * が 30 を作り、最後の + が 42 を作る
    • Forth で . はスタックから値を取り出して出力する
  • HP-35 電卓 は、RPN がコンピュータサイエンスの外でも知られるようになるうえで重要な歴史的事例である
    • 1970年代初頭、HP は強力なデスクトップ電卓を持っており、HP-35 はその計算能力を「shirt pocket」電卓に収めた事例として紹介される
    • HP の電卓は RPN 文法で有名で、RPN は効率的だが部外者にはやや難解に見えた
  • 第二の特徴はデータスタックである
    • PUSH, POP, SWAP, DUP のような動作は Forth word でもある
    • 数字を入力するとスタックに積まれ、演算子はスタックから値を取り出して計算し、その結果を再び積む
  • スタックは、中間値に名前を付ける必要を減らす
    • 多くの imperative language では result2, matched_part3 のような一時名が必要になる
    • 名前なしで作業する方式は、implicit、tacit、point-free programming とも呼ばれる
    • Forth を RPN とスタックだけで理解するのは不十分だが、歴史的起源を理解する出発点としては妥当である

Concatenative programming と Joy、そして Forth の違い

  • Forth を探っていくと、concatenative programming という概念に出会う
    • applicative の例は eat(bake(prove(mix(ingredients))))
    • concatenative の例は ingredients mix prove bake eat
    • 関数は順番に並べられ、各段階の値は次の段階へ暗黙に渡される
  • Joy は concatenative language の代表例である
    • Manfred von Thun は、John Backus による 1977 年の ACM Turing Award lecture “Can Programming Be Liberated from the von Neumann Style?” から着想を得た
    • Joy では、すべての関数が 1 つのスタックを入力として受け取り、1 つのスタックを出力として返す
    • プログラムは左から右へ読まれる関数の一覧である
  • Joy の quotation と combinator は、変数なしの計算方式を示している
    • JavaScript の [1, 2, 3, 4].map(n => n + 1)[2,3,4,5] を作る
    • Joy では [1 2 3 4] [1 +] map で同じ結果を得る
    • Joy の [] は、データだけでなくプログラムも入れられる quotation メカニズムである
  • Combinator は、関数を入力として受け取る高階関数として扱われる
    • map() は、リスト走査の定型処理を抽象化する例である
    • I, K, S combinator と SKI calculus は、普遍計算を説明する構成として登場する
    • SK だけでも、普遍計算のための完全なシステムになりうる
  • Forth でも execution token と EXECUTE word によって高階関数を作れる
    • FOO EXECUTEFOO word が返した word を実行する
    • MAP, FOLD, REDUCE のような combinatorial word を定義できる
  • Forth と Joy は見た目の文法こそ似ているが、式を解釈する方法は異なる
    • Forth で 2 3 + は「2 と 3 をスタックに push して足す」と読まれる
    • Joy では「関数 2、3、+ の composition は関数 5 と同じである」と読まれる
    • Forth は、抽象的な concatenative computing の原理よりもハードウェアとの相互作用の中で成長した言語に近い

Chuck MooreがForthを作るまでの道のり

  • 1958年、Chuck MooreはSmithsonian Astrophysical ObservatoryとMITにいた時期にFortranとIBM 704を使用していた
    • MooreはForth, the Early yearsの中で「Compiling took 30 minutes...you got one shot per day」と述べている
    • IBM 704は部屋を埋めるほどの真空管コンピュータで、平均して約8時間ごとに故障していたという引用も登場する
  • Mooreは再コンパイルを減らすため、プログラムを制御するカードを読み込む単純なインタプリタを作った
    • recompileなしで複数のsatelliteに対する異なるequationを構成できた
    • free-form input formatはFortranのformatted columnよりも人間が書くうえで信頼性が高かった
    • このシステムが後にForthと呼ばれることになるシステムの起源となった
  • 1961年、StanfordでMooreはBurroughs B5500を使い、CURVEというmathematical applicationを書いた
    • CURVEには、より洗練されたinterpreter、data stack、control flow operatorが含まれていた
    • 機能としてはおおむねIF ELSE DUP DROP SWAP + - *のようなForth wordに相当する
    • parameter stackと新しいprocedure定義機能が追加され、Forthに近い構造が現れる
  • 1965年前後にはteletype、paper tape、timesharing、interactive terminal環境が登場し、Forthはよりインタラクティブになった
    • KEY, EMIT, CR, SPACE, DIGITのようなwordが追加された
    • これらのwordはMooreのシステムをprogram editorへと変え、ユーザーはprogramの中でprogramを編集できるようになった
  • 1968年、MohascoでMooreはIBM 1130を使って作業し、「FORTH」という名前を付けた
    • IBM 1130は16ビット、8KB RAM構成で、ファイル名は5文字に制限されていた
    • Mooreの「fourth generation」システムは5文字制限のためFORTHになった
    • この時期にreturn call stackとword dictionaryが追加された
  • Forthの名前付きword dictionaryは主要な抽象化として機能する
    • : DOUBLE DUP + ;
    • : QUAD DOUBLE DOUBLE ;
    • return stackがなければ、DOUBLEの実行後にQUADの残り位置へ戻ることはできない

NRAO、ポーティング、indirect threaded code

  • 1970年代初頭、MooreはNational Radio Astronomy Observatoryでradio telescope向けのコンピュータ制御ソフトウェアを書いた
    • NRAOにはminicomputerでFortranを使う方針があったが、Mooreは以前の成功をもとにForth使用の許可を得た
    • spectral-line observingでは、収集中のspectraを表示し、least-squaresでline-shapesをフィッティングできた
    • この作業はonline data reductionのstate-of-the-artを前進させ、天文学者たちはこれをinter-stellar moleculesの発見とマッピングに利用した
  • Elizabeth “Bess” RatherはForthを受け入れ、1972年に最初のForth manualを書いた
    • その後、Chuck MooreとともにFORTH, Incを共同創業した
    • 2006年に引退するまで、Forth languageの主要な専門家かつpromoterの一人であり続けた
  • ForthはIBM 360/50、Honeywell 316、Honeywell DDP-116、DEC PDP-11など複数のマシンへポートされた
    • H316向けForth実装はコンピュータ自身の上でプログラミングされ、別のForthを作るためにも使われたため、最初のcompleteでstand-aloneなimplementationと見なされている
    • PDP-11はUnixとC programming languageの歴史につながる重要なminicomputerである
  • 複数のマシンへポーティングできた背景には、indirect threaded codeがあった
    • ここでのthreaded codeはconcurrencyやmulti-threaded programmingとは関係ない
    • threaded codeはsubroutine call instructionの代わりにsubroutine addressの一覧を格納する
    • address listを実行するにはcode interpreterが必要になる
  • indirect threaded codeは、codeを直接指すアドレスではなく、codeを指すアドレスを指すアドレスの一覧を格納する
    • 2段目のindirectionによって、異なる種類のsubroutineごとに別々のinner interpreterを持てる
    • Forthではouter interpreterがユーザーがterminalで対話する部分で、inner interpreterがwordの残りを実行する
  • この時点でのForthは、単純なcommand interpreterを超え、interactive language、editor、operating system、code storage and execution methodへと拡張されていた
    • postfix notation、stack-oriented、concatenative style、interpreted、machine architectureにhighly adaptable、extremely compactといった特性が整理される
    • Forthは1958年に一度で設計された言語ではなく、Mooreが自身の必要と新しいhardwareに合わせて成長させた結果である

Forthを理解するにはForthを実装しなければならない

  • 「To understand Forth, you have to implement a Forth」という助言で重要な言葉はa Forthである
    • Chuck Mooreの観点では、Forth systemはsystemとtaskに合わせてcustom-tailoredされるときに最もよく機能する
  • 筆者はJonesForthのソースを扱う前に、assemblyとLinux ABIの基礎を学ぶためAssembly Nightsを書いた
    • JonesForthはGNU GAS assemblerで書かれたi386 assemblyソースを使っている
    • 32-bit専用で、Linux system call ABIを直接使う
    • JonesForthをNASM assemblerで動作する複製へポートするのに約1年を費やし、そのポートがnasmjfである
  • nasmjfのポーティング過程で、traditionalなindirect threaded Forthの動作方式を身につけた
    • JonesForthのjonesforth.Sはassembly部分を収めた単一ファイルで、Richard W.M. JonesはASCII artと説明でinterpreterの流れを案内している
    • 筆者は自身の理解を整理するため、nasmjfソースに複数のASCII artダイアグラムを書いた
  • NEXT macroはword実行後に次のwordへ進む中核的な流れである
%macro NEXT 0
    lodsd     ; NEXT: Load from memory into eax, inc esi to point to next word.
    jmp [eax] ; Jump to whatever code we're now pointing at.
%endmacro
  • lodsdはmemoryからdouble wordをeaxへ移し、次の位置を指すように更新する
  • jmp [eax]は現在指している場所へ実行を移し、そのsubroutineのinner interpreterとなる
  • traditionalなForthには基本的にcode wordとcolon wordがある
    • code wordはmachine codeで書かれたprimitiveである
    • colon wordはForth languageで書かれた通常のwordで、: compilerによって組み立てられる
    • colon wordはEXITで終わり、EXITはreturn stackを処理したあとNEXTへ流れをつなぐ
  • Forthは非常に小さな部品が協調して動き、running systemを作る構造になっている
    • 低いレベルでは柔軟性と単純さが得られる一方、高いレベルでは理解しやすさが犠牲になることがある

Code word、colon word、compiler は同じインタプリタ上で動作する

  • SWAPDUPDROP は、Forth primitive が machine code としてどれほど直接的に実装できるかを示している
DEFCODE "SWAP",SWAP,0
    pop eax
    pop ebx
    push eax
    push ebx
NEXT
DEFCODE "DUP",DUP,0
    mov eax, [esp]
    push eax
NEXT
DEFCODE "DROP",DROP,0
    pop eax
NEXT
  • JonesForth は i386 の call/return stack を Forth の parameter stack として使うため、native の poppush で stack operation を実装している
  • nasmjf には 130 個の code word があり、そのほとんどは効率性のためのものだ
    • bootstrappable な Forth system に必要な machine-code word 数には theoretical minimum がある
    • primitive の数を過度に減らすと、残りの Forth code は非効率でいびつなものになりうる
    • Frank Sergeant の A 3-INSTRUCTION FORTH FOR EMBEDDED SYSTEMS WORK は、Motorola MC68HC11 上で 66 bytes だけを必要とする 3-instruction Forth を扱っている
    • sectorforth は、512-byte boot sector に収まる 16-bit x86 Forth である
  • colon word は、既存の word を composition して新しい word を作る方式である
: SDD SWAP DROP DUP ;
  • SDDSWAP DROP DUP を順番に呼び出したのと同じ効果を持つ
  • indirect threaded code の観点では、colon word は 3 つの code word の inner interpreter address へ compile された状態である
  • :; は syntax のように見えるが、実際には Forth word である
    • : は新しい word name を受け取り、compile mode を有効にする
    • ; は新しい dictionary entry を完成させ、compile mode を無効にする
    • ユーザーは : 自体を自分の definition で置き換えて、Forth を拡張したり変更したりできる
    • Forth の唯一の syntax は、input token 間の whitespace として扱われる
  • Forth における compiling とは、memory に word address または literal と push code を入れることだ
    • normal mode では word を即座に実行する
    • compile mode では word address を memory に保存する
    • 同じ interpreter が code の実行と code の compiling の両方を担う
  • IF...THEN のような control structure も Forth 自体で実装できる
: IF IMMEDIATE ' 0BRANCH , HERE @ 0 , ;

: THEN IMMEDIATE DUP HERE @ SWAP - SWAP ! ;
  • IF のような fundamental な要素でさえ language の中で定義されるという点が、“The programming language that writes itself” というタイトルの核心的な根拠である
  • nested comment である ( ... )jonesforth.f では Forth で実装されている
    • comment でさえ language の中で実装されており、ユーザーはそれを再定義したり、自分独自の comment 方式を追加したりできる
    • この例は、Forth に native syntax がほとんどないことを強調している

Dictionary と再定義が拡張性を生む

  • Forth dictionary は伝統的に linked list を使い、word matching はもっとも新しい entry から始まる
    • 同じ名前を持つ最新の word definition が以前の definition を隠す
    • どんな word でも再定義でき、assembly で最初に定義された word でさえ再定義可能である
    • 既存の compile 済み word は名前ではなく address を保存しているため、再定義前の word の address を引き続き指す
  • 新しい definition から同じ名前の以前の word を呼び出して、word を拡張できる
    • recursive な word を作るとき、: は現在 compile 中の word を dictionary から隠すか、無効状態としてマークする
    • 現在の word の内部で自分自身を呼び出すには RECURSE が必要になる
  • Leo Brodie の Thinking Forth から取り、改変したリンゴ変数の例は、Forth の柔軟性を示している
    • VARIABLE APPLES は、呼び出し時に memory address を stack に載せる APPLES word を作る
    • 20 APPLES ! は、その address に 20 を保存する
    • APPLES ? は値を取り出して表示する
    • Thinking Forth (PDF) は無料で提供されている
  • 赤いリンゴと青いリンゴを別々に追跡する必要があっても、既存の APPLES 使用コードを変更せずに済む
VARIABLE COLOR

VARIABLE REDS
: RED REDS COLOR ! ;

VARIABLE GREENS
: GREEN GREENS COLOR ! ;

: APPLES COLOR @ ;
  • 新しい APPLES も address を stack に載せる word なので、既存の APPLES !APPLES ? の使い方は維持される
  • address が有効なリンゴの色に応じて REDS または GREENS に変わるだけである
  • 一般的な言語の観点では、変数が関数に変わったように見えるが、Forth では変数も address を載せる word であり、関数も word なので、言語レベルの概念変化はない
  • 数値のように見える token でさえ dictionary word として再定義できる
: 4 12 ;
  • ." The value of 4 is " 4 . CR を実行すると、The value of 4 is 12 が出力される

Meow5 と「抵抗が最も小さい経路」としての Forth

  • JonesForth を NASM へ移植した nasmjf は、Moore の過程を再現したものではなく、最終成果物を細かく観察した「master copy」に近い訓練だった
  • その後、筆者は Meow5 という極端な concatenative programming の実験を進めた
    • Meow5 は、すべての code を常に連結し、inline 化する実験である
    • Forth のように parameter stack の概念を使うため、concatenative である
    • function call address を保存する代わりに、関数全体のコピーを保存したらどうなるかを押し進めた思考実験である
  • Meow5 の核心は、すべての word を 100% inline することだった
    • 小さな function call overhead を避ける一般的な最適化である inline expansion から出発している
    • DROP のような 1 命令の primitive を、複数の jump を経由して呼び出すのは無駄に見えた
  • Meow5 は「楽しい小さな失敗」で終わった
    • machine code の inline 自体はうまく動作し、出力された ELF executable file も意図どおりに動いた
    • 問題は string data で、文字列を毎回コピーするか、どの word が文字列を使うのかを複雑に追跡する必要があった
    • 選択的 inline を提供する Forth の INLINE word のほうが、より良い方式だと評価された
  • 文字列 syntax においても Moore の助言が再確認された
    • Forth では " という word を使うので、" Hello World." のように whitespace が必要になる
    • Meow5 は "Hello World." という形の自然な quoting style と、\n\" のような escape sequence を採用した
    • この選択のために tokenizer と interpreter のあちこちで " の例外処理が必要になり、純粋性と単純性が損なわれた
  • Forth の道筋をたどり始めると、残りも「自ら書かれていく」ようにつながっていく
    • Forth は bootstrapping であり、meta-programming であり、OS や IDE/editor にもなりうる
    • まったく新しい CPU architecture 向けにもっとも単純な interpreter を作っていくと、Forth に似たものを書くことになるかもしれない、という主張につながる

小規模な Forth 実装と実際の用途

  • Forth は Forth の中でさらに多くの Forth を定義でき、多くの Forth にはアセンブラも含まれる
    • JonesForth の末尾には、Forth の中で動作するアセンブラのスタブがある
    • ;CODE は、codeword が DOCOL ではなく assembled code を指すように header を更新する
  • PlanckForth は、手書きの 1KB 未満のバイナリ Forth である
    • 完全な ELF バイナリと動作する Forth 実装が 1KB 未満に収まっている
    • bootstrap.fs は、初期の難解な演算子群から始まり、数百行後には読みやすい Forth になる
  • 小規模実装の事例は、Forth の極端な圧縮性を示している
    • SmithForth は David Smith による手書きの machine code Forth で、1,000 バイトかつ 1,000 行の Forth システムとして紹介されている
    • sectorforth は 512 バイトの boot sector Forth である
  • Forth は、発電所、ロボティクス、ミサイル追跡システム、産業自動化、ビデオゲームの組み込み言語、データベース、会計、ワードプロセッサ、グラフィックス、計算システム、Open Firmware boot loader、さまざまなプロセッサやマイクロコントローラで使われている
  • Open Firmware は Sun Microsystems のエンジニアリングから生まれた重要な事例である
    • interactive programming language ベースであるため、新しいハードウェアを効率的にテストし、bring-up できる
    • Space Shuttle ESN の事例では、Open Firmware はハードウェア、ソフトウェア、プラグインドライバ、ファームウェア自体までデバッグできるツールとして扱われている
  • Jupiter Ace は 1982 年の英国製ホームコンピュータで、OS が Forth だった
    • OS と routine library は 8KB ROM に収まっていた
    • 組み込み Forth は interpreted BASIC より「10 倍速く」、メモリ要件も半分未満だったという 1982 年の引用がある
  • Canon Cat は 1987 年に OS として Forth を採用し、256KB ROM の中に OS、オフィススイート、プログラミング環境を収めていた
    • Jef Raskin のキーボード中心インターフェースと設計思想を、ハードウェアとソフトウェアで実装した製品である
    • Forth インターフェースへの進入手順は最優先の利用フローには見えないが、手順を知っていれば数回のキー入力で可能である

宇宙ソフトウェアと Forth

  • Forth の興味深い用途のひとつが 宇宙探査 である
    • 宇宙機は高コストで、修理のために接近するのが難しいか不可能なため、ソフトウェアの信頼性が重要になる
    • NASA における Forth 利用プロジェクトの一覧は長く、元のリンクは消えているが、Wayback Machine と forth.com の複製がある
  • Space Shuttle Small Payload Accommodations Interface Module(SPAIM) は Forth を使った事例である
    • 開発チームは PC 上で Forth routine を作成し、ダウンロードしてから対話的にテストした
    • STS-45 Shuttle mission の期間中、SPAIM の flight software は問題なく動作したという引用がある
    • SPAIM の Forth system は multitasking に対応し、各 task は独自の stack を持ち、watchdog task が stack の状態を監視していた
  • Space Shuttle Robot Arm Simulator は、複雑な装置を 1 人のプログラマが 5 週間で開発した事例である
    • 3 軸 joystick の命令を受け取り、長さ 50 フィート、6 つの関節、6 つの座標系を持つアームを制御する必要があった
    • system には 14 個の独立した process があったと引用されている
    • simulation test が徹底していたため、現地設置後に executive control アルゴリズムを変更しなかったという引用がある
  • Shuttle Mission Design and Operations System(SMDOS) は JPL の地上ベース制御ソフトウェアだった
    • SIR-B mission の最中、複数のハードウェア故障に対し、その場でのソフトウェア修正で対応した
    • アンテナ問題と軌道変更のために新しいデータ収集戦略が必要となり、SMDOS は新条件に合う計画を表示するために使われた
    • 多くのデータは失われたが、回転・捕捉・回転・送信という方式で 20% のデータを回収した
  • Harris RTX2010 は、多くの宇宙用途で使われた Forth ハードウェアである
    • Forth を直接実行する
    • 256-word 深さの hardware stack を 2 基備える
    • 8MHz clock と低い latency
    • radiation-hardened 特性
  • Rosetta と Philae は、彗星を周回する宇宙機を送り、着陸機を彗星表面に降ろした最初のミッションとして紹介されている
    • Rosetta の Ion and Electron Sensor は Harris RTX2010 を使用している
    • Philae lander は CDMS に RTX2010 を 2 基、ADS 制御用に 2 基使用している
    • Rosetta は 2004 年から 2014 年まで飛行し、67P/Churyumov-Gerasimenko と会合した
    • 67P は幅 4km で、6 年半ごとに太陽を公転する
  • Philae は、銛と着陸 thruster の失敗により表面で低重力下の bounce を経験したが、科学ミッションの「80%」を実行できるだけの堅牢性を備えていた
  • 1993 年の Galileo magnetometer コードパッチ事例も登場する
    • magnetometer は RCA1802、RAM 2KB、ROM 2KB を備え、Apple II ベースの開発システムで Forth によりプログラムされていた
    • 装置コードの途中に不良メモリバイトが生じ、そのバイトを使わないようにパッチを当てる必要があった
    • 引用者は Lisp でその装置向け Forth 開発環境とハードウェアシミュレータを一から書き、パッチを生成しており、パートタイムで 3 カ月未満しかかからなかった

Forth は単一の実装というより、アイデアと系譜に近い

  • Forth は、ひとつの代表的実装というより 共有された概念と系譜 を持つアイデアに近い
  • Forth を学びにくい理由のひとつは、「Forth」という名前を排他的に代表する単一の実装が存在しない点である
    • 初期の Forth の一部は、「Forth」という名前そのものより先行していた
    • Forth 標準は ANS Forth 文書へと連なり、Forth 2012 Standard と Forth200x committee に言及がある
  • 各種 Forth は概念と共通の word を共有する一方、目的特化型の Forth は独自の特殊語彙を持つ
  • Chuck Moore は 1973 年に Forth, Inc を設立し、その後さまざまなシステムへ Forth を移植してきており、今も新しいシステムを作り続けている
  • colorForth は Chuck Moore の後期の環境である
    • ソースコードの色が、標準 Forth の一部の句読点の代わりとなって word の処理方法を決定する
    • 色は Forth の意味論を単純化し、compile 速度を高め、Moore の弱い視力にも役立つものとして扱われている
    • colorForth は独自の 63KB OS を含む
  • Moore は、機能が追加され続けることでソフトウェアは複雑化し、誰も意図しない結果を恐れて変更できなくなると考えている
    • その結果、必要なのは単一アプリケーションにキャリアを捧げ、繰り返し書き直して完成度を高める専任プログラマだという主張につながる

機械親和性、Forthチップ、GreenArrays

  • Chuck Mooreは1950年代からソフトウェアの複雑性に反対してきており、Windows、UNIX、DOSのようなオペレーティングシステムを理解不能または不要なものと見なす引用が登場する
  • 筆者はMooreの哲学をMechanical Sympathyで説明している
    • この表現はFormula OneドライバーのJackie Stewartの引用に由来し、ソフトウェアの文脈ではMartin ThompsonのWhy Mechanical Sympathy?で使われている
    • Forthは電気エンジニアや組み込みシステム設計者のような「ハードウェア寄りの人々」に人気がある傾向がある
  • Chuck Mooreの本当の情熱はプロセッサ設計にあるように見える
    • Harris RTX2000とRTX2010は、実質的にMooreのチップとして紹介されている
    • Mooreは1983年のNovix N400 gate arrayからハードウェアを設計しており、改良された設計がHarrisに販売されてRTXチップになった
  • Mooreは500行のForthで書いた独自のVLSIソフトウェアOKADでプロセッサを設計した
    • VLSI Design Tools (OKAD)では、500行のcolorForthがチップ設計に必要なすべてを提供すると説明している
    • OKADは、論理ゲート技術、回路レイアウト、電気的動作のsimulation、GDSII exportを含むツール群である
  • Novix NC4000は高水準のForth命令を直接実行するよう設計された超高速処理エンジンである
    • 一般的なassembly languageと内部microcodeを排除することで性能を得ている
    • 二重スタックarchitectureはsubroutine実装のoverheadを大幅に減らす
  • GreenArraysチップは、Mooreの2013年の発表「Programming a 144-computer chip to minimize power」を中心に紹介される
    • 1つのチップに144個の非同期コンピュータを備える
    • アイドル状態のcoreは100 nW、アクティブなcoreは4 mWを消費し、666 Mipsで動作した後にアイドル状態へ戻る
    • すべてのコンピュータが最大速度で動作したときの消費電力は550 mW、約0.5 Wである
  • GreenArrays Architectureの文書では「NO CLOCKS」が強調されている
    • 一般的なコンピュータのclock生成と分配は、待機中でも多くのエネルギーを消費する一方で何もしていないと説明される
    • GreenArraysはMulti-Core CPUではなくMulti-Computer Systemとして紹介されている

単純さ、効率、低消費電力コンピューティングの未来

  • 筆者は、ソフトウェアとハードウェアが今なお、より多くの複雑性の層を積み重ねる方向に進んできたと見ている
    • 大規模データセンターのコンピューティングは広告費によって間接的に支払われているため、安価または無料だと認識されている
    • 実際に支払われている対価は、ユーザーの注意と個人データだと説明している
  • 今後も、より非効率で粗雑に作られたソフトウェアと、さらに急激に高まるハードウェア要求を使い続ける理由はないと主張する
  • Forth類似言語は次の分野で強い未来を持ちうる
    • 小さく、あらゆる場所にあるコンピュータ
    • 太陽光電力
    • 強く制約されたVM
  • Dennard scalingは2006年ごろにはほぼ止まった
    • より小さなtransistorがより高い速度と低い電圧を可能にしていた関係は、電流漏れと発熱のため約4GHzで頭打ちになった
    • Herb SutterのThe Free Lunch Is Overは、CPU性能向上の方法がhyper-threadingとmulticoreへ移行しつつあることを扱った文章である
  • Sutterは、アプリケーションを並行性に合わせて再設計するか、より効率的で無駄の少ないコードを書くべきだと見ている
    • 性能最適化の重要性が下がるのではなく、むしろ高まるだろうと述べている
  • 今日では、IBM 704よりはるかに強力なmicrocontrollerを小銭程度の価格で買うことができ、その上で強力なForth systemを書くことができる
    • microcontrollerはコイン電池や小型の太陽光パネルで動作できる
    • 小規模コンピューティングにとって、今ほど驚くべき時代はなかったという表現へ続く
  • Forthを理解するには、「simple」と「easy」の違いを考える必要がある
    • Rich HickeyのSimple Made Easyは、この区別を語れるようにしてくれた発表として紹介されている
    • Forthは簡単ではなく、常に楽しいとも限らないが、確かに単純な言語である
  • Guy SteeleのGrowing a Languageは、言語がprimitiveからどのように構築されるかを示す発表である
    • ユーザー定義の新しい単語がprimitiveのように見え、primitiveもユーザー定義の単語のように見えるとき、継ぎ目のないより大きな言語になるというLispの引用は、Forthにも当てはめられる
  • 最後の勧めは、自分のための完璧なプログラミング言語を作れということである

1件のコメント

 
GN⁺ 2023-07-18
Hacker News のコメント
  • Forth に触れた瞬間、自分で作ってみるべきだと思い、2年前に MiniForth1週間で作りました
    Blue Pill と元々の Arduino を対象にしていましたが、ホスト上でテストできるようクロスコンパイラとして開発しました
    退勤後に毎日いじる時間が待ち遠しいほど没頭し、平日の夜5回と週末1回で完成させました。それくらい Forth を作るのは楽しかったです
    この過程は強くおすすめします。同じように悟りを得たのは、初めて Lisp マクロに触れたとき(https://www.thanassis.space/score4.html#lisp)くらいでした
    • その通りです。1年生のコンピュータアーキテクチャの授業で、LC-3 向けの自由テーマの期末プロジェクトをやる必要がありました。以前 RedPower 2 Minecraft mod で Forth を少し触ったことがあったので、実装してみたら面白そうだと思いました
      その学期の自由時間はほとんど全部それに食われ、ある日は日が昇り始めてから、徹夜していたことに気づいて時計を見ました
      実生活で Forth を実用的に使ったことはありませんが、一から作る経験は、ほとんど宗教的体験に近いと言うのがふさわしいほどでした
      Fred Brooks が語ったプログラミングの純粋な蒸留版のようでした。プログラマは詩人のように純粋な思考の素材からわずかに離れた場所で働き、想像力だけで空中に城を築き、プログラムは呪文を正しく入力すれば、画面上にそれまで存在しなかったものが命を得る現実の魔法だ、という話です
    • 完全に同意します。ずっと昔に ZX81 BASIC で Forth コンパイラを作ったことがあります
      画面に数字1000個を出力するのに19秒かかっていたものが、瞬時に終わるレベルに変わりました
      もう一つ大きな教訓も得ました。生成された機械語を見て、完璧でもう改善できないと思ったのに、翌日戻ってきたら、はるかに速くできたのです
  • 「どうやって自分自身を書くというんだ?単に関数を書けるという意味では?」と疑問に思うかもしれません
    ある程度はその通りですが、Forth は新しいワードを定義して、それを言語そのものの一部のようにできる点で、さらに先へ進んでいます
    これらのワードは組み込み演算のように使え、言語の動作方式まで変えられます
    拡張可能な言語なので、新しい制御構造を定義したり、構文を変えるワードも作れます。こうした柔軟性は他の言語ではあまり一般的ではありません
    この点で Forth は、プログラマが言語を非常に根本的なレベルでカスタマイズし拡張できるため、「自分自身を書く」言語と見なせます
    Lisp のマクロシステムとも似ていて、Lisp マクロがコンパイル時変換によって新しい構文構造やドメイン特化言語を作れるように、Forth のワードも構文と機能を拡張できます
    • すばらしいとは思いますが、ほぼ40年プロのプログラマとして働いてきて、問題になったのは構文ではなく、いつも意味論でした
      行列乗算のように A = B + C * D; と書くほうが、呼び出す関数を一つ一つ書くより良い状況はあるでしょうが、実際にそういう問題に出会ったことはありません
      自分に想像力が足りないのか、特定の領域でだけ役に立つがその領域にいたことがないのか、Forth の構文があまりに貧弱で拡張しないと使い物にならないのか、それとも人々が車をチューニングするように言語をカスタマイズしたがっているのか、気になります
      人々がなぜ本当にここに関心を持つのか、よくわかりません
  • 現在もっとも興味深い Forth プロジェクトの一つは Dusk OS で、独自の C コンパイラを含む Forth で書かれた32ビット OS であり、複数の移植作業も進んでいます
    https://duskos.org/
    • DuskOS 自体はよく知りませんが、歴史的に Forth が「自分専用の OS」だったのは確かだとしても、現代の読者が OS と聞いて思い浮かべるものと比べると、かなり粗削りです
      8KB RAM でも動くものに何を期待するのか、という話はその通りですが、プリミティブな機能は提供していても、歴史的にはドライバやほとんどの抽象化概念がほぼありませんでした
      コードはソースからロードされるので遅く、リンクはブロックを正しい順序でロードすることに近く、新しいプログラムをロードするには先に現在のプログラムを取り除く必要がありました
      プログラム終了時にマシンをコールドスタートしていた CP/M より大きく優れているとも言いにくいですが、少なくとも CP/M は BIOS と BDOS を分離していました
    • これは見逃していました。ちょうど “Beyond the Collapse” を読んでいたところで、Lisp や APL/J、C の腕では OS レベルでの Forth の単純さに近づくのは難しそうだと感じていました
      次の週末までには必ず確認してみるつもりです
  • 最初のプログラミング言語は x86 アセンブリと Forth でした。父が Forth に夢中で、その人からプログラミングを学びました
    十代の頃に DOS 用の x86 Forth システムをいくつも作り、最後にはかなり磨き込まれた ANS 準拠の実装 “Third” まで作りました: https://github.com/benhoyt/third
    アセンブラまで含む完全にブートストラップ可能な Forth コンパイラを、数千行のコードで持てるというのはかなり驚きです
    少し前には、Forth Dimensions 誌に共著で書いた昔の記事を書き起こしました
    Forth のアイデアはいまでも良いものですが、スタック操作はすぐに退屈になり、読むのも非常に難しくなります
    https://benhoyt.com/writings/forth-lookup-tables/ のコード例、特に Search-Table を見ればわかります。名前を付けるのは難しいですが、名前を付けないのはさらに難しいようです
    • スタック操作が退屈になるのは、おそらくあなたも私も Chuck Moore ではないからかもしれません
      彼のコードは概してスタックのかき混ぜが非常に少ないです。例: http://www.merlintec.com/download/color.html
    • Third のソースコードを少し見ましたが、興味深いです
      ブートストラップ時に kernel.com を呼び出していましたが、kernel.com はどうやってビルドしたのか気になります
  • 関連する Chuck Moore の講演: “Programming a 144 Computer Chip to Minimize Power” (2013)

https://www.youtube.com/watch?v=0PclgBd6_Zs
Forth が超低消費電力コンピュータを動かす仕組みはこういうものらしい:GreenArrays は144コアの非同期チップを出荷中で、エネルギーは 7 pJ/inst しか必要としない
アイドル状態のコアは電力を使わず(100 nW)、アクティブなコアは 4 mW で高速に実行したあと(666 Mips)、通信を待ちながらアイドル状態になる

  • 「サイズと速度は、いつもアマチュアにとってだけ重要なものだと思っていた。だが現代の文脈で重要なパラメータはたった3つだけだ。電力、電力、電力
    --Chuck Moore
    https://youtu.be/0PclgBd6_Zs?t=389
  • こういう位相構造が今後数年のうちに戻ってくるのではないかと、本気で気になっている
  • 優れた入門書は Starting Forth
    教科書で見た挿絵の中でもっとも魅力的なものが載っている
    [0] https://www.forth.com/starting-forth/
  • ずっと昔、OS/2 が出たとき、友人から「OS/2 のプログラムはアセンブラでは書けず、C で書かないといけない」と聞かされた
    その言葉に反発して Forth/2 を作った
    アセンブラで書いた OS/2 向けの直接スレッド方式ネイティブコード Forth コンパイラで、Brian Matthewson が素晴らしいマニュアルを書いてくれ、数十人のユーザーを得た
    [1] https://sourceforge.net/projects/forth2/
  • 少し話はそれるが、この記事の元になった発表プロトタイプの形を読んだ記憶がある
    今の記事と基本的には同じだが、テキストはずっと少なく、余白はもっと多かった
    それに触れるのは、その資料が基盤となるウェブサイト技術の面でもミニマリズムの美しさを示しているからだ
    [0] http://ratfactor.com/forth/forth_talk_2023.html
    [1] http://ratfactor.com/minslides/
    • 自分だけの Forth を作ることと、自分だけの単純なプレゼンテーションソフトウェアを作ることの間には、何か関係があるのだろうか? https://www.mankier.com/1/techtalk-pse
  • Rust にも Forth コンパイラが存在するという点が興味深い。関連資料は [1] にある
    使い方はまだ少し不明瞭だが [2]、以前にもここで取り上げられたことがあり [3]、実装は堅実に見える
    REPL Forth 仮想マシンではないが、印象的な仮想マシン実装
    FORTH が仮想マシンなら、ストリーミングデータを管理できる小さく効率的なシステムが必要なときに、ベアメタルに近い性能を出せる最適な選択肢かもしれないと考えてきた
    オペレーティングシステムと格闘する必要がないという点もある
    これは本質的に FPGA がやっていることを標準 CPU でやるものなのではないかと思う
    ただし、必要なハードウェアと接続するためにすべてのドライバを自分で作る必要はない特殊なシステムを想像している
    [1] https://docs.rs/rust-forth-compiler/latest/src/rust_forth_co...
    [2] https://docs.rs/fortraith/latest/fortraith/
    [3] https://news.ycombinator.com/item?id=23501474
  • もう一つの Forth を自分で実装した
    元のアイデアを忠実にコピーすることが目的ではなく、少し違う動きをする
    記事では Forth を発見できると言っていたので、自分の実装も残しておく: https://github.com/loscoala/goforth
    最大の違いは、この Forth 変種ではソーステキストが完全にバイトコードへ変換され、古典的な Forth の意味でのランタイムがないことだ
    そのため、バイトコードを C に翻訳しやすい
    この Forth を使って C コードを生成し、そのコードを別のソフトウェアに埋め込んで使っている
    • その方式は非常に生産的で賢いやり方になり得るが、こうした多言語的な解法は長期的には保守上の頭痛の種になりやすい、という点は常に意識しておく必要がある
      聴音と初見を訓練できる本当に良いオープンソースプロジェクトがあるのだが、作者が作った言語で書かれており、その言語は JavaScript にコンパイルされる
      ツールチェーンを設定する面倒が大きすぎて、既知のバグがかなり多いにもかかわらず、修正する気になれなかった
      https://sightreading.training/
      https://github.com/leafo/sightreading.training
      このプロジェクトは「Moonscript」という言語で書かれている: https://github.com/leafo/moonscript
      Moonscript は Lua にコンパイルされ、Lua は JS にコンパイルされる
      正気の沙汰ではない。素晴らしい狂気ではあるが、それでも自分がコントリビューターになるのを妨げた