/******************************************************************************* | |
* Copyright (c) 2004-2008 Gabor Bergmann and Daniel Varro | |
* All rights reserved. This program and the accompanying materials | |
* are made available under the terms of the Eclipse Public License v1.0 | |
* which accompanies this distribution, and is available at | |
* http://www.eclipse.org/legal/epl-v10.html | |
* | |
* Contributors: | |
* Gabor Bergmann - initial API and implementation | |
*******************************************************************************/ | |
package org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.construction; | |
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.tuple.FlatTuple; | |
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.tuple.LeftInheritanceTuple; | |
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.tuple.Tuple; | |
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.tuple.TupleMask; | |
import org.eclipse.viatra2.gtasm.patternmatcher.incremental.rete.util.Options; | |
/** | |
* Lightweight class that generates Java code of a builder method from the build actions. | |
* Code is sent to a coordinator to be collected in string buffers there. | |
* @author Bergmann Gábor | |
*/ | |
public abstract class CodegenRecorderBuildable<PatternDescription> | |
implements Buildable<PatternDescription, String, String> | |
{ | |
public CodegenRecordingCoordinator<PatternDescription> coordinator; | |
public PatternDescription effort; | |
public String myName; | |
public String baseName; | |
public String indent; | |
/** | |
* @param code | |
* @param indent | |
* @param myName | |
*/ | |
public CodegenRecorderBuildable(CodegenRecordingCoordinator<PatternDescription> coordinator, | |
PatternDescription effort, String indent, String baseName, String instanceSuffix) | |
{ | |
super(); | |
this.coordinator = coordinator; | |
this.effort = effort; | |
this.indent = indent; | |
this.baseName = baseName; | |
this.myName = baseName+instanceSuffix; | |
} | |
public void reinitialize() { | |
throw new UnsupportedOperationException(); | |
} | |
protected String prettyPrintStringArray(String[] elements, String separator) { | |
if (elements.length == 0) return ""; | |
else { | |
StringBuilder result = new StringBuilder(elements[0]); | |
for (int i=1; i<elements.length; ++i) { | |
result.append(", "); | |
result.append(elements[i]); | |
} | |
return result.toString(); | |
} | |
} | |
protected String prettyPrintStringArray(String[] elements) { | |
return prettyPrintStringArray(elements, ", "); | |
} | |
protected String prettyPrintIntArray(int[] elements, String separator) { | |
if (elements.length == 0) return ""; | |
else { | |
StringBuilder result = new StringBuilder(); | |
result.append(elements[0]); | |
for (int i=1; i<elements.length; ++i) { | |
result.append(", "); | |
result.append(elements[i]); | |
} | |
return result.toString(); | |
} | |
} | |
protected String prettyPrintIntArray(int[] elements) { | |
return prettyPrintIntArray(elements, ", "); | |
} | |
protected String prettyPrintObjectArray(Object[] elements, String separator, boolean strict) { | |
if (elements.length == 0) return ""; | |
else { | |
StringBuilder result = new StringBuilder(gen(elements[0], strict)); | |
for (int i=1; i<elements.length; ++i) { | |
result.append(separator); | |
result.append(gen(elements[i], strict)); | |
} | |
return result.toString(); | |
} | |
} | |
protected String prettyPrintObjectArray(Object[] constantValues, boolean strict) { | |
return prettyPrintObjectArray(constantValues, ", ", strict); | |
} | |
protected void emitLine(String line) { | |
coordinator.emitPatternBuilderLine(effort, indent, line); | |
} | |
protected String call(String methodName, String arguments) { | |
return(myName+"."+methodName+"("+arguments+")"); | |
} | |
protected String call(String methodName, String[] arguments) { | |
return call(methodName, prettyPrintStringArray(arguments)); | |
} | |
protected String emitFunctionCall(String resultType, String methodName, String arguments) { | |
return declareNewValue(resultType, call(methodName, arguments)); | |
} | |
protected String emitFunctionCall(String resultType, String methodName, String[] arguments) { | |
return declareNewValue(resultType, call(methodName, arguments)); | |
} | |
protected void emitProcedureCall(String methodName, String arguments) { | |
emitLine(call(methodName, arguments)+";"); | |
} | |
protected void emitProcedureCall(String methodName, String[] arguments) { | |
emitLine(call(methodName, arguments)+";"); | |
} | |
protected void declareNew(String type, String identifier, String value, boolean isFinal) { | |
emitLine((isFinal ? "final " : "") + type + " " + identifier + " = " + value + ";"); | |
} | |
protected String declareNewValue(String type, String value) { | |
String name = coordinator.newVariableIdentifier(); | |
declareNew(type, name, value, true); | |
return name; | |
} | |
protected String declareNewBuildable(String value) { | |
String name = coordinator.newBuildableIdentifier(); | |
declareNew(coordinator.buildableType, name, value, true); | |
return name; | |
} | |
protected String gen(Stub<String> stub) { | |
return stub.getHandle(); | |
} | |
protected String gen(boolean bool) { | |
return bool? "true": "false"; | |
} | |
protected String gen(Integer integer) { | |
return integer == null ? "null" : integer.toString(); | |
} | |
protected String gen(int[] ints) { | |
// return declareNewValue("int[]", "{"+prettyPrintIntArray(ints)+"}"); | |
return "new int[] {" + prettyPrintIntArray(ints) + "}"; | |
} | |
protected String gen(TupleMask mask) { | |
return declareNewValue("TupleMask", "new TupleMask("+gen(mask.indices)+", " + gen(mask.sourceWidth)+ ")"); | |
} | |
protected String gen(Object o, boolean strict) { | |
if (o instanceof Number) return o.toString(); | |
if (o instanceof String) return "\"" + o.toString() + "\""; | |
if (!strict) return "\"" + o.toString() + "\""; | |
throw new UnsupportedOperationException( | |
"Cannot currently generate code from an " + o.getClass() + " instance: " + o.toString()); | |
} | |
protected String gen(Object[] o, boolean strict) { | |
// return declareNewValue("Object[]", "{"+prettyPrintObjectArray(o, strict)+"}"); | |
return "new Object[] {" + prettyPrintObjectArray(o, strict) + "}"; | |
} | |
protected String gen(Tuple tuple, boolean strict) { | |
return "new FlatTuple(" + gen(tuple.getElements(), strict) + ")"; | |
} | |
public String genCalibrationElement(Object calibrationElement) { | |
return gen(calibrationElement, false);//calibrationElement.toString(); | |
} | |
// public String genUnaryType(Object type) { | |
// return type==null? "null" : "context.retrieveUnaryType(\"" + coordinator.targetContext.retrieveUnaryTypeFQN(type) + "\")"; | |
// } | |
// | |
// public String genTernaryEdgeType(Object type) { | |
// return type==null? "null" : "context.retrieveTernaryEdgeType(\"" + coordinator.targetContext.retrieveBinaryEdgeTypeFQN(type) + "\")"; | |
// | |
// } | |
// public String genBinaryEdgeType(Object type) { | |
// return type==null? "null" : "context.retrieveBinaryEdgeType(\"" + coordinator.targetContext.retrieveTernaryEdgeTypeFQN(type) + "\")"; | |
// } | |
public abstract String genUnaryType(Object type); | |
public abstract String genTernaryEdgeType(Object type); | |
public abstract String genBinaryEdgeType(Object type); | |
public abstract String genPattern(PatternDescription desc); | |
//public abstract String genPosMap(PatternDescription desc); | |
public String declareNextContainerVariable() { | |
return declareNewBuildable(call("getNextContainer", "")); | |
} | |
// public String declarePutOnTabVariable(PatternDescription effort) { | |
// return declareNewBuildable(call("putOnTab", genPattern(effort))); | |
// } | |
//////////////////////////////////// | |
// * BL | |
//////////////////////////////////// | |
public Stub<String> buildBetaNode(Stub<String> primaryStub, Stub<String> sideStub, | |
TupleMask primaryMask, TupleMask sideMask, | |
TupleMask complementer, boolean negative) | |
{ | |
String[] arguments = { | |
gen(primaryStub), gen(sideStub), | |
gen(primaryMask), gen(sideMask), | |
gen(complementer), gen(negative) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "buildBetaNode", arguments); | |
if (negative) { | |
return new Stub<String>(primaryStub, resultVar); | |
} else { | |
Tuple newCalibrationPattern = negative ? | |
primaryStub.getVariablesTuple() : | |
complementer.combine(primaryStub.getVariablesTuple(), sideStub.getVariablesTuple(), Options.enableInheritance, true); | |
return new Stub<String>(primaryStub, sideStub, newCalibrationPattern, resultVar); | |
} | |
} | |
public Stub<String> buildCountCheckBetaNode(Stub<String> primaryStub, | |
Stub<String> sideStub, TupleMask primaryMask, | |
TupleMask originalSideMask, int resultPositionInSignature) | |
{ | |
String[] arguments = { | |
gen(primaryStub), gen(sideStub), | |
gen(primaryMask), gen(originalSideMask), | |
gen(resultPositionInSignature) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "buildCountCheckBetaNode", arguments); | |
return new Stub<String>(primaryStub, primaryStub.getVariablesTuple(), resultVar); | |
} | |
public Stub<String> buildCounterBetaNode(Stub<String> primaryStub, | |
Stub<String> sideStub, TupleMask primaryMask, | |
TupleMask originalSideMask, TupleMask complementer, | |
Object aggregateResultCalibrationElement) | |
{ | |
String[] arguments = { | |
gen(primaryStub), gen(sideStub), | |
gen(primaryMask), gen(originalSideMask), | |
gen(complementer), | |
genCalibrationElement(aggregateResultCalibrationElement) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "buildCounterBetaNode", arguments); | |
Object[] newCalibrationElement = {aggregateResultCalibrationElement}; | |
Tuple newCalibrationPattern = new LeftInheritanceTuple(primaryStub.getVariablesTuple(), newCalibrationElement); | |
return new Stub<String>(primaryStub, newCalibrationPattern, resultVar); | |
} | |
public void buildConnection(Stub<String> stub, String collector) { | |
String[] arguments = { | |
gen(stub), collector | |
}; | |
emitProcedureCall("buildConnection", arguments); | |
} | |
public Stub<String> buildEqualityChecker(Stub<String> stub, int[] indices) { | |
String[] arguments = { | |
gen(stub), | |
gen(indices) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "buildEqualityChecker", arguments); | |
return new Stub<String>(stub, resultVar); | |
} | |
public Stub<String> buildInjectivityChecker(Stub<String> stub, int subject, int[] inequalIndices) { | |
String[] arguments = { | |
gen(stub), gen(subject), | |
gen(inequalIndices) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "buildInjectivityChecker", arguments); | |
return new Stub<String>(stub, resultVar); | |
} | |
@Override | |
public Stub<String> buildTransitiveClosure(Stub<String> stub) { | |
String[] arguments = { | |
gen(stub) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "buildTransitiveClosure", arguments); | |
return new Stub<String>(stub, resultVar); | |
} | |
public Stub<String> buildScopeConstrainer(Stub<String> stub, boolean transitive, | |
Object unwrappedContainer, int constrainedIndex) { | |
throw new UnsupportedOperationException("Code generation does not support external scoping as of now"); | |
} | |
public Stub<String> buildStartStub(Object[] constantValues, Object[] constantNames) { | |
String[] arguments = { | |
gen(constantValues, true), | |
gen(constantNames, false), | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "buildStartStub", arguments); | |
return new Stub<String>(new FlatTuple(constantNames), resultVar); | |
} | |
public Stub<String> buildTrimmer(Stub<String> stub, TupleMask trimMask) { | |
String[] arguments = { | |
gen(stub), gen(trimMask) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "buildTrimmer", arguments); | |
return new Stub<String>(stub, trimMask.transform(stub.getVariablesTuple()), resultVar); | |
} | |
public Stub<String> containmentDirectStub(Tuple nodes) { | |
String[] arguments = { | |
gen(nodes, false) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "containmentDirectStub", arguments); | |
return new Stub<String>(nodes, resultVar); | |
} | |
public Stub<String> containmentTransitiveStub(Tuple nodes) { | |
String[] arguments = { | |
gen(nodes, false) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "containmentTransitiveStub", arguments); | |
return new Stub<String>(nodes, resultVar); | |
} | |
public Stub<String> unaryTypeStub(Tuple nodes, Object supplierKey) { | |
String[] arguments = { | |
gen(nodes, false), declareNewValue("Object", genUnaryType(supplierKey)) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "unaryTypeStub", arguments); | |
return new Stub<String>(nodes, resultVar); | |
} | |
public Stub<String> generalizationDirectStub(Tuple nodes) { | |
String[] arguments = { | |
gen(nodes, false) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "generalizationDirectStub", arguments); | |
return new Stub<String>(nodes, resultVar); | |
} | |
public Stub<String> generalizationTransitiveStub(Tuple nodes) { | |
String[] arguments = { | |
gen(nodes, false) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "generalizationTransitiveStub", arguments); | |
return new Stub<String>(nodes, resultVar); | |
} | |
public Stub<String> instantiationDirectStub(Tuple nodes) { | |
String[] arguments = { | |
gen(nodes, false) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "instantiationDirectStub", arguments); | |
return new Stub<String>(nodes, resultVar); | |
} | |
public Stub<String> instantiationTransitiveStub(Tuple nodes) { | |
String[] arguments = { | |
gen(nodes, false) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "instantiationTransitiveStub", arguments); | |
return new Stub<String>(nodes, resultVar); | |
} | |
public Stub<String> patternCallStub(Tuple nodes, PatternDescription supplierKey) | |
{ | |
//if (!coordinator.collectors.containsKey(supplierKey)) coordinator.unbuilt.add(supplierKey); | |
String[] arguments = { | |
gen(nodes, false), genPattern(supplierKey) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "patternCallStub", arguments); | |
return new Stub<String>(nodes, resultVar); | |
} | |
public Stub<String> binaryEdgeTypeStub(Tuple nodes, Object supplierKey) { | |
String[] arguments = { | |
gen(nodes, false), declareNewValue("Object", genBinaryEdgeType(supplierKey)) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "binaryEdgeTypeStub", arguments); | |
return new Stub<String>(nodes, resultVar); | |
} | |
public Stub<String> ternaryEdgeTypeStub(Tuple nodes, Object supplierKey) { | |
String[] arguments = { | |
gen(nodes, false), declareNewValue("Object", genTernaryEdgeType(supplierKey)) | |
}; | |
String resultVar = emitFunctionCall(coordinator.stubType, "ternaryEdgeTypeStub", arguments); | |
return new Stub<String>(nodes, resultVar); | |
} | |
public String patternCollector(PatternDescription pattern) { | |
String patternName = genPattern(pattern); | |
String[] arguments = {patternName}; | |
return emitFunctionCall(coordinator.collectorType, "patternCollector", arguments); | |
// return coordinator.allocateNewCollector(pattern); | |
} | |
// /** | |
// * @pre coordinator.isComplete() | |
// */ | |
// public void printInitializer(String collectorsMap, String posMappingMap) { | |
// for (Entry<PatternDescription, String> entry : coordinator.collectors.entrySet()) { | |
// String patternName = genPattern(entry.getKey()); | |
// emitLine("// "+patternName); | |
// emitLine(posMappingMap + ".put(" + patternName + ", " +genPosMap(entry.getKey()) + ");"); | |
// String[] arguments = {patternName}; | |
// String resultVar = emitFunctionCall(coordinator.collectorType, "patternCollector", arguments); | |
// emitLine(entry.getValue() + " = " + resultVar + ";"); | |
// emitLine(collectorsMap + ".put(" + patternName + ", " +entry.getValue() + ");"); | |
// } | |
// } | |
} |