Commit 83f14986 authored by Miklos Magyari's avatar Miklos Magyari Committed by Arpad Lovassy

OOP: added UndefCreateExpression to decide between create op and constructor call

Signed-off-by: Miklos Magyari's avatarMiklos Magyari <miklos.magyari@sigmatechnology.se>
parent c832698a
......@@ -226,6 +226,8 @@ public abstract class Expression_Value extends Value {
TIMER_READ_OPERATION,
/** undefined running (reference.running). */
UNDEFINED_RUNNING_OPERATION,
/** undefined create (component create or constructor call) */
UNDEFINED_CREATE_OPERATION,
/** timer running (reference.running). */
TIMER_RUNNING_OPERATION,
/** create (reference.create(name, location) alive). */
......
/******************************************************************************
* Copyright (c) 2000-2021 Ericsson Telecom AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
******************************************************************************/
/**
* UndefCreateExpression represents an expression in the source code that is
* either a create operation or a constructor call.
*
* Ttcn grammar is ambiguous for some cases and the parser is unable to
* differentiate between createop and constructor call in all circumstances
* so we need to store parsed data in a temporary form to postpone the decision
* for the semantic analysis phase.
*
* @author Miklos Magyari
*/
package org.eclipse.titan.designer.AST.TTCN3.values.expressions;
import java.text.MessageFormat;
import java.util.List;
import org.eclipse.titan.designer.AST.ASTVisitor;
import org.eclipse.titan.designer.AST.Assignment;
import org.eclipse.titan.designer.AST.INamedNode;
import org.eclipse.titan.designer.AST.Assignment.Assignment_type;
import org.eclipse.titan.designer.AST.Reference;
import org.eclipse.titan.designer.AST.ReferenceFinder;
import org.eclipse.titan.designer.AST.Scope;
import org.eclipse.titan.designer.AST.Type;
import org.eclipse.titan.designer.AST.Value;
import org.eclipse.titan.designer.AST.IReferenceChain;
import org.eclipse.titan.designer.AST.IType;
import org.eclipse.titan.designer.AST.IType.Type_type;
import org.eclipse.titan.designer.AST.ReferenceFinder.Hit;
import org.eclipse.titan.designer.AST.IValue;
import org.eclipse.titan.designer.AST.TTCN3.Expected_Value_type;
import org.eclipse.titan.designer.AST.TTCN3.definitions.Def_Type;
import org.eclipse.titan.designer.AST.TTCN3.types.Component_Type;
import org.eclipse.titan.designer.AST.TTCN3.values.Expression_Value;
import org.eclipse.titan.designer.parsers.CompilationTimeStamp;
import org.eclipse.titan.designer.parsers.ttcn3parser.ReParseException;
import org.eclipse.titan.designer.parsers.ttcn3parser.TTCN3ReparseUpdater;
public class UndefCreateExpression extends Expression_Value {
private static final String FIRSTOPERANDERROR = "The first operand of operation `create()' should be a charstring value";
private static final String SECONDOPERANDERROR = "The second operand of operation `create()' should be a charstring value";
private static final String COMPONENTEXPECTED = "Operation `create'' should refer to a component type instead of {0}";
private static final String TYPEMISMATCH1 = "Type mismatch: reference to a component type was expected in operation `create'' instead of `{0}''";
private static final String TYPEMISMATCH2 = "Incompatible component type: operation `create'' should refer to `{0}'' instaed of `{1}''";
private static final String OPERATIONNAME = "create()";
private Reference componentReference;
private Value name;
private Value location;
private boolean isAlive;
private Expression_Value realExpression;
private CompilationTimeStamp checkCreateTimestamp;
private Component_Type checkCreateCache;
public UndefCreateExpression(final Reference reference, final Value name, final Value location, final boolean isAlive) {
this.componentReference = reference;
this.name = name;
this.location = location;
this.isAlive = isAlive;
if (reference != null) {
reference.setFullNameParent(this);
}
if (name != null) {
name.setFullNameParent(this);
}
if (location != null) {
location.setFullNameParent(this);
}
}
@Override
/** {@inheritDoc} */
public Operation_type getOperationType() {
return Operation_type.UNDEFINED_CREATE_OPERATION;
}
@Override
/** {@inheritDoc} */
public boolean checkExpressionSelfReference(final CompilationTimeStamp timestamp, final Assignment lhs) {
// assume no self-ref
return false;
}
@Override
/** {@inheritDoc} */
public void setMyScope(final Scope scope) {
super.setMyScope(scope);
if (componentReference != null) {
componentReference.setMyScope(scope);
}
if (name != null) {
name.setMyScope(scope);
}
if (location != null) {
location.setMyScope(scope);
}
}
@Override
/** {@inheritDoc} */
public void setCodeSection(final CodeSectionType codeSection) {
super.setCodeSection(codeSection);
if (componentReference != null) {
componentReference.setCodeSection(codeSection);
}
if (name != null) {
name.setCodeSection(codeSection);
}
if (location != null) {
location.setCodeSection(codeSection);
}
if (realExpression != null) {
realExpression.setCodeSection(codeSection);
}
}
@Override
/** {@inheritDoc} */
public StringBuilder getFullName(final INamedNode child) {
final StringBuilder builder = super.getFullName(child);
if (componentReference == child) {
return builder.append(OPERAND1);
} else if (name == child) {
return builder.append(OPERAND2);
} else if (location == child) {
return builder.append(OPERAND3);
}
return builder;
}
@Override
/** {@inheritDoc} */
public Type_type getExpressionReturntype(final CompilationTimeStamp timestamp, final Expected_Value_type expectedValue) {
if (realExpression != null)
return realExpression.getExpressionReturntype(timestamp, expectedValue);
else
return null;
}
@Override
/** {@inheritDoc} */
public boolean isUnfoldable(final CompilationTimeStamp timestamp, final Expected_Value_type expectedValue,
final IReferenceChain referenceChain) {
return true;
}
@Override
/** {@inheritDoc} */
public Type getExpressionGovernor(final CompilationTimeStamp timestamp, final Expected_Value_type expectedValue) {
return checkCreate(timestamp);
}
/**
* Checks the parameters of the expression and if they are valid in
* their position in the expression or not.
*
* @param timestamp
* the timestamp of the actual semantic check cycle.
* @param expectedValue
* the kind of value expected.
* @param referenceChain
* a reference chain to detect cyclic references.
* */
private void checkExpressionOperands(final CompilationTimeStamp timestamp, final Expected_Value_type expectedValue,
final IReferenceChain referenceChain) {
checkCreate(timestamp);
if (name != null) {
final IValue last = name.setLoweridToReference(timestamp);
final Type_type typeType = last.getExpressionReturntype(timestamp, expectedValue);
if (!last.getIsErroneous(timestamp)) {
switch (typeType) {
case TYPE_CHARSTRING:
last.getValueRefdLast(timestamp, referenceChain);
break;
case TYPE_UNDEFINED:
break;
default:
name.getLocation().reportSemanticError(FIRSTOPERANDERROR);
setIsErroneous(true);
break;
}
}
}
if (location != null) {
final IValue last = location.setLoweridToReference(timestamp);
final Type_type typeType = last.getExpressionReturntype(timestamp, expectedValue);
if (!last.getIsErroneous(timestamp)) {
switch (typeType) {
case TYPE_CHARSTRING:
last.getValueRefdLast(timestamp, referenceChain);
break;
case TYPE_UNDEFINED:
break;
default:
name.getLocation().reportSemanticError(SECONDOPERANDERROR);
setIsErroneous(true);
break;
}
}
}
checkExpressionDynamicPart(expectedValue, OPERATIONNAME, false, true, false);
}
@Override
/** {@inheritDoc} */
public IValue evaluateValue(final CompilationTimeStamp timestamp, final Expected_Value_type expectedValue,
final IReferenceChain referenceChain) {
if (lastTimeChecked != null && !lastTimeChecked.isLess(timestamp)) {
return lastValue;
}
isErroneous = false;
lastTimeChecked = timestamp;
lastValue = this;
if (componentReference == null) {
return lastValue;
}
checkCreate(timestamp);
checkExpressionOperands(timestamp, expectedValue, referenceChain);
realExpression = new ComponentCreateExpression(componentReference, name, location, isAlive);
realExpression.setMyScope(getMyScope());
realExpression.setFullNameParent(this);
realExpression.setLocation(getLocation());
realExpression.evaluateValue(timestamp, expectedValue, referenceChain);
return lastValue;
}
private Component_Type checkCreate(final CompilationTimeStamp timestamp) {
if (checkCreateTimestamp != null && !checkCreateTimestamp.isLess(timestamp)) {
return checkCreateCache;
}
checkCreateTimestamp = timestamp;
checkCreateCache = null;
final Assignment assignment = componentReference.getRefdAssignment(timestamp, true);
if (assignment == null) {
setIsErroneous(true);
return null;
}
if (!Assignment_type.A_TYPE.semanticallyEquals(assignment.getAssignmentType())) {
componentReference.getLocation().reportSemanticError(MessageFormat.format(COMPONENTEXPECTED, assignment.getDescription()));
setIsErroneous(true);
return null;
}
final IType type = ((Def_Type) assignment).getType(timestamp).getFieldType(timestamp, componentReference, 1,
Expected_Value_type.EXPECTED_DYNAMIC_VALUE, false);
if (type == null) {
setIsErroneous(true);
return null;
}
if (!Type_type.TYPE_COMPONENT.equals(type.getTypetype())) {
componentReference.getLocation().reportSemanticError(MessageFormat.format(TYPEMISMATCH1, type.getTypename()));
setIsErroneous(true);
return null;
}
if (myGovernor != null) {
final IType last = myGovernor.getTypeRefdLast(timestamp);
if (Type_type.TYPE_COMPONENT.equals(last.getTypetype()) && !last.isCompatible(timestamp, type, null, null, null)) {
componentReference.getLocation().reportSemanticError(
MessageFormat.format(TYPEMISMATCH2, last.getTypename(), type.getTypename()));
setIsErroneous(true);
return null;
}
}
checkCreateCache = (Component_Type) type;
return checkCreateCache;
}
@Override
/** {@inheritDoc} */
public void updateSyntax(final TTCN3ReparseUpdater reparser, final boolean isDamaged) throws ReParseException {
if (isDamaged) {
throw new ReParseException();
}
if (componentReference != null) {
componentReference.updateSyntax(reparser, false);
reparser.updateLocation(componentReference.getLocation());
}
if (name != null) {
name.updateSyntax(reparser, false);
reparser.updateLocation(name.getLocation());
}
if (location != null) {
location.updateSyntax(reparser, false);
reparser.updateLocation(location.getLocation());
}
}
@Override
/** {@inheritDoc} */
public void findReferences(final ReferenceFinder referenceFinder, final List<Hit> foundIdentifiers) {
if (componentReference != null) {
componentReference.findReferences(referenceFinder, foundIdentifiers);
}
if (name != null) {
name.findReferences(referenceFinder, foundIdentifiers);
}
if (location != null) {
location.findReferences(referenceFinder, foundIdentifiers);
}
}
@Override
/** {@inheritDoc} */
protected boolean memberAccept(final ASTVisitor v) {
if (componentReference != null && !componentReference.accept(v)) {
return false;
}
if (name != null && !name.accept(v)) {
return false;
}
if (location != null && !location.accept(v)) {
return false;
}
return true;
}
@Override
public String createStringRepresentation() {
// TODO Auto-generated method stub
return null;
}
}
......@@ -4730,7 +4730,7 @@ pr_ConfigurationOps returns[Value value]
);
pr_CreateOpEnd [Reference temporalReference]
returns [ComponentCreateExpression value]
returns [UndefCreateExpression value]
@init {
$value = null;
Token endcol = null;
......@@ -4763,7 +4763,7 @@ pr_CreateOpEnd [Reference temporalReference]
)?
)
{
$value = new ComponentCreateExpression($temporalReference, name, location, isAlive);
$value = new UndefCreateExpression($temporalReference, name, location, isAlive);
$value.setLocation( getLocation( $temporalReference.getLocation(), endcol ) );
}
;
......
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