hidekuno / rust-elisp Goto Github PK
View Code? Open in Web Editor NEWMini lisp a like scheme in Rust
Mini lisp a like scheme in Rust
関数実行時のバグなので直す
<rust.elisp> (define (gcm n m)(if (= 0 (modulo n m)) m (gcm m (modulo n m))))
gcm
<rust.elisp> (gcm 36 27)
Calculate A Division By Zero (src/lisp.rs:629)
<rust.elisp>
現状、println!マクロで出力しているだけなので
スクリプトファイルを実行する仕組みを実装
https://github.com/hidekuno/rust-elisp/issues/new
正解は40
<rust.elisp> (define (testf x) (lambda () (* x 10)))
testf
<rust.elisp> (define (foo x) (testf (* 2 x)))
foo
<rust.elisp> ((foo 2))
20
<rust.elisp>
以下関数を実装
Macで動かすため
quotient関数を仕様に準じた振る舞いにする
コンパイルエラーが発生するので対応する
NPC106:rust-elisp kunohi$ cargo run --bin lisp
Compiling elisp v0.1.0 (/Users/kunohi/git/rust-elisp)
error[E0308]: mismatched types
--> src/dyn_lisp.rs:934:17
|
934 | DataType::RsSymbolDesc => {}
| ^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::any::TypeId`, found enum `dyn_lisp::DataType`
|
= note: expected type `std::any::TypeId`
found type `dyn_lisp::DataType`
(略)
Function, Let式がcloneされている場合、値もコピーされているためパフォーマンスが劣化する。
スマートポインタを利用して性能向上を測る。
"((square-limit wave 4) frame)"が実行完了した時点でのメモリ使用量
をGo言語版と比較した。
kunohi 2099 4.3 0.2 894036 18460 pts/4 Sl+ 08:05 0:05 ./lisp_draw_main
kunohi 2412 5.2 0.8 462408 70544 pts/4 Rl+ 08:09 0:08 ./target/release/glisp
また、どの程度増加するか測定した。
kunohi 2834 0.1 0.0 17896 1660 pts/4 S+ 08:16 0:00 ./target/release/lisp
kunohi 2834 12.1 0.5 58912 42768 pts/4 S+ 08:16 0:02 ./target/release/lisp
原因と対策を講じる
プログラム文字列を渡しているが、このコーリングシーケンスだとmoveされてしまう。
(Stringはプリミティブでないため)
使い勝手が悪いので、参照を渡すように修正する
(pubなので)
go-schemeも対応する予定
継続を調査するため下記関数を実装
<rust.elisp> (define (fact/cps n cont)
(if (= n 0)
(cont 1)
(fact/cps (- n 1) (lambda (a) (cont (* n a))))))
fact/cps
結果、暴走する
(fact/cps 1 (lambda (a) (* 2 a)))
thread 'main' has overflowed its stack
fatal runtime error: stack overflow
中止 (コアダンプ)
/演算子の結果が
=> (/ 5 3)
=> 1
になるが、
=> (/ 5 3)
=> 5/3
が正解
いちいち、マウスでクリックするのが面倒なので。
gosh> (reduce (lambda (a b) (+ a b)) 0 (list 1))
1
gosh> (reduce (lambda (a b) (+ a b)) 0 (list))
0
gosh> (reduce (lambda (a b) (+ a b)) "a" (list))
"a"
gosh> (reduce (lambda (a b) (+ a b)) 10 (list 1 2 3 4 5))
15
gosh> (reduce (lambda (a b) (+ a b)) "a" (list 1 2 3 4 5))
15
gosh> (reduce (lambda (a b) (+ a b)) (+ 10 10) (list))
20
gosh>
エラーメッセージを適切な文言に修正する
gosh
gosh> 1)
1
gosh> *** READ-ERROR: Read error at "(standard input)":line 2: extra close parenthesis `)'
Stack Trace:
_______________________________________
0 (read)
at "/usr/local/share/gauche-0.9/0.9.5/lib/gauche/interactive.scm":251
gosh> (quit)
rust.elisp
<rust.elisp> 1)
1
Unexpected ')' while reading (src/lisp.rs:1336)
newline, begin関数追加
(and (= a b)(= c d))
(or (= a b)(= c d))
(not (= a b))
実測結果
kunohi 9543 0.4 0.2 294640 17632 pts/4 S+ 09:03 0:00 glisp/target/release/glisp
kunohi 9543 13.6 0.9 351064 74116 pts/4 S+ 09:03 0:12 glisp/target/release/glisp
kunohi 9543 16.7 0.9 352292 75436 pts/4 S+ 09:03 0:25 glisp/target/release/glisp
kunohi 9543 18.2 0.9 354212 77232 pts/4 S+ 09:03 0:41 glisp/target/release/glisp
kunohi 9041 0.2 0.2 294688 17640 pts/4 S+ 08:54 0:00 glisp/target/release/glisp
kunohi 9041 3.0 1.6 410112 133148 pts/4 S+ 08:54 0:04 glisp/target/release/glisp
kunohi 9041 5.2 2.6 484416 207624 pts/4 S+ 08:54 0:09 glisp/target/release/glisp
kunohi 9041 7.8 3.5 557796 280996 pts/4 S+ 08:54 0:15 glisp/target/release/glisp
kunohi 9041 6.1 4.4 632104 355164 pts/4 S+ 08:54 0:29 glisp/target/release/glisp
下記にて内容を示す
<rust.elisp> (define (counter step) (let ((c 0)) (lambda () (set! c (+ c step)) c)))
counter
<rust.elisp> (define a (counter 10))
a
<rust.elisp> (a)
Undefine variable (src/lisp.rs:1461)
<rust.elisp>
callback(event処理)が完了するまで、画面表示がされないので。
go版と同等の性能を目標とする
下記の文字に対応
#¥tab
#¥space
#¥newline
#¥return
$ rustc --version
rustc 1.35.0
warning: cannot borrow `b` as mutable because it is also borrowed as immutable
--> src/lisp.rs:604:13
|
603 | if let Some(r) = b.get("/") {
| - immutable borrow occurs here
604 | b.insert("quotient", *r);
| ^ -- immutable borrow later used here
| |
| mutable borrow occurs here
|
= note: #[warn(mutable_borrow_reservation_conflict)] on by default
= warning: this borrowing pattern was not meant to be accepted, and may become a hard error in the future
= note: for more information, see issue #59159 <https://github.com/rust-lang/rust/issues/59159>
プログラム内容
(define stream-car (lambda (l)(car l)))
(define stream-cdr (lambda (l)(force (cdr l))))
(define make-generator (lambda (generator inits)(cons (car inits)(delay (make-generator generator (generator inits))))))
(define inf-list (lambda (generator inits limit)(let loop ((l (make-generator generator inits))(c limit)) (if (>= 0 c) (list)(cons (stream-car l)(loop (stream-cdr l)(- c 1)))))))
実行結果
<rust.elisp> (inf-list (lambda (n) (list (+ 1 (car n)))) (list 0) 10)
(0 1 2 3 4 5 6 7 8 9)
<rust.elisp> (inf-list (lambda (n) (list (+ 1 (car n)))) (list 0) 10)
Not Number (src/lisp.rs:1318)
<rust.elisp> (inf-list (lambda (n) (list (+ 1 (car n)))) (list 0) 10)
Not Number (src/lisp.rs:1318)
<rust.elisp> (inf-list (lambda (n) (list (+ 1 (car n)))) (list 0) 10)
Not Number (src/lisp.rs:1318)
<rust.elisp> (inf-list (lambda (n) (list (+ 1 (car n)))) (list 0) 10)
(0 1 2 3 4 5 6 7 8 9)
<rust.elisp>
実数と整数の演算・比較を実装する
権限のないファイルはNot Foundになる
<rust.elisp> (load-file "/etc/sudoers~orig")
Not Found Program File (src/lisp.rs:1245)
バイナリファイルはコケる
<rust.elisp> (load-file "/Users/kunohi/tmp/a.out")
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Custom { kind: InvalidData, error: StringError("stream did not contain valid UTF-8") }', src/libcore/result.rs:997:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
ディレクトリもコケる
NPC106:elisp kunohi$ cargo run --bin lisp
Finished dev [unoptimized + debuginfo] target(s) in 0.13s
Running `target/debug/lisp`
<rust.elisp> (load-file "/Users/kunohi/tmp")
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 21, kind: Other, message: "Is a directory" }', src/libcore/result.rs:997:5
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
テスト結果
failures:
---- tests::tan stdout ----
thread 'tests::tan' panicked at 'assertion failed: do_lisp("(tan (/(* 45.025 (* 4 (atan 1))) 180))") ==
"1.0008730456194168".to_string()', src/lib.rs:520:9
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
プログラム実行の結果
<rust.elisp> (tan (/(* 45.025 (* 4 (atan 1))) 180))
1.0008730456194166
<rust.elisp>
サンプルプログラム(順列)
(define (perm xlist n l)
(if (>= 0 n) (begin (display l)(newline))
(let loop ((x xlist))
(cond ((null? x) (list))
(else
(perm (delete (car x) xlist)(- n 1)(cons (car x) l))
(loop (cdr x)))))))
(define delete (lambda (x l) (filter (lambda (n) (not (= x n))) l)))
実行結果が
<rust.elisp> (perm (list 1 2 3) 2 (list))
(2 1)
nil
<rust.elisp>
最低これを実装
gaucheではこーなる
gosh> (expt 3 -2)
1/9
gosh> (expt 2 0.5)
1.4142135623730951
gosh> (expt 0.5 0.5)
0.7071067811865476
gosh>
rust-elipsでは
<rust.elisp> (expt 3 -2)
0.1111111111111111
<rust.elisp> (expt 2 0.5)
Not Integer (src/lisp.rs:721)
<rust.elisp>
なので見直し
単一の式を評価する場合は問題ない。
<rust.elisp> "A
Unexpected EOF while reading (src/lisp.rs:1477)
<rust.elisp> A"
Unexpected EOF while reading (src/lisp.rs:1477)
<rust.elisp> "
Unexpected EOF while reading (src/lisp.rs:1477)
<rust.elisp>
複数の場合、エラーが無視される
<rust.elisp> (+ 1 2)"A
3
<rust.elisp>
環境情報(本体)の構造を変更したので、glispも変更する。
Rust-gtkのイベント処理は、Fn(クロージャ)で実装されているため、注意が必要である。
(mutable変数が使えない)
https://users.rust-lang.org/t/rs-gtk-vs-mutable-data/5417
The majority of signal handlers can be called recursively thus they need to be Fn.
You can push this static check to run-time by wrapping the value in a RefCell and dealing with possible recursion yourself
goでは評価される
PC106:src kunohi$ go run lisp_main.go
scheme.go> "山田太郎"
"山田太郎"
scheme.go> (quit)
がrustではシステムエラーとなる
NPC106:elisp kunohi$ cargo run --bin lisp
Compiling elisp v0.1.0 (/Users/kunohi/git/rust-elisp/elisp)
Finished dev [unoptimized + debuginfo] target(s) in 5.56s
Running `target/debug/lisp`
<rust.elisp> "山田太郎"
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:345:21
note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
let loopと比較して極端に遅いので。
Gtkがインストールされていない環境で、本体のビルドテストが出来るようにするため
下記関数を実装する
let式の追加
1行で複数の式を評価するように改修する
Gaucheでの実行結果
gosh> (list 30) ho + 2
(30)
gosh> *** ERROR: unbound variable: ho
Stack Trace:
_______________________________________
0 ho
[unknown location]
1 (eval expr env)
at "/usr/local/Cellar/gauche/0.9.7/share/gauche-0.97/0.9.7/lib/gauche/interactive.scm":269
gosh> #<subr (+ :rest args)>
gosh> 2
gosh>
glispではこーなる
<rust.elisp> (list 30) ho + 2
(30)
<rust.elisp>
下記機能の検討
(define (sierpinski x0 y0 x1 y1 x2 y2 c)
(if (> c 1) (let ((xx0 (/ (+ x0 x1) 2))
(yy0 (/ (+ y0 y1) 2))
(xx1 (/ (+ x1 x2) 2))
(yy1 (/ (+ y1 y2) 2))
(xx2 (/ (+ x2 x0) 2))
(yy2 (/ (+ y2 y0) 2)))
(sierpinski x0 y0 xx0 yy0 xx2 yy2 (- c 1))
(sierpinski x1 y1 xx0 yy0 xx1 yy1 (- c 1))
(sierpinski x2 y2 xx2 yy2 xx1 yy1 (- c 1)))
(let ((hoge 0))
(draw-line x0 y0 x1 y1)
(draw-line x1 y1 x2 y2)
(draw-line x2 y2 x0 y0))))
(sierpinski 319.0 40.0 30.0 430.0 609.0 430.0 2)
例)
SICP図形言語を動かす
apply関数を追加
調査・学習した上で実装
std::rc::Rcとstd::cell::RefCellはマルチスレッドに対応していないので、データ構造の見直しが
必要
下記関数追加
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.