From ffb2cb067d7b219890a039ab1ec52d5de11c9c75 Mon Sep 17 00:00:00 2001
From: MarkBeB <177214717+MarkBeB@users.noreply.github.com>
Date: Fri, 14 Aug 2026 12:43:44 +0200
Subject: [PATCH 1/9] Add lower/upper bounds to gipsl variables
---
.../model/generated/Gipsl.ecore | 10 ++++++++++
.../model/generated/Gipsl.genmodel | 9 ++++++++-
.../src/org/emoflon/gips/gipsl/Gipsl.xtext | 16 ++++++++++++++--
.../gips/gipsl/formatting2/GipslFormatter.xtend | 15 +++++++++++----
4 files changed, 43 insertions(+), 7 deletions(-)
diff --git a/org.emoflon.gips.gipsl/model/generated/Gipsl.ecore b/org.emoflon.gips.gipsl/model/generated/Gipsl.ecore
index 85576dda..520e9abd 100644
--- a/org.emoflon.gips.gipsl/model/generated/Gipsl.ecore
+++ b/org.emoflon.gips.gipsl/model/generated/Gipsl.ecore
@@ -64,6 +64,8 @@
+
@@ -83,6 +85,14 @@
+
+
+
+
+
+
@@ -126,6 +126,7 @@
+
@@ -143,6 +144,12 @@
+
+
+
+
+
+
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/Gipsl.xtext b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/Gipsl.xtext
index d809c29d..bce24ceb 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/Gipsl.xtext
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/Gipsl.xtext
@@ -64,7 +64,9 @@ GipsMapping :
;
GipsMappingVariable :
- 'var' name=ID ':' type=[ecore::EDataType] (bound ?= 'bind' parameter=[GT::EditorParameter])?
+ 'var' name=ID ':' type=[ecore::EDataType]
+ (interval=GipsInterval)?
+ (bound ?= 'bind' parameter=[GT::EditorParameter])?
;
GipsTypeExtension :
@@ -74,7 +76,17 @@ GipsTypeExtension :
;
GipsTypeExtensionVariable :
- 'var' name=ID ':' type=[ecore::EDataType] (bound ?= 'bind' 'to' attribute=[ecore::EAttribute])?
+ 'var' name=ID ':' type=[ecore::EDataType]
+ (interval=GipsInterval)?
+ (bound ?= 'bind' 'to' attribute=[ecore::EAttribute])?
+;
+
+GipsInterval:
+ '['
+ ( (lowerBound=GipsArithmeticLiteral) | lowerInfinity?='*' )
+ ','
+ ( (upperBound=GipsArithmeticLiteral) | upperInfinity?='*' )
+ ']'
;
GipsConstant:
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/formatting2/GipslFormatter.xtend b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/formatting2/GipslFormatter.xtend
index 562cc0c9..ad418fcb 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/formatting2/GipslFormatter.xtend
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/formatting2/GipslFormatter.xtend
@@ -80,6 +80,7 @@ import org.emoflon.ibex.gt.editor.gT.EditorAttributeAssignment
import static org.emoflon.gips.gipsl.gipsl.GipslPackage.Literals.*
import org.emoflon.gips.gipsl.gipsl.GipsTypeExtension
import org.emoflon.gips.gipsl.gipsl.GipsTypeExtensionVariable
+import org.emoflon.gips.gipsl.gipsl.GipsInterval
class GipslFormatter extends GTFormatter implements IFormatter2 {
@@ -214,7 +215,7 @@ class GipslFormatter extends GTFormatter implements IFormatter2 {
def dispatch void format(GipsMappingVariable gipsMappingVariable, extension IFormattableDocument document) {
gipsMappingVariable.regionFor.keyword(gipsMappingVariableAccess.varKeyword_0).append[oneSpace]
gipsMappingVariable.regionFor.keyword(gipsMappingVariableAccess.colonKeyword_2).surround[oneSpace]
- gipsMappingVariable.regionFor.keyword(gipsMappingVariableAccess.boundBindKeyword_4_0_0).surround[oneSpace]
+ gipsMappingVariable.regionFor.keyword(gipsMappingVariableAccess.boundBindKeyword_5_0_0).surround[oneSpace]
gipsMappingVariable.formatChilds(document)
}
@@ -237,11 +238,17 @@ class GipslFormatter extends GTFormatter implements IFormatter2 {
def dispatch void format(GipsTypeExtensionVariable gipsTypeExtensionVariable, extension IFormattableDocument document) {
gipsTypeExtensionVariable.regionFor.keyword(gipsTypeExtensionVariableAccess.varKeyword_0).append[oneSpace]
gipsTypeExtensionVariable.regionFor.keyword(gipsTypeExtensionVariableAccess.colonKeyword_2).surround[oneSpace]
- gipsTypeExtensionVariable.regionFor.keyword(gipsTypeExtensionVariableAccess.boundBindKeyword_4_0_0).surround[oneSpace]
- gipsTypeExtensionVariable.regionFor.keyword(gipsTypeExtensionVariableAccess.toKeyword_4_1).append[oneSpace]
-
+ gipsTypeExtensionVariable.interval.prepend[oneSpace]
+ gipsTypeExtensionVariable.regionFor.keyword(gipsTypeExtensionVariableAccess.boundBindKeyword_5_0_0).surround[oneSpace]
+ gipsTypeExtensionVariable.regionFor.keyword(gipsTypeExtensionVariableAccess.toKeyword_5_1).append[oneSpace]
gipsTypeExtensionVariable.formatChilds(document)
}
+
+ def dispatch void format(GipsInterval gipsInterval, extension IFormattableDocument document) {
+ gipsInterval.regionFor.keyword(gipsIntervalAccess.leftSquareBracketKeyword_0).append[noSpace]
+ gipsInterval.regionFor.keyword(gipsIntervalAccess.commaKeyword_2).prepend[noSpace].append[oneSpace]
+ gipsInterval.regionFor.keyword(gipsIntervalAccess.rightSquareBracketKeyword_4).prepend[noSpace]
+ }
def dispatch void format(GipsConstant gipsConstant, extension IFormattableDocument document) {
gipsConstant.regionFor.keyword(gipsConstantAccess.letKeyword_0).append[oneSpace]
From 25f6a84754bc98856c0277e650739c7bbea8af7e Mon Sep 17 00:00:00 2001
From: MarkBeB <177214717+MarkBeB@users.noreply.github.com>
Date: Tue, 18 Aug 2026 10:51:18 +0200
Subject: [PATCH 2/9] Add upper/lower bounds to variables
---
.../preprocess/RuleBinaryValueNegation.java | 6 +-
.../preprocess/RuleEquivalenceShortcutA.java | 7 +--
.../preprocess/RuleEquivalenceShortcutB.java | 5 +-
.../preprocess/RuleEquivalenceShortcutC.java | 3 +-
.../preprocess/RuleEquivalenceShortcutD.java | 6 +-
.../preprocess/RuleImplicitBooleans.java | 2 +-
.../helper/GipsTransformationUtils.java | 27 ++++++++-
.../ArithmeticExpressionTransformer.java | 32 +++++-----
.../model/generated/Gipsl.ecore | 10 +++-
.../model/generated/Gipsl.genmodel | 10 +++-
.../src/org/emoflon/gips/gipsl/Gipsl.xtext | 6 +-
.../gips/gipsl/generator/GeneratorUtil.java | 12 +++-
.../special/pattern/BinaryValueNegation.java | 8 +--
.../special/pattern/EquivalenceShortcutA.java | 4 +-
.../special/pattern/EquivalenceShortcutB.java | 2 +-
.../special/pattern/EquivalenceShortcutC.java | 2 +-
.../special/pattern/EquivalenceShortcutD.java | 17 +++---
.../special/pattern/ImplicationShortcutA.java | 2 +-
.../pattern/ValueConstantRelation.java | 16 ++---
.../validation/GipslMappingValidator.java | 11 ++++
.../gips/gipsl/validation/GipslValidator.java | 58 ++++++++++++++++---
.../gipsl/validation/GipslValidatorUtil.java | 3 +
22 files changed, 169 insertions(+), 80 deletions(-)
diff --git a/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleBinaryValueNegation.java b/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleBinaryValueNegation.java
index 9ae27b09..c89d2d01 100644
--- a/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleBinaryValueNegation.java
+++ b/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleBinaryValueNegation.java
@@ -20,10 +20,10 @@ public GipsBooleanExpression tryRule(GipslFactory factory, GipsBooleanExpression
relational.setOperator(RelationalOperator.EQUAL);
relational.setLeft(EcoreUtil.copy(pattern.getNodeA()));
- if (pattern.getLiteral().getValue().equals("1")) {
- relational.setRight(GeneratorUtil.createArithmeticLiteral(factory, "0"));
+ if (pattern.getLiteral().getValue() == 1) {
+ relational.setRight(GeneratorUtil.createIntegerLiteral(factory, 0));
} else {
- relational.setRight(GeneratorUtil.createArithmeticLiteral(factory, "1"));
+ relational.setRight(GeneratorUtil.createIntegerLiteral(factory, 1));
}
return relational;
diff --git a/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutA.java b/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutA.java
index b0e7aebc..cab8a9f9 100644
--- a/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutA.java
+++ b/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutA.java
@@ -63,8 +63,8 @@ public GipsBooleanExpression tryRule(GipslFactory factory, GipsBooleanExpression
for (var element : pattern.getOtherNodes())
summands.add(EcoreUtil.copy(element));
- var minusN = factory.createGipsArithmeticLiteral();
- minusN.setValue(Integer.toString(1 - pattern.getOtherNodes().size()));
+ var minusN = factory.createGipsIntegerLiteral();
+ minusN.setValue(1 - pattern.getOtherNodes().size());
summands.add(minusN);
// B + C + ... + (1-n)
@@ -81,8 +81,7 @@ public GipsBooleanExpression tryRule(GipslFactory factory, GipsBooleanExpression
// A <= B*M
// ...
for (var element : pattern.getOtherNodes()) {
- var bigM = GeneratorUtil.createArithmeticLiteral(factory,
- Double.toString(PluginPreferences.getBigMValue()));
+ var bigM = GeneratorUtil.createDoubleLiteral(factory, PluginPreferences.getBigMValue());
var bigMProduct = factory.createGipsArithmeticProduct();
bigMProduct.setOperator(GipsProductOperator.MULT);
diff --git a/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutB.java b/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutB.java
index b6c99e36..3425c880 100644
--- a/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutB.java
+++ b/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutB.java
@@ -70,8 +70,7 @@ public GipsBooleanExpression tryRule(GipslFactory factory, GipsBooleanExpression
for (var element : pattern.getOtherNodes())
summands.add(EcoreUtil.copy(element));
- var minusN = factory.createGipsArithmeticLiteral();
- minusN.setValue(Integer.toString(1 - pattern.getOtherNodes().size()));
+ var minusN = GeneratorUtil.createIntegerLiteral(factory, 1 - pattern.getOtherNodes().size());
summands.add(minusN);
// B + C + ... + (1-n)
@@ -95,7 +94,7 @@ public GipsBooleanExpression tryRule(GipslFactory factory, GipsBooleanExpression
var sum = GeneratorUtil.sum(factory, GipsSumOperator.PLUS, summands);
// n
- var n = GeneratorUtil.createArithmeticLiteral(factory, Double.toString(summands.size()));
+ var n = GeneratorUtil.createIntegerLiteral(factory, summands.size());
// n * A
var nProduct = factory.createGipsArithmeticProduct();
diff --git a/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutC.java b/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutC.java
index 63a7e6f6..1c1ba9f4 100644
--- a/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutC.java
+++ b/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutC.java
@@ -57,8 +57,7 @@ public GipsBooleanExpression tryRule(GipslFactory factory, GipsBooleanExpression
var product = factory.createGipsArithmeticProduct();
product.setOperator(GipsProductOperator.MULT);
product.setLeft(EcoreUtil.copy(pattern.getNodeA()));
- product.setRight(
- GeneratorUtil.createArithmeticLiteral(factory, Integer.toString(pattern.getOtherNodes().size())));
+ product.setRight(GeneratorUtil.createIntegerLiteral(factory, pattern.getOtherNodes().size()));
// B + C (+ D + ...) <= A*n
var conjunctTwo = factory.createGipsRelationalExpression();
diff --git a/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutD.java b/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutD.java
index 4f9013f5..138c031d 100644
--- a/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutD.java
+++ b/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleEquivalenceShortcutD.java
@@ -1,7 +1,5 @@
package org.emoflon.gips.build.gipsl.preprocess;
-import static org.emoflon.gips.gipsl.generator.GeneratorUtil.createArithmeticLiteral;
-
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.emoflon.gips.build.preference.PluginPreferences;
import org.emoflon.gips.gipsl.generator.GeneratorUtil;
@@ -41,7 +39,7 @@ public GipsBooleanExpression tryRule(GipslFactory factory, GipsBooleanExpression
if (!pattern.matchPattern(expression))
return null;
- var one = createArithmeticLiteral(factory, "1");
+ var one = GeneratorUtil.createIntegerLiteral(factory, 1);
// 1-B
var oneMinusB = factory.createGipsArithmeticSum();
@@ -55,7 +53,7 @@ public GipsBooleanExpression tryRule(GipslFactory factory, GipsBooleanExpression
conjunctOne.setLeft(EcoreUtil.copy(oneMinusB));
conjunctOne.setRight(EcoreUtil.copy(pattern.getNodeA()));
- var bigM = createArithmeticLiteral(factory, Double.toString(PluginPreferences.getBigMValue()));
+ var bigM = GeneratorUtil.createDoubleLiteral(factory, PluginPreferences.getBigMValue());
// (1-B)*M
var bigMProduct = factory.createGipsArithmeticProduct();
diff --git a/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleImplicitBooleans.java b/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleImplicitBooleans.java
index 5787244a..df388a3e 100644
--- a/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleImplicitBooleans.java
+++ b/org.emoflon.gips.build/src/org/emoflon/gips/build/gipsl/preprocess/RuleImplicitBooleans.java
@@ -19,7 +19,7 @@ public GipsBooleanExpression tryRule(GipslFactory factory, GipsBooleanExpression
var relational = factory.createGipsRelationalExpression();
relational.setOperator(RelationalOperator.EQUAL);
relational.setLeft(EcoreUtil.copy(pattern.getNodeA()));
- relational.setRight(GeneratorUtil.createArithmeticLiteral(factory, "1"));
+ relational.setRight(GeneratorUtil.createIntegerLiteral(factory, 1));
// if (expression.eContainer() instanceof GipsBooleanNegation) {
// var brackets = factory.createGipsBooleanBracket();
diff --git a/org.emoflon.gips.build/src/org/emoflon/gips/build/transformation/helper/GipsTransformationUtils.java b/org.emoflon.gips.build/src/org/emoflon/gips/build/transformation/helper/GipsTransformationUtils.java
index ade49c7d..3474f965 100644
--- a/org.emoflon.gips.build/src/org/emoflon/gips/build/transformation/helper/GipsTransformationUtils.java
+++ b/org.emoflon.gips.build/src/org/emoflon/gips/build/transformation/helper/GipsTransformationUtils.java
@@ -6,6 +6,9 @@
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EcorePackage;
+import org.emoflon.gips.gipsl.gipsl.GipsArithmeticLiteral;
+import org.emoflon.gips.gipsl.gipsl.GipsDoubleLiteral;
+import org.emoflon.gips.gipsl.gipsl.GipsIntegerLiteral;
import org.emoflon.gips.gipsl.gipsl.GipsVariable;
import org.emoflon.gips.intermediate.GipsIntermediate.ArithmeticBinaryExpression;
import org.emoflon.gips.intermediate.GipsIntermediate.ArithmeticExpression;
@@ -310,29 +313,49 @@ public static Set extractConstantReference(final RelationalEx
}
public static double getUpperBound(final GipsVariable gipsVar, final VariableType type) {
- if (type == VariableType.BINARY) {
+ if (type == VariableType.BINARY)
return 1;
+
+ if (gipsVar.getInterval() != null && !gipsVar.getInterval().isUpperInfinity()) {
+ return getValue(gipsVar.getInterval().getUpperBound());
+
} else if (type == VariableType.INTEGER) {
return Integer.MAX_VALUE;
+
} else if (type == VariableType.REAL) {
return Double.MAX_VALUE;
+
}
throw new UnsupportedOperationException();
}
public static double getLowerBound(final GipsVariable gipsVar, final VariableType type) {
- if (type == VariableType.BINARY) {
+ if (type == VariableType.BINARY)
return 0;
+
+ if (gipsVar.getInterval() != null && !gipsVar.getInterval().isLowerInfinity()) {
+ return getValue(gipsVar.getInterval().getLowerBound());
+
} else if (type == VariableType.INTEGER) {
return Integer.MIN_VALUE;
+
} else if (type == VariableType.REAL) {
return -Double.MAX_VALUE;
+
}
throw new UnsupportedOperationException();
}
+ private static double getValue(final GipsArithmeticLiteral literal) {
+ return switch (literal) {
+ case GipsIntegerLiteral val -> val.getValue();
+ case GipsDoubleLiteral val -> val.getValue();
+ default -> throw new IllegalArgumentException("Unexpected value: " + literal);
+ };
+ }
+
public static ExpressionReturnType extractReturnType(BooleanExpression expression) {
return ExpressionReturnTypeResolver.extractReturnType(expression);
}
diff --git a/org.emoflon.gips.build/src/org/emoflon/gips/build/transformation/transformer/ArithmeticExpressionTransformer.java b/org.emoflon.gips.build/src/org/emoflon/gips/build/transformation/transformer/ArithmeticExpressionTransformer.java
index 51ab5418..69c7542c 100644
--- a/org.emoflon.gips.build/src/org/emoflon/gips/build/transformation/transformer/ArithmeticExpressionTransformer.java
+++ b/org.emoflon.gips.build/src/org/emoflon/gips/build/transformation/transformer/ArithmeticExpressionTransformer.java
@@ -16,6 +16,8 @@
import org.emoflon.gips.gipsl.gipsl.GipsArithmeticUnary;
import org.emoflon.gips.gipsl.gipsl.GipsConstantReference;
import org.emoflon.gips.gipsl.gipsl.GipsConstraint;
+import org.emoflon.gips.gipsl.gipsl.GipsDoubleLiteral;
+import org.emoflon.gips.gipsl.gipsl.GipsIntegerLiteral;
import org.emoflon.gips.gipsl.gipsl.GipsLinearFunction;
import org.emoflon.gips.gipsl.gipsl.GipsLinearFunctionReference;
import org.emoflon.gips.gipsl.gipsl.GipsObjective;
@@ -162,22 +164,20 @@ public ArithmeticExpression transform(final GipsArithmeticBracket bracket) throw
}
public ArithmeticExpression transform(final GipsArithmeticLiteral literal) throws Exception {
- try {
- int value = Integer.parseInt(literal.getValue());
- IntegerLiteral intLit = factory.createIntegerLiteral();
- intLit.setLiteral(value);
- return intLit;
- } catch (Exception e) {
- try {
- double dValue = Double.parseDouble(literal.getValue());
- DoubleLiteral doubleLit = factory.createDoubleLiteral();
- doubleLit.setLiteral(dValue);
- return doubleLit;
- } catch (Exception e2) {
- throw new IllegalArgumentException(
- "Value <" + literal.getValue() + "> can't be parsed to neither integer nor double value.");
- }
- }
+ return switch (literal) {
+ case GipsIntegerLiteral value -> {
+ IntegerLiteral lit = factory.createIntegerLiteral();
+ lit.setLiteral(value.getValue());
+ yield lit;
+ }
+ case GipsDoubleLiteral value -> {
+ DoubleLiteral lit = factory.createDoubleLiteral();
+ lit.setLiteral(value.getValue());
+ yield lit;
+ }
+ default -> throw new IllegalArgumentException(
+ "Value <" + literal + "> can't be parsed to neither integer nor double value.");
+ };
}
public ArithmeticExpression transform(final GipsArithmeticConstant constant) throws Exception {
diff --git a/org.emoflon.gips.gipsl/model/generated/Gipsl.ecore b/org.emoflon.gips.gipsl/model/generated/Gipsl.ecore
index 520e9abd..ca471031 100644
--- a/org.emoflon.gips.gipsl/model/generated/Gipsl.ecore
+++ b/org.emoflon.gips.gipsl/model/generated/Gipsl.ecore
@@ -160,9 +160,7 @@
-
-
-
+
@@ -325,6 +323,12 @@
+
+
+
+
+
+
diff --git a/org.emoflon.gips.gipsl/model/generated/Gipsl.genmodel b/org.emoflon.gips.gipsl/model/generated/Gipsl.genmodel
index 282ba4bb..053ae1f2 100644
--- a/org.emoflon.gips.gipsl/model/generated/Gipsl.genmodel
+++ b/org.emoflon.gips.gipsl/model/generated/Gipsl.genmodel
@@ -184,9 +184,7 @@
-
-
-
+
@@ -289,6 +287,12 @@
+
+
+
+
+
+
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/Gipsl.xtext b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/Gipsl.xtext
index bce24ceb..203920bc 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/Gipsl.xtext
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/Gipsl.xtext
@@ -214,7 +214,7 @@ GipsArithmeticOperand:
;
GipsArithmeticLiteral:
- value = (GipsDoubleLiteral | GipsIntegerLiteral)
+ GipsDoubleLiteral | GipsIntegerLiteral
;
GipsArithmeticConstant:
@@ -450,11 +450,11 @@ enum QueryOperator :
;
GipsDoubleLiteral:
- GipsDouble
+ value = GipsDouble
;
GipsIntegerLiteral:
- GipsInteger
+ value = GipsInteger
;
GipsDouble returns ecore::EDouble:
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/generator/GeneratorUtil.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/generator/GeneratorUtil.java
index fc79b75b..e45269f0 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/generator/GeneratorUtil.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/generator/GeneratorUtil.java
@@ -10,6 +10,8 @@
import org.emoflon.gips.gipsl.gipsl.GipsBooleanConjunction;
import org.emoflon.gips.gipsl.gipsl.GipsBooleanDisjunction;
import org.emoflon.gips.gipsl.gipsl.GipsBooleanExpression;
+import org.emoflon.gips.gipsl.gipsl.GipsDoubleLiteral;
+import org.emoflon.gips.gipsl.gipsl.GipsIntegerLiteral;
import org.emoflon.gips.gipsl.gipsl.GipsSumOperator;
import org.emoflon.gips.gipsl.gipsl.GipslFactory;
@@ -18,8 +20,14 @@ private GeneratorUtil() {
}
- public static GipsArithmeticLiteral createArithmeticLiteral(GipslFactory factory, String value) {
- GipsArithmeticLiteral literal = factory.createGipsArithmeticLiteral();
+ public static GipsArithmeticLiteral createIntegerLiteral(GipslFactory factory, int value) {
+ GipsIntegerLiteral literal = factory.createGipsIntegerLiteral();
+ literal.setValue(value);
+ return literal;
+ }
+
+ public static GipsArithmeticLiteral createDoubleLiteral(GipslFactory factory, double value) {
+ GipsDoubleLiteral literal = factory.createGipsDoubleLiteral();
literal.setValue(value);
return literal;
}
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/BinaryValueNegation.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/BinaryValueNegation.java
index cef8293a..09ac872b 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/BinaryValueNegation.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/BinaryValueNegation.java
@@ -3,9 +3,9 @@
import java.util.Arrays;
import java.util.Collection;
-import org.emoflon.gips.gipsl.gipsl.GipsArithmeticLiteral;
import org.emoflon.gips.gipsl.gipsl.GipsBooleanExpression;
import org.emoflon.gips.gipsl.gipsl.GipsBooleanNegation;
+import org.emoflon.gips.gipsl.gipsl.GipsIntegerLiteral;
import org.emoflon.gips.gipsl.gipsl.GipsRelationalExpression;
import org.emoflon.gips.gipsl.gipsl.GipsValueExpression;
import org.emoflon.gips.gipsl.gipsl.RelationalOperator;
@@ -34,7 +34,7 @@ public class BinaryValueNegation extends AbstractPatternMatcher {
RelationalOperator.EQUAL, //
this::matchLiteral);
- public GipsArithmeticLiteral getLiteral() {
+ public GipsIntegerLiteral getLiteral() {
return pattern.getLiteral();
}
@@ -68,8 +68,8 @@ protected void tryMatchPattern(GipsBooleanExpression expression) {
}
- private boolean matchLiteral(String literal) {
- return "1".equals(literal) || "0".equals(literal);
+ private boolean matchLiteral(Integer literal) {
+ return 1 == literal || 0 == literal;
}
private void matchNodes(GipsRelationalExpression expression) {
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutA.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutA.java
index 8661b9a9..1ac0fdff 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutA.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutA.java
@@ -32,12 +32,12 @@ public class EquivalenceShortcutA extends AbstractPatternMatcher {
private final ValueConstantRelation isGreaterEqualPair = new ValueConstantRelation( //
false, //
RelationalOperator.GREATER_OR_EQUAL, //
- c -> "1".equals(c));
+ c -> 1 == c);
private final ValueConstantRelation isEqualPair = new ValueConstantRelation( //
false, //
RelationalOperator.EQUAL, //
- c -> "1".equals(c));
+ c -> 1 == c);
private final ImplicitBoolean isImplicitBool = new ImplicitBoolean();
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutB.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutB.java
index b2ea0aab..0227453b 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutB.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutB.java
@@ -32,7 +32,7 @@ public class EquivalenceShortcutB extends AbstractPatternMatcher {
private final ValueConstantRelation isRelationalPair = new ValueConstantRelation( //
false, //
RelationalOperator.EQUAL, //
- c -> "1".equals(c));
+ c -> 1 == c);
public GipsArithmeticExpression getNodeA() {
return nodeA;
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutC.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutC.java
index e51b56ea..86016a05 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutC.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutC.java
@@ -32,7 +32,7 @@ public class EquivalenceShortcutC extends AbstractPatternMatcher {
private final ValueConstantRelation isRelationalPair = new ValueConstantRelation( //
false, //
RelationalOperator.EQUAL, //
- c -> "1".equals(c));
+ c -> 1 == c);
public GipsArithmeticExpression getNodeA() {
return nodeA;
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutD.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutD.java
index da1b3bed..a2ed079d 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutD.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/EquivalenceShortcutD.java
@@ -29,7 +29,7 @@ public class EquivalenceShortcutD extends AbstractPatternMatcher {
private final ValueConstantRelation isRelationalPair = new ValueConstantRelation( //
false, //
RelationalOperator.EQUAL, //
- c -> "0".equals(c) || "1".equals(c));
+ c -> 0 == c || 1 == c);
public GipsArithmeticExpression getNodeA() {
return nodeA;
@@ -57,27 +57,26 @@ public void tryMatchPattern(GipsBooleanExpression expression) {
return;
if (!hasMatch()) {
- nodeA = matchNode(implication.getLeft(), "0");
- nodeB = matchNode(implication.getRight(), "1");
+ nodeA = matchNode(implication.getLeft(), 0);
+ nodeB = matchNode(implication.getRight(), 1);
clearPartialMatch();
}
if (!hasMatch()) {
- nodeA = matchNode(implication.getRight(), "0");
- nodeB = matchNode(implication.getLeft(), "1");
+ nodeA = matchNode(implication.getRight(), 0);
+ nodeB = matchNode(implication.getLeft(), 1);
clearPartialMatch();
}
}
- private GipsArithmeticExpression matchNode(GipsBooleanExpression expression, String expectedConstant) {
+ private GipsArithmeticExpression matchNode(GipsBooleanExpression expression, int expectedConstant) {
expression = peelBrackets(expression);
// A == c
- if (isRelationalPair.matchPattern(expression)
- && expectedConstant.equals(isRelationalPair.getLiteral().getValue()))
+ if (isRelationalPair.matchPattern(expression) && expectedConstant == isRelationalPair.getLiteral().getValue())
return isRelationalPair.getNodeA();
- boolean mustBeNegated = "0".equals(expectedConstant);
+ boolean mustBeNegated = 0 == expectedConstant;
// A / !A
if (isImplicitBool.matchPattern(expression) && mustBeNegated == isImplicitBool.isNegated())
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/ImplicationShortcutA.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/ImplicationShortcutA.java
index 6a5e71e3..afa1acff 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/ImplicationShortcutA.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/ImplicationShortcutA.java
@@ -29,7 +29,7 @@ public class ImplicationShortcutA extends AbstractPatternMatcher {
private final ValueConstantRelation isRelationalPair = new ValueConstantRelation( //
false, //
RelationalOperator.EQUAL, //
- c -> "1".equals(c));
+ c -> 1 == c);
public GipsArithmeticExpression getNodeA() {
return nodeA;
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/ValueConstantRelation.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/ValueConstantRelation.java
index aa6a8238..3283ef67 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/ValueConstantRelation.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/special/pattern/ValueConstantRelation.java
@@ -6,8 +6,8 @@
import java.util.Objects;
import java.util.function.Predicate;
-import org.emoflon.gips.gipsl.gipsl.GipsArithmeticLiteral;
import org.emoflon.gips.gipsl.gipsl.GipsBooleanExpression;
+import org.emoflon.gips.gipsl.gipsl.GipsIntegerLiteral;
import org.emoflon.gips.gipsl.gipsl.GipsRelationalExpression;
import org.emoflon.gips.gipsl.gipsl.GipsValueExpression;
import org.emoflon.gips.gipsl.gipsl.RelationalOperator;
@@ -20,14 +20,14 @@ public class ValueConstantRelation extends AbstractPatternMatcher {
private final RelationalOperator matchOperator;
private final RelationalOperator reversedmatchOperator;
- private final Predicate matchConstant;
+ private final Predicate matchConstant;
private final boolean onlyBinaries;
private GipsValueExpression nodeA;
- private GipsArithmeticLiteral literal;
+ private GipsIntegerLiteral literal;
public ValueConstantRelation(boolean onlyBinaries, RelationalOperator matchOperator,
- Predicate matchConstant) {
+ Predicate matchConstant) {
this.onlyBinaries = onlyBinaries;
this.matchOperator = Objects.requireNonNull(matchOperator);
this.matchConstant = Objects.requireNonNull(matchConstant);
@@ -41,7 +41,7 @@ public ValueConstantRelation(boolean onlyBinaries, RelationalOperator matchOpera
};
}
- public GipsArithmeticLiteral getLiteral() {
+ public GipsIntegerLiteral getLiteral() {
return literal;
}
@@ -75,14 +75,14 @@ protected void tryMatchPattern(GipsBooleanExpression expression) {
if (matchOperator == relational.getOperator()) {
if (leftNode instanceof GipsValueExpression exp //
- && rightNode instanceof GipsArithmeticLiteral literal //
+ && rightNode instanceof GipsIntegerLiteral literal //
&& matchConstant.test(literal.getValue())) {
matchPair(exp, literal);
}
} else if (reversedmatchOperator == relational.getOperator()) {
- if (leftNode instanceof GipsArithmeticLiteral literal //
+ if (leftNode instanceof GipsIntegerLiteral literal //
&& rightNode instanceof GipsValueExpression exp //
&& matchConstant.test(literal.getValue())) {
@@ -92,7 +92,7 @@ protected void tryMatchPattern(GipsBooleanExpression expression) {
}
}
- protected void matchPair(GipsValueExpression exp, GipsArithmeticLiteral literal) {
+ protected void matchPair(GipsValueExpression exp, GipsIntegerLiteral literal) {
var type = GipslExpressionValidator.evaluate(exp, new LinkedList<>());
if (type.isScalar()) {
if (onlyBinaries) {
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslMappingValidator.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslMappingValidator.java
index 2bd1a2a1..80983b50 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslMappingValidator.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslMappingValidator.java
@@ -42,6 +42,17 @@ public static void checkMapping(final GipsMapping mapping) {
checkMappingValueInUse(mapping);
}
+ public static void checkMappingVariable(final GipsMappingVariable variable) {
+ if (GipslValidator.DISABLE_VALIDATOR)
+ return;
+
+ if (variable == null)
+ return;
+
+ checkMappingVariableNameUnique(variable);
+ checkMappingVariableInUse(variable);
+ }
+
/**
* Checks for validity of a mapping name. The name must not be on the list of
* invalid names, the name should be in lowerCamelCase, and the name should
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java
index 8cabaf0c..c7009109 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java
@@ -16,8 +16,10 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
+import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
+import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.resource.XtextResourceSet;
@@ -29,6 +31,9 @@
import org.emoflon.gips.gipsl.gipsl.GipsConfig;
import org.emoflon.gips.gipsl.gipsl.GipsConstant;
import org.emoflon.gips.gipsl.gipsl.GipsConstraint;
+import org.emoflon.gips.gipsl.gipsl.GipsDoubleLiteral;
+import org.emoflon.gips.gipsl.gipsl.GipsIntegerLiteral;
+import org.emoflon.gips.gipsl.gipsl.GipsInterval;
import org.emoflon.gips.gipsl.gipsl.GipsJoinAllOperation;
import org.emoflon.gips.gipsl.gipsl.GipsJoinBySelectionOperation;
import org.emoflon.gips.gipsl.gipsl.GipsLinearFunction;
@@ -42,6 +47,7 @@
import org.emoflon.gips.gipsl.gipsl.GipsTypeExtension;
import org.emoflon.gips.gipsl.gipsl.GipsTypeExtensionVariable;
import org.emoflon.gips.gipsl.gipsl.GipsTypeSelect;
+import org.emoflon.gips.gipsl.gipsl.GipsVariable;
import org.emoflon.gips.gipsl.gipsl.GipsVariableReferenceExpression;
import org.emoflon.gips.gipsl.gipsl.GipslPackage;
import org.emoflon.gips.gipsl.gipsl.ImportedPattern;
@@ -374,14 +380,7 @@ public void checkMapping(final GipsMapping mapping) {
@Check
public void checkMappingVariable(final GipsMappingVariable variable) {
- if (GipslValidator.DISABLE_VALIDATOR) {
- return;
- }
- if (variable == null) {
- return;
- }
- GipslMappingValidator.checkMappingVariableNameUnique(variable);
- GipslMappingValidator.checkMappingVariableInUse(variable);
+ GipslMappingValidator.checkMappingVariable(variable);
}
@Check
@@ -394,6 +393,49 @@ public void checkTypeExtensionVariable(final GipsTypeExtensionVariable variable)
GipslTypeExtensionValidator.checkTypeExtensionVariable(variable);
}
+ @Check
+ public void checkInterval(final GipsInterval interval) {
+ if (GipslValidator.DISABLE_VALIDATOR)
+ return;
+
+ if (!interval.isLowerInfinity() && !interval.isUpperInfinity()) {
+ double lowerBound = switch (interval.getLowerBound()) {
+ case GipsDoubleLiteral val -> val.getValue();
+ case GipsIntegerLiteral val -> val.getValue();
+ default -> throw new IllegalArgumentException("Unexpected value: " + interval.getLowerBound());
+ };
+
+ double upperBound = switch (interval.getUpperBound()) {
+ case GipsDoubleLiteral val -> val.getValue();
+ case GipsIntegerLiteral val -> val.getValue();
+ default -> throw new IllegalArgumentException("Unexpected value: " + interval.getLowerBound());
+ };
+
+ if (Double.compare(lowerBound, upperBound) > 0)
+ GipslValidator.err( //
+ GipslValidatorUtil.VARIABLE_BOUNDS_LIMIT_ERROR, //
+ interval, //
+ GipslPackage.Literals.GIPS_VARIABLE__INTERVAL);
+ }
+
+ // intervals cannot be used with booleans
+
+ EObject container = interval.eContainer();
+ if (container == null)
+ return;
+
+ EDataType type = null;
+ if (container instanceof GipsVariable variable)
+ type = variable.getType();
+
+ if (type == EcorePackage.Literals.EBOOLEAN) {
+ GipslValidator.err(GipslValidatorUtil.VARIABLE_BOUNDS_SUPPORT_ERROR, //
+ interval, //
+ GipslPackage.Literals.GIPS_VARIABLE__INTERVAL);
+ }
+
+ }
+
@Check
public void checkConstant(final GipsConstant constant) {
if (GipslValidator.DISABLE_VALIDATOR) {
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidatorUtil.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidatorUtil.java
index 9b49eef3..dd5e7dff 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidatorUtil.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidatorUtil.java
@@ -119,6 +119,9 @@ protected enum ContextType {
public static final String TYPE_EXTENSION_VARIABLE_ATTRIBUTE_ALREADY_BOUND = "Variable '%s' in extension '%s' is already bound to this attribute.";
public static final String TYPE_EXTENSION_VARIABLE_NOT_USED = "Variable '%s' is never used. No (M)ILP variable will be created for this variable.";
+ public static final String VARIABLE_BOUNDS_SUPPORT_ERROR = "Boolean does not support lower or upper bounds.";
+ public static final String VARIABLE_BOUNDS_LIMIT_ERROR = "The lower bound cannot be greater than the upper bound.";
+
public static final String FUNCTION_NAME_MULTIPLE_DECLARATIONS_MESSAGE = "Linear function '%s' must not be declared '%s' (case insensitive)";
public static final String FUNCTION_NAME_FORBIDDEN_MESSAGE = "Objectives cannot be be named '%s'. Use a different name.";
public static final String FUNCTION_NAME_CONTAINS_UNDERSCORES_MESSAGE = "Objective name '%s' contains underscores. Use camelCase instead.";
From c86d7cbf5d62bc0b388286eff8d45f5f298574b5 Mon Sep 17 00:00:00 2001
From: MarkBeB <177214717+MarkBeB@users.noreply.github.com>
Date: Wed, 19 Aug 2026 16:25:21 +0200
Subject: [PATCH 3/9] Improve validator
---
.../validation/GipslIntervalValidator.java | 60 +++++++++++++++++++
.../gips/gipsl/validation/GipslValidator.java | 47 ++-------------
.../validation/GipslVariableValidator.java | 33 ++++++++++
3 files changed, 98 insertions(+), 42 deletions(-)
create mode 100644 org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslIntervalValidator.java
create mode 100644 org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslVariableValidator.java
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslIntervalValidator.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslIntervalValidator.java
new file mode 100644
index 00000000..3ee3a710
--- /dev/null
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslIntervalValidator.java
@@ -0,0 +1,60 @@
+package org.emoflon.gips.gipsl.validation;
+
+import org.emoflon.gips.gipsl.gipsl.GipsDoubleLiteral;
+import org.emoflon.gips.gipsl.gipsl.GipsIntegerLiteral;
+import org.emoflon.gips.gipsl.gipsl.GipsInterval;
+import org.emoflon.gips.gipsl.gipsl.GipslPackage;
+
+public class GipslIntervalValidator {
+ private GipslIntervalValidator() {
+
+ }
+
+ public static void checkInterval(final GipsInterval interval) {
+ if (GipslValidator.DISABLE_VALIDATOR)
+ return;
+
+ if (interval == null)
+ return;
+
+ checkBounds(interval);
+ }
+
+ private static void checkBounds(GipsInterval interval) {
+ if (!interval.isLowerInfinity() && interval.getLowerBound() == null) {
+ GipslValidator.err( //
+ "Lower bound not defined", //
+ interval, GipslPackage.Literals.GIPS_INTERVAL__LOWER_BOUND);
+ return;
+ }
+
+ if (!interval.isUpperInfinity() && interval.getUpperBound() == null) {
+ GipslValidator.err( //
+ "Upper bound not defined", //
+ interval, GipslPackage.Literals.GIPS_INTERVAL__UPPER_BOUND);
+ return;
+ }
+
+ if (!interval.isLowerInfinity() && !interval.isUpperInfinity()) {
+ double lowerBound = switch (interval.getLowerBound()) {
+ case GipsDoubleLiteral val -> val.getValue();
+ case GipsIntegerLiteral val -> val.getValue();
+ case null, default -> throw new IllegalArgumentException("Unexpected value: " + interval.getLowerBound());
+ };
+
+ double upperBound = switch (interval.getUpperBound()) {
+ case GipsDoubleLiteral val -> val.getValue();
+ case GipsIntegerLiteral val -> val.getValue();
+ case null, default -> throw new IllegalArgumentException("Unexpected value: " + interval.getLowerBound());
+ };
+
+ if (Double.compare(lowerBound, upperBound) > 0) {
+ GipslValidator.err( //
+ GipslValidatorUtil.VARIABLE_BOUNDS_LIMIT_ERROR, //
+ interval, //
+ GipslPackage.Literals.GIPS_INTERVAL__LOWER_BOUND);
+ return;
+ }
+ }
+ }
+}
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java
index c7009109..e3bd9c11 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java
@@ -16,10 +16,8 @@
import org.eclipse.core.runtime.CoreException;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
-import org.eclipse.emf.ecore.EDataType;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
-import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.resource.XtextResourceSet;
@@ -31,8 +29,6 @@
import org.emoflon.gips.gipsl.gipsl.GipsConfig;
import org.emoflon.gips.gipsl.gipsl.GipsConstant;
import org.emoflon.gips.gipsl.gipsl.GipsConstraint;
-import org.emoflon.gips.gipsl.gipsl.GipsDoubleLiteral;
-import org.emoflon.gips.gipsl.gipsl.GipsIntegerLiteral;
import org.emoflon.gips.gipsl.gipsl.GipsInterval;
import org.emoflon.gips.gipsl.gipsl.GipsJoinAllOperation;
import org.emoflon.gips.gipsl.gipsl.GipsJoinBySelectionOperation;
@@ -395,45 +391,12 @@ public void checkTypeExtensionVariable(final GipsTypeExtensionVariable variable)
@Check
public void checkInterval(final GipsInterval interval) {
- if (GipslValidator.DISABLE_VALIDATOR)
- return;
-
- if (!interval.isLowerInfinity() && !interval.isUpperInfinity()) {
- double lowerBound = switch (interval.getLowerBound()) {
- case GipsDoubleLiteral val -> val.getValue();
- case GipsIntegerLiteral val -> val.getValue();
- default -> throw new IllegalArgumentException("Unexpected value: " + interval.getLowerBound());
- };
-
- double upperBound = switch (interval.getUpperBound()) {
- case GipsDoubleLiteral val -> val.getValue();
- case GipsIntegerLiteral val -> val.getValue();
- default -> throw new IllegalArgumentException("Unexpected value: " + interval.getLowerBound());
- };
-
- if (Double.compare(lowerBound, upperBound) > 0)
- GipslValidator.err( //
- GipslValidatorUtil.VARIABLE_BOUNDS_LIMIT_ERROR, //
- interval, //
- GipslPackage.Literals.GIPS_VARIABLE__INTERVAL);
- }
-
- // intervals cannot be used with booleans
-
- EObject container = interval.eContainer();
- if (container == null)
- return;
-
- EDataType type = null;
- if (container instanceof GipsVariable variable)
- type = variable.getType();
-
- if (type == EcorePackage.Literals.EBOOLEAN) {
- GipslValidator.err(GipslValidatorUtil.VARIABLE_BOUNDS_SUPPORT_ERROR, //
- interval, //
- GipslPackage.Literals.GIPS_VARIABLE__INTERVAL);
- }
+ GipslIntervalValidator.checkInterval(interval);
+ }
+ @Check
+ public void checkInterval(final GipsVariable variable) {
+ GipslVariableValidator.checkVariable(variable);
}
@Check
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslVariableValidator.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslVariableValidator.java
new file mode 100644
index 00000000..fb73a301
--- /dev/null
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslVariableValidator.java
@@ -0,0 +1,33 @@
+package org.emoflon.gips.gipsl.validation;
+
+import org.eclipse.emf.ecore.EcorePackage;
+import org.emoflon.gips.gipsl.gipsl.GipsVariable;
+import org.emoflon.gips.gipsl.gipsl.GipslPackage;
+
+public class GipslVariableValidator {
+ private GipslVariableValidator() {
+
+ }
+
+ public static void checkVariable(final GipsVariable variable) {
+ if (GipslValidator.DISABLE_VALIDATOR)
+ return;
+
+ if (variable == null)
+ return;
+
+ checkBounds(variable);
+ }
+
+ private static void checkBounds(GipsVariable variable) {
+ if (variable.getInterval() == null)
+ return;
+
+ if (variable.getType() == EcorePackage.Literals.EBOOLEAN) {
+ GipslValidator.err(GipslValidatorUtil.VARIABLE_BOUNDS_SUPPORT_ERROR, //
+ variable, //
+ GipslPackage.Literals.GIPS_VARIABLE__INTERVAL);
+ }
+ }
+
+}
From 41c560e6933de2af07a836b0e85681c4b90ceebf Mon Sep 17 00:00:00 2001
From: MarkBeB <177214717+MarkBeB@users.noreply.github.com>
Date: Thu, 20 Aug 2026 10:53:30 +0200
Subject: [PATCH 4/9] xtext update
---
org.emoflon.gips.gipsl/model/generated/Gipsl.genmodel | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/org.emoflon.gips.gipsl/model/generated/Gipsl.genmodel b/org.emoflon.gips.gipsl/model/generated/Gipsl.genmodel
index 053ae1f2..06571e64 100644
--- a/org.emoflon.gips.gipsl/model/generated/Gipsl.genmodel
+++ b/org.emoflon.gips.gipsl/model/generated/Gipsl.genmodel
@@ -1,6 +1,6 @@
From d1cf738fc21bfa475232749d3560e3460f77bed6 Mon Sep 17 00:00:00 2001
From: MarkBeB <177214717+MarkBeB@users.noreply.github.com>
Date: Thu, 20 Aug 2026 14:00:57 +0200
Subject: [PATCH 5/9] Allow bounds to be set on EBooleans
---
.../gips/gipsl/validation/GipslValidator.java | 6 ----
.../validation/GipslVariableValidator.java | 33 -------------------
2 files changed, 39 deletions(-)
delete mode 100644 org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslVariableValidator.java
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java
index e3bd9c11..859d4f69 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java
@@ -43,7 +43,6 @@
import org.emoflon.gips.gipsl.gipsl.GipsTypeExtension;
import org.emoflon.gips.gipsl.gipsl.GipsTypeExtensionVariable;
import org.emoflon.gips.gipsl.gipsl.GipsTypeSelect;
-import org.emoflon.gips.gipsl.gipsl.GipsVariable;
import org.emoflon.gips.gipsl.gipsl.GipsVariableReferenceExpression;
import org.emoflon.gips.gipsl.gipsl.GipslPackage;
import org.emoflon.gips.gipsl.gipsl.ImportedPattern;
@@ -394,11 +393,6 @@ public void checkInterval(final GipsInterval interval) {
GipslIntervalValidator.checkInterval(interval);
}
- @Check
- public void checkInterval(final GipsVariable variable) {
- GipslVariableValidator.checkVariable(variable);
- }
-
@Check
public void checkConstant(final GipsConstant constant) {
if (GipslValidator.DISABLE_VALIDATOR) {
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslVariableValidator.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslVariableValidator.java
deleted file mode 100644
index fb73a301..00000000
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslVariableValidator.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package org.emoflon.gips.gipsl.validation;
-
-import org.eclipse.emf.ecore.EcorePackage;
-import org.emoflon.gips.gipsl.gipsl.GipsVariable;
-import org.emoflon.gips.gipsl.gipsl.GipslPackage;
-
-public class GipslVariableValidator {
- private GipslVariableValidator() {
-
- }
-
- public static void checkVariable(final GipsVariable variable) {
- if (GipslValidator.DISABLE_VALIDATOR)
- return;
-
- if (variable == null)
- return;
-
- checkBounds(variable);
- }
-
- private static void checkBounds(GipsVariable variable) {
- if (variable.getInterval() == null)
- return;
-
- if (variable.getType() == EcorePackage.Literals.EBOOLEAN) {
- GipslValidator.err(GipslValidatorUtil.VARIABLE_BOUNDS_SUPPORT_ERROR, //
- variable, //
- GipslPackage.Literals.GIPS_VARIABLE__INTERVAL);
- }
- }
-
-}
From f53b460dc6dbb5ee524338169937e105275cc9d7 Mon Sep 17 00:00:00 2001
From: MarkBeB <177214717+MarkBeB@users.noreply.github.com>
Date: Thu, 20 Aug 2026 14:35:45 +0200
Subject: [PATCH 6/9] Revert "Allow bounds to be set on EBooleans"
This reverts commit d1cf738fc21bfa475232749d3560e3460f77bed6.
---
.../gips/gipsl/validation/GipslValidator.java | 6 ++++
.../validation/GipslVariableValidator.java | 35 +++++++++++++++++++
2 files changed, 41 insertions(+)
create mode 100644 org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslVariableValidator.java
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java
index 859d4f69..e3bd9c11 100644
--- a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslValidator.java
@@ -43,6 +43,7 @@
import org.emoflon.gips.gipsl.gipsl.GipsTypeExtension;
import org.emoflon.gips.gipsl.gipsl.GipsTypeExtensionVariable;
import org.emoflon.gips.gipsl.gipsl.GipsTypeSelect;
+import org.emoflon.gips.gipsl.gipsl.GipsVariable;
import org.emoflon.gips.gipsl.gipsl.GipsVariableReferenceExpression;
import org.emoflon.gips.gipsl.gipsl.GipslPackage;
import org.emoflon.gips.gipsl.gipsl.ImportedPattern;
@@ -393,6 +394,11 @@ public void checkInterval(final GipsInterval interval) {
GipslIntervalValidator.checkInterval(interval);
}
+ @Check
+ public void checkInterval(final GipsVariable variable) {
+ GipslVariableValidator.checkVariable(variable);
+ }
+
@Check
public void checkConstant(final GipsConstant constant) {
if (GipslValidator.DISABLE_VALIDATOR) {
diff --git a/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslVariableValidator.java b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslVariableValidator.java
new file mode 100644
index 00000000..14503658
--- /dev/null
+++ b/org.emoflon.gips.gipsl/src/org/emoflon/gips/gipsl/validation/GipslVariableValidator.java
@@ -0,0 +1,35 @@
+package org.emoflon.gips.gipsl.validation;
+
+import org.eclipse.emf.ecore.EcorePackage;
+import org.emoflon.gips.gipsl.gipsl.GipsVariable;
+import org.emoflon.gips.gipsl.gipsl.GipslPackage;
+
+public class GipslVariableValidator {
+ private GipslVariableValidator() {
+
+ }
+
+ public static void checkVariable(final GipsVariable variable) {
+ if (GipslValidator.DISABLE_VALIDATOR)
+ return;
+
+ if (variable == null)
+ return;
+
+ checkBounds(variable);
+ }
+
+ private static void checkBounds(GipsVariable variable) {
+ if (variable.getInterval() == null)
+ return;
+
+ // A binary type can only have bounds of 0 and 1, otherwise it is no longer
+ // binary or can take on a value that is atypical or unexpected for a binary.
+ if (variable.getType() == EcorePackage.Literals.EBOOLEAN) {
+ GipslValidator.err(GipslValidatorUtil.VARIABLE_BOUNDS_SUPPORT_ERROR, //
+ variable, //
+ GipslPackage.Literals.GIPS_VARIABLE__INTERVAL);
+ }
+ }
+
+}
From e82f98014674601fe3a2a1bd969dfba818f1910d Mon Sep 17 00:00:00 2001
From: MarkBeB <177214717+MarkBeB@users.noreply.github.com>
Date: Thu, 20 Aug 2026 17:14:14 +0200
Subject: [PATCH 7/9] Add upper/lower bounds to mapping variables (code
generator)
---
.../templates/RuleMappingTemplate.xtend | 24 +++++++++++--------
1 file changed, 14 insertions(+), 10 deletions(-)
diff --git a/org.emoflon.gips.build/src/org/emoflon/gips/build/generator/templates/RuleMappingTemplate.xtend b/org.emoflon.gips.build/src/org/emoflon/gips/build/generator/templates/RuleMappingTemplate.xtend
index ab4da0aa..803719f6 100644
--- a/org.emoflon.gips.build/src/org/emoflon/gips/build/generator/templates/RuleMappingTemplate.xtend
+++ b/org.emoflon.gips.build/src/org/emoflon/gips/build/generator/templates/RuleMappingTemplate.xtend
@@ -52,18 +52,22 @@ class RuleMappingTemplate extends ClassGeneratorTemplate {
«ENDIF»
public «className»(final String milpVariable, final boolean hasBinaryVariable, final «data.mapping2matchClassName.get(context)» match) {
- super(milpVariable, hasBinaryVariable, match);
+ super(milpVariable, hasBinaryVariable, match);
+
+ «IF !context.freeVariables.isNullOrEmpty»
+ «FOR v : context.freeVariables»
+ «v.name.toFirstLower» = new «GipsImportManager.variableToJavaDataType(v, imports)»(name + "->«v.name»");
+ «v.name.toFirstLower».setUpperBound(«v.upperBound»);
+ «v.name.toFirstLower».setLowerBound(«v.lowerBound»);
+ «ENDFOR»
+ «ENDIF»
- «IF !context.freeVariables.isNullOrEmpty»
- «FOR v : context.freeVariables»
- «v.name.toFirstLower» = new «GipsImportManager.variableToJavaDataType(v, imports)»(name + "->«v.name»");
- «ENDFOR»
- «ENDIF»
-
«IF !context.boundVariables.isNullOrEmpty»
- «FOR v : context.boundVariables»
- «v.name.toFirstLower» = new «GipsImportManager.variableToJavaDataType(v, imports)»(name + "->«v.name»");
- «ENDFOR»
+ «FOR v : context.boundVariables»
+ «v.name.toFirstLower» = new «GipsImportManager.variableToJavaDataType(v, imports)»(name + "->«v.name»");
+ «v.name.toFirstLower».setUpperBound(«v.upperBound»);
+ «v.name.toFirstLower».setLowerBound(«v.lowerBound»);
+ «ENDFOR»
«ENDIF»
}
From 0a62c9fad3cc02777caff18e5903d2651f3e03dc Mon Sep 17 00:00:00 2001
From: MarkBeB <177214717+MarkBeB@users.noreply.github.com>
Date: Wed, 26 Aug 2026 23:03:03 +0200
Subject: [PATCH 8/9] Cast upper/lower bound to int for integer/binary
variables
---
.../templates/RuleMappingTemplate.xtend | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/org.emoflon.gips.build/src/org/emoflon/gips/build/generator/templates/RuleMappingTemplate.xtend b/org.emoflon.gips.build/src/org/emoflon/gips/build/generator/templates/RuleMappingTemplate.xtend
index 803719f6..dc6cbbb6 100644
--- a/org.emoflon.gips.build/src/org/emoflon/gips/build/generator/templates/RuleMappingTemplate.xtend
+++ b/org.emoflon.gips.build/src/org/emoflon/gips/build/generator/templates/RuleMappingTemplate.xtend
@@ -6,6 +6,7 @@ import org.emoflon.gips.intermediate.GipsIntermediate.RuleMapping
import org.emoflon.gips.intermediate.GipsIntermediate.VariableType
import org.emoflon.ibex.patternmodel.IBeXPatternModel.IBeXContextAlternatives
import org.emoflon.ibex.patternmodel.IBeXPatternModel.IBeXContextPattern
+import org.eclipse.xtend.core.richstring.EndIf
class RuleMappingTemplate extends ClassGeneratorTemplate {
@@ -57,16 +58,26 @@ class RuleMappingTemplate extends ClassGeneratorTemplate {
«IF !context.freeVariables.isNullOrEmpty»
«FOR v : context.freeVariables»
«v.name.toFirstLower» = new «GipsImportManager.variableToJavaDataType(v, imports)»(name + "->«v.name»");
- «v.name.toFirstLower».setUpperBound(«v.upperBound»);
- «v.name.toFirstLower».setLowerBound(«v.lowerBound»);
+ «IF v.type === VariableType.REAL»
+ «v.name.toFirstLower».setUpperBound(«v.upperBound»);
+ «v.name.toFirstLower».setLowerBound(«v.lowerBound»);
+ «ELSE»
+ «v.name.toFirstLower».setUpperBound((int)«v.upperBound»);
+ «v.name.toFirstLower».setLowerBound((int)«v.lowerBound»);
+ «ENDIF»
«ENDFOR»
«ENDIF»
«IF !context.boundVariables.isNullOrEmpty»
«FOR v : context.boundVariables»
«v.name.toFirstLower» = new «GipsImportManager.variableToJavaDataType(v, imports)»(name + "->«v.name»");
- «v.name.toFirstLower».setUpperBound(«v.upperBound»);
- «v.name.toFirstLower».setLowerBound(«v.lowerBound»);
+ «IF v.type === VariableType.REAL»
+ «v.name.toFirstLower».setUpperBound(«v.upperBound»);
+ «v.name.toFirstLower».setLowerBound(«v.lowerBound»);
+ «ELSE»
+ «v.name.toFirstLower».setUpperBound((int)«v.upperBound»);
+ «v.name.toFirstLower».setLowerBound((int)«v.lowerBound»);
+ «ENDIF»
«ENDFOR»
«ENDIF»
}
From a6475fbea1ab79996c79961ccbff8752a04ba63b Mon Sep 17 00:00:00 2001
From: MarkBeB <177214717+MarkBeB@users.noreply.github.com>
Date: Thu, 27 Aug 2026 14:17:44 +0200
Subject: [PATCH 9/9] Compute max/min bounds for ints
---
.../helper/GipsTransformationUtils.java | 90 ++++++++++++++-----
1 file changed, 66 insertions(+), 24 deletions(-)
diff --git a/org.emoflon.gips.build/src/org/emoflon/gips/build/transformation/helper/GipsTransformationUtils.java b/org.emoflon.gips.build/src/org/emoflon/gips/build/transformation/helper/GipsTransformationUtils.java
index 3474f965..f4feedce 100644
--- a/org.emoflon.gips.build/src/org/emoflon/gips/build/transformation/helper/GipsTransformationUtils.java
+++ b/org.emoflon.gips.build/src/org/emoflon/gips/build/transformation/helper/GipsTransformationUtils.java
@@ -313,39 +313,21 @@ public static Set extractConstantReference(final RelationalEx
}
public static double getUpperBound(final GipsVariable gipsVar, final VariableType type) {
- if (type == VariableType.BINARY)
- return 1;
-
if (gipsVar.getInterval() != null && !gipsVar.getInterval().isUpperInfinity()) {
- return getValue(gipsVar.getInterval().getUpperBound());
-
- } else if (type == VariableType.INTEGER) {
- return Integer.MAX_VALUE;
-
- } else if (type == VariableType.REAL) {
- return Double.MAX_VALUE;
-
+ var upperBound = getValue(gipsVar.getInterval().getUpperBound());
+ return getLeastUpperBound(upperBound, type);
}
- throw new UnsupportedOperationException();
+ return getMaxValue(type);
}
public static double getLowerBound(final GipsVariable gipsVar, final VariableType type) {
- if (type == VariableType.BINARY)
- return 0;
-
if (gipsVar.getInterval() != null && !gipsVar.getInterval().isLowerInfinity()) {
- return getValue(gipsVar.getInterval().getLowerBound());
-
- } else if (type == VariableType.INTEGER) {
- return Integer.MIN_VALUE;
-
- } else if (type == VariableType.REAL) {
- return -Double.MAX_VALUE;
-
+ var lowerBound = getValue(gipsVar.getInterval().getLowerBound());
+ return getGreatestLowerBound(lowerBound, type);
}
- throw new UnsupportedOperationException();
+ return getMinValue(type);
}
private static double getValue(final GipsArithmeticLiteral literal) {
@@ -356,6 +338,66 @@ private static double getValue(final GipsArithmeticLiteral literal) {
};
}
+ public static double getLeastUpperBound(double upperBound, VariableType type) {
+ if (Double.isNaN(upperBound))
+ throw new IllegalArgumentException("Boundary value cannot be NaN.");
+
+ return switch (type) {
+ case BINARY -> getMaxValue(VariableType.BINARY);
+ case REAL -> upperBound;
+ case INTEGER -> {
+ double floored = Math.floor(upperBound);
+ if (floored <= getMinValue(VariableType.INTEGER))
+ yield getMinValue(VariableType.INTEGER);
+
+ if (floored >= getMaxValue(VariableType.INTEGER))
+ yield getMaxValue(VariableType.INTEGER);
+
+ yield floored;
+ }
+ default -> throw new IllegalArgumentException("Unexpected value: " + type);
+ };
+ }
+
+ public static double getGreatestLowerBound(double lowerBound, VariableType type) {
+ if (Double.isNaN(lowerBound))
+ throw new IllegalArgumentException("Boundary value cannot be NaN.");
+
+ return switch (type) {
+ case BINARY -> getMinValue(VariableType.BINARY);
+ case REAL -> lowerBound;
+ case INTEGER -> {
+ double ceiled = Math.ceil(lowerBound);
+ if (ceiled <= getMinValue(VariableType.INTEGER))
+ yield getMinValue(VariableType.INTEGER);
+
+ if (ceiled >= getMaxValue(VariableType.INTEGER))
+ yield getMaxValue(VariableType.INTEGER);
+
+ yield ceiled;
+ }
+ default -> throw new IllegalArgumentException("Unexpected value: " + type);
+ };
+ }
+
+ public static double getMaxValue(VariableType type) {
+ return switch (type) {
+ case BINARY -> 1.0;
+ case INTEGER -> Integer.MAX_VALUE;
+ case REAL -> Double.MAX_VALUE;
+ default -> throw new IllegalArgumentException("Unexpected value: " + type);
+ };
+ }
+
+ public static double getMinValue(VariableType type) {
+ return switch (type) {
+ case BINARY -> 0.0;
+ case INTEGER -> Integer.MIN_VALUE;
+ case REAL -> -Double.MAX_VALUE;
+ default -> throw new IllegalArgumentException("Unexpected value: " + type);
+ };
+ }
+
public static ExpressionReturnType extractReturnType(BooleanExpression expression) {
return ExpressionReturnTypeResolver.extractReturnType(expression);
}