Submit Search
Upload
謎の言語Forthが謎なので実装した
•
0 likes
•
1,932 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
SECDマシン 実装と動きとその他もろもろについて
SECDマシン 実装と動きとその他もろもろについて
t-sin
Rpn and forth 超入門
Rpn and forth 超入門
Yoshitaka Seo
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門
Kimikazu Kato
冬のLock free祭り safe
冬のLock free祭り safe
Kumazaki Hiroki
Glibc malloc internal
Glibc malloc internal
Motohiro KOSAKI
たのしい関数型
たのしい関数型
Shinichi Kozake
ラムダ計算入門
ラムダ計算入門
Eita Sugimoto
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps
MITSUNARI Shigeo
Recommended
SECDマシン 実装と動きとその他もろもろについて
SECDマシン 実装と動きとその他もろもろについて
t-sin
Rpn and forth 超入門
Rpn and forth 超入門
Yoshitaka Seo
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門
Kimikazu Kato
冬のLock free祭り safe
冬のLock free祭り safe
Kumazaki Hiroki
Glibc malloc internal
Glibc malloc internal
Motohiro KOSAKI
たのしい関数型
たのしい関数型
Shinichi Kozake
ラムダ計算入門
ラムダ計算入門
Eita Sugimoto
条件分岐とcmovとmaxps
条件分岐とcmovとmaxps
MITSUNARI Shigeo
フラグを愛でる
フラグを愛でる
MITSUNARI Shigeo
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Genya Murakami
色々なダイクストラ高速化
色々なダイクストラ高速化
yosupo
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
yohhoy
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
Hideyuki Tanaka
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
Ryo Suzuki
Wavelet matrix implementation
Wavelet matrix implementation
MITSUNARI Shigeo
Lockfree Queue
Lockfree Queue
Kumazaki Hiroki
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~
Nobuhisa Koizumi
キメるClojure
キメるClojure
Yoshitaka Kawashima
プログラムを高速化する話
プログラムを高速化する話
京大 マイコンクラブ
Lispマシン・シミュレータの紹介
Lispマシン・シミュレータの紹介
たけおか しょうぞう
オブジェクト指向できていますか?
オブジェクト指向できていますか?
Moriharu Ohzu
明日使えないすごいビット演算
明日使えないすごいビット演算
京大 マイコンクラブ
指数時間アルゴリズム入門
指数時間アルゴリズム入門
Yoichi Iwata
WebAssembly向け多倍長演算の実装
WebAssembly向け多倍長演算の実装
MITSUNARI Shigeo
自動定理証明の紹介
自動定理証明の紹介
Masahiro Sakai
様々な全域木問題
様々な全域木問題
tmaehara
katagaitai workshop #7 crypto ナップサック暗号と低密度攻撃
katagaitai workshop #7 crypto ナップサック暗号と低密度攻撃
trmr
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
Takuya Akiba
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
フラグを愛でる
フラグを愛でる
MITSUNARI Shigeo
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
Genya Murakami
色々なダイクストラ高速化
色々なダイクストラ高速化
yosupo
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
yohhoy
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
Hideyuki Tanaka
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
Ryo Suzuki
Wavelet matrix implementation
Wavelet matrix implementation
MITSUNARI Shigeo
Lockfree Queue
Lockfree Queue
Kumazaki Hiroki
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~
Nobuhisa Koizumi
キメるClojure
キメるClojure
Yoshitaka Kawashima
プログラムを高速化する話
プログラムを高速化する話
京大 マイコンクラブ
Lispマシン・シミュレータの紹介
Lispマシン・シミュレータの紹介
たけおか しょうぞう
オブジェクト指向できていますか?
オブジェクト指向できていますか?
Moriharu Ohzu
明日使えないすごいビット演算
明日使えないすごいビット演算
京大 マイコンクラブ
指数時間アルゴリズム入門
指数時間アルゴリズム入門
Yoichi Iwata
WebAssembly向け多倍長演算の実装
WebAssembly向け多倍長演算の実装
MITSUNARI Shigeo
自動定理証明の紹介
自動定理証明の紹介
Masahiro Sakai
様々な全域木問題
様々な全域木問題
tmaehara
katagaitai workshop #7 crypto ナップサック暗号と低密度攻撃
katagaitai workshop #7 crypto ナップサック暗号と低密度攻撃
trmr
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
Takuya Akiba
What's hot
(20)
フラグを愛でる
フラグを愛でる
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
constexpr関数はコンパイル時処理。これはいい。実行時が霞んで見える。cpuの嬌声が聞こえてきそうだ
色々なダイクストラ高速化
色々なダイクストラ高速化
20分くらいでわかった気分になれるC++20コルーチン
20分くらいでわかった気分になれるC++20コルーチン
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
ゲーム開発者のための C++11/C++14
ゲーム開発者のための C++11/C++14
Wavelet matrix implementation
Wavelet matrix implementation
Lockfree Queue
Lockfree Queue
F#入門 ~関数プログラミングとは何か~
F#入門 ~関数プログラミングとは何か~
キメるClojure
キメるClojure
プログラムを高速化する話
プログラムを高速化する話
Lispマシン・シミュレータの紹介
Lispマシン・シミュレータの紹介
オブジェクト指向できていますか?
オブジェクト指向できていますか?
明日使えないすごいビット演算
明日使えないすごいビット演算
指数時間アルゴリズム入門
指数時間アルゴリズム入門
WebAssembly向け多倍長演算の実装
WebAssembly向け多倍長演算の実装
自動定理証明の紹介
自動定理証明の紹介
様々な全域木問題
様々な全域木問題
katagaitai workshop #7 crypto ナップサック暗号と低密度攻撃
katagaitai workshop #7 crypto ナップサック暗号と低密度攻撃
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
プログラミングコンテストでのデータ構造 2 ~平衡二分探索木編~
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
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
(8)
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