Skip to content

Commit

Permalink
basic instrumentation works:
Browse files Browse the repository at this point in the history
issue #58 : #58
  • Loading branch information
miho committed Aug 4, 2015
1 parent e3d4d0f commit 475fbfc
Show file tree
Hide file tree
Showing 3 changed files with 138 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@
*/
package eu.mihosoft.vrl.lang.model.transform;

import eu.mihosoft.vrl.instrumentation.VRLInstrumentationUtil;
import eu.mihosoft.vrl.lang.model.Argument;
import eu.mihosoft.vrl.lang.model.ClassDeclaration;
import eu.mihosoft.vrl.lang.model.CompilationUnitDeclaration;
import eu.mihosoft.vrl.lang.model.ControlFlow;
import eu.mihosoft.vrl.lang.model.ControlFlowScope;
import eu.mihosoft.vrl.lang.model.IArgument;
import eu.mihosoft.vrl.lang.model.Invocation;
import eu.mihosoft.vrl.lang.model.MethodDeclaration;
import eu.mihosoft.vrl.lang.model.Scope2Code;
import eu.mihosoft.vrl.lang.model.Operator;
import eu.mihosoft.vrl.lang.model.ScopeInvocation;
import eu.mihosoft.vrl.lang.model.Type;
import eu.mihosoft.vrl.lang.model.Variable;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
*
Expand All @@ -26,67 +30,117 @@ public class InstrumentCode implements CodeTransform<CompilationUnitDeclaration>
@Override
public CompilationUnitDeclaration transform(CompilationUnitDeclaration cu) {
// TODO 01.08.2015 add clone()

CompilationUnitDeclaration result = cu;

InstrumentControlFlowScope im = new InstrumentControlFlowScope();
for(ClassDeclaration cd : result.getDeclaredClasses()) {

for (ClassDeclaration cd : result.getDeclaredClasses()) {
List<MethodDeclaration> methods = new ArrayList<>();
for(MethodDeclaration md : cd.getDeclaredMethods()) {
methods.add((MethodDeclaration)im.transform(md));
for (MethodDeclaration md : cd.getDeclaredMethods()) {
methods.add((MethodDeclaration) im.transform(md));
}
cd.getDeclaredMethods().clear();
cd.getDeclaredMethods().addAll(methods);
}

System.out.println(Scope2Code.getCode(cu));


return result;
}
}

class InstrumentControlFlowScope implements CodeTransform<ControlFlowScope> {

int varNameCounter = 0;

private String newVarName() {
return "__vrl_reserved_intermediate_var_" + ++varNameCounter;
}

@Override
public ControlFlowScope transform(ControlFlowScope ce) {
// TODO 01.08.2015 add clone()


ControlFlowScope result = ce;

List<Invocation> invocations = new ArrayList<>();
invocations.addAll(ce.getControlFlow().getInvocations());

result.getControlFlow().getInvocations().clear();

for(Invocation i : invocations) {
System.out.println("i : " + i);
result.getControlFlow().callMethod(
"", "this", "println", Type.VOID,
Argument.constArg(
Type.STRING, "pre-m-call: " + i.toString()));
result.getControlFlow().getInvocations().add(i);
result.getControlFlow().callMethod(
"", "this", "println", Type.VOID,
Argument.constArg(
Type.STRING, "post-m-call: " + i.toString()));
if (i instanceof ScopeInvocation) {
ScopeInvocation si = (ScopeInvocation) i;

ControlFlow cf = result.getControlFlow();

for (int i = 0; i < invocations.size(); i++) {

Invocation inv = invocations.get(i);

System.out.println("i : " + inv);

String varName = newVarName();

// cf.declareVariable("", Type.STRING, varName+"_pre_arg");
// Variable rightArgVariable = ce.getVariable(varName+"_pre_arg");
// Invocation preArgInv = cf.invokeOperator("",
// Argument.constArg(Type.STRING, "pre-m-call: " + inv.getMethodName() + ", args: "),
// Argument.varArg(result.getVariable(varName)), Operator.PLUS);
// cf.assignVariable("", rightArgVariable.getName(), Argument.invArg(preArgInv));


Invocation preEventInv
= cf.callMethod("", "this", "println", Type.VOID, Argument.constArg(
Type.STRING, "pre-m-call: " + inv.getMethodName()));

boolean lastInvocation = i == invocations.size() - 1;

IArgument retValArg = Argument.NULL;

if (!lastInvocation) {
Invocation nextI = invocations.get(i + 1);

boolean iIsArgOfNextI = nextI.getArguments().stream().
filter(a -> Objects.equals(a.getInvocation().orElse(null), inv)).
findAny().isPresent();

if (iIsArgOfNextI) {

cf.declareVariable("", inv.getReturnType(), varName);
cf.assignVariable("", varName, Argument.invArg(inv));

int[] argumentsToReplace = nextI.getArguments().stream().
filter(a -> Objects.equals(a.getInvocation().orElse(null), inv)).
mapToInt(a -> nextI.getArguments().indexOf(a)).toArray();

for (int aIndex : argumentsToReplace) {
nextI.getArguments().set(aIndex,
Argument.varArg(result.getVariable(varName)));
}

cf.declareVariable("", Type.STRING, varName+"_post_arg");
Variable rightArgVariable = ce.getVariable(varName+"_post_arg");
Invocation retValPostArgInv = cf.invokeOperator("",
Argument.constArg(Type.STRING, "post-m-call: " + inv.getMethodName() + ", retVal: "),
Argument.varArg(result.getVariable(varName)), Operator.PLUS);
cf.assignVariable("", rightArgVariable.getName(), Argument.invArg(retValPostArgInv));

retValArg = Argument.varArg(rightArgVariable);
}
}

cf.getInvocations().add(inv);
if (Objects.equals(retValArg, Argument.NULL)) {
cf.callMethod("", "this", "println", Type.VOID, Argument.constArg(
Type.STRING, "post-m-call: " + inv.getMethodName()));
} else {
cf.callMethod("", "this", "println", Type.VOID, retValArg);
}

if (inv instanceof ScopeInvocation) {
ScopeInvocation si = (ScopeInvocation) inv;
transform((ControlFlowScope) si.getScope());
}

}

// for(Invocation i : invocations) {
// System.out.println("i : " + i);
//
// result.getControlFlow().callStaticMethod("",
// Type.fromClass(VRLInstrumentationUtil.class),
// "__instrumentCode", i.getMethodName(),
// i.getArguments().toArray(new IArgument[i.getArguments().size()]));
// }


return result;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,14 @@
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.logging.Level;
import java.util.logging.Logger;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import junit.framework.Assert;
import org.codehaus.groovy.control.CompilationFailedException;
import org.junit.Test;
import org.objenesis.instantiator.ObjectInstantiator;

Expand All @@ -54,11 +56,10 @@ public static String getResourceAsString(String resourceName) {
return tmpCode;
}


@Test
public void instrumentationTest() {

String fileName = "IfCode01.groovy";
String fileName = "Instrumentation01.groovy";

String code = getResourceAsString(fileName);

Expand Down Expand Up @@ -97,6 +98,19 @@ public void instrumentationTest() {

CompilationUnitDeclaration newCu = instrumentCode.transform(cu);

System.out.println(Scope2Code.getCode(newCu));
String instrumentedCode = Scope2Code.getCode(newCu);

System.out.println(instrumentedCode);


try {
GroovyClassLoader gcl = new GroovyClassLoader();
Class<?> instrumentedCodeClass = gcl.parseClass(instrumentedCode);
instrumentedCodeClass.getMethod("main", String[].class).
invoke(instrumentedCodeClass, (Object)new String[0]);

} catch (CompilationFailedException | NoSuchMethodException | SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
Logger.getLogger(LangModelTest.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/* global comment*/

package my.testpackage;

/**
* class MyFileClass
*/
@eu.mihosoft.vrl.instrumentation.VRLVisualization
public class MyFileClass {

public MyFileClass() {
}

public MyFileClass(int param1, int param2) {
}

public static void main(String[] args) {

int a = 2+3*2;
int b = 5-a;

//MyFileClass mfc = new MyFileClass(a,b+1);

if (a<b) {
println("a<b: " + (a < b));
}
}
}

0 comments on commit 475fbfc

Please sign in to comment.