Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

LambdaTransformer #40

Open
wants to merge 1 commit into
base: LambdaT
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/bin/
/target/
.gitignore
78 changes: 39 additions & 39 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -46,44 +46,44 @@
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>

<plugin>
<groupId>org.rascalmpl</groupId>
<artifactId>rascal-maven-plugin</artifactId>
<version>0.3.4</version>
<configuration>
<bin>${project.build.outputDirectory}</bin>
<errorsAsWarnings>true</errorsAsWarnings>
<enableStandardLibrary>true</enableStandardLibrary>
<srcs>
<src>${project.basedir}/src/main/rascal</src>
</srcs>
<srcIgnores>
<ignore>${project.basedir}/src/main/rascal/lang/jimple/toolkit/GraphUtil.rsc</ignore>
<ignore>${project.basedir}/src/main/rascal/lang/jimple/toolkit/CallGraph.rsc</ignore>
</srcIgnores>
</configuration>
<executions>
<execution>
<id>it-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>

</plugins>
<pluginManagement>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>

<plugin>
<groupId>org.rascalmpl</groupId>
<artifactId>rascal-maven-plugin</artifactId>
<version>0.3.4</version>
<configuration>
<bin>${project.build.outputDirectory}</bin>
<errorsAsWarnings>true</errorsAsWarnings>
<enableStandardLibrary>true</enableStandardLibrary>
<srcs>
<src>${project.basedir}/src/main/rascal</src>
</srcs>
<srcIgnores>
<ignore>${project.basedir}/src/main/rascal/lang/jimple/toolkit/GraphUtil.rsc</ignore>
<ignore>${project.basedir}/src/main/rascal/lang/jimple/toolkit/CallGraph.rsc</ignore>
</srcIgnores>
</configuration>
<executions>
<execution>
<id>it-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>

</project>
208 changes: 198 additions & 10 deletions src/main/rascal/lang/jimple/decompiler/jimplify/LambdaTransformer.rsc
Original file line number Diff line number Diff line change
@@ -1,28 +1,216 @@
module lang::jimple::decompiler::jimplify::LambdaTransformer

import lang::jimple::core::Syntax;
import lang::jimple::core::Syntax;

str bootstrapMethod = "bootstrap$";
import String;
import List;

alias CID = ClassOrInterfaceDeclaration;

str bootstrapMethod = "bootstrap$";

public list[ClassOrInterfaceDeclaration] lambdaTransformer(ClassOrInterfaceDeclaration c) {
list[ClassOrInterfaceDeclaration] classes = [];
list[ClassOrInterfaceDeclaration] classes = [];

c = visit(c) {
case dynamicInvoke(_, bsmArgs, sig, args)=> generateStaticInvokeExp(mh, sig, args)
when iValue(methodHandle(mh)):= bsmArgs[1]
c = visit(c) { //TODO: add LambdaMetafactory verification(in the indy's first argument)

//Accumulating Transformer: traverse the tree, collect information and also transform tree.
case dynamicInvoke(_, bsmArgs, sig, args): {
classes += generateBootstrapClass(bsmArgs, sig);
MethodSignature mh = methodSignature(bsmArgs[1]);
//iValue(methodHandle(mh)) := bsmArgs[1];
insert generateStaticInvokeExp(mh, sig, args);
}

}

classes += c;
return classes;
}

private InvokeExp generateStaticInvokeExp(MethodSignature sig1, MethodSignature sig2, list[Immediate] args) {
MethodSignature sig = methodSignature("<className(sig1)>$<methodName(sig1)>", returnType(sig2), bootstrapMethod, formals(sig2));

MethodSignature sig = methodSignature("<split("/", className(sig1))[1]>$<methodName(sig1)>", returnType(sig2), bootstrapMethod, formals(sig2));
return staticMethodInvoke(sig, args);
}
}

