Browse Source

Updated Type Inferrer

Andreas Mülder 11 years ago
parent
commit
c88a7266b8

+ 158 - 154
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/types/STextDefaultTypeInferrer.xtend

@@ -8,7 +8,7 @@
  * Contributors:
  * 	itemis AG - initial API and implementation
  *  
- */
+ */
 package org.yakindu.sct.model.stext.types
 
 import com.google.inject.Inject
@@ -22,10 +22,14 @@ import org.yakindu.base.expressions.inferrer.DefaultExpressionsTypeInferrer
 import org.yakindu.base.types.Event
 import org.yakindu.base.types.Feature
 import org.yakindu.base.types.ITypeSystem
+import org.yakindu.base.types.ITypeSystem.BinaryOperators
 import org.yakindu.base.types.InferenceIssue
 import org.yakindu.base.types.InferenceResult
 import org.yakindu.base.types.InferredType
+import org.yakindu.base.types.ParameterizedType
 import org.yakindu.base.types.Type
+import org.yakindu.base.types.TypeParameter
+import org.yakindu.base.types.TypedElement
 import org.yakindu.sct.model.stext.stext.ActiveStateReferenceExpression
 import org.yakindu.sct.model.stext.stext.EventDefinition
 import org.yakindu.sct.model.stext.stext.EventRaisingExpression
@@ -34,10 +38,6 @@ import org.yakindu.sct.model.stext.stext.InterfaceScope
 import org.yakindu.sct.model.stext.stext.InternalScope
 import org.yakindu.sct.model.stext.stext.OperationDefinition
 import org.yakindu.sct.model.stext.stext.VariableDefinition
