Submit Search
Upload
謎の言語Forthが謎なので実装した
•
0 likes
•
1,933 views
t-sin
Follow
Lisp meetup #69 にて。
Read less
Read more
Engineering
Report
Share
Report
Share
1 of 41
Download now
Download to read offline
Recommended
Rpn and forth 超入門
Rpn and forth 超入門
Yoshitaka Seo
Glibc malloc internal
Glibc malloc internal
Motohiro KOSAKI
SAT/SMTソルバの仕組み
SAT/SMTソルバの仕組み
Masahiro Sakai
いつやるの?Git入門 v1.1.0
いつやるの?Git入門 v1.1.0
Masakazu Matsushita
プログラムを高速化する話
プログラムを高速化する話
京大 マイコンクラブ
できる!並列・並行プログラミング
できる!並列・並行プログラミング
Preferred Networks
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門
masayoshi takahashi
こわくない Git
こわくない Git
Kota Saito
Recommended
Rpn and forth 超入門
Rpn and forth 超入門
Yoshitaka Seo
Glibc malloc internal
Glibc malloc internal
Motohiro KOSAKI
SAT/SMTソルバの仕組み
SAT/SMTソルバの仕組み
Masahiro Sakai
いつやるの?Git入門 v1.1.0
いつやるの?Git入門 v1.1.0
Masakazu Matsushita
プログラムを高速化する話
プログラムを高速化する話
京大 マイコンクラブ
できる!並列・並行プログラミング
できる!並列・並行プログラミング
Preferred Networks
何となく勉強した気分になれるパーサ入門
何となく勉強した気分になれるパーサ入門
masayoshi takahashi
こわくない Git
こわくない Git
Kota Saito
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps
MITSUNARI Shigeo
中3女子でもわかる constexpr
中3女子でもわかる constexpr
Genya Murakami
30分で分かる!OSの作り方 ver.2
30分で分かる!OSの作り方 ver.2
uchan_nos
メタプログラミングって何だろう
メタプログラミングって何だろう
Kota Mizushima
Constexpr 中3女子テクニック
Constexpr 中3女子テクニック
Genya Murakami
中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr
Genya Murakami
ARM LinuxのMMUはわかりにくい
ARM LinuxのMMUはわかりにくい
wata2ki
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
yohhoy
C/C++プログラマのための開発ツール
C/C++プログラマのための開発ツール
MITSUNARI Shigeo
async/await のしくみ
async/await のしくみ
信之 岩永
Effective Modern C++ 勉強会 Item 22
Effective Modern C++ 勉強会 Item 22
Keisuke Fukuda
Rustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったか
ShunsukeNakamura17
Linuxのsemaphoreとmutexを見る
Linuxのsemaphoreとmutexを見る
wata2ki
Pythonによる黒魔術入門
Pythonによる黒魔術入門
大樹 小倉
Ruby で高速なプログラムを書く
Ruby で高速なプログラムを書く
mametter
コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!
amusementcreators
カスタムメモリマネージャと高速なメモリアロケータについて
カスタムメモリマネージャと高速なメモリアロケータについて
alwei
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
shinjiigarashi
ふつうのRailsアプリケーション開発
ふつうのRailsアプリケーション開発
Takafumi ONAKA
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜
Teppei Sato
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1
Ransui Iso
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか
m2ym
More Related Content
What's hot
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps
MITSUNARI Shigeo
中3女子でもわかる constexpr
中3女子でもわかる constexpr
Genya Murakami
30分で分かる!OSの作り方 ver.2
30分で分かる!OSの作り方 ver.2
uchan_nos
メタプログラミングって何だろう
メタプログラミングって何だろう
Kota Mizushima
Constexpr 中3女子テクニック
Constexpr 中3女子テクニック
Genya Murakami
中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr
Genya Murakami
ARM LinuxのMMUはわかりにくい
ARM LinuxのMMUはわかりにくい
wata2ki
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
yohhoy
C/C++プログラマのための開発ツール
C/C++プログラマのための開発ツール
MITSUNARI Shigeo
async/await のしくみ
async/await のしくみ
信之 岩永
Effective Modern C++ 勉強会 Item 22
Effective Modern C++ 勉強会 Item 22
Keisuke Fukuda
Rustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったか
ShunsukeNakamura17
Linuxのsemaphoreとmutexを見る
Linuxのsemaphoreとmutexを見る
wata2ki
Pythonによる黒魔術入門
Pythonによる黒魔術入門
大樹 小倉
Ruby で高速なプログラムを書く
Ruby で高速なプログラムを書く
mametter
コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!
amusementcreators
カスタムメモリマネージャと高速なメモリアロケータについて
カスタムメモリマネージャと高速なメモリアロケータについて
alwei
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
shinjiigarashi
ふつうのRailsアプリケーション開発
ふつうのRailsアプリケーション開発
Takafumi ONAKA
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜
Teppei Sato
What's hot
(20)
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps
中3女子でもわかる constexpr
中3女子でもわかる constexpr
30分で分かる!OSの作り方 ver.2
30分で分かる!OSの作り方 ver.2
メタプログラミングって何だろう
メタプログラミングって何だろう
Constexpr 中3女子テクニック
Constexpr 中3女子テクニック
中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr
ARM LinuxのMMUはわかりにくい
ARM LinuxのMMUはわかりにくい
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
C/C++プログラマのための開発ツール
C/C++プログラマのための開発ツール
async/await のしくみ
async/await のしくみ
Effective Modern C++ 勉強会 Item 22
Effective Modern C++ 勉強会 Item 22
Rustに触れて私のPythonはどう変わったか
Rustに触れて私のPythonはどう変わったか
Linuxのsemaphoreとmutexを見る
Linuxのsemaphoreとmutexを見る
Pythonによる黒魔術入門
Pythonによる黒魔術入門
Ruby で高速なプログラムを書く
Ruby で高速なプログラムを書く
コルーチンでC++でも楽々ゲーム作成!
コルーチンでC++でも楽々ゲーム作成!
カスタムメモリマネージャと高速なメモリアロケータについて
カスタムメモリマネージャと高速なメモリアロケータについて
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
導入から 10 年、PHP の trait は滅びるべきなのか その適切な使いどころと弱点、将来について
ふつうのRailsアプリケーション開発
ふつうのRailsアプリケーション開発
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜
Node.js Native ESM への道 〜最終章: Babel / TypeScript Modules との闘い〜
Similar to 謎の言語Forthが謎なので実装した
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1
Ransui Iso
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか
m2ym
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
inaz2
NGS速習コース:UNIXの基礎の理解/Linux導入
NGS速習コース:UNIXの基礎の理解/Linux導入
Takeru Nakazato
Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6
Ransui Iso
ZFSのソースコードをチラ見してみる
ZFSのソースコードをチラ見してみる
Koichi Suzuki
PFIセミナーH271022 ~コマンドを叩いて遊ぶ コンテナ仮想、その裏側~
PFIセミナーH271022 ~コマンドを叩いて遊ぶ コンテナ仮想、その裏側~
Preferred Networks
2011.09.18 v7から始めるunix まとめ
2011.09.18 v7から始めるunix まとめ
Makiko Konoshima
続・SECDマシン
続・SECDマシン
t-sin
つくっておぼえる!仮想マシン〜直前で実装編〜
つくっておぼえる!仮想マシン〜直前で実装編〜
Eric Sartre
Lxc cf201207-presen
Lxc cf201207-presen
Kouhei Maeda
What is Metasepi?
What is Metasepi?
Kiwamu Okabe
NetBSDのクロスビルドのしくみとインストール済みLive Imageの作成
NetBSDのクロスビルドのしくみとインストール済みLive Imageの作成
Izumi Tsutsui
Buffer overflow
Buffer overflow
ionis111
ゆるふわLinux-HA 〜PostgreSQL編〜
ゆるふわLinux-HA 〜PostgreSQL編〜
Taro Matsuzawa
nftables: the Next Generation Firewall in Linux
nftables: the Next Generation Firewall in Linux
Tomofumi Hayashi
Sagittariusの紹介
Sagittariusの紹介
Kato Takashi
Rubyで実はwritev(2) が使われているはなし
Rubyで実はwritev(2) が使われているはなし
Masaki Matsushita
Solr 4.0 の主な機能
Solr 4.0 の主な機能
Shinichiro Abe
スタート低レイヤー #0
スタート低レイヤー #0
Kiwamu Okabe
Similar to 謎の言語Forthが謎なので実装した
(20)
Lisp tutorial for Pythonista : Day 1
Lisp tutorial for Pythonista : Day 1
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか
括弧への異常な愛情 または私は如何にして心配するのを止めてCommon Lispを愛するようになったか
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
ROP Illmatic: Exploring Universal ROP on glibc x86-64 (ja)
NGS速習コース:UNIXの基礎の理解/Linux導入
NGS速習コース:UNIXの基礎の理解/Linux導入
Lisp Tutorial for Pythonista Day 6
Lisp Tutorial for Pythonista Day 6
ZFSのソースコードをチラ見してみる
ZFSのソースコードをチラ見してみる
PFIセミナーH271022 ~コマンドを叩いて遊ぶ コンテナ仮想、その裏側~
PFIセミナーH271022 ~コマンドを叩いて遊ぶ コンテナ仮想、その裏側~
2011.09.18 v7から始めるunix まとめ
2011.09.18 v7から始めるunix まとめ
続・SECDマシン
続・SECDマシン
つくっておぼえる!仮想マシン〜直前で実装編〜
つくっておぼえる!仮想マシン〜直前で実装編〜
Lxc cf201207-presen
Lxc cf201207-presen
What is Metasepi?
What is Metasepi?
NetBSDのクロスビルドのしくみとインストール済みLive Imageの作成
NetBSDのクロスビルドのしくみとインストール済みLive Imageの作成
Buffer overflow
Buffer overflow
ゆるふわLinux-HA 〜PostgreSQL編〜
ゆるふわLinux-HA 〜PostgreSQL編〜
nftables: the Next Generation Firewall in Linux
nftables: the Next Generation Firewall in Linux
Sagittariusの紹介
Sagittariusの紹介
Rubyで実はwritev(2) が使われているはなし
Rubyで実はwritev(2) が使われているはなし
Solr 4.0 の主な機能
Solr 4.0 の主な機能
スタート低レイヤー #0
スタート低レイヤー #0
More from t-sin
SECDマシン 実装と動きとその他もろもろについて
SECDマシン 実装と動きとその他もろもろについて
t-sin
Common Lisp製のテキストエディタLemにフレーム多重化機能をつくった
Common Lisp製のテキストエディタLemにフレーム多重化機能をつくった
t-sin
Common Lispっぽいものをつくっています
Common Lispっぽいものをつくっています
t-sin
Sounds Like Common Lisp - ゼロからはじめるサウンドプログラミング
Sounds Like Common Lisp - ゼロからはじめるサウンドプログラミング
t-sin
PythonでLispを実装した (evalつき)
PythonでLispを実装した (evalつき)
t-sin
バッテリー強奪! PythonをCommon Lispから使う
バッテリー強奪! PythonをCommon Lispから使う
t-sin
Common lispでグラフィックアート
Common lispでグラフィックアート
t-sin
One - Common Lispでもワンライナーしたい
One - Common Lispでもワンライナーしたい
t-sin
Inquisitor -Common Lispに文字コード判定を-
Inquisitor -Common Lispに文字コード判定を-
t-sin
More from t-sin
(9)
SECDマシン 実装と動きとその他もろもろについて
SECDマシン 実装と動きとその他もろもろについて
Common Lisp製のテキストエディタLemにフレーム多重化機能をつくった
Common Lisp製のテキストエディタLemにフレーム多重化機能をつくった
Common Lispっぽいものをつくっています
Common Lispっぽいものをつくっています
Sounds Like Common Lisp - ゼロからはじめるサウンドプログラミング
Sounds Like Common Lisp - ゼロからはじめるサウンドプログラミング
PythonでLispを実装した (evalつき)
PythonでLispを実装した (evalつき)
バッテリー強奪! PythonをCommon Lispから使う
バッテリー強奪! PythonをCommon Lispから使う
Common lispでグラフィックアート
Common lispでグラフィックアート
One - Common Lispでもワンライナーしたい
One - Common Lispでもワンライナーしたい
Inquisitor -Common Lispに文字コード判定を-
Inquisitor -Common Lispに文字コード判定を-
謎の言語Forthが謎なので実装した
1.
謎の⾔語Forthが謎なので実装した 2018-10-25, lisp meetup
#69
2.
今⽇のお話 ⾔語を実装したいが、 それを実⾏する仮想機械の設計がわからず、 スタック機械みたいな⾔語Forthがあると知ったが、 Forth謎すぎてファンタジーなので、 とりあえずForth処理系つくってみた。
3.
動機: ⾔語を実装したい1/3 先⽣、⾔語を実装したいです…… 理由 既存の⾔語への理解を深めたい Common Lispもっと理解したい 低レイヤー覗きたい 使いたい かっこいい
4.
動機: ⾔語を実装したい2/3 ⾔語実装の軌跡1/2 nutslisp Lisp-2、レキシカルスコープ、パッケージ、Nim製 「CLっぽいもの」という壮⼤な⽬標の前に撃沈 https://github.com/t-sin/nutslisp lisc ほぼ純Lisp、Pythonのリスト内包表記ワンライナー アホス https://github.com/t-sin/lisc svm ⾔語実装VMという名のCPUエミュレータもどき メモリ操作つらい https://github.com/t-sin/svm
5.
動機: ⾔語を実装したい3/3 ⾔語実装の軌跡2/2 secdm 関数型⾔語のためのVM SECDマシンの実装 フィボナッチ数計算成功、S式パーサ作成で挫折 https://github.com/t-sin/secdm wl
(設計中) C⾔語製、VM型でクロージャのあるLisp-2(予定) VMの設計がまったくわからんぬ https://github.com/t-sin/wl
6.
動機: 仮想機械の設計?1/3 仮想機械の設計、 どうやったらいいか まったくわからん 😭😭😭😭😭😭😭
7.
動機: 仮想機械の設計?2/3 仮想機械(かそうきかい、仮想マシン、バーチャルマシン、 英語: virtual
machine、VM)とは、コンピュータの動作をエ ミュレートするソフトウェアやフレームワークである。ま た、エミュレートされた仮想のコンピュータそのものも仮想 機械という。 ─ 『仮想機械』, Wikipediaより
8.
動機: 仮想機械の設計?3/3 仮想機械の実装を⾒て参考にしよう! SECDマシン →論⽂読んでつくった。低レベルすぎてつらい… Lua →⼩さいけど、最適化ゆえかけっこう複雑… Python →でかい…でかすぎる…
9.
Forthという⾔語があるらしい…? その⾔語はまるで アセンブラみたいに低レベル 表現⼒・抽象度が⾼い しかもスタックマシンみたいな⾔語 らしい これやれば仮想機械設計の感触掴めるかもしれない
10.
謎の⾔語、Forth 1/5 Wikipediaの記事より特徴を要約すると… スタックベース 逆ポーランド記法(後置記法) ⼿続き型 対話型環境 コンパイラモード
11.
謎の⾔語、Forth 2/5 典型的なForth の実装には、LISP
におけるRead–eval–print loop(英語版)(REPL)に対応する、⼊⼒されたワードを即 座に実⾏する対話型のインタプリタモードと(これは、正規 のオペレーティングシステムがないシステム向けのシェルに も適している)、後の実⾏のために⼀連のワードをコンパイ ルするモードのふたつのモードがある。後者にはコロン(:) というワードにより遷移しセミコロン(;)というワードで脱 する。 ─ 『Forth』, Wikipediaより
12.
謎の⾔語、Forth 3/5 Forth は現在Open
Firmware のようなブートローダや宇宙開 発[1]、組込みシステム、ロボット制御などに使われている。 ─ 『Forth』, Wikipediaより
13.
謎の⾔語、Forth 4/5 なぞすぎるプロダクト群… 1991 -
http://www.1-9-9-1.com/ Forthで書かれたHTTPサーバー なぜかコードがすごくちいさい forsh - https://bitbucket.org/cowile/forsh Forthで書かれたシェル もちろん後置記法 fmacs - https://github.com/larsbrinkhoff/fmacs Forthで書かれたEmacs どういうこと??
14.
謎の⾔語、Forth 5/5 なんなのこの⾔語。 Common Lisp感があるけど、謎。 Forthのことぜんぜんわからない…。
15.
Forthが謎なので… 実装してみた
16.
uf:Forthインタプリタ https://github.com/t-sin/uf をつくった 特徴 Common Lisp製 ワード(Forthにおける関数)の呼び出し∕定義 スタック操作ワード 数値計算・数値⽐較のワード 条件分岐 コンパイラなし 対話環境がなんかおかしい
17.
Forthのいろは 1. プログラムはスペース区切り 2. トークンがディクショナリに あったらワード(関数)の本体コードにジャンプして実 ⾏ なかったら定数リテラルなのでスタックに積む これだけ!
18.
プログラム例1 1 + 2
* 10 を計算 // スタック: [] 1 // スタック: [1] 2 // スタック: [2 1] 10 // スタック: [10 2 1] * // スタック: [20 1] + // スタック: [21]
19.
プログラム例2 数値を⾜した結果をASCIIコードと⾒て出⼒ // スタック: [] 40
2 + // スタック: [42] emit // => * // スタック: []
20.
プログラム例3 1/7 フィボナッチ数列を計算、する前に…
21.
プログラム例3 2/7 前提: ufの持つ命令(⼀部) スタック操作ワード swap
(2要素交換), dup (複製), rot (先頭要素と3番⽬を 交換), drop (削除), over (2番⽬の要素を先頭に複製) I/Oワード . (スタックトップを出⼒), .s (スタックをデバッグ出⼒) 数値演算・⽐較ワード + , - , * , / , = , < 論理演算ワード and , or , not
22.
プログラム例3 3/7 フィボナッチ数列を計算 まずはスタック要素を2つ読んで⽐較する述語 <=
を定義する : <= over over < rot swap = or ;
23.
プログラム例3 4/7 <= 使⽤例 (<=
20 21) → t を計算 21 20 // スタック: [20 21] <= // 上の定義の⼀語め (over)にジャンプ // 引数を複製する over // スタック: [21 20 21] over // スタック: [20 21 20 21] // Forthは偽が0、真が0以外 < // スタック: [-1 20 21] (つづく)
24.
プログラム例3 5/7 <= 使⽤例(つづき) //
スタック: [-1 20 21] rot // スタック: [21 20 -1] swap // スタック: [20 21 -1] = // スタック: [0 -1] or // スタック: [-1] // ワードの終わりが来たので<=呼び出し位置にジャンプ ;
25.
プログラム例3 6/7 つぎに、フィボナッチ数を再帰的に計算するワードを定義する : fib dup
0 swap <= if drop 0 else dup 1 = if drop 1 else dup 1 swap - fib swap 2 swap - fib + then then ; 引数としてフィボナッチ数の項数をひとつ受けとる if で⼆回引数を使うので、最初に引数を複製している Forthの再帰はLispのダイナミックスコープにおける名前参照 みたいにふるまう
26.
プログラム例3 7/7 さいごに、引数をスタックに積んで fib
を呼び出す // スタック: [] 10 // スタック: [10] fib // スタック: [55] . // せっかくなので出⼒してみる 55 ok // スタック: []
27.
実装 ここからは実装のしかたのお話
28.
実装: パーサ スペース以外の⽂字で区切って切り出し、リストに溜める ついでに数値はCLの数値に変換しておく (defun parse
(stream) (let (code buf atomp numberp) (flet ((read-atom (ch) ...)) (loop :for ch := (read-char stream nil :eof) :until (eq ch :eof) :do (case ch (#space (terminate-atom)) (#newline (terminate-atom)) (t (read-atom ch))) :finally (progn (terminate-atom) (return (nreverse code))))))) split-sequence を使えばほぼ⼀撃ですねこれ(今きづいた
29.
実装: ワードまわり ワードの構造体と実⾏状態の構造体をつくる (defstruct word
name fn start system-p) (defstruct vm code ip dict stack rstack ifdepth skip-to debug-p) ディクショナリは word のリスト find とか push で探索や追加を⾏う 通常はスタック2本(データ・呼び出し)でよいが、 インタプリタとするにはifのネストを読み⾶ばすために3本⽬ が要る
30.
実装: 解釈器1/2 パーサが⽣成したAST(CLのアトムのリスト)を解釈して実⾏す る if のスキップ時と通常の実⾏時の2つの状態がある 通常の解釈 :
だったら→ワード定義処理(後述) ; だったら→ if だったら→条件評価後、true部を実⾏or true部をスキップ (ネスト数を覚えておく) else だったら→true部実⾏してたので、else部をスキップ (ネスト数を覚えておく) それ以外→ワード呼び出しなので、コールスタックに現在の PC積む、ワード本体にPCをセット
31.
実装: 解釈器2/2 if で実⾏しない部分(
if がネストし得る)を読み⾶ばす if ⽂スキップ if だったら→ネスト数を1加算 then だったら→ネスト数を1減算 もしスキップ開始時のネスト数と今のネスト数が同じな ら →スキップ処理終了 それ以外→読み⾶ばす
32.
実装: ワード定義1/2 ufでは :
によるワードの定義も解釈時に⾏う 基本的には、 1. : がきたら、 2. 名前を読み取り、 3. プログラム開始位置を覚え、 4. ; まで読み⾶ばし、 5. 名前と開始位置から word 構造体をディクショナリに push という流れ : ... ; のネストは不可 これはForth 2012の仕様でも同様 「コンパイルモード時にコンパイルモードに⼊る」の排除か
33.
実装: ワード定義2/2 だいたいこんなコードです(ハミ出る) (defun define-word
(vm) (let ((name (get-atom vm))) (when (null name) (error "invalid word definition : it doesn't have a name. (let ((start-pos (vm-ip vm))) (loop :for atom := (get-atom vm) :until (eq atom 'uf/dict::|;|) :do (when (null atom) (error "invalid word definition '~a': it doesn't (let ((word (make-word :name name :system-p nil :start (let ((w (find name (vm-dict vm) :key #'word-name))) (if (and (not (null w)) (word-system-p w)) (error "cannot overwrite the predefined word: ~s" (push word (vm-dict vm))))))))
34.
実装: 初期ワード定義 . (出⼒)とか
+ とかを実装していく ここはひたすら気合いです ;; I/O (defword (|.|) (format t "~a" (pop (vm-stack vm)))) (defword (|cr|) (terpri)) (defword (|emit|) (format t "~a" (code-char (pop (vm-stack vm))))) (defword (|.s|) (format t "~s" (vm-stack vm))) ;; stack maneuvers (defword (|swap|) (let ((o1 (pop (vm-stack vm))) (o2 (pop (vm-stack vm)))) (push o1 (vm-stack vm)) (push o2 (vm-stack vm))))
35.
たったこれだけです ここからまとめに⼊ります
36.
ufの実装で反省したこと 1. 処理系のモードがないことによる苦労 2. VMの状態を引き回せない問題
37.
反省点1: 処理系のモードがないことによ る苦労 if の解釈のためにめんどくさいことをした if
スキップのフェーズはインタプリタに固有の処理 分岐をコンパイル時でジャンプに変換できれば不要
38.
反省点2: VM状態を引き回せない問題1/2 ufのroswellコマンドによるシェルが変… ~/code/uf$ roswell/ufi.ros uf,
Ursa Major Forth, 0.1.0 Ctrl-D to exit : fn hello . ; fn hellook fn ok 定義したワードがREPLの⾏を跨ぐと消えている
39.
反省点2: VM状態を引き回せない問題2/2 これは実は、REPLにおいてVMのコードを上書きしており、 word に格納された本体開始位置が無効になっている (loop :for
line := (read-line stream nil :eof) :until (eq line :eof) :for code := (with-input-from-string (in line) (parse in)) :do (handler-bind ((condition (lambda (c) (format t "not ok~% ~s~%" ;; ここでコードを上書きしてしまっている! (setf (vm-code vm) code (vm-ip vm) 0) (execute vm)) :do (format t "ok~%")))) 解決策は、 コンパイルモードを実装する(ほしい) code を append する(ハック)
40.
ufのこれから ⽂字列は配列といった、より実⽤的なデータ構造を実装した い Forthの⽂字列例: " hello
world" . パーサでの特別扱いが必要 実⾏モード(実⾏・解釈・コンパイル)を実装したい if の問題やREPLの微妙さを⼀気に解消できそう ついでにバイトコードにしてみたい なにかに埋め込んで使ってみたい お絵描き? 弾幕STGのDSL?
41.
まとめ 簡単なForthインタプリタをCommon Lispで実装した 謎は深まるばかり… インタプリタでも、純Lispと違い低レイヤーを意識させられた スタック型仮想機械の設計、すこし⾒えてきたような… コンパイラに向けて⾛っていきたい なにかに組み込んで使いたい
Download now