diff --git a/log.txt b/log.txt new file mode 100644 index 00000000..8b06ddc8 --- /dev/null +++ b/log.txt @@ -0,0 +1,306 @@ +{ + "parent" : null, + "stable" : false, + "kind" : 0, + "pragmaAtHost" : null, + "name" : null, + "atoms" : [ ], + "mems" : [ ], + "rules" : [ { + "name" : "_init", + "fSuppressEmptyHeadWarning" : false, + "leftMem" : { + "parent" : null, + "stable" : false, + "kind" : 0, + "pragmaAtHost" : null, + "name" : null, + "atoms" : [ ], + "mems" : [ ], + "rules" : [ ], + "aggregates" : [ ], + "processContexts" : [ ], + "ruleContexts" : [ ], + "typedProcessContexts" : [ ], + "freeLinks" : { }, + "rulesets" : [ ], + "normalAtomCount" : 0, + "freeLinkAtomCount" : 0, + "firstAtomName" : "null" + }, + "rightMem" : { + "parent" : null, + "stable" : false, + "kind" : 0, + "pragmaAtHost" : null, + "name" : null, + "atoms" : [ { + "args" : [ { + "name" : "~1", + "pos" : 0, + "informativeText" : "_1(a/1,0)" + } ], + "line" : 1, + "column" : 1, + "functor" : { + "name" : "a", + "arity" : 1, + "path" : null, + "integer" : false, + "string" : false, + "quotedAtomName" : "a", + "active" : true, + "number" : false, + "symbol" : true, + "insideProxy" : false, + "outsideProxy" : false, + "value" : "a", + "quotedFullyFunctorName" : "a", + "quotedFunctorName" : "a", + "quotedFullyAtomName" : "a" + }, + "isSelfEvaluated" : false + }, { + "args" : [ { + "name" : "~1", + "pos" : 0, + "informativeText" : "_1(b/1,0)" + } ], + "line" : 1, + "column" : 3, + "functor" : { + "name" : "b", + "arity" : 1, + "path" : null, + "integer" : false, + "string" : false, + "quotedAtomName" : "b", + "active" : true, + "number" : false, + "symbol" : true, + "insideProxy" : false, + "outsideProxy" : false, + "value" : "b", + "quotedFullyFunctorName" : "b", + "quotedFunctorName" : "b", + "quotedFullyAtomName" : "b" + }, + "isSelfEvaluated" : false + } ], + "mems" : [ ], + "rules" : [ { + "name" : null, + "fSuppressEmptyHeadWarning" : false, + "leftMem" : { + "parent" : null, + "stable" : false, + "kind" : 0, + "pragmaAtHost" : null, + "name" : null, + "atoms" : [ { + "args" : [ { + "name" : "X", + "pos" : 0, + "informativeText" : "X(a/1,0)" + } ], + "line" : 1, + "column" : 7, + "functor" : { + "name" : "a", + "arity" : 1, + "path" : null, + "integer" : false, + "string" : false, + "quotedAtomName" : "a", + "active" : true, + "number" : false, + "symbol" : true, + "insideProxy" : false, + "outsideProxy" : false, + "value" : "a", + "quotedFullyFunctorName" : "a", + "quotedFunctorName" : "a", + "quotedFullyAtomName" : "a" + }, + "isSelfEvaluated" : false + } ], + "mems" : [ ], + "rules" : [ ], + "aggregates" : [ ], + "processContexts" : [ ], + "ruleContexts" : [ ], + "typedProcessContexts" : [ ], + "freeLinks" : { + "X" : { + "name" : "X", + "pos" : 0, + "informativeText" : "X(a/1,0)" + } + }, + "rulesets" : [ ], + "normalAtomCount" : 1, + "freeLinkAtomCount" : 0, + "firstAtomName" : "a" + }, + "rightMem" : { + "parent" : null, + "stable" : false, + "kind" : 0, + "pragmaAtHost" : null, + "name" : null, + "atoms" : [ { + "args" : [ { + "name" : "X", + "pos" : 0, + "informativeText" : "X(b/1,0)" + } ], + "line" : 1, + "column" : 15, + "functor" : { + "name" : "b", + "arity" : 1, + "path" : null, + "integer" : false, + "string" : false, + "quotedAtomName" : "b", + "active" : true, + "number" : false, + "symbol" : true, + "insideProxy" : false, + "outsideProxy" : false, + "value" : "b", + "quotedFullyFunctorName" : "b", + "quotedFunctorName" : "b", + "quotedFullyAtomName" : "b" + }, + "isSelfEvaluated" : false + } ], + "mems" : [ ], + "rules" : [ ], + "aggregates" : [ ], + "processContexts" : [ ], + "ruleContexts" : [ ], + "typedProcessContexts" : [ ], + "freeLinks" : { + "X" : { + "name" : "X", + "pos" : 0, + "informativeText" : "X(b/1,0)" + } + }, + "rulesets" : [ ], + "normalAtomCount" : 1, + "freeLinkAtomCount" : 0, + "firstAtomName" : "b" + }, + "guardMem" : { + "parent" : null, + "stable" : false, + "kind" : 0, + "pragmaAtHost" : null, + "name" : null, + "atoms" : [ ], + "mems" : [ ], + "rules" : [ ], + "aggregates" : [ ], + "processContexts" : [ ], + "ruleContexts" : [ ], + "typedProcessContexts" : [ ], + "freeLinks" : { }, + "rulesets" : [ ], + "normalAtomCount" : 0, + "freeLinkAtomCount" : 0, + "firstAtomName" : "null" + }, + "guardNegatives" : [ ], + "processContexts" : { }, + "ruleContexts" : { }, + "typedProcessContexts" : { }, + "lineno" : 1, + "initialRule" : false + } ], + "aggregates" : [ ], + "processContexts" : [ ], + "ruleContexts" : [ ], + "typedProcessContexts" : [ ], + "freeLinks" : { }, + "rulesets" : [ ], + "normalAtomCount" : 2, + "freeLinkAtomCount" : 0, + "firstAtomName" : "a" + }, + "guardMem" : { + "parent" : null, + "stable" : false, + "kind" : 0, + "pragmaAtHost" : null, + "name" : null, + "atoms" : [ ], + "mems" : [ ], + "rules" : [ ], + "aggregates" : [ ], + "processContexts" : [ ], + "ruleContexts" : [ ], + "typedProcessContexts" : [ ], + "freeLinks" : { }, + "rulesets" : [ ], + "normalAtomCount" : 0, + "freeLinkAtomCount" : 0, + "firstAtomName" : "null" + }, + "guardNegatives" : [ ], + "processContexts" : { }, + "ruleContexts" : { }, + "typedProcessContexts" : { }, + "lineno" : 1, + "initialRule" : false + } ], + "aggregates" : [ ], + "processContexts" : [ ], + "ruleContexts" : [ ], + "typedProcessContexts" : [ ], + "freeLinks" : { }, + "rulesets" : [ ], + "normalAtomCount" : 0, + "freeLinkAtomCount" : 0, + "firstAtomName" : "null" +} +Compiled Ruleset @602 +Compiled Rule + --atommatch: + --memmatch: + spec [1, 1] + jump [L106, [0], [], []] + --guard:L106: + spec [1, 1] + jump [L107, [0], [], []] + --body:L107: + spec [1, 3] + commit ["_init", 0] + loadruleset [0, @601] + newatom [1, 0, 'a'_1] + newatom [2, 0, 'b'_1] + newlink [1, 0, 2, 0, 0] + proceed [] + + +Compiled Ruleset @601 +Compiled Rule + --atommatch: + --memmatch: + spec [1, 2] + findatom [1, 0, 'a'_1] + jump [L101, [0], [1], []] + --guard:L101: + spec [2, 2] + jump [L102, [0], [1], []] + --body:L102: + spec [2, 3] + commit ["_aXbX", 0] + removeatom [1, 0] + newatom [2, 0, 'b'_1] + relink [2, 0, 1, 0, 0] + freeatom [1] + proceed [] + + diff --git a/src/compile/Optimizer.java b/src/compile/Optimizer.java index cff0cc13..a53ef38b 100644 --- a/src/compile/Optimizer.java +++ b/src/compile/Optimizer.java @@ -71,7 +71,7 @@ public static void setLevel(int level) { * * @param rule ルールオブジェクト */ - public static void optimizeRule(Rule rule) { + public static void optimizeRule(Rule rule, boolean isOrRule) { // TODO 最適化器を統合する Compactor.compactRule(rule); // TODO 本質的にインライン展開が必要ないものは、展開しなくてもできるようにする @@ -80,7 +80,7 @@ public static void optimizeRule(Rule rule) { // allocatomReduce のために常に head と guard をくっつける if (true) { // head と guard をくっつける - inlineExpandTailJump(rule.memMatch); + inlineExpandTailJump(rule.memMatch, isOrRule); rule.guardLabel = null; rule.guard = null; } @@ -88,7 +88,7 @@ public static void optimizeRule(Rule rule) { rule.memMatch.remove(rule.memMatch.size() - 1); } optimize(rule.memMatch, rule.body); - if (fGuardMove) { + if (fGuardMove && !isOrRule) { guardMove(rule.memMatch); allocMove(rule.memMatch); } @@ -101,7 +101,8 @@ public static void optimizeRule(Rule rule) { if (fSystemRulesetsInlining) inlineExpandSystemRuleSets(rule.body); if (fInlining) { // head(+guard) と body をくっつける - inlineExpandTailJump(rule.memMatch); + // guard or に対応するため、head と guard の切れ目に印をつけるように変更 + inlineExpandTailJump(rule.memMatch, false); rule.bodyLabel = null; rule.body = null; @@ -139,7 +140,7 @@ public static void optimize(List head, List body) { * [ spec[X,Y]; C;jump[L,A1..Am] ] where L:[spec[m,m+n];D] * ==> [ spec[X,Y+n];C; D{ 1..m->A1..Am, m+1..m+n->Y+1..Y+n } ] * } */ - public static void inlineExpandTailJump(List insts) { + public static void inlineExpandTailJump(List insts, boolean isOrRule) { if (insts.isEmpty()) return; Instruction spec = insts.get(0); if (spec.getKind() != Instruction.SPEC) return; @@ -147,12 +148,12 @@ public static void inlineExpandTailJump(List insts) { Instruction branch = insts.get(i); if (branch.getKind() != Instruction.BRANCH) break; InstructionList label = (InstructionList) branch.getArg1(); - inlineExpandTailJump(label.insts); + inlineExpandTailJump(label.insts, isOrRule); } int formals = spec.getIntArg1(); int locals = spec.getIntArg2(); - locals = inlineExpandTailJump(insts, locals); + locals = inlineExpandTailJump(insts, locals, isOrRule); spec.updateSpec(formals, locals); } @@ -161,7 +162,7 @@ public static void inlineExpandTailJump(List insts) { * @param varcount 展開前の実引数 * @return 展開後の実引数 * */ - public static int inlineExpandTailJump(List insts, int varcount) { + public static int inlineExpandTailJump(List insts, int varcount, boolean isOrRule) { if (insts.isEmpty()) return varcount; int size = insts.size(); Instruction jump = insts.get(size - 1); @@ -188,6 +189,10 @@ public static int inlineExpandTailJump(List insts, int varcount) { Instruction.applyVarRewriteMap(subinsts, map); subinsts.remove(0); // specを除去 insts.remove(size - 1); // jump命令を除去 + if (isOrRule) { // guard or 用の dummy を追加 + Instruction dummy = new Instruction(Instruction.ORDUMMY); + insts.add(dummy); + } insts.addAll(subinsts); return varcount; } diff --git a/src/compile/RuleCompiler.java b/src/compile/RuleCompiler.java index a4897dc8..77c047b1 100644 --- a/src/compile/RuleCompiler.java +++ b/src/compile/RuleCompiler.java @@ -103,7 +103,7 @@ public RuleCompiler(RuleStructure rs) { /** * 初期化時に指定されたルール構造をルールオブジェクトにコンパイルする */ - public Rule compile(boolean isTypeDef) throws CompileException { + public Rule compile(boolean isTypeDef, boolean isOrRule) throws CompileException { // System.out.println("compile() called: " + rs); liftupActiveAtoms(rs.leftMem); simplify(); @@ -154,7 +154,7 @@ public Rule compile(boolean isTypeDef) throws CompileException { String ruleName = theRule.name != null ? theRule.name : makeRuleName(rs.toString(), Env.showlongrulename, 4); theRule.body.add(1, Instruction.commit(ruleName, theRule.lineno)); - optimize(); + optimize(isOrRule); return theRule; } @@ -1061,11 +1061,11 @@ private static void checkExplicitFreeLinks(Membrane mem) throws CompileException /** * 命令列を最適化する */ - private void optimize() { + private void optimize(boolean isOrRule) { Env.c("optimize"); if (!rs.isInitialRule()) { // このフラグがtrue <=> theRuleは初期データ生成用ルール - Optimizer.optimizeRule(theRule); + Optimizer.optimizeRule(theRule, isOrRule); } } diff --git a/src/compile/RulesetCompiler.java b/src/compile/RulesetCompiler.java index 99388b77..7f593ffd 100644 --- a/src/compile/RulesetCompiler.java +++ b/src/compile/RulesetCompiler.java @@ -8,6 +8,7 @@ import compile.structure.RuleStructure; import compile.structure.TypeDefStructure; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; import runtime.Env; import runtime.Instruction; @@ -60,21 +61,44 @@ public static void processMembrane(Membrane mem) { List rules = new ArrayList<>(); // この膜にあるルール構造をルールオブジェクトにコンパイルする - for (RuleStructure rs : mem.rules) { - // ルールの右辺膜以下にある子ルールをルールセットにコンパイルする - processMembrane(rs.leftMem); // 一応左辺も - processMembrane(rs.rightMem); - - RuleCompiler rc = null; - try { - rc = new RuleCompiler(rs); - rc.compile(false); - // 2006.1.22 Ruleに行番号を渡す by inui - rc.theRule.lineno = rs.lineno; - } catch (CompileException e) { - Env.p(" in " + rs.toString() + "\n"); + // guard or 用に変更 + for (int i = 0; i < mem.or_pairs.size(); i++) { + LinkedList pairs = mem.or_pairs.get(i); + if (pairs.size() > 1) { + for (int itr = 0; itr < pairs.size(); itr++) { + RuleStructure rs = mem.rules.get(pairs.get(itr)); + // ルールの右辺膜以下にある子ルールをルールセットにコンパイルする + processMembrane(rs.leftMem); // 一応左辺も + processMembrane(rs.rightMem); + + RuleCompiler rc = null; + try { + rc = new RuleCompiler(rs); + rc.compile(false, true); + // 2006.1.22 Ruleに行番号を渡す by inui + rc.theRule.lineno = rs.lineno; + } catch (CompileException e) { + Env.p(" in " + rs.toString() + "\n"); + } + rules.add(rc.theRule); + } + } else { + RuleStructure rs = mem.rules.get(pairs.get(0)); + // ルールの右辺膜以下にある子ルールをルールセットにコンパイルする + processMembrane(rs.leftMem); // 一応左辺も + processMembrane(rs.rightMem); + + RuleCompiler rc = null; + try { + rc = new RuleCompiler(rs); + rc.compile(false, false); + // 2006.1.22 Ruleに行番号を渡す by inui + rc.theRule.lineno = rs.lineno; + } catch (CompileException e) { + Env.p(" in " + rs.toString() + "\n"); + } + rules.add(rc.theRule); } - rules.add(rc.theRule); } // typedef におけるサブルールをコンパイルする @@ -111,7 +135,7 @@ public static void processMembrane(Membrane mem) { RuleCompiler rc = null; try { rc = new RuleCompiler(rs); - rc.compile(true); + rc.compile(true, false); // 2006.1.22 Ruleに行番号を渡す by inui rc.theRule.lineno = rs.lineno; @@ -126,8 +150,57 @@ public static void processMembrane(Membrane mem) { // 生成したルールオブジェクトのリストをルールセット(のセット)にコンパイルする if (!rules.isEmpty()) { + List notAdd = new LinkedList<>(); InterpretedRuleset ruleset = new InterpretedRuleset(); - for (Rule r : rules) { + // guard or 用に and のみを含むように分割したルールを合成する + // -O3 前提 + int maxlocals = 0; + for (int itr = 0; itr < mem.or_pairs.size(); itr++) { + LinkedList pair = (LinkedList) mem.or_pairs.get(itr); + if (pair.size() > 1) { // guard or を含む場合 + InstructionList orlists = new InstructionList(); + for (int i = 1; i < pair.size(); i++) { + notAdd.add(pair.get(i)); + InstructionList orlist = new InstructionList(); + orlist.insts = InstructionList.cloneInstructions(rules.get(pair.get(i)).memMatch); + if (orlist.insts.get(0).getIntArg2() > maxlocals) { + maxlocals = orlist.insts.get(0).getIntArg2(); + } + for (Instruction instr : rules.get(pair.get(i)).memMatch) { + if (instr.getKind() == Instruction.ORDUMMY) { // ordummy 以降の命令をすべて branch で囲む + orlist.insts.remove(0); + Instruction branch = new Instruction(Instruction.BRANCH, orlist); + orlists.add(branch); + break; + } + orlist.insts.remove(0); // ordummy が来るまで前から順に命令を削除 + } + } + // ordummy を guard or を表す branch 命令の列に置き換える + List replace = rules.get(pair.get(0)).memMatch; + Instruction spec = replace.get(0); + if (spec.getIntArg2() > maxlocals) { + maxlocals = spec.getIntArg2(); + } + spec.updateSpec(spec.getIntArg1(), maxlocals); + for (int i = 0; i < replace.size(); i++) { + if (replace.get(i).getKind() == Instruction.ORDUMMY) { + replace.addAll(i + 1, orlists.insts); + replace.remove(i); + break; + } + } + } + // ruleset.rules.add(rules.get(pair.get(0))); + } + for (int i = 0; i < rules.size(); i++) { + if (!notAdd.isEmpty()) { + if (i == notAdd.get(0)) { + notAdd.remove(0); + continue; + } + } + Rule r = rules.get(i); ruleset.rules.add(r); } ruleset.branchmap = null; diff --git a/src/compile/parser/LMNParser.java b/src/compile/parser/LMNParser.java index 0612ab1c..254d4277 100644 --- a/src/compile/parser/LMNParser.java +++ b/src/compile/parser/LMNParser.java @@ -379,39 +379,113 @@ private void addSrcRuleContextToMem(SrcRuleContext sRule, Membrane mem) { * @param mem 追加先の膜 */ private void addSrcRuleToMem(SrcRule sRule, Membrane mem) throws ParseException { - // 2006.1.22 linenoを追加 by inui - RuleStructure rule = new RuleStructure(mem, sRule.getText(), sRule.lineno); - rule.name = sRule.name; - // 略記法の展開 - expander.expandRuleAbbreviations(sRule); - // 左辺のルールを構文エラーとして除去する - assertLHSRules(sRule.getHead()); - - // 左辺およびガード型制約に対して、構造を生成し、リンク以外の名前を解決する - addProcessToMem(sRule.getHead(), rule.leftMem); - addProcessToMem(sRule.getGuard(), rule.guardMem); - HashMap names = resolveHeadContextNames(rule); - // ガード否定条件および右辺に対して、構造を生成し、リンク以外の名前を解決する - addGuardNegatives(sRule.getGuardNegatives(), rule, names); - addProcessToMem(sRule.getBody(), rule.rightMem); - resolveContextNames(rule, names); - - // 略記法が展開されて構造が生成され, - // リンク以外の名前が解決されている ( $p,@pのContext.defがセットされている,*Vは双方向リンクがはられている ) - - // プロキシアトムを生成し、リンクをつなぎ、膜の自由リンクリストを決定する - // この時点ではアトムのリンク引数には自分自身のLinkOccurreceが格納されている - // これらが終わると,アトムのリンク引数のLinkOccurrenceのbuddyがセットされる - // リンクを繋ぐ作業はaddLinkOccurrenceで行われる - - addProxies(rule.leftMem); // addProxiesAndCoupleLinksであるべき? - coupleLinks(rule.guardMem); - addProxies(rule.rightMem); - addProxiesToGuardNegatives(rule); - coupleGuardNegativeLinks(rule); // ガード否定条件のリンクを接続する - coupleInheritedLinks(rule); // 右辺と左辺の自由リンクを接続する - - mem.rules.add(rule); + // guard に or を含むルールを and のみのルールに分割する + LinkedList splitRules = splitGuardOr(sRule); + LinkedList pairs = new LinkedList(); + + for (int itr = 0; itr < splitRules.size(); itr++) { + SrcRule sRuleTmp = splitRules.get(itr); + // 2006.1.22 linenoを追加 by inui + RuleStructure rule = new RuleStructure(mem, sRuleTmp.getText(), sRule.lineno); + rule.name = sRuleTmp.name; + // 略記法の展開 + expander.expandRuleAbbreviations(sRuleTmp); + // 左辺のルールを構文エラーとして除去する + assertLHSRules(sRuleTmp.getHead()); + + // 左辺およびガード型制約に対して、構造を生成し、リンク以外の名前を解決する + addProcessToMem(sRuleTmp.getHead(), rule.leftMem); + addProcessToMem(sRuleTmp.getGuard(), rule.guardMem); + HashMap names = resolveHeadContextNames(rule); + // ガード否定条件および右辺に対して、構造を生成し、リンク以外の名前を解決する + addGuardNegatives(sRuleTmp.getGuardNegatives(), rule, names); + addProcessToMem(sRuleTmp.getBody(), rule.rightMem); + resolveContextNames(rule, names); + + // 略記法が展開されて構造が生成され, + // リンク以外の名前が解決されている ( $p,@pのContext.defがセットされている,*Vは双方向リンクがはられている ) + + // プロキシアトムを生成し、リンクをつなぎ、膜の自由リンクリストを決定する + // この時点ではアトムのリンク引数には自分自身のLinkOccurreceが格納されている + // これらが終わると,アトムのリンク引数のLinkOccurrenceのbuddyがセットされる + // リンクを繋ぐ作業はaddLinkOccurrenceで行われる + + addProxies(rule.leftMem); // addProxiesAndCoupleLinksであるべき? + coupleLinks(rule.guardMem); + addProxies(rule.rightMem); + addProxiesToGuardNegatives(rule); + coupleGuardNegativeLinks(rule); // ガード否定条件のリンクを接続する + coupleInheritedLinks(rule); // 右辺と左辺の自由リンクを接続する + + mem.rules.add(rule); + pairs.add(mem.rules.size() - 1); + } + if (pairs.size() > 0) mem.or_pairs.add(pairs); + + // // 2006.1.22 linenoを追加 by inui + // RuleStructure rule = new RuleStructure(mem, sRule.getText(), sRule.lineno); + // rule.name = sRule.name; + // // 略記法の展開 + // expander.expandRuleAbbreviations(sRule); + // // 左辺のルールを構文エラーとして除去する + // assertLHSRules(sRule.getHead()); + + // // 左辺およびガード型制約に対して、構造を生成し、リンク以外の名前を解決する + // addProcessToMem(sRule.getHead(), rule.leftMem); + // addProcessToMem(sRule.getGuard(), rule.guardMem); + // HashMap names = resolveHeadContextNames(rule); + // // ガード否定条件および右辺に対して、構造を生成し、リンク以外の名前を解決する + // addGuardNegatives(sRule.getGuardNegatives(), rule, names); + // addProcessToMem(sRule.getBody(), rule.rightMem); + // resolveContextNames(rule, names); + + // // 略記法が展開されて構造が生成され, + // // リンク以外の名前が解決されている ( $p,@pのContext.defがセットされている,*Vは双方向リンクがはられている ) + + // // プロキシアトムを生成し、リンクをつなぎ、膜の自由リンクリストを決定する + // // この時点ではアトムのリンク引数には自分自身のLinkOccurreceが格納されている + // // これらが終わると,アトムのリンク引数のLinkOccurrenceのbuddyがセットされる + // // リンクを繋ぐ作業はaddLinkOccurrenceで行われる + + // addProxies(rule.leftMem); // addProxiesAndCoupleLinksであるべき? + // coupleLinks(rule.guardMem); + // addProxies(rule.rightMem); + // addProxiesToGuardNegatives(rule); + // coupleGuardNegativeLinks(rule); // ガード否定条件のリンクを接続する + // coupleInheritedLinks(rule); // 右辺と左辺の自由リンクを接続する + + // mem.rules.add(rule); + } + + /** + * guard or を含むルールを and のみのルールに分割する + * @param rule + * @return + */ + private LinkedList splitGuardOr(SrcRule rule) { + LinkedList result = new LinkedList(); + if (rule.getGuard() != null) { + LinkedList guard = rule.getGuard(); + if (guard.size() > 0) { + if (guard.get(0) instanceof LinkedList) { + for (int i = 0; i < guard.size(); i++) { + SrcRule tmp = + new SrcRule( + rule.name, rule.head, (LinkedList) guard.get(i), rule.body, rule.lineno); + tmp.guard = (LinkedList) guard.get(i); + tmp.setText(); + result.add(tmp); + } + } else { + result.add(rule); + } + } else { + result.add(rule); + } + } else { + result.add(rule); + } + return result; } /** diff --git a/src/compile/parser/SrcDumper.java b/src/compile/parser/SrcDumper.java index d6eb2134..97e62fb6 100644 --- a/src/compile/parser/SrcDumper.java +++ b/src/compile/parser/SrcDumper.java @@ -32,10 +32,29 @@ public static String dumpLinkedList(LinkedList list, String sep) { return s; } + // guard or 用 dumper + public static String dumpLinkedListWithOr(LinkedList list, String sep_and, String sep_or) { + if (list == null || list.size() == 0) return ""; + String s = ""; + if (list.get(0) instanceof LinkedList) { + s += dump(list.get(0)); + for (int i = 1; i < list.size(); i++) { + s += sep_or + dump(list.get(i)); + } + } else { + s += dump(list.get(0)); + for (int i = 1; i < list.size(); i++) { + s += sep_and + dump(list.get(i)); + } + } + + return s; + } + public static String dumpMembrane(SrcMembrane mem) { String name = mem.name == null ? "" : mem.name; String s = name + "{"; - if (mem.getProcess().size() > 0) s += dumpLinkedList(mem.getProcess(), ", "); + if (mem.getProcess().size() > 0) s += dumpLinkedListWithOr(mem.getProcess(), ", ", "; "); s += "}"; if (mem.kind == 1) s += "_"; if (mem.stable) s += "/"; @@ -50,7 +69,7 @@ public static String dumpRule(SrcRule rule) { if (rule.getHead() != null && rule.getHead().size() > 0) s += dumpLinkedList(rule.getHead(), ", "); s += " :- "; - if (rule.getGuard().size() > 0) s += dumpLinkedList(rule.getGuard(), ", ") + " | "; + if (rule.getGuard().size() > 0) s += dumpLinkedListWithOr(rule.getGuard(), ", ", "; ") + " | "; s += dumpLinkedList(rule.getBody(), ", ") + ". )"; return s; } @@ -91,7 +110,7 @@ public static String dump(Object obj) { } else if (obj instanceof SrcRuleContext) { return dumpRuleContext((SrcRuleContext) obj); } else if (obj instanceof LinkedList) { - return dumpLinkedList((LinkedList) obj, ", "); + return dumpLinkedListWithOr((LinkedList) obj, ", ", "; "); } else if (obj instanceof SrcTypeDef) { return dumpTypeDef((SrcTypeDef) obj); } diff --git a/src/compile/parser/SrcRule.java b/src/compile/parser/SrcRule.java index d4177d82..21f59a17 100644 --- a/src/compile/parser/SrcRule.java +++ b/src/compile/parser/SrcRule.java @@ -99,7 +99,10 @@ public SrcRule( } LinkedList head3 = this.head; LinkedList body2 = this.body; - addTypeConstraint(head3); + /* I から始まるアトムを int 型として扱う旧時代の機能 + * なぜか simpagation にだけ残っていたのでコメントアウト + * addTypeConstraint(head3); + */ addHyperLinkConstraint(head3, this.guard, body2); } @@ -134,6 +137,7 @@ private LinkedList addHyperLinkConstraintSub( headhl.add(name.toString()); SrcAtom newg = new SrcAtom("hlink", newl); guard.add(newg); + } else if (o instanceof SrcAtom) { SrcAtom sa = (SrcAtom) o; headhl = addHyperLinkConstraintSub(sa.process, guard, null, headhl); @@ -222,7 +226,17 @@ public void addTypeConstraint(LinkedList l) { */ private void unSimpagationize(List head2) { // head を全てbodyへコピー (前に追加のほうが再利用の上でも都合がいい?) - body.addAll(copySrcs(head)); + if (body.get(0) instanceof LinkedList) { + for (int i = 0; i < body.size(); i++) { + if (body.get(i) instanceof LinkedList) { + LinkedList b = (LinkedList) body.get(i); + b.addAll(copySrcs(head)); + } + } + } else { + body.addAll(copySrcs(head)); + } + // head2をheadの後ろに連結 head.addAll(head2); } @@ -306,7 +320,7 @@ public LinkedList getBody() { } public String toString() { - return "(rule:" + name + ")"; + return "(rule:" + name + "), head: " + head + ", guard: " + guard + ", body: " + body; } /** diff --git a/src/compile/parser/lmntal.cup b/src/compile/parser/lmntal.cup index dc82ae48..64c65622 100644 --- a/src/compile/parser/lmntal.cup +++ b/src/compile/parser/lmntal.cup @@ -30,7 +30,7 @@ terminal COMMA, LPAREN, RPAREN, LBRACE, RBRACE_UNDERBAR, RBRACE_UNDERBAR_SLASH, RBRACE_UNDERBAR_AT, RBRACE_UNDERBAR_SLASH_AT, RBRACE_ASTERISK, - COLON, PERIOD, BACKSLASH, GUARD, PROCVAR, RULEVAR, + COLON, SEMICOLON, PERIOD, BACKSLASH, GUARD, PROCVAR, RULEVAR, LBRACKET, RBRACKET, NEGATIVE, MOD, LOGAND, LOGIOR, LOGXOR, /* LOGNOT, */ ASH, HAT, TILDE, ASTERISK_ASTERISK, @@ -73,6 +73,7 @@ non terminal SrcContext Context; non terminal Object Process; non terminal SrcRule ProcessListContinuation; non terminal LinkedList ProcessList; +non terminal LinkedList OrList; non terminal LinkedList NonemptyProcessList; non terminal LinkedList WorldProcessList; non terminal LinkedList NonemptyWorldProcessList; @@ -434,20 +435,27 @@ Rule ::= {: RESULT = new SrcRule(null, head, body, lineno.intValue()); :} | RuleName:name RULENAMESEP ProcessList:head RULE:lineno ProcessList:body {: RESULT = new SrcRule(name, head, body, lineno.intValue()); :} - | ProcessList:head RULE:lineno ProcessList:guard GUARD ProcessList:body + | ProcessList:head RULE:lineno OrList:guard GUARD ProcessList:body {: RESULT = new SrcRule(null, head, guard, body, lineno.intValue()); :} - | RuleName:name RULENAMESEP ProcessList:head RULE:lineno ProcessList:guard GUARD ProcessList:body + | RuleName:name RULENAMESEP ProcessList:head RULE:lineno OrList:guard GUARD ProcessList:body {: RESULT = new SrcRule(name, head, guard, body, lineno.intValue()); :} | ProcessList:head BACKSLASH ProcessList:head2 RULE:lineno ProcessList:body {: RESULT = new SrcRule(null, head, head2, null, body, lineno.intValue()); :} | RuleName:name RULENAMESEP ProcessList:head BACKSLASH ProcessList:head2 RULE:lineno ProcessList:body {: RESULT = new SrcRule(name, head, head2, null, body, lineno.intValue()); :} - | ProcessList:head BACKSLASH ProcessList:head2 RULE:lineno ProcessList:guard GUARD ProcessList:body + | ProcessList:head BACKSLASH ProcessList:head2 RULE:lineno OrList:guard GUARD ProcessList:body {: RESULT = new SrcRule(null, head, head2, guard, body, lineno.intValue()); :} - | RuleName:name RULENAMESEP ProcessList:head BACKSLASH ProcessList:head2 RULE:lineno ProcessList:guard GUARD ProcessList:body + | RuleName:name RULENAMESEP ProcessList:head BACKSLASH ProcessList:head2 RULE:lineno OrList:guard GUARD ProcessList:body {: RESULT = new SrcRule(name, head, head2, guard, body, lineno.intValue()); :} ; +OrList ::= + ProcessList:pl + {: LinkedList list = new LinkedList(); list.add(pl); RESULT = list; :} + | OrList:list SEMICOLON ProcessList:pl + {: list.add(pl); RESULT = list; :} +; + // 「丸カッコありのルール構文、または丸カッコとカンマによる項組構文」のための非終端記号 // こっちはルール名には非対応。(a,b,c :- ( 対応しているようだが…。) // 出現した行番号を追加 by Inui @@ -457,11 +465,11 @@ ProcessListContinuation ::= {: RESULT = null; :} | RULE:lineno ProcessList:body RPAREN {: RESULT = new SrcRule(null, null, body, lineno.intValue()); :} - | RULE:lineno ProcessList:guard GUARD ProcessList:body RPAREN + | RULE:lineno OrList:guard GUARD ProcessList:body RPAREN {: RESULT = new SrcRule(null, null, guard, body, lineno.intValue()); :} | BACKSLASH ProcessList:head2 RULE:lineno ProcessList:body RPAREN {: RESULT = new SrcRule(null, null, head2, null, body, lineno.intValue()); :} - | BACKSLASH ProcessList:head2 RULE:lineno ProcessList:guard GUARD ProcessList:body RPAREN + | BACKSLASH ProcessList:head2 RULE:lineno OrList:guard GUARD ProcessList:body RPAREN {: RESULT = new SrcRule(null, null, head2, guard, body, lineno.intValue()); :} ; diff --git a/src/compile/parser/lmntal.flex b/src/compile/parser/lmntal.flex index 013242ca..3cf08a80 100644 --- a/src/compile/parser/lmntal.flex +++ b/src/compile/parser/lmntal.flex @@ -91,6 +91,7 @@ HyperLinkOp = "><" | ">*<" | ">+<" |">>" | "<<" { "/*" { yybegin(COMMENT); } "," { return symbol(sym.COMMA); } + ";" { return symbol(sym.SEMICOLON); } "(" { return symbol(sym.LPAREN); } ")" { return symbol(sym.RPAREN); } "{" { return symbol(sym.LBRACE); } diff --git a/src/compile/structure/Membrane.java b/src/compile/structure/Membrane.java index 2313b526..d8e40f3d 100644 --- a/src/compile/structure/Membrane.java +++ b/src/compile/structure/Membrane.java @@ -49,6 +49,9 @@ public final class Membrane { /** ルール(compile.structure.RuleStructure)のリスト */ public List rules = new LinkedList<>(); + /**guard or を展開したペアのリスト */ + public List or_pairs = new LinkedList<>(); + /** 型定義(compile.structure.TypeDefStructure)のリスト */ public List typeDefs = new LinkedList<>(); diff --git a/src/runtime/Instruction.java b/src/runtime/Instruction.java index a5b1291e..b98d02d0 100644 --- a/src/runtime/Instruction.java +++ b/src/runtime/Instruction.java @@ -2131,6 +2131,12 @@ public class Instruction implements Cloneable { setArgType(SUBRULE, new ArgType(true, ARG_VAR, ARG_INT, ARG_OBJ, ARG_VARS)); } + public static final int ORDUMMY = 1000; + + static { + setArgType(ORDUMMY, new ArgType(false)); + } + /** 命令の種類を取得する。*/ public int getKind() { return kind;