Commit 75a50c78 authored by Miklos Magyari's avatar Miklos Magyari Committed by Adam Knapp
Browse files

OOP: improved 'super' references (issue #417, issue #427)


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent 3cfc640e
......@@ -124,6 +124,27 @@ type class ClassWithThis {
}
}
function f_fake_super() return charstring {
return "abc";
}
// bad super references
function f_notinclass(in integer pl_int) {
var charstring vl_ch := super.f_fake_super();
}
type class FuncClass extends BaseFunctionClass {
public function f_get_one() return charstring {
return "xyz";
}
private function f_test_super() {
// type mismatches
var integer vl_int := f_get_one();
var charstring vl_cs:= super.f_get_one();
}
}
testcase tc_basicSyntax() runs on CT {
var GrandSubClass vl_gsc := GrandSubClass.create;
......
......@@ -191,6 +191,24 @@ type class SubClass4 extends SuperBaseClass {
}
}
type class BaseFunctionClass {
public function f_get_one() return integer {
return 1;
}
}
type class FuncClass extends BaseFunctionClass {
public function f_get_one() return charstring {
return "xyz";
}
private function f_test_super() {
// type mismatches
var integer vl_int := super.f_get_one();
var charstring vl_cs:= f_get_one();
}
}
testcase tc_basicSyntax() runs on CT {
var object vl_obj := MinimalClass.create;
......
......@@ -41,6 +41,7 @@ import org.eclipse.titan.designer.AST.TTCN3.statements.StatementBlock;
import org.eclipse.titan.designer.AST.TTCN3.types.AbstractOfType;
import org.eclipse.titan.designer.AST.TTCN3.types.Anytype_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.Array_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.ClassTypeBody;
import org.eclipse.titan.designer.AST.TTCN3.types.Class_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.CompField;
import org.eclipse.titan.designer.AST.TTCN3.types.ComponentTypeBody;
......@@ -60,11 +61,13 @@ import org.eclipse.titan.designer.parsers.ttcn3parser.TTCN3ReparseUpdater;
* in the source code.
*
* @author Kristof Szabados
* @author Miklos Magyari
* */
public class Reference extends ASTNode implements ILocateableNode, IIncrementallyUpdateable, IReferencingElement {
private static final String STRINGELEMENTUNUSABLE = "Reference to a string element of type `{0}'' cannot be used in this context";
private static final String VARIABLEXPECTED = "Reference to a variable or value parameter was expected instead of {0}";
private static final String ALTSTEPEXPECTED = "Reference to an altstep was expected in the argument instead of {0}";
private static final String THISORSUPEROUTSIDECLASS = "`{0}'' reference is only valid inside class bodies";
private static final String FULLNAMEPART = ".<sub_reference";
......@@ -515,12 +518,26 @@ public class Reference extends ASTNode implements ILocateableNode, IIncrementall
detectedModuleId = false;
detectModid();
if (reftype == Ref_Type.REF_THIS) {
if (reftype == Ref_Type.REF_THIS || reftype == Ref_Type.REF_SUPER) {
Scope s = myScope;
while (s != null && s instanceof StatementBlock || s instanceof NamedBridgeScope || s instanceof FormalParameterList) {
s = s.getParentScope();
}
referredAssignment = s.getAssBySRef(timestamp, this, referenceChain);
if (s == null) {
return null;
}
if (! (s instanceof ClassTypeBody)) {
getLocation().reportSemanticError(MessageFormat.format(THISORSUPEROUTSIDECLASS, reftype == Ref_Type.REF_THIS ? "this" : "super"));
setIsErroneous(true);
return null;
}
if (reftype == Ref_Type.REF_SUPER) {
final ClassTypeBody body = (ClassTypeBody)s;
referredAssignment = body.getAssFromParents(timestamp, this);
}
if (reftype == Ref_Type.REF_THIS) {
referredAssignment = s.getAssBySRef(timestamp, this, referenceChain);
}
} else {
referredAssignment = myScope.getAssBySRef(timestamp, this, referenceChain);
}
......
......@@ -321,6 +321,19 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl
return result;
}
public Assignment getAssFromParents(final CompilationTimeStamp timestamp, final Reference reference) {
final LinkedList<ClassTypeBody> toBeChecked = new LinkedList<ClassTypeBody>(extendsReferences.getClassBodies());
Assignment assignment = null;
for (ClassTypeBody body : toBeChecked) {
assignment = body.getAssBySRef(timestamp, reference);
if (assignment != null) {
return assignment;
}
}
return null;
}
public void check(final CompilationTimeStamp timestamp) {
if (lastCompilationTimeStamp != null && !lastCompilationTimeStamp.isLess(timestamp)) {
return;
......
......@@ -3061,11 +3061,12 @@ pr_FunctionInstance returns[Reference temporalReference]
ParsedActualParameters parameters = null;
Reference ref = null;
FieldSubReference fieldSubReference = null;
Reference superRef = null;
}:
( ((id = pr_Identifier {
fieldSubReference = new FieldSubReference($id.identifier);
fieldSubReference.setLocation(getLocation( $id.start, $id.stop));
} | SUPER) DOT )?
} | SUPER { superRef = new Reference(null, Reference.Ref_Type.REF_SUPER); } ) DOT )?
t = pr_FunctionRef { $temporalReference = $t.reference; }
a = pr_LParen
( p = pr_FunctionActualParList { parameters = $p.parsedParameters; } )?
......@@ -3074,6 +3075,9 @@ pr_FunctionInstance returns[Reference temporalReference]
{
if($temporalReference != null) {
ISubReference subReference = $temporalReference.removeLastSubReference();
if (superRef != null) {
$temporalReference = superRef;
}
if(parameters == null) {
parameters = new ParsedActualParameters();
}
......@@ -3092,6 +3096,7 @@ pr_FunctionInstance returns[Reference temporalReference]
pr_FunctionRef returns[Reference reference]
@init {
$reference = null;
boolean isSuperRef = false;
}:
( i1 = pr_Identifier
( DOT
......@@ -6443,10 +6448,11 @@ pr_ValueReference returns[Reference reference]
@init {
$reference = null;
boolean isThisRef = false;
boolean isSuperRef = false;
}:
( ( ( r = pr_GlobalModuleId { $reference = $r.reference; }
| th = pr_ThisKeyword { isThisRef = true; }
| SUPER
| THIS { isThisRef = true; }
| SUPER { isSuperRef = true; }
)
pr_Dot
)?
......@@ -6454,6 +6460,9 @@ pr_ValueReference returns[Reference reference]
if (isThisRef == true) {
$reference = new Reference(null, Reference.Ref_Type.REF_THIS);
}
if (isSuperRef == true) {
$reference = new Reference(null, Reference.Ref_Type.REF_SUPER);
}
if ( $id.identifier != null ) {
if ( $reference == null ) {
$reference = new Reference(null);
......@@ -6464,7 +6473,7 @@ pr_ValueReference returns[Reference reference]
$reference.setLocation(getLocation( $start, getLastVisibleToken()));//TODO: maybe this can be improved too.
}
}
| th = pr_ThisKeyword {
| THIS {
$reference = new Reference(null, Reference.Ref_Type.REF_THIS);
}
);
......@@ -9014,10 +9023,6 @@ pr_ClassKeyword:
CLASS
);
pr_ThisKeyword:
THIS
;
pr_FinalModifier returns[boolean isFinal]
@init {
$isFinal = false;
......
......@@ -45,7 +45,7 @@ public class OOP_Semantic_tests {
private ArrayList<MarkerToCheck> oopNegative_ttcn_initializer() {
//oopNegativeSemanticTest.ttcn
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(13);
ArrayList<MarkerToCheck> markersToCheck = new ArrayList<MarkerToCheck>(16);
int lineNum = 28;
markersToCheck.add(new MarkerToCheck("class type expected", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 15;
......@@ -66,7 +66,12 @@ public class OOP_Semantic_tests {
markersToCheck.add(new MarkerToCheck("A class cannot be both abstract and trait", ++lineNum, IMarker.SEVERITY_ERROR));
lineNum += 12;
markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `charstring' was expected instead of `integer'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 17;
lineNum += 15;
markersToCheck.add(new MarkerToCheck("`super' reference is only valid inside class bodies", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 10;
markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `integer' was expected instead of `charstring'", lineNum, IMarker.SEVERITY_ERROR));
markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `charstring' was expected instead of `integer'", ++lineNum, IMarker.SEVERITY_ERROR));
lineNum += 12;
markersToCheck.add(new MarkerToCheck("Type mismatch: a value of type `charstring' was expected instead of `integer'", lineNum, IMarker.SEVERITY_ERROR));
lineNum += 8;
markersToCheck.add(new MarkerToCheck("integer value was expected", lineNum, IMarker.SEVERITY_ERROR));
......
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