Code Monkey home page Code Monkey logo

rust-elisp's People

Contributors

dependabot[bot] avatar hidekuno avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

Forkers

scaevola

rust-elisp's Issues

gcm関数作成でバグ

関数実行時のバグなので直す

<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>

クロージャのバグ

正解は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> 

rust 1.34対応(コンパイルエラー)

コンパイルエラーが発生するので対応する

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`
(略)

パフォーマンス改善その2

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

原因と対策を講じる

do_core_logic関数の引数を見直す

プログラム文字列を渡しているが、このコーリングシーケンスだとmoveされてしまう。
(Stringはプリミティブでないため)
使い勝手が悪いので、参照を渡すように修正する
(pubなので)

継続渡しスタイル (Continuation Passing Style : CPS)が動かない

継続を調査するため下記関数を実装

<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

が正解

reduceをscheme標準仕様に合わせる

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>

syntax エラーメッセージの修正

エラーメッセージを適切な文言に修正する
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)

図形言語にてメモリリークが発生する

実測結果

  • ベクトル図形
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> 

rust 1.35対応(コンパイル warning)

$ 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> 

load-file関数の安全性を高める

権限のないファイルは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.

macでUnitTestが失敗する

テスト結果

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> 

cond文 else句の評価でのバグ

サンプルプログラム(順列)

(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>

expt関数の見直し

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> 

なので見直し

文字列のtokenize, parseを強化する

単一の式を評価する場合は問題ない。

<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> 

Rust Gtkに関する処理について修正

環境情報(本体)の構造を変更したので、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

日本語文字列(UTF8)文字列対応

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.

replの改善

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> 

デバッグ機能の実装

下記機能の検討

  • 関数実行のトレース
  • 環境のdump
  • 環境のリファレンスカウント(drop時)

シェルピンスキーの三角形で不具合

(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)

エラーメッセージの改善

例)

  • undefineエラーの場合、変数を表示する
  • 型エラーの場合、正しい型を表示する
  • パラメータ数エラーの場合、正しい数を表示する

並列処理に対応する

std::rc::Rcとstd::cell::RefCellはマルチスレッドに対応していないので、データ構造の見直しが
必要

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.