ソースを参照

Adopted type system to support concatination of strings and type
conversion for integer, boolean and real to string in context of
NumericalAddSubstractExpression #108

muelder 10 年 前
コミット
9dab3030be

+ 284 - 275
plugins/org.yakindu.base.expressions/src/org/yakindu/base/expressions/inferrer/ExpressionsTypeInferrer.java

@@ -1,275 +1,284 @@
-/**
- * Copyright (c) 2014 committers of YAKINDU 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:
- * 	committers of YAKINDU - initial API and implementation
- * 
- */
-package org.yakindu.base.expressions.inferrer;
-
-import static org.yakindu.base.types.typesystem.ITypeSystem.BOOLEAN;
-import static org.yakindu.base.types.typesystem.ITypeSystem.INTEGER;
-import static org.yakindu.base.types.typesystem.ITypeSystem.NULL;
-import static org.yakindu.base.types.typesystem.ITypeSystem.REAL;
-import static org.yakindu.base.types.typesystem.ITypeSystem.STRING;
-import static org.yakindu.base.types.typesystem.ITypeSystem.VOID;
-
-import org.eclipse.emf.common.util.EList;
-import org.eclipse.xtext.EcoreUtil2;
-import org.yakindu.base.expressions.expressions.AssignmentExpression;
-import org.yakindu.base.expressions.expressions.BitwiseAndExpression;
-import org.yakindu.base.expressions.expressions.BitwiseOrExpression;
-import org.yakindu.base.expressions.expressions.BitwiseXorExpression;
-import org.yakindu.base.expressions.expressions.BoolLiteral;
-import org.yakindu.base.expressions.expressions.ConditionalExpression;
-import org.yakindu.base.expressions.expressions.DoubleLiteral;
-import org.yakindu.base.expressions.expressions.ElementReferenceExpression;
-import org.yakindu.base.expressions.expressions.Expression;
-import org.yakindu.base.expressions.expressions.FeatureCall;
-import org.yakindu.base.expressions.expressions.FloatLiteral;
-import org.yakindu.base.expressions.expressions.HexLiteral;
-import org.yakindu.base.expressions.expressions.IntLiteral;
-import org.yakindu.base.expressions.expressions.LogicalAndExpression;
-import org.yakindu.base.expressions.expressions.LogicalNotExpression;
-import org.yakindu.base.expressions.expressions.LogicalOrExpression;
-import org.yakindu.base.expressions.expressions.LogicalRelationExpression;
-import org.yakindu.base.expressions.expressions.NullLiteral;
-import org.yakindu.base.expressions.expressions.NumericalAddSubtractExpression;
-import org.yakindu.base.expressions.expressions.NumericalMultiplyDivideExpression;
-import org.yakindu.base.expressions.expressions.NumericalUnaryExpression;
-import org.yakindu.base.expressions.expressions.ParenthesizedExpression;
-import org.yakindu.base.expressions.expressions.PrimitiveValueExpression;
-import org.yakindu.base.expressions.expressions.ShiftExpression;
-import org.yakindu.base.expressions.expressions.StringLiteral;
-import org.yakindu.base.expressions.expressions.TypeCastExpression;
-import org.yakindu.base.expressions.expressions.UnaryOperator;
-import org.yakindu.base.types.EnumerationType;
-import org.yakindu.base.types.Enumerator;
-import org.yakindu.base.types.Operation;
-import org.yakindu.base.types.Parameter;
-import org.yakindu.base.types.Property;
-import org.yakindu.base.types.Type;
-import org.yakindu.base.types.TypeAlias;
-import org.yakindu.base.types.inferrer.AbstractTypeSystemInferrer;
-
-/**
- * @author andreas muelder - Initial contribution and API
- * 
- */
-public class ExpressionsTypeInferrer extends AbstractTypeSystemInferrer implements ExpressionsTypeInferrerMessages {
-
-	public Type infer(AssignmentExpression e) {
-		Type type1 = inferTypeDispatch(e.getVarRef());
-		Type type2 = inferTypeDispatch(e.getExpression());
-		assertAssignable(type1, type2, String.format(ASSIGNMENT_OPERATOR, e.getOperator(), type1, type2));
-		return inferTypeDispatch(e.getVarRef());
-	}
-
-	public Type infer(ConditionalExpression e) {
-		Type type1 = inferTypeDispatch(e.getTrueCase());
-		Type type2 = inferTypeDispatch(e.getFalseCase());
-		assertCompatible(type1, type2, String.format(COMMON_TYPE, type1, type2));
-		assertIsType(inferTypeDispatch(e.getCondition()), CONDITIONAL_BOOLEAN, getType(BOOLEAN));
-		return getCommonType(type1, type2);
-	}
-
-	public Type infer(LogicalOrExpression e) {
-		Type type1 = inferTypeDispatch(e.getLeftOperand());
-		Type type2 = inferTypeDispatch(e.getRightOperand());
-		assertIsType(type1, String.format(LOGICAL_OPERATORS, "||", type1, type2), getType(BOOLEAN));
-		assertIsType(type2, String.format(LOGICAL_OPERATORS, "||", type1, type2), getType(BOOLEAN));
-		return getType(BOOLEAN);
-	}
-
-	public Type infer(LogicalAndExpression e) {
-		Type type1 = inferTypeDispatch(e.getLeftOperand());
-		Type type2 = inferTypeDispatch(e.getRightOperand());
-		assertIsType(type1, String.format(LOGICAL_OPERATORS, "&&", type1, type2), getType(BOOLEAN));
-		assertIsType(type2, String.format(LOGICAL_OPERATORS, "&&", type1, type2), getType(BOOLEAN));
-		return getType(BOOLEAN);
-	}
-
-	public Type infer(LogicalNotExpression e) {
-		Type type = inferTypeDispatch(e.getOperand());
-		assertIsType(type, String.format(LOGICAL_OPERATOR, "!", type), getType(BOOLEAN));
-		return getType(BOOLEAN);
-	}
-
-	public Type infer(BitwiseXorExpression e) {
-		Type type1 = inferTypeDispatch(e.getLeftOperand());
-		Type type2 = inferTypeDispatch(e.getRightOperand());
-		assertIsType(type1, String.format(BITWISE_OPERATORS, "^", type1, type2), getType(INTEGER));
-		assertIsType(type2, String.format(BITWISE_OPERATORS, "^", type1, type2), getType(INTEGER));
-		return getType(INTEGER);
-	}
-
-	public Type infer(BitwiseOrExpression e) {
-		Type type1 = inferTypeDispatch(e.getLeftOperand());
-		Type type2 = inferTypeDispatch(e.getRightOperand());
-		assertIsType(type1, String.format(BITWISE_OPERATORS, "|", type1, type2), getType(INTEGER));
-		assertIsType(type2, String.format(BITWISE_OPERATORS, "|", type1, type2), getType(INTEGER));
-		return getType(INTEGER);
-	}
-
-	public Type infer(BitwiseAndExpression e) {
-		Type type1 = inferTypeDispatch(e.getLeftOperand());
-		Type type2 = inferTypeDispatch(e.getRightOperand());
-		assertIsType(type1, String.format(BITWISE_OPERATORS, "&", type1, type2), getType(INTEGER));
-		assertIsType(type2, String.format(BITWISE_OPERATORS, "&", type1, type2), getType(INTEGER));
-		return getType(INTEGER);
-	}
-
-	public Type infer(ShiftExpression e) {
-		Type type1 = inferTypeDispatch(e.getLeftOperand());
-		Type type2 = inferTypeDispatch(e.getRightOperand());
-		assertIsType(type1, String.format(BITWISE_OPERATORS, e.getOperator(), type1, type2), getType(INTEGER));
-		assertIsType(type2, String.format(BITWISE_OPERATORS, e.getOperator(), type1, type2), getType(INTEGER));
-		return getType(INTEGER);
-	}
-
-	public Type infer(LogicalRelationExpression e) {
-		Type type1 = inferTypeDispatch(e.getLeftOperand());
-		Type type2 = inferTypeDispatch(e.getRightOperand());
-		assertCompatible(type1, type2, String.format(COMPARSION_OPERATOR, e.getOperator(), type1, type2));
-		Type result = getType(BOOLEAN);
-		return result;
-
-	}
-
-	public Type infer(NumericalAddSubtractExpression e) {
-		Type type1 = inferTypeDispatch(e.getLeftOperand());
-		Type type2 = inferTypeDispatch(e.getRightOperand());
-		assertCompatible(type1, type2, String.format(ARITHMETIC_OPERATORS, e.getOperator(), type1, type2));
-		assertIsType(type1, String.format(ARITHMETIC_OPERATORS, e.getOperator(), type1, type2), getType(INTEGER),
-				getType(REAL));
-		return getCommonType(e.getLeftOperand(), e.getRightOperand());
-	}
-
-	public Type infer(NumericalMultiplyDivideExpression e) {
-		Type type1 = inferTypeDispatch(e.getLeftOperand());
-		Type type2 = inferTypeDispatch(e.getRightOperand());
-		assertCompatible(type1, type2, String.format(ARITHMETIC_OPERATORS, e.getOperator(), type1, type2));
-		assertIsType(type1, String.format(ARITHMETIC_OPERATORS, e.getOperator(), type1, type2), getType(INTEGER),
-				getType(REAL));
-		return getCommonType(type1, type2);
-	}
-
-	public Type infer(NumericalUnaryExpression e) {
-		Type type1 = inferTypeDispatch(e.getOperand());
-		if (e.getOperator() == UnaryOperator.COMPLEMENT)
-			assertIsType(type1, String.format(BITWISE_OPERATOR, '~', type1), getType(INTEGER));
-		else {
-			assertCompatible(type1, getType(REAL), String.format(ARITHMETIC_OPERATOR, e.getOperator(), type1));
-		}
-		return type1;
-	}
-
-	public Type infer(TypeCastExpression e) {
-		Type type1 = inferTypeDispatch(e.getOperand());
-		Type type2 = inferTypeDispatch(e.getType());
-		assertCompatible(type1, type2, String.format(CAST_OPERATORS, type1, type2));
-		return inferTypeDispatch(e.getType());
-	}
-
-	public Type infer(EnumerationType enumType) {
-		return enumType;
-	}
-
-	public Type infer(Enumerator enumerator) {
-		return EcoreUtil2.getContainerOfType(enumerator, Type.class);
-	}
-
-	public Type infer(Type type) {
-		return type;
-	}
-
-	// TODO: How to handle TypeAlias, like in C as weak types or like Lint
-	// strong types?
-	public Object infer(TypeAlias typeAlias) {
-		return inferTypeDispatch(typeAlias.getType());
-	}
-
-	public Type infer(FeatureCall e) {
-		if (e.isOperationCall()) {
-			Operation operation = (Operation) e.getFeature();
-			EList<Parameter> parameters = operation.getParameters();
-			EList<Expression> args = e.getArgs();
-			inferParameter(parameters, args);
-		}
-		return inferTypeDispatch(e.getFeature());
-	}
-
-	public Type infer(ElementReferenceExpression e) {
-		if (e.isOperationCall()) {
-			Operation operation = (Operation) e.getReference();
-			EList<Parameter> parameters = operation.getParameters();
-			EList<Expression> args = e.getArgs();
-			inferParameter(parameters, args);
-		}
-		return inferTypeDispatch(e.getReference());
-	}
-
-	protected void inferParameter(EList<Parameter> parameters, EList<Expression> args) {
-		if (parameters.size() == args.size()) {
-			for (int i = 0; i < parameters.size(); i++) {
-				Type type1 = inferTypeDispatch(parameters.get(i));
-				Type type2 = inferTypeDispatch(args.get(i));
-				assertCompatible(type2, type1, String.format(INCOMPATIBLE_TYPES, type2, type1));
-			}
-		}
-	}
-
-	public Type infer(ParenthesizedExpression e) {
-		return inferTypeDispatch(e.getExpression());
-	}
-
-	public Type infer(PrimitiveValueExpression e) {
-		return inferTypeDispatch(e.getValue());
-	}
-
-	public Type infer(BoolLiteral literal) {
-		return getType(BOOLEAN);
-	}
-
-	public Type infer(IntLiteral literal) {
-		return getType(INTEGER);
-	}
-
-	public Type infer(HexLiteral literal) {
-		return getType(INTEGER);
-	}
-
-	public Type infer(DoubleLiteral literal) {
-		return getType(REAL);
-	}
-	
-	public Type infer(FloatLiteral literal){
-		return getType(REAL);
-	}
-
-	public Type infer(StringLiteral literal) {
-		return getType(STRING);
-	}
-
-	public Type infer(NullLiteral literal) {
-		return getType(NULL);
-	}
-
-	public Object infer(Property p) {
-		Type type = inferTypeDispatch(p.getType());
-		assertNotType(type, VARIABLE_VOID_TYPE, getType(VOID));
-		return inferTypeDispatch(type);
-
-	}
-
-	public Object infer(Operation e) {
-		return inferTypeDispatch(e.getType() != null ? e.getType() : getType(VOID));
-	}
-
-	public Object infer(Parameter e) {
-		return inferTypeDispatch(e.getType());
-	}
-}
+/**
+ * Copyright (c) 2014 committers of YAKINDU 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:
+ * 	committers of YAKINDU - initial API and implementation
+ * 
+ */
+package org.yakindu.base.expressions.inferrer;
+
+import static org.yakindu.base.types.typesystem.ITypeSystem.BOOLEAN;
+import static org.yakindu.base.types.typesystem.ITypeSystem.INTEGER;
+import static org.yakindu.base.types.typesystem.ITypeSystem.NULL;
+import static org.yakindu.base.types.typesystem.ITypeSystem.REAL;
+import static org.yakindu.base.types.typesystem.ITypeSystem.STRING;
+import static org.yakindu.base.types.typesystem.ITypeSystem.VOID;
+
+import org.eclipse.emf.common.util.EList;
+import org.eclipse.xtext.EcoreUtil2;
+import org.yakindu.base.expressions.expressions.AssignmentExpression;
+import org.yakindu.base.expressions.expressions.BitwiseAndExpression;
+import org.yakindu.base.expressions.expressions.BitwiseOrExpression;
+import org.yakindu.base.expressions.expressions.BitwiseXorExpression;
+import org.yakindu.base.expressions.expressions.BoolLiteral;
+import org.yakindu.base.expressions.expressions.ConditionalExpression;
+import org.yakindu.base.expressions.expressions.DoubleLiteral;
+import org.yakindu.base.expressions.expressions.ElementReferenceExpression;
+import org.yakindu.base.expressions.expressions.Expression;
+import org.yakindu.base.expressions.expressions.FeatureCall;
+import org.yakindu.base.expressions.expressions.FloatLiteral;
+import org.yakindu.base.expressions.expressions.HexLiteral;
+import org.yakindu.base.expressions.expressions.IntLiteral;
+import org.yakindu.base.expressions.expressions.LogicalAndExpression;
+import org.yakindu.base.expressions.expressions.LogicalNotExpression;
+import org.yakindu.base.expressions.expressions.LogicalOrExpression;
+import org.yakindu.base.expressions.expressions.LogicalRelationExpression;
+import org.yakindu.base.expressions.expressions.NullLiteral;
+import org.yakindu.base.expressions.expressions.NumericalAddSubtractExpression;
+import org.yakindu.base.expressions.expressions.NumericalMultiplyDivideExpression;
+import org.yakindu.base.expressions.expressions.NumericalUnaryExpression;
+import org.yakindu.base.expressions.expressions.ParenthesizedExpression;
+import org.yakindu.base.expressions.expressions.PrimitiveValueExpression;
+import org.yakindu.base.expressions.expressions.ShiftExpression;
+import org.yakindu.base.expressions.expressions.StringLiteral;
+import org.yakindu.base.expressions.expressions.TypeCastExpression;
+import org.yakindu.base.expressions.expressions.UnaryOperator;
+import org.yakindu.base.types.EnumerationType;
+import org.yakindu.base.types.Enumerator;
+import org.yakindu.base.types.Operation;
+import org.yakindu.base.types.Parameter;
+import org.yakindu.base.types.Property;
+import org.yakindu.base.types.Type;
+import org.yakindu.base.types.TypeAlias;
+import org.yakindu.base.types.inferrer.AbstractTypeSystemInferrer;
+
+/**
+ * @author andreas muelder - Initial contribution and API
+ * 
+ */
+public class ExpressionsTypeInferrer extends AbstractTypeSystemInferrer implements ExpressionsTypeInferrerMessages {
+
+	public Type infer(AssignmentExpression e) {
+		Type type1 = inferTypeDispatch(e.getVarRef());
+		Type type2 = inferTypeDispatch(e.getExpression());
+		assertAssignable(type1, type2, String.format(ASSIGNMENT_OPERATOR, e.getOperator(), type1, type2));
+		return inferTypeDispatch(e.getVarRef());
+	}
+
+	public Type infer(ConditionalExpression e) {
+		Type type1 = inferTypeDispatch(e.getTrueCase());
+		Type type2 = inferTypeDispatch(e.getFalseCase());
+		assertCompatible(type1, type2, String.format(COMMON_TYPE, type1, type2));
+		assertIsType(inferTypeDispatch(e.getCondition()), CONDITIONAL_BOOLEAN, getType(BOOLEAN));
+		return getCommonType(type1, type2);
+	}
+
+	public Type infer(LogicalOrExpression e) {
+		Type type1 = inferTypeDispatch(e.getLeftOperand());
+		Type type2 = inferTypeDispatch(e.getRightOperand());
+		assertIsType(type1, String.format(LOGICAL_OPERATORS, "||", type1, type2), getType(BOOLEAN));
+		assertIsType(type2, String.format(LOGICAL_OPERATORS, "||", type1, type2), getType(BOOLEAN));
+		return getType(BOOLEAN);
+	}
+
+	public Type infer(LogicalAndExpression e) {
+		Type type1 = inferTypeDispatch(e.getLeftOperand());
+		Type type2 = inferTypeDispatch(e.getRightOperand());
+		assertIsType(type1, String.format(LOGICAL_OPERATORS, "&&", type1, type2), getType(BOOLEAN));
+		assertIsType(type2, String.format(LOGICAL_OPERATORS, "&&", type1, type2), getType(BOOLEAN));
+		return getType(BOOLEAN);
+	}
+
+	public Type infer(LogicalNotExpression e) {
+		Type type = inferTypeDispatch(e.getOperand());
+		assertIsType(type, String.format(LOGICAL_OPERATOR, "!", type), getType(BOOLEAN));
+		return getType(BOOLEAN);
+	}
+
+	public Type infer(BitwiseXorExpression e) {
+		Type type1 = inferTypeDispatch(e.getLeftOperand());
+		Type type2 = inferTypeDispatch(e.getRightOperand());
+		assertIsType(type1, String.format(BITWISE_OPERATORS, "^", type1, type2), getType(INTEGER));
+		assertIsType(type2, String.format(BITWISE_OPERATORS, "^", type1, type2), getType(INTEGER));
+		return getType(INTEGER);
+	}
+
+	public Type infer(BitwiseOrExpression e) {
+		Type type1 = inferTypeDispatch(e.getLeftOperand());
+		Type type2 = inferTypeDispatch(e.getRightOperand());
+		assertIsType(type1, String.format(BITWISE_OPERATORS, "|", type1, type2), getType(INTEGER));
+		assertIsType(type2, String.format(BITWISE_OPERATORS, "|", type1, type2), getType(INTEGER));
+		return getType(INTEGER);
+	}
+
+	public Type infer(BitwiseAndExpression e) {
+		Type type1 = inferTypeDispatch(e.getLeftOperand());
+		Type type2 = inferTypeDispatch(e.getRightOperand());
+		assertIsType(type1, String.format(BITWISE_OPERATORS, "&", type1, type2), getType(INTEGER));
+		assertIsType(type2, String.format(BITWISE_OPERATORS, "&", type1, type2), getType(INTEGER));
+		return getType(INTEGER);
+	}
+
+	public Type infer(ShiftExpression e) {
+		Type type1 = inferTypeDispatch(e.getLeftOperand());
+		Type type2 = inferTypeDispatch(e.getRightOperand());
+		assertIsType(type1, String.format(BITWISE_OPERATORS, e.getOperator(), type1, type2), getType(INTEGER));
+		assertIsType(type2, String.format(BITWISE_OPERATORS, e.getOperator(), type1, type2), getType(INTEGER));
+		return getType(INTEGER);
+	}
+
+	public Type infer(LogicalRelationExpression e) {
+		Type type1 = inferTypeDispatch(e.getLeftOperand());
+		Type type2 = inferTypeDispatch(e.getRightOperand());
+		assertCompatible(type1, type2, String.format(COMPARSION_OPERATOR, e.getOperator(), type1, type2));
+		Type result = getType(BOOLEAN);
+		return result;
+
+	}
+
+	public Type infer(NumericalAddSubtractExpression e) {
+		Type type1 = inferTypeDispatch(e.getLeftOperand());
+		Type type2 = inferTypeDispatch(e.getRightOperand());
+		if (registry.isSame(type1, getType(STRING))) {
+			assertCompatibleWithConversion(type1, type2, String.format(CAN_NOT_CONVERT, type2, type1));
+			return getType(STRING);
+		} else {
+			assertCompatible(type1, type2, String.format(ARITHMETIC_OPERATORS, e.getOperator(), type1, type2));
+			assertIsType(type1, String.format(ARITHMETIC_OPERATORS, e.getOperator(), type1, type2), getType(INTEGER),
+					getType(REAL));
+			assertIsType(type2, String.format(ARITHMETIC_OPERATORS, e.getOperator(), type1, type2), getType(INTEGER),
+					getType(REAL));
+			return getCommonType(e.getLeftOperand(), e.getRightOperand());
+		}
+	}
+
+	public Type infer(NumericalMultiplyDivideExpression e) {
+		Type type1 = inferTypeDispatch(e.getLeftOperand());
+		Type type2 = inferTypeDispatch(e.getRightOperand());
+		assertCompatible(type1, type2, String.format(ARITHMETIC_OPERATORS, e.getOperator(), type1, type2));
+		assertIsType(type1, String.format(ARITHMETIC_OPERATORS, e.getOperator(), type1, type2), getType(INTEGER),
+				getType(REAL));
+		assertIsType(type2, String.format(ARITHMETIC_OPERATORS, e.getOperator(), type1, type2), getType(INTEGER),
+				getType(REAL));
+		return getCommonType(type1, type2);
+	}
+
+	public Type infer(NumericalUnaryExpression e) {
+		Type type1 = inferTypeDispatch(e.getOperand());
+		if (e.getOperator() == UnaryOperator.COMPLEMENT)
+			assertIsType(type1, String.format(BITWISE_OPERATOR, '~', type1), getType(INTEGER));
+		else {
+			assertCompatible(type1, getType(REAL), String.format(ARITHMETIC_OPERATOR, e.getOperator(), type1));
+		}
+		return type1;
+	}
+
+	public Type infer(TypeCastExpression e) {
+		Type type1 = inferTypeDispatch(e.getOperand());
+		Type type2 = inferTypeDispatch(e.getType());
+		assertAssignable(type1, type2, String.format(CAST_OPERATORS, type1, type2));
+		return inferTypeDispatch(e.getType());
+	}
+
+	public Type infer(EnumerationType enumType) {
+		return enumType;
+	}
+
+	public Type infer(Enumerator enumerator) {
+		return EcoreUtil2.getContainerOfType(enumerator, Type.class);
+	}
+
+	public Type infer(Type type) {
+		return type;
+	}
+
+	// TODO: How to handle TypeAlias, like in C as weak types or like Lint
+	// strong types?
+	public Object infer(TypeAlias typeAlias) {
+		return inferTypeDispatch(typeAlias.getType());
+	}
+
+	public Type infer(FeatureCall e) {
+		if (e.isOperationCall()) {
+			Operation operation = (Operation) e.getFeature();
+			EList<Parameter> parameters = operation.getParameters();
+			EList<Expression> args = e.getArgs();
+			inferParameter(parameters, args);
+		}
+		return inferTypeDispatch(e.getFeature());
+	}
+
+	public Type infer(ElementReferenceExpression e) {
+		if (e.isOperationCall()) {
+			Operation operation = (Operation) e.getReference();
+			EList<Parameter> parameters = operation.getParameters();
+			EList<Expression> args = e.getArgs();
+			inferParameter(parameters, args);
+		}
+		return inferTypeDispatch(e.getReference());
+	}
+
+	protected void inferParameter(EList<Parameter> parameters, EList<Expression> args) {
+		if (parameters.size() == args.size()) {
+			for (int i = 0; i < parameters.size(); i++) {
+				Type type1 = inferTypeDispatch(parameters.get(i));
+				Type type2 = inferTypeDispatch(args.get(i));
+				assertCompatible(type2, type1, String.format(INCOMPATIBLE_TYPES, type2, type1));
+			}
+		}
+	}
+
+	public Type infer(ParenthesizedExpression e) {
+		return inferTypeDispatch(e.getExpression());
+	}
+
+	public Type infer(PrimitiveValueExpression e) {
+		return inferTypeDispatch(e.getValue());
+	}
+
+	public Type infer(BoolLiteral literal) {
+		return getType(BOOLEAN);
+	}
+
+	public Type infer(IntLiteral literal) {
+		return getType(INTEGER);
+	}
+
+	public Type infer(HexLiteral literal) {
+		return getType(INTEGER);
+	}
+
+	public Type infer(DoubleLiteral literal) {
+		return getType(REAL);
+	}
+
+	public Type infer(FloatLiteral literal) {
+		return getType(REAL);
+	}
+
+	public Type infer(StringLiteral literal) {
+		return getType(STRING);
+	}
+
+	public Type infer(NullLiteral literal) {
+		return getType(NULL);
+	}
+
+	public Object infer(Property p) {
+		Type type = inferTypeDispatch(p.getType());
+		assertNotType(type, VARIABLE_VOID_TYPE, getType(VOID));
+		return inferTypeDispatch(type);
+
+	}
+
+	public Object infer(Operation e) {
+		return inferTypeDispatch(e.getType() != null ? e.getType() : getType(VOID));
+	}
+
+	public Object infer(Parameter e) {
+		return inferTypeDispatch(e.getType());
+	}
+}

