package org.overture.codegen.trans.conc;
import java.util.List;
import org.overture.codegen.ir.IRConstants;
import org.overture.codegen.ir.IRInfo;
import org.overture.codegen.ir.analysis.AnalysisException;
import org.overture.codegen.ir.analysis.DepthFirstAnalysisAdaptor;
import org.overture.codegen.ir.declarations.ADefaultClassDeclIR;
import org.overture.codegen.ir.declarations.AFieldDeclIR;
import org.overture.codegen.ir.declarations.AFormalParamLocalParamIR;
import org.overture.codegen.ir.declarations.AMethodDeclIR;
import org.overture.codegen.ir.expressions.AExternalExpIR;
import org.overture.codegen.ir.expressions.AIdentifierVarExpIR;
import org.overture.codegen.ir.name.ATokenNameIR;
import org.overture.codegen.ir.patterns.AIdentifierPatternIR;
import org.overture.codegen.ir.statements.ABlockStmIR;
import org.overture.codegen.ir.statements.APlainCallStmIR;
import org.overture.codegen.ir.types.AClassTypeIR;
import org.overture.codegen.ir.types.AExternalTypeIR;
import org.overture.codegen.ir.types.AIntNumericBasicTypeIR;
import org.overture.codegen.ir.types.AMethodTypeIR;
import org.overture.codegen.ir.types.AVoidTypeIR;
public class SentinelTrans extends DepthFirstAnalysisAdaptor
{
private IRInfo info;
private ConcPrefixes concPrefixes;
public SentinelTrans(IRInfo info, ConcPrefixes concPrefixes)
{
this.info = info;
this.concPrefixes = concPrefixes;
}
@Override
public void caseADefaultClassDeclIR(ADefaultClassDeclIR node)
throws AnalysisException
{
if (!info.getSettings().generateConc())
{
return;
}
if(info.getDeclAssistant().isTest(node))
{
return;
}
if (node.getSuperNames().size() > 1)
{
info.addTransformationWarning(node, MainClassConcTrans.MULTIPLE_INHERITANCE_WARNING);
return;
}
ADefaultClassDeclIR innerClass = new ADefaultClassDeclIR();
innerClass.setStatic(true);
String classname = node.getName();
List<AMethodDeclIR> innerClassMethods;
if (!node.getSuperNames().isEmpty())
{
innerClassMethods = info.getDeclAssistant().getAllMethods(node, info.getClasses());
} else
{
innerClassMethods = node.getMethods();
}
String className = classname + concPrefixes.sentinelClassPostFix();
innerClass.setName(className);
AClassTypeIR innerClassType = new AClassTypeIR();
innerClassType.setName(classname);
int n = 0;
Boolean existing = false;
for (AMethodDeclIR method : innerClassMethods)
{
for (AFieldDeclIR field : innerClass.getFields())
{
if (field.getName().equals(method.getName()))
{
existing = true;
}
}
if (existing)
{
existing = false;
} else
{
// Set up of the int type of the fields.
String intTypeName = concPrefixes.nativeIntTypeName();
AExternalTypeIR intBasicType = new AExternalTypeIR();
intBasicType.setName(intTypeName);
AFieldDeclIR field = new AFieldDeclIR();
field.setName(method.getName());
field.setAccess(IRConstants.PUBLIC);
field.setFinal(true);
field.setType(intBasicType);
field.setStatic(true);
// setting up initial values
AExternalExpIR intValue = new AExternalExpIR();
intValue.setType(new AIntNumericBasicTypeIR());
intValue.setTargetLangExp("" + n);
field.setInitial(intValue);
// increase the number that initialize the variables.
n++;
innerClass.getFields().add(field);
}
}
// setting up initial values
AExternalTypeIR intBasicType = new AExternalTypeIR();
// intBasicType.setName(intTypeName);
intBasicType.setName(concPrefixes.nativeIntTypeName());
AExternalExpIR intValue = new AExternalExpIR();
intValue.setType(new AIntNumericBasicTypeIR());
intValue.setTargetLangExp("" + n);
innerClass.getFields().add(info.getDeclAssistant().constructField(IRConstants.PUBLIC, concPrefixes.funcSumConstFieldName(), false, true, intBasicType, intValue));
AMethodDeclIR method_pp = new AMethodDeclIR();
AMethodTypeIR method_ppType = new AMethodTypeIR();
method_ppType.setResult(innerClassType.clone());
method_pp.setMethodType(method_ppType);
// adding the first constructor to the innerclass
method_pp.setIsConstructor(true);
method_pp.setImplicit(false);
method_pp.setAccess(IRConstants.PUBLIC);
method_pp.setName(innerClass.getName());
method_pp.setBody(new ABlockStmIR());
innerClass.getMethods().add(method_pp);
// adding the second constructor.
AMethodDeclIR method_con = new AMethodDeclIR();
// The parameter
AExternalTypeIR evalPpType = new AExternalTypeIR();
evalPpType.setName(concPrefixes.evalPpTypeName());
method_con.setName(innerClass.getName());
method_con.setIsConstructor(true);
method_con.setAccess(IRConstants.PUBLIC);
AFormalParamLocalParamIR formalParam = new AFormalParamLocalParamIR();
formalParam.setType(evalPpType);
AIdentifierPatternIR identifier = new AIdentifierPatternIR();
identifier.setName(concPrefixes.instanceParamName());
formalParam.setPattern(identifier);
method_con.getFormalParams().add(formalParam);
AMethodTypeIR evalPPConType = new AMethodTypeIR();
evalPPConType.setResult(innerClassType.clone());
evalPPConType.getParams().add(evalPpType.clone());
method_con.setMethodType(evalPPConType);
// Creating the body of the constructor.
// The parameters named ‘instance’ and function_sum passed to the init call statement:
AIdentifierVarExpIR instanceParam = new AIdentifierVarExpIR();
instanceParam.setIsLambda(false);
instanceParam.setIsLocal(true);
instanceParam.setName(concPrefixes.instanceParamName());
instanceParam.setType(evalPpType.clone());
AIdentifierVarExpIR function_sum = new AIdentifierVarExpIR();
function_sum.setIsLambda(false);
function_sum.setIsLocal(false);
function_sum.setName(concPrefixes.funcSumConstFieldName());
function_sum.setType(new AIntNumericBasicTypeIR());
// the init method
APlainCallStmIR initCall = new APlainCallStmIR();
initCall.setName(concPrefixes.initMethodName());
initCall.setType(new AVoidTypeIR());
// Adding argument #1
initCall.getArgs().add(instanceParam);
// Adding argument #2
initCall.getArgs().add(function_sum);
// Set the body
method_con.setBody(initCall);
innerClass.getMethods().add(method_con);
// method_pp.setFormalParams();
ATokenNameIR superName = new ATokenNameIR();
if (!node.getSuperNames().isEmpty())
{
if (!node.getSuperNames().get(0).equals(concPrefixes.vdmThreadClassName()))
{
superName.setName(node.getSuperNames().get(0)
+ concPrefixes.sentinelClassPostFix());
} else
{
superName.setName(concPrefixes.sentinelClassName());
}
innerClass.getSuperNames().add(superName);
} else
{
superName.setName(concPrefixes.sentinelClassName());
innerClass.getSuperNames().add(superName);
}
innerClass.setAccess(IRConstants.PUBLIC);
node.getInnerClasses().add(innerClass);
}
}