Upgrade to Pro — share decks privately, control downloads, hide ads and more …

scheme-silver-paren.pdf

Niyarin
September 26, 2019

 scheme-silver-paren.pdf

Niyarin

September 26, 2019
Tweet

More Decks by Niyarin

Other Decks in Programming

Transcript

  1. 実装中のSchemeパッケージマネージャと
    featuresと
    マクロ
    Niyarin

    View Slide

  2. はなすこと
    ○前提
    ・Schemeの仕様
    ・featuresとcond-expand
    ○ Package manager “Silver paren”
    ○ R7RSでマクロを書くには
    ・CPSマクロ

    View Slide

  3. Schemeの仕様1 R7RS
    ・Schemeの現在主流の仕様
    small(コアの部分) :2013-
    large(たくさんの機能追加): Red(2016) , Tangerine(2019) …
    ・ライブラリとして小分けされている
    Samll
    (scheme base) (scheme file) (scheme load) (scheme repl) …
    Red
    (scheme list) (scheme sort) (scheme hash-table) …
    ・基本の(scheme base)ライブラリ以外は提供の選択は自由
    → R7RS large以降の処理系ごとの差はさらに広がるかも

    View Slide

  4. Schemeの仕様2 SRFI
    ・Schemeのライブラリ、言語拡張の仕様(非公式) 。
    各機能ごとに番号がつけられている
    例:SRFI1 : list ライブラリ
      SRFI62: S式コメント
    SRFI106:socketライブラリ
    いくつかはRnRSにマージされている
    例:SRFI1 listライブラリ → R7RS large (scheme list)
    SRFI62 S式コメント → R7RS small
    処理系作者が好きなものを選んでいれる

    View Slide

  5. Schemeのfeatures
    処理系の機能をシンボルのリストで持っている
    > (features)
    (srfi-111 srfi-106 srfi-95 srfi-60 srfi-43 srfi-26 srfi-17 srfi-8 srfi-1 srfi-0 r7rs little-endian lp64 x86-64
    gnu-linux unix posix ieee-float picrin)
    ・処理系の名前、バージョン
     picrin , gauche , gauche-0.9.8
    ・OS環境
    windows gnu-linux linux …
    ・文字コード
    full-unicode
    ・ライブラリ
    r7rs , srfi-111 , ffi , crypto
    特に規定はないが、概ね↓のようなものが提供される

    View Slide

  6. Schemeのcond-expand
    featuresごとに場合分けする
    (cond-expand
    (gauche
    Gaucheに依存したなにか)
    (sagittarius
    Sagittariusに依存したなにか)
    (unix
    unix環境に依存したなにか )
    (else
    (error “Sorry”)))

    View Slide

  7. Schemeのcond-expand2
    test部にはもう少し複雑なことが書ける (and or not library)
    (cond-expand
    ((or unix gnu-linux bsd)
    Unix系に依存したなにか )
    ((library (srfi 1))
    SRFI1に依存したなにか)
    ((library (scheme list))
    Scheme listに依存したなにか))

    View Slide

  8. パッケージマネージャ ”Silver Paren”
    ・現在実装中(https://github.com/niyarin/silver-paren)
    ・特定の処理系に依存しない
    → R7RSに準拠した処理系でならば動作する
    ・パッケージの依存+featuresで管理する

    View Slide

  9. Silver Parenでのfeaturesの役割
    ・特定の環境用のパッケージが使えるかの確認
    OS(windows,unix )や 日本語が使えるか(full-unicode)
    ・オプション用
    featuresで切り替えることで、依存関係を小さくする

    ・アプリケーションでGUIをサポートするか

    View Slide

  10. Silver Parenでの外部表現
    ○パッケージ名の構造
    (package-xxx (features gui full-unicode) (version 1.0))
    ○コマンドライン上での表現
    ・二重引用符で囲ったリスト VS 他の表現
    sip gosh install package-xxx :feature gui :feature full-unicode :version 1.0

    View Slide

  11. 実装する上で不足している”標準”Scheme機能1
    ・ディレクトリ周りの仕様が存在しない
    処理系固有のものは当然ある
    Gaucheの(file util)やSagitarriusの(util file)など
    → 特定の処理系に依存しないということに反する
    R7RS largeに期待する
    Green Docket(非ポータブルなライブラリ群)
    system command か ディレクトリライブラリのどちらかは入るはず
    だいぶ先になりそう
    Red(2016) → Tangerine(2019)→Orange(2022?)→Amber(2025?)→ Yellow(2028?)
    → Green(2031?)

    View Slide

  12. 実装する上で不足している”標準”Scheme機能2
    ・Github上のライブラリをダウンロードしたい
    外部コマンドを叩く手段がポータブルに用意されていない
    → 同じく、Green Docket system command 期待

    View Slide

  13. Scheme内で解決することを諦めた
    Shell Scriptの中で呼び出して、コマンドを受けとる
    #!/bin/sh
    function do_command(){
    if [ $cmd = "create-dir" ]; then
    target_dir=`eval "echo $opt"`
    mkdir $target_dir
    elif [ $cmd = "restart" ]; then
    restart
    fi
    }
    function read_loop(){
    for output in `$TARGET_SCHEME $SILVER_PAREN_PATH/sip-main.scm $OPT $OUTSOURCING_OPT`
    do
    if echo $output|grep "^Silver-paren-out-command:" >/dev/null ; then
    expression=`echo $output|sed "s/^Silver-paren-out-command://g"`;
    do_command $expression
    else
    echo $output
    fi
    done
    }
    read_loop

    View Slide

  14. R7RSマクロ1 Schemeのマクロ
    R7RSのマクロ syntax-rules
    (define-syntax my-let
    (syntax-rules ()
    ((_ ((name value) ... ) body ... )
    ((lambda (name ... ) body ... ) value ... ))))
    ・高水準マクロ(lisp評価を使わない、別言語 )
    R6RS(一つ前の仕様) 、 処理系依存のマクロ
    syntax-case , implicit-renaming , explicit-renaming , syntactic-lambda など
    (define-syntax my-let
    (ir-macro-transformer
    (lambda (form rename compare)
    (let ((bindings (cadr form))
    (bodies (cddr form)))
    `((lambda ,(map car bindings) ,@bodies) ,@(map cadr bindings))))))

    View Slide

  15. R7RSマクロ2 syntax-rulesで扱いにくいマクロ
    (ore-quote (1 (1 2 3 4 5) (6 7 8 9)))
    ; → (quote (1 (5 4 3 2 1) (6 7 8 9)))
    (ore-quote (2 (1 2 3 4 5) (6 7 8 9)))
    ; → (quote (1 (1 2 3 4 5) (9 8 7 6)))
    ※quasi-quoteに展開すれば楽だけど。
    このようなマクロ ore-quoteを考える
    引数のCAR部が1なら次の要素をreverseする
    2なら次の次の要素をreverseする

    View Slide

  16. R7RSマクロ3 reverse
    (define-syntax ore-reverse
    (syntax-rules ()
    ((_ "INTERNAL" (robj ...) ())
    (robj ...))
    ((_ "INTERNAL" (robj ...) (obj1 obj2 ...))
    (ore-reverse "INTERNAL" (obj1 robj ...) (obj2 ...)))
    ((_ (obj ...))
    (ore-reverse "INTERNAL" () (obj ...))))))
    展開
    (ore-reverse (1 2 3))
    → (ore-reverse “INTERNAL” () (1 2 3))
    → (ore-reverse “INTERNAL” (1) (2 3))
    → (ore-reverse “INTERNAL” (2 1) (3))
    → (ore-reverse “INTERNAL” (3 2 1) ())
    → (3 2 1)

    View Slide

  17. R7RSマクロ4 ore-quote(失敗)
    (define-syntax ore-quote
    (syntax-rules ()
    ((_ (1 ls1 ls2))
    (quote (1 (ore-reverse ls1) ls2)))
    ((_ (2 ls1 ls2))
    (quote (2 ls1 (ore-reverse ls2))))))
    展開
    (ore-quote (1 (1 2 3) (4 5 6)))
    → (quote (1 (ore-reverse 1 2 3) (4 5 6)))
    quoteの中はリテラルであってlisp式でないのでこれ以上展開されない

    View Slide

  18. R7RSマクロ5 CPSマクロを使う
    マクロを展開を内側からできればうまくいく
    → CPSマクロ
    次にすることを明示的に渡すマクロ記述スタイル
    (define-syntax cps-macro-example
    (syntax-rules ()
    ((_ 次に展開したいマクロ 引数1 引数2 …)
    (次に展開したいマクロ 展開結果))))
    例えば、今回のケースだと、reverseした後quoteで囲いたい
    → reverse-CPSマクロは
    次に展開したいマクロである”quoteで囲うマクロ”を受け取る

    View Slide

  19. R7RSマクロ5 CPSマクロの動作
    (%reverse
    (syntax-lambda (it) it)
    (1 2 3 list))
    →(list 3 2 1)
    次になにもすることがない(一番外側)の場合
    (%reverse
    (syntax-lambda (it)
    (quote (1 it (4 5 6)))
    (1 2 3))
    →(quote (1 (3 2 1) (4 5 6)))
    quoteで囲う例

    View Slide

  20. R7RSマクロ6 syntax-lambdaとは
    syntax-lambdaにどうやって結果をいれているのか
    →syntax-lambdaはマクロの機構ではなく勝手につくっただけ
    → syntax-lambdaをマクロに変換して適用できるようにする
    (syntax-rules ()
    ((_ (syntax-lambda (c-arg) c-body) 引数 1 引数2 …)
    (let-syntax ((cont-syntax ;↓syntax-lambdaからマクロに変換
    (syntax-rules ()
    ((_ c-arg) c-body))))
    (cont-syntax ;変換されたsyntax-lambdaに結果を適用
    (結果 …) )))

    View Slide

  21. R7RSマクロ7 %ore-quoteはどうなったのか
    (define-syntax %ore-quote
    (syntax-rules (syntax-lambda)
    ((_ (syntax-lambda (c-arg) c-body) (1 ls1 ls2))
    (let-syntax ((cont-syntax
    (syntax-rules ()
    ((_ c-arg) c-body))))
    (cont-syntax
    (%ore-reverse
    (syntax-lambda (it)
    (quote (1 it ls2)))
    ls1))))
    ((_ (syntax-lambda (c-arg) c-body)(2 ls1 ls2))
    (let-syntax ((cont-syntax
    (syntax-rules ()
    ((_ c-arg) c-body))))
    (cont-syntax
    (%ore-reverse
    (syntax-lambda (it)
    (quote (2 ls1 it)))
    ls2))))))

    View Slide

  22. R7RSマクロ7 全体
    https://gist.github.com/niyarin/87752d24508f63cf8a6eb33a2f43d9ae

    View Slide

  23. 話したこと
    ・Schemeの仕様について話した
    ・パッケージマネージャSilver Parenについて
    ・CPSマクロについて
    まとめ
    年内にはsilver-parenを動くようにしたい

    View Slide