+ 34 - 33
plugins/org.yakindu.base.expressions/src/org/yakindu/base/expressions/inferrer/ExpressionsTypeInferrerMessages.java

@@ -1,33 +1,34 @@
-/**
- * Copyright (c) 2014 committers of YAKINDU 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:
- * 	committers of YAKINDU - initial API and implementation
- * 
- */
-package org.yakindu.base.expressions.inferrer;
-
-/**
- * @author andreas muelder - Initial contribution and API
- * 
- */
-public interface ExpressionsTypeInferrerMessages {
-
-	public static final String LOGICAL_OPERATOR = "Logical operator '%s' may only be applied on boolean types, not on %s.";
-	public static final String LOGICAL_OPERATORS = "Logical operator '%s' may only be applied on boolean types, not on %s and %s.";
-	public static final String COMPARSION_OPERATOR = "Comparison operator '%s' may only be applied on compatible types, not on %s and %s.";
-	public static final String BITWISE_OPERATOR = "Bitwise operator '%s' may only be applied on integer types, not on %s.";
-	public static final String BITWISE_OPERATORS = "Bitwise operator '%s' may only be applied on integer types, not on %s and %s.";
-	public static final String ASSIGNMENT_OPERATOR = "Assignment operator '%s' may only be applied on compatible types, not on %s and %s.";
-	public static final String ARITHMETIC_OPERATOR = "Arithmetic operator '%s' may only be applied on numeric types, not on %s.";
-	public static final String ARITHMETIC_OPERATORS = "Arithmetic operator '%s' may only be applied on numeric types, not on %s and %s.";
-	public static final String COMMON_TYPE = "Could not determine a common type for %s and %s.";
-	public static final String CONDITIONAL_BOOLEAN = "conditional expression must be of type boolean.";
-	public static final String CAST_OPERATORS = "Cannot cast from %s to %s.";
-	public static final String INCOMPATIBLE_TYPES = "Incompatible types %s and %s.";
-	public static final String VARIABLE_VOID_TYPE = "'void' is an invalid type for variables";
-
-}
+/**
+ * Copyright (c) 2014 committers of YAKINDU 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:
+ * 	committers of YAKINDU - initial API and implementation
+ * 
+ */
+package org.yakindu.base.expressions.inferrer;
+
+/**
+ * @author andreas muelder - Initial contribution and API
+ * 
+ */
+public interface ExpressionsTypeInferrerMessages {
+
+	public static final String LOGICAL_OPERATOR = "Logical operator '%s' may only be applied on boolean types, not on %s.";
+	public static final String LOGICAL_OPERATORS = "Logical operator '%s' may only be applied on boolean types, not on %s and %s.";
+	public static final String COMPARSION_OPERATOR = "Comparison operator '%s' may only be applied on compatible types, not on %s and %s.";
+	public static final String BITWISE_OPERATOR = "Bitwise operator '%s' may only be applied on integer types, not on %s.";
+	public static final String BITWISE_OPERATORS = "Bitwise operator '%s' may only be applied on integer types, not on %s and %s.";
+	public static final String ASSIGNMENT_OPERATOR = "Assignment operator '%s' may only be applied on compatible types, not on %s and %s.";
+	public static final String ARITHMETIC_OPERATOR = "Arithmetic operator '%s' may only be applied on numeric types, not on %s.";
+	public static final String ARITHMETIC_OPERATORS = "Arithmetic operator '%s' may only be applied on numeric types, not on %s and %s.";
+	public static final String COMMON_TYPE = "Could not determine a common type for %s and %s.";
+	public static final String CONDITIONAL_BOOLEAN = "conditional expression must be of type boolean.";
+	public static final String CAST_OPERATORS = "Cannot cast from %s to %s.";
+	public static final String CAN_NOT_CONVERT = "%s cannot be converted to '%s'.";
+	public static final String INCOMPATIBLE_TYPES = "Incompatible types %s and %s.";
+	public static final String VARIABLE_VOID_TYPE = "'void' is an invalid type for variables";
+
+}

