Browse Source

Added static type analysis for SText Expression Language

Andreas Mülder 13 years ago
parent
commit
b1f90df821

+ 19 - 0
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/validation/STextJavaValidator.java

@@ -23,6 +23,7 @@ import org.eclipse.xtext.validation.ValidationMessageAcceptor;
 import org.yakindu.sct.model.sgraph.SGraphPackage;
 import org.yakindu.sct.model.sgraph.Scope;
 import org.yakindu.sct.model.sgraph.Statechart;
+import org.yakindu.sct.model.sgraph.Statement;
 import org.yakindu.sct.model.stext.stext.AlwaysEvent;
 import org.yakindu.sct.model.stext.stext.Direction;
 import org.yakindu.sct.model.stext.stext.EntryEvent;
@@ -40,6 +41,8 @@ import org.yakindu.sct.model.stext.stext.StatechartDefinition;
 import org.yakindu.sct.model.stext.stext.StextPackage;
 import org.yakindu.sct.model.stext.stext.VariableDefinition;
 
+import com.google.inject.Inject;
+
 import de.itemis.xtext.utils.gmf.resource.InjectMembersResource;
 
 /**
@@ -50,6 +53,22 @@ import de.itemis.xtext.utils.gmf.resource.InjectMembersResource;
  */
 public class STextJavaValidator extends AbstractSTextJavaValidator {
 
+	@Inject
+	private StaticTypeAnalyzer analyzer;
+
+	@Check
+	public void checkExpression(final Statement statement) {
+		try {
+			analyzer.check(statement);
+		} catch (TypeCheckException e) {
+			error(e.getMessage(), null);
+		} catch (IllegalArgumentException e) {
+			// This happens, when the expression is not completed for Unhandled
+			// parameter types: [null]
+			// We can safely ignore this exception
+		}
+	}
+
 	@Check(CheckType.FAST)
 	public void checkReactionTrigger(ReactionTrigger reactionTrigger) {
 		for (EventSpec eventSpec : reactionTrigger.getTriggers()) {

+ 220 - 0
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/validation/StaticTypeAnalyzer.xtend

@@ -0,0 +1,220 @@
+/**
+ * Copyright (c) 2011 itemis AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ * 	itemis AG - initial API and implementation
+ *  
+ */
+package org.yakindu.sct.model.stext.validation
+
+import org.yakindu.sct.model.stext.stext.Expression
+import org.yakindu.sct.model.stext.stext.LogicalAndExpression
+import org.yakindu.sct.model.sgraph.Statement
+import org.yakindu.sct.model.stext.stext.RealLiteral
+import org.yakindu.sct.model.stext.stext.BoolLiteral
+import org.yakindu.sct.model.stext.stext.IntLiteral
+import org.yakindu.sct.model.stext.stext.PrimitiveValueExpression
+import org.yakindu.sct.model.stext.stext.LogicalOrExpression
+import org.yakindu.sct.model.stext.stext.LogicalNotExpression
+import org.yakindu.sct.model.stext.stext.BitwiseAndExpression
+import org.yakindu.sct.model.stext.stext.BitwiseOrExpression
+import org.yakindu.sct.model.stext.stext.BitwiseXorExpression
+import org.yakindu.sct.model.stext.stext.LogicalRelationExpression
+import org.yakindu.sct.model.stext.stext.NumericalAddSubtractExpression
+import org.yakindu.sct.model.stext.stext.NumericalMultiplyDivideExpression
+import org.yakindu.sct.model.stext.stext.ShiftExpression
+import org.yakindu.sct.model.stext.stext.NumericalUnaryExpression
+import org.yakindu.sct.model.stext.stext.EventValueReferenceExpression
+import org.yakindu.sct.model.stext.stext.EventRaisedReferenceExpression
+import org.yakindu.sct.model.stext.stext.ElementReferenceExpression
+import org.yakindu.sct.model.stext.stext.ConditionalExpression
+import org.yakindu.sct.model.stext.stext.EventRaising
+import org.yakindu.sct.model.stext.stext.Assignment
+import org.yakindu.sct.model.stext.stext.RelationalOperator
+import org.yakindu.sct.model.stext.stext.VariableDefinition
+import org.yakindu.sct.model.stext.stext.Type
+import com.google.inject.Inject
+import org.eclipse.xtext.validation.ValidationMessageAcceptor
+import org.yakindu.sct.model.stext.stext.EventDefinition
+
+/**
+ * 
+ * The Static type analyzer checks an expression AST for type conformance
+ * 
+ * @author andreas muelder - Initial contribution and API
+ * 
+ */
+class StaticTypeAnalyzer {
+	
+	/**
+	 * Check Variable assignments
+	 */
+	def dispatch check(Assignment assignment){
+		var valueType = assignment.expression.check
+		var ref = assignment.varRef
+		var type = (ref as VariableDefinition).getType()
+		switch(type){
+			case Type::BOOLEAN:
+				if(!(valueType == typeof(Boolean))){
+					error("Can not assign a value of type " + valueType.simpleName + " to a variable of type " + type)
+				}
+			case Type::INTEGER:
+				if(!(valueType == typeof(Number))){
+					error("Can not assign a value of type " + valueType.simpleName + " to a variable of type " + type)
+				}
+			case Type::REAL:
+				if(!(valueType == typeof(Number))){
+					error("Can not assign a value of type " + valueType.simpleName + " to a variable of type " + type)
+				}
+		} 
+		return null 
+	}
+	/**
+	 * Check Event value assignments
+	 */
+	def dispatch check(EventRaising eventRaising){
+		var valueType = eventRaising.value.check
+		var ref = eventRaising.event
+		var type = (ref as EventDefinition).getType()
+		switch(type){
+			case Type::BOOLEAN:
+				if(!(valueType == typeof(Boolean))){
+					error("Can not assign a value of type " + valueType.simpleName + " to an event of type " + type)
+				}
+			case Type::INTEGER:
+				if(!(valueType == typeof(Number))){
+					error("Can not assign a value of type " + valueType.simpleName + " to an event of type " + type)
+				}
+			case Type::REAL:
+				if(!(valueType == typeof(Number))){
+					error("Can not assign a value of type " + valueType.simpleName + " to an event  type " + type)
+				}
+		} 
+		return null 
+	}
+	
+	
+	
+	def dispatch check(LogicalAndExpression expression){
+		assertIsBoolean(expression.leftOperand.check, '&&')
+		assertIsBoolean(expression.rightOperand.check, '&&')
+		typeof(Boolean)
+	}
+	def dispatch check(LogicalOrExpression expression){
+		assertIsBoolean(expression.leftOperand.check,'||')
+		assertIsBoolean(expression.rightOperand.check,'||')
+		typeof(Boolean)
+	}
+	def dispatch check(LogicalNotExpression expression){
+		assertIsBoolean(expression.operand.check,'!')
+		typeof(Boolean)
+	}
+	def dispatch check(BitwiseAndExpression expression){
+		assertIsNumber(expression.leftOperand.check,'&')
+		assertIsNumber(expression.rightOperand.check,'&')
+		typeof(Number)
+	}
+	def dispatch check(BitwiseOrExpression expression){
+		assertIsNumber(expression.leftOperand.check,'|')
+		assertIsNumber(expression.rightOperand.check,'|')
+		typeof(Number)
+	}
+	def dispatch check(BitwiseXorExpression expression){
+		assertIsNumber(expression.leftOperand.check,'^')
+		assertIsNumber(expression.rightOperand.check,'^')
+		typeof(Number)
+	}
+	def dispatch check(LogicalRelationExpression expression){
+		var leftType = expression.leftOperand.check
+		var rightType = expression.rightOperand.check
+		if(leftType != rightType){
+			error("Incompatible operands " +leftType.simpleName + " and " + rightType.simpleName + " for operator '" + expression.operator.literal+"'")
+		}
+		//If both types are boolean, only relational operators Equals and not_Equals are allowed
+		if(leftType == typeof(Boolean) && rightType == typeof(Boolean)){
+			if(expression.operator != RelationalOperator::EQUALS && expression.operator != RelationalOperator::NOT_EQUALS){
+				error("operator '" + expression.operator.literal + "' can not be applied to boolean values!")
+			}
+		}
+		return typeof(Boolean) 
+		
+	}
+	def dispatch check(NumericalAddSubtractExpression expression){
+		assertIsNumber(expression.leftOperand.check, expression.operator.literal)
+		assertIsNumber(expression.rightOperand.check, expression.operator.literal)
+		typeof(Number)
+	}
+	def dispatch check(NumericalMultiplyDivideExpression expression){
+		assertIsNumber(expression.leftOperand.check, expression.operator.literal)
+		assertIsNumber(expression.rightOperand.check, expression.operator.literal)
+		typeof(Number)
+	}
+	def dispatch check(NumericalUnaryExpression expression){
+		assertIsNumber(expression.operand.check, expression.operator.literal)
+		typeof(Number)
+	}	
+	def dispatch check(PrimitiveValueExpression expression){
+		expression.value.type
+	}
+	def dispatch check(ShiftExpression expression){
+		//TODO: Implement me
+	}
+	def dispatch check(ConditionalExpression expression){
+		//TODO: Implement me
+	} 
+	def dispatch check(ElementReferenceExpression expression){
+		var declaration = expression.value
+		if(declaration instanceof VariableDefinition){
+			return (declaration as VariableDefinition).type.toJavaType
+		}
+		return null;
+	}
+	def dispatch check(EventRaisedReferenceExpression expression){
+		//TODO: Impement me
+	}
+	def dispatch check(EventValueReferenceExpression expression){
+		//TODO: Implement me
+	}
+	
+	def dispatch type(IntLiteral literal){
+		return typeof(Number)
+	} 
+	
+	def dispatch type(BoolLiteral bool){
+		return typeof(Boolean)
+	}
+	
+	def dispatch type(RealLiteral literal){
+		return typeof(Number)
+	}
+	
+	def toJavaType(Type type){
+		switch(type){
+			case Type::BOOLEAN:
+				return typeof(Boolean)
+			case Type::INTEGER:
+				return typeof(Number)
+			case Type::REAL:
+				return typeof(Number)
+		} 
+		return typeof(Void)
+	}
+	
+	def assertIsNumber(Object object, String operator){
+		if(!(object == typeof(Number)))
+			error("operator '" +operator+"' can only be applied to numbers!")
+	}
+	def assertIsBoolean(Object object, String operator){
+		if(!(object == typeof(Boolean)))
+			error("operator '" +operator+"' can only ne applied to boolean values!")
+	}
+	
+	def error(String msg){
+		throw new TypeCheckException(msg)
+	}
+
+}

+ 28 - 0
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/validation/TypeCheckException.java

@@ -0,0 +1,28 @@
+/**
+ * Copyright (c) 2011 itemis AG and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ * 
+ * Contributors:
+ * 	itemis AG - initial API and implementation
+ * 
+ */
+package org.yakindu.sct.model.stext.validation;
+
+/**
+ * checked Exception thrown by the {@link StaticTypeAnalyzer} if a type
+ * conformance check fails.
+ * 
+ * @author andreas muelder - Initial contribution and API
+ * 
+ */
+public class TypeCheckException extends Exception {
+
+	private static final long serialVersionUID = 1L;
+
+	public TypeCheckException(String cause) {
+		super(cause);
+	}
+}

+ 500 - 0
plugins/org.yakindu.sct.model.stext/xtend-gen/org/yakindu/sct/model/stext/validation/StaticTypeAnalyzer.java

@@ -0,0 +1,500 @@
+package org.yakindu.sct.model.stext.validation;
+
+import java.io.Serializable;
+import org.eclipse.xtext.xbase.lib.BooleanExtensions;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.lib.StringExtensions;
+import org.yakindu.sct.model.sgraph.Declaration;
+import org.yakindu.sct.model.sgraph.Event;
+import org.yakindu.sct.model.sgraph.Statement;
+import org.yakindu.sct.model.sgraph.Variable;
+import org.yakindu.sct.model.stext.stext.AdditiveOperator;
+import org.yakindu.sct.model.stext.stext.Assignment;
+import org.yakindu.sct.model.stext.stext.BitwiseAndExpression;
+import org.yakindu.sct.model.stext.stext.BitwiseOrExpression;
+import org.yakindu.sct.model.stext.stext.BitwiseXorExpression;
+import org.yakindu.sct.model.stext.stext.BoolLiteral;
+import org.yakindu.sct.model.stext.stext.ConditionalExpression;
+import org.yakindu.sct.model.stext.stext.ElementReferenceExpression;
+import org.yakindu.sct.model.stext.stext.EventDefinition;
+import org.yakindu.sct.model.stext.stext.EventRaisedReferenceExpression;
+import org.yakindu.sct.model.stext.stext.EventRaising;
+import org.yakindu.sct.model.stext.stext.EventValueReferenceExpression;
+import org.yakindu.sct.model.stext.stext.Expression;
+import org.yakindu.sct.model.stext.stext.IntLiteral;
+import org.yakindu.sct.model.stext.stext.Literal;
+import org.yakindu.sct.model.stext.stext.LogicalAndExpression;
+import org.yakindu.sct.model.stext.stext.LogicalNotExpression;
+import org.yakindu.sct.model.stext.stext.LogicalOrExpression;
+import org.yakindu.sct.model.stext.stext.LogicalRelationExpression;
+import org.yakindu.sct.model.stext.stext.MultiplicativeOperator;
+import org.yakindu.sct.model.stext.stext.NumericalAddSubtractExpression;
+import org.yakindu.sct.model.stext.stext.NumericalMultiplyDivideExpression;
+import org.yakindu.sct.model.stext.stext.NumericalUnaryExpression;
+import org.yakindu.sct.model.stext.stext.PrimitiveValueExpression;
+import org.yakindu.sct.model.stext.stext.RealLiteral;
+import org.yakindu.sct.model.stext.stext.RelationalOperator;
+import org.yakindu.sct.model.stext.stext.ShiftExpression;
+import org.yakindu.sct.model.stext.stext.Type;
+import org.yakindu.sct.model.stext.stext.UnaryOperator;
+import org.yakindu.sct.model.stext.stext.VariableDefinition;
+import org.yakindu.sct.model.stext.validation.TypeCheckException;
+
+@SuppressWarnings("all")
+public class StaticTypeAnalyzer {
+  
+  protected Class<? extends Object> _check(final Assignment assignment) throws TypeCheckException {
+    {
+      Expression _expression = assignment.getExpression();
+      Class<? extends Object> _check = this.check(_expression);
+      Class<? extends Object> valueType = _check;
+      Variable _varRef = assignment.getVarRef();
+      Variable ref = _varRef;
+      Type _type = ((VariableDefinition) ref).getType();
+      Type type = _type;
+      final Type type_1 = type;
+      boolean matched = false;
+      if (!matched) {
+        if (org.eclipse.xtext.xbase.lib.ObjectExtensions.operator_equals(type_1,Type.BOOLEAN)) {
+          matched=true;
+          boolean _operator_equals = ObjectExtensions.operator_equals(valueType, java.lang.Boolean.class);
+          boolean _operator_not = BooleanExtensions.operator_not(_operator_equals);
+          if (_operator_not) {
+            String _simpleName = valueType.getSimpleName();
+            String _operator_plus = StringExtensions.operator_plus("Can not assign a value of type ", _simpleName);
+            String _operator_plus_1 = StringExtensions.operator_plus(_operator_plus, " to a variable of type ");
+            String _operator_plus_2 = StringExtensions.operator_plus(_operator_plus_1, type);
+            this.error(_operator_plus_2);
+          }
+        }
+      }
+      if (!matched) {
+        if (org.eclipse.xtext.xbase.lib.ObjectExtensions.operator_equals(type_1,Type.INTEGER)) {
+          matched=true;
+          boolean _operator_equals_1 = ObjectExtensions.operator_equals(valueType, java.lang.Number.class);
+          boolean _operator_not_1 = BooleanExtensions.operator_not(_operator_equals_1);
+          if (_operator_not_1) {
+            String _simpleName_1 = valueType.getSimpleName();
+            String _operator_plus_3 = StringExtensions.operator_plus("Can not assign a value of type ", _simpleName_1);
+            String _operator_plus_4 = StringExtensions.operator_plus(_operator_plus_3, " to a variable of type ");
+            String _operator_plus_5 = StringExtensions.operator_plus(_operator_plus_4, type);
+            this.error(_operator_plus_5);
+          }
+        }
+      }
+      if (!matched) {
+        if (org.eclipse.xtext.xbase.lib.ObjectExtensions.operator_equals(type_1,Type.REAL)) {
+          matched=true;
+          boolean _operator_equals_2 = ObjectExtensions.operator_equals(valueType, java.lang.Number.class);
+          boolean _operator_not_2 = BooleanExtensions.operator_not(_operator_equals_2);
+          if (_operator_not_2) {
+            String _simpleName_2 = valueType.getSimpleName();
+            String _operator_plus_6 = StringExtensions.operator_plus("Can not assign a value of type ", _simpleName_2);
+            String _operator_plus_7 = StringExtensions.operator_plus(_operator_plus_6, " to a variable of type ");
+            String _operator_plus_8 = StringExtensions.operator_plus(_operator_plus_7, type);
+            this.error(_operator_plus_8);
+          }
+        }
+      }
+      return null;
+    }
+  }
+  
+  protected Class<? extends Object> _check(final EventRaising eventRaising) throws TypeCheckException {
+    {
+      Expression _value = eventRaising.getValue();
+      Class<? extends Object> _check = this.check(_value);
+      Class<? extends Object> valueType = _check;
+      Event _event = eventRaising.getEvent();
+      Event ref = _event;
+      Type _type = ((EventDefinition) ref).getType();
+      Type type = _type;
+      final Type type_1 = type;
+      boolean matched = false;
+      if (!matched) {
+        if (org.eclipse.xtext.xbase.lib.ObjectExtensions.operator_equals(type_1,Type.BOOLEAN)) {
+          matched=true;
+          boolean _operator_equals = ObjectExtensions.operator_equals(valueType, java.lang.Boolean.class);
+          boolean _operator_not = BooleanExtensions.operator_not(_operator_equals);
+          if (_operator_not) {
+            String _simpleName = valueType.getSimpleName();
+            String _operator_plus = StringExtensions.operator_plus("Can not assign a value of type ", _simpleName);
+            String _operator_plus_1 = StringExtensions.operator_plus(_operator_plus, " to an event of type ");
+            String _operator_plus_2 = StringExtensions.operator_plus(_operator_plus_1, type);
+            this.error(_operator_plus_2);
+          }
+        }
+      }
+      if (!matched) {
+        if (org.eclipse.xtext.xbase.lib.ObjectExtensions.operator_equals(type_1,Type.INTEGER)) {
+          matched=true;
+          boolean _operator_equals_1 = ObjectExtensions.operator_equals(valueType, java.lang.Number.class);
+          boolean _operator_not_1 = BooleanExtensions.operator_not(_operator_equals_1);
+          if (_operator_not_1) {
+            String _simpleName_1 = valueType.getSimpleName();
+            String _operator_plus_3 = StringExtensions.operator_plus("Can not assign a value of type ", _simpleName_1);
+            String _operator_plus_4 = StringExtensions.operator_plus(_operator_plus_3, " to an event of type ");
+            String _operator_plus_5 = StringExtensions.operator_plus(_operator_plus_4, type);
+            this.error(_operator_plus_5);
+          }
+        }
+      }
+      if (!matched) {
+        if (org.eclipse.xtext.xbase.lib.ObjectExtensions.operator_equals(type_1,Type.REAL)) {
+          matched=true;
+          boolean _operator_equals_2 = ObjectExtensions.operator_equals(valueType, java.lang.Number.class);
+          boolean _operator_not_2 = BooleanExtensions.operator_not(_operator_equals_2);
+          if (_operator_not_2) {
+            String _simpleName_2 = valueType.getSimpleName();
+            String _operator_plus_6 = StringExtensions.operator_plus("Can not assign a value of type ", _simpleName_2);
+            String _operator_plus_7 = StringExtensions.operator_plus(_operator_plus_6, " to an event  type ");
+            String _operator_plus_8 = StringExtensions.operator_plus(_operator_plus_7, type);
+            this.error(_operator_plus_8);
+          }
+        }
+      }
+      return null;
+    }
+  }
+  
+  protected Class<? extends Object> _check(final LogicalAndExpression expression) throws TypeCheckException {
+    Class<Boolean> _xblockexpression = null;
+    {
+      Expression _leftOperand = expression.getLeftOperand();
+      Class<? extends Object> _check = this.check(_leftOperand);
+      this.assertIsBoolean(_check, "&&");
+      Expression _rightOperand = expression.getRightOperand();
+      Class<? extends Object> _check_1 = this.check(_rightOperand);
+      this.assertIsBoolean(_check_1, "&&");
+      _xblockexpression = (java.lang.Boolean.class);
+    }
+    return _xblockexpression;
+  }
+  
+  protected Class<? extends Object> _check(final LogicalOrExpression expression) throws TypeCheckException {
+    Class<Boolean> _xblockexpression = null;
+    {
+      Expression _leftOperand = expression.getLeftOperand();
+      Class<? extends Object> _check = this.check(_leftOperand);
+      this.assertIsBoolean(_check, "||");
+      Expression _rightOperand = expression.getRightOperand();
+      Class<? extends Object> _check_1 = this.check(_rightOperand);
+      this.assertIsBoolean(_check_1, "||");
+      _xblockexpression = (java.lang.Boolean.class);
+    }
+    return _xblockexpression;
+  }
+  
+  protected Class<? extends Object> _check(final LogicalNotExpression expression) throws TypeCheckException {
+    Class<Boolean> _xblockexpression = null;
+    {
+      Expression _operand = expression.getOperand();
+      Class<? extends Object> _check = this.check(_operand);
+      this.assertIsBoolean(_check, "!");
+      _xblockexpression = (java.lang.Boolean.class);
+    }
+    return _xblockexpression;
+  }
+  
+  protected Class<? extends Object> _check(final BitwiseAndExpression expression) throws TypeCheckException {
+    Class<Number> _xblockexpression = null;
+    {
+      Expression _leftOperand = expression.getLeftOperand();
+      Class<? extends Object> _check = this.check(_leftOperand);
+      this.assertIsNumber(_check, "&");
+      Expression _rightOperand = expression.getRightOperand();
+      Class<? extends Object> _check_1 = this.check(_rightOperand);
+      this.assertIsNumber(_check_1, "&");
+      _xblockexpression = (java.lang.Number.class);
+    }
+    return _xblockexpression;
+  }
+  
+  protected Class<? extends Object> _check(final BitwiseOrExpression expression) throws TypeCheckException {
+    Class<Number> _xblockexpression = null;
+    {
+      Expression _leftOperand = expression.getLeftOperand();
+      Class<? extends Object> _check = this.check(_leftOperand);
+      this.assertIsNumber(_check, "|");
+      Expression _rightOperand = expression.getRightOperand();
+      Class<? extends Object> _check_1 = this.check(_rightOperand);
+      this.assertIsNumber(_check_1, "|");
+      _xblockexpression = (java.lang.Number.class);
+    }
+    return _xblockexpression;
+  }
+  
+  protected Class<? extends Object> _check(final BitwiseXorExpression expression) throws TypeCheckException {
+    Class<Number> _xblockexpression = null;
+    {
+      Expression _leftOperand = expression.getLeftOperand();
+      Class<? extends Object> _check = this.check(_leftOperand);
+      this.assertIsNumber(_check, "^");
+      Expression _rightOperand = expression.getRightOperand();
+      Class<? extends Object> _check_1 = this.check(_rightOperand);
+      this.assertIsNumber(_check_1, "^");
+      _xblockexpression = (java.lang.Number.class);
+    }
+    return _xblockexpression;
+  }
+  
+  protected Class<? extends Object> _check(final LogicalRelationExpression expression) throws TypeCheckException {
+    {
+      Expression _leftOperand = expression.getLeftOperand();
+      Class<? extends Object> _check = this.check(_leftOperand);
+      Class<? extends Object> leftType = _check;
+      Expression _rightOperand = expression.getRightOperand();
+      Class<? extends Object> _check_1 = this.check(_rightOperand);
+      Class<? extends Object> rightType = _check_1;
+      boolean _operator_notEquals = ObjectExtensions.operator_notEquals(leftType, rightType);
+      if (_operator_notEquals) {
+        String _simpleName = leftType.getSimpleName();
+        String _operator_plus = StringExtensions.operator_plus("Incompatible operands ", _simpleName);
+        String _operator_plus_1 = StringExtensions.operator_plus(_operator_plus, " and ");
+        String _simpleName_1 = rightType.getSimpleName();
+        String _operator_plus_2 = StringExtensions.operator_plus(_operator_plus_1, _simpleName_1);
+        String _operator_plus_3 = StringExtensions.operator_plus(_operator_plus_2, " for operator \'");
+        RelationalOperator _operator = expression.getOperator();
+        String _literal = _operator.getLiteral();
+        String _operator_plus_4 = StringExtensions.operator_plus(_operator_plus_3, _literal);
+        String _operator_plus_5 = StringExtensions.operator_plus(_operator_plus_4, "\'");
+        this.error(_operator_plus_5);
+      }
+      boolean _operator_and = false;
+      boolean _operator_equals = ObjectExtensions.operator_equals(leftType, java.lang.Boolean.class);
+      if (!_operator_equals) {
+        _operator_and = false;
+      } else {
+        boolean _operator_equals_1 = ObjectExtensions.operator_equals(rightType, java.lang.Boolean.class);
+        _operator_and = BooleanExtensions.operator_and(_operator_equals, _operator_equals_1);
+      }
+      if (_operator_and) {
+        boolean _operator_and_1 = false;
+        RelationalOperator _operator_1 = expression.getOperator();
+        boolean _operator_notEquals_1 = ObjectExtensions.operator_notEquals(_operator_1, RelationalOperator.EQUALS);
+        if (!_operator_notEquals_1) {
+          _operator_and_1 = false;
+        } else {
+          RelationalOperator _operator_2 = expression.getOperator();
+          boolean _operator_notEquals_2 = ObjectExtensions.operator_notEquals(_operator_2, RelationalOperator.NOT_EQUALS);
+          _operator_and_1 = BooleanExtensions.operator_and(_operator_notEquals_1, _operator_notEquals_2);
+        }
+        if (_operator_and_1) {
+          RelationalOperator _operator_3 = expression.getOperator();
+          String _literal_1 = _operator_3.getLiteral();
+          String _operator_plus_6 = StringExtensions.operator_plus("operator \'", _literal_1);
+          String _operator_plus_7 = StringExtensions.operator_plus(_operator_plus_6, "\' can not be applied to boolean values!");
+          this.error(_operator_plus_7);
+        }
+      }
+      return java.lang.Boolean.class;
+    }
+  }
+  
+  protected Class<? extends Object> _check(final NumericalAddSubtractExpression expression) throws TypeCheckException {
+    Class<Number> _xblockexpression = null;
+    {
+      Expression _leftOperand = expression.getLeftOperand();
+      Class<? extends Object> _check = this.check(_leftOperand);
+      AdditiveOperator _operator = expression.getOperator();
+      String _literal = _operator.getLiteral();
+      this.assertIsNumber(_check, _literal);
+      Expression _rightOperand = expression.getRightOperand();
+      Class<? extends Object> _check_1 = this.check(_rightOperand);
+      AdditiveOperator _operator_1 = expression.getOperator();
+      String _literal_1 = _operator_1.getLiteral();
+      this.assertIsNumber(_check_1, _literal_1);
+      _xblockexpression = (java.lang.Number.class);
+    }
+    return _xblockexpression;
+  }
+  
+  protected Class<? extends Object> _check(final NumericalMultiplyDivideExpression expression) throws TypeCheckException {
+    Class<Number> _xblockexpression = null;
+    {
+      Expression _leftOperand = expression.getLeftOperand();
+      Class<? extends Object> _check = this.check(_leftOperand);
+      MultiplicativeOperator _operator = expression.getOperator();
+      String _literal = _operator.getLiteral();
+      this.assertIsNumber(_check, _literal);
+      Expression _rightOperand = expression.getRightOperand();
+      Class<? extends Object> _check_1 = this.check(_rightOperand);
+      MultiplicativeOperator _operator_1 = expression.getOperator();
+      String _literal_1 = _operator_1.getLiteral();
+      this.assertIsNumber(_check_1, _literal_1);
+      _xblockexpression = (java.lang.Number.class);
+    }
+    return _xblockexpression;
+  }
+  
+  protected Class<? extends Object> _check(final NumericalUnaryExpression expression) throws TypeCheckException {
+    Class<Number> _xblockexpression = null;
+    {
+      Expression _operand = expression.getOperand();
+      Class<? extends Object> _check = this.check(_operand);
+      UnaryOperator _operator = expression.getOperator();
+      String _literal = _operator.getLiteral();
+      this.assertIsNumber(_check, _literal);
+      _xblockexpression = (java.lang.Number.class);
+    }
+    return _xblockexpression;
+  }
+  
+  protected Class<? extends Object> _check(final PrimitiveValueExpression expression) {
+    Literal _value = expression.getValue();
+    Class<? extends Serializable> _type = this.type(_value);
+    return _type;
+  }
+  
+  protected Class<? extends Object> _check(final ShiftExpression expression) {
+    return null;
+  }
+  
+  protected Class<? extends Object> _check(final ConditionalExpression expression) {
+    return null;
+  }
+  
+  protected Class<? extends Object> _check(final ElementReferenceExpression expression) {
+    {
+      Declaration _value = expression.getValue();
+      Declaration declaration = _value;
+      if ((declaration instanceof org.yakindu.sct.model.stext.stext.VariableDefinition)) {
+        Type _type = ((VariableDefinition) declaration).getType();
+        Class<? extends Object> _javaType = this.toJavaType(_type);
+        return _javaType;
+      }
+      return null;
+    }
+  }
+  
+  protected Class<? extends Object> _check(final EventRaisedReferenceExpression expression) {
+    return null;
+  }
+  
+  protected Class<? extends Object> _check(final EventValueReferenceExpression expression) {
+    return null;
+  }
+  
+  protected Class<? extends Serializable> _type(final IntLiteral literal) {
+    return java.lang.Number.class;
+  }
+  
+  protected Class<? extends Serializable> _type(final BoolLiteral bool) {
+    return java.lang.Boolean.class;
+  }
+  
+  protected Class<? extends Serializable> _type(final RealLiteral literal) {
+    return java.lang.Number.class;
+  }
+  
+  public Class<? extends Object> toJavaType(final Type type) {
+    {
+      final Type type_1 = type;
+      boolean matched = false;
+      if (!matched) {
+        if (org.eclipse.xtext.xbase.lib.ObjectExtensions.operator_equals(type_1,Type.BOOLEAN)) {
+          matched=true;
+          return java.lang.Boolean.class;
+        }
+      }
+      if (!matched) {
+        if (org.eclipse.xtext.xbase.lib.ObjectExtensions.operator_equals(type_1,Type.INTEGER)) {
+          matched=true;
+          return java.lang.Number.class;
+        }
+      }
+      if (!matched) {
+        if (org.eclipse.xtext.xbase.lib.ObjectExtensions.operator_equals(type_1,Type.REAL)) {
+          matched=true;
+          return java.lang.Number.class;
+        }
+      }
+      return java.lang.Void.class;
+    }
+  }
+  
+  public Object assertIsNumber(final Object object, final String operator) throws TypeCheckException {
+    Object _xifexpression = null;
+    boolean _operator_equals = ObjectExtensions.operator_equals(object, java.lang.Number.class);
+    boolean _operator_not = BooleanExtensions.operator_not(_operator_equals);
+    if (_operator_not) {
+      String _operator_plus = StringExtensions.operator_plus("operator \'", operator);
+      String _operator_plus_1 = StringExtensions.operator_plus(_operator_plus, "\' can only be applied to numbers!");
+      this.error(_operator_plus_1);
+    }
+    return _xifexpression;
+  }
+  
+  public Object assertIsBoolean(final Object object, final String operator) throws TypeCheckException {
+    Object _xifexpression = null;
+    boolean _operator_equals = ObjectExtensions.operator_equals(object, java.lang.Boolean.class);
+    boolean _operator_not = BooleanExtensions.operator_not(_operator_equals);
+    if (_operator_not) {
+      String _operator_plus = StringExtensions.operator_plus("operator \'", operator);
+      String _operator_plus_1 = StringExtensions.operator_plus(_operator_plus, "\' can only ne applied to boolean values!");
+      this.error(_operator_plus_1);
+    }
+    return _xifexpression;
+  }
+  
+  public void error(final String msg) throws TypeCheckException {
+    TypeCheckException _typeCheckException = new TypeCheckException(msg);
+    throw _typeCheckException;
+  }
+  
+  public Class<? extends Object> check(final Statement expression) throws TypeCheckException {
+    if ((expression instanceof BitwiseAndExpression)) {
+      return _check((BitwiseAndExpression)expression);
+    } else if ((expression instanceof BitwiseOrExpression)) {
+      return _check((BitwiseOrExpression)expression);
+    } else if ((expression instanceof BitwiseXorExpression)) {
+      return _check((BitwiseXorExpression)expression);
+    } else if ((expression instanceof ConditionalExpression)) {
+      return _check((ConditionalExpression)expression);
+    } else if ((expression instanceof ElementReferenceExpression)) {
+      return _check((ElementReferenceExpression)expression);
+    } else if ((expression instanceof EventRaisedReferenceExpression)) {
+      return _check((EventRaisedReferenceExpression)expression);
+    } else if ((expression instanceof EventValueReferenceExpression)) {
+      return _check((EventValueReferenceExpression)expression);
+    } else if ((expression instanceof LogicalAndExpression)) {
+      return _check((LogicalAndExpression)expression);
+    } else if ((expression instanceof LogicalNotExpression)) {
+      return _check((LogicalNotExpression)expression);
+    } else if ((expression instanceof LogicalOrExpression)) {
+      return _check((LogicalOrExpression)expression);
+    } else if ((expression instanceof LogicalRelationExpression)) {
+      return _check((LogicalRelationExpression)expression);
+    } else if ((expression instanceof NumericalAddSubtractExpression)) {
+      return _check((NumericalAddSubtractExpression)expression);
+    } else if ((expression instanceof NumericalMultiplyDivideExpression)) {
+      return _check((NumericalMultiplyDivideExpression)expression);
+    } else if ((expression instanceof NumericalUnaryExpression)) {
+      return _check((NumericalUnaryExpression)expression);
+    } else if ((expression instanceof PrimitiveValueExpression)) {
+      return _check((PrimitiveValueExpression)expression);
+    } else if ((expression instanceof ShiftExpression)) {
+      return _check((ShiftExpression)expression);
+    } else if ((expression instanceof Assignment)) {
+      return _check((Assignment)expression);
+    } else if ((expression instanceof EventRaising)) {
+      return _check((EventRaising)expression);
+    } else {
+      throw new IllegalArgumentException("Unhandled parameter types: " +
+        java.util.Arrays.<Object>asList(expression).toString());
+    }
+  }
+  
+  public Class<? extends Serializable> type(final Literal bool) {
+    if ((bool instanceof BoolLiteral)) {
+      return _type((BoolLiteral)bool);
+    } else if ((bool instanceof IntLiteral)) {
+      return _type((IntLiteral)bool);
+    } else if ((bool instanceof RealLiteral)) {
+      return _type((RealLiteral)bool);
+    } else {
+      throw new IllegalArgumentException("Unhandled parameter types: " +
+        java.util.Arrays.<Object>asList(bool).toString());
+    }
+  }
+}