/** | |
* Copyright (c) 2008 OptXware Research and Development LLC. | |
* 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: | |
* Daniel Varro - Initial API and implementation | |
*/ | |
package org.eclipse.viatra2.lpgparser.typechecker; | |
import java.io.File; | |
import java.io.IOException; | |
import java.util.ArrayList; | |
import java.util.HashMap; | |
import java.util.List; | |
import java.util.Map; | |
import org.eclipse.emf.ecore.EObject; | |
import org.eclipse.emf.ecore.resource.Resource; | |
import org.eclipse.emf.ecore.resource.ResourceSet; | |
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; | |
import org.eclipse.emf.ecore.xmi.XMIResource; | |
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl; | |
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl; | |
import org.eclipse.viatra2.core.IModelElement; | |
import org.eclipse.viatra2.core.IModelManager; | |
import org.eclipse.viatra2.core.IModelSpace; | |
import org.eclipse.viatra2.errors.VPMRuntimeException; | |
import org.eclipse.viatra2.errors.info.ErrorInformation; | |
import org.eclipse.viatra2.errors.info.ErrorInformation.ErrorKind; | |
import org.eclipse.viatra2.errors.info.ErrorInformation.ErrorSeverity; | |
import org.eclipse.viatra2.errors.info.Location; | |
import org.eclipse.viatra2.framework.FrameworkManager; | |
import org.eclipse.viatra2.gtasm.typerules.BinaryTypeJudgement; | |
import org.eclipse.viatra2.gtasm.typerules.CustomTypeJudgement; | |
import org.eclipse.viatra2.gtasm.typerules.RuleSet; | |
import org.eclipse.viatra2.gtasm.typerules.TypeJudgement; | |
import org.eclipse.viatra2.gtasm.typerules.TypeRule; | |
import org.eclipse.viatra2.gtasm.typerules.TyperulesPackage; | |
import org.eclipse.viatra2.gtasm.typerules.UnaryTypeJudgement; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.core.AnnotatedElement; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.core.Annotation; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.ASMFunction; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.DefinitionsFactory; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.InitialValue; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.Rule; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.SymbolicRuleParameter; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.TypeConstant; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.Variable; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.definitions.VariableDefinition; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.enums.ValueKind; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.simpleRules.CallRule; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.simpleRules.GTRuleInvocation; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.simpleRules.RuleUpdate; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.simpleRules.RuleUpdateASMFunction; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.simpleRules.RuleUpdateVariable; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.ASMFunctionInvocation; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.FunctionInvocation; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.GTPatternCall; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.ModelElementQuery; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.NativeFunctionInvocation; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.Term; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.VariableReference; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.ArithmeticOperation; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.ConversionOperation; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.asm.terms.builtInFunctions.RelationalOperation; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTPattern; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTPatternBody; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.GTRule; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.PatternVariable; | |
import org.eclipse.viatra2.gtasmmodel.gtasm.metamodel.gt.PatternVariableAssignment; | |
import org.eclipse.viatra2.gtasmmodel.vpm.editmodel.Entity; | |
import org.eclipse.viatra2.gtasmmodel.vpm.editmodel.ModelElement; | |
import org.eclipse.viatra2.gtasmmodel.vpm.editmodel.Relation; | |
import org.eclipse.viatra2.gtasmmodel.vpm.editmodel.Relationship; | |
import org.eclipse.viatra2.lpgparser.loader.VTCLMessages; | |
import org.eclipse.viatra2.lpgparser.modelbuilder.ModelBuilderHelper; | |
/** | |
* This class is responsible for type checking of VTCL programs. | |
* @author Daniel Varro | |
*/ | |
public class VTCLTypeChecker { | |
private static final String PARSER_MARKER = "org.eclipse.viatra2.loaders.vtclparsermarker"; | |
private IModelSpace modelSpace; | |
private IModelManager modelManager; | |
private TypeResolver typeResolver = new TypeResolver(); | |
// private TypeAssignments typeAssignments = new TypeAssignments(); | |
private RuleSet typeRuleSet = null; | |
private Map<String, List<CustomTypeJudgement>> customTypeRuleMap = null; | |
private Map<StringTriple, BinaryTypeJudgement> binaryTypeRuleMap = null; | |
private Map<StringPair, UnaryTypeJudgement> unaryTypeRuleMap = null; | |
private List<Term> termsToCheck = new ArrayList<Term>(); | |
private List<GTRuleInvocation> gtRuleInvocsToCheck = new ArrayList<GTRuleInvocation>(); | |
private List<CallRule> asmCallRuleToCheck = new ArrayList<CallRule>(); | |
private List<ASMFunctionInvocation> asmFunInvocsToCheck = new ArrayList<ASMFunctionInvocation>(); | |
private List<NativeFunctionInvocation> nativeFunInvocsToCheck = new ArrayList<NativeFunctionInvocation>(); | |
private List<GTPatternCall> patternCallToCheck = new ArrayList<GTPatternCall>(); | |
private List<RuleUpdate> updateRulesToCheck = new ArrayList<RuleUpdate>(); | |
private List<InitialValue> initValuesToCheck = new ArrayList<InitialValue>(); | |
private List<VariableDefinition> varDefsToCheck = new ArrayList<VariableDefinition>(); | |
private List<GTPattern> gtPatternDefToCheck = new ArrayList<GTPattern>(); | |
protected enum AbstractionKind { | |
FIRST, SECOND, BOTH | |
}; | |
public VTCLTypeChecker(IModelSpace aModelSpace) { | |
modelSpace = aModelSpace; | |
modelSpace = aModelSpace; | |
modelSpace = aModelSpace; | |
modelSpace = aModelSpace; | |
modelSpace = aModelSpace; | |
modelSpace = aModelSpace; | |
modelSpace = aModelSpace; | |
modelSpace = aModelSpace; | |
modelManager = modelSpace.getModelManager(); | |
typeRuleSet = null; | |
try { | |
initializeTypeRuleSet(); | |
} catch (VPMRuntimeException e) { | |
// This exception should never be thrown | |
e.printStackTrace(); | |
} | |
} | |
public TypeResolver getTypeResolver() { | |
return typeResolver; | |
} | |
/** | |
* Returns the type assignment repository | |
* @return the type assignment repository | |
*/ | |
/* | |
* public TypeAssignments getTypeAssignments() { return typeAssignments; } | |
*/ | |
public List<Term> getTermsToCheck() { | |
return termsToCheck; | |
} | |
public List<ASMFunctionInvocation> getAsmFunInvocsToCheck() { | |
return asmFunInvocsToCheck; | |
} | |
public List<NativeFunctionInvocation> getNativeFunInvocsToCheck() { | |
return nativeFunInvocsToCheck; | |
} | |
public List<GTRuleInvocation> getGtRuleInvocsToCheck() { | |
return gtRuleInvocsToCheck; | |
} | |
public List<CallRule> getAsmCallRuleToCheck() { | |
return asmCallRuleToCheck; | |
} | |
public List<GTPatternCall> getPatternCallToCheck() { | |
return patternCallToCheck; | |
} | |
public List<RuleUpdate> getUpdateRulesToCheck() { | |
return updateRulesToCheck; | |
} | |
public List<InitialValue> getInitValuesToCheck() { | |
return initValuesToCheck; | |
} | |
public List<VariableDefinition> getVarDefsToCheck() { | |
return varDefsToCheck; | |
} | |
public List<GTPattern> getPatternDefToCheck() { | |
return gtPatternDefToCheck; | |
} | |
private List<ErrorInformation> typeErrorInfos = new ArrayList<ErrorInformation>(); | |
public List<ErrorInformation> getAllTypeErrorInfos() { | |
return typeErrorInfos; | |
} | |
public void clearAllTypeErrors() { | |
typeErrorInfos.clear(); | |
} | |
/** | |
* Creates an ErrorInformation | |
* @param annotations | |
* : location information of the error | |
* @param errorString | |
* : textual representation of the error (VTCLMessages should be | |
* used) | |
* @param errorSeverity | |
* : severity of the error | |
* @param context | |
* : list of contextual information | |
*/ | |
public void addTypeError(List<Annotation> annotations, String errorString, | |
ErrorSeverity errorSeverity, String[] context) { | |
Location location = ModelBuilderHelper.createLocationInfo(annotations); | |
ErrorInformation errorInfo = new ErrorInformation(errorString, | |
PARSER_MARKER, ErrorKind.VALIDATION_ERROR, location, | |
errorSeverity); | |
// Bind contextual parameters of error strings | |
errorInfo.bind(context); | |
typeErrorInfos.add(errorInfo); | |
} | |
public void loadTypeRules(File file) throws VPMRuntimeException { | |
// Create a resource set. | |
ResourceSet resourceSet = new ResourceSetImpl(); | |
resourceSet.getPackageRegistry().put(TyperulesPackage.eNS_URI, | |
TyperulesPackage.eINSTANCE); | |
Resource res = resourceSet.getResource(org.eclipse.emf.common.util.URI | |
.createFileURI(file.getAbsolutePath()), true); | |
try { | |
res.load(null); | |
} catch (IOException e) { | |
throw new VPMRuntimeException("Type rules cannot be loaded"); | |
} | |
if (res.getContents().get(0) instanceof RuleSet) { | |
RuleSet rs = (RuleSet) res.getContents().get(0); | |
// The new rule set extends the existing one | |
rs.setExtends(typeRuleSet); | |
// Save the new rule set | |
typeRuleSet = rs; | |
} | |
// TODO: Filter deactivated rules | |
// filterDeactivatedTypeRules(); | |
} | |
public void initializeTypeChecker() { | |
clearAllTypeErrors(); | |
clearLists(); | |
} | |
/** | |
* Empties to lists containing various task elements | |
*/ | |
private void clearLists() { | |
termsToCheck.clear(); | |
asmCallRuleToCheck.clear(); | |
gtRuleInvocsToCheck.clear(); | |
asmFunInvocsToCheck.clear(); | |
nativeFunInvocsToCheck.clear(); | |
patternCallToCheck.clear(); | |
updateRulesToCheck.clear(); | |
initValuesToCheck.clear(); | |
varDefsToCheck.clear(); | |
gtPatternDefToCheck.clear(); | |
} | |
/** | |
* This method initiates type checking for all - Terms collected in | |
* termsToCheck - CallRules collected in asmCallRuleToCheck - | |
* GTRuleInvocations collected in gtRuleInvocsToCheck - | |
* ASMFunctionInvocations collected in asmFunInvocsToCheck - | |
* NativeFunctionInvocations collected in nativeFunInvocsToCheck - | |
* GTPatternCalls (from pattern composition) collected in patternCallToCheck | |
*/ | |
public void doTypeChecking() { | |
try { | |
assert (typeErrorInfos.isEmpty()) : "Type error list is not empty"; | |
// Infer types for pattern variable references | |
for (GTPattern patternDef : gtPatternDefToCheck) { | |
typeCheckPatternDefinition(patternDef); | |
} | |
for (Term term : termsToCheck) { | |
typeCheckTerm(term); | |
} | |
for (CallRule callRule : asmCallRuleToCheck) { | |
typeCheckCallRule(callRule); | |
} | |
for (GTRuleInvocation gtRuleInvoc : gtRuleInvocsToCheck) { | |
typeCheckGTRuleCall(gtRuleInvoc); | |
} | |
for (ASMFunctionInvocation asmFunInvoc : asmFunInvocsToCheck) { | |
typeCheckAsmFunctionInvocation(asmFunInvoc); | |
} | |
for (NativeFunctionInvocation nativeFunInvoc : nativeFunInvocsToCheck) { | |
typeCheckNativeFunctionInvocation(nativeFunInvoc); | |
} | |
for (GTPatternCall patternCall : patternCallToCheck) { | |
typeCheckPatternCall(patternCall); | |
} | |
for (RuleUpdate updateRule : updateRulesToCheck) { | |
typeCheckUpdateRule(updateRule); | |
} | |
for (InitialValue initValue : initValuesToCheck) { | |
typeCheckInitialValue(initValue); | |
} | |
for (VariableDefinition varDef : varDefsToCheck) { | |
typeCheckVariableDefinition(varDef); | |
} | |
} finally { | |
clearLists(); | |
} | |
} | |
protected void initializeTypeRuleSet() throws VPMRuntimeException { | |
String bundleStr = "org.eclipse.viatra2.gtasm.typing.model"; | |
String fileName = "/model/VTCLCore.typerules"; | |
File file = FrameworkManager.getFileFromBundle(bundleStr, fileName); | |
if (file == null) { | |
throw new VPMRuntimeException("Type rule file cannot be found"); | |
} | |
// Create a resource set. | |
// added by Istvan to make it work in headless mode | |
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put | |
("typerules", | |
new XMIResourceFactoryImpl() | |
{ | |
public Resource createResource(org.eclipse.emf.common.util.URI uri) | |
{ | |
XMIResource xmiResource = new XMIResourceImpl(uri); | |
return xmiResource; | |
} | |
}); | |
ResourceSet resourceSet = new ResourceSetImpl(); | |
resourceSet.getPackageRegistry().put(TyperulesPackage.eNS_URI, | |
TyperulesPackage.eINSTANCE); | |
Resource res = resourceSet.getResource(org.eclipse.emf.common.util.URI | |
.createFileURI(file.getAbsolutePath()), true); | |
try { | |
res.load(null); | |
} catch (IOException e) { | |
throw new VPMRuntimeException("Type rules cannot be loaded"); | |
} | |
if (res.getContents().get(0) instanceof RuleSet) { | |
typeRuleSet = (RuleSet) res.getContents().get(0); | |
} | |
if (typeRuleSet != null) { | |
binaryTypeRuleMap = new HashMap<StringTriple, BinaryTypeJudgement>(); | |
unaryTypeRuleMap = new HashMap<StringPair, UnaryTypeJudgement>(); | |
customTypeRuleMap = new HashMap<String, List<CustomTypeJudgement>>(); | |
for (TypeRule typeRule : typeRuleSet.getTyperules()) { | |
List<CustomTypeJudgement> customList = null; | |
for (TypeJudgement judgement : typeRule.getJudgements()) { | |
if (judgement instanceof BinaryTypeJudgement) { | |
BinaryTypeJudgement binaryJudge = (BinaryTypeJudgement) judgement; | |
StringTriple triple = new StringTriple(typeRule | |
.getOperator(), binaryJudge.getFirstOperand(), | |
binaryJudge.getSecondOperand()); | |
binaryTypeRuleMap.put(triple, binaryJudge); | |
} else if (judgement instanceof UnaryTypeJudgement) { | |
UnaryTypeJudgement unaryJudge = (UnaryTypeJudgement) judgement; | |
StringPair pair = new StringPair( | |
typeRule.getOperator(), unaryJudge.getOperand()); | |
unaryTypeRuleMap.put(pair, unaryJudge); | |
} else if (judgement instanceof CustomTypeJudgement) { | |
CustomTypeJudgement customJudge = (CustomTypeJudgement) judgement; | |
customList = customTypeRuleMap.get(typeRule | |
.getOperator()); | |
if (customList == null) { | |
customList = new ArrayList<CustomTypeJudgement>(); | |
} | |
customList.add(customJudge); | |
} | |
} | |
customTypeRuleMap.put(typeRule.getOperator(), customList); | |
} | |
} | |
} | |
protected void typeCheckPatternDefinition(GTPattern patternDef) { | |
// Process pattern parameters | |
for (PatternVariable patternVar : patternDef.getSymParameters()) { | |
TypeConstant typeConst = DefinitionsFactory.eINSTANCE | |
.createTypeConstant(); | |
typeConst.setKind(ValueKind.UNDEF_LITERAL); | |
typeConst.setFqn(VTCLTypeNameConstants.TOP); | |
// Infer types for all references | |
for (Object varRefObj : patternVar.getReferences()) { | |
VariableReference varRef = (VariableReference) varRefObj; | |
typeConst = inferTypeForPatternVariableRef(varRef, typeConst); | |
} | |
inferTypeForPatternVariableDef(patternVar, typeConst); | |
} | |
// Process all bodies | |
for (GTPatternBody body : patternDef.getPatternBodies()) { | |
// Process local pattern variables | |
for (PatternVariable patternVar : body.getLocalVariables()) { | |
TypeConstant typeConst = DefinitionsFactory.eINSTANCE | |
.createTypeConstant(); | |
typeConst.setKind(ValueKind.UNDEF_LITERAL); | |
typeConst.setFqn(VTCLTypeNameConstants.TOP); | |
for (Object varRefObj : patternVar.getReferences()) { | |
VariableReference varRef = (VariableReference) varRefObj; | |
typeConst = inferTypeForPatternVariableRef(varRef, | |
typeConst); | |
} | |
inferTypeForPatternVariableDef(patternVar, typeConst); | |
} | |
} | |
} | |
/** | |
* @param varRef | |
* @param prevTypeConst | |
* @return | |
*/ | |
protected TypeConstant inferTypeForPatternVariableRef( | |
VariableReference varRef, TypeConstant prevTypeConst) { | |
EObject parent = varRef.eContainer(); | |
String typeStr = null; | |
ValueKind kind; | |
// Handling model elements (entity, relation) in pattern body | |
if (parent instanceof ModelElement) { | |
ModelElement element = (ModelElement) parent; | |
// If it is the first variable reference of an entity/relation | |
if (varRef.equals(element.getVariableReferences().get(0)) | |
|| prevTypeConst == null) { | |
// Check if type is defined | |
if (!element.getType().isEmpty()) { | |
ModelElement type = element.getType().get(0); | |
typeStr = type.getName(); | |
} else { | |
if (parent instanceof Entity) { | |
typeStr = VTCLTypeNameConstants.ENTITY; | |
} else if (parent instanceof Relation) { | |
typeStr = VTCLTypeNameConstants.RELATION; | |
} else { | |
typeStr = VTCLTypeNameConstants.MODELELEMENT; | |
} | |
} | |
// Determine the LUB of variable reference types | |
if (prevTypeConst != null | |
&& !prevTypeConst.getKind().equals( | |
ValueKind.UNDEF_LITERAL)) { | |
// TODO: Distinguish between variables in OR patterns and | |
// within the same body | |
typeStr = typeResolver.leastUpperBound(modelManager, | |
typeStr, prevTypeConst.getFqn()); | |
} | |
} | |
// If variable reference is not the first | |
else { | |
typeStr = typeResolver.greatestLowerBound(modelManager, | |
VTCLTypeNameConstants.MODELELEMENT, prevTypeConst | |
.getFqn()); | |
} | |
kind = ValueKind.MODELELEMENT_LITERAL; | |
// Schedule variable reference for type checking | |
termsToCheck.add(varRef); | |
} | |
// Relationship definition | |
else if (parent instanceof Relationship) { | |
typeStr = VTCLTypeNameConstants.MODELELEMENT; | |
kind = ValueKind.MODELELEMENT_LITERAL; | |
// Schedule variable reference for type checking | |
termsToCheck.add(varRef); | |
// Determine the GLB of variable reference types | |
if (prevTypeConst != null) { | |
typeStr = typeResolver.greatestLowerBound(modelManager, | |
typeStr, prevTypeConst.getFqn()); | |
} | |
} | |
// Pattern Variable Assignment | |
else if (parent instanceof PatternVariableAssignment) { | |
typeStr = VTCLTypeNameConstants.MODELELEMENT; | |
kind = ValueKind.MODELELEMENT_LITERAL; | |
// Schedule variable reference for type checking | |
termsToCheck.add(varRef); | |
// Determine the GLB of variable reference types | |
if (prevTypeConst != null) { | |
typeStr = typeResolver.greatestLowerBound(modelManager, | |
typeStr, prevTypeConst.getFqn()); | |
} | |
} | |
// All other cases (should be checked separately) | |
else { | |
if (prevTypeConst != null) { | |
typeStr = prevTypeConst.getFqn(); | |
kind = prevTypeConst.getKind(); | |
} else { | |
typeStr = VTCLTypeNameConstants.TOP; | |
kind = ValueKind.MODELELEMENT_LITERAL; | |
} | |
} | |
varRef.setType(typeStr); | |
varRef.setKind(kind); | |
/*if (typeStr.contentEquals(VTCLTypeNameConstants.MODELELEMENT) | |
|| typeStr.contentEquals(VTCLTypeNameConstants.ENTITY) | |
|| typeStr.contentEquals(VTCLTypeNameConstants.RELATION)) { | |
return null; | |
}*/ | |
TypeConstant resultTypeConst = DefinitionsFactory.eINSTANCE | |
.createTypeConstant(); | |
// Set result type constant | |
resultTypeConst.setFqn(typeStr); | |
resultTypeConst.setKind(kind); | |
return resultTypeConst; | |
} | |
protected void inferTypeForPatternVariableDef(PatternVariable varDef, | |
TypeConstant typeConst) { | |
// Type inference is only required when the type of varDef is not | |
// explicitly defined | |
if (varDef.getVariableType() == null && typeConst != null) { | |
varDef.setVariableType(typeConst); | |
} | |
} | |
protected void typecheckPatternBody(GTPatternBody body) { | |
// For each pattern variable definition below body | |
for (Object paramObject : body.getHeader().getSymParameters()) { | |
PatternVariable param = (PatternVariable) paramObject; | |
// For each variable reference | |
for (Object varRefObj : param.getReferences()) { | |
VariableReference varRef = (VariableReference) varRefObj; | |
// Get the parent of the variable reference | |
EObject parent = varRef.eContainer(); | |
if (parent instanceof ModelElement) { | |
ModelElement element = (ModelElement) parent; | |
if (!element.getType().isEmpty()) { | |
ModelElement type = element.getType().get(0); | |
String typeStr = type.getName(); | |
varRef.setType(typeStr); | |
} else { | |
if (parent instanceof Entity) { | |
varRef.setType(VTCLTypeNameConstants.ENTITY); | |
} else if (parent instanceof Relation) { | |
varRef.setType(VTCLTypeNameConstants.RELATION); | |
} else { | |
varRef.setType(VTCLTypeNameConstants.MODELELEMENT); | |
} | |
} | |
varRef.setKind(ValueKind.MODELELEMENT_LITERAL); | |
} | |
// GTPatternCalls are already handled | |
else if (parent instanceof PatternVariableAssignment) { | |
// TODO Check if the LHS and RHS are compatible | |
// PatternVariableAssignment pva = | |
// (PatternVariableAssignment) parent; | |
} | |
} | |
} | |
// Register its type | |
// Allocate type for its variable definition | |
} | |
/** | |
* Recursive traversal of the term | |
* @param term | |
*/ | |
protected void typeCheckTerm(Term term) { | |
if (term instanceof RelationalOperation | |
|| term instanceof ArithmeticOperation | |
|| term instanceof ConversionOperation) { | |
FunctionInvocation funInvoc = (FunctionInvocation) term; | |
if (funInvoc.getActualParameters().size() == 1) { | |
Term operand = funInvoc.getActualParameters().get(0); | |
if (operand.getType() == null) { | |
// Typecheck operand (if needed) | |
typeCheckTerm(operand); | |
} | |
// Typecheck the current term | |
typeCheckUnaryTerm(term, operand); | |
} else if (funInvoc.getActualParameters().size() == 2) { | |
// Typecheck left operand (when needed) | |
Term leftOperand = funInvoc.getActualParameters().get(0); | |
if (leftOperand.getType() == null) { | |
typeCheckTerm(leftOperand); | |
} | |
// Typecheck right operand (if needed) | |
Term rightOperand = funInvoc.getActualParameters().get(1); | |
if (rightOperand.getType() == null) { | |
typeCheckTerm(rightOperand); | |
} | |
// Typecheck the current term | |
typeCheckBinaryTerm(term, leftOperand, rightOperand); | |
} | |
} else if (term instanceof ASMFunctionInvocation) { | |
ASMFunctionInvocation asmFunInvoc = (ASMFunctionInvocation) term; | |
for (Object param : asmFunInvoc.getActualParameters()) { | |
Term actualParam = (Term) param; | |
if (actualParam.getType() == null) { | |
typeCheckTerm(actualParam); | |
} | |
} | |
ASMFunction asmFunDef = asmFunInvoc.getCalledFunction(); | |
// All GT rule invocations should be resolved prior to type checking | |
assert (asmFunDef != null) : "ASM function definition is not resolved for " | |
+ asmFunInvoc.getFqn(); | |
if (asmFunDef.getReturnType() != null) { | |
TypeConstant type = asmFunDef.getReturnType(); | |
asmFunInvoc.setType(type.getFqn()); | |
asmFunInvoc.setKind(type.getKind()); | |
} else { | |
asmFunInvoc.setType(VTCLTypeNameConstants.TOP); | |
asmFunInvoc.setKind(ValueKind.UNDEF_LITERAL); | |
} | |
// typeCheckAsmFunctionInvocation(asmFunInvoc); | |
} else if (term instanceof NativeFunctionInvocation) { | |
NativeFunctionInvocation nativeFunInvoc = (NativeFunctionInvocation) term; | |
for (Object param : nativeFunInvoc.getActualParameters()) { | |
Term actualParam = (Term) param; | |
if (actualParam.getType() == null) { | |
typeCheckTerm(actualParam); | |
} | |
} | |
// TODO: Provide better return type if possible | |
nativeFunInvoc.setType(VTCLTypeNameConstants.TOP); | |
nativeFunInvoc.setKind(ValueKind.UNDEF_LITERAL); | |
// typeCheckNativeFunctionInvocation(nativeFunInvoc); | |
} else if (term instanceof ModelElementQuery) { | |
ModelElementQuery meQuery = (ModelElementQuery) term; | |
Term argument = meQuery.getArgument(); | |
if (argument.getType() == null) { | |
typeCheckTerm(argument); | |
} | |
typeCheckUnaryTerm(term, argument); | |
} else if (term instanceof GTPatternCall) { | |
GTPatternCall patternCall = (GTPatternCall) term; | |
for (Object param : patternCall.getActualParameters()) { | |
Term actualParam = (Term) param; | |
if (actualParam.getType() == null) { | |
typeCheckTerm(actualParam); | |
} | |
} | |
// Set the type information for pattern call (used as a term) | |
patternCall.setKind(ValueKind.BOOLEAN_LITERAL); | |
patternCall.setType("datatypes.Boolean"); | |
// typeCheckPatternCall(patternCall); | |
} else if (term instanceof VariableReference) { | |
VariableReference varRef = (VariableReference) term; | |
typeCheckVariableReference(varRef); | |
} else { | |
// assert false; | |
} | |
} | |
/** | |
* Provides type checking for a {@link VariableReference}: it looks up the | |
* type of its corresponding {@link Variable} definition | |
* @param varRef | |
* : the {@link VariableReference} to be checked | |
*/ | |
protected void typeCheckVariableReference(VariableReference varRef) { | |
Variable varDef = varRef.getVariable(); | |
if (varDef == null) { | |
varRef.setType(VTCLTypeNameConstants.TOP); | |
varRef.setKind(ValueKind.UNDEF_LITERAL); | |
return; | |
} | |
if (varDef.getVariableType() != null) { | |
TypeConstant typeConstant = varDef.getVariableType(); | |
String typeStr = typeConstant.getFqn(); | |
ValueKind kind = typeConstant.getKind(); | |
// Set type for variable reference | |
if (typeStr != null && !typeStr.equals("")) { | |
assert (kind != null) : "Kind of type constant is not yet set"; | |
// If the type of the variable reference is not yet set | |
// assign it according to the type of the variable definition | |
if (varRef.getType() == null) { | |
varRef.setType(typeStr); | |
varRef.setKind(kind); | |
} | |
// Check type compatibility if both values are set | |
else { | |
if (!typeResolver.isSupertype(modelManager, typeStr, varRef | |
.getType())) { | |
// If inconsistent, report error | |
String[] context = new String[] { varRef.getType(), | |
typeStr }; | |
addTypeError( | |
varRef.getAnnotations(), | |
VTCLMessages.VTCLValidationErrorCodes_INCOMPATIBLE_VARIABLEREF_TYPE, | |
ErrorSeverity.WARNING, context); | |
} | |
} | |
} else { | |
if (varRef.getType() == null) { | |
varRef.setType(VTCLTypeNameConstants.TOP); | |
varRef.setKind(ValueKind.UNDEF_LITERAL); | |
} | |
} | |
} else { | |
if (varRef.getType() == null) { | |
varRef.setType(VTCLTypeNameConstants.TOP); | |
varRef.setKind(ValueKind.UNDEF_LITERAL); | |
} | |
} | |
} | |
/** | |
* Provides type checking for the actual parameters of a | |
* {@link GTRuleInvocation} | |
* @param gtRuleInvoc | |
* : the {@link GTRuleInvocation} to be checked | |
*/ | |
protected void typeCheckGTRuleCall(GTRuleInvocation gtRuleInvoc) { | |
GTRule gtRuleDef = gtRuleInvoc.getRule(); | |
// All GT rule invocations should be resolved prior to type checking | |
assert (gtRuleDef != null) : "GT rule is not resolved for " | |
+ gtRuleInvoc.getFqn(); | |
assert (gtRuleDef.getSymParameters().size() == gtRuleInvoc | |
.getActualParameters().size()) : "Parameter mismatch in GT rule invocation"; | |
for (int i = 0; i < gtRuleDef.getSymParameters().size(); i++) { | |
SymbolicRuleParameter symParam = gtRuleDef.getSymParameters() | |
.get(i); | |
Variable varDef = symParam.getVariable(); | |
assert (varDef != null) : "Variable is not resolved for Symbolic parameter"; | |
Term actualParam = gtRuleInvoc.getActualParameters().get(i); | |
if (varDef.getVariableType() != null) { | |
TypeConstant type = varDef.getVariableType(); | |
// Check consistency of types | |
if (!typeResolver.isSupertype(modelManager, type.getFqn(), | |
actualParam.getType())) { | |
// If inconsistent, report error | |
String[] context = new String[] { actualParam.getType(), | |
type.getFqn(), varDef.getName(), | |
gtRuleInvoc.getFqn() }; | |
addTypeError( | |
actualParam.getAnnotations(), | |
VTCLMessages.VTCLValidationErrorCodes_INCOMPATIBLE_ACTUALPARAM_TYPE, | |
ErrorSeverity.WARNING, context); | |
} | |
} | |
} | |
} | |
/** | |
* Provides type checking for the actual parameters of a | |
* {@link GTPatternCall} | |
* @param patternCall | |
* : the {@link GTPatternCall} to be checked | |
*/ | |
protected void typeCheckPatternCall(GTPatternCall patternCall) { | |
GTPattern patternDef = patternCall.getCalledPattern(); | |
// All pattern calls should be resolved prior to type checking | |
assert (patternDef != null) : "Pattern definition is not resolved"; | |
assert (patternDef.getSymParameters().size() == patternCall | |
.getActualParameters().size()) : "Parameter mismatch in pattern call"; | |
for (int i = 0; i < patternDef.getSymParameters().size(); i++) { | |
PatternVariable symParam = patternDef.getSymParameters().get(i); | |
Term actualParam = patternCall.getActualParameters().get(i); | |
if (symParam.getVariableType() != null) { | |
TypeConstant type = symParam.getVariableType(); | |
// Check consistency of types | |
// TODO this is a workaround for a nullpointer e | |
String actualParamType = actualParam.getType(); | |
String paramType = type.getFqn(); | |
if (!typeResolver.isSupertype(modelManager, paramType, | |
actualParamType) | |
&& !typeResolver.isSupertype(modelManager, | |
actualParamType, paramType)) { | |
// If inconsistent, report a warning, as a subpattern can | |
// strengthen a precondition | |
String[] context = new String[] { actualParamType, | |
paramType, symParam.getName(), patternCall.getFqn() }; | |
addTypeError( | |
actualParam.getAnnotations(), | |
VTCLMessages.VTCLValidationErrorCodes_INCOMPATIBLE_ACTUALPARAM_TYPE, | |
ErrorSeverity.WARNING, context); | |
} | |
} | |
} | |
} | |
/** | |
* Provides type compatibility checking for the actual parameters of a | |
* {@link CallRule} | |
* @param callRule | |
* : the {@link CallRule} to be checked | |
*/ | |
protected void typeCheckCallRule(CallRule callRule) { | |
Rule ruleDef = callRule.getRule(); | |
// All pattern calls should be resolved prior to type checking | |
assert (ruleDef != null) : "ASM rule is not resolved"; | |
assert (ruleDef.getSymParameters().size() == callRule | |
.getActualParameters().size()) : "Parameter mismatch in call rule"; | |
for (int i = 0; i < ruleDef.getSymParameters().size(); i++) { | |
SymbolicRuleParameter symParam = ruleDef.getSymParameters().get(i); | |
Variable varDef = symParam.getVariable(); | |
assert (varDef != null) : "Variable cannot be resolved for Symbolic rule parameter"; | |
Term actualParam = callRule.getActualParameters().get(i); | |
if (varDef.getVariableType() != null) { | |
TypeConstant type = varDef.getVariableType(); | |
// Check consistency of types | |
if (!typeResolver.isSupertype(modelManager, type.getFqn(), | |
actualParam.getType())) { | |
// If inconsistent, report error | |
String[] context = new String[] { actualParam.getType(), | |
type.getFqn(), varDef.getName(), callRule.getFqn() }; | |
addTypeError( | |
actualParam.getAnnotations(), | |
VTCLMessages.VTCLValidationErrorCodes_INCOMPATIBLE_ACTUALPARAM_TYPE, | |
ErrorSeverity.WARNING, context); | |
} | |
} | |
} | |
} | |
/** | |
* Provides type compatibility checking for the left and right values of a | |
* {@link RuleUpdate} | |
* @param updateRule | |
* : the {@link RuleUpdate} to be checked | |
*/ | |
protected void typeCheckUpdateRule(RuleUpdate updateRule) { | |
// Determine the type of its left value | |
String leftValueType = ""; | |
if (updateRule instanceof RuleUpdateVariable) { | |
RuleUpdateVariable varUpdateRule = (RuleUpdateVariable) updateRule; | |
VariableReference varRef = varUpdateRule.getVariable(); | |
assert (varRef != null); | |
// We assume that the type of varRef is already resolved | |
leftValueType = varRef.getType(); | |
} else if (updateRule instanceof RuleUpdateASMFunction) { | |
RuleUpdateASMFunction asmFunUpdateRule = (RuleUpdateASMFunction) updateRule; | |
ASMFunction asmFunDef = asmFunUpdateRule.getFunction(); | |
assert (asmFunDef != null); | |
TypeConstant typeConst = asmFunDef.getReturnType(); | |
if (typeConst != null) { | |
leftValueType = typeConst.getFqn(); | |
} else { | |
leftValueType = VTCLTypeNameConstants.TOP; | |
} | |
// Check type consistency of locations | |
if (!asmFunDef.getArgumentTypes().isEmpty()) { | |
for (int i = 0; i < asmFunUpdateRule.getLocations().size(); i++) { | |
Term term = asmFunUpdateRule.getLocations().get(i); | |
TypeConstant typeConstArg = asmFunDef.getArgumentTypes() | |
.get(i); | |
typeCheckCompatibility(term, typeConstArg.getFqn(), term | |
.getType()); | |
} | |
} | |
} | |
// Determine the type of its right value | |
Term value = updateRule.getValue(); | |
assert (value != null); | |
String rightValueType = value.getType(); | |
// Issue an error message if the type of left value is not a supertype | |
// of the right value | |
if (!typeResolver.isSupertype(modelManager, leftValueType, | |
rightValueType)) { | |
String[] context = new String[] { leftValueType, rightValueType }; | |
addTypeError( | |
updateRule.getAnnotations(), | |
VTCLMessages.VTCLValidationErrorCodes_INCOMPATIBLE_TYPE_IN_UPDATE, | |
ErrorSeverity.WARNING, context); | |
} | |
} | |
protected void typeCheckNativeFunctionInvocation( | |
NativeFunctionInvocation nativeFunInvoc) { | |
// FIXME To be completed later | |
} | |
protected void typeCheckAsmFunctionInvocation( | |
ASMFunctionInvocation asmFunInvoc) { | |
ASMFunction asmFun = asmFunInvoc.getCalledFunction(); | |
assert (asmFun != null); | |
if (!asmFun.getArgumentTypes().isEmpty()) { | |
for (int i = 0; i < asmFunInvoc.getActualParameters().size(); i++) { | |
Term term = asmFunInvoc.getActualParameters().get(i); | |
TypeConstant typeConst = asmFun.getArgumentTypes().get(i); | |
typeCheckCompatibility(term, typeConst.getFqn(), term.getType()); | |
} | |
} | |
} | |
protected void typeCheckInitialValue(InitialValue initValue) { | |
ASMFunction asmFun = (ASMFunction) initValue.eContainer(); | |
// Check if initial value is consistent with type | |
if (!asmFun.getArgumentTypes().isEmpty()) { | |
for (int i = 0; i < initValue.getLocations().size(); i++) { | |
Term term = initValue.getLocations().get(i); | |
TypeConstant typeConst = asmFun.getArgumentTypes().get(i); | |
typeCheckCompatibility(term, typeConst.getFqn(), term.getType()); | |
} | |
} | |
// Check if value is consistent with return type | |
if (asmFun.getReturnType() != null) { | |
Term term = initValue.getValue(); | |
TypeConstant typeConst = asmFun.getReturnType(); | |
typeCheckCompatibility(term, typeConst.getFqn(), term.getType()); | |
} | |
} | |
protected void typeCheckVariableDefinition(VariableDefinition varDefine) { | |
// Check if initial value of a variable is consistent with its type | |
Variable var = varDefine.getVariable(); | |
TypeConstant typeConst = var.getVariableType(); | |
if (typeConst != null) { | |
Term initValue = varDefine.getValue(); | |
typeCheckCompatibility(varDefine, typeConst.getFqn(), initValue | |
.getType()); | |
} | |
} | |
protected void typeCheckCompatibility(AnnotatedElement element, | |
String supertypeStr, String subtypeStr) { | |
if (!typeResolver.isSupertype(modelManager, supertypeStr, subtypeStr)) { | |
// If inconsistent, report error | |
String[] context = new String[] { supertypeStr, subtypeStr }; | |
addTypeError( | |
element.getAnnotations(), | |
VTCLMessages.VTCLValidationErrorCodes_INCOMPATIBLE_INITIALVALUE_TYPE, | |
ErrorSeverity.WARNING, context); | |
} | |
} | |
protected void typeCheckBinaryTerm(Term term, Term leftOperand, | |
Term rightOperand) { | |
// // Type checking | |
// TODO: Enable the following code if needed for double-checking | |
ValueKind resultKind = TermTypeChecker.typeCheck(term, leftOperand | |
.getKind(), rightOperand.getKind()); | |
term.setKind(resultKind); | |
// // Report type error | |
// if (resultKind.getValue() == ValueKind.ERROR) { | |
// String[] context = new String[]{ | |
// TermTypeChecker.getOperationString(term), | |
// leftOperand.getKind().getName(), rightOperand.getKind().getName()}; | |
// addTypeError( | |
// term.getAnnotations(), | |
// VTCLMessages.VTCLValidationErrorCodes_BINARY_INCOMPATIBLE_TYPES, | |
// ErrorSeverity.WARNING, | |
// context); | |
// } | |
// String based Type checking | |
String resultType = typeCheckBinaryTerm(term.eClass().getName(), | |
leftOperand, rightOperand); | |
term.setType(resultType); | |
// Report type error | |
if (resultType.equals(VTCLTypeNameConstants.BOTTOM)) { | |
String[] context = new String[] { | |
TermTypeChecker.getOperationString(term), | |
leftOperand.getType(), rightOperand.getType() }; | |
addTypeError( | |
term.getAnnotations(), | |
VTCLMessages.VTCLValidationErrorCodes_BINARY_INCOMPATIBLE_TYPES, | |
ErrorSeverity.WARNING, context); | |
} | |
} | |
protected void typeCheckUnaryTerm(Term term, Term operand) { | |
ValueKind resultKind = TermTypeChecker.typeCheck(term, operand | |
.getKind()); | |
term.setKind(resultKind); | |
// // Report type error | |
// if (resultKind.getValue() == ValueKind.ERROR) { | |
// String[] context = new String[]{ | |
// TermTypeChecker.getOperationString(term), | |
// operand.getKind().getName(), }; | |
// addTypeError( | |
// term.getAnnotations(), | |
// VTCLMessages.VTCLValidationErrorCodes_UNARY_INCOMPATIBLE_TYPES, | |
// ErrorSeverity.WARNING, | |
// context); | |
// } | |
// String based Type checking | |
String resultType = typeCheckUnaryTerm(term.eClass().getName(), operand); | |
term.setType(resultType); | |
// Report type error | |
// TODO resultType nullcheck shouldn't be needed | |
if (resultType.equals(VTCLTypeNameConstants.BOTTOM)) { | |
String[] context = new String[] { | |
TermTypeChecker.getOperationString(term), operand.getType() }; | |
addTypeError( | |
term.getAnnotations(), | |
VTCLMessages.VTCLValidationErrorCodes_UNARY_INCOMPATIBLE_TYPES, | |
ErrorSeverity.WARNING, context); | |
} | |
} | |
protected final String[] longTypeCheckList = { | |
VTCLTypeNameConstants.MYSELF, VTCLTypeNameConstants.STAR, | |
VTCLTypeNameConstants.SUPERTYPE, VTCLTypeNameConstants.ENTITY, | |
VTCLTypeNameConstants.RELATION, VTCLTypeNameConstants.MODELELEMENT }; | |
protected final String[] builtInTypeCheckList = { | |
VTCLTypeNameConstants.MYSELF, VTCLTypeNameConstants.STAR }; | |
protected final String[] topTypeCheckList = { VTCLTypeNameConstants.TOP, | |
VTCLTypeNameConstants.STAR }; | |
protected final String[] bottomTypeCheckList = { VTCLTypeNameConstants.BOTTOM }; | |
protected String nextTypeToCheck(String typeCode, String operand) { | |
if (typeCode.equals(String.valueOf(VTCLTypeNameConstants.MYSELF))) { | |
return operand; | |
} else if (typeCode.equals(String.valueOf(VTCLTypeNameConstants.STAR))) { | |
return String.valueOf("*"); | |
} else if (typeCode.equals(String | |
.valueOf(VTCLTypeNameConstants.SUPERTYPE))) { | |
// TODO: Handle this case properly | |
return String.valueOf(VTCLTypeNameConstants.SUPERTYPE); | |
} else { | |
return typeCode; | |
} | |
} | |
private String[] createTypeCheckList(ValueKind kind, String type) { | |
if (kind.equals(ValueKind.MODELELEMENT_LITERAL)) { | |
IModelElement element = modelManager.getElementByName(type); | |
if (element != null) { | |
if (element.isEntity()) { | |
String[] resultList = { VTCLTypeNameConstants.MYSELF, | |
VTCLTypeNameConstants.STAR, | |
VTCLTypeNameConstants.SUPERTYPE, | |
VTCLTypeNameConstants.ENTITY, | |
VTCLTypeNameConstants.MODELELEMENT }; | |
return resultList; | |
} else if (element.isRelation()) { | |
String[] resultList = { VTCLTypeNameConstants.MYSELF, | |
VTCLTypeNameConstants.STAR, | |
VTCLTypeNameConstants.SUPERTYPE, | |
VTCLTypeNameConstants.RELATION, | |
VTCLTypeNameConstants.MODELELEMENT }; | |
return resultList; | |
} else { | |
// This case should never happen | |
String[] resultList = { VTCLTypeNameConstants.MYSELF, | |
VTCLTypeNameConstants.STAR, | |
VTCLTypeNameConstants.SUPERTYPE, | |
VTCLTypeNameConstants.MODELELEMENT }; | |
return resultList; | |
} | |
} | |
// TODO: Handle case when type cannot be resolved in the model space | |
else { | |
if (type.equals(VTCLTypeNameConstants.ENTITY) | |
|| type.equals("entity")) { | |
String[] resultList = { VTCLTypeNameConstants.STAR, | |
VTCLTypeNameConstants.ENTITY, | |
VTCLTypeNameConstants.MODELELEMENT }; | |
return resultList; | |
} else if (type.equals(VTCLTypeNameConstants.RELATION) | |
|| type.equals("relation")) { | |
String[] resultList = { VTCLTypeNameConstants.STAR, | |
VTCLTypeNameConstants.RELATION, | |
VTCLTypeNameConstants.MODELELEMENT }; | |
return resultList; | |
} else { | |
String[] resultList = { VTCLTypeNameConstants.STAR, | |
VTCLTypeNameConstants.MODELELEMENT }; | |
return resultList; | |
} | |
} | |
} else if (kind.equals(ValueKind.UNDEF_LITERAL)) { | |
return topTypeCheckList; | |
} else if (kind.equals(ValueKind.ERROR_LITERAL)) { | |
return bottomTypeCheckList; | |
} else { | |
return builtInTypeCheckList; | |
} | |
} | |
protected String typeCheckBinaryTerm(String termClassName, | |
Term leftOperandTerm, Term rightOperandTerm) { | |
String leftOperand = leftOperandTerm.getType(); | |
String rightOperand = rightOperandTerm.getType(); | |
String[] leftCheckList; | |
String[] rightCheckList; | |
ValueKind leftKind = leftOperandTerm.getKind(); // typeResolver.getValueKind(leftOperand); | |
ValueKind rightKind = rightOperandTerm.getKind(); // typeResolver.getValueKind(rightOperand); | |
leftCheckList = createTypeCheckList(leftKind, leftOperand); | |
rightCheckList = createTypeCheckList(rightKind, rightOperand); | |
for (String leftType : leftCheckList) { | |
String leftCheck = nextTypeToCheck(leftType, leftOperand); | |
for (String rightType : rightCheckList) { | |
String rightCheck = nextTypeToCheck(rightType, rightOperand); | |
StringTriple triple = new StringTriple(termClassName, | |
leftCheck, rightCheck); | |
BinaryTypeJudgement judgement = binaryTypeRuleMap.get(triple); | |
if (judgement != null) { | |
return judgement.getResult(); | |
} | |
} | |
} | |
// // GivenType x GivenType | |
// StringTriple triple = new StringTriple(termClassName, leftOperand, | |
// rightOperand); | |
// BinaryTypeJudgement judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// IModelElement leftElement = | |
// modelManager.getElementByName(leftOperand); | |
// IModelElement rightElement = | |
// modelManager.getElementByName(rightOperand); | |
// if (leftElement != null) { | |
// // ENTITY x GivenType | |
// if (leftElement.isEntity()) { | |
// triple = new StringTriple(termClassName, "ENTITY", rightOperand); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// if (rightElement != null) { | |
// // ENTITY x ENTITY | |
// if (rightElement.isEntity()) { | |
// triple = new StringTriple(termClassName, "ENTITY", "ENTITY"); | |
// } | |
// // ENTITY x RELATION | |
// else if (rightElement.isRelation()) { | |
// triple = new StringTriple(termClassName, "ENTITY", "RELATION"); | |
// } | |
// // ENTITY x MODELELEMENT | |
// else { | |
// triple = new StringTriple(termClassName, "ENTITY", "MODELELEMENT"); | |
// } | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// } | |
// // rightOperand cannot be resolved to a model element | |
// // else { | |
// // ENTITY x TOP | |
// triple = new StringTriple(termClassName, "ENTITY", "TOP"); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// // ENTITY x * | |
// triple = new StringTriple(termClassName, "ENTITY", "*"); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// // } | |
// } | |
// // RELATION x GivenType | |
// else if (leftElement.isRelation()) { | |
// triple = new StringTriple(termClassName, "RELATION", rightOperand); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// if (rightElement != null) { | |
// // RELATION x ENTITY | |
// if (rightElement.isEntity()) { | |
// triple = new StringTriple(termClassName, "RELATION", "ENTITY"); | |
// } | |
// // RELATION x RELATION | |
// else if (rightElement.isRelation()) { | |
// triple = new StringTriple(termClassName, "RELATION", "RELATION"); | |
// } | |
// // RELATION x MODELELEMENT | |
// else { | |
// triple = new StringTriple(termClassName, "RELATION", "MODELELEMENT"); | |
// } | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// } | |
// // rightOperand cannot be resolved to a model element | |
// // else { | |
// // RELATION x TOP | |
// triple = new StringTriple(termClassName, "RELATION", "TOP"); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// // RELATION x * | |
// triple = new StringTriple(termClassName, "RELATION", "*"); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// // } | |
// } | |
// // MODELELEMENT x GivenType | |
// else { | |
// triple = new StringTriple(termClassName, "MODELELEMENT", | |
// rightOperand); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// if (rightElement != null) { | |
// // MODELELEMENT x ENTITY | |
// if (rightElement.isEntity()) { | |
// triple = new StringTriple(termClassName, "MODELELEMENT", "ENTITY"); | |
// } | |
// // MODELELEMENT x RELATION | |
// else if (rightElement.isRelation()) { | |
// triple = new StringTriple(termClassName, "MODELELEMENT", "RELATION"); | |
// } | |
// // MODELELEMENT x MODELELEMENT | |
// else { | |
// triple = new StringTriple(termClassName, "MODELELEMENT", | |
// "MODELELEMENT"); | |
// } | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// } | |
// // rightOperand cannot be resolved to a model element | |
// // else { | |
// // MODELELEMENT x TOP | |
// triple = new StringTriple(termClassName, "MODELELEMENT", "TOP"); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// // ENTITY x * | |
// triple = new StringTriple(termClassName, "MODELELEMENT", "*"); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// // } | |
// } | |
// } | |
// // leftOperand cannot be resolved to a model element | |
// // else { | |
// // TOP X GivenType | |
// triple = new StringTriple(termClassName, "TOP", rightOperand); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// if (rightElement != null) { | |
// // TOP x ENTITY | |
// if (rightElement.isEntity()) { | |
// triple = new StringTriple(termClassName, "TOP", "ENTITY"); | |
// } | |
// // TOP x RELATION | |
// else if (rightElement.isRelation()) { | |
// triple = new StringTriple(termClassName, "TOP", "RELATION"); | |
// } | |
// // TOP x MODELELEMENT | |
// else { | |
// triple = new StringTriple(termClassName, "TOP", "MODELELEMENT"); | |
// } | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// } | |
// // rightOperand cannot be resolved to a model element | |
// // else { | |
// // TOP x TOP | |
// triple = new StringTriple(termClassName, "TOP", "TOP"); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// // TOP x * | |
// triple = new StringTriple(termClassName, "TOP", "*"); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// // } | |
// | |
// // * X GivenType | |
// triple = new StringTriple(termClassName, "*", rightOperand); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// if (rightElement != null) { | |
// // * x ENTITY | |
// if (rightElement.isEntity()) { | |
// triple = new StringTriple(termClassName, "*", "ENTITY"); | |
// } | |
// // * x RELATION | |
// else if (rightElement.isRelation()) { | |
// triple = new StringTriple(termClassName, "*", "RELATION"); | |
// } | |
// // * x MODELELEMENT | |
// else { | |
// triple = new StringTriple(termClassName, "*", "MODELELEMENT"); | |
// } | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// } | |
// // rightOperand cannot be resolved to a model element | |
// // else { | |
// // * x TOP | |
// triple = new StringTriple(termClassName, "*", "TOP"); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// // * x * | |
// triple = new StringTriple(termClassName, "*", "*"); | |
// judgement = binaryTypeRuleMap.get(triple); | |
// if (judgement != null) { | |
// return judgement.getResult(); | |
// } | |
// // } | |
// // } | |
return VTCLTypeNameConstants.BOTTOM; | |
} | |
protected String typeCheckUnaryTerm(String termClassName, Term operand) { | |
String operandStr = operand.getType(); | |
String resultType = VTCLTypeNameConstants.BOTTOM; | |
// XXX when multiple custom judgements are available, the result might | |
// vary | |
// Handle custom type judgment | |
List<CustomTypeJudgement> customList = customTypeRuleMap | |
.get(termClassName); | |
if (customList != null) { | |
for (CustomTypeJudgement customJudgement : customList) { | |
if (customJudgement.getName().equals("typeSource")) { | |
resultType = CustomTypeJudgementCheck.typeSource( | |
modelManager, operandStr); | |
} else if (customJudgement.getName().equals("typeTarget")) { | |
resultType = CustomTypeJudgementCheck.typeTarget( | |
modelManager, operandStr); | |
} else if (customJudgement.getName().equals("typeInverse")) { | |
resultType = CustomTypeJudgementCheck.typeInverse( | |
modelManager, operandStr); | |
} else if (customJudgement.getName().equals( | |
"typeElementReference")) { | |
resultType = CustomTypeJudgementCheck.typeElementReference( | |
modelManager, operand); | |
} | |
} | |
} | |
// If Custom judgement was successful, return its result | |
if (resultType != VTCLTypeNameConstants.BOTTOM) { | |
return resultType; | |
} | |
String[] leftCheckList; | |
ValueKind leftKind = operand.getKind();// typeResolver.getValueKind(operandStr); | |
leftCheckList = createTypeCheckList(leftKind, operandStr); | |
// XXX in case of multiple matching unary type rules the result may vary | |
for (String leftType : leftCheckList) { | |
String leftCheck = nextTypeToCheck(leftType, operandStr); | |
StringPair pair = new StringPair(termClassName, leftCheck); | |
UnaryTypeJudgement judgement = unaryTypeRuleMap.get(pair); | |
if (judgement != null) { | |
return judgement.getResult(); | |
} | |
} | |
// | |
// // Handle unary type judgment: with given operand | |
// StringPair pair = new StringPair(termClassName, operand); | |
// UnaryTypeJudgement unaryJudgement = unaryTypeRuleMap.get(pair); | |
// if (unaryJudgement != null) { | |
// return unaryJudgement.getResult(); | |
// } | |
// IModelElement element = modelManager.getElementByName(operand); | |
// // Handle unary type judgment: with ENTITY or RELATION | |
// if (element != null) { | |
// if (element.isEntity()) { | |
// pair = new StringPair(termClassName, "ENTITY"); | |
// } | |
// else if (element.isRelation()) { | |
// pair = new StringPair(termClassName, "RELATION"); | |
// | |
// } | |
// // Handle unary type judgment: with MODELELEMENT | |
// else { | |
// pair = new StringPair(termClassName, "MODELELEMENT"); | |
// } | |
// unaryJudgement = unaryTypeRuleMap.get(pair); | |
// if (unaryJudgement != null) { | |
// return unaryJudgement.getResult(); | |
// } | |
// } | |
// // else { | |
// // Handle unary type judgment: with TOP | |
// pair = new StringPair(termClassName, "TOP"); | |
// unaryJudgement = unaryTypeRuleMap.get(pair); | |
// if (unaryJudgement != null) { | |
// return unaryJudgement.getResult(); | |
// } | |
// // Handle unary type judgment: with * | |
// pair = new StringPair(termClassName, "*"); | |
// unaryJudgement = unaryTypeRuleMap.get(pair); | |
// if (unaryJudgement != null) { | |
// return unaryJudgement.getResult(); | |
// } | |
// // } | |
return resultType; | |
} | |
} |