yhara.jp

Recent Posts
Edit

Fomentを読む(6)

2016-10-09
Tech

前回はこちら。月一でやろうかなと言っていたけど、先月はちょっと忙しくて休載した。しかしまあ「長期的には成し遂げたいけど、短期的には優先度が高くない課題」に対する手法としては、月に一日だけやるというのはわりと良さそうな感じがしてきた。

前回はsynrules.cppの提供する2つの関数、CompileSyntaxRulesとExpandSyntaxRulesについて、どの補助関数が呼ばれているかを調べたのだった。次は何をしようかなぁ。とりあえずこれらの関数の引数と返り値が知りたいな。

ExpandSyntaxRules

synrules.cppを見る。ExpandSyntaxRulesはExpandTemplateの結果を返す。ExpandTemplateはMakePairかListToVectorの結果を返すので、Schemeレベルの値を返すっぽい。

引数の方はどうだろうか。ぜんぶFObjectだから分かんないんだよな...。綺麗なコードだと言ったけど、Cなのに事実上型がないような感じでつらみが出てきた。

FObject ExpandSyntaxRules(FObject se, FObject sr, FObject expr)

ともあれsrはFAssert(SyntaxRulesP(sr));とあるので、foment.hppにあるSyntaxRulesRecordTypeによると、レコード型SyntaxRulesRecordTypeっぽい。

レコード型について

時間が空いたので再度まとめておくが、RecordTypeはMakeRecordTypeCから作られるもので、

R.SyntaxRulesRecordType = MakeRecordTypeC("syntax-rules",
        sizeof(SyntaxRulesFieldsC) / sizeof(char *), SyntaxRulesFieldsC);

MakeRecordによってFXxxXxxのようなインスタンスを作成できる。

FSyntaxRules * sr = (FSyntaxRules *) MakeRecord(R.SyntaxRulesRecordType);

ややこしいので、このシリーズではレコード型はFSyntaxRulesみたいな名前で統一しようかな。

ExpandSyntaxRulesのシグネチャ

ここまでで分かっているExpandSyntaxRulesのシグネチャは以下。

ExpandSyntaxRules(se, FSyntaxRules sr, expr) -> PairとかVectorとか

exprはSchemeの式なのだろう。seはMatchPatternの第一引数で、MatchReferenceの第二引数である。MatchReferenceはsynpass.cppにあった。seはResolveIdentifierの第一引数。ResolveIdentifierには以下のアサーションがあるので、FSyntacticEnvだと分かった。

    FAssert(SyntacticEnvP(se));

FSyntacticEnv

FSyntacticEnvはたぶん、syntactic closure関係の何かだと思う。syntactic closureについては僕も説明できるほど理解していない(理解してたらfomentの実装とか読んでない)ので、知りたい人はググるか、ポインタとしてはこちらの記事などを。

このシリーズでもいずれ説明することになる、はず。

CompileSyntaxRulesのシグネチャ

CompileSyntaxRulesの方は以下のようなシグネチャだった。

synpass.cppでの使用箇所を見るとseはFSyntacticEnv、objはSchemeの式(expr)っぽい。また返り値はMakeSyntaxRulesなのでFSyntaxRules。ということでこうなる。

CompileSyntaxRulesの使い方

synpass.cppのSPassSpecialSyntaxという関数に使用箇所がある。

ここではquote, lambda, if, set!, let, let*などの組み込みの構文と、syntax-rulesによるユーザ定義構文を処理しているようだ。(syntax-rules xxx)のようなS式だったらそれをFSyntaxRulesにコンパイルするということかな。

    else if (ss == DoSyntax)
    {
        // (do ((<variable> <init> [<step>]) ...) (<test> <expression> ...) <command> ...)

        return(SPassDo(enc, se, expr));
    }
    else if (ss == SyntaxRulesSyntax)
    {
        // (syntax-rules (<literal> ...) <syntax rule> ...)
        // (syntax-rules <ellipse> (<literal> ...) <syntax rule> ...)

        return(CompileSyntaxRules(MakeSyntacticEnv(se), expr));
    }

ExpandSyntaxRulesの使い方

上記の関数SPassSpecialSyntaxは、同じsynrules.cppのSPassExpressionから呼ばれている。ここを見るとExpandSyntaxRulesの方の呼び出しもあった。(foo 1 2 3)みたいな式があって、fooがsytnax-rulesで定義された構文だったら、これをExpandSyntaxRulesで展開するということのようだ。

            val = EnvironmentGet(AsReference(op)->Binding, AsReference(op)->Identifier);
        }

        if (SpecialSyntaxP(val))
            return(SPassSpecialSyntax(enc, se, val, expr));

        if (SyntaxRulesP(val))
            return(SPassExpression(enc, se, ExpandSyntaxRules(se, val, Rest(expr))));

まとめ

今回は前にやった内容を思い出しつつ、CompileSyntaxRulesとExpandSyntaxRulesのシグネチャを調べた。コールグラフとともに再掲しておく。

- CompileSyntaxRules(FSyntacticEnv se, expr) -> FSyntaxRules
  - CopyLiterals
    - LiteralFind
  - CompileRule
    - CompilePatternVariables
      - PatternVariableFind, LiteralFind
    - AssignVariableIndexes
    - CompilePattern
      - PatternVariableFind, LiteralFind
      - CountPatternsAfterRepeat
      - RepeatPatternVariables
        - PatternVariableFind
    - CompileTemplate
      - PatternVariableFind
      - AddVarToTemplateRepeat
        - ListFind

- ExpandSyntaxRules(FSyntacticEnv se, FSyntaxRules sr, expr) -> expr
 - MatchPattern
   - InitRepeatVariables
   - GatherRepeatVariables
 - ExpandTemplate
   - CheckRepeatVariables
   - SetRepeatVariables
   - ExpandTemplateRepeat -> ExpandTemplateを呼ぶことがある(相互再帰)

More posts