Skip to content

Commit fb0ce78

Browse files
committed
implement guard-or
1 parent 32c0d43 commit fb0ce78

File tree

8 files changed

+232
-65
lines changed

8 files changed

+232
-65
lines changed

src/compile/Optimizer.java

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,21 +71,21 @@ public static void setLevel(int level) {
7171
*
7272
* @param rule ルールオブジェクト
7373
*/
74-
public static void optimizeRule(Rule rule) {
74+
public static void optimizeRule(Rule rule, boolean isOrRule) {
7575
// TODO 最適化器を統合する
7676
Compactor.compactRule(rule);
7777
// TODO 本質的にインライン展開が必要ないものは、展開しなくてもできるようにする
7878
if (fInlining || fGuardMove || fGrouping || fReuseMem || fLoop || rule.isTypeDef) {
7979
// head と guard をくっつける
80-
inlineExpandTailJump(rule.memMatch);
80+
inlineExpandTailJump(rule.memMatch, isOrRule);
8181
rule.guardLabel = null;
8282
rule.guard = null;
8383
}
8484
if (rule.isTypeDef) {
8585
rule.memMatch.remove(rule.memMatch.size() - 1);
8686
}
8787
optimize(rule.memMatch, rule.body);
88-
if (fGuardMove) {
88+
if (fGuardMove && !isOrRule) {
8989
guardMove(rule.memMatch);
9090
allocMove(rule.memMatch);
9191
}
@@ -98,7 +98,8 @@ public static void optimizeRule(Rule rule) {
9898
if (fSystemRulesetsInlining) inlineExpandSystemRuleSets(rule.body);
9999
if (fInlining) {
100100
// head(+guard) と body をくっつける
101-
inlineExpandTailJump(rule.memMatch);
101+
// guard or に対応するため、head と guard の切れ目に印をつけるように変更
102+
inlineExpandTailJump(rule.memMatch, false);
102103

103104
rule.bodyLabel = null;
104105
rule.body = null;
@@ -136,20 +137,20 @@ public static void optimize(List<Instruction> head, List<Instruction> body) {
136137
* [ spec[X,Y]; C;jump[L,A1..Am] ] where L:[spec[m,m+n];D]
137138
* ==> [ spec[X,Y+n];C; D{ 1..m->A1..Am, m+1..m+n->Y+1..Y+n } ]
138139
* }</pre> */
139-
public static void inlineExpandTailJump(List<Instruction> insts) {
140+
public static void inlineExpandTailJump(List<Instruction> insts, boolean isOrRule) {
140141
if (insts.isEmpty()) return;
141142
Instruction spec = insts.get(0);
142143
if (spec.getKind() != Instruction.SPEC) return;
143144
for (int i = 1; i < insts.size(); i++) {
144145
Instruction branch = insts.get(i);
145146
if (branch.getKind() != Instruction.BRANCH) break;
146147
InstructionList label = (InstructionList) branch.getArg1();
147-
inlineExpandTailJump(label.insts);
148+
inlineExpandTailJump(label.insts, isOrRule);
148149
}
149150

150151
int formals = spec.getIntArg1();
151152
int locals = spec.getIntArg2();
152-
locals = inlineExpandTailJump(insts, locals);
153+
locals = inlineExpandTailJump(insts, locals, isOrRule);
153154
spec.updateSpec(formals, locals);
154155
}
155156

@@ -158,7 +159,7 @@ public static void inlineExpandTailJump(List<Instruction> insts) {
158159
* @param varcount 展開前の実引数
159160
* @return 展開後の実引数
160161
* */
161-
public static int inlineExpandTailJump(List<Instruction> insts, int varcount) {
162+
public static int inlineExpandTailJump(List<Instruction> insts, int varcount, boolean isOrRule) {
162163
if (insts.isEmpty()) return varcount;
163164
int size = insts.size();
164165
Instruction jump = insts.get(size - 1);
@@ -185,6 +186,10 @@ public static int inlineExpandTailJump(List<Instruction> insts, int varcount) {
185186
Instruction.applyVarRewriteMap(subinsts, map);
186187
subinsts.remove(0); // specを除去
187188
insts.remove(size - 1); // jump命令を除去
189+
if (isOrRule) { // guard or 用の dummy を追加
190+
Instruction dummy = new Instruction(Instruction.ORDUMMY);
191+
insts.add(dummy);
192+
}
188193
insts.addAll(subinsts);
189194
return varcount;
190195
}

src/compile/RuleCompiler.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ public RuleCompiler(RuleStructure rs) {
103103
/**
104104
* 初期化時に指定されたルール構造をルールオブジェクトにコンパイルする
105105
*/
106-
public Rule compile(boolean isTypeDef) throws CompileException {
106+
public Rule compile(boolean isTypeDef, boolean isOrRule) throws CompileException {
107107
// System.out.println("compile() called: " + rs);
108108
liftupActiveAtoms(rs.leftMem);
109109
simplify();
@@ -154,7 +154,7 @@ public Rule compile(boolean isTypeDef) throws CompileException {
154154
String ruleName =
155155
theRule.name != null ? theRule.name : makeRuleName(rs.toString(), Env.showlongrulename, 4);
156156
theRule.body.add(1, Instruction.commit(ruleName, theRule.lineno));
157-
optimize();
157+
optimize(isOrRule);
158158
return theRule;
159159
}
160160

@@ -1050,11 +1050,11 @@ private static void checkExplicitFreeLinks(Membrane mem) throws CompileException
10501050
/**
10511051
* 命令列を最適化する
10521052
*/
1053-
private void optimize() {
1053+
private void optimize(boolean isOrRule) {
10541054
Env.c("optimize");
10551055
if (!rs.isInitialRule()) {
10561056
// このフラグがtrue <=> theRuleは初期データ生成用ルール
1057-
Optimizer.optimizeRule(theRule);
1057+
Optimizer.optimizeRule(theRule, isOrRule);
10581058
}
10591059
}
10601060

src/compile/RulesetCompiler.java

Lines changed: 80 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import compile.structure.RuleStructure;
99
import compile.structure.TypeDefStructure;
1010
import java.util.ArrayList;
11+
import java.util.LinkedList;
1112
import java.util.List;
1213
import runtime.Env;
1314
import runtime.Instruction;
@@ -60,21 +61,44 @@ public static void processMembrane(Membrane mem) {
6061
List<Rule> rules = new ArrayList<>();
6162

6263
// この膜にあるルール構造をルールオブジェクトにコンパイルする
63-
for (RuleStructure rs : mem.rules) {
64-
// ルールの右辺膜以下にある子ルールをルールセットにコンパイルする
65-
processMembrane(rs.leftMem); // 一応左辺も
66-
processMembrane(rs.rightMem);
67-
68-
RuleCompiler rc = null;
69-
try {
70-
rc = new RuleCompiler(rs);
71-
rc.compile(false);
72-
// 2006.1.22 Ruleに行番号を渡す by inui
73-
rc.theRule.lineno = rs.lineno;
74-
} catch (CompileException e) {
75-
Env.p(" in " + rs.toString() + "\n");
64+
// guard or 用に変更
65+
for (int i = 0; i < mem.or_pairs.size(); i++) {
66+
LinkedList<Integer> pairs = mem.or_pairs.get(i);
67+
if (pairs.size() > 1) {
68+
for (int itr = 0; itr < pairs.size(); itr++) {
69+
RuleStructure rs = mem.rules.get(pairs.get(itr));
70+
// ルールの右辺膜以下にある子ルールをルールセットにコンパイルする
71+
processMembrane(rs.leftMem); // 一応左辺も
72+
processMembrane(rs.rightMem);
73+
74+
RuleCompiler rc = null;
75+
try {
76+
rc = new RuleCompiler(rs);
77+
rc.compile(false, true);
78+
// 2006.1.22 Ruleに行番号を渡す by inui
79+
rc.theRule.lineno = rs.lineno;
80+
} catch (CompileException e) {
81+
Env.p(" in " + rs.toString() + "\n");
82+
}
83+
rules.add(rc.theRule);
84+
}
85+
} else {
86+
RuleStructure rs = mem.rules.get(pairs.get(0));
87+
// ルールの右辺膜以下にある子ルールをルールセットにコンパイルする
88+
processMembrane(rs.leftMem); // 一応左辺も
89+
processMembrane(rs.rightMem);
90+
91+
RuleCompiler rc = null;
92+
try {
93+
rc = new RuleCompiler(rs);
94+
rc.compile(false, false);
95+
// 2006.1.22 Ruleに行番号を渡す by inui
96+
rc.theRule.lineno = rs.lineno;
97+
} catch (CompileException e) {
98+
Env.p(" in " + rs.toString() + "\n");
99+
}
100+
rules.add(rc.theRule);
76101
}
77-
rules.add(rc.theRule);
78102
}
79103

80104
// typedef におけるサブルールをコンパイルする
@@ -111,7 +135,7 @@ public static void processMembrane(Membrane mem) {
111135
RuleCompiler rc = null;
112136
try {
113137
rc = new RuleCompiler(rs);
114-
rc.compile(true);
138+
rc.compile(true, false);
115139

116140
// 2006.1.22 Ruleに行番号を渡す by inui
117141
rc.theRule.lineno = rs.lineno;
@@ -126,8 +150,48 @@ public static void processMembrane(Membrane mem) {
126150

127151
// 生成したルールオブジェクトのリストをルールセット(のセット)にコンパイルする
128152
if (!rules.isEmpty()) {
153+
List<Integer> notAdd = new LinkedList<>();
129154
InterpretedRuleset ruleset = new InterpretedRuleset();
130-
for (Rule r : rules) {
155+
// guard or 用に and のみを含むように分割したルールを合成する
156+
// -O3 前提
157+
for (int itr = 0; itr < mem.or_pairs.size(); itr++) {
158+
LinkedList<Integer> pair = (LinkedList) mem.or_pairs.get(itr);
159+
if (pair.size() > 1) { // guard or を含む場合
160+
InstructionList orlists = new InstructionList();
161+
for (int i = 1; i < pair.size(); i++) {
162+
notAdd.add(pair.get(i));
163+
InstructionList orlist = new InstructionList();
164+
orlist.insts = InstructionList.cloneInstructions(rules.get(pair.get(i)).memMatch);
165+
for (Instruction instr : rules.get(pair.get(i)).memMatch) {
166+
if (instr.getKind() == Instruction.ORDUMMY) { // ordummy 以降の命令をすべて branch で囲む
167+
orlist.insts.remove(0);
168+
Instruction branch = new Instruction(Instruction.BRANCH, orlist);
169+
orlists.add(branch);
170+
break;
171+
}
172+
orlist.insts.remove(0); // ordummy が来るまで前から順に命令を削除
173+
}
174+
}
175+
// ordummy を guard or を表す branch 命令の列に置き換える
176+
List<Instruction> replace = rules.get(pair.get(0)).memMatch;
177+
for (int i = 0; i < replace.size(); i++) {
178+
if (replace.get(i).getKind() == Instruction.ORDUMMY) {
179+
replace.addAll(i + 1, orlists.insts);
180+
replace.remove(i);
181+
break;
182+
}
183+
}
184+
}
185+
// ruleset.rules.add(rules.get(pair.get(0)));
186+
}
187+
for (int i = 0; i < rules.size(); i++) {
188+
if (!notAdd.isEmpty()) {
189+
if (i == notAdd.get(0)) {
190+
notAdd.remove(0);
191+
continue;
192+
}
193+
}
194+
Rule r = rules.get(i);
131195
ruleset.rules.add(r);
132196
}
133197
ruleset.branchmap = null;

src/compile/parser/LMNParser.java

Lines changed: 103 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -379,39 +379,109 @@ private void addSrcRuleContextToMem(SrcRuleContext sRule, Membrane mem) {
379379
* @param mem 追加先の膜
380380
*/
381381
private void addSrcRuleToMem(SrcRule sRule, Membrane mem) throws ParseException {
382-
// 2006.1.22 linenoを追加 by inui
383-
RuleStructure rule = new RuleStructure(mem, sRule.getText(), sRule.lineno);
384-
rule.name = sRule.name;
385-
// 略記法の展開
386-
expander.expandRuleAbbreviations(sRule);
387-
// 左辺のルールを構文エラーとして除去する
388-
assertLHSRules(sRule.getHead());
389-
390-
// 左辺およびガード型制約に対して、構造を生成し、リンク以外の名前を解決する
391-
addProcessToMem(sRule.getHead(), rule.leftMem);
392-
addProcessToMem(sRule.getGuard(), rule.guardMem);
393-
HashMap names = resolveHeadContextNames(rule);
394-
// ガード否定条件および右辺に対して、構造を生成し、リンク以外の名前を解決する
395-
addGuardNegatives(sRule.getGuardNegatives(), rule, names);
396-
addProcessToMem(sRule.getBody(), rule.rightMem);
397-
resolveContextNames(rule, names);
398-
399-
// 略記法が展開されて構造が生成され,
400-
// リンク以外の名前が解決されている ( $p,@pのContext.defがセットされている,*Vは双方向リンクがはられている )
401-
402-
// プロキシアトムを生成し、リンクをつなぎ、膜の自由リンクリストを決定する
403-
// この時点ではアトムのリンク引数には自分自身のLinkOccurreceが格納されている
404-
// これらが終わると,アトムのリンク引数のLinkOccurrenceのbuddyがセットされる
405-
// リンクを繋ぐ作業はaddLinkOccurrenceで行われる
406-
407-
addProxies(rule.leftMem); // addProxiesAndCoupleLinksであるべき?
408-
coupleLinks(rule.guardMem);
409-
addProxies(rule.rightMem);
410-
addProxiesToGuardNegatives(rule);
411-
coupleGuardNegativeLinks(rule); // ガード否定条件のリンクを接続する
412-
coupleInheritedLinks(rule); // 右辺と左辺の自由リンクを接続する
413-
414-
mem.rules.add(rule);
382+
// guard に or を含むルールを and のみのルールに分割する
383+
LinkedList<SrcRule> splitRules = splitGuardOr(sRule);
384+
LinkedList<Integer> pairs = new LinkedList<Integer>();
385+
386+
for (int itr = 0; itr < splitRules.size(); itr++) {
387+
SrcRule sRuleTmp = splitRules.get(itr);
388+
// 2006.1.22 linenoを追加 by inui
389+
RuleStructure rule = new RuleStructure(mem, sRuleTmp.getText(), sRule.lineno);
390+
rule.name = sRuleTmp.name;
391+
// 略記法の展開
392+
expander.expandRuleAbbreviations(sRuleTmp);
393+
// 左辺のルールを構文エラーとして除去する
394+
assertLHSRules(sRuleTmp.getHead());
395+
396+
// 左辺およびガード型制約に対して、構造を生成し、リンク以外の名前を解決する
397+
addProcessToMem(sRuleTmp.getHead(), rule.leftMem);
398+
addProcessToMem(sRuleTmp.getGuard(), rule.guardMem);
399+
HashMap names = resolveHeadContextNames(rule);
400+
// ガード否定条件および右辺に対して、構造を生成し、リンク以外の名前を解決する
401+
addGuardNegatives(sRuleTmp.getGuardNegatives(), rule, names);
402+
addProcessToMem(sRuleTmp.getBody(), rule.rightMem);
403+
resolveContextNames(rule, names);
404+
405+
// 略記法が展開されて構造が生成され,
406+
// リンク以外の名前が解決されている ( $p,@pのContext.defがセットされている,*Vは双方向リンクがはられている )
407+
408+
// プロキシアトムを生成し、リンクをつなぎ、膜の自由リンクリストを決定する
409+
// この時点ではアトムのリンク引数には自分自身のLinkOccurreceが格納されている
410+
// これらが終わると,アトムのリンク引数のLinkOccurrenceのbuddyがセットされる
411+
// リンクを繋ぐ作業はaddLinkOccurrenceで行われる
412+
413+
addProxies(rule.leftMem); // addProxiesAndCoupleLinksであるべき?
414+
coupleLinks(rule.guardMem);
415+
addProxies(rule.rightMem);
416+
addProxiesToGuardNegatives(rule);
417+
coupleGuardNegativeLinks(rule); // ガード否定条件のリンクを接続する
418+
coupleInheritedLinks(rule); // 右辺と左辺の自由リンクを接続する
419+
420+
mem.rules.add(rule);
421+
pairs.add(mem.rules.size() - 1);
422+
}
423+
if (pairs.size() > 0) mem.or_pairs.add(pairs);
424+
425+
// // 2006.1.22 linenoを追加 by inui
426+
// RuleStructure rule = new RuleStructure(mem, sRule.getText(), sRule.lineno);
427+
// rule.name = sRule.name;
428+
// // 略記法の展開
429+
// expander.expandRuleAbbreviations(sRule);
430+
// // 左辺のルールを構文エラーとして除去する
431+
// assertLHSRules(sRule.getHead());
432+
433+
// // 左辺およびガード型制約に対して、構造を生成し、リンク以外の名前を解決する
434+
// addProcessToMem(sRule.getHead(), rule.leftMem);
435+
// addProcessToMem(sRule.getGuard(), rule.guardMem);
436+
// HashMap names = resolveHeadContextNames(rule);
437+
// // ガード否定条件および右辺に対して、構造を生成し、リンク以外の名前を解決する
438+
// addGuardNegatives(sRule.getGuardNegatives(), rule, names);
439+
// addProcessToMem(sRule.getBody(), rule.rightMem);
440+
// resolveContextNames(rule, names);
441+
442+
// // 略記法が展開されて構造が生成され,
443+
// // リンク以外の名前が解決されている ( $p,@pのContext.defがセットされている,*Vは双方向リンクがはられている )
444+
445+
// // プロキシアトムを生成し、リンクをつなぎ、膜の自由リンクリストを決定する
446+
// // この時点ではアトムのリンク引数には自分自身のLinkOccurreceが格納されている
447+
// // これらが終わると,アトムのリンク引数のLinkOccurrenceのbuddyがセットされる
448+
// // リンクを繋ぐ作業はaddLinkOccurrenceで行われる
449+
450+
// addProxies(rule.leftMem); // addProxiesAndCoupleLinksであるべき?
451+
// coupleLinks(rule.guardMem);
452+
// addProxies(rule.rightMem);
453+
// addProxiesToGuardNegatives(rule);
454+
// coupleGuardNegativeLinks(rule); // ガード否定条件のリンクを接続する
455+
// coupleInheritedLinks(rule); // 右辺と左辺の自由リンクを接続する
456+
457+
// mem.rules.add(rule);
458+
}
459+
460+
/**
461+
* guard or を含むルールを and のみのルールに分割する
462+
* @param rule
463+
* @return
464+
*/
465+
private LinkedList<SrcRule> splitGuardOr(SrcRule rule) {
466+
LinkedList<SrcRule> result = new LinkedList<SrcRule>();
467+
if (rule.getGuard() != null) {
468+
LinkedList guard = rule.getGuard();
469+
if (guard.size() > 0) {
470+
if (guard.get(0) instanceof LinkedList) {
471+
for (int i = 0; i < guard.size(); i++) {
472+
SrcRule tmp =
473+
new SrcRule(
474+
rule.name, rule.head, (LinkedList) guard.get(i), rule.body, rule.lineno);
475+
tmp.guard = (LinkedList) guard.get(i);
476+
tmp.setText();
477+
result.add(tmp);
478+
}
479+
}
480+
} else {
481+
result.add(rule);
482+
}
483+
}
484+
return result;
415485
}
416486

417487
/**

0 commit comments

Comments
 (0)