reworked resolve method for expressions

parent 0e823454
......@@ -21,11 +21,14 @@
package de.monticore.lang.monticar.cnnarch;
import de.monticore.lang.monticar.cnnarch._symboltable.VariableSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.VariableType;
public class PredefinedVariables {
public static final String IF_NAME = "_if";
public static final String FOR_NAME = "_for";
public static final String TRUE_NAME = "true";
public static final String FALSE_NAME = "false";
public static VariableSymbol createIfParameter(){
return new VariableSymbol.Builder()
......@@ -42,5 +45,21 @@ public class PredefinedVariables {
.build();
}
//todo true and false
//necessary because true is currently only a name in MontiMath and it needs to be evaluated at compile time for this language
public static VariableSymbol createTrueConstant(){
return new VariableSymbol.Builder()
.name(TRUE_NAME)
.type(VariableType.CONSTANT)
.defaultValue(true)
.build();
}
//necessary because false is currently only a name in MontiMath and it needs to be evaluated at compile time for this language
public static VariableSymbol createFalseConstant() {
return new VariableSymbol.Builder()
.name(FALSE_NAME)
.type(VariableType.CONSTANT)
.defaultValue(false)
.build();
}
}
......@@ -26,6 +26,8 @@ import de.monticore.lang.monticar.cnnarch._symboltable.VariableSymbol;
public class CheckVariableConstraints implements CNNArchASTVariableCoCo {
//todo: make coco to check tuple elements (no tuple inside of tuple)
@Override
public void check(ASTVariable node) {
if (node == null || !node.getSymbol().isPresent()){
......@@ -34,7 +36,7 @@ public class CheckVariableConstraints implements CNNArchASTVariableCoCo {
VariableSymbol variable = (VariableSymbol) node.getSymbol().get();
for (Constraint constraint : variable.getConstraints()){
constraint.check(variable.getValueSymbol());
constraint.check(variable.getExpression());
}
}
}
......@@ -20,6 +20,7 @@
*/
package de.monticore.lang.monticar.cnnarch._symboltable;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
......@@ -34,10 +35,26 @@ abstract public class ArchAbstractSequenceExpression extends ArchExpressionSymbo
abstract public boolean isSerialSequence();
//todo no Optional
abstract public Optional<Integer> getParallelLength();
//todo no Optional
abstract public Optional<Integer> getSerialLength();
abstract public Optional<Integer> getMaxSerialLength();
@Override
public Optional<Object> getValue() {
if (isResolved()){
List<List<Object>> parallelValues = new ArrayList<>(getParallelLength().get());
for (List<ArchSimpleExpressionSymbol> serialElements : getElements().get()){
List<Object> serialValues = new ArrayList<>(getMaxSerialLength().get());
for (ArchSimpleExpressionSymbol element : serialElements){
serialValues.add(element.getValue().get());
}
parallelValues.add(serialValues);
}
return Optional.of(parallelValues);
}
else{
return Optional.empty();
}
}
}
......@@ -21,42 +21,44 @@
package de.monticore.lang.monticar.cnnarch._symboltable;
import de.monticore.symboltable.CommonSymbol;
import de.monticore.symboltable.Scope;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.*;
abstract public class ArchExpressionSymbol extends CommonSymbol {
public static final ArchExpressionKind KIND = new ArchExpressionKind();
private boolean fullyResolved = false;
private Set<String> unresolvableNames = null;
public ArchExpressionSymbol() {
super("", KIND);
}
/**
* Getter for the fullyResolved attribute.
* If it is still false for the return of resolve()
* then the value contains a dimension variable for input
* and output which has to be set to succesfully resolve thr expression.
*
* @return returns true iff the expression is resolved.
*/
public boolean isFullyResolved() {
return fullyResolved;
public Set<String> getUnresolvableNames() {
if (unresolvableNames == null){
checkIfResolvable();
}
return unresolvableNames;
}
//todo: change to isResolvable()
public boolean isResolvable(){
return getUnresolvableNames().isEmpty();
}
protected void setFullyResolved(boolean fullyResolved) {
this.fullyResolved = fullyResolved;
public void checkIfResolvable(){
if (isResolved()){
unresolvableNames = new HashSet<>();
}
else {
unresolvableNames = computeUnresolvableNames();
}
}
/**
* Checks whether the value is a boolean. If true getRhs() will return a Boolean if present.
* Checks whether the value is a boolean. If true getValue() will return a Boolean if present.
*
* @return returns true iff the value of the resolved expression will be a boolean.
*/
......@@ -66,7 +68,7 @@ abstract public class ArchExpressionSymbol extends CommonSymbol {
/**
* Checks whether the value is a number.
* Note that the return of getRhs() can be either a Double or an Integer if present.
* Note that the return of getValue() can be either a Double or an Integer if present.
*
* @return returns true iff the value of the resolved expression will be a number.
*/
......@@ -76,7 +78,7 @@ abstract public class ArchExpressionSymbol extends CommonSymbol {
/**
* Checks whether the value is a Tuple.
* If true getRhs() will return (if present) a List of Objects.
* If true getValue() will return (if present) a List of Objects.
* These Objects can either be Integer, Double or Boolean.
*
* @return returns true iff the value of the expression will be a tuple.
......@@ -86,14 +88,38 @@ abstract public class ArchExpressionSymbol extends CommonSymbol {
}
/**
* Checks whether the value is an integer. This can only be checked if the expression is resolvable.
* Checks whether the value is an integer. This can only be checked if the expression is resolved.
* If true getRhs() will return an Integer.
*
* @return returns Optional.of(true) iff the value of the expression is an integer.
* The Optional is present if the expression can be resolved.
* @return returns true iff the value of the expression is an integer.
* The Optional is present if the expression was resolved.
*/
public Optional<Boolean> isInt(){
return Optional.of(false);
if (getValue().isPresent()){
return Optional.of(getIntValue().isPresent());
}
return Optional.empty();
}
public Optional<Boolean> isIntTuple(){
if (getValue().isPresent()){
return Optional.of(getIntTupleValue().isPresent());
}
return Optional.empty();
}
public Optional<Boolean> isNumberTuple(){
if (getValue().isPresent()){
return Optional.of(getDoubleTupleValue().isPresent());
}
return Optional.empty();
}
public Optional<Boolean> isBooleanTuple(){
if (getValue().isPresent()){
return Optional.of(getBooleanTupleValue().isPresent());
}
return Optional.empty();
}
/**
......@@ -139,72 +165,133 @@ abstract public class ArchExpressionSymbol extends CommonSymbol {
return false;
}
public Optional<Integer> getIntValue(){
Optional<Object> optValue = getValue();
if (optValue.isPresent() && (optValue.get() instanceof Integer)){
return Optional.of((Integer) optValue.get());
}
return Optional.empty();
}
public Optional<Double> getDoubleValue(){
Optional<Object> optValue = getValue();
if (optValue.isPresent()){
if (optValue.get() instanceof Double){
return Optional.of((Double) optValue.get());
}
if (optValue.get() instanceof Integer){
return Optional.of(((Integer) optValue.get()).doubleValue());
}
}
return Optional.empty();
}
/**
* This method returns the result of the expression.
* This can be a primitive object (Integer, Double or Boolean)
* or a list of lists of primitive objects. (See other methods for more information)
*
* @return returns the value as Object or Optional.empty if the expression cannot be completely resolved yet.
*
*/
abstract public Optional<Object> getValue();
/**
* Replaces all variable names in this values expression.
* If the expression contains an IOVariable which has not yet been set
* then the expression is resolved as much as possible and the attribute fullyResolved of this object remains false.
*
* @return returns a set of all names which could not be resolved.
*/
abstract public Set<String> resolve();
//todo remove
abstract protected void checkIfResolved();
abstract public boolean isResolved();
public Optional<Boolean> getBooleanValue(){
Optional<Object> optValue = getValue();
if (optValue.isPresent() && (optValue.get() instanceof Boolean)){
return Optional.of((Boolean) optValue.get());
}
return Optional.empty();
}
abstract public List<List<ArchSimpleExpressionSymbol>> getElements();
public Optional<List<Integer>> getIntTupleValue(){
Optional<List<Object>> optValue = getTupleValue();
if (optValue.isPresent()){
List<Integer> list = new ArrayList<>();
for (Object value : optValue.get()) {
if (value instanceof Integer){
list.add((Integer) value);
}
else {
return Optional.empty();
}
}
return Optional.of(list);
}
return Optional.empty();
}
public void resolveOrError(){
resolve();
if (isResolved()){
throw new IllegalStateException("The following names could not be resolved: " + getUnresolvableNames());
public Optional<List<Double>> getDoubleTupleValue() {
Optional<List<Object>> optValue = getTupleValue();
if (optValue.isPresent()){
List<Double> list = new ArrayList<>();
for (Object value : optValue.get()) {
if (value instanceof Double) {
list.add((Double) value);
}
else if (value instanceof Integer){
list.add(((Integer) value).doubleValue());
}
else {
return Optional.empty();
}
}
return Optional.of(list);
}
return Optional.empty();
}
public boolean isResolvable(){
//todo
return true;
public Optional<List<Boolean>> getBooleanTupleValue() {
Optional<List<Object>> optValue = getTupleValue();
if (optValue.isPresent()){
List<Boolean> list = new ArrayList<>();
for (Object value : optValue.get()) {
if (value instanceof Boolean) {
list.add((Boolean) value);
}
else {
return Optional.empty();
}
}
return Optional.of(list);
}
return Optional.empty();
}
public Set<String> getUnresolvableNames() {
//todo
return null;
public Optional<List<Object>> getTupleValue(){
if (getValue().isPresent()){
if (isTuple()){
@SuppressWarnings("unchecked")
List<Object> list = (List<Object>) getValue().get();
return Optional.of(list);
}
}
return Optional.empty();
}
public void checkIfResolvable(){
//todo: unresolvableNames = computeUnresolvableNames();
/**
* Same as resolve() but throws an error if it was not successful.
*/
public void resolveOrError(Scope resolvingScope){
resolve(resolvingScope);
if (!isResolved()){
throw new IllegalStateException("The following names could not be resolved: " + getUnresolvableNames());
}
}
/**
* This method returns the result of the expression if it is already resolved.
* This can be a primitive object (Integer, Double or Boolean)
* or a list of primitive objects if it is a tuple
* or a list of lists of primitive objects if it is a sequence. (See other methods for more information)
*
* @return returns the value as Object or Optional.empty if the expression is not resolved.
*
*/
abstract public Optional<Object> getValue();
protected Set<String> computeUnresolvableNames(){
//todo
return null;
}
/**
* Replaces all variable names in this values expression if possible.
* The values of the variables depend on the current scope. The replacement is irreversible if successful.
*
* @return returns a set of all names which could not be resolved.
*/
abstract public Set<String> resolve(Scope resolvingScope);
public boolean isIntTuple(){
return false;
}
abstract public Optional<List<List<ArchSimpleExpressionSymbol>>> getElements();
public boolean isNumberTuple(){
return false;
}
abstract protected Set<String> computeUnresolvableNames();
public boolean isBooleanTuple(){
return false;
}
abstract public boolean isResolved();
}
......@@ -20,6 +20,8 @@
*/
package de.monticore.lang.monticar.cnnarch._symboltable;
import de.monticore.symboltable.Scope;
import java.util.*;
public class ArchRangeExpressionSymbol extends ArchAbstractSequenceExpression {
......@@ -27,6 +29,7 @@ public class ArchRangeExpressionSymbol extends ArchAbstractSequenceExpression {
private ArchSimpleExpressionSymbol startSymbol;
private ArchSimpleExpressionSymbol endSymbol;
private boolean parallel;
private List<List<ArchSimpleExpressionSymbol>> elements = null;
public ArchRangeExpressionSymbol() {
......@@ -69,7 +72,7 @@ public class ArchRangeExpressionSymbol extends ArchAbstractSequenceExpression {
private Optional<Integer> getLength(){
Optional<Integer> optLength = Optional.empty();
if (isFullyResolved()) {
if (isResolved()){
Object startValue = getEndSymbol().getValue().get();
Object endValue = getEndSymbol().getValue().get();
if (startValue instanceof Integer && endValue instanceof Integer) {
......@@ -92,7 +95,7 @@ public class ArchRangeExpressionSymbol extends ArchAbstractSequenceExpression {
}
@Override
public Optional<Integer> getSerialLength() {
public Optional<Integer> getMaxSerialLength() {
if (isSerialSequence()) {
return getLength();
}
......@@ -102,70 +105,61 @@ public class ArchRangeExpressionSymbol extends ArchAbstractSequenceExpression {
}
@Override
public Optional<Object> getValue() {
if (isFullyResolved()){
//todo check in CoCo: startSymbol.isInt() && endSymbol.isInt()
int startInt = (Integer) startSymbol.getValue().get();
int endInt = (Integer) endSymbol.getValue().get();
int step = 1;
if (endInt < startInt){
step = -1;
}
List<List<Integer>> valueLists = new ArrayList<>();
public Set<String> resolve(Scope resolvingScope) {
if (!isResolved()){
checkIfResolvable();
if (isResolvable()){
if (isParallel()){
for (int i = startInt; i <= endInt; i = i + step){
List<Integer> values = new ArrayList<>(1);
values.add(i);
valueLists.add(values);
}
getStartSymbol().resolveOrError(resolvingScope);
getEndSymbol().resolveOrError(resolvingScope);
}
else {
List<Integer> values = new ArrayList<>();
for (int i = startInt; i <= endInt; i = i + step){
values.add(i);
}
valueLists.add(values);
}
return Optional.of(valueLists);
}
else {
return Optional.empty();
}
return getUnresolvableNames();
}
@Override
public Set<String> resolve() {
Set<String> unresolvableSet = new HashSet<>();
if (!isFullyResolved()){
unresolvableSet.addAll(startSymbol.resolve());
unresolvableSet.addAll(endSymbol.resolve());
if (unresolvableSet.isEmpty()) {
setFullyResolved(true);
}
}
return unresolvableSet;
public boolean isResolved() {
return getStartSymbol().isResolved() && getEndSymbol().isResolved();
}
@Override
protected void checkIfResolved() {
startSymbol.checkIfResolved();
endSymbol.checkIfResolved();
setFullyResolved(startSymbol.isFullyResolved() && endSymbol.isFullyResolved());
}
public Optional<List<List<ArchSimpleExpressionSymbol>>> getElements() {
if (elements == null){
if (isResolved()){
int start = startSymbol.getIntValue().get();
int end = endSymbol.getIntValue().get();
int step = 1;
if (end < start){
step = -1;
}
@Override
public boolean isResolved() {
//todo
return false;
List<List<ArchSimpleExpressionSymbol>> elementList = new ArrayList<>(getParallelLength().get());
if (isParallel()){
for (int i = start; i <= end; i = i + step){
List<ArchSimpleExpressionSymbol> values = new ArrayList<>(1);
values.add(ArchSimpleExpressionSymbol.of(i));
elementList.add(values);
}
}
else {
List<ArchSimpleExpressionSymbol> values = new ArrayList<>(getMaxSerialLength().get());
for (int i = start; i <= end; i = i + step){
values.add(ArchSimpleExpressionSymbol.of(i));
}
elementList.add(values);
}
this.elements = elementList;
}
}
return Optional.ofNullable(elements);
}
@Override
public List<List<ArchSimpleExpressionSymbol>> getElements() {
//todo
return null;
protected Set<String> computeUnresolvableNames() {
Set<String> unresolvableNames = new HashSet<>();
unresolvableNames.addAll(getStartSymbol().computeUnresolvableNames());
unresolvableNames.addAll(getEndSymbol().computeUnresolvableNames());
return unresolvableNames;
}
}
......@@ -20,6 +20,8 @@
*/
package de.monticore.lang.monticar.cnnarch._symboltable;
import de.monticore.symboltable.Scope;
import java.util.*;
public class ArchSequenceExpressionSymbol extends ArchAbstractSequenceExpression {
......@@ -31,7 +33,12 @@ public class ArchSequenceExpressionSymbol extends ArchAbstractSequenceExpression
}
public List<List<ArchSimpleExpressionSymbol>> getElements() {
@Override
public Optional<List<List<ArchSimpleExpressionSymbol>>> getElements() {
return Optional.of(_getElements());