Commit df54a6b0 authored by Miklos Magyari's avatar Miklos Magyari
Browse files

OOP: 'this' reference improvements (issue #417, issue #427)


Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent 74972ccd
......@@ -54,7 +54,7 @@ type class BaseFunctionClass {
}
type class OuterClass {
private var integer m_int := 0;
private var integer m_int := 0;
class NestedClass {
const charstring c_text := "abc";
......@@ -90,14 +90,14 @@ type class SubFunctionClass extends BaseFunctionClass {
type class @abstract FinallyClass {
public const integer m_const := 0;
} finally {
log(this);
log(this.m_const);
}
// a trait class cannot have a finally block
type class @trait FinallyClass2 {
public const integer m_const := 0;
} finally {
log(this);
log(this.m_const);
}
// bad combination of class modifiers
......@@ -105,6 +105,25 @@ type class @final @abstract BadClass1 { }
type class @final @trait BadClass3 { }
type class @abstract @trait BadClass2 { }
// class with this
type class ClassWithThis {
public var integer vl_a;
const float vl_b;
public function pl_dummy(in integer pl_int) return integer {
return 1;
}
public function f_dummy2(in charstring pl_dummy) {
var charstring vl_int := this.pl_dummy(1);
}
create (integer a, float b) {
this.a := vl_a;
this.b := vl_b;
}
}
testcase tc_basicSyntax() runs on CT {
var GrandSubClass vl_gsc := GrandSubClass.create;
......
......@@ -95,7 +95,7 @@ type class VariousMembers {
}
}
type class @trait AbstractMembersClass {
type class @trait AbstractMembersClass {
function @abstract f();
function @abstract f2(in integer p_int);
function @abstract f3(in integer p_int) return charstring;
......@@ -121,13 +121,21 @@ type class OuterClass {
type class @abstract FinallyClass {
public const integer m_const := 0;
} finally {
log(this);
log(this.m_const);
}
// `this` reference
type class ClassWithThis {
public var integer vl_a;
const float vl_b;
public function pl_dummy(in integer pl_int) return integer {
return 1;
}
public function f_dummy2(in charstring pl_dummy) {
var integer vl_int := this.pl_dummy(1);
}
create (integer a, float b) {
this.a := vl_a;
......
......@@ -37,6 +37,7 @@ import org.eclipse.titan.designer.AST.TTCN3.definitions.FormalParameter.paramete
import org.eclipse.titan.designer.AST.TTCN3.definitions.FormalParameterList;
import org.eclipse.titan.designer.AST.TTCN3.definitions.IParameterisedAssignment;
import org.eclipse.titan.designer.AST.TTCN3.definitions.LazyFuzzyParamData;
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;
......@@ -72,6 +73,12 @@ public class Reference extends ASTNode implements ILocateableNode, IIncrementall
public static final String TYPEEXPECTED = "Type reference expected";
public static final String ASN1SETTINGEXPECTED = "Reference to ASN.1 setting expected";
public enum Ref_Type {
REF_BASIC,
REF_THIS,
REF_SUPER
}
/**
* Module identifier. Might be null. In that case it means, that we were
* not able to decide if the reference has a module identifier or not
......@@ -115,6 +122,8 @@ public class Reference extends ASTNode implements ILocateableNode, IIncrementall
* not.
*/
private boolean usedInIsbound = false;
private Ref_Type reftype = Ref_Type.REF_BASIC;
public Reference(final Identifier modid) {
this.modid = modid;
......@@ -122,6 +131,11 @@ public class Reference extends ASTNode implements ILocateableNode, IIncrementall
subReferences = new ArrayList<ISubReference>();
}
public Reference(final Identifier modid, Ref_Type reftype) {
this(null);
this.reftype = reftype;
}
public Reference(final Identifier modid, final List<ISubReference> subReferences) {
this.modid = modid;
detectedModuleId = modid != null;
......@@ -159,7 +173,7 @@ public class Reference extends ASTNode implements ILocateableNode, IIncrementall
@Override
/** {@inheritDoc} */
public void setMyScope(final Scope scope) {
public void setMyScope(Scope scope) {
super.setMyScope(scope);
subReferences.trimToSize();
for (int i = 0; i < subReferences.size(); i++) {
......@@ -501,7 +515,15 @@ public class Reference extends ASTNode implements ILocateableNode, IIncrementall
detectedModuleId = false;
detectModid();
referredAssignment = myScope.getAssBySRef(timestamp, this, referenceChain);
if (reftype == Ref_Type.REF_THIS) {
Scope s = myScope;
while (s != null && s instanceof StatementBlock || s instanceof NamedBridgeScope || s instanceof FormalParameterList) {
s = s.getParentScope();
}
referredAssignment = s.getAssBySRef(timestamp, this, referenceChain);
} else {
referredAssignment = myScope.getAssBySRef(timestamp, this, referenceChain);
}
if (referredAssignment == null) {
isErroneous = true;
return referredAssignment;
......@@ -1445,4 +1467,8 @@ public class Reference extends ASTNode implements ILocateableNode, IIncrementall
}
}
public Ref_Type getReferenceType() {
return reftype;
}
}
......@@ -151,34 +151,29 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl
@Override
/** {@inheritDoc} */
public Assignment getAssBySRef(final CompilationTimeStamp timestamp, final Reference reference, final IReferenceChain refChain) {
if (reference.getModuleIdentifier() != null) {
return getParentScope().getAssBySRef(timestamp, reference);
}
if (lastUniquenessCheck == null) {
checkUniqueness(timestamp);
}
if (reference.getModuleIdentifier() != null) {
return getParentScope().getAssBySRef(timestamp, reference);
final String name = reference.getId().getName();
Definition definition = definitions.getDefinition(name);
if (definition != null) {
return definition;
}
int nrSub = reference.getSubreferences().size();
if (nrSub > 0) {
Identifier identifier = reference.getSubreferences(nrSub - 1, nrSub - 1).get(0).getId();
String name = identifier.getName();
Definition definition = definitions.getDefinition(name);
if (definition != null) {
definition = extendsGainedDefinitions.get(name);
if (definition != null) {
if (VisibilityModifier.Public.equals(definition.getVisibilityModifier())) {
return definition;
}
definition = extendsGainedDefinitions.get(name);
if (definition != null) {
if (VisibilityModifier.Public.equals(definition.getVisibilityModifier()) ||
VisibilityModifier.Protected.equals(definition.getVisibilityModifier())) {
return definition;
}
reference.getLocation().reportSemanticError(MessageFormat.format(
MEMBERNOTVISIBLE, reference.getId().getDisplayName(), identifier.getDisplayName()));
return null;
}
reference.getLocation().reportSemanticError(MessageFormat.format(
MEMBERNOTVISIBLE, reference.getId().getDisplayName(), identifier.getDisplayName()));
return null;
}
return getParentScope().getAssBySRef(timestamp, reference);
......@@ -196,6 +191,19 @@ public final class ClassTypeBody extends TTCN3Scope implements IReferenceChainEl
return super.hasAssignmentWithId(timestamp, identifier);
}
public Assignment getAssByIdentifier(final CompilationTimeStamp timestamp, final Identifier identifier) {
final String name = identifier.getName();
Definition definition = definitions.getDefinition(name);
if (definition != null) {
return definition;
}
definition = extendsGainedDefinitions.get(name);
if (definition != null) {
return definition;
}
return null;
}
/**
* Checks the uniqueness of the definitions, and also builds a hashmap of
* them to speed up further searches.
......
......@@ -105,7 +105,7 @@ public final class Class_Type extends Type implements ITypeWithComponents {
return null;
case fieldSubReference:
case parameterisedSubReference:
Assignment assignment = classBody.getAssBySRef(timestamp, reference);
Assignment assignment = classBody.getAssByIdentifier(timestamp, subreference.getId());
if (assignment == null)
return null;
......@@ -144,6 +144,7 @@ public final class Class_Type extends Type implements ITypeWithComponents {
if (isTrait && finallyBlock != null) {
finallyBlock.getLocation().reportSemanticError(TRAITWITHFINALLY);
setIsErroneous(true);
}
initAttributes(timestamp);
......
......@@ -6442,14 +6442,18 @@ pr_ReferencedValue returns[Value value]
pr_ValueReference returns[Reference reference]
@init {
$reference = null;
boolean isThisRef = false;
}:
( ( ( r = pr_GlobalModuleId { $reference = $r.reference; }
| th = pr_ThisKeyword
| th = pr_ThisKeyword { isThisRef = true; }
| SUPER
)
pr_Dot
)?
id = pr_Identifier {
if (isThisRef == true) {
$reference = new Reference(null, Reference.Ref_Type.REF_THIS);
}
if ( $id.identifier != null ) {
if ( $reference == null ) {
$reference = new Reference(null);
......@@ -6460,9 +6464,6 @@ pr_ValueReference returns[Reference reference]
$reference.setLocation(getLocation( $start, getLastVisibleToken()));//TODO: maybe this can be improved too.
}
}
| th = pr_ThisKeyword {
}
);
pr_AddressValue returns[Value value]
......@@ -9011,9 +9012,8 @@ pr_ClassKeyword:
);
pr_ThisKeyword:
(
THIS
);
;
pr_FinalModifier returns[boolean isFinal]
@init {
......
......@@ -64,11 +64,13 @@ public class OOP_Semantic_tests {
markersToCheck.add(new MarkerToCheck("An absract class cannot be final", lineNum, IMarker.SEVERITY_ERROR));
markersToCheck.add(new MarkerToCheck("A trait class cannot be final", ++lineNum, IMarker.SEVERITY_ERROR));
markersToCheck.add(new MarkerToCheck("A class cannot be both abstract and trait", ++lineNum, IMarker.SEVERITY_ERROR));
lineNum += 9;
markersToCheck.add(new MarkerToCheck("There is no visible definition with name `vl_gsc' in module `classesNegativeSemantic'", 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 += 17;
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));
return markersToCheck;
}
......
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