+ 183 - 176
plugins/org.yakindu.base.types/src/org/yakindu/base/types/inferrer/AbstractTypeSystemInferrer.java

@@ -1,176 +1,183 @@
-/**
- * Copyright (c) 2014 committers of YAKINDU 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:
- * 	committers of YAKINDU - initial API and implementation
- * 
- */
-package org.yakindu.base.types.inferrer;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.xtext.util.PolymorphicDispatcher;
-import org.yakindu.base.types.Type;
-import org.yakindu.base.types.typesystem.ITypeSystem;
-import org.yakindu.base.types.validation.IValidationIssueAcceptor;
-import org.yakindu.base.types.validation.IValidationIssueAcceptor.ListBasedValidationIssueAcceptor;
-import org.yakindu.base.types.validation.IValidationIssueAcceptor.ValidationIssue;
-import org.yakindu.base.types.validation.IValidationIssueAcceptor.ValidationIssue.Severity;
-
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.inject.Inject;
-
-/**
- * @author andreas muelder - Initial contribution and API
- * 
- */
-public abstract class AbstractTypeSystemInferrer implements ITypeSystemInferrer {
-
-	private static final String NO_INFER_METHOD = "No infer method for type(s) %s";
-	private static final String ASSERT_IS_TYPE = "Expected one of %s, but was %s.";
-	private static final String ASSERT_NOT_TYPE = "Expected type is not %s.";
-	private static final String ASSERT_SAME = "Expected types %s and %s are same.";
-	private static final String ASSERT_COMPATIBLE = "Incompatible types %s and %s.";
-	
-	private static final String METHOD_NAME = "infer";
-
-	@Inject
-	private ITypeSystem registry;
-
-	private IValidationIssueAcceptor acceptor;
-
-	private PolymorphicDispatcher<Object> dispatcher;
-
-	private LoadingCache<EObject, Type> typeCache;
-
-	public AbstractTypeSystemInferrer() {
-		initDispatcher();
-	}
-
-	protected Type getType(String name) {
-		return registry.getType(name);
-	}
-
-	protected Type getCommonType(EObject object1, EObject object2) {
-		return registry.getCommonType(inferTypeDispatch(object1), inferTypeDispatch(object2));
-	}
-
-	@Override
-	public final Type inferType(EObject object, IValidationIssueAcceptor acceptor) {
-		initTypeCache(object);
-		this.acceptor = (acceptor != null ? acceptor : new ListBasedValidationIssueAcceptor());
-		Type result = inferTypeDispatch(object);
-		typeCache.invalidateAll();
-		return result;
-	}
-
-	protected Type inferTypeDispatch(EObject object) {
-		if (object == null || object.eIsProxy())
-			return null;
-		try {
-			return typeCache.get(object);
-		} catch (Exception e) {
-			// Ignore invalid expressions and recursions
-		}
-		return null;
-	}
-
-	private void initTypeCache(final EObject context) {
-		typeCache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader<EObject, Type>() {
-			public Type load(EObject key) {
-				if (key instanceof Type) {
-					Collection<Type> types = registry.getTypes(context);
-					for (Type type : types) {
-						if (registry.isSame((Type) key, type))
-							return type;
-					}
-				}
-				return (Type) (EObject) dispatcher.invoke(key);
-			}
-		});
-	}
-
-	protected void initDispatcher() {
-		dispatcher = new PolymorphicDispatcher<Object>(METHOD_NAME, 1, 1, Collections.singletonList(this),
-				new PolymorphicDispatcher.ErrorHandler<Object>() {
-					@Override
-					public Object handle(Object[] params, Throwable throwable) {
-						if (throwable instanceof NoSuchMethodError) {
-							warning(String.format(NO_INFER_METHOD, Arrays.toString(params)), NO_INFER_METHOD_CODE);
-						} else {
-							error(throwable.getMessage(), EXCEPTION_CODE);
-						}
-						return null;
-					}
-				});
-	}
-
-	protected void assertIsType(Type currentType, String msg, Type... candidates) {
-		if (currentType == null)
-			return;
-		boolean same = false;
-		for (Type type : candidates) {
-			if (registry.isSame(currentType, type)) {
-				same = true;
-			}
-		}
-		if (!same) {
-			error(msg != null ? msg : String.format(ASSERT_IS_TYPE, Arrays.toString(candidates), currentType),
-					IS_TYPE_CODE);
-		}
-	}
-
-	protected void assertNotType(Type currentType, String msg, Type... candidates) {
-		if (currentType == null)
-			return;
-		for (Type type : candidates) {
-			if (registry.isSame(currentType, type)) {
-				error(msg != null ? msg : String.format(ASSERT_NOT_TYPE, currentType), NOT_TYPE_CODE);
-			}
-		}
-	}
-
-	protected void assertSame(Type type1, Type type2, String msg) {
-		if (type1 == null || type2 == null)
-			return;
-		if (!registry.isSame(type1, type2)) {
-			error(msg != null ? msg : String.format(ASSERT_SAME, type1, type2), NOT_SAME_CODE);
-		}
-	}
-
-	protected void assertCompatible(Type type1, Type type2, String msg) {
-		if (type1 == null || type2 == null)
-			return;
-		if (!registry.haveCommonType(type1, type2)) {
-			error(msg != null ? msg : String.format(ASSERT_COMPATIBLE, type1, type2), NOT_COMPATIBLE_CODE);
-		}
-	}
-
-	protected void assertAssignable(Type varType, Type valueType, String msg) {
-		if (varType == null || valueType == null)
-			return;
-		if (!registry.isSuperType(valueType, varType)) {
-			error(msg != null ? msg : String.format(ASSERT_COMPATIBLE, varType, valueType), NOT_COMPATIBLE_CODE);
-		}
-	}
-
-	protected void info(String msg, String issueCode) {
-		acceptor.accept(new ValidationIssue(Severity.INFO, msg, issueCode));
-	}
-
-	protected void warning(String msg, String issueCode) {
-		acceptor.accept(new ValidationIssue(Severity.WARNING, msg, issueCode));
-	}
-
-	protected void error(String msg, String issueCode) {
-		acceptor.accept(new ValidationIssue(Severity.ERROR, msg, issueCode));
-	}
-}
+/**
+ * Copyright (c) 2014 committers of YAKINDU 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:
+ * 	committers of YAKINDU - initial API and implementation
+ * 
+ */
+package org.yakindu.base.types.inferrer;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.xtext.util.PolymorphicDispatcher;
+import org.yakindu.base.types.Type;
+import org.yakindu.base.types.typesystem.ITypeSystem;
+import org.yakindu.base.types.validation.IValidationIssueAcceptor;
+import org.yakindu.base.types.validation.IValidationIssueAcceptor.ListBasedValidationIssueAcceptor;
+import org.yakindu.base.types.validation.IValidationIssueAcceptor.ValidationIssue;
+import org.yakindu.base.types.validation.IValidationIssueAcceptor.ValidationIssue.Severity;
+
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.inject.Inject;
+
+/**
+ * @author andreas muelder - Initial contribution and API
+ * 
+ */
+public abstract class AbstractTypeSystemInferrer implements ITypeSystemInferrer {
+
+	private static final String NO_INFER_METHOD = "No infer method for type(s) %s";
+	private static final String ASSERT_IS_TYPE = "Expected one of %s, but was %s.";
+	private static final String ASSERT_NOT_TYPE = "Expected type is not %s.";
+	private static final String ASSERT_SAME = "Expected types %s and %s are same.";
+	private static final String ASSERT_COMPATIBLE = "Incompatible types %s and %s.";
+	
+	private static final String METHOD_NAME = "infer";
+
+	@Inject
+	protected ITypeSystem registry;
+
+	private IValidationIssueAcceptor acceptor;
+
+	private PolymorphicDispatcher<Object> dispatcher;
+
+	private LoadingCache<EObject, Type> typeCache;
+
+	public AbstractTypeSystemInferrer() {
+		initDispatcher();
+	}
+
+	protected Type getType(String name) {
+		return registry.getType(name);
+	}
+
+	protected Type getCommonType(EObject object1, EObject object2) {
+		return registry.getCommonType(inferTypeDispatch(object1), inferTypeDispatch(object2));
+	}
+
+	@Override
+	public final Type inferType(EObject object, IValidationIssueAcceptor acceptor) {
+		initTypeCache(object);
+		this.acceptor = (acceptor != null ? acceptor : new ListBasedValidationIssueAcceptor());
+		Type result = inferTypeDispatch(object);
+		typeCache.invalidateAll();
+		return result;
+	}
+
+	protected Type inferTypeDispatch(EObject object) {
+		if (object == null || object.eIsProxy())
+			return null;
+		try {
+			return typeCache.get(object);
+		} catch (Exception e) {
+			// Ignore invalid expressions and recursions
+		}
+		return null;
+	}
+
+	private void initTypeCache(final EObject context) {
+		typeCache = CacheBuilder.newBuilder().maximumSize(100).build(new CacheLoader<EObject, Type>() {
+			public Type load(EObject key) {
+				if (key instanceof Type) {
+					Collection<Type> types = registry.getTypes(context);
+					for (Type type : types) {
+						if (registry.isSame((Type) key, type))
+							return type;
+					}
+				}
+				return (Type) (EObject) dispatcher.invoke(key);
+			}
+		});
+	}
+
+	protected void initDispatcher() {
+		dispatcher = new PolymorphicDispatcher<Object>(METHOD_NAME, 1, 1, Collections.singletonList(this),
+				new PolymorphicDispatcher.ErrorHandler<Object>() {
+					@Override
+					public Object handle(Object[] params, Throwable throwable) {
+						if (throwable instanceof NoSuchMethodError) {
+							warning(String.format(NO_INFER_METHOD, Arrays.toString(params)), NO_INFER_METHOD_CODE);
+						} else {
+							error(throwable.getMessage(), EXCEPTION_CODE);
+						}
+						return null;
+					}
+				});
+	}
+
+	protected void assertIsType(Type currentType, String msg, Type... candidates) {
+		if (currentType == null)
+			return;
+		boolean same = false;
+		for (Type type : candidates) {
+			if (registry.isSame(currentType, type)) {
+				same = true;
+			}
+		}
+		if (!same) {
+			error(msg != null ? msg : String.format(ASSERT_IS_TYPE, Arrays.toString(candidates), currentType),
+					IS_TYPE_CODE);
+		}
+	}
+
+	protected void assertNotType(Type currentType, String msg, Type... candidates) {
+		if (currentType == null)
+			return;
+		for (Type type : candidates) {
+			if (registry.isSame(currentType, type)) {
+				error(msg != null ? msg : String.format(ASSERT_NOT_TYPE, currentType), NOT_TYPE_CODE);
+			}
+		}
+	}
+
+	protected void assertSame(Type type1, Type type2, String msg) {
+		if (type1 == null || type2 == null)
+			return;
+		if (!registry.isSame(type1, type2)) {
+			error(msg != null ? msg : String.format(ASSERT_SAME, type1, type2), NOT_SAME_CODE);
+		}
+	}
+
+	protected void assertCompatible(Type type1, Type type2, String msg) {
+		if (type1 == null || type2 == null)
+			return;
+		if (!registry.haveCommonType(type1, type2)) {
+			error(msg != null ? msg : String.format(ASSERT_COMPATIBLE, type1, type2), NOT_COMPATIBLE_CODE);
+		}
+	}
+	protected void assertCompatibleWithConversion(Type type1, Type type2, String msg) {
+		if (type1 == null || type2 == null)
+			return;
+		if (!registry.haveCommonTypeWithConversion(type1, type2)) {
+			error(msg != null ? msg : String.format(ASSERT_COMPATIBLE, type1, type2), NOT_COMPATIBLE_CODE);
+		}
+	}
+	
+	protected void assertAssignable(Type varType, Type valueType, String msg) {
+		if (varType == null || valueType == null)
+			return;
+		if (!registry.isSuperType(valueType, varType)) {
+			error(msg != null ? msg : String.format(ASSERT_COMPATIBLE, varType, valueType), NOT_COMPATIBLE_CODE);
+		}
+	}
+
+	protected void info(String msg, String issueCode) {
+		acceptor.accept(new ValidationIssue(Severity.INFO, msg, issueCode));
+	}
+
+	protected void warning(String msg, String issueCode) {
+		acceptor.accept(new ValidationIssue(Severity.WARNING, msg, issueCode));
+	}
+
+	protected void error(String msg, String issueCode) {
+		acceptor.accept(new ValidationIssue(Severity.ERROR, msg, issueCode));
+	}
+}

