Skip to content

Commit

Permalink
codegen for accumulator
Browse files Browse the repository at this point in the history
  • Loading branch information
PtrMan committed Dec 11, 2015
1 parent 158d193 commit be1392b
Show file tree
Hide file tree
Showing 7 changed files with 204 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,11 @@ public enum EnumType {
COMPARISION_EQUAL,
COMPARISION_NOTEQUAL,

/*
OPERATION_SUBTRACTION,
OPERATION_ADDITION,
OPERATION_MULTIPLICATION,
OPERATION_DIVISION,
OPERATION_DIVISION,*/

NIL,

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@
import ptrman.causalReasoningSystem.functional.language.ast.Element;
import ptrman.causalReasoningSystem.functional.language.ast.Type;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javassist.CtClass;
import ptrman.causalReasoningSystem.functional.language.runtime.ResultAndControlflowPropagationInfo;

/**
*
Expand All @@ -23,8 +26,15 @@
*/
// Inline : returns directly the code, without wrapping in an extrafunction
public class CodegenJava {
private enum EnumMathematicalAccumulatorInitialValue {
ONE,
ZERO
}

private final CtClass ctClass;



public CodegenJava(CtClass classTemplate) {
this.ctClass = classTemplate;
}
Expand All @@ -44,15 +54,118 @@ private InlinedResultCodeWithType generateFunctionByStaticTypesInternalFunctionW
return generateBodyForwardPass(astBody, typeinfoOfVariables);
}

private InlinedResultCodeWithType generateBodyForwardPass(Element astElement, Map<String, Typeinfo> typeinfoOfVariables) throws CannotCompileException {
// public for testing
public InlinedResultCodeWithType generateBodyForwardPass(Element astElement, Map<String, Typeinfo> typeinfoOfVariables) throws CannotCompileException {
if( astElement.type.isEqualWithType(new Type(Type.EnumType.COND)) ) {
return generateBodyForwardPassForCondition(astElement, typeinfoOfVariables);
}
else if( astElement.type.isEqualWithType(new Type(Type.EnumType.FUNCTION_CALL))) {
if( astElement.identifier == null ) {
if( astElement.callType == Element.EnumCallType.ADD ) {
return generateBodyForwardPassForMathematicalAccumulatorOperation("+", EnumMathematicalAccumulatorInitialValue.ZERO, astElement, typeinfoOfVariables);
}
else if( astElement.callType == Element.EnumCallType.SUB ) {
return generateBodyForwardPassForMathematicalAccumulatorOperation("-", EnumMathematicalAccumulatorInitialValue.ZERO, astElement, typeinfoOfVariables);
}
else if( astElement.callType == Element.EnumCallType.MUL ) {
return generateBodyForwardPassForMathematicalAccumulatorOperation("*", EnumMathematicalAccumulatorInitialValue.ONE, astElement, typeinfoOfVariables);
}
else if( astElement.callType == Element.EnumCallType.DIV ) {
return generateBodyForwardPassForMathematicalAccumulatorOperation("/", EnumMathematicalAccumulatorInitialValue.ONE, astElement, typeinfoOfVariables);
}
else {
throw new RuntimeException("Internal Error!");
}
}
else {
throw new RuntimeException("TODO< generate code for call of function >");
}
}
else if( astElement.type.isEqualWithType(new Type(Type.EnumType.CONSTANT_INTEGER)) ) {
return generateBodyForwardPassForIntegerConstant(astElement, typeinfoOfVariables);
}
else {
throw new RuntimeException("Internal Error!");
}
}

private InlinedResultCodeWithType generateBodyForwardPassForMathematicalAccumulatorOperation(String operationString, EnumMathematicalAccumulatorInitialValue accumulatorInitialValue, Element astElement, Map<String, Typeinfo> typeinfoOfVariables) throws CannotCompileException {
/*assert
astElement.type.isEqualWithType(new Type(Type.EnumType.OPERATION_ADDITION)) ||
astElement.type.isEqualWithType(new Type(Type.EnumType.OPERATION_SUBTRACTION)) ||
astElement.type.isEqualWithType(new Type(Type.EnumType.OPERATION_MULTIPLICATION)) ||
astElement.type.isEqualWithType(new Type(Type.EnumType.OPERATION_DIVISION));*/

StringBuilder resultCodeBuilder = new StringBuilder();

final List<InlinedResultCodeWithType> inlinedResultCodeForArguments = inlineResultCodeForAllArguments(astElement, typeinfoOfVariables);
final List<Typeinfo> typesOfArguments = getTypesOfInlinedResultCodeWithType(inlinedResultCodeForArguments);
final Typeinfo resultType = getMergedTypes(typesOfArguments);

resultCodeBuilder.append("// codegen: initial value\n");
resultCodeBuilder.append(String.format("%s iterationResult = (%s)%s;\n", resultType.getJavaTypeString(), resultType.getJavaTypeString(), getJavaStringOfAccumulatorInitialValue(accumulatorInitialValue)));
resultCodeBuilder.append("\n");
resultCodeBuilder.append("\n");

resultCodeBuilder.append("// codegen: accumulation\n");
for( int argumentI = 0; argumentI < astElement.children.size(); argumentI++ ) {
// the generated code accumulates over the accumulator
// for the extraction of the value we call into a static method of the runtime which either extracts the typed value or converts the result value to the type
resultCodeBuilder.append(String.format("iterationResult %s= %s.%s(%s);\n", operationString, RUNTIME_CLASS_FOR_TYPECONVERSATION, getJavaFunctionnameForConversationOrExtractionOfResultOfType(resultType, typesOfArguments.get(argumentI)), getJavaFunctioncallForFunction(inlinedResultCodeForArguments.get(argumentI).functionInfo)));
}
resultCodeBuilder.append("\n");
resultCodeBuilder.append("\n");

resultCodeBuilder.append(String.format("result = %s.%s(iterationResult);\n", RESULT_AND_PROPAGATION_TYPENAME, ResultAndControlflowPropagationInfo.codegenGetJavaFunctionnameForCreationOfType(resultType)));

final String resultCode = resultCodeBuilder.toString();
GeneratedFunctionInfo generatedFunctionInfo = emitInternalFunction(resultType, resultCode);

return new InlinedResultCodeWithType(resultType, generatedFunctionInfo);
}

private String getJavaStringOfAccumulatorInitialValue(EnumMathematicalAccumulatorInitialValue accumulatorInitialValue) {
if( accumulatorInitialValue == EnumMathematicalAccumulatorInitialValue.ONE ) {
return "1";
}
else {
return "0";
}
}

private String getJavaFunctionnameForConversationOrExtractionOfResultOfType(Typeinfo resultType, Typeinfo sourceType) {
if (resultType.type == Typeinfo.EnumType.INTEGER && sourceType.type == Typeinfo.EnumType.INTEGER) {
return "passThroughInteger";
}
/*
else if (resultType.type == Typeinfo.EnumType.BOOLEAN && sourceType.type == Typeinfo.EnumType.BOOLEAN) {
return "passThroughBoolean";
}
*/
throw new RuntimeException("Internal error: Couldn't find out the Runtime method to pass or convert type to javatype!");
}

private List<Typeinfo> getTypesOfInlinedResultCodeWithType(List<InlinedResultCodeWithType> functionsWithTypes) {
List<Typeinfo> result = new ArrayList<>();

for( InlinedResultCodeWithType iterationGeneratedFunctionWithType : functionsWithTypes ) {
result.add(iterationGeneratedFunctionWithType.returnType);
}

return result;
}

private List<InlinedResultCodeWithType> inlineResultCodeForAllArguments(Element astElement, Map<String, Typeinfo> typeinfoOfVariables) throws CannotCompileException {
List<InlinedResultCodeWithType> inlinedResultForArguments = new ArrayList<>();
for( ptrman.causalReasoningSystem.functional.tree.Element iterationChildren : astElement.children ) {
Element castedIterationChildren = (Element)iterationChildren;

inlinedResultForArguments.add(generateBodyForwardPass(castedIterationChildren, typeinfoOfVariables));
}

return inlinedResultForArguments;
}

private InlinedResultCodeWithType generateBodyForwardPassForCondition(Element condition, Map<String, Typeinfo> typeinfoOfVariables) throws CannotCompileException {
assert condition.type.isEqualWithType(new Type(Type.EnumType.COND));

Expand All @@ -70,45 +183,58 @@ private InlinedResultCodeWithType generateBodyForwardPassForCondition(Element co
throw new RuntimeException("Compilation error, condition has to be boolean!");
}

String resultCode = "";
//functionCode += "" + resultType.getJavaTypeString() + " result;\n";
resultCode += "boolean condition = " + getFunctionnameForInternalFunction(inlinedCheck.functionInfo) + "();" + "\n";
resultCode += "if (condition) {\n";
resultCode += " result = " + getFunctionnameForInternalFunction(inlinedTruePath.functionInfo) + "();\n";
resultCode += "}\n";
resultCode += "else {\n";
resultCode += " result = " + getFunctionnameForInternalFunction(inlinedFalsePath.functionInfo) + "();\n";
resultCode += "}\n";
StringBuilder resultCodeBuilder = new StringBuilder();

resultCodeBuilder.append(String.format("boolean condition = %s;\n", getJavaFunctioncallForFunction(inlinedCheck.functionInfo)));
resultCodeBuilder.append( "if (condition) {\n");
resultCodeBuilder.append(String.format(" result = %s;\n", getJavaFunctioncallForFunction(inlinedTruePath.functionInfo)));
resultCodeBuilder.append( "}\n");
resultCodeBuilder.append( "else {\n");
resultCodeBuilder.append(String.format(" result = %s;\n", getJavaFunctioncallForFunction(inlinedFalsePath.functionInfo)));
resultCodeBuilder.append( "}\n");

final String resultCode = resultCodeBuilder.toString();
GeneratedFunctionInfo generatedFunctionInfo = emitInternalFunction(resultType, resultCode);

return new InlinedResultCodeWithType(resultType, generatedFunctionInfo);
}

// for testing public
public InlinedResultCodeWithType generateBodyForwardPassForIntegerConstant(Element constant, Map<String, Typeinfo> typeinfoOfVariables) throws CannotCompileException {
private InlinedResultCodeWithType generateBodyForwardPassForIntegerConstant(Element constant, Map<String, Typeinfo> typeinfoOfVariables) throws CannotCompileException {
assert constant.type.isEqualWithType(new Type(Type.EnumType.CONSTANT_INTEGER));

final Typeinfo resultType = new Typeinfo(Typeinfo.EnumType.INTEGER);

String resultCode = String.format("result = %s.createResultForConstantInteger(%d);\n", RESULT_AND_PROPAGATION_TYPENAME, constant.constantInteger);
String resultCode = String.format("result = %s.%s(%d);\n", RESULT_AND_PROPAGATION_TYPENAME, ResultAndControlflowPropagationInfo.codegenGetJavaFunctionnameForCreationOfType(resultType), constant.constantInteger);

GeneratedFunctionInfo generatedFunctionInfo = emitInternalFunction(resultType, resultCode);

return new InlinedResultCodeWithType(resultType, generatedFunctionInfo);
}


/*private static InlinedResultCodeWithType mergeInlinedResultCode(final InlinedResultCodeWithType a, final InlinedResultCodeWithType b) {
}*/


private String getJavaFunctioncallForFunction(GeneratedFunctionInfo functionInfo) {
// TODO< parameters >
return functionInfo.getInternalFunctionname() + "()";
}


/**
* generates the final java code for a javafunction
* A javafunction is generated for each Expression of the functional AST
*
*/
private GeneratedFunctionInfo emitInternalFunction(Typeinfo typeinfo, String code) throws CannotCompileException {
GeneratedFunctionInfo generatedFunctionInfo = new GeneratedFunctionInfo(functionInternalNumberCounter);

StringBuilder functionCodeBuilder = new StringBuilder();

// for now public for debugging, later private
functionCodeBuilder.append(String.format("public static %s %s() {\n", RESULT_AND_PROPAGATION_TYPENAME, getFunctionnameForInternalFunction(generatedFunctionInfo)));
functionCodeBuilder.append(String.format("public static %s %s() {\n", RESULT_AND_PROPAGATION_TYPENAME, generatedFunctionInfo.getInternalFunctionname()));

functionCodeBuilder.append("// codegen: result allocation\n");
functionCodeBuilder.append(RESULT_AND_PROPAGATION_TYPENAME + " result;\n");
Expand Down Expand Up @@ -143,6 +269,20 @@ private GeneratedFunctionInfo emitInternalFunction(Typeinfo typeinfo, String cod

private int functionInternalNumberCounter = 0;

private static Typeinfo getMergedTypes(final List<Typeinfo> types) {
Typeinfo resultType = types.get(0);

if( types.size() <= 1 ) {
return resultType;
}

for( int i = 1; i < types.size(); i++ ) {
resultType = getMergedTypes(resultType, types.get(i));
}

return resultType;
}

private static Typeinfo getMergedTypes(final Typeinfo a, final Typeinfo b) {
if( a.type == b.type ) {
return a;
Expand All @@ -152,10 +292,7 @@ private static Typeinfo getMergedTypes(final Typeinfo a, final Typeinfo b) {
throw new RuntimeException("Codegen Error: Can't merge types!");
}

private static String getFunctionnameForInternalFunction(GeneratedFunctionInfo functionInfo) {
return functionInfo.getInternalFunctionname();
}

private final static String RESULT_AND_PROPAGATION_TYPENAME = "ResultAndControlflowPropagationInfo";
private final static String RUNTIME_CLASS_FOR_TYPECONVERSATION = "TypeConversation";

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ public static Element convert(ParseTreeElement root) {
result.identifier = convertedRoot.identifier;
return result;
}
else if( root instanceof BasicIntegerParseTreeElement ) {
BasicIntegerParseTreeElement convertedRoot = (BasicIntegerParseTreeElement) root;

Element result = new Element(new Type(Type.EnumType.CONSTANT_INTEGER));
result.constantInteger = Integer.parseInt(convertedRoot.constant);
return result;
}

else if( root instanceof HasChildrenParseTreeElement ) {
HasChildrenParseTreeElement convertedRoot = (HasChildrenParseTreeElement)root;

Expand Down Expand Up @@ -70,7 +78,10 @@ else if( convertedRoot.type == HasChildrenParseTreeElement.EnumType.CONSTANT_INT
result.constantInteger = Integer.parseInt(constantParseTreeElement.constant);
return result;
}

else if( convertedRoot.type == HasChildrenParseTreeElement.EnumType.VARIABLE_OR_CONSTANT_OR_STANDARD_CALL_BRACES ) {
// simplfy it
return convert(convertedRoot.children[0]);
}
else {
throw new RuntimeException("Internal Error!");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Rule variableOrConstantOrStandardCallBraces() {
return firstOf(
sequence(standardCallBraces(), push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.VARIABLE_OR_CONSTANT_OR_STANDARD_CALL_BRACES, new ParseTreeElement[]{pop()}))),
sequence(variable(), push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.VARIABLE_OR_CONSTANT_OR_STANDARD_CALL_BRACES, new ParseTreeElement[]{pop()}))),
sequence(integer(), push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.CONSTANT_INTEGER, new ParseTreeElement[]{pop()})))
sequence(integer(), push(new HasChildrenParseTreeElement(HasChildrenParseTreeElement.EnumType.VARIABLE_OR_CONSTANT_OR_STANDARD_CALL_BRACES, new ParseTreeElement[]{pop()})))
);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,28 @@
package ptrman.causalReasoningSystem.functional.language.runtime;

import ptrman.causalReasoningSystem.functional.language.codegen.Typeinfo;

/**
* Created by r0b3 on 11.12.2015.
* Used by the generated code to propagate results and controlflow information
*
*/
class ResultAndControlflowPropagationInfo {
public class ResultAndControlflowPropagationInfo {
int resultInteger;

// called from generated code
public static ResultAndControlflowPropagationInfo createResultForConstantInteger(final int value) {
ResultAndControlflowPropagationInfo result = new ResultAndControlflowPropagationInfo();
result.resultInteger = value;
return result;
}

// used by codegeneration
public static String codegenGetJavaFunctionnameForCreationOfType(Typeinfo typeinfo) {
if( typeinfo.type == Typeinfo.EnumType.INTEGER ) {
return "createResultForConstantInteger";
}

throw new RuntimeException("Internal Error: No function for Static Runtime found to create value of type!");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package ptrman.causalReasoningSystem.functional.language.runtime;

/**
* Used by the generated code to extract values or convert results from one type to another
*/
public class TypeConversation {
public static int passThroughInteger(ResultAndControlflowPropagationInfo data) {
return data.resultInteger;
}

/*
public static int passThroughBoolean(ResultAndControlflowPropagationInfo data) {
return data.resultBoolean;
}
*/
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ public static void main(String[] args) {
CtClass class0 = ctPool.makeClass("GeneratedCode");


ParseTreeElement parseTree = Parse.parse("5");
ParseTreeElement parseTree = Parse.parse("(+ 5 4)");
Element ast = ConvertParseTreeToAst.convert(parseTree);


CodegenJava codegen = new CodegenJava(class0);
try {
codegen.generateBodyForwardPassForIntegerConstant(ast, new HashMap<>());
codegen.generateBodyForwardPass(ast, new HashMap<>());
} catch (CannotCompileException e) {
e.printStackTrace();
}
Expand Down

0 comments on commit be1392b

Please sign in to comment.