Skip to content

Commit

Permalink
Abstract all versioned class instances (#31)
Browse files Browse the repository at this point in the history
* Abstract all versioned classes

* Update tests
  • Loading branch information
ansharlubis authored Oct 1, 2023
1 parent 500f6ca commit c3ca5e6
Show file tree
Hide file tree
Showing 38 changed files with 529 additions and 72 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
/tests/method_04/class
/tests/subtype_01/class
/tests/hash_01/class
/tests/hash_02/class

/tests/output

Expand Down
143 changes: 122 additions & 21 deletions batakjava/backend/Compilation.jrag
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ aspect Generation {
TypeDecl oldFactory = generated.findInterface(newInterface.packageName(), newInterface.name() + "_Factory");

for (BodyDecl newMethod: newInterface.getBodyDeclList()) {
//System.err.println(newMethod.prettyPrint());
oldInterface.addBodyDecl(newMethod.treeCopy());
}

Expand Down Expand Up @@ -59,14 +60,15 @@ aspect Generation {

for (String name: names) {
generated.removeDuplicate(name);
generated.processMethods(name);
generated.removeDuplicate(name + "_Factory");
generated.processMethod(name);
generated.processConstructor(name);
}

return generated;
}

public void Program.processMethods(String name) {
public void Program.processMethod(String name) {
TypeDecl parent = findInterface(name);
SimpleSet<TypeDecl> classSet = findClassSet(name);
for (TypeDecl t: classSet) {
Expand Down Expand Up @@ -101,7 +103,7 @@ aspect Generation {
}

public void Program.removeDuplicate(String name) {
TypeDecl t = findInterface(name + "_Factory");
TypeDecl t = findInterface(name);
List<BodyDecl> withoutDuplicate = new List();
java.util.Set<String> signatures = new HashSet();
for (BodyDecl b: t.getBodyDeclList()) {
Expand All @@ -125,7 +127,6 @@ aspect Generation {

syn nta List<TypeDecl> TypeDecl.compileInterface() = new List();

// TODO: handle different constructors in different versions
eq VersionClassDecl.compileInterface() {
List<TypeDecl> types = new List();
List<BodyDecl> bodyList = new List();
Expand Down Expand Up @@ -167,7 +168,7 @@ aspect Generation {
bodyList = bodyList.add(body.compile());
}

Opt<Access> superAccess = hasSuperClass() ? new Opt(getSuperClass().compileAccess()) : new Opt();
Opt<Access> superAccess = hasSuperClass() ? new Opt(getSuperClass().compileInstanceAccess()) : new Opt();

types = types.add(new ClassDecl(
getModifiers(),
Expand All @@ -183,7 +184,7 @@ aspect Generation {
List<TypeDecl> types = new List();
List<BodyDecl> bodyList = new List();

if (this instanceof GenericVersionClassDecl) {
if (isGenericVersionClassDecl()) {
GenericVersionClassDecl thisType = (GenericVersionClassDecl) this;
for (VersionVariable v: thisType.getVersionVariableList()) {
TypeAccess typeAccess = v.typeAccess();
Expand All @@ -203,7 +204,7 @@ aspect Generation {
}

Opt<Access> superAccess = hasSuperClass()
? new Opt(getSuperClass().compileAccess()) : new Opt();
? new Opt(getSuperClass().compileInstanceAccess()) : new Opt();

types = types.add(new ClassDecl(
getModifiers(),
Expand Down Expand Up @@ -244,7 +245,7 @@ aspect Generation {
List<Stmt> blockStmtList = new List();

// TODO: get rid of instanceof from here
if (hostType() instanceof GenericVersionClassDecl) {
if (hostType().isGenericVersionClassDecl()) {
GenericVersionClassDecl host = (GenericVersionClassDecl) hostType();
for (int i = 0; i < host.getNumVersionVariable(); i++) {
VersionVariable v_i = host.getVersionVariable(i);
Expand Down Expand Up @@ -350,6 +351,28 @@ aspect Generation {

syn nta List<BodyDecl> BodyDecl.compileInterface() = new List();

eq MethodDecl.compileInterface() {
if (getID().equals("main")) {
return new List();
}

List<ParameterDeclaration> ps = new List();

for (ParameterDeclaration p: getParameterList()) {
ParameterDeclaration np = new ParameterDeclaration(
p.getModifiers(), p.getTypeAccess().compileAccess(), p.getID());
ps = ps.add(np);
}

return new List().add(new MethodDecl(
getModifiers(),
getTypeAccess().compileAccess(),
getID(),
ps,
new List(),
new Opt()));
}

eq GenericVersionMethodDecl.compileInterface() {
List<ParameterDeclaration> ps = new List();

Expand Down Expand Up @@ -384,6 +407,8 @@ aspect Generation {

eq Dot.compileAccess() = new Dot(getLeft().compileExpr(), getRight().compileAccess());

// TODO: abstract every versioned class?
/*
eq TypeAccess.compileAccess() {
TypeDecl type = program().typeMap.get(
new Integer(model().evaluate(solverConst, false).toString()));
Expand All @@ -394,11 +419,14 @@ aspect Generation {
}

eq VersionTypeAccess.compileAccess() {
if (getVersionArgument() instanceof VersionVarArgument) {
if (getVersionArgument().isVersionVarArgument()) {
return getTypeAccess().treeCopy();
}
return getTypeAccess().compileAccess();
}
*/

eq VersionTypeAccess.compileAccess() = getTypeAccess().compileAccess();

eq ParVersionTypeAccess.compileAccess() = getTypeAccess().compileAccess();

Expand All @@ -421,13 +449,13 @@ aspect Generation {
VersionArgument va = getVersionArgument(i);
TypeAccess compileAccess = vv.typeAccess();
// TODO: handle version variable argument
if (va instanceof VersionNumArgument) {
if (va.isVersionNumArgument()) {
argList = argList.add(new ClassInstanceExpr(
new TypeAccess(compileAccess.getPackage(),
compileAccess.getID() + "_v" + va.getID() + "_Factory"),
new List()
));
} else if (va instanceof VersionVarArgument) {
} else if (va.isVersionVarArgument()) {
argList = argList.add(new VarAccess(va.getID()));
}
i++;
Expand Down Expand Up @@ -457,6 +485,26 @@ aspect Generation {
return new Block(stmtList);
}

syn Access Access.compileInstanceAccess() = treeCopy();

eq TypeAccess.compileInstanceAccess() {
TypeDecl type = getSolution();
if (type.isVersioned()) {
return new TypeAccess(getPackage(), type.getID() + "_v" + type.version());
}
return treeCopy();
}

eq VersionTypeAccess.compileInstanceAccess() {
VersionArgument va = getVersionArgument();
assert va.isVersionNumArgument();

TypeDecl type = getSolution();
return new TypeAccess(((TypeAccess) getTypeAccess()).getPackage(), type.getID() + "_v" + type.version());
}

eq ParVersionTypeAccess.compileInstanceAccess() = getTypeAccess().compileAccess();

syn nta Stmt Stmt.compileStmt() = treeCopy();

eq VarDeclStmt.compileStmt() {
Expand Down Expand Up @@ -506,28 +554,29 @@ aspect Generation {

eq Access.compileExpr() = compileAccess();

/*
eq ClassInstanceExpr.compileExpr() {
Access toCompile = getAccess();

List<Expr> argList = new List();
if (getAccess() instanceof ParVersionTypeAccess) {
if (getAccess().isParVersionTypeAccess()) {
ParVersionTypeAccess typeAccess = (ParVersionTypeAccess) getAccess();

TypeDecl compileType = program().typeMap.get(new Integer(model().evaluate(getAccess().solverConst, false).toString()));
assert compileType instanceof GenericVersionClassDecl;
assert compileType.isGenericVersionClassDecl();
GenericVersionClassDecl compileClass = (GenericVersionClassDecl) compileType;

for (int i = 0; i < typeAccess.getNumVersionArgument(); i++) {
VersionArgument va = typeAccess.getVersionArgument(i);
VersionVariable vv = compileClass.getVersionVariable(i);
TypeAccess compileAccess = vv.typeAccess();
if (va instanceof VersionNumArgument) {
if (va.isVersionNumArgument()) {
argList = argList.add(new ClassInstanceExpr(
new TypeAccess(compileAccess.getPackage(),
compileAccess.getID() + "_v" + va.getID() + "_Factory"),
new List()
));
} else if (va instanceof VersionVarArgument) {
} else if (va.isVersionVarArgument()) {
argList = argList.add(new VarAccess(va.getID()));
}
}
Expand All @@ -539,19 +588,69 @@ aspect Generation {
argList = argList.add(arg.compileExpr());
}

if (toCompile instanceof VersionTypeAccess) {
Access access = toCompile.compileAccess();

if (toCompile.isVersionTypeAccess()) {
VersionTypeAccess typeAccess = (VersionTypeAccess) toCompile;
VersionArgument va = typeAccess.getVersionArgument();

if (va instanceof VersionVarArgument) {
if (va.isVersionNumArgument()) {
access = typeAccess.getTypeAccess().compileAccess();
} else if (va.isVersionVarArgument()) {
Access makeCall = new MethodAccess("make", argList);
return new Dot(
new VarAccess(va.getID()),
makeCall);
}
}

return new ClassInstanceExpr(toCompile.compileAccess(), argList);
return new ClassInstanceExpr(access, argList);
}
*/

eq ClassInstanceExpr.compileExpr() {
Access toCompile = getAccess();
List<Expr> argList = new List();

if (toCompile.isParVersionTypeAccess()) {
TypeDecl compileType = program().typeMap
.get(new Integer(model().evaluate(getAccess().solverConst, false).toString()));
assert compileType.isGenericVersionClassDecl();
GenericVersionClassDecl compileClass = (GenericVersionClassDecl) compileType;

ParVersionTypeAccess typeAccess = (ParVersionTypeAccess) toCompile;

for (int i = 0; i < typeAccess.getNumVersionArgument(); i++) {
VersionArgument va = typeAccess.getVersionArgument(i);
VersionVariable vv = compileClass.getVersionVariable(i);
TypeAccess compileAccess = vv.typeAccess();
if (va.isVersionNumArgument()) {
argList = argList.add(new ClassInstanceExpr(
new TypeAccess(compileAccess.getPackage(), compileAccess.getID() + "_v" + va.getID() + "_Factory"),
new List()));
} else {
argList = argList.add(new VarAccess(va.getID()));
}
}

toCompile = typeAccess.getTypeAccess();
}

for (Expr arg: getArgList()) {
argList = argList.add(arg.compileExpr());
}

if (toCompile.isVersionTypeAccess()) {
VersionTypeAccess typeAccess = (VersionTypeAccess) toCompile;
VersionArgument va = typeAccess.getVersionArgument();
if (va.isVersionVarArgument()) {
return new Dot(new VarAccess(va.getID()), new MethodAccess("make", argList));
}
}

Access access = toCompile.compileInstanceAccess();

return new ClassInstanceExpr(access, argList);
}

eq AssignSimpleExpr.compileExpr()
Expand All @@ -571,7 +670,7 @@ aspect Generation {
List<ParameterDeclaration> params = new List();
List<Expr> argList = new List();

if (hostType() instanceof GenericVersionClassDecl) {
if (hostType().isGenericVersionClassDecl()) {
GenericVersionClassDecl host = (GenericVersionClassDecl) hostType();
for (int i = 0; i < host.getNumVersionVariable(); i++) {
VersionVariable v_i = host.getVersionVariable(i);
Expand Down Expand Up @@ -616,7 +715,7 @@ aspect Generation {
eq ConstructorDecl.compileInterfaceFactory() {
List<ParameterDeclaration> params = new List();

if (hostType() instanceof GenericVersionClassDecl) {
if (hostType().isGenericVersionClassDecl()) {
GenericVersionClassDecl host = (GenericVersionClassDecl) hostType();
for (int i = 0; i < host.getNumVersionVariable(); i++) {
VersionVariable v_i = host.getVersionVariable(i);
Expand Down Expand Up @@ -655,7 +754,9 @@ aspect Generation {
ps = ps.add(p.treeCopy());
}

List<Stmt> stmtList = new List().add(new ReturnStmt(new NullLiteral("null")));
List<Stmt> stmtList = type().isVoid()
? new List().add(new ReturnStmt())
: new List().add(new ReturnStmt(new NullLiteral("null")));

return new MethodDecl(
getModifiers(),
Expand Down
9 changes: 7 additions & 2 deletions batakjava/constraint/Generation.jrag
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@ aspect ConstraintVariable {
return Collections.singleton(solverConst);
}

public TypeDecl Expr.getSolution() {
assert solverConst != null;
return program().typeMap.get(new Integer(model().evaluate(solverConst, false).toString()));
}

}

aspect ConstraintGeneration {
Expand Down Expand Up @@ -171,8 +176,8 @@ aspect ConstraintGeneration {
eq ClassInstanceExpr.constraint() {
Formula f = new Formula();
// TODO: remove this temporary fix
if (getAccess() instanceof VersionTypeAccess &&
((VersionTypeAccess) getAccess()).getVersionArgument() instanceof VersionVarArgument) {
if (getAccess().isVersionTypeAccess() &&
((VersionTypeAccess) getAccess()).getVersionArgument().isVersionVarArgument()) {
return f;
}
for (TypeDecl type: typeSet()) {
Expand Down
2 changes: 1 addition & 1 deletion batakjava/frontend/InnerClasses.jrag
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ aspect InnerClassesBatak {

public boolean TypeDecl.hasLocalMethod(MethodDecl decl) {
for (BodyDecl b: getBodyDeclList()) {
if (b instanceof MethodDecl) {
if (b.isMethodDecl()) {
MethodDecl m = (MethodDecl) b;
if (m.signature().equals(decl.signature())) {
return true;
Expand Down
6 changes: 5 additions & 1 deletion batakjava/frontend/LookupMethod.jrag
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ aspect LookupMethod {

aspect MethodDecl {

syn boolean BodyDecl.isMethodDecl() = false;

eq MethodDecl.isMethodDecl() = true;

syn Optional<Formula> MethodAccess.verApplicableAndAccessible(MethodDecl m) {
if (m.getNumParameter() != getNumArg()) {
return Optional.empty();
Expand Down Expand Up @@ -57,7 +61,7 @@ aspect MemberMethods {
}
ArrayList<MethodDecl> methods = new ArrayList<MethodDecl>(getNumBodyDecl());
for (BodyDecl decl : getBodyDeclList()) {
if (decl instanceof MethodDecl) {
if (decl.isMethodDecl()) {
methods.add((MethodDecl) decl);
}
}
Expand Down
Loading

0 comments on commit c3ca5e6

Please sign in to comment.