+ 210 - 201
plugins/org.yakindu.base.types/src/org/yakindu/base/types/typesystem/AbstractTypeSystem.java

@@ -1,201 +1,210 @@
-/**
- * Copyright (c) 2014 committers of YAKINDU 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:
- * 	committers of YAKINDU - initial API and implementation
- * 
- */
-package org.yakindu.base.types.typesystem;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import org.eclipse.emf.common.util.URI;
-import org.eclipse.emf.ecore.EObject;
-import org.eclipse.emf.ecore.resource.Resource;
-import org.eclipse.emf.ecore.resource.impl.ResourceImpl;
-import org.eclipse.emf.ecore.util.EcoreUtil;
-import org.yakindu.base.types.PrimitiveType;
-import org.yakindu.base.types.Type;
-import org.yakindu.base.types.TypesFactory;
-
-/**
- * Abstract base implementation if {@link ITypeSystem}. Provides convenience
- * methods to determine type compatibility.
- * 
- * @author andreas muelder - Initial contribution and API
- * 
- */
-public abstract class AbstractTypeSystem implements ITypeSystem {
-
-	protected Map<String, Type> typeRegistry = new HashMap<String, Type>();
-	protected Map<Type, Type> extendsRegistry = new HashMap<Type, Type>();
-	protected Map<Type, Type> conversionRegistry = new HashMap<Type, Type>();
-
-	protected abstract void initBuiltInTypes();
-
-	protected Resource resource;
-
-	public AbstractTypeSystem() {
-		resource = new ResourceImpl(URI.createURI("types"));
-		initBuiltInTypes();
-	}
-
-	protected void reset() {
-		typeRegistry.clear();
-		extendsRegistry.clear();
-		conversionRegistry.clear();
-	}
-
-	public Type getType(String type) {
-		Type result = typeRegistry.get(type);
-		if (result == null) {
-			System.err.println("Could not find type " + type);
-		}
-		return result;
-	}
-
-	public Type getSuperType(Type type) {
-		Set<Entry<Type, Type>> entrySet = extendsRegistry.entrySet();
-		for (Entry<Type, Type> entry : entrySet) {
-			if (isSame(type, entry.getKey())) {
-				return entry.getValue();
-			}
-
-		}
-		return null;
-	}
-
-	public boolean isSuperType(Type subtype, Type supertype) {
-		List<Type> typehierachy = new ArrayList<Type>();
-		typehierachy.add(subtype);
-		collectSupertypes(subtype, typehierachy);
-		for (Type eObject : typehierachy) {
-			if (isSame(eObject, supertype))
-				return true;
-		}
-		return false;
-	}
-
-	private void collectSupertypes(Type subtypeClass, List<Type> typehierachy) {
-		if (subtypeClass == null)
-			return;
-		Type superType = getSuperType(subtypeClass);
-		if (superType != null) {
-			typehierachy.add(superType);
-			collectSupertypes(superType, typehierachy);
-		}
-
-	}
-
-	public Collection<Type> getTypes(EObject context) {
-		return Collections.unmodifiableCollection(typeRegistry.values());
-	}
-
-	public Collection<Type> getConcreteTypes(EObject context) {
-		List<Type> result = new ArrayList<Type>();
-		for (Type type : getTypes(context)) {
-			if (!type.isAbstract())
-				result.add(type);
-		}
-		return result;
-	}
-
-	protected Type declarePrimitive(String name) {
-		PrimitiveType primitive = TypesFactory.eINSTANCE.createPrimitiveType();
-		primitive.setName(name);
-		declareType(primitive, name);
-		resource.getContents().add(primitive);
-		return primitive;
-	}
-
-	public void declareType(Type type, String name) {
-		typeRegistry.put(name, type);
-	}
-
-	public void removeType(String name) {
-		Type type = typeRegistry.get(name);
-		if (type != null) {
-			extendsRegistry.remove(type);
-			resource.getContents().remove(type);
-			typeRegistry.remove(type);
-		}
-	}
-
-	public void declareSuperType(Type subType, Type superType) {
-		extendsRegistry.put(subType, superType);
-	}
-
-	public void declareConversion(Type baseType, Type targetType) {
-		conversionRegistry.put(baseType, targetType);
-	}
-
-	public boolean haveCommonType(Type type1, Type type2) {
-		return getCommonType(type1, type2) != null;
-	}
-
-	public boolean isSame(Type type1, Type type2) {
-		return EcoreUtil.equals(type1, type2);
-	}
-
-	public Type getCommonType(Type type1, Type type2) {
-		Type result = getCommonTypeInternal(type1, type2);
-		if (result != null)
-			return result;
-
-		Type conversionType1 = getConversionType(type1);
-		if (conversionType1 != null) {
-			result = getCommonTypeInternal(conversionType1, type2);
-			if (result != null)
-				return result;
-		}
-
-		Type conversionType2 = getConversionType(type2);
-		if (conversionType2 != null)
-			return getCommonTypeInternal(type1, conversionType2);
-
-		return null;
-	}
-
-	private Type getCommonTypeInternal(Type type1, Type type2) {
-
-		if (isSame(type1, type2))
-			return type1;
-		if (isSuperType(type1, type2)) {
-			return type2;
-		}
-		if (isSuperType(type2, type1))
-			return type1;
-
-		List<Type> typehierachy1 = new ArrayList<Type>();
-		collectSupertypes(type1, typehierachy1);
-		List<Type> typehierachy2 = new ArrayList<Type>();
-		collectSupertypes(type2, typehierachy2);
-
-		for (Type type : typehierachy1) {
-			if (typehierachy2.contains(type)) {
-				return type;
-			}
-		}
-		for (Type type : typehierachy2) {
-			if (typehierachy1.contains(type)) {
-				return type;
-			}
-		}
-
-		return null;
-	}
-
-	protected Type getConversionType(Type sourceType) {
-		return conversionRegistry.get(sourceType);
-	}
-}
+/**
+ * Copyright (c) 2014 committers of YAKINDU 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:
+ * 	committers of YAKINDU - initial API and implementation
+ * 
+ */
+package org.yakindu.base.types.typesystem;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import org.eclipse.emf.common.util.URI;
+import org.eclipse.emf.ecore.EObject;
+import org.eclipse.emf.ecore.resource.Resource;
+import org.eclipse.emf.ecore.resource.impl.ResourceImpl;
+import org.eclipse.emf.ecore.util.EcoreUtil;
+import org.yakindu.base.types.PrimitiveType;
+import org.yakindu.base.types.Type;
+import org.yakindu.base.types.TypesFactory;
+
+/**
+ * Abstract base implementation if {@link ITypeSystem}. Provides convenience
+ * methods to determine type compatibility.
+ * 
+ * @author andreas muelder - Initial contribution and API
+ * 
+ */
+public abstract class AbstractTypeSystem implements ITypeSystem {
+
+	protected Map<String, Type> typeRegistry = new HashMap<String, Type>();
+	protected Map<Type, Type> extendsRegistry = new HashMap<Type, Type>();
+	protected Map<Type, Type> conversionRegistry = new HashMap<Type, Type>();
+
+	protected abstract void initBuiltInTypes();
+
+	protected Resource resource;
+
+	public AbstractTypeSystem() {
+		resource = new ResourceImpl(URI.createURI("types"));
+		initBuiltInTypes();
+	}
+
+	protected void reset() {
+		typeRegistry.clear();
+		extendsRegistry.clear();
+		conversionRegistry.clear();
+	}
+
+	public Type getType(String type) {
+		Type result = typeRegistry.get(type);
+		if (result == null) {
+			System.err.println("Could not find type " + type);
+		}
+		return result;
+	}
+
+	public Type getSuperType(Type type) {
+		Set<Entry<Type, Type>> entrySet = extendsRegistry.entrySet();
+		for (Entry<Type, Type> entry : entrySet) {
+			if (isSame(type, entry.getKey())) {
+				return entry.getValue();
+			}
+
+		}
+		return null;
+	}
+
+	public boolean isSuperType(Type subtype, Type supertype) {
+		List<Type> typehierachy = new ArrayList<Type>();
+		typehierachy.add(subtype);
+		collectSupertypes(subtype, typehierachy);
+		for (Type eObject : typehierachy) {
+			if (isSame(eObject, supertype))
+				return true;
+		}
+		return false;
+	}
+
+	private void collectSupertypes(Type subtypeClass, List<Type> typehierachy) {
+		if (subtypeClass == null)
+			return;
+		Type superType = getSuperType(subtypeClass);
+		if (superType != null) {
+			typehierachy.add(superType);
+			collectSupertypes(superType, typehierachy);
+		}
+
+	}
+
+	public Collection<Type> getTypes(EObject context) {
+		return Collections.unmodifiableCollection(typeRegistry.values());
+	}
+
+	public Collection<Type> getConcreteTypes(EObject context) {
+		List<Type> result = new ArrayList<Type>();
+		for (Type type : getTypes(context)) {
+			if (!type.isAbstract())
+				result.add(type);
+		}
+		return result;
+	}
+
+	protected Type declarePrimitive(String name) {
+		PrimitiveType primitive = TypesFactory.eINSTANCE.createPrimitiveType();
+		primitive.setName(name);
+		declareType(primitive, name);
+		resource.getContents().add(primitive);
+		return primitive;
+	}
+
+	public void declareType(Type type, String name) {
+		typeRegistry.put(name, type);
+	}
+
+	public void removeType(String name) {
+		Type type = typeRegistry.get(name);
+		if (type != null) {
+			extendsRegistry.remove(type);
+			resource.getContents().remove(type);
+			typeRegistry.remove(type);
+		}
+	}
+
+	public void declareSuperType(Type subType, Type superType) {
+		extendsRegistry.put(subType, superType);
+	}
+
+	public void declareConversion(Type baseType, Type targetType) {
+		conversionRegistry.put(baseType, targetType);
+	}
+
+	public boolean haveCommonType(Type type1, Type type2) {
+		return getCommonType(type1, type2) != null;
+	}
+
+	public boolean isSame(Type type1, Type type2) {
+		return EcoreUtil.equals(type1, type2);
+	}
+
+	public Type getCommonType(Type type1, Type type2) {
+		Type result = getCommonTypeInternal(type1, type2);
+		if (result != null)
+			return result;
+		return null;
+	}
+
+	@Override
+	public boolean haveCommonTypeWithConversion(Type type1, Type type2) {
+		return getCommonTypeWithConversion(type1, type2) != null;
+	}
+
+	public Type getCommonTypeWithConversion(Type type1, Type type2) {
+		Type result = getCommonType(type1, type2);
+		if (result != null)
+			return result;
+		Type conversionType1 = getConversionType(type1);
+		if (conversionType1 != null) {
+			result = getCommonTypeInternal(conversionType1, type2);
+			if (result != null)
+				return result;
+		}
+		Type conversionType2 = getConversionType(type2);
+		if (conversionType2 != null)
+			return getCommonTypeInternal(type1, conversionType2);
+		return null;
+	}
+
+	private Type getCommonTypeInternal(Type type1, Type type2) {
+
+		if (isSame(type1, type2))
+			return type1;
+		if (isSuperType(type1, type2)) {
+			return type2;
+		}
+		if (isSuperType(type2, type1))
+			return type1;
+
+		List<Type> typehierachy1 = new ArrayList<Type>();
+		collectSupertypes(type1, typehierachy1);
+		List<Type> typehierachy2 = new ArrayList<Type>();
+		collectSupertypes(type2, typehierachy2);
+
+		for (Type type : typehierachy1) {
+			if (typehierachy2.contains(type)) {
+				return type;
+			}
+		}
+		for (Type type : typehierachy2) {
+			if (typehierachy1.contains(type)) {
+				return type;
+			}
+		}
+
+		return null;
+	}
+
+	protected Type getConversionType(Type sourceType) {
+		return conversionRegistry.get(sourceType);
+	}
+}

