2016-07-10
■ [scheme] Fomentを読む(2)
前回からの続き。前回はリビジョンを書くのを忘れたが、現時点のgit masterを手元にダウンロードして読んでいる。
昨日はsyntax-rulesからだいぶ離れてしまったので、またsynrules.cppから見ていこう。
void SetupSyntaxRules()
{
R.SyntaxRulesRecordType = MakeRecordTypeC("syntax-rules",
sizeof(SyntaxRulesFieldsC) / sizeof(char *), SyntaxRulesFieldsC);
R.PatternVariableRecordType = MakeRecordTypeC("pattern-variable",
sizeof(PatternVariableFieldsC) / sizeof(char *), PatternVariableFieldsC);
R.PatternRepeatRecordType = MakeRecordTypeC("pattern-repeat",
sizeof(PatternRepeatFieldsC) / sizeof(char *), PatternRepeatFieldsC);
R.TemplateRepeatRecordType = MakeRecordTypeC("template-repeat",
sizeof(TemplateRepeatFieldsC) / sizeof(char *), TemplateRepeatFieldsC);
R.SyntaxRuleRecordType = MakeRecordTypeC("syntax-rule",
sizeof(SyntaxRuleFieldsC) / sizeof(char *), SyntaxRuleFieldsC);
}
レコード型
ここでは5つのレコード型を定義している。
- SyntaxRuleRecordType
- PatternVariableRecordType
- PatternRepeatRecordType
- TemplateRepeatRecordType
- SyntaxRuleRecordType
型名は分かったが、フィールドの定義はどこにあるのだろう。それぞれSyntaxRulesFieldsCのようなシンボルを渡しているので、これを確認してみよう。
同じファイルを「FieldsC」で検索すると以下が見つかった。
static const char * SyntaxRulesFieldsC[] = {"literals", "rules", "syntactic-env"};
static const char * PatternVariableFieldsC[] = {"repeat-depth", "index", "variable"};
static const char * PatternRepeatFieldsC[] = {"leave-count", "ellipsis", "variables", "pattern",
static const char * TemplateRepeatFieldsC[] = {"ellipsis", "repeat-count", "variables", "template",
"rest"};
static const char * SyntaxRuleFieldsC[] = {"num-variables", "variables", "pattern", "template"};
整理しておこう。
- SyntaxRules = (literals, rules, syntactic-env)
- PatternVariable = (repeat-depth, index, variable)
- PatternRepeat = (leave-count, ellipsis, variables, pattern)
- TemplateRepeat = (ellipsis, repeat-count, variables, template, rest)
- SyntaxRule = (num-variables, variables, pattern, template)
メンバ名から察するに、以下の様な階層構造だと思われる。
- SyntaxRules = (literals, rules, syntactic-env)
- SyntaxRule = (num-variables, variables, pattern, template)
- PatternVariable = (repeat-depth, index, variable)
- PatternRepeat = (leave-count, ellipsis, variables, pattern)
- TemplateRepeat = (ellipsis, repeat-count, variables, template, rest)
- SyntaxRule = (num-variables, variables, pattern, template)
struct
一方でsynrules.cppでは以下のようなstructも定義されている。これとレコード型はどのような関係なのだろうか?
typedef struct
{
FRecord Record;
FObject Literals;
FObject Rules;
FObject SyntacticEnv;
} FSyntaxRules;
synrules.cppで定義されているstructは以下。全部のレコード型にstructがあるわけではないようだ。
- FSyntaxRules
- FSyntaxRule
FSyntaxRulesの定義の下に、MakeSyntaxRulesという関数がある。これによると、MakeRecordで生成したレコードを、struct FSyntaxRulesで受けられるらしい。
FSyntaxRules * sr = (FSyntaxRules *) MakeRecord(R.SyntaxRulesRecordType);
sr->Literals = lits;
sr->Rules = rules;
sr->SyntacticEnv = se;
synrules.cppをMakeRecordで検索すると、FPatternVariable, FPatternRepeat, FTemplateRepeatという識別子も存在することがわかる。これらの定義はsynrules.cppには無いが、compile.hppにあることが分かった。例えばFTemplateRepeatの定義は以下である。
typedef struct
{
FRecord Record;
FObject Ellipsis;
FObject RepeatCount;
FObject Variables;
FObject Template;
FObject Rest;
} FTemplateRepeat;
一方でTemplateRepeatFieldsCの定義は以下だったので、見比べると、最初のFRecord Record
以外はレコード型のフィールド名と対応していることがわかる。
static const char * TemplateRepeatFieldsC[] = {"ellipsis", "repeat-count", "variables", "template",
ということで最初の疑問の答えだが、レコード型の値をMakeRecordで作成すると対応するstructの値が得られる、ということで良さそうだ。