Commit e4ea85c0 authored by Niklas Fors's avatar Niklas Fors
Browse files

Generate method violateLowerBounds() and fix minor things with lists/opts

parent 2834ef70
......@@ -85,6 +85,16 @@ aspect ComponentAnalysis {
when !isTargetOfDirectedRelation() && toTypeDecl() != null
to TypeDecl.relationComponents()
for toTypeDecl();
syn Set<OneRelationComponent> TypeDecl.oneRelationComponents() {
Set<OneRelationComponent> set = new HashSet<>();
for (RelationComponent rc: relationComponents()) {
if (rc instanceof OneRelationComponent) {
set.add((OneRelationComponent) rc);
}
}
return set;
}
}
aspect Constructors {
......
......@@ -75,6 +75,7 @@ aspect BackendAspect {
sb.append("import java.util.ArrayList;\n");
sb.append("import java.util.Collections;\n");
sb.append("aspect RelAstAPI {\n");
for (TypeDecl td: getTypeDecls()) {
if (td.needsConstructor()) {
td.generateConstructor(sb);
......@@ -84,7 +85,9 @@ aspect BackendAspect {
r.generateAPI(sb);
}
sb.append(ind(1) + "public void ASTNode.assertNotNull(Object obj) {\n");
generateLowerBoundCheck(sb);
sb.append(ind(1) + "public static void ASTNode.assertNotNull(Object obj) {\n");
sb.append(ind(2) + "if (obj == null) {\n");
sb.append(ind(3) + "throw new NullPointerException();\n");
sb.append(ind(2) + "}\n");
......@@ -96,17 +99,35 @@ aspect BackendAspect {
sb.append(ind(1) + "public " + getID() + "." + getID() + "(");
int i = 0;
for (Component c: componentsTransitive()) {
sb.append(c.getTypeUse() + " " + c.getID());
sb.append(c.constructorParameter());
if (++i < componentsTransitive().size()) {
sb.append(", ");
}
}
sb.append(") {\n");
for (Component c: componentsTransitive()) {
sb.append(ind(2) + "set" + c.getID() + "(" + c.getID() + ");\n");
sb.append(ind(2) + c.constructorSetMethod() + "(" + c.getID() + ");\n");
}
sb.append(ind(1) + "}\n");
}
public String Component.constructorParameter() {
return getTypeUse() + " " + getID();
}
public String ListComponent.constructorParameter() {
return "List<" + getTypeUse() + "> " + getID();
}
public String OptComponent.constructorParameter() {
return "Opt<" + getTypeUse() + "> " + getID();
}
public String Component.constructorSetMethod() {
return "set" + getID();
}
public String ListComponent.constructorSetMethod() {
return "set" + getID() + "List";
}
public String OptComponent.constructorSetMethod() {
return "set" + getID() + "Opt";
}
}
aspect BackendAPI {
......@@ -403,6 +424,79 @@ aspect BackendBidirectionalAPI {
}
}
aspect LowerBoundCheck {
public void Program.generateLowerBoundCheck(StringBuilder sb) {
sb.append(ind(1) + "public boolean ASTNode.violateLowerBounds() {\n");
sb.append(ind(2) + "return !getLowerBoundsViolations().isEmpty();\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public java.util.List<Pair<ASTNode, String>> "
+ "ASTNode.getLowerBoundsViolations() {\n");
sb.append(ind(2) + "ArrayList<Pair<ASTNode, String>> list = new ArrayList<>();\n");
sb.append(ind(2) + "computeLowerBoundsViolations(list);\n");
sb.append(ind(2) + "return list;\n");
sb.append(ind(1) + "}\n");
sb.append(ind(1) + "public void ASTNode.computeLowerBoundsViolations("
+ "java.util.List<Pair<ASTNode, String>> list) {\n");
sb.append(ind(2) + "for (int i = 0; i < getNumChildNoTransform(); i++) {\n");
sb.append(ind(3) + "getChildNoTransform(i).computeLowerBoundsViolations(list);\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
for (TypeDecl td: getTypeDecls()) {
td.generateLowerBoundCheck(sb);
}
generatePairClass(sb);
}
public void TypeDecl.generateLowerBoundCheck(StringBuilder sb) {
if (!oneRelationComponents().isEmpty()) {
sb.append(ind(1) + "public void " + getID() + ".computeLowerBoundsViolations(" +
"java.util.List<Pair<ASTNode, String>> list) {\n");
for (OneRelationComponent o: oneRelationComponents()) {
o.generateLowerBoundCheck(sb);
}
sb.append(ind(2) + "super.computeLowerBoundsViolations(list);\n");
sb.append(ind(1) + "}\n");
}
}
public void OneRelationComponent.generateLowerBoundCheck(StringBuilder sb) {
sb.append(ind(2) + "if (" + name() + "() == null) {\n");
sb.append(ind(3) + "list.add(new Pair<>(this, \"" + name() + "\"));\n");
sb.append(ind(2) + "}\n");
}
public void Program.generatePairClass(StringBuilder sb) {
sb.append(ind(1) + "public class Pair<T1, T2> {\n");
sb.append(ind(2) + "public final T1 _1;\n");
sb.append(ind(2) + "public final T2 _2;\n");
// Constructor
sb.append(ind(2) + "public Pair(T1 _1, T2 _2) {\n");
sb.append(ind(3) + "ASTNode.assertNotNull(_1);\n");
sb.append(ind(3) + "ASTNode.assertNotNull(_2);\n");
sb.append(ind(3) + "this._1 = _1;\n");
sb.append(ind(3) + "this._2 = _2;\n");
sb.append(ind(2) + "}\n");
// equals
sb.append(ind(2) + "public boolean equals(Object other) {\n");
sb.append(ind(3) + "if (other instanceof Pair) {\n");
sb.append(ind(4) + "Pair<?,?> p = (Pair<?,?>) other;\n");
sb.append(ind(4) + "return _1.equals(p._1) && _2.equals(p._2);\n");
sb.append(ind(3) + "} else {\n");
sb.append(ind(4) + "return false;\n");
sb.append(ind(3) + "}\n");
sb.append(ind(2) + "}\n");
// hashCode
sb.append(ind(2) + "public int hashCode() {\n");
sb.append(ind(3) + "return 31*_1.hashCode() + _2.hashCode();\n");
sb.append(ind(2) + "}\n");
sb.append(ind(1) + "}\n");
}
}
aspect PrettyPrint {
public String Relation.prettyPrint() {
......
......@@ -53,8 +53,8 @@ Component component =
| ID COL s_type_use.u STAR {: return new ListComponent(ID, u); :}
| s_type_use.u STAR {: return new ListComponent(u.getID(), u); :}
// Opt
| ID COL s_type_use.u QUESTION_MARK {: return new OptComponent(ID, u); :}
| s_type_use.u QUESTION_MARK {: return new OptComponent(u.getID(), u); :}
| LBRACKET ID COL s_type_use.u RBRACKET {: return new OptComponent(ID, u); :}
| LBRACKET s_type_use.u RBRACKET {: return new OptComponent(u.getID(), u); :}
// Token
| LT ID COL type_use.u GT {: return new TokenComponent(ID, u); :}
| LT ID GT {: return new TokenComponent(ID, new SimpleTypeUse("String")); :}
......
......@@ -60,6 +60,8 @@ ID = [a-zA-Z$_][a-zA-Z0-9$_]*
"," { return sym(Terminals.COMMA); }
"<" { return sym(Terminals.LT); }
">" { return sym(Terminals.GT); }
"[" { return sym(Terminals.LBRACKET); }
"]" { return sym(Terminals.RBRACKET); }
"?" { return sym(Terminals.QUESTION_MARK); }
"->" { return sym(Terminals.RIGHT); }
"<->" { return sym(Terminals.BIDIRECTIONAL); }
......
/AST/*
/AllGen.ast
/AllGen.jadd
/AllGenGen.ast
/AllGenGen.jadd
/*Gen.ast
/*Gen.jadd
public class AbstractTests {
protected void assertException() {
check(false, "should throw exception");
}
protected void assertTrue(boolean b) {
check(b, "value should be true (is false)");
}
protected void assertFalse(boolean b) {
check(!b, "value should be flase (is true)");
}
protected void assertNull(Object obj) {
check(obj == null, "Object not null: " + obj);
}
protected void assertSame(Object o1, Object o2) {
check(o1 == o2, "Objects not same: " + o1 + ", " + o2);
}
protected void assertEquals(Object o1, Object o2) {
check(o1.equals(o2), "Objects not equals: " + o1 + ", " + o2);
}
protected void check(boolean b, String message) {
if (!b) {
throw new RuntimeException(message);
}
}
}
\ No newline at end of file
import AST.*;
import java.util.*;
public class Test {
public class All extends AbstractTests {
private Root r;
private A a1;
private A a2;
......@@ -11,7 +11,7 @@ public class Test {
private B b3;
public static void main(String args[]) {
new Test().test();
new All().test();
}
public void test() {
......@@ -551,29 +551,4 @@ public class Test {
r.addB(b2);
r.addB(b3);
}
private void assertException() {
check(false, "should throw exception");
}
private void assertTrue(boolean b) {
check(b, "value should be true (is false)");
}
private void assertFalse(boolean b) {
check(!b, "value should be flase (is true)");
}
private void assertNull(Object obj) {
check(obj == null, "Object not null: " + obj);
}
private void assertSame(Object o1, Object o2) {
check(o1 == o2, "Objects not same: " + o1 + ", " + o2);
}
private void assertEquals(Object o1, Object o2) {
check(o1.equals(o2), "Objects not equals: " + o1 + ", " + o2);
}
private void check(boolean b, String message) {
if (!b) {
throw new RuntimeException(message);
}
}
}
\ No newline at end of file
import AST.*;
public class LowerBounds extends AbstractTests {
public static void main(String args[]) {
new LowerBounds().test();
}
/*
* Root ::= A* B*;
* A ::= <Name> [C];
* B ::= <Name>;
* C ::= <Name>;
* rel A.b -> B;
* rel B.c <-> C.b;
* rel Root.aa? -> A;
*/
public void test() {
Root r = new Root();
C c1 = new C("c1");
C c2 = new C("c2");
A a1 = new A("a1", new Opt<>(c1));
A a2 = new A("a2", new Opt<>(c2));
B b1 = new B("b1");
B b2 = new B("b2");
r.addA(a1);
r.addA(a2);
r.addB(b1);
r.addB(b2);
assertTrue(r.violateLowerBounds());
a1.setB(b1);
a2.setB(b2);
b1.setC(c1);
b2.setC(c2);
assertFalse(r.violateLowerBounds());
b2.setC(c1);
assertTrue(r.violateLowerBounds());
b1.setC(c2);
assertFalse(r.violateLowerBounds());
}
}
\ No newline at end of file
Root ::= A* B*;
A ::= <Name> [C];
B ::= <Name>;
C ::= <Name>;
rel A.b -> B;
rel B.c <-> C.b;
rel Root.aa? -> A;
all: build-jar test
test: compile run check-idempotent
test: test1 test2
@echo "#"
@echo "# VALID TESTS OK"
@echo "#"
build-jar:
(cd ../../ && ant jar)
compile:
test1:
java -jar ../../relast-compiler.jar All.relast --file
rm -rf AST
java -jar ../../tools/jastadd2.jar --package=AST AllGen.ast AllGen.jadd Utils.jadd
run:
javac AST/*.java Test.java
java Test
check-idempotent:
javac AST/*.java All.java
java All
java -jar ../../relast-compiler.jar AllGen.ast --file
diff AllGen.ast AllGenGen.ast
test2:
java -jar ../../relast-compiler.jar LowerBounds.relast --file
rm -rf AST
java -jar ../../tools/jastadd2.jar --package=AST LowerBoundsGen.ast LowerBoundsGen.jadd Utils.jadd
javac AST/*.java LowerBounds.java
java LowerBounds
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment