use of org.eclipse.titan.designer.AST.TTCN3.TemplateRestriction in project titan.EclipsePlug-ins by eclipse.
the class Def_Var_Template method generateCode.
@Override
public /**
* {@inheritDoc}
*/
void generateCode(final JavaGenData aData, final boolean cleanUp) {
final String genName = getGenName();
final StringBuilder sb = aData.getSrc();
final StringBuilder source = new StringBuilder();
final StringBuilder initComp = aData.getInitComp();
final String typeGeneratedName = type.getGenNameTemplate(aData, source, getMyScope());
if (type.getTypetype().equals(Type_type.TYPE_ARRAY)) {
final Array_Type arrayType = (Array_Type) type;
final StringBuilder sbforTemp = aData.getCodeForType(arrayType.getGenNameOwn());
arrayType.generateCodeTemplate(aData, sbforTemp);
}
source.append(MessageFormat.format(" public static final {0} {1} = new {0}();\n", typeGeneratedName, genName));
sb.append(source);
if (initialValue != null) {
initialValue.generateCodeInit(aData, initComp, genName);
if (templateRestriction != Restriction_type.TR_NONE && generateRestrictionCheck) {
TemplateRestriction.generateRestrictionCheckCode(aData, initComp, location, genName, templateRestriction);
}
} else if (cleanUp) {
initComp.append(MessageFormat.format("{0}.cleanUp();\n", genName));
}
}
use of org.eclipse.titan.designer.AST.TTCN3.TemplateRestriction in project titan.EclipsePlug-ins by eclipse.
the class Assignment_Statement method check.
@Override
public /**
* {@inheritDoc}
*/
void check(final CompilationTimeStamp timestamp) {
if (lastTimeChecked != null && !lastTimeChecked.isLess(timestamp)) {
return;
}
lastTimeChecked = timestamp;
isErroneous = false;
selfReference = false;
templateRestriction = Restriction_type.TR_NONE;
generateRestrictionCheck = false;
if (reference == null) {
return;
}
reference.setUsedOnLeftHandSide();
final Assignment assignment = reference.getRefdAssignment(timestamp, true);
if (assignment == null || assignment.getIsErroneous()) {
isErroneous = true;
return;
}
if (template == null) {
return;
}
switch(assignment.getAssignmentType()) {
case A_PAR_VAL_IN:
((FormalParameter) assignment).useAsLValue(reference);
if (template.isValue(timestamp)) {
// TODO: isValue should be checked within the previous line! This is double check!
final IValue temporalValue = template.getValue();
checkVarAssignment(timestamp, assignment, temporalValue);
template.setMyGovernor(temporalValue.getMyGovernor());
break;
} else if (Template_type.VALUE_LIST.equals(template.getTemplatetype()) && ((ValueList_Template) template).getNofTemplates() == 1) {
// TODO: convert (x) to x to compilation!
break;
} else {
template.getLocation().reportSemanticError(TEMPLATEASSIGNMENTTOVALUE);
template.setIsErroneous(true);
return;
}
case A_PAR_VAL_OUT:
case A_PAR_VAL_INOUT:
case A_PAR_VAL:
((FormalParameter) assignment).setWritten();
if (template.isValue(timestamp)) {
// TODO: isValue should be checked within the previous line! This is double check!
final IValue temporalValue = template.getValue();
checkVarAssignment(timestamp, assignment, temporalValue);
template.setMyGovernor(temporalValue.getMyGovernor());
break;
} else if (Template_type.VALUE_LIST.equals(template.getTemplatetype()) && ((ValueList_Template) template).getNofTemplates() == 1) {
// TODO: convert (x) to x to compilation!
break;
} else {
template.getLocation().reportSemanticError(TEMPLATEASSIGNMENTTOVALUE);
template.setIsErroneous(true);
return;
}
// break
case A_VAR:
((Def_Var) assignment).setWritten();
if (template.getIsErroneous(timestamp)) {
return;
}
final IValue temporalValue = template.getValue();
if (temporalValue != null) {
checkVarAssignment(timestamp, assignment, temporalValue);
template.setMyGovernor(temporalValue.getMyGovernor());
break;
} else if (Template_type.VALUE_LIST.equals(template.getTemplatetype()) && ((ValueList_Template) template).getNofTemplates() == 1) {
break;
} else {
template.getLocation().reportSemanticError(TEMPLATEASSIGNMENTTOVALUE);
template.setIsErroneous(true);
return;
}
case A_PAR_TEMP_IN:
((FormalParameter) assignment).useAsLValue(reference);
checkTemplateAssignment(timestamp, assignment, Expected_Value_type.EXPECTED_TEMPLATE, null);
break;
case A_PAR_TEMP_OUT:
case A_PAR_TEMP_INOUT:
((FormalParameter) assignment).setWritten();
checkTemplateAssignment(timestamp, assignment, Expected_Value_type.EXPECTED_TEMPLATE, null);
break;
case A_VAR_TEMPLATE:
((Def_Var_Template) assignment).setWritten();
checkTemplateAssignment(timestamp, assignment, Expected_Value_type.EXPECTED_TEMPLATE, null);
break;
default:
reference.getLocation().reportSemanticError(MessageFormat.format(VARIABLEREFERENCEEXPECTED, assignment.getAssignmentName()));
reference.setIsErroneous(true);
isErroneous = true;
}
}
use of org.eclipse.titan.designer.AST.TTCN3.TemplateRestriction in project titan.EclipsePlug-ins by eclipse.
the class Assignment_Statement method generateCode.
@Override
public /**
* {@inheritDoc}
*/
void generateCode(final JavaGenData aData, final StringBuilder source) {
if (reference == null || template == null) {
return;
}
final boolean rhsCopied = selfReference;
// TODO this is actually much more complicated
final Assignment assignment = reference.getRefdAssignment(CompilationTimeStamp.getBaseTimestamp(), true);
if (assignment == null) {
// TODO: handle null
return;
}
boolean isValue;
switch(assignment.getAssignmentType()) {
case A_PAR_VAL_IN:
case A_PAR_VAL_OUT:
case A_PAR_VAL_INOUT:
case A_PAR_VAL:
case A_VAR:
isValue = true;
break;
default:
isValue = false;
break;
}
boolean isOptional = false;
if (assignment.getType(CompilationTimeStamp.getBaseTimestamp()).fieldIsOptional(reference.getSubreferences())) {
isOptional = true;
}
if (isValue) {
final String rhsCopy = aData.getTemporaryVariableName();
String rhsRef = rhsCopy;
if (rhsCopied) {
source.append("{\n");
if (isOptional) {
source.append(MessageFormat.format("Optional<{0}> {1} = new Optional<{0}>({0}.class);\n", template.getMyGovernor().getGenNameValue(aData, source, myScope), rhsCopy));
rhsRef += ".get()";
} else {
source.append(MessageFormat.format("{0} {1} = new {0}();\n", template.getMyGovernor().getGenNameValue(aData, source, myScope), rhsCopy));
}
}
final IValue value = template.getValue();
// TODO handle needs_conv
if (reference.getSubreferences().size() > 1) {
if (value.canGenerateSingleExpression()) {
final ExpressionStruct expression = new ExpressionStruct();
reference.generateCode(aData, expression);
source.append(expression.preamble);
String temp;
IType type = getType(CompilationTimeStamp.getBaseTimestamp(), assignment);
type = type.getFieldType(CompilationTimeStamp.getBaseTimestamp(), reference, 1, Expected_Value_type.EXPECTED_TEMPLATE, false);
// if (value.getValuetype() != Value_type.OMIT_VALUE && (isOptional || type.getTypetypeTtcn3() != value.getExpressionReturntype(CompilationTimeStamp.getBaseTimestamp(), Expected_Value_type.EXPECTED_TEMPLATE))) {
if (value.getValuetype() != Value_type.OMIT_VALUE && value.getValuetype() != Value_type.REFERENCED_VALUE && (isOptional || type.getTypetypeTtcn3() != value.getExpressionReturntype(CompilationTimeStamp.getBaseTimestamp(), Expected_Value_type.EXPECTED_TEMPLATE))) {
temp = MessageFormat.format("new {0}({1})", value.getMyGovernor().getGenNameValue(aData, source, myScope), value.generateSingleExpression(aData));
} else {
temp = value.generateSingleExpression(aData).toString();
}
if (rhsCopied) {
source.append(MessageFormat.format("{0}.assign({1});\n", rhsCopy, temp));
expression.expression.append(MessageFormat.format(".assign({0});\n", rhsCopy));
} else {
expression.expression.append(MessageFormat.format(".assign({0});\n", temp));
}
source.append(expression.expression);
source.append(expression.postamble);
} else {
final String tempID = aData.getTemporaryVariableName();
final String typeGenname = value.getMyGovernor().getGenNameValue(aData, source, myScope);
final ExpressionStruct leftExpression = new ExpressionStruct();
reference.generateCode(aData, leftExpression);
if (rhsCopied) {
// TODO handle needs conversion case
value.generateCodeInit(aData, source, rhsRef);
} else if (isOptional) {
leftExpression.expression.append(".get()");
}
source.append("{\n");
source.append(leftExpression.preamble);
if (reference.refersToStringElement()) {
// LHS is a string element
aData.addBuiltinTypeImport(typeGenname + "_Element");
source.append(MessageFormat.format("{0}_Element {1} = {2};\n", typeGenname, tempID, leftExpression.expression));
} else {
source.append(MessageFormat.format("{0} {1} = {2};\n", typeGenname, tempID, leftExpression.expression));
}
source.append(leftExpression.postamble);
if (rhsCopied) {
source.append(MessageFormat.format("{0}.assign({1});\n", tempID, rhsCopy));
} else {
// TODO handle needs conversion
value.generateCodeInit(aData, source, tempID);
}
source.append("}\n");
}
} else {
// left hand side is a single assignment
final String name = assignment.getGenNameFromScope(aData, source, myScope, null);
if (!isOptional && value.getValuetype() == Value_type.REFERENCED_VALUE) {
final Reference rightReference = ((Referenced_Value) value).getReference();
final Assignment rightAssignment = rightReference.getRefdAssignment(CompilationTimeStamp.getBaseTimestamp(), true);
if (rightAssignment.getType(CompilationTimeStamp.getBaseTimestamp()).fieldIsOptional(rightReference.getSubreferences())) {
value.generateCodeInitMandatory(aData, source, rhsCopied ? rhsCopy : name);
} else {
value.generateCodeInit(aData, source, rhsCopied ? rhsCopy : name);
}
} else {
value.generateCodeInit(aData, source, rhsCopied ? rhsCopy : name);
}
if (rhsCopied) {
source.append(MessageFormat.format("{0}.assign({1});\n", name, rhsCopy));
}
}
if (rhsCopied) {
source.append("}\n");
}
} else {
final String rhsCopy = aData.getTemporaryVariableName();
if (rhsCopied) {
source.append("{\n");
source.append(MessageFormat.format("{0} {1} = new {0}();\n", template.getMyGovernor().getGenNameTemplate(aData, source, myScope), rhsCopy));
}
// TODO handle needs_conv
if (reference.getSubreferences().size() > 1) {
if ((templateRestriction != Restriction_type.TR_NONE || !generateRestrictionCheck) && template.hasSingleExpression()) {
final ExpressionStruct expression = new ExpressionStruct();
reference.generateCode(aData, expression);
source.append(expression.preamble);
if (rhsCopied) {
source.append(MessageFormat.format("{0}.assign({1});\n", rhsCopy, template.getSingleExpression(aData, false)));
expression.expression.append(MessageFormat.format(".assign({0});\n", rhsCopy));
} else {
expression.expression.append(MessageFormat.format(".assign({0});\n", template.getSingleExpression(aData, false)));
}
expression.mergeExpression(source);
} else {
final String tempID = aData.getTemporaryVariableName();
final ExpressionStruct expression = new ExpressionStruct();
reference.generateCode(aData, expression);
if (rhsCopied) {
// TODO handle needs conversion case
template.generateCodeInit(aData, source, rhsCopy);
}
source.append("{\n");
source.append(expression.preamble);
final IType governor = template.getMyGovernor();
source.append(MessageFormat.format("{0} {1} = {2};\n", governor.getGenNameTemplate(aData, source, template.getMyScope()), tempID, expression.expression));
source.append(expression.postamble);
if (rhsCopied) {
source.append(MessageFormat.format("{0}.assign({1});\n", tempID, rhsCopy));
} else {
// TODO handle needs conversion case
if (Type_type.TYPE_SEQUENCE_OF.equals(governor.getTypetype()) || Type_type.TYPE_ARRAY.equals(governor.getTypetype())) {
source.append(MessageFormat.format("{0}.removeAllPermutations();\n", tempID));
}
template.generateCodeInit(aData, source, tempID);
}
if (templateRestriction != Restriction_type.TR_NONE && generateRestrictionCheck) {
TemplateRestriction.generateRestrictionCheckCode(aData, source, location, tempID, templateRestriction);
}
source.append("}\n");
}
} else {
// left hand side is a single assignment
final String rhsName = reference.getRefdAssignment(CompilationTimeStamp.getBaseTimestamp(), false).getGenNameFromScope(aData, source, myScope, "");
final IType governor = template.getMyGovernor();
if (Type_type.TYPE_SEQUENCE_OF.equals(governor.getTypetype()) || Type_type.TYPE_ARRAY.equals(governor.getTypetype())) {
source.append(MessageFormat.format("{0}.removeAllPermutations();\n", rhsCopied ? rhsCopy : rhsName));
}
template.generateCodeInit(aData, source, rhsCopied ? rhsCopy : rhsName);
if (rhsCopied) {
source.append(MessageFormat.format("{0}.assign({1});\n", rhsName, rhsCopy));
}
if (templateRestriction != Restriction_type.TR_NONE && generateRestrictionCheck) {
TemplateRestriction.generateRestrictionCheckCode(aData, source, location, rhsName, templateRestriction);
}
}
if (rhsCopied) {
source.append("}\n");
}
}
}
use of org.eclipse.titan.designer.AST.TTCN3.TemplateRestriction in project titan.EclipsePlug-ins by eclipse.
the class Invoke_Template method generateCodeExpression.
@Override
public /**
* {@inheritDoc}
*/
void generateCodeExpression(final JavaGenData aData, final ExpressionStruct expression, final TemplateRestriction.Restriction_type templateRestriction) {
IType governor = myGovernor;
if (governor == null) {
governor = getExpressionGovernor(CompilationTimeStamp.getBaseTimestamp(), Expected_Value_type.EXPECTED_TEMPLATE);
}
if (governor == null) {
return;
}
if (lengthRestriction == null && !isIfpresent && templateRestriction == Restriction_type.TR_NONE) {
// The single expression must be tried first because this rule might cover some referenced templates.
if (hasSingleExpression()) {
final String genName = governor.getGenNameTemplate(aData, expression.expression, myScope);
expression.expression.append(MessageFormat.format("new {0}(", genName));
if (governor.getTypetype() == Type_type.TYPE_ARRAY) {
final Array_Type array_type = (Array_Type) governor;
expression.expression.append(MessageFormat.format(" {0}.class, ", array_type.getElementType().getGenNameTemplate(aData, expression.expression, myScope)));
}
expression.expression.append(getSingleExpression(aData, true));
expression.expression.append(')');
return;
}
generateCodeExpressionInvoke(aData, expression);
return;
}
final String tempId = aData.getTemporaryVariableName();
expression.preamble.append(MessageFormat.format("{0} {1} = new {0}();\n", governor.getGenNameTemplate(aData, expression.expression, myScope), tempId));
generateCodeInit(aData, expression.preamble, tempId);
if (templateRestriction != Restriction_type.TR_NONE) {
TemplateRestriction.generateRestrictionCheckCode(aData, expression.expression, location, tempId, templateRestriction);
}
expression.expression.append(tempId);
}
use of org.eclipse.titan.designer.AST.TTCN3.TemplateRestriction in project titan.EclipsePlug-ins by eclipse.
the class Function_Type method checkThisValue.
@Override
public /**
* {@inheritDoc}
*/
boolean checkThisValue(final CompilationTimeStamp timestamp, final IValue value, final Assignment lhs, final ValueCheckingOptions valueCheckingOptions) {
final boolean selfReference = super.checkThisValue(timestamp, value, lhs, valueCheckingOptions);
final IValue last = value.getValueRefdLast(timestamp, valueCheckingOptions.expected_value, null);
if (last == null || last.getIsErroneous(timestamp)) {
return selfReference;
}
last.setMyGovernor(this);
// already handled ones
switch(value.getValuetype()) {
case OMIT_VALUE:
case REFERENCED_VALUE:
return selfReference;
case UNDEFINED_LOWERIDENTIFIER_VALUE:
if (Value_type.REFERENCED_VALUE.equals(last.getValuetype())) {
return selfReference;
}
break;
default:
break;
}
Assignment assignment = null;
switch(last.getValuetype()) {
case FUNCTION_REFERENCE_VALUE:
assignment = ((Function_Reference_Value) last).getReferredFunction();
if (assignment == null) {
value.setIsErroneous(true);
return selfReference;
}
assignment.check(timestamp);
break;
case TTCN3_NULL_VALUE:
value.setValuetype(timestamp, Value_type.FAT_NULL_VALUE);
return selfReference;
case EXPRESSION_VALUE:
case MACRO_VALUE:
// already checked
return selfReference;
default:
value.getLocation().reportSemanticError(FUNCTIONREFERENCEVALUEEXPECTED);
value.setIsErroneous(true);
return selfReference;
}
// external functions do not have runs on clauses
if (assignment instanceof Def_Function) {
formalParList.checkCompatibility(timestamp, ((Def_Function) assignment).getFormalParameterList(), value.getLocation());
final IType tempRunsOnType = ((Def_Function) assignment).getRunsOnType(timestamp);
if (tempRunsOnType != null) {
if (runsOnSelf) {
// check against the runs on component type of the scope of the value
final Scope valueScope = value.getMyScope();
if (valueScope == null) {
value.setIsErroneous(true);
value.setLastTimeChecked(timestamp);
return selfReference;
}
final RunsOnScope runsOnScope = valueScope.getScopeRunsOn();
if (runsOnScope != null) {
final Component_Type componentType = runsOnScope.getComponentType();
if (!tempRunsOnType.isCompatible(timestamp, componentType, null, null, null)) {
value.getLocation().reportSemanticError(MessageFormat.format("Runs on clause mismatch: type `{0}'' has a `runs on self'' clause and the current scope expects " + "component type `{1}'', but {2} runs on `{3}''", getTypename(), componentType.getTypename(), assignment.getDescription(), tempRunsOnType.getTypename()));
}
} else {
// compatibility using this component type as the scope
if (valueScope instanceof ComponentTypeBody) {
final ComponentTypeBody body = (ComponentTypeBody) valueScope;
if (!tempRunsOnType.isCompatible(timestamp, body.getMyType(), null, null, null)) {
value.getLocation().reportSemanticError(MessageFormat.format("Runs on clause mismatch: type `{0}'' has a `runs on self'' clause and the current component definition " + "is of type `{1}'', but {2} runs on `{3}''", getTypename(), body.getMyType().getTypename(), assignment.getDescription(), tempRunsOnType.getTypename()));
}
} else {
value.getLocation().reportSemanticError(MessageFormat.format("Type `{0}'' has a `runs on self'' " + "clause and the current scope does not have a `runs on'' clause, but {1} runs on `{2}''", getTypename(), assignment.getDescription(), tempRunsOnType.getTypename()));
}
}
} else {
if (runsOnRef == null) {
value.getLocation().reportSemanticError(MessageFormat.format(RUNSONLESSEXPECTED, getTypename(), assignment.getAssignmentName(), tempRunsOnType.getTypename()));
value.setIsErroneous(true);
} else {
if (runsOnType != null && !tempRunsOnType.isCompatible(timestamp, runsOnType, null, null, null)) {
value.getLocation().reportSemanticError(MessageFormat.format(INCOMPATIBLERUNSONTYPESERROR, getTypename(), runsOnType.getTypename(), assignment.getAssignmentName(), tempRunsOnType.getTypename()));
value.setIsErroneous(true);
}
}
}
}
}
switch(assignment.getAssignmentType()) {
case A_FUNCTION:
case A_EXT_FUNCTION:
if (returnType != null) {
value.getLocation().reportSemanticError(MessageFormat.format("Type `{0}'' expects a function or external function that returns a {1} of type `{2}'', but {3} does not have a return type", getTypename(), returnsTemplate ? "template" : "value", returnType.getTypename(), assignment.getDescription()));
}
break;
case A_FUNCTION_RTEMP:
{
final Restriction_type restriction = ((Def_Function) assignment).getTemplateRestriction();
if (!templateRestriction.equals(restriction)) {
value.getLocation().reportSemanticError(MessageFormat.format("Type `{0}'' expects a function or external function that returns a template with {1} restriction, " + "but {2} returns a template with {3} restriction", getTypename(), Restriction_type.TR_NONE.equals(templateRestriction) ? "no" : templateRestriction.getDisplayName(), assignment.getDescription(), Restriction_type.TR_NONE.equals(restriction) ? "no" : restriction.getDisplayName()));
}
if (returnType != null) {
final IType tempReturnType = assignment.getType(timestamp);
if (!returnType.isIdentical(timestamp, tempReturnType)) {
value.getLocation().reportSemanticError(MessageFormat.format("Return type mismatch: type `{0}'' expects a function or external function that returns a {1} of type `{2}'', " + "but {3} returns a template of type `{3}''", getTypename(), returnsTemplate ? "template" : "value", returnType.getTypename(), assignment.getDescription(), tempReturnType.getTypename()));
} else if (!returnsTemplate) {
value.getLocation().reportSemanticError(MessageFormat.format("Type `{0}'' expects a function or external function that returns a value of type `{1}'', but {2} returns a template", getTypename(), returnType.getTypename(), assignment.getDescription()));
}
} else {
value.getLocation().reportSemanticError(MessageFormat.format("Type `{0}'' expects a function or external function without return type, but {1} returns a template of type `{2}''", getTypename(), assignment.getDescription(), assignment.getType(timestamp).getTypename()));
}
break;
}
case A_EXT_FUNCTION_RTEMP:
{
final Restriction_type restriction = ((Def_Extfunction) assignment).getTemplateRestriction();
if (!templateRestriction.equals(restriction)) {
value.getLocation().reportSemanticError(MessageFormat.format("Type `{0}'' expects a function or external function that returns a template with {1} restriction, " + "but {2} returns a template with {3} restriction", getTypename(), Restriction_type.TR_NONE.equals(templateRestriction) ? "no" : templateRestriction.getDisplayName(), assignment.getDescription(), Restriction_type.TR_NONE.equals(restriction) ? "no" : restriction.getDisplayName()));
}
if (returnType != null) {
final IType tempReturnType = assignment.getType(timestamp);
if (!returnType.isIdentical(timestamp, tempReturnType)) {
value.getLocation().reportSemanticError(MessageFormat.format("Return type mismatch: type `{0}'' expects a function or external function that returns a {1} of type `{2}'', " + "but {3} returns a template of type `{3}''", getTypename(), returnsTemplate ? "template" : "value", returnType.getTypename(), assignment.getDescription(), tempReturnType.getTypename()));
} else if (!returnsTemplate) {
value.getLocation().reportSemanticError(MessageFormat.format("Type `{0}'' expects a function or external function that returns a value of type `{1}'', but {2} returns a template", getTypename(), returnType.getTypename(), assignment.getDescription()));
}
} else {
value.getLocation().reportSemanticError(MessageFormat.format("Type `{0}'' expects a function or external function without return type, but {1} returns a template of type `{2}''", getTypename(), assignment.getDescription(), assignment.getType(timestamp).getTypename()));
}
break;
}
case A_FUNCTION_RVAL:
case A_EXT_FUNCTION_RVAL:
if (returnType != null) {
final IType tempReturnType = assignment.getType(timestamp);
if (!returnType.isIdentical(timestamp, tempReturnType)) {
value.getLocation().reportSemanticError(MessageFormat.format("Return type mismatch: type `{0}'' expects a function or external function that returns a {1} of type `{2}''," + " but {3} returns a value of type `{3}''", getTypename(), returnsTemplate ? "template" : "value", returnType.getTypename(), assignment.getDescription(), tempReturnType.getTypename()));
} else if (returnsTemplate) {
value.getLocation().reportSemanticError(MessageFormat.format("Type `{0}'' expects a function or external function that returns a template of type `{1}'', but {2} returns a value", getTypename(), returnType.getTypename(), assignment.getDescription()));
}
} else {
value.getLocation().reportSemanticError(MessageFormat.format("Type `{0}'' expects a function or external function without return type, but {1} returns a value of type `{2}''", getTypename(), assignment.getDescription(), assignment.getType(timestamp).getTypename()));
}
break;
default:
break;
}
if (valueCheckingOptions.sub_check) {
// there is no parent type to check
if (subType != null) {
subType.checkThisValue(timestamp, last);
}
}
value.setLastTimeChecked(timestamp);
return selfReference;
}
Aggregations