private CID generateBootstrapClass(list[Immediate] bsmArgs, MethodSignature bsmSig) {

MethodSignature targetSig = methodSignature(bsmArgs[1]);

str bsmClassName = "<last(split("/", className(targetSig)))>$<methodName(targetSig)>";

MethodSignature bootstrapSig = methodSignature(bsmClassName, TVoid(), "\<init\>", formals(bsmSig));

MethodSignature initSig = methodSignature("java.lang.Object", TVoid(), "\<init\>", []);

list[Type] classVars = formals(bsmSig);

list[Immediate] lambdaArgs = [];

//MethodBody local variable declarations
list[LocalVariableDeclaration] bsmLocals = generateLocalVarDecls(formals(bsmSig), 0) //instance attribute vars
+ generateLocalVarDecls([TObject(bsmClassName)], size(formals(bsmSig))); //thisClass var

list[LocalVariableDeclaration] initLocals = generateLocalVarDecls([TObject(bsmClassName)], 0) //thisClass var
+ generateLocalVarDecls(formals(bsmSig), 1); //instance attribute vars

// if the type is TObject("java.lang.Object"), jlO, we need to create local variables for type casting

list[Type] frm1 = valueFormals(bsmArgs[0]); //lambda signature formals
list[Type] frm2 = valueFormals(bsmArgs[2]); //erased signature formals (real types)
int numArgs = size(frm1);
int numCasts = 0;

for(i <- [0..size(frm1)]) {
if(frm1[i]!=frm2[i])
numCasts+=1;
}

list[LocalVariableDeclaration] targetLocals = generateLocalVarDecls([TObject(bsmClassName)], 0) //thisClass var
+ generateLocalVarDecls(valueFormals(bsmArgs[0]), 1); //method param vars (Object)
//variables for cast
if(numCasts>0)
targetLocals += generateLocalVarDecls(valueFormals(bsmArgs[2]), size(valueFormals(bsmArgs[0]))+1);

targetLocals += generateLocalVarDecls(formals(bsmSig), size(valueFormals(bsmArgs[0]))+numCasts+1); //instance attribute vars

//return var
if(returnType(targetSig) != TVoid())
targetLocals += [localVariableDeclaration(returnType(targetSig), "$i0")];

//MethodBody statements
//instantiation "fase"
list[Statement] bsmStmts = instantiateParameters(formals(bsmSig), 0)
+ [assign(localVariable("$r<size(formals(bsmSig))>"), newInstance(TObject(bsmClassName)))];

list[Statement] initStmts = [identity("$r0", "@this", TObject(bsmClassName))]
+ instantiateParameters(formals(bsmSig), 1);

list[Statement] targetStmts = [identity("$r0", "@this", TObject(bsmClassName))]
+ instantiateParameters(valueFormals(bsmArgs[0]), 1);

//BSM STATEMENTS
list[Immediate] bsmParams = [local(localVariable(decl))|decl <- prefix(bsmLocals)];

bsmStmts += invokeStmt(specialInvoke(localVariable(last(bsmLocals)), bootstrapSig, bsmParams));
bsmStmts += returnStmt(local(localVariable(last(bsmLocals))));

//INIT STATEMENTS
initStmts += invokeStmt(specialInvoke("$r0", initSig, []));
//fieldRef assignment
list[Immediate] initParams = [local(localVariable(decl))|decl <- tail(initLocals)];

for(int i <- [0..size(initParams)]) {
FieldSignature fieldSig = fieldSignature(bsmClassName, formals(bsmSig)[i], "cap<i>");
initStmts += assign(fieldRef("$r0", fieldSig), immediate(initParams[i]));
}

initStmts += returnEmptyStmt();
//TARGET STATEMENTS
//1st: casts
//for(int i <- [0..numCasts]) {
for(int i <- [0..size(valueFormals(bsmArgs[2]))]) {
if(numCasts>0)
targetStmts += assign(localVariable("$r<i+size(valueFormals(bsmArgs[0])+1)>"), cast(valueFormals(bsmArgs[2])[i], local("$r<i+1>")));
lambdaArgs += local("$r<i+numCasts+1>");
}

//2nd: localFieldRef : instance attributes (cap0,..)
for(int i <- [0..size(formals(bsmSig))]){
Expression lfr = localFieldRef("$r0", bsmClassName, formals(bsmSig)[i], "cap<i>");
targetStmts += assign(localVariable("$r<i+(numArgs+numCasts)+1>"), lfr);
lambdaArgs += local("$r<i+(numArgs+numCasts)+1>");
}

if(size(frm1)>0 && size(formals(bsmSig))>0)
lambdaArgs=reverse(lambdaArgs);

//invoke (staticinvoke) lambdaMethod
if(returnType(methodSignature(bsmArgs[1]))==TVoid()){
targetStmts += invokeStmt(staticMethodInvoke(methodSignature(bsmArgs[1]), lambdaArgs));
targetStmts += returnEmptyStmt();
} else {
targetStmts += assign(localVariable("$i0"), invokeExp(staticMethodInvoke(methodSignature(bsmArgs[1]), lambdaArgs)));
targetStmts += returnStmt(local("$i0"));
}

//Method bodies
MethodBody bsmBody = methodBody(bsmLocals, bsmStmts, []);
MethodBody initBody = methodBody(initLocals, initStmts, []);
MethodBody targetBody = methodBody(targetLocals, targetStmts, []);

//Methods
Method bsm = method([Public(), Static()], // list[Modifiers] modifiers
returnType(bsmSig), // Type returnType
"bootstrap$", // Name name
formals(bsmSig), // list[Type] formals
[], // list[Type] exceptions //TODO!
bsmBody); // MethodBody body

Method initMethod = method([Public(), Static()],
TVoid(),
"\<init\>",
formals(bsmSig),
[],
initBody);


Method targetMethod = method([Public(), Static()],
returnType(targetSig),
methodName(bsmSig),
valueFormals(bsmArgs[0]),
[],
targetBody);


CID bsmClass = classDecl(TObject(bsmClassName), // Type typeName
[Public(), Final()], // list[Modifiers] modifiers
object(), // Type superClass
[returnType(bsmSig)], // list[Type] interfaces
getFields(bsmSig), // list[Fields] fields
[bsm, initMethod, targetMethod]); // list[Method] methods

return bsmClass;
}

