Commit 638f3228 authored by Adam Knapp's avatar Adam Knapp
Browse files

Advanced matching semantic check improvements #413 #414 #415


Signed-off-by: Adam Knapp's avatarAdam Knapp <adam.knapp@ericsson.com>
parent bc3612e0
...@@ -76,8 +76,8 @@ public class Reference extends ASTNode implements ILocateableNode, IIncrementall ...@@ -76,8 +76,8 @@ public class Reference extends ASTNode implements ILocateableNode, IIncrementall
public static final String TYPEEXPECTED = "Type reference expected"; public static final String TYPEEXPECTED = "Type reference expected";
public static final String ASN1SETTINGEXPECTED = "Reference to ASN.1 setting expected"; public static final String ASN1SETTINGEXPECTED = "Reference to ASN.1 setting expected";
private static final String INVALIDVALUEREFERENCE = "Invalid `value` reference"; private static final String INVALIDVALUEREFERENCE = "Reference to `value` is not allowed here";
private static final String VALUENOTSETTER = "A property getter cannot have a `value` reference"; private static final String VALUENOTSETTER = "Reference to `value` is not allowed in a property getter";
public enum Ref_Type { public enum Ref_Type {
/** basic reference (not related to a class scope or a dynamic template) */ /** basic reference (not related to a class scope or a dynamic template) */
...@@ -514,13 +514,13 @@ public class Reference extends ASTNode implements ILocateableNode, IIncrementall ...@@ -514,13 +514,13 @@ public class Reference extends ASTNode implements ILocateableNode, IIncrementall
final StatementBlock sb = (StatementBlock)getMyScope(); final StatementBlock sb = (StatementBlock)getMyScope();
FormalParameter valueParam = getValueParameter(sb); FormalParameter valueParam = getValueParameter(sb);
if (valueParam != null) { if (valueParam != null) {
return (Assignment)valueParam; return valueParam;
} else { } else {
if (sb.ownerIsProperty() && ! sb.isPropertySetter()) { if (sb.ownerIsProperty() && ! sb.isPropertySetter()) {
getLocation().reportSemanticError(VALUENOTSETTER); getLocation().reportSemanticError(VALUENOTSETTER);
return null; } else {
getLocation().reportSemanticError(INVALIDVALUEREFERENCE);
} }
getLocation().reportSemanticError(INVALIDVALUEREFERENCE);
return null; return null;
} }
} }
......
...@@ -29,6 +29,7 @@ import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Function; ...@@ -29,6 +29,7 @@ import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Function;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Definition; import org.eclipse.titan.designer.AST.TTCN3.definitions.Definition;
import org.eclipse.titan.designer.AST.TTCN3.templates.ITTCN3Template; import org.eclipse.titan.designer.AST.TTCN3.templates.ITTCN3Template;
import org.eclipse.titan.designer.AST.TTCN3.templates.TTCN3Template; import org.eclipse.titan.designer.AST.TTCN3.templates.TTCN3Template;
import org.eclipse.titan.designer.AST.TTCN3.types.Boolean_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.Property_Type; import org.eclipse.titan.designer.AST.TTCN3.types.Property_Type;
import org.eclipse.titan.designer.AST.TTCN3.values.expressions.ExpressionStruct; import org.eclipse.titan.designer.AST.TTCN3.values.expressions.ExpressionStruct;
import org.eclipse.titan.designer.compiler.JavaGenData; import org.eclipse.titan.designer.compiler.JavaGenData;
...@@ -53,8 +54,9 @@ public final class Return_Statement extends Statement { ...@@ -53,8 +54,9 @@ public final class Return_Statement extends Statement {
+ "It is allowed only in functions, altsteps, dynamic matching and class property getters"; + "It is allowed only in functions, altsteps, dynamic matching and class property getters";
private static final String RETURNINDESTRUCTOR = "Return statement cannot be used in a class destructor"; private static final String RETURNINDESTRUCTOR = "Return statement cannot be used in a class destructor";
private static final String INVALIDSETTERRETURN = "Return statement cannot be used in a property setter"; private static final String INVALIDSETTERRETURN = "Return statement cannot be used in a property setter";
private static final String RETURNINDYNAMICTEMPLATESB = "The dynamic template's statement block should return a boolean value"; private static final String INVALIDRETURNINDYNAMICTEMPLATESB1 =
private static final String RETURNINDYNAMICTEMPLATEREF = "The dynamic template's referenced function should return a boolean value"; "Missing return value. The dynamic template's statement block should return a boolean value";
private static final String INVALIDRETURNINDYNAMICTEMPLATESB2 = "A specific value without matching symbols was expected as return value";
private static final String FULLNAMEPART = ".returnexpression"; private static final String FULLNAMEPART = ".returnexpression";
private static final String STATEMENT_NAME = "return"; private static final String STATEMENT_NAME = "return";
private static final String RETURNTYPEEXPECTED = "Return type `{0}'' expected"; private static final String RETURNTYPEEXPECTED = "Return type `{0}'' expected";
...@@ -143,10 +145,10 @@ public final class Return_Statement extends Statement { ...@@ -143,10 +145,10 @@ public final class Return_Statement extends Statement {
template.getLocation().reportSemanticError(UNEXPECTEDRETURNVALUE); template.getLocation().reportSemanticError(UNEXPECTEDRETURNVALUE);
} }
break; break;
case A_FUNCTION_RVAL: case A_FUNCTION_RVAL: {
final Type returnType = ((Def_Function) definition).getType(timestamp); final Type returnType = ((Def_Function) definition).getType(timestamp);
if (template == null) { if (template == null) {
location.reportSemanticError(MessageFormat.format(MISSINGVALUE, returnType.getTypename())); location.reportSemanticError(MessageFormat.format(MISSINGVALUE, returnType.getTypename()));
break; break;
} }
if (!template.isValue(timestamp)) { if (!template.isValue(timestamp)) {
...@@ -161,28 +163,28 @@ public final class Return_Statement extends Statement { ...@@ -161,28 +163,28 @@ public final class Return_Statement extends Statement {
returnType.checkThisValueRef(timestamp, value); returnType.checkThisValueRef(timestamp, value);
returnType.checkThisValue(timestamp, value, null, new ValueCheckingOptions(Expected_Value_type.EXPECTED_DYNAMIC_VALUE, false, false, true, false, false)); returnType.checkThisValue(timestamp, value, null, new ValueCheckingOptions(Expected_Value_type.EXPECTED_DYNAMIC_VALUE, false, false, true, false, false));
} }
break; break;
}
case A_FUNCTION_RTEMP: case A_FUNCTION_RTEMP: {
if (template == null) { if (template == null) {
location.reportSemanticError(MessageFormat.format(MISSINGTEMPLATE, ((Def_Function) definition).getType(timestamp) location.reportSemanticError(MessageFormat.format(MISSINGTEMPLATE, ((Def_Function) definition).getType(timestamp)
.getTypename())); .getTypename()));
} else { } else {
final Type returnType1 = ((Def_Function) definition).getType(timestamp); final Type returnType = ((Def_Function) definition).getType(timestamp);
template.setMyGovernor(returnType1); template.setMyGovernor(returnType);
final ITTCN3Template temporalTemplate1 = returnType1.checkThisTemplateRef(timestamp, template,Expected_Value_type.EXPECTED_TEMPLATE,null); final ITTCN3Template temporalTemplate = returnType.checkThisTemplateRef(timestamp, template,Expected_Value_type.EXPECTED_TEMPLATE,null);
temporalTemplate1.checkThisTemplateGeneric(timestamp, returnType1, true, true, true, true, true, null); temporalTemplate.checkThisTemplateGeneric(timestamp, returnType, true, true, true, true, true, null);
genRestrictionCheck = TemplateRestriction.check(timestamp, definition, temporalTemplate1, null); genRestrictionCheck = TemplateRestriction.check(timestamp, definition, temporalTemplate, null);
} }
break; break;
}
case A_ALTSTEP: case A_ALTSTEP:
if (template != null) { if (template != null) {
template.getLocation().reportSemanticError(ALTSTEPRETURNINGVALUE); template.getLocation().reportSemanticError(ALTSTEPRETURNINGVALUE);
} }
break; break;
// class property getter/setter // class property getter/setter
case A_VAR: case A_VAR: {
if (myStatementBlock.ownerIsProperty()) { if (myStatementBlock.ownerIsProperty()) {
if (myStatementBlock.isPropertyGetter()) { if (myStatementBlock.isPropertyGetter()) {
final INamedNode node = myStatementBlock.getNameParent(); final INamedNode node = myStatementBlock.getNameParent();
...@@ -207,19 +209,28 @@ public final class Return_Statement extends Statement { ...@@ -207,19 +209,28 @@ public final class Return_Statement extends Statement {
} }
} }
break; break;
}
// dynamic match template // dynamic match template
case A_TEMPLATE: case A_TEMPLATE:
case A_VAR_TEMPLATE: case A_VAR_TEMPLATE: {
if (myStatementBlock.isInDynamicTemplate() && template != null && if (myStatementBlock.isInDynamicTemplate() && template == null) {
!Type_type.TYPE_BOOL.equals( myStatementBlock.getDynamicTemplate().getLocation().reportSemanticError(INVALIDRETURNINDYNAMICTEMPLATESB1);
template.getExpressionReturntype(timestamp, Expected_Value_type.EXPECTED_DYNAMIC_VALUE))) { } else if (myStatementBlock.isInDynamicTemplate() && !template.isValue(timestamp)) {
if (myStatementBlock.getDynamicTemplate().hasReference()) { myStatementBlock.getDynamicTemplate().getLocation().reportSemanticError(INVALIDRETURNINDYNAMICTEMPLATESB2);
myStatementBlock.getDynamicTemplate().getLocation().reportSemanticError(RETURNINDYNAMICTEMPLATEREF); }
} else { if (template == null) {
myStatementBlock.getDynamicTemplate().getLocation().reportSemanticError(RETURNINDYNAMICTEMPLATESB); break;
} }
final Type returnType = new Boolean_Type();
template.setMyGovernor(returnType);
final IValue value = template.getValue();
if (value != null) {
value.setMyGovernor(returnType);
returnType.checkThisValueRef(timestamp, value);
returnType.checkThisValue(timestamp, value, null, new ValueCheckingOptions(Expected_Value_type.EXPECTED_DYNAMIC_VALUE, false, false, true, false, false));
} }
break; break;
}
default: default:
location.reportSemanticError(MessageFormat.format(UNEXPETEDRETURNSTATEMENT, definition.getAssignmentName())); location.reportSemanticError(MessageFormat.format(UNEXPETEDRETURNSTATEMENT, definition.getAssignmentName()));
break; break;
......
...@@ -30,6 +30,7 @@ import org.eclipse.titan.designer.parsers.CompilationTimeStamp; ...@@ -30,6 +30,7 @@ import org.eclipse.titan.designer.parsers.CompilationTimeStamp;
* @author Adam Knapp * @author Adam Knapp
* */ * */
public class ConjunctionMatch_template extends CompositeTemplate { public class ConjunctionMatch_template extends CompositeTemplate {
private static final String ANYOROMITWARNING = "`*'' in complemented list. This template will not match anything.";
public ConjunctionMatch_template(final ListOfTemplates templates) { public ConjunctionMatch_template(final ListOfTemplates templates) {
super(templates); super(templates);
...@@ -74,13 +75,18 @@ public class ConjunctionMatch_template extends CompositeTemplate { ...@@ -74,13 +75,18 @@ public class ConjunctionMatch_template extends CompositeTemplate {
if (type == null) { if (type == null) {
return false; return false;
} }
final boolean allowOmitInValueList = TTCN3Template.allowOmitInValueList(getLocation(), allowOmit);
boolean selfReference = false; boolean selfReference = false;
for (int i = 0, size = templates.getNofTemplates(); i < size; i++) { for (int i = 0, size = templates.getNofTemplates(); i < size; i++) {
final TTCN3Template component = templates.getTemplateByIndex(i); final TTCN3Template component = templates.getTemplateByIndex(i);
component.setMyGovernor(type); component.setMyGovernor(type);
final ITTCN3Template temporalComponent = type.checkThisTemplateRef(timestamp, component); final ITTCN3Template temporalComponent = type.checkThisTemplateRef(timestamp, component);
selfReference |= temporalComponent.checkThisTemplateGeneric(timestamp, type, false, false, true, subCheck, implicitOmit, lhs); selfReference |= temporalComponent.checkThisTemplateGeneric(timestamp, type, false, allowOmitInValueList, true, subCheck, implicitOmit, lhs);
if (Template_type.ANY_OR_OMIT.equals(temporalComponent.getTemplatetype())) {
component.getLocation().reportSemanticWarning(ANYOROMITWARNING);
}
} }
checkLengthRestriction(timestamp, type); checkLengthRestriction(timestamp, type);
......
...@@ -16,6 +16,7 @@ import org.eclipse.titan.designer.AST.Assignment.Assignment_type; ...@@ -16,6 +16,7 @@ import org.eclipse.titan.designer.AST.Assignment.Assignment_type;
import org.eclipse.titan.designer.AST.IReferenceChain; import org.eclipse.titan.designer.AST.IReferenceChain;
import org.eclipse.titan.designer.AST.IType; import org.eclipse.titan.designer.AST.IType;
import org.eclipse.titan.designer.AST.Identifier; import org.eclipse.titan.designer.AST.Identifier;
import org.eclipse.titan.designer.AST.NULL_Location;
import org.eclipse.titan.designer.AST.Identifier.Identifier_type; import org.eclipse.titan.designer.AST.Identifier.Identifier_type;
import org.eclipse.titan.designer.AST.Reference; import org.eclipse.titan.designer.AST.Reference;
import org.eclipse.titan.designer.AST.Scope; import org.eclipse.titan.designer.AST.Scope;
...@@ -36,6 +37,9 @@ import org.eclipse.titan.designer.parsers.CompilationTimeStamp; ...@@ -36,6 +37,9 @@ import org.eclipse.titan.designer.parsers.CompilationTimeStamp;
* @author Adam Knapp * @author Adam Knapp
* */ * */
public class DynamicMatch_template extends TTCN3Template { public class DynamicMatch_template extends TTCN3Template {
private static final String MISSINGRETURN = "The dynamic template's statement block does not have a return statement";
private static final String LEAVEWITHOUTRETURN =
"Control might leave the dynamic template's statement block without reaching a return statement";
/** function reference used in defining the dynamic template, not owned */ /** function reference used in defining the dynamic template, not owned */
private Reference reference; private Reference reference;
...@@ -68,14 +72,6 @@ public class DynamicMatch_template extends TTCN3Template { ...@@ -68,14 +72,6 @@ public class DynamicMatch_template extends TTCN3Template {
this.setMyScope(block); this.setMyScope(block);
} }
public void addValueParamList(final Type type) {
final FormalParameter valueParam = new FormalParameter(null, Assignment_type.A_PAR_VAL_IN, type, new Identifier(Identifier_type.ID_TTCN, "value"), null, null);
final List<FormalParameter> paramList = new ArrayList<FormalParameter>();
paramList.add(valueParam);
final FormalParameterList fpList = new FormalParameterList(paramList);
statementBlock.setValueParamList(fpList);
}
@Override @Override
public String createStringRepresentation() { public String createStringRepresentation() {
final StringBuilder builder = new StringBuilder(); final StringBuilder builder = new StringBuilder();
...@@ -120,23 +116,47 @@ public class DynamicMatch_template extends TTCN3Template { ...@@ -120,23 +116,47 @@ public class DynamicMatch_template extends TTCN3Template {
return false; return false;
} }
boolean selfReference = type.checkThisTemplate(timestamp, this, isModified, implicitOmit, lhs);
checkLengthRestriction(timestamp, type);
final Type myType = (Type)statementBlock.getMyDefinition().getType(timestamp); final Type myType = (Type)statementBlock.getMyDefinition().getType(timestamp);
addValueParamList(myType); final FormalParameter valueParam =
new FormalParameter(null, Assignment_type.A_PAR_VAL_IN, myType, new Identifier(Identifier_type.ID_TTCN, "value"), null, null);
final List<FormalParameter> paramList = new ArrayList<FormalParameter>();
paramList.add(valueParam);
final FormalParameterList fpList = new FormalParameterList(paramList);
fpList.setFullNameParent(this);
fpList.setMyScope(this.getMyScope());
statementBlock.setValueParamList(fpList);
statementBlock.getValueParamList().check(timestamp, null);
statementBlock.check(timestamp); statementBlock.check(timestamp);
switch (statementBlock.hasReturn(timestamp)) {
case RS_NO:
location.reportSemanticError(MISSINGRETURN);
break;
case RS_MAYBE:
location.reportSemanticError(LEAVEWITHOUTRETURN);
break;
default:
break;
}
checkLengthRestriction(timestamp, type);
if (!allowOmit && isIfpresent) {
if (location != null && !(location instanceof NULL_Location)) {
location.reportSemanticError("`ifpresent' is not allowed here");
}
}
if (reference == null) { if (reference == null) {
return false; return false;
} }
final Assignment assignment = reference.getRefdAssignment(timestamp, true); final Assignment assignment = reference.getRefdAssignment(timestamp, true);
if (assignment == null) { if (assignment == null) {
return false; return false;
} }
selfReference |= lhs == assignment; boolean selfReference = lhs == assignment;
assignment.check(timestamp); assignment.check(timestamp);
IType governor = assignment.getType(timestamp); IType governor = assignment.getType(timestamp);
...@@ -145,7 +165,6 @@ public class DynamicMatch_template extends TTCN3Template { ...@@ -145,7 +165,6 @@ public class DynamicMatch_template extends TTCN3Template {
} }
if (governor == null) { if (governor == null) {
setIsErroneous(true); setIsErroneous(true);
return selfReference;
} }
return selfReference; return selfReference;
......
...@@ -71,17 +71,11 @@ public class ImplicationMatch_template extends TTCN3Template { ...@@ -71,17 +71,11 @@ public class ImplicationMatch_template extends TTCN3Template {
public boolean checkThisTemplateGeneric(final CompilationTimeStamp timestamp, final IType type, final boolean isModified, public boolean checkThisTemplateGeneric(final CompilationTimeStamp timestamp, final IType type, final boolean isModified,
final boolean allowOmit, final boolean allowAnyOrOmit, final boolean subCheck, final boolean implicitOmit, final Assignment lhs) { final boolean allowOmit, final boolean allowAnyOrOmit, final boolean subCheck, final boolean implicitOmit, final Assignment lhs) {
boolean selfReference = type.checkThisTemplate(timestamp, this, isModified, implicitOmit, lhs); precondition.check(timestamp, type);
implied_template.check(timestamp, type);
ITTCN3Template temporalComponent = type.checkThisTemplateRef(timestamp, precondition.getTemplateBody());
selfReference |= temporalComponent.checkThisTemplateGeneric(timestamp, type, false, false, true, subCheck, implicitOmit, lhs);
temporalComponent = type.checkThisTemplateRef(timestamp, implied_template.getTemplateBody());
selfReference |= temporalComponent.checkThisTemplateGeneric(timestamp, type, false, false, true, subCheck, implicitOmit, lhs);
checkLengthRestriction(timestamp, type); checkLengthRestriction(timestamp, type);
return selfReference; return false;
} }
@Override @Override
......
...@@ -2214,7 +2214,10 @@ pr_TemplateBody returns[ TTCN3Template template] ...@@ -2214,7 +2214,10 @@ pr_TemplateBody returns[ TTCN3Template template]
| t4 = pr_SimpleSpec { $template = $t4.template; } | t4 = pr_SimpleSpec { $template = $t4.template; }
) )
( pr_ExtraMatchingAttributes[$template] )? ( pr_ExtraMatchingAttributes[$template] )?
( t5 = pr_ImplicationMatch { implied_template = $t5.implied_template; } )? (
( t5 = pr_ImplicationMatch { implied_template = $t5.implied_template; } )
( pr_ExtraMatchingAttributes[$template] )?
)?
| dc = pr_DecodedContentMatch { $template = $dc.template; } | dc = pr_DecodedContentMatch { $template = $dc.template; }
) )
{ {
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment