use of org.osate.ba.utils.DimensionException in project osate2 by osate.
the class AadlBaTypeChecker method subprogramParameterListCheck.
// This method checks the given parameter labels and matches them against the
// subprogram parameters. It resolves target/value expression semantic
// ambiguities. On error, reports error and returns false.
// Event if the subprogram call action doesn't have any parameter labels,
// the subprogram type may have and vice versa : subprogramParameterListCheck
// / is also design for these cases.
/**
* Document: AADL Behavior Annex draft
* Version : 0.94
* Type : Legality rule
* Section : D.6 Behavior Action Language
* Object : Check legality rule D.6.(L5)
* Keys : parameter list match signature subprogram call
*/
private boolean subprogramParameterListCheck(CommAction comAct, EList<ParameterLabel> callParams, Classifier subprogType) {
// Fetches sorted subprogram feature list.
List<Feature> tmp = Aadl2Utils.orderFeatures(subprogType);
List<Feature> subprogFeat = new ArrayList<Feature>(tmp.size());
for (Feature feat : tmp) {
if (feat instanceof DataAccess || feat instanceof Parameter) {
subprogFeat.add(feat);
}
}
// Preliminary checking : on error, reports error and exit early.
if (callParams.size() != subprogFeat.size()) {
String subprogramName = null;
if (comAct.getReference() != null) {
subprogramName = unparseReference(comAct.getReference());
} else {
subprogramName = unparseQualifiedNamedElement(comAct.getQualifiedName());
}
reportError(comAct, "Invalid number of argument(s) for the subprogram " + subprogramName);
return false;
}
boolean isconsistent = true;
boolean hasCheckingPassed = true;
Enum<?> currentDirRight;
ValueExpression valueExp;
ListIterator<ParameterLabel> it = callParams.listIterator();
Value v;
Target tar;
TypeHolder t1, t2;
ValueAndTypeHolder vth;
List<TypeHolder> typesFound = new ArrayList<TypeHolder>(callParams.size());
List<Enum<?>> dirRightsFound = new ArrayList<Enum<?>>(callParams.size());
List<TypeHolder> expectedTypes = new ArrayList<TypeHolder>(subprogFeat.size());
List<Enum<?>> expectedDirRight = new ArrayList<Enum<?>>(subprogFeat.size());
// driven by the subprogram signature.
for (Feature feat : subprogFeat) {
if (feat instanceof Parameter) {
Parameter param = (Parameter) feat;
currentDirRight = param.getDirection();
expectedDirRight.add(currentDirRight);
} else // DataAccess case.
{
DataAccess data = (DataAccess) feat;
currentDirRight = Aadl2Utils.getDataAccessRight(data);
expectedDirRight.add(currentDirRight);
}
valueExp = (ValueExpression) it.next();
Classifier klass = AadlBaUtils.getClassifier(feat, _baParentContainer);
// ValueExpression case.
if (currentDirRight == DirectionType.IN || currentDirRight == Aadl2Utils.DataAccessRight.read_only) {
vth = valueExpressionCheck(valueExp);
if (vth != null) {
try {
t1 = AadlBaUtils.getTypeHolder(klass);
} catch (DimensionException de) {
reportDimensionException(de);
return false;
}
t2 = vth.typeHolder;
expectedTypes.add(t1);
typesFound.add(t2);
dirRightsFound.add(DirectionType.IN);
if (!_dataChecker.conformsTo(t1, t2, true)) {
isconsistent = false;
}
} else // Value expression checking error case.
{
// Error reporting has already been done.
hasCheckingPassed = false;
}
} else if (currentDirRight != Aadl2Utils.DataAccessRight.unknown) {
v = AadlBaUtils.isOnlyOneValue(valueExp);
boolean isOnlyOneReference = false;
if (v instanceof Reference) {
Reference r = (Reference) v;
if (r.getIds().size() == 1) {
isOnlyOneReference = true;
}
}
if (// Target but not reference case.
v instanceof Target && isOnlyOneReference) {
TypeCheckRule stopOnThisRule = TypeCheckRule.DATA_ACCESS;
tar = targetCheck((Target) v, stopOnThisRule);
if (tar != null) {
try {
t1 = AadlBaUtils.getTypeHolder(klass);
t2 = AadlBaUtils.getTypeHolder(tar, _baParentContainer);
} catch (DimensionException de) {
reportDimensionException(de);
return false;
}
expectedTypes.add(t1);
typesFound.add(t2);
Enum<?> dirRightFound = AadlBaUtils.getDirectionType(tar);
if (dirRightFound == null) {
dirRightFound = AadlBaUtils.getDataAccessRight(tar);
}
dirRightsFound.add(dirRightFound);
if (!_dataChecker.conformsTo(t1, t2, true)) {
isconsistent = false;
} else {
// As checking passed and ambiguity between
// ValueExpression and Target has been resolved, it replaces
// the value expression by the target as parameter label.
it.set(tar);
}
} else // Target checking error case.
{
// Error reporting has already been done.
hasCheckingPassed = false;
}
} else // Value expression taken as a target -> warning arithmetic pointer operation.
{
// Due to target/value expression semantic ambiguity, the parsing
// phase may have introduced a semantic errors :
// If v == null :
// The parameter label has
// to be a value expression with a single value when the expected
// subprogram parameter is IN_OUT or OUT.
// If v is not instanceof Target but ValueExpression or Value
// like :
// _ IntegerConstant or ValueConstant
// _ PortFreshValue
// _ PortCountValue
// _ PortDequeueValue
// It resolves the type in order to format the warning message:
vth = valueExpressionCheck(valueExp);
if (vth != null) {
try {
t1 = AadlBaUtils.getTypeHolder(klass);
} catch (DimensionException de) {
reportDimensionException(de);
return false;
}
t2 = vth.typeHolder;
expectedTypes.add(t1);
typesFound.add(t2);
boolean inconsistentDir = false;
if (v instanceof Reference) {
Reference ref = (Reference) v;
ArrayableIdentifier refRootId = ref.getIds().get(0);
Enum<?> dirRightFound = null;
if (refRootId.getOsateRef() != null) {
dirRightFound = AadlBaUtils.getDirectionType(refRootId.getOsateRef());
}
if (dirRightFound == null && refRootId.getOsateRef() instanceof DataAccess) {
dirRightFound = Aadl2Utils.getDataAccessRight((DataAccess) refRootId.getOsateRef());
}
if (dirRightFound == DirectionType.IN || dirRightFound == Aadl2Utils.DataAccessRight.read_only) {
inconsistentDir = true;
}
} else {
inconsistentDir = true;
dirRightsFound.add(DirectionType.IN);
}
if (inconsistentDir) {
StringBuilder msg = new StringBuilder();
msg.append('\'');
msg.append(unparseNameElement(valueExp));
msg.append("\': is a read only value and it is used as a writable value");
// Reports a warning.
reportWarning(valueExp, msg.toString());
}
} else {
// Error reporting has already been done.
hasCheckingPassed = false;
}
}
} else {
reportError(valueExp, "can't fetch data access right. Set the default " + "right in memory_properties.aadl");
}
}
// Reports consistency error.
if (!isconsistent && hasCheckingPassed) {
String subprogramName = null;
if (comAct.getReference() != null) {
subprogramName = unparseReference(comAct.getReference());
} else {
subprogramName = unparseQualifiedNamedElement(comAct.getQualifiedName());
}
reportSubprogParamMatchingError(comAct, subprogramName, expectedTypes, expectedDirRight, typesFound, dirRightsFound);
}
return isconsistent && hasCheckingPassed;
}
Aggregations