list[Field] getFields(MethodSignature sig){
list[Field] fields = [];

for(int i <- [0..size(formals(sig))]){
fields += field([], formals(sig)[i], "cap<i>");
}

return fields;
}

list[LocalVariableDeclaration] generateLocalVarDecls(list[Type] frmls, int n){
list[LocalVariableDeclaration] localVarDecls = [];

for(int i <- [0..size(frmls)]){
localVarDecls += localVariableDeclaration(frmls[i], "$r<i+n>");
}

return localVarDecls;
}

list[Statement] instantiateParameters(list[Type] frmls, int n){
list[Statement] stmts = [];

for(int i <- [0..size(frmls)]){
stmts += identity("$r<i+n>", "@parameter<i>", frmls[i]);
}

return stmts;
}


private str className(methodSignature(name, _, _, _)) = name;
private str methodName(methodSignature(_, _, name,_)) = name;
private Type returnType(methodSignature(_, aType, _, _)) = aType;
private list[Type] formals(methodSignature(_, _, _, formalArgs)) = formalArgs;
private list[Type] valueFormals(iValue(methodValue(_, formalArgs))) = formalArgs;
private MethodSignature methodSignature(iValue(methodHandle(mh))) = mh;
private Identifier localVariable(localVariableDeclaration(_, local)) = local;



23 changes: 12 additions & 11 deletions src/test/java/samples/arrays/ArrayExample.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,25 @@

public class ArrayExample {

public static void main(String[] args) throws Exception {
List<Integer> nums = Arrays.asList(-3, 0, 1, 8);
public static void main(String[] args) throws Exception {
List<Integer> nums = Arrays.asList(-3, 0, 1, 8);

Runnable r = () -> nums.forEach(n -> {
Runnable r = () -> nums.forEach(n -> {

if (n < 0) System.out.println("Negative: " + n);
if (n < 0)
System.out.println("Negative: " + n);

else System.out.println("Positive: " + n);
else
System.out.println("Positive: " + n);

});
});

Thread t = new Thread(r);
Thread t = new Thread(r);

t.start();
t.start();

t.join();
t.join();

}
}

}

14 changes: 14 additions & 0 deletions src/test/java/samples/lambdaExpressions/AddLambda.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package samples.lambdaExpressions;

interface Addable {
int add(int a, int b);
}

public class AddLambda {
public static void main(String[] args) {

Addable sum = (a, b) -> (a + b);

System.out.println(sum.add(1, 2));
}
}
15 changes: 15 additions & 0 deletions src/test/java/samples/lambdaExpressions/IncClosure.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package samples.lambdaExpressions;

interface Incrementable {
int inc(int a);
}

public class IncClosure {
public static void main(String[] args) {
int i = 1;

Incrementable incBy = (a) -> (a+i);

System.out.println(incBy.inc(1));
}
}
Loading