+ 38 - 35
plugins/org.yakindu.base.types/src/org/yakindu/base/types/typesystem/GenericTypeSystem.java

@@ -1,35 +1,38 @@
-/**
- * Copyright (c) 2014 committers of YAKINDU 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:
- * 	committers of YAKINDU - initial API and implementation
- * 
- */
-package org.yakindu.base.types.typesystem;
-
-import com.google.inject.Singleton;
-
-/**
- * 
- * @author andreas muelder - Initial contribution and API
- * 
- */
-@Singleton
-public class GenericTypeSystem extends AbstractTypeSystem {
-
-	@Override
-	protected void initBuiltInTypes() {
-		declarePrimitive(STRING);
-		declarePrimitive(REAL);
-		declarePrimitive(INTEGER);
-		declarePrimitive(BOOLEAN);
-		declarePrimitive(VOID);
-		declarePrimitive(NULL);
-
-		declareSuperType(getType(INTEGER), getType(REAL));
-	}
-
-}
+/**
+ * Copyright (c) 2014 committers of YAKINDU 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:
+ * 	committers of YAKINDU - initial API and implementation
+ * 
+ */
+package org.yakindu.base.types.typesystem;
+
+import com.google.inject.Singleton;
+
+/**
+ * 
+ * @author andreas muelder - Initial contribution and API
+ * 
+ */
+@Singleton
+public class GenericTypeSystem extends AbstractTypeSystem {
+
+	@Override
+	protected void initBuiltInTypes() {
+		declarePrimitive(STRING);
+		declarePrimitive(REAL);
+		declarePrimitive(INTEGER);
+		declarePrimitive(BOOLEAN);
+		declarePrimitive(VOID);
+		declarePrimitive(NULL);
+
+		declareSuperType(getType(INTEGER), getType(REAL));
+		
+		declareConversion(getType(INTEGER), getType(STRING));
+		declareConversion(getType(REAL), getType(STRING));
+		declareConversion(getType(BOOLEAN), getType(STRING));
+	}
+}