-import org.yakindu.base.types.ITypeSystem.BinaryOperators
-import org.yakindu.base.types.TypeParameter
-import org.yakindu.base.types.TypedElement
-import java.lang.reflect.ParameterizedType
 
 /**
  * 
@@ -46,167 +46,171 @@ import java.lang.reflect.ParameterizedType
  * @author andreas muelder - Initial contribution and API
  * @author Alexander Nyßen - Complete revision of API
  *  
- */
- @Singleton
-class STextDefaultTypeInferrer extends DefaultExpressionsTypeInferrer implements ISTextTypeInferrer {
-	
-	@Inject protected extension
-	ITypeSystem ts
-	
-	
-	
-	override inferType(VariableDefinition definition) {
-		if(definition == null){
-			throw new IllegalArgumentException("Definition may not be null")
-		}
-		else{
-			definition.doInferType
-		}
-	}
-	
-	override inferType(EventDefinition definition) {
-		if(definition == null){
-			throw new IllegalArgumentException("Definition may not be null")
-		}
-		else{
-			definition.doInferType
-		}
-	}
-	
-	def dispatch InferenceResult doInferType(VariableDefinition definition) {
-		if(definition.type == null) {
- 				return new InferenceResult(null, new InferenceIssue("Could not infer type of variable: " + definition.name, IStatus::ERROR))
- 		}
- 		else{
- 			var varType = new InferenceResult(new InferredType(definition.type))
- 			if(definition.initialValue != null){
- 				val valueType = definition.initialValue.doInferType
- 				if(valueType.type == null){
-					return valueType
- 				}
- 			
- 				// reuse the assignment logic of the type system
- 				val result = inferResult(varType, valueType, BinaryOperators.ASSIGN)
- 				if(result.type == null){
- 					return new InferenceResult(null, new InferenceIssue("Cannot assign a value of type " + valueType.type.type.name + " to a variable of type " + varType.type.type.name + ".", IStatus::ERROR))
- 				}	
- 			}
- 			return varType
- 		}
-	}
-
-	def dispatch InferenceResult doInferType(EventDefinition definition) {
-		if(definition == null){
-			throw new IllegalArgumentException("EventDefinition may not be null")
-		}
-		if(definition.type == null){
-			return new InferenceResult(new InferredType(voidType))
-		}
-		return new InferenceResult(new InferredType(definition.type))
-	}
-
-	def dispatch InferenceResult doInferType(OperationDefinition definition) {
-		if(definition == null){
-			throw new IllegalArgumentException("EventDefinition may not be null")
-		}
-		if(definition.type == null){
-			return new InferenceResult(new InferredType(voidType))
-		}
-		return new InferenceResult(new InferredType(definition.type))
-	}
-	
-	def dispatch InferenceResult doInferType(Type type) {
-		return new InferenceResult(new InferredType(type))
-	}
-	
-	
-	
-	def dispatch InferenceResult doInferType(InterfaceScope s){
+ */
+@Singleton
+class STextDefaultTypeInferrer extends DefaultExpressionsTypeInferrer implements ISTextTypeInferrer {
+
+	@Inject protected extension ITypeSystem ts
+
+	override inferType(VariableDefinition definition) {
+		if (definition == null) {
+			throw new IllegalArgumentException("Definition may not be null")
+		} else {
+			definition.doInferType
+		}
+	}
+
+	override inferType(EventDefinition definition) {
+		if (definition == null) {
+			throw new IllegalArgumentException("Definition may not be null")
+		} else {
+			definition.doInferType
+		}
+	}
+
+	def dispatch InferenceResult doInferType(VariableDefinition definition) {
+		if (definition.type == null) {
+			return new InferenceResult(null,
+				new InferenceIssue("Could not infer type of variable: " + definition.name, IStatus::ERROR))
+		} else {
+			var varType = new InferenceResult(new InferredType(definition.type))
+			if (definition.initialValue != null) {
+				val valueType = definition.initialValue.doInferType
+				if (valueType.type == null) {
+					return valueType
+				}
+
+				// reuse the assignment logic of the type system
+				val result = inferResult(varType, valueType, BinaryOperators.ASSIGN)
+				if (result.type == null) {
+					return new InferenceResult(null,
+						new InferenceIssue(
+							"Cannot assign a value of type " + valueType.type.type.name + " to a variable of type " +
+								varType.type.type.name + ".", IStatus::ERROR))
+				}
+			}
+			return varType
+		}
+	}
+
+	def dispatch InferenceResult doInferType(EventDefinition definition) {
+		if (definition == null) {
+			throw new IllegalArgumentException("EventDefinition may not be null")
+		}
+		if (definition.type == null) {
+			return new InferenceResult(new InferredType(voidType))
+		}
+		return new InferenceResult(new InferredType(definition.type))
+	}
+
+	def dispatch InferenceResult doInferType(OperationDefinition definition) {
+		if (definition == null) {
+			throw new IllegalArgumentException("EventDefinition may not be null")
+		}
+		if (definition.type == null) {
+			return new InferenceResult(new InferredType(voidType))
+		}
+		return new InferenceResult(new InferredType(definition.type))
+	}
+
+	def dispatch InferenceResult doInferType(Type type) {
+		return new InferenceResult(new InferredType(type))
+	}
+
+	def dispatch InferenceResult doInferType(InterfaceScope s) {
+
 		// TODO: this could be handled via the type system
-		return new InferenceResult(voidType)	
-	}
-	
-	def dispatch InferenceResult doInferType(InternalScope s){
+		return new InferenceResult(voidType)
+	}
+
+	def dispatch InferenceResult doInferType(InternalScope s) {
+
 		// TODO: this could be handled via the type system
-		return new InferenceResult(voidType)	
-	}
-
+		return new InferenceResult(voidType)
+	}
+
 	def dispatch InferenceResult doInferType(Expression e) {
-		throw new UnsupportedOperationException("Unsupported expression type " + e)
-	}
-	
-	
-	
-	def dispatch InferenceResult doInferType(AssignmentExpression expression){
-		return inferResult(expression.varRef.doInferType, expression.expression.doInferType, getTypeSystemOperator(expression.operator))
-	}
-	
-	def dispatch InferenceResult doInferType(EventRaisingExpression eventRaising){
- 		val eventType = eventRaising.event.doInferType
- 		if(eventType.type == null) {
- 			return eventType
- 		}
- 		else{
- 			if(eventRaising.value == null){
- 				if(!eventType.type.voidType){
- 					return new InferenceResult(null, new InferenceIssue("Need to assign a value to an event of type " + eventType.type.type.name + ".", IStatus::ERROR))
- 				}	
- 				return eventType
- 			}
- 			else{
- 				val valueType = eventRaising.value.doInferType
- 				if(valueType.type == null){
- 					return valueType
- 				}
- 			
- 				// reuse the assignment logic of the type system
- 				val result = inferResult(eventType, valueType, BinaryOperators.ASSIGN)
- 				if(result.type == null){
- 					return new InferenceResult(null, new InferenceIssue("Cannot assign a value of type " + valueType.type.type.name + " to an event of type " + eventType.type.type.name + ".", IStatus::ERROR))
- 				}
- 				else {
- 					return result
- 				}
- 			}
- 		}
-	}
-	
-	
-	 
-	def dispatch InferenceResult doInferType(ActiveStateReferenceExpression expression){
-		return new InferenceResult(getBooleanType)
-	}
-
-	def dispatch InferenceResult doInferType(ElementReferenceExpression expression){
-		if(expression.reference instanceof EventDefinition && !(expression.eContainer instanceof EventRaisingExpression
-				|| expression.eContainer instanceof EventValueReferenceExpression)){
+		println("Unsupported expression type " + e)
+		return new InferenceResult(voidType);
+//		throw new UnsupportedOperationException("Unsupported expression type " + e)
+	}
+
+	def dispatch InferenceResult doInferType(AssignmentExpression expression) {
+		return inferResult(expression.varRef.doInferType, expression.expression.doInferType,
+			getTypeSystemOperator(expression.operator))
+	}
+
+	def dispatch InferenceResult doInferType(EventRaisingExpression eventRaising) {
+		val eventType = eventRaising.event.doInferType
+		if (eventType.type == null) {
+			return eventType
+		} else {
+			if (eventRaising.value == null) {
+				if (!eventType.type.voidType) {
+					return new InferenceResult(null,
+						new InferenceIssue(
+							"Need to assign a value to an event of type " + eventType.type.type.name + ".",
+							IStatus::ERROR))
+				}
+				return eventType
+			} else {
+				val valueType = eventRaising.value.doInferType
+				if (valueType.type == null) {
+					return valueType
+				}
+
+				// reuse the assignment logic of the type system
+				val result = inferResult(eventType, valueType, BinaryOperators.ASSIGN)
+				if (result.type == null) {
+					return new InferenceResult(null,
+						new InferenceIssue(
+							"Cannot assign a value of type " + valueType.type.type.name + " to an event of type " +
+								eventType.type.type.name + ".", IStatus::ERROR))
+				} else {
+					return result
+				}
+			}
+		}
+	}
+
+	def dispatch InferenceResult doInferType(ActiveStateReferenceExpression expression) {
+		return new InferenceResult(getBooleanType)
+	}
+
+	def dispatch InferenceResult doInferType(ElementReferenceExpression expression) {
+		if (expression.reference instanceof EventDefinition && !(expression.eContainer instanceof EventRaisingExpression ||
+			expression.eContainer instanceof EventValueReferenceExpression)) {
+
 			// in case we are not inside an raise or valueOf expression, the event is a shortcut for isRaised(event) and thus, we may return boolean here
-			return new InferenceResult(getBooleanType)
-		}
-		else {
+			return new InferenceResult(getBooleanType)
+		} else {
+
 			// inference of the reference type is not context dependent
-			return expression.reference.doInferType
-		}
-	}
-	
-	def dispatch InferenceResult doInferType(FeatureCall featureCall){
-		if(featureCall.feature instanceof Event /*Definition*/ 
-			&& !(featureCall.eContainer instanceof EventRaisingExpression) 
-			&& !(featureCall.eContainer instanceof EventValueReferenceExpression)
-		){
+			return expression.reference.doInferType
+		}
+	}
+
+	def dispatch InferenceResult doInferType(FeatureCall featureCall) {
+		if (featureCall.feature instanceof Event /*Definition*/ &&
+			!(featureCall.eContainer instanceof EventRaisingExpression) &&
+			!(featureCall.eContainer instanceof EventValueReferenceExpression)) {
+
 			// e1 is a shortcut for isRaised(e1) and thus we have to return boolean here
 			return new InferenceResult(getBooleanType)
 		}
 		if (featureCall.feature instanceof Feature) {
 			val type = (featureCall.feature as Feature).type
 			if (type != null) {
-				if (type instanceof TypeParameter) {
+				if (type instanceof TypeParameter) {
 					var current = featureCall
-					while(!(current.owner instanceof ElementReferenceExpression)) current = current.owner as FeatureCall
-					var typedElement = ((featureCall.owner as ElementReferenceExpression).reference as TypedElement)
-					var index = (typedElement.type as org.yakindu.base.types.ParameterizedType).parameter.indexOf(type)
-					var innerType = typedElement.typeArguments.get(index)
-					return new InferenceResult(new InferredType(innerType))
+					while (!(current.owner instanceof ElementReferenceExpression))
+						current = current.owner as FeatureCall
+					var typedElement = ((current.owner as ElementReferenceExpression).reference as TypedElement)
+					var index = (typedElement.type as ParameterizedType).parameter.indexOf(type)
+					if (!(index == -1)) {
+						var innerType = typedElement.typeArguments.get(index)
+						return new InferenceResult(new InferredType(innerType))
+					}
 				}
 				return new InferenceResult(new InferredType(type))
 			}