/**
* This class contains the implementation of the contract inference
*/
package deadlock.analyser.inference;
import abs.frontend.ast.*;
import abs.frontend.typechecker.*;
import abs.frontend.typechecker.KindedName.Kind;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.LinkedList;
import java.util.Map;
import java.util.Set;
import choco.kernel.common.util.tools.ArrayUtils;
import com.gzoumix.semisolver.constraint.Constraint;
import com.gzoumix.semisolver.term.*;
import deadlock.analyser.AnalyserLog;
import deadlock.analyser.factory.*;
import deadlock.analyser.generation.*;
/**
* @author Abel, Michael
*
*/
public class ContractInference {
private static final String _initName = "!init!";
private static final String _runName = "run";
private static final String _destinyName = "!destiny!";
private static final String _this = "this";
private static final String _dummyMethod = "!dummy";
private static final String _dummyClass = "!Dummy";
private static final String _dummyModule = "!Dummy";
private static ClassDecl _emptyDecl;
private AnalyserLog _log;
private Factory _df;
private Map<InterfaceDecl, ClassDecl> _intertoclass;
private Model _model;
private TypingEnvironment _env;
private GroupName _a;
private ClassDecl _cd;
public ContractInference(AnalyserLog log, Factory df, Model m) {
_log = log;
_df = df;
_intertoclass = null;
_model = m;
_env = new TypingEnvironment();
_a = null;
_cd = null;
_emptyDecl = new ClassDecl();
_emptyDecl.setName(_dummyClass);
MethodSig methodSig = new MethodSig(_dummyMethod, new abs.frontend.ast.List<Annotation>(), new DataTypeUse(),
new abs.frontend.ast.List<ParamDecl>());
MethodImpl node = new MethodImpl(methodSig, new Block(), false);
_emptyDecl.addMethod(node);
}
/************************************/
/* Helper function */
/************************************/
// create a record instance of the particular class, living in the cog a
public RecordPresent createInstance(ClassDecl cd, GroupName a) {
LinkedList<RecordField> l = new LinkedList<RecordField>();
for (ParamDecl f : cd.getParams()) {
RecordVariable X = _df.newRecordVariable();
l.add(_df.newRecordField(f.getName(), X));
}
for (FieldDecl f : cd.getFields()) {
l.add(_df.newRecordField(f.getName(), _df.newRecordVariable())); // init
// expressions
// are
// managed
// in
// the
// analysis
// of
// the
// init
// block.
}
return _df.newRecordPresent(a, l);
}
private RecordPresent createInstance(Type t, ClassDecl clthis, GroupName a) {
ClassDecl cl;
if (t.isInterfaceType()) {
cl = _intertoclass.get(((InterfaceType) t).getDecl());
} else {
cl = clthis;
}
if (cl == null) {
_log.logError("Class retrival failed!!!");
} // should NEVER occur
return this.createInstance(cl, a);
}
/************************************/
/* Map Interface_name to Class_name */
/************************************/
/*
* This mapping is used so we can associate a contract to an interface, not
* only a class. In the original paper, there was no interfaces, and we
* could directly get the contract of a method call by looking to the type
* of the called object. In ABS, this is not true anymore, so we use this
* trick. This means that two classes cannot implement the same interface,
* otherwise we once again don't know what is the contract of the interface.
*/
// reviewed //
public void computeMapInterfaceToClass() {
Map<InterfaceDecl, ClassDecl> res = new HashMap<InterfaceDecl, ClassDecl>();
List<InterfaceDecl> allInterfaces = new LinkedList<InterfaceDecl>();
for (Decl decl : _model.getDecls()) {
if (decl instanceof ClassDecl) {
// 1. Computes recursively the set of all interfaces the class
// extends
Set<InterfaceTypeUse> toAdd = new HashSet<InterfaceTypeUse>();
Set<InterfaceTypeUse> set = new HashSet<InterfaceTypeUse>();
Set<InterfaceTypeUse> tmp = new HashSet<InterfaceTypeUse>();
for (InterfaceTypeUse it : ((ClassDecl) decl).getImplementedInterfaceUses()) {
toAdd.add(it);
}
while (!toAdd.isEmpty()) {
Iterator<InterfaceTypeUse> i = toAdd.iterator();
while (i.hasNext()) {
InterfaceTypeUse it = i.next();
if ((!set.contains(it)) && (it.getType() instanceof InterfaceType)) {
set.add(it);
for (InterfaceTypeUse itin : ((InterfaceType) it.getType()).getDecl()
.getExtendedInterfaceUses()) {
tmp.add(itin);
}
}
}
toAdd = tmp;
tmp = new HashSet<InterfaceTypeUse>();
}
// 2. add these interfaces to the map
for (InterfaceTypeUse it : set) {
InterfaceDecl d = ((InterfaceType) it.getType()).getDecl();
if (res.containsKey(d)) {
_log.logWarning("WARNING: the class \"" + res.get(d).getName() + "\" and \""
+ ((ClassDecl) decl).qualifiedName() + "\" both implement the interface \""
+ d.qualifiedName() + "\"."
+ "This will probably cause an erroneous deadlock analysis");
} else {
res.put(d, (ClassDecl) decl);
}
}
} else if (decl instanceof InterfaceDecl)
allInterfaces.add((InterfaceDecl) decl);
}
allInterfaces.removeAll(res.keySet());
for (InterfaceDecl notImplInterface : allInterfaces) {
res.put(notImplInterface, _emptyDecl);
}
_intertoclass = res;
}
/************************************/
/* Environment Creation */
/************************************/
public void computeEnvironment() {
for (CompilationUnit cu : _model.getCompilationUnits()) {
for (ModuleDecl md : cu.getModuleDecls()) {
for (Decl d : md.getDecls()) {
if (d instanceof ClassDecl) {
computeEnvironment(((ClassDecl) d), md.getName());
} else if (d instanceof FunctionDecl) {
computeEnvironment(((FunctionDecl) d), md.getName());
} else if (d instanceof DataTypeDecl) {
computeEnvironment(((DataTypeDecl) d), md.getName());
}
}
}
}
computeEnvironment(_emptyDecl, _dummyModule);
}
// method declaration
public void computeEnvironment(ClassDecl cd, String moduleName) {
if (cd == _emptyDecl)
return;
// Methods
for (MethodImpl m : cd.getMethods()) {
_log.logNormal("Generating initial environment for the method \"" + cd.getName() + "."
+ m.getMethodSig().getName() + "\"");
// 1. Record of "this"
IRecord rthis = createInstance(cd, _df.newGroupName());
// 2. Simple variables for the method parameters
LinkedList<IRecord> rparam = new LinkedList<IRecord>();
for (ParamDecl p : m.getMethodSig().getParams()) {
rparam.add(_df.newRecordVariable());
}
// 3. Simple variable for the return object (or datatype)
RecordVariable rres = _df.newRecordVariable();
// 4. Finalize
MethodInterface mIntf = _df.newMethodInterface(rthis, rparam, rres);
_env.putMethod(moduleName, cd.getName(), m.getMethodSig().getName(), mIntf);
}
// 2. init
MethodInterface mi = _df.newMethodInterface(createInstance(cd, _df.newGroupName()), new LinkedList<IRecord>(),
_df.newRecordVariable());
_env.putMethod(moduleName, cd.getName(), _initName, mi);
}
// functions declaration
public void computeEnvironment(FunctionDecl decl, String moduleName) {
String name = decl.getName();
// 1. type parameters
HashMap<String, RecordVariable> typeParameterMap = new HashMap<>();
if (decl instanceof ParametricFunctionDecl) {
for (TypeParameterDecl args : ((ParametricFunctionDecl) decl).getTypeParameterList()) {
typeParameterMap.put(args.getName(), _df.newRecordVariable());
}
}
// 2. parameters, result record, and put the resulting Function
// Interface in the typing environment
List<Term> l = new LinkedList();
for (ParamDecl pd : decl.getParamList()) {
Access a = pd.getAccess(); // get the type of the parameter
if (a instanceof TypeUse) {
l.add(expandArgs((TypeUse) a, typeParameterMap));
} else {
_log.logError("unable to retrieve the type of the parameter \"" + pd.getName() + "\" of Function \""
+ moduleName + "." + name + "\"");
return;
} // should never occur
}
_env.putFunction(moduleName, name, new FunctionInterface(l, expandArgs(decl.getTypeUse(), typeParameterMap)));
}
private Term expandArgs(TypeUse arg, HashMap<String, RecordVariable> map) {
if (arg instanceof DataTypeUse) { // datatype
java.util.List<Term> l = new LinkedList<>();
if (arg instanceof ParametricDataTypeUse) { // it is recursive
for (TypeUse subarg : ((ParametricDataTypeUse) arg).getParamList()) {
l.add(this.expandArgs(subarg, map));
}
}
return _df.newTerm(arg.getName(), l);
} else if (arg instanceof InterfaceTypeUse) {
ClassDecl c = _intertoclass.get(((InterfaceTypeUse) arg).getDecl());
return createInstance(c, _df.newGroupName());
} else if (arg instanceof TypeParameterUse) { // we have a variable
return map.get(((TypeParameterUse) arg).getName());
}
// Should never occur...
_log.logError("Unknown error in method expandArgs of deadlock analysis");
return null;
}
// datatype declaration
public void computeEnvironment(DataTypeDecl decl, String moduleName) { // TODO
}
/************************************/
/* TYPE INFERENCE */
/************************************/
// ResultInferenceStmt stands for
// 'deadlock.constraints.constraint.ConstraintGeneration_output'.
// Suppose that 'ResultInferenceStmt' is class type containing three
// value (Record r, Contract c,
// deadlock.constraints.constraint.ConstraintStore U)
// Suppose that ResultInferenceStmt has method getRecord() setRecord(),
// getContract setContract addContract accumulateContract()
// "the )( operator",
// getdeadlock.constraints.constraint.ConstraintStore,
// setdeadlock.constraints.constraint.ConstraintStore,
// adddeadlock.constraints.constraint.Constraint(),
// adddeadlock.constraints.constraint.ConstraintStore()
// because of all the methods different from get/set needs the Factory, we
// perform that operation outside ResultInferenceStmt class.
// itfToClass is an HashMap that bind InterfaceName to ClassDelc, this is
// done because in ABS Interface are type and Class are not.
// ////////////////////////////////////////////////////////////////////////////
// 1. Model, Compilation Units (files), Classes and methods
// ////////////////////////////////////////////////////////////////////////////
public ResultInference typeInference() {
ResultInference res = new ResultInference();
_log.logDebug("Initial Environment:\n" + _env.toString());
// 1. methods
for (CompilationUnit cu : _model.getCompilationUnits()) {
res.add(typeInference(cu));
}
// 2. main
/*
* _a = _df.newGroupName(); ResultInferenceStmt resMain =
* typeInference(_model.getMainBlock());
*
* res.add(resMain.getConstraint()); Contract co =
* _df.newContractEmpty(); for(TypingEnvironment te :
* resMain.getEnvironment()) co =
* _df.newContractUnion(_model.getMainBlock(), co,
* _df.newContract(te.unsync(_model.getMainBlock())));
* res.setMain(resMain.getContract(), co);
*/
return res;
}
public ResultInference typeInference(CompilationUnit cu) {
ResultInference res = new ResultInference();
_log.logDebug("Contract Inference for the file \"" + cu.getName() + "\"");
_log.beginIndent();
Set<String> searchPath = new HashSet<>();
for (ModuleDecl md : cu.getModuleDecls()) {
searchPath.add(md.getName());
res.add(typeInference(md));
}
if (cu.hasMainBlock()) {
searchPath.add("ABS.StdLib");
_env.setSearchPath(searchPath);
_a = _df.newGroupName();
ResultInferenceStmt resMain = typeInference(cu.getMainBlock());
res.add(resMain.getConstraint());
Contract co = _df.newContractEmpty();
for (TypingEnvironment te : resMain.getEnvironment())
co = _df.newContractUnion(cu.getMainBlock(), co, _df.newContract(te.unsync(_model.getMainBlock())));
res.setMain(resMain.getContract(), co);
}
_log.endIndent();
return res;
}
public ResultInference typeInference(ModuleDecl md) {
ResultInference res = new ResultInference();
_log.logDebug("Contract Inference for the module \"" + md.getName() + "\"");
_log.beginIndent();
// 1. add the import to the visibility list
_env.addSearchPath(md.getName()); // current library
_env.addSearchPath("ABS.StdLib"); // default library
for (Import imp : md.getImportList()) {
if (imp instanceof NamedImport) {
for (Name name : ((NamedImport) imp).getNameList())
_env.addSearchPath(name.getName());
} // WARNING: not sure what that is, there are no usage examples
// from the examples
else if (imp instanceof StarImport) {
_env.addSearchPath(((StarImport) imp).getModuleName());
} else if (imp instanceof FromImport) {
_env.addSearchPath(((FromImport) imp).getModuleName());
} // WARNING: we are not precise, we include all declaration from
// the module
}
_log.logDebug("module " + md.getName() + ": initial search path = " + _env.toStringSearchPath());
for (Decl d : md.getDecls()) {
if (d instanceof ClassDecl) {
res.add(typeInference(((ClassDecl) d)));
} else if (d instanceof FunctionDecl) {
} // TODO: add function definition
}
_env.resetSearchPath();
_log.endIndent();
return res;
}
public ResultInference typeInference(ClassDecl cd) {
ResultInference res = new ResultInference();
if (cd == _emptyDecl)
return res;
_log.logDebug("Contract Inference for the class \"" + cd.getName() + "\"");
_log.beginIndent();
_cd = cd;
// 1. Methods
for (MethodImpl m : cd.getMethods()) {
res.add(typeInference(m));
}
// 2. Init
MethodInterface mi = _env.getMethod(cd.getName(), _initName);
IRecord thisRecord = mi.getThis();
_a = ((RecordPresent) thisRecord).getRoot();
Constraint c = _df.newConstraint();
Contract cp, cf;
_env.newScope();
_env.putVariable(_this, thisRecord);
// 2.1. Field assignments
for (FieldDecl f : cd.getFields()) {
if (f.hasInitExp()) {
ResultInferencePureExp tmp = typeInferenceAsPure(f.getInitExp());
c.add(tmp.getConstraint());
c.addEquation(new ASTNodeInformation(f), ((RecordPresent) thisRecord).getField(f.getName()),
_env.getRecord(tmp.getVariableType()));
}
}
// 2.2. Init block
if (cd.hasInitBlock()) {
ResultInferenceStmt resInitBlock = typeInference(cd.getInitBlock());
cp = resInitBlock.getContract();
c.add(resInitBlock.getConstraint());
cf = _df.newContractEmpty();
for (TypingEnvironment te : resInitBlock.getEnvironment())
cf = _df.newContractUnion(cd.getInitBlock(), cf, _df.newContract(te.unsync(cd.getInitBlock())));
} else {
cp = _df.newContractEmpty();
cf = _df.newContractEmpty();
}
// 2.3. add the call to run if the method exists.
if (_env.getMethod(cd.getName(), _runName) != null) {
ASTNode node = (cd.hasInitBlock() ? cd.getInitBlock() : cd);
MethodInterface mirun = _df.newMethodInterface(thisRecord, new LinkedList<IRecord>(),
_df.newRecordVariable());
c.addSemiEquation(new ASTNodeInformation(node), _env.getMethod(cd.getName(), _runName), mirun);
List<Contract> tmp = new LinkedList<>();
tmp.add(cf);
tmp.add(_df.newContractInvk(node, cd.getName(), _runName, mirun));
cf = _df.newContractParallel(node, tmp);
}
res.add(c);
res.add(cd.getName(), _initName, _df.newMethodContract(mi, cp, cf));
_env.clearFutures();
_env.clearVariables();
_log.endIndent();
_log.logDebug("Inference for the class \"" + cd.getName() + "\" Finished");
return res;
}
public ResultInference typeInference(MethodImpl mImp) {
_log.logDebug(
"Contract Inference for the method \"" + _cd.getName() + "." + mImp.getMethodSig().getName() + "\"");
_log.beginIndent();
// 1. Generate the environment for the contract inference
_env.newScope();
MethodInterface mi = _env.getMethod(_cd.getName(), mImp.getMethodSig().getName());
IRecord thisRecord = mi.getThis();
List<IRecord> params = mi.getParameters();
IRecord result = mi.getResult();
_a = ((RecordPresent) thisRecord).getRoot();
_env.putVariable(_this, thisRecord); // WARNING: problem with inference
// if futures in this
Iterator<IRecord> it = params.iterator();
for (ParamDecl p : mImp.getMethodSig().getParams()) {
if (p.getType().isFutureType()) {
TypingEnvironmentVariableTypeFuture f = new TypingEnvironmentVariableTypeFuture();
_env.putVariable(p.getName(), f);
_env.putFuture(f, new TypingEnvironmentFutureTypeTick(it.next()));
} else {
_env.putVariable(p.getName(), it.next());
}
}
_env.putVariable(_destinyName, result);
// 2. perform the inference
ResultInferenceStmt resBlock = typeInference(mImp.getBlock());
// 4. give back the result.
ResultInference res = new ResultInference();
Contract co = _df.newContractEmpty();
for (TypingEnvironment te : resBlock.getEnvironment())
co = _df.newContractUnion(mImp, co, _df.newContract(te.unsync(mImp)));
res.add(_cd.getName(), mImp.getMethodSig().getName(), _df.newMethodContract(mi, resBlock.getContract(), co));
res.add(resBlock.getConstraint());
_env.clearFutures();
_env.clearVariables();
_log.endIndent();
_log.logDebug("Inference for Method Block Finished");
return res;
}
// ////////////////////////////////////////////////////////////////////////////
// 2. Rules
// ////////////////////////////////////////////////////////////////////////////
// ////////////////////////////////////////////////////////////////////////////
// 2.1. Generic inference rules, for nodes that are not yet managed by the
// inference
private Method getInferenceMethod(Class dynamicClass, Class staticClass, Class... parameters) {
return getInferenceMethod("typeInference", dynamicClass, staticClass, parameters);
}
private Method getInferenceMethod(String methodName, Class dynamicClass, Class staticClass, Class... parameters) {
Class newc = dynamicClass;
Method m = null;
Class[] params = new Class[parameters.length + 1];
for (int i = 0; i < parameters.length; i++)
params[i + 1] = parameters[i];
// Try the superclasses
while (m == null && newc != staticClass) {
try {
params[0] = newc;
m = getClass().getMethod(methodName, params);
} catch (NoSuchMethodException e) {
newc = newc.getSuperclass();
}
}
return m;
}
public ResultInferenceStmt typeInference(Decl d) {
Method m = getInferenceMethod(d.getClass(), Decl.class);
if (m != null)
try {
return (ResultInferenceStmt) m.invoke(this, d);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
_log.logWarning("WARNING: Contract inference not implemented for declaration \"" + d.getClass().getName()
+ "\". Assumed empty contract and constraint");
return new ResultInferenceStmt(_df.newContractEmpty(), _df.newConstraint(), _env);
}
public ResultInferenceStmt typeInference(Stmt s) {
Method m = getInferenceMethod(s.getClass(), Stmt.class);
if (m != null)
try {
return (ResultInferenceStmt) m.invoke(this, s);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
_log.logWarning("WARNING: Contract inference not implemented for statement \"" + s.getClass().getName()
+ "\". Assumed empty contract and constraint");
return new ResultInferenceStmt(_df.newContractEmpty(), _df.newConstraint(), _env);
}
public ResultInferenceEffExp typeInference(Exp e) {
Method m = getInferenceMethod(e.getClass(), Exp.class);
if (m != null)
try {
return (ResultInferenceEffExp) m.invoke(this, e);
} catch (IllegalAccessException e1) {
e1.printStackTrace();
} catch (IllegalArgumentException e1) {
e1.printStackTrace();
} catch (InvocationTargetException e1) {
e1.printStackTrace();
}
_log.logWarning("WARNING: Contract inference not implemented for Expression \"" + e.getClass().getName()
+ "\". Assumed Unit Type");
return new ResultInferenceEffExp(_df.newRecordVariable(), _df.newContractEmpty(), _df.newConstraint(), _env);
}
public ResultInferencePureExp typeInferenceAsPure(PureExp exp) {
Method m = getInferenceMethod("typeInferenceAsPure", exp.getClass(), PureExp.class);
if (m != null)
try {
return (ResultInferencePureExp) m.invoke(this, exp);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
_log.logWarning("WARNING: Contract inference not implemented for Expression \"" + exp.getClass().getName()
+ "\". Assumed Unit Type");
// return new ResultInferencePureExp(_df,
// _df.newRecordDataType(env.getUnitType(), new LinkedList<IRecord>()));
return new ResultInferencePureExp(_df, _df.dummyDataType());
}
public ResultInferenceEffExp typeInference(PureExp pexp) {
Method m = getInferenceMethod(pexp.getClass(), PureExp.class);
if (m != null)
try {
return (ResultInferenceEffExp) m.invoke(this, pexp);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
ResultInferencePureExp resPure = typeInferenceAsPure(pexp);
return new ResultInferenceEffExp(resPure.getVariableType(), _df.newContractEmpty(), _df.newConstraint(), _env);
}
public ResultInferencePureExp typeInference(Guard g) {
Method m = getInferenceMethod(g.getClass(), Guard.class);
if (m != null)
try {
return (ResultInferencePureExp) m.invoke(this, g);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
_log.logWarning("WARNING: Contract inference not implemented for Guard \"" + g.getClass().getName()
+ "\". Assumed Boolean Type");
// return new ResultInferencePureExp(_df,
// _df.newRecordDataType(env.getBoolType(), new LinkedList<IRecord>()));
return new ResultInferencePureExp(_df, _df.dummyDataType());
}
// /////////////////////////////////////////////////////////////////////////////
// 2.2. Declarations
public ResultInferenceStmt typeInference(VarDecl vd) {
_log.logDebug("Contract Inference for the VarDecl \"" + vd.getName() + "\"");
_log.beginIndent();
Contract contract;
Constraint c;
ITypingEnvironmentVariableType X;
if (vd.hasInitExp()) {
Exp exp = vd.getInitExp();
if (exp instanceof PureExp) {
ResultInferencePureExp resInitExp = typeInferenceAsPure((PureExp) exp);
contract = _df.newContractEmpty();
c = _df.newConstraint();
X = resInitExp.getVariableType();
} else {
ResultInferenceEffExp resInitExp = typeInference((EffExp) exp);
contract = resInitExp.getContract();
c = resInitExp.getConstraint();
X = resInitExp.getRecord();
}
} else {
contract = _df.newContractEmpty();
c = _df.newConstraint();
X = _df.newRecordVariable();
}
_env.putVariable(vd.getName(), X);
return new ResultInferenceStmt(contract, c, _env);
}
// ////////////////////////////////////////////////////////////////////////////
// 2.3. Statments
public ResultInferenceStmt typeInference(AssignStmt astmt) {
_log.logDebug("Contract Inference for the AssignStmt");
_log.beginIndent();
String name = astmt.getVar().getName();
Contract contract;
Constraint c;
ITypingEnvironmentVariableType X;
Exp exp = astmt.getValue();
if (exp instanceof PureExp) {
ResultInferencePureExp resValue = typeInferenceAsPure((PureExp) exp);
contract = _df.newContractEmpty();
c = _df.newConstraint();
X = resValue.getVariableType();
} else {
ResultInferenceEffExp resValue = typeInference((EffExp) exp);
contract = resValue.getContract();
c = resValue.getConstraint();
X = resValue.getRecord();
}
_log.endIndent();
_log.logDebug("AssignStmt Sub-Expression Finished");
if (_env.isField(name)) {
c.addEquation(new ASTNodeInformation(astmt), _env.getVariableRecord(name), (IRecord) X);
} else {
_env.putVariable(name, X);
}
return new ResultInferenceStmt(contract, c, _env);
}
public ResultInferenceStmt typeInference(AwaitStmt astmt) {
_log.logDebug("Contract Inference for the AwaitStmt");
_log.beginIndent();
Contract contract;
Constraint c = _df.newConstraint();
GroupName aprime = _df.newGroupName();
// 1. First look if there is some annotation defined
Iterator<Annotation> it = astmt.getAnnotations().iterator();
if (it.hasNext()) {
PureExp dep = it.next().getValue();
ResultInferencePureExp resAnn = typeInferenceAsPure(dep);
contract = _df.newContractAwait(astmt, aprime, _a);
_log.endIndent();
_log.logDebug("AwaitStmt Annotation Finished");
c.addEquation(new ASTNodeInformation(astmt), (IRecord) resAnn.getVariableType(),
createInstance(dep.getType(), _cd, aprime));
return new ResultInferenceStmt(contract, c, _env);
} else {
ResultInferencePureExp resGuard = typeInference(astmt.getGuard());
_log.endIndent();
_log.logDebug("AwaitStmt Sub-Expression Finished");
if (resGuard.getVariableType() instanceof TypingEnvironmentVariableTypeFuture) {
ITypingEnvironmentFutureType z = _env
.getFuture((TypingEnvironmentVariableTypeFuture) resGuard.getVariableType());
if (z instanceof TypingEnvironmentFutureTypeUntick) {
_env.putFuture((TypingEnvironmentVariableTypeFuture) resGuard.getVariableType(),
new TypingEnvironmentFutureTypeTick(z.getRecord()));
c.addEquation(new ASTNodeInformation(astmt), z.getRecord(),
_df.newRecordFuture(aprime, _df.newRecordVariable()));
contract = _df.newContract(_df.newContractElementParallel(
_df.newContractInvkA(astmt, ((TypingEnvironmentFutureTypeUntick) z).getContract(),
new ContractElementAwait(astmt, _a, aprime)),
_env.unsync(astmt)));
} else {
try {
c.addEquation(new ASTNodeInformation(astmt), z.getRecord(),
_df.newRecordFuture(aprime, _df.newRecordVariable()));
} catch (Exception e) {
e.getMessage();
}
contract = _df.newContractEmpty();
}
} else {
// the guard in the await is not a future.
// maybe a boolean or something else, in any case, we cannot
// manage it for now
_log.logWarning("WARNING: the guard of the await statement is not a future. Assumed an empty contract");
contract = _df.newContractEmpty();
}
return new ResultInferenceStmt(contract, c, _env);
}
}
public ResultInferenceStmt typeInference(SkipStmt skip) {
return new ResultInferenceStmt(_df.newContractEmpty(), _df.newConstraint(), _env);
}
public ResultInferenceStmt typeInference(SuspendStmt susp) {
return new ResultInferenceStmt(_df.newContractEmpty(), _df.newConstraint(), _env);
}
public ResultInferenceStmt typeInference(DurationStmt dration) {
return new ResultInferenceStmt(_df.newContractEmpty(), _df.newConstraint(), _env);
}
public ResultInferenceStmt typeInference(ReturnStmt res) {
_log.logDebug("Contract Inference for the ReturnStmt");
_log.beginIndent();
ResultInferenceEffExp resRetExp = typeInference(res.getRetExp());
_log.endIndent();
_log.logDebug("ReturnStmt Sub-Expression Finished");
Contract contract = resRetExp.getContract();
Constraint c = resRetExp.getConstraint();
c.addEquation(new ASTNodeInformation(res), _env.getVariableRecord(_destinyName),
_env.getRecord(resRetExp.getRecord()));
return new ResultInferenceStmt(contract, c, resRetExp.getEnvironment());
}
public ResultInferenceStmt typeInference(ExpressionStmt exp) {
_log.logDebug("Contract Inference for the ExpressionStmt");
_log.beginIndent();
ResultInferenceEffExp resExp = typeInference(exp.getExp());
_log.endIndent();
_log.logDebug("ExpressionStmt Sub-Expression Finished");
return new ResultInferenceStmt(resExp.getContract(), resExp.getConstraint(), resExp.getEnvironment());
}
public ResultInferenceStmt typeInference(AssertStmt ass) {
_log.logDebug("Contract Inference for the AssertStmt");
return new ResultInferenceStmt(_df.newContractEmpty(), _df.newConstraint(), _env);
}
public ResultInferenceStmt typeInference(VarDeclStmt vd) {
_log.logDebug("Contract Inference for the VarDeclStmt");
_log.beginIndent();
ResultInferenceStmt resVarDecl = typeInference(vd.getVarDecl());
_log.endIndent();
_log.logDebug("VarDeclStmt Sub-Expression Finished");
return resVarDecl;
}
public ResultInferenceStmt typeInference(IfStmt ifstmt) {
_log.logDebug("Contract inference of a Conditional Statement");
_log.beginIndent();
TypingEnvironment tmp = _env.copy();
ResultInferenceStmt resThen = typeInference(ifstmt.getThen());
List<TypingEnvironment> resultEnvs = new LinkedList<>();
resultEnvs.addAll(resThen.getEnvironment());
Contract contract;
Constraint c = resThen.getConstraint();
if (ifstmt.hasElse()) {
this._env = tmp;
ResultInferenceStmt resElse = typeInference(ifstmt.getElse());
c.add(resElse.getConstraint());
resultEnvs.addAll(resElse.getEnvironment());
contract = _df.newContractUnion(ifstmt, resThen.getContract(), resElse.getContract());
} else {
resultEnvs.add(tmp);
contract = _df.newContractUnion(ifstmt, resThen.getContract(), _df.newContractEmpty());
}
_log.endIndent();
_log.logDebug("IfStmt Sub-Statments Finished");
return new ResultInferenceStmt(contract, c, resultEnvs);
}
public ResultInferenceStmt typeInference(WhileStmt whilestmt) {
_log.logDebug("Contract Inference for the While (Approximated with one iteration)");
_log.beginIndent();
ResultInferenceStmt resStmt = typeInference(whilestmt.getBody());
_log.endIndent();
_log.logDebug("While Sub-Statments Finished");
return resStmt;
}
public ResultInferenceStmt typeInference(Block b) {
_log.logDebug("Contract Inference for the Block");
_log.beginIndent();
_env.newScope();
// accumulate contracts and constraint.Constraints
// in the resulting output
ResultInferenceStmt resStmt = null;
Constraint c = _df.newConstraint();
Contract contract = _df.newContractEmpty();
List<TypingEnvironment> envs = new LinkedList<TypingEnvironment>();
envs.add(_env);
for (Stmt s : b.getStmts()) {
List<TypingEnvironment> cumul = new LinkedList<TypingEnvironment>();
Contract current = null;
for (TypingEnvironment tmpEnv : envs) {
_env = tmpEnv;
resStmt = typeInference(s);
c.add(resStmt.getConstraint());
cumul.addAll(resStmt.getEnvironment());
current = (current == null) ? resStmt.getContract()
: _df.newContractUnion(b, current, resStmt.getContract());
}
envs = cumul;
contract.add(current);
}
_log.endIndent();
_log.logDebug("Block Sub-Expression Finished");
for (TypingEnvironment env : envs) {
env.popScope();
}
return new ResultInferenceStmt(contract, c, envs);
}
// ////////////////////////////////////////////////////////////////////////////
// 2.4. Expressions
// 2.4.1. Pure Expressions
public ResultInferencePureExp typeInferenceAsPure(NullExp exp) {
_log.logDebug("Contract Inference for the 'null' PureExp");
return new ResultInferencePureExp(_df, _df.newRecordVariable());
}
public ResultInferencePureExp typeInferenceAsPure(ThisExp exp) {
_log.logDebug("Contract Inference for the 'this' PureExp");
return new ResultInferencePureExp(_df, _env.getVariableRecord(_this));
}
public ResultInferencePureExp typeInferenceAsPure(VarOrFieldUse var) {
_log.logDebug("Contract Inference for the VarOrFieldUse");
return new ResultInferencePureExp(_df, _env.getVariable(var.getName()));
}
// DATATYPES YEAH
/*
* //reviewed// public ResultInferencePureExp
* typeInferenceAsPure(StringLiteral lit, String ident, TypingEnvironment
* env, GroupName a, Map<InterfaceDecl, ClassDecl> intertoclass, Factory df,
* ClassDecl cl) { if (ident != null) { System.out.println(ident +
* "Contract inference of a Literal "); }
*
* return new ResultInferencePureExp(df,
* df.newRecordDataType(env.getStringType(), new LinkedList<IRecord>())); }
*
* //reviewed// public ResultInferencePureExp typeInferenceAsPure(IntLiteral
* lit, String ident, TypingEnvironment env, GroupName a, Map<InterfaceDecl,
* ClassDecl> intertoclass, Factory df, ClassDecl cl) { if (ident != null) {
* System.out.println(ident + "Contract inference of a Literal "); } return
* new ResultInferencePureExp(df, df.newRecordDataType(env.getIntType(), new
* LinkedList<IRecord>())); }
*
* //reviewed// public ResultInferencePureExp
* typeInferenceAsPure(DataConstructorExp exp, String ident,
* TypingEnvironment env, GroupName a, Map<InterfaceDecl, ClassDecl>
* intertoclass, Factory df, ClassDecl cl) { // DATATYPES String nident =
* null; if (ident != null) { System.out.println(ident +
* "Contract inference of the Data type Constructor \"" +
* exp.getConstructor() + "\""); nident = " " + ident; } FunctionInterface
* fi = env.getFunction(exp.getConstructor()); Constraint c =
* df.newConstraint(); LinkedList<Term> params = new LinkedList<Term>();
* for(PureExp e : exp.getParamList()) { ResultInferencePureExp tmp =
* this.typeInferenceAsPure(e, ident, env, a,intertoclass, df, cl);
* c.add(tmp.getConstraint());
* params.add(env.getRecord(tmp.getVariableType())); }
*
* RecordVariable r = df.newRecordVariable(); FunctionInterface fiapp = new
* FunctionInterface(params, r); c.addSemiEquation(new
* ASTNodeInformation(exp), fiapp, fi); //for (PureExp param :
* exp.getParams()) { // res.add(typeInferenceAsPure(param, nident, env, a,
* intertoclass, df, cl)); //} return new ResultInferencePureExp(df, r, c);
* }
*
* //reviewed// public ResultInferencePureExp typeInferenceAsPure(LetExp
* exp, String ident, TypingEnvironment env, GroupName a, Map<InterfaceDecl,
* ClassDecl> intertoclass, Factory df, ClassDecl cl) { String nident =
* null; if (ident != null) { System.out.println(ident +
* "Contract inference of a Let Expression "); nident = " " + ident; }
* ResultInferencePureExp res = typeInferenceAsPure(exp.getVal(), nident,
* env, a, intertoclass, df, cl); ITypingEnvironmentVariableType X =
* res.getVariableType(); TypingEnvironment envExp = env.clone();
* envExp.putVariable(exp.getVar().getName(), X);
*
* ResultInferencePureExp resExp = typeInferenceAsPure(exp.getExp(), nident,
* envExp, a, intertoclass, df, cl); return resExp; }
*
* // reviewed // public ResultInferencePureExp typeInferenceAsPure(FnApp
* fn, String ident, TypingEnvironment env, GroupName a, Map<InterfaceDecl,
* ClassDecl> intertoclass, Factory df, ClassDecl cl) { // DATATYPES String
* nident = null; if (ident != null) { System.out.println(ident +
* "Contract inference of the function application \"" + fn.getName() +
* "\""); nident = " " + ident; } FunctionInterface fi =
* env.getFunction(fn.getName()); Constraint c = df.newConstraint();
* LinkedList<Term> params = new LinkedList<Term>(); for(PureExp e :
* fn.getParamList()) { ResultInferencePureExp tmp =
* this.typeInferenceAsPure(e, ident, env, a,intertoclass, df, cl);
* c.add(tmp.getConstraint());
* params.add(env.getRecord(tmp.getVariableType())); }
*
* RecordVariable r = df.newRecordVariable(); FunctionInterface fiapp = new
* FunctionInterface(params, r); c.addSemiEquation(new
* ASTNodeInformation(fn), fiapp, fi); //for (PureExp param :
* exp.getParams()) { // res.add(typeInferenceAsPure(param, nident, env, a,
* intertoclass, df, cl)); //} return new ResultInferencePureExp(df, r, c);
* }
*
*
* //reviewed// public ResultInferencePureExp typeInferenceAsPure(IfExp
* ifExp, String ident, TypingEnvironment env, GroupName a,
* Map<InterfaceDecl, ClassDecl> intertoclass, Factory df, ClassDecl cl) {
* String nident = null; if (ident != null) { System.out.println(ident +
* "Contract inference of an Exp Conditional Expression"); nident = " " +
* ident; } ResultInferencePureExp resL =
* typeInferenceAsPure(ifExp.getThenExp(), nident, env, a, intertoclass, df,
* cl); ResultInferencePureExp resR =
* typeInferenceAsPure(ifExp.getThenExp(), nident, env, a, intertoclass, df,
* cl); Constraint c = df.newConstraint(); c.addEquation(new
* ASTNodeInformation(ifExp), env.getRecord(resL.getVariableType()),
* env.getRecord(resR.getVariableType()));
*
* return new ResultInferencePureExp(df,
* env.getRecord(resL.getVariableType()), c); }
*
*
*
*
* // reviewed // public ResultInferencePureExp typeInferenceAsPure(BoolExp
* bin, String ident, TypingEnvironment env, GroupName a, Map<InterfaceDecl,
* ClassDecl> intertoclass, Factory df, ClassDecl cl) { // DATATYPES String
* nident = null; if (ident != null) { System.out.println(ident +
* "Contract Inference for a Bool Binary Pure Expression -> no contract and no record "
* ); nident = " " + ident; }
*
* return new ResultInferencePureExp(df, new
* RecordDataType(env.getBoolType(), new LinkedList<IRecord>())); }
*
* // reviewed // public ResultInferencePureExp
* typeInferenceAsPure(RelationalExpr bin, String ident, TypingEnvironment
* env, GroupName a, Map<InterfaceDecl, ClassDecl> intertoclass, Factory df,
* ClassDecl cl) { // DATATYPES String nident = null; if (ident != null) {
* System.out.println(ident +
* "Contract Inference for a Relational Binary Pure Expression -> no contract and no record "
* ); nident = " " + ident; }
*
* return new ResultInferencePureExp(df, new
* RecordDataType(env.getBoolType(), new LinkedList<IRecord>())); }
*
* // reviewed // public ResultInferencePureExp
* typeInferenceAsPure(ArithmeticExp bin, String ident, TypingEnvironment
* env, GroupName a, Map<InterfaceDecl, ClassDecl> intertoclass, Factory df,
* ClassDecl cl) { // DATATYPES String nident = null; if (ident != null) {
* System.out.println(ident +
* "Contract Inference for an Arithmetic Binary Pure Expression -> no contract and no record "
* ); nident = " " + ident; }
*
* return new ResultInferencePureExp(df, new
* RecordDataType(env.getIntType(), new LinkedList<IRecord>())); }
*
* // reviewed // public ResultInferencePureExp typeInferenceAsPure(NegExp
* un, String ident, TypingEnvironment env, GroupName a, Map<InterfaceDecl,
* ClassDecl> intertoclass, Factory df, ClassDecl cl) { // DATATYPES String
* nident = null; if (ident != null) { System.out.println(ident +
* "Contract Inference for a Pure Negative Boolean Expression -> no contract and no record "
* ); nident = " " + ident; }
*
* return new ResultInferencePureExp(df, new
* RecordDataType(env.getBoolType(), new LinkedList<IRecord>())); }
*
* // reviewed // public ResultInferencePureExp typeInferenceAsPure(MinusExp
* un, String ident, TypingEnvironment env, GroupName a, Map<InterfaceDecl,
* ClassDecl> intertoclass, Factory df, ClassDecl cl) { // DATATYPES String
* nident = null; if (ident != null) { System.out.println(ident +
* "Contract Inference for an Unary Minus Pure Expression -> no contract and no record "
* ); nident = " " + ident; }
*
* return new ResultInferencePureExp(df, new
* RecordDataType(env.getIntType(), new LinkedList<IRecord>())); }
*
*/
/***********************************************************/
// INIT TEMPORARY VERSION OF DATATYPE MANAGEMENT
public ResultInferencePureExp typeInferenceAsPure(StringLiteral lit) {
_log.logDebug("Contract Inference for a String Literal");
return new ResultInferencePureExp(_df, _df.dummyDataType());
}
public ResultInferencePureExp typeInferenceAsPure(IntLiteral lit) {
_log.logDebug("Contract Inference for an Int Literal");
return new ResultInferencePureExp(_df, _df.dummyDataType());
}
public ResultInferencePureExp typeInferenceAsPure(DataConstructorExp exp) {
_log.logDebug("Contract Inference for a DataType Constructor");
return new ResultInferencePureExp(_df, _df.dummyDataType());
}
public ResultInferencePureExp typeInferenceAsPure(LetExp exp) {
_log.logDebug("Contract Inference for a Let Expression");
return new ResultInferencePureExp(_df, _df.dummyDataType());
}
public ResultInferencePureExp typeInferenceAsPure(FnApp fn) {
_log.logDebug("Contract Inference for a Function Application");
return new ResultInferencePureExp(_df, _df.dummyDataType());
}
public ResultInferencePureExp typeInferenceAsPure(IfExp ifExp) {
_log.logDebug("Contract Inference for an if Expression");
return new ResultInferencePureExp(_df, _df.dummyDataType());
}
public ResultInferencePureExp typeInferenceAsPure(BoolExp bin) {
_log.logDebug("Contract Inference for a Boolean Expression");
return new ResultInferencePureExp(_df, _df.dummyDataType());
}
public ResultInferencePureExp typeInferenceAsPure(RelationalExpr bin) {
_log.logDebug("Contract Inference for a Relational Expression");
return new ResultInferencePureExp(_df, _df.dummyDataType());
}
public ResultInferencePureExp typeInferenceAsPure(ArithmeticExp bin) {
_log.logDebug("Contract Inference for an Arithmetic Expression");
return new ResultInferencePureExp(_df, _df.dummyDataType());
}
// reviewed //
public ResultInferencePureExp typeInferenceAsPure(NegExp un) {
_log.logDebug("Contract Inference for a Not Expression");
return new ResultInferencePureExp(_df, _df.dummyDataType());
}
// reviewed //
public ResultInferencePureExp typeInferenceAsPure(MinusExp un) {
_log.logDebug("Contract Inference for a Minus Expression");
return new ResultInferencePureExp(_df, _df.dummyDataType());
}
/*********************************************************/
// TODO:
// CaseExp : PureExp ::= Expr:PureExp Branch:CaseBranch* ;
// CaseBranch ::= Left:Pattern Right:PureExp ;
// abstract Pattern ;
// PatternVarUse: Pattern ::= <Name>;
// PatternVar: Pattern ::= Var:PatternVarDecl;
// ConstructorPattern: Pattern ::= <Constructor> Param:Pattern*;
// LiteralPattern: Pattern ::= Literal:LiteralExp;
// UnderscorePattern: Pattern;
// 2.4.2. Expressions with side effects.
public ResultInferenceEffExp typeInference(NewExp newExp) {
_log.logDebug("Contract Inference for the NewExp");
_log.beginIndent();
// 1. Create the record for the new object, and collect contract and
// constraints from arguments
ClassDecl cl = (ClassDecl) (newExp.lookup(new KindedName(Kind.CLASS, newExp.getClassName())));
LinkedList<RecordField> fields = new LinkedList<RecordField>();
int i = 0;
Contract contract = _df.newContractEmpty();
Constraint c = _df.newConstraint();
// 1.1. Params
_env.newScope();
ResultInferencePureExp resParam;
for (PureExp p : newExp.getParams()) {
resParam = typeInferenceAsPure(p);
ITypingEnvironmentVariableType x = _env.getRecord(resParam.getVariableType());
IRecord r = _env.getRecord(x);
fields.add(_df.newRecordField(cl.getParam(i).getName(), r));
_env.putVariable(cl.getParam(i).getName(), r);
c.add(resParam.getConstraint());
i++;
}
// 1.2. Fields
for (FieldDecl f : cl.getFields()) {
if (f.hasInitExp()) {
resParam = typeInferenceAsPure(f.getInitExp());
RecordField newRecordField = _df.newRecordField(f.getName(), (IRecord) resParam.getVariableType());
fields.add(newRecordField);
_env.putVariable(f.getName(), (IRecord) resParam.getVariableType());
c.add(resParam.getConstraint());
} else {
fields.add(_df.newRecordField(f.getName(), _df.newRecordVariable()));
}
}
// 1.3. Group Name
GroupName aprime; // depends if the new object is in the same cog or not
if (!newExp.hasLocal()) {
aprime = _df.newGroupName();
} else {
aprime = _a;
}
IRecord r = _df.newRecordPresent(aprime, fields);
// 1.4. Calling the init of r
MethodInterface miinit = _df.newMethodInterface(r, new LinkedList<IRecord>(), _df.newRecordVariable());
c.addSemiEquation(new ASTNodeInformation(newExp), _env.getMethod(cl.getName(), _initName), miinit);
contract.add(_df.newContractInvk(newExp, cl.getName(), _initName, miinit));
_env.popScope();
_log.endIndent();
_log.logDebug("End Contract Inference for the NewExp");
return new ResultInferenceEffExp(r, contract, c, _env);
}
public ResultInferenceEffExp typeInference(Call call) {
_log.logDebug("Contract Inference for a " + ((call instanceof SyncCall) ? "Synchronous" : "Asynchronous")
+ " method Call");
_log.beginIndent();
ITypingEnvironmentVariableType r;
GroupName aprime = _df.newGroupName();
// 1. Get the method interface
Type t = call.getCallee().getType();
ClassDecl cl;
if (t.isInterfaceType()) {
cl = _intertoclass.get(((InterfaceType) t).getDecl());
} else {
cl = _cd;
}
String nameOfClass;
String nameOfMethod;
LinkedList<IRecord> s = new LinkedList<IRecord>();
if (cl == _emptyDecl) {
// we are in presence of an non implemented interface
// in that case, we don't know how the method would behave, and
// simply put a null contract.
_log.endIndent();
_log.logError("Class retrival failed!!!");
nameOfClass = _dummyClass;
nameOfMethod = _dummyMethod;
// return new ResultInferenceEffExp( _df.newRecordVariable(),
// _df.newContractEmpty(), _df.newConstraint(), _env);
} else {
nameOfClass = cl.getName();
nameOfMethod = call.getMethod();
ResultInferencePureExp resParam;
for (PureExp p : call.getParams()) {
resParam = typeInferenceAsPure(p);
s.add(_env.getRecord(resParam.getVariableType()));
}
}
// else
{
// 2. Collect contracts and
// deadlock.constraints.constraint.Constraints from the call
ResultInferencePureExp resCallee = typeInferenceAsPure(call.getCallee());
Contract contract = _df.newContractEmpty();
Constraint c = _df.newConstraint();
// cast to IRecord as the callee cannot be a future
IRecord callee = (IRecord) resCallee.getVariableType();
// 3. Construct the record for the return value
IRecord Y = _df.newRecordVariable();
// 4. pack up the result
MethodInterface mi = _df.newMethodInterface(callee, s, Y);
c.addSemiEquation(new ASTNodeInformation(call), _env.getMethod(nameOfClass, nameOfMethod), mi);
if (call instanceof SyncCall) {
r = Y;
contract.add(_df.newContractSyncInvk(call, nameOfClass, nameOfMethod, mi));
} else if (call instanceof AsyncCall) {
IRecord calleeShape = createInstance(cl, aprime);
c.addEquation(new ASTNodeInformation(call), callee, calleeShape);
r = new TypingEnvironmentVariableTypeFuture();
_env.putFuture((TypingEnvironmentVariableTypeFuture) r, new TypingEnvironmentFutureTypeUntick(
_df.newRecordFuture(aprime, Y), new ContractElementInvk(call, nameOfClass, nameOfMethod, mi)));
} else if (call instanceof AwaitAsyncCall) {
// same stuff that for sync calls
// AwaitAsyncCall are actually rewritten in the AST if the flag
// public static boolean Model.doAACrewrite is set to true;
// objects of this kind are rewritten at the ast level as
// AsyncCall + await
// you can switch this switch in file
// frontend/src/abs/backend/coreabs/GenerateCoreAbs.jadd line 38
r = Y;
contract.add(_df.newContractSyncInvk(call, nameOfClass, nameOfMethod, mi));
} else {
// should not happen
r = null;
_log.logError("Unexpected call type");
}
_log.endIndent();
_log.logDebug("End Contract Inference for the Call");
return new ResultInferenceEffExp(r, contract, c, _env);
}
}
public ResultInferenceEffExp typeInference(GetExp exp) {
_log.logDebug("Contract Inference for a GetExp");
_log.beginIndent();
// 1. first is calculate the inference of the expression 'e' of 'e.get'
ResultInferencePureExp resPureExp = typeInferenceAsPure(exp.getPureExp());
_log.endIndent();
_log.logDebug("GetExp Sub-Expression Finished");
Contract contract;
Constraint c = _df.newConstraint();
// 2. record for the result
GroupName aprime = _df.newGroupName();
IRecord X = _df.newRecordVariable();
// 3. check if future is tick
ITypingEnvironmentVariableType variableType = resPureExp.getVariableType();
if (variableType instanceof TypingEnvironmentVariableTypeFuture) {
ITypingEnvironmentFutureType fType = _env.getFuture((TypingEnvironmentVariableTypeFuture) variableType);
if (fType instanceof TypingEnvironmentFutureTypeUntick) {
_env.putFuture((TypingEnvironmentVariableTypeFuture) variableType,
new TypingEnvironmentFutureTypeTick(fType.getRecord()));
contract = _df.newContract(_df.newContractElementParallel(
_df.newContractInvkG(exp, ((TypingEnvironmentFutureTypeUntick) fType).getContract(),
new ContractElementGet(exp, _a, aprime)),
_env.unsync(exp)));
} else {
contract = _df.newContractEmpty();
}
try {
c.addEquation(new ASTNodeInformation(exp), _df.newRecordFuture(aprime, X), fType.getRecord());
} catch (Exception e) {
e.getMessage();
}
} else {
contract = _df.newContractEmpty();
}
return new ResultInferenceEffExp(X, contract, c, _env);
}
// ////////////////////////////////////////////////////////////////////////////
// 2.5. Guards
public ResultInferencePureExp typeInference(ClaimGuard cg) {
_log.logDebug("Contract Inference for a ClaimGuard");
_log.beginIndent();
ResultInferencePureExp res = typeInferenceAsPure(cg.getVar());
_log.endIndent();
return res;
}
// TODO; AndGuard, ExpGuard, DurationGuard
}