+ 60 - 55
plugins/org.yakindu.base.types/src/org/yakindu/base/types/typesystem/ITypeSystem.java

@@ -1,55 +1,60 @@
-/**
- * Copyright (c) 2014 committers of YAKINDU 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:
- * 	committers of YAKINDU - initial API and implementation
- * 
- */
-package org.yakindu.base.types.typesystem;
-
-import java.util.Collection;
-
-import org.eclipse.emf.ecore.EObject;
-import org.yakindu.base.types.Type;
-
-import com.google.inject.ImplementedBy;
-
-/**
- * A Implementation of {@link ITypeSystem} defines all existing types and the
- * type compatibility.
- * 
- * @author andreas muelder - Initial contribution and API
- * 
- */
-@ImplementedBy(GenericTypeSystem.class)
-public interface ITypeSystem {
-	
-	public static final String STRING = "string";
-	public static final String REAL = "real";
-	public static final String INTEGER = "integer";
-	public static final String BOOLEAN = "boolean";
-	public static final String VOID = "void";
-	public static final String NULL = "null";
-
-	public Collection<Type> getTypes(EObject context);
-	
-	public Collection<Type> getConcreteTypes(EObject context);
-
-	public Type getType(String name);
-	
-	public boolean isSame(Type type1, Type type2);
-
-	public Type getCommonType(Type type1, Type type2);
-
-	public boolean haveCommonType(Type type1, Type type2);
-
-	public Type getSuperType(Type type);
-
-	public boolean isSuperType(Type subtype, Type supertype);
-
-	public void declareType(Type type, String name);
-
-}
+/**
+ * Copyright (c) 2014 committers of YAKINDU 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:
+ * 	committers of YAKINDU - initial API and implementation
+ * 
+ */
+package org.yakindu.base.types.typesystem;
+
+import java.util.Collection;
+
+import org.eclipse.emf.ecore.EObject;
+import org.yakindu.base.types.Type;
+
+import com.google.inject.ImplementedBy;
+
+/**
+ * A Implementation of {@link ITypeSystem} defines all existing types and the
+ * type compatibility.
+ * 
+ * @author andreas muelder - Initial contribution and API
+ * 
+ */
+@ImplementedBy(GenericTypeSystem.class)
+public interface ITypeSystem {
+	
+	public static final String STRING = "string";
+	public static final String REAL = "real";
+	public static final String INTEGER = "integer";
+	public static final String BOOLEAN = "boolean";
+	public static final String VOID = "void";
+	public static final String NULL = "null";
+
+	public Collection<Type> getTypes(EObject context);
+	
+	public Collection<Type> getConcreteTypes(EObject context);
+
+	public Type getType(String name);
+	
+	public boolean isSame(Type type1, Type type2);
+
+	public boolean haveCommonType(Type type1, Type type2);
+
+	public Type getCommonType(Type type1, Type type2);
+
+	public boolean haveCommonTypeWithConversion(Type type1, Type type2);
+
+	public Type getCommonTypeWithConversion(Type type1, Type type2);
+	
+	public Type getSuperType(Type type);
+
+	public boolean isSuperType(Type subtype, Type supertype);
+
+	public void declareType(Type type, String name);
+
+
+}