うちのアパートがまさにこのタイプなんだけど、このタイプのトイレットペーパーホルダーには思わぬ罠があって、トイレットペーパーを適当に買うと、幅が足らなくて微妙に引っかからないことがあるのだ。結果として、紙を引き出そうとするたびにトイレットペーパーが勢い良く飛び出してくるというユーザ・エクスペリエンスを体験する羽目になる。

前回からの続き。前回はsyntax-rulesを構成していそうな関数をリストアップしたのだった。

関数一覧

一覧を再掲する。ただし引数がFObjectであるものは型名を省略した。

static FObject LiteralFind(se, list, obj) static FObject CopyLiterals(se, obj, ellip) static FObject PatternVariableFind(se, list, var) static FObject CompilePatternVariables(se, form, lits, pat, ellip, pvars, int_t rd) static void AssignVariableIndexes(pvars, int_t idx) static int_t CountPatternsAfterRepeat(pat) static FObject RepeatPatternVariables(se, pvars, pat, rvars) static FObject CompilePattern(se, lits, pvars, ellip, pat) static int_t ListFind(list, obj) static int_t AddVarToTemplateRepeat(var, trs) static FObject CompileTemplate(se, form, pvars, ellip, tpl, trs, int_t qea) static FObject CompileRule(se, form, lits, rule, ellip) FObject CompileSyntaxRules(se, obj) static void InitRepeatVariables(vars, vals[], rvals[]) static void GatherRepeatVariables(vars, vals[], rvals[]) static int_t MatchPattern(se, cpat, vals[], expr) static int_t CheckRepeatVariables(vars, vals[], expr) static void SetRepeatVariables(vars, vals[], rvals[]) static FObject ExpandTemplateRepeat(tse, use, ctpl, int_t nv, vals[], int_t rc, ret, expr) static FObject ExpandTemplate(tse, use, ctpl, int_t nv, vals[], expr) FObject ExpandSyntaxRules(se, sr, expr)

よく見るとstaticな関数とそうでないものが存在する。なんだっけ、staticを付けると関数のスコープがこのファイル内だけになるんだっけか。

ExpandSyntaxRulesの他にはCompileSyntaxRulesが、ファイル外にも公開されているようだ。ExpandとCompileはどう違うのだろうか。引数も返り値もFObjectだらけなので、実際に期待されている型がわかりにくいな...。

CompileSyntaxRules, ExpandSyntaxRules

CompileSyntaxRulesは最後の行がこれなので、FSyntaxRulesを返すことが分かる。

return(MakeSyntaxRules(lits, ReverseListModify(nr), se));

ExpandSyntaxRulesの最後の行はこれ。あれ、値を返さないのか？

return(NoValueObject);

いや、途中にもreturnがあった。

return(ExpandTemplate(MakeSyntacticEnv(AsSyntaxRules(sr)->SyntacticEnv), se, ...略

ExpandTemplateの返り値を見てみる。

static FObject ExpandTemplate(FObject tse, FObject use, FObject ctpl, int_t nv, FObject vals[], FObject expr) { if (PairP(ctpl)) return(MakePair(ExpandTemplate(tse, use, First(ctpl), nv, vals, expr), ExpandTemplate(tse, use, Rest(ctpl), nv, vals, expr))); if (VectorP(ctpl)) return(ListToVector(ExpandTemplate(tse, use, AsVector(ctpl)->Vector[0], nv, vals, expr))); ...略

最初のreturnを見るとPairを返しているようだが、次のreturnはVectorを返すはず。ああそうか、引数によって違うものが返るのか。Cだけど、Schemeのコードに近いな。

NoValueObject

さっき出てきたNoValueObject、どういうものなのか気になるので調べてみる。foment.hppに定義があった。

#define EndOfFileObject MakeImmediate(3, MiscellaneousTag) #define EndOfFileObjectP(obj) ((obj) == EndOfFileObject) #define NoValueObject MakeImmediate(4, MiscellaneousTag) #define NoValueObjectP(obj) ((obj) == NoValueObject) #define WantValuesObject MakeImmediate(5, MiscellaneousTag) #define WantValuesObjectP(obj) ((obj) == WantValuesObject)