前回からの続き。前回はリビジョンを書くのを忘れたが、現時点の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)



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の値が得られる、ということで良さそうだ。