فهرست منبع

TypeAnalyzer inferType for retrieving type of expressions.
JavaCodegenerator checks for String and takes equals-method. (YAKHMI-560)

benjamin.schwertfeger@gmail.com 14 سال پیش
والد
کامیت
db007e0863

+ 22 - 0
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/extensions/TypeAnalyzerExtensions.ext

@@ -0,0 +1,22 @@
+/*
+  Copyright (c) 2011 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:
+  	Markus Muehlbrandt - Initial contribution and API
+ */
+import types;
+import stext;
+import sexec;
+import sgraph;
+
+Type inferType(Statement stmt):
+	JAVA org.yakindu.sct.generator.core.extensions.TypeAnalyzerExtensions.inferType(org.yakindu.sct.model.sgraph.Statement);
+
+boolean isBoolean(Type t):
+	JAVA org.yakindu.sct.generator.core.extensions.TypeAnalyzerExtensions.isBoolean(org.yakindu.base.types.Type);
+
+boolean isString(Type t):
+	JAVA org.yakindu.sct.generator.core.extensions.TypeAnalyzerExtensions.isString(org.yakindu.base.types.Type);

+ 52 - 0
plugins/org.yakindu.sct.generator.core/src/org/yakindu/sct/generator/core/extensions/TypeAnalyzerExtensions.java

@@ -0,0 +1,52 @@
+package org.yakindu.sct.generator.core.extensions;
+
+import static org.yakindu.sct.generator.core.impl.AbstractXpandBasedCodeGenerator.CONTEXT_INJECTOR_PROPERTY_NAME;
+
+import org.eclipse.xtend.expression.ExecutionContext;
+import org.eclipse.xtend.expression.IExecutionContextAware;
+import org.yakindu.base.types.Type;
+import org.yakindu.sct.model.sgraph.Statement;
+import org.yakindu.sct.model.stext.validation.ITypeAnalyzer;
+
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+
+public class TypeAnalyzerExtensions implements IExecutionContextAware {
+	@Inject
+	ITypeAnalyzer typeAnalyzer;
+
+	public void setExecutionContext(ExecutionContext ctx) {
+		Injector injector = null;
+		if (ctx.getGlobalVariables().get(CONTEXT_INJECTOR_PROPERTY_NAME) != null) {
+			injector = (Injector) ctx.getGlobalVariables()
+					.get(CONTEXT_INJECTOR_PROPERTY_NAME).getValue();
+		} else if (ctx.getGlobalVariables().get(Injector.class.getName()) != null) {
+			injector = (Injector) ctx.getGlobalVariables()
+					.get(Injector.class.getName()).getValue();
+		}
+		if (injector != null) {
+			injector.injectMembers(this);
+		}
+	}
+
+	public boolean isBoolean(Type type) {
+		return typeAnalyzer.isBoolean(type);
+	}
+
+	public boolean isInteger(Type type) {
+		return typeAnalyzer.isInteger(type);
+	}
+
+	public boolean isReal(Type type) {
+		return typeAnalyzer.isReal(type);
+	}
+
+	public boolean isString(Type type) {
+		return typeAnalyzer.isString(type);
+	}
+
+	public Type inferType(Statement stmt) {
+		return typeAnalyzer.inferType(stmt);
+	}
+
+}

+ 5 - 1
plugins/org.yakindu.sct.generator.java/src/org/yakindu/sct/generator/java/templates/Expression.ext

@@ -14,6 +14,7 @@ import sgraph;
 
 extension org::yakindu::sct::generator::java::templates::Naming;
 extension org::yakindu::sct::generator::java::templates::TypeModelExtensions;
+extension org::yakindu::sct::generator::core::extensions::TypeAnalyzerExtensions;
 
 String toCode(Void void) :
 	"/*toCode() called with NULL element. Polymorphic resolver could not match callable method!*/";
@@ -94,7 +95,10 @@ String toCode(LogicalNotExpression expression) :
   	" !" + expression.operand.toCode();
 
 String toCode(LogicalRelationExpression expression) :
-   "("+expression.leftOperand.toCode() + getOperator(expression.operator) + expression.rightOperand.toCode()+")";
+	if (expression.leftOperand.inferType().isString()) then
+		"("+expression.leftOperand.toCode()+"==null?"+expression.rightOperand.toCode()+"==null:"+expression.leftOperand.toCode()+".equals("+expression.rightOperand.toCode()+"))"
+	else
+		"("+expression.leftOperand.toCode() + getOperator(expression.operator) + expression.rightOperand.toCode()+")";
     
 String toCode(BitwiseAndExpression expression) :
   	"("+expression.leftOperand.toCode() + " & " + expression.rightOperand.toCode()+")";

+ 7 - 0
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/validation/ErrorAcceptor.java

@@ -0,0 +1,7 @@
+package org.yakindu.sct.model.stext.validation;
+
+public class ErrorAcceptor {
+	public void acceptError(String msg) {
+		throw new TypeCheckException(msg);
+	}
+}

+ 24 - 0
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/validation/ITypeAnalyzer.java

@@ -0,0 +1,24 @@
+package org.yakindu.sct.model.stext.validation;
+
+import org.yakindu.base.types.Type;
+import org.yakindu.sct.model.sgraph.Statement;
+
+import com.google.inject.ImplementedBy;
+
+@ImplementedBy(StaticTypeAnalyzer.class)
+public interface ITypeAnalyzer {
+	boolean isBoolean(Type type);
+
+	boolean isInteger(Type type);
+
+	boolean isReal(Type type);
+
+	boolean isString(Type type);
+
+	Type inferType(Statement expr);
+
+	boolean isAssignable(Type expected, Type actual);
+
+	Type combine(Type typeOne, Type typeTwo);
+
+}

+ 54 - 46
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/validation/STextJavaValidator.java

@@ -67,14 +67,14 @@ public class STextJavaValidator extends AbstractSTextJavaValidator {
 	@Inject
 	private StaticTypeAnalyzer analyzer;
 
-	
-//	@Check
-//	public void checkOperationCall(final FeatureCall call) {
-//		if (! (call.getFeature() instanceof Operation) /*&& !call.isOperationCall()*/) {
-//			error(call.getFeature().getName()
-//					+ " is not an operation ", null);
-//		}
-//	}
+	// @Check
+	// public void checkOperationCall(final FeatureCall call) {
+	// if (! (call.getFeature() instanceof Operation) /*&&
+	// !call.isOperationCall()*/) {
+	// error(call.getFeature().getName()
+	// + " is not an operation ", null);
+	// }
+	// }
 	@Check
 	public void checkOperationArguments(final FeatureCall call) {
 		if (call.getFeature() instanceof Operation) {
@@ -90,6 +90,7 @@ public class STextJavaValidator extends AbstractSTextJavaValidator {
 	@Check
 	public void checkExpression(final Statement statement) {
 		try {
+			analyzer.setErrorAcceptor(new ErrorAcceptor());
 			analyzer.check(statement);
 		} catch (TypeCheckException e) {
 			error(e.getMessage(), null);
@@ -128,7 +129,6 @@ public class STextJavaValidator extends AbstractSTextJavaValidator {
 		}
 	}
 
-	
 	/**
 	 * Only Expressions that produce an effect should be used as actions.
 	 * 
@@ -138,67 +138,75 @@ public class STextJavaValidator extends AbstractSTextJavaValidator {
 	public void checkReactionEffectActions(ReactionEffect effect) {
 		for (Expression exp : effect.getActions()) {
 
-			if ( ! (exp instanceof AssignmentExpression)
-				 && ! (exp instanceof EventRaisingExpression) ) {
-				
-				if ( exp instanceof FeatureCall ) {
+			if (!(exp instanceof AssignmentExpression)
+					&& !(exp instanceof EventRaisingExpression)) {
+
+				if (exp instanceof FeatureCall) {
 					checkFeatureCallEffect((FeatureCall) exp);
-				} else if ( exp instanceof TypedElementReferenceExpression ) {
-					checkTypedElementReferenceEffect((TypedElementReferenceExpression) exp);					
+				} else if (exp instanceof TypedElementReferenceExpression) {
+					checkTypedElementReferenceEffect((TypedElementReferenceExpression) exp);
 				} else {
 					error("Action has no effect.",
-							StextPackage.Literals.REACTION_EFFECT__ACTIONS, effect.getActions().indexOf(exp));
+							StextPackage.Literals.REACTION_EFFECT__ACTIONS,
+							effect.getActions().indexOf(exp));
 				}
 
 			}
 		}
 	}
 
-	
 	protected void checkFeatureCallEffect(FeatureCall call) {
-		if (! (call.getFeature() instanceof Operation)) {
-			if ( call.getFeature() instanceof Property ) {
-				error("Access to property '" + call.getFeature().getName() + "' has no effect.",
-						call,
-						StextPackage.Literals.FEATURE_CALL__FEATURE, 0);	
-			} else if ( call.getFeature() instanceof Event ) {
-				error("Access to event '" + call.getFeature().getName() + "' has no effect.",
-						call,
-						StextPackage.Literals.FEATURE_CALL__FEATURE, 0);	
+		if (!(call.getFeature() instanceof Operation)) {
+			if (call.getFeature() instanceof Property) {
+				error("Access to property '" + call.getFeature().getName()
+						+ "' has no effect.", call,
+						StextPackage.Literals.FEATURE_CALL__FEATURE, 0);
+			} else if (call.getFeature() instanceof Event) {
+				error("Access to event '" + call.getFeature().getName()
+						+ "' has no effect.", call,
+						StextPackage.Literals.FEATURE_CALL__FEATURE, 0);
 			} else {
-				error("Access to feature '" + call.getFeature().getName() + "' has no effect.",
-						call,
-						StextPackage.Literals.FEATURE_CALL__FEATURE, 0);	
+				error("Access to feature '" + call.getFeature().getName()
+						+ "' has no effect.", call,
+						StextPackage.Literals.FEATURE_CALL__FEATURE, 0);
 			}
-			
+
 			if (call.getOwner() != null) {
-				if (call.getOwner() instanceof FeatureCall) checkFeatureCallEffect((FeatureCall)call.getOwner());
-				else if (call.getOwner() instanceof TypedElementReferenceExpression) checkTypedElementReferenceEffect((TypedElementReferenceExpression)call.getOwner());
+				if (call.getOwner() instanceof FeatureCall)
+					checkFeatureCallEffect((FeatureCall) call.getOwner());
+				else if (call.getOwner() instanceof TypedElementReferenceExpression)
+					checkTypedElementReferenceEffect((TypedElementReferenceExpression) call
+							.getOwner());
 			}
 		}
 
 	}
-	
-	
-	protected void checkTypedElementReferenceEffect(TypedElementReferenceExpression ter) {
-		if (! (ter.getReference() instanceof Operation)) {
-			if ( ter.getReference() instanceof Property ) {
-				error("Access to property '" + ter.getReference().getName() + "' has no effect.",
+
+	protected void checkTypedElementReferenceEffect(
+			TypedElementReferenceExpression ter) {
+		if (!(ter.getReference() instanceof Operation)) {
+			if (ter.getReference() instanceof Property) {
+				error("Access to property '" + ter.getReference().getName()
+						+ "' has no effect.",
 						ter,
-						StextPackage.Literals.TYPED_ELEMENT_REFERENCE_EXPRESSION__REFERENCE, 0);	
-			} else if ( ter.getReference() instanceof Event ) {
-				error("Access to event '" + ter.getReference().getName() + "' has no effect.",
+						StextPackage.Literals.TYPED_ELEMENT_REFERENCE_EXPRESSION__REFERENCE,
+						0);
+			} else if (ter.getReference() instanceof Event) {
+				error("Access to event '" + ter.getReference().getName()
+						+ "' has no effect.",
 						ter,
-						StextPackage.Literals.TYPED_ELEMENT_REFERENCE_EXPRESSION__REFERENCE, 0);	
+						StextPackage.Literals.TYPED_ELEMENT_REFERENCE_EXPRESSION__REFERENCE,
+						0);
 			} else {
-				error("Access to feature '" + ter.getReference().getName() + "' has no effect.",
+				error("Access to feature '" + ter.getReference().getName()
+						+ "' has no effect.",
 						ter,
-						StextPackage.Literals.TYPED_ELEMENT_REFERENCE_EXPRESSION__REFERENCE, 0);		
+						StextPackage.Literals.TYPED_ELEMENT_REFERENCE_EXPRESSION__REFERENCE,
+						0);
 			}
 		}
 	}
-	
-	
+
 	@Check(CheckType.FAST)
 	public void checkVariable(VariableDefinition variable) {
 		if (variable.eContainer() instanceof SimpleScope) {

+ 224 - 108
plugins/org.yakindu.sct.model.stext/src/org/yakindu/sct/model/stext/validation/StaticTypeAnalyzer.xtend

@@ -10,7 +10,7 @@
  *  
  */
 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
@@ -46,6 +46,13 @@ import org.yakindu.sct.model.stext.stext.TypedElementReferenceExpression
 import org.yakindu.base.types.Feature
 import javax.lang.model.element.TypeElement
 import org.yakindu.sct.model.stext.stext.FeatureCall
+import org.yakindu.sct.model.stext.validation.ITypeAnalyzer
+import org.yakindu.base.types.LibrariesExtensions
+import org.yakindu.base.types.scope.TypeLibraryLocation
+import org.yakindu.base.types.TypesPackage
+import org.yakindu.base.types.TypesFactory
+import org.yakindu.sct.model.stext.stext.StringLiteral
+import org.eclipse.xtext.validation.AbstractValidationMessageAcceptor
  
 /**
  * 
@@ -54,136 +61,150 @@ import org.yakindu.sct.model.stext.stext.FeatureCall
  * @author andreas muelder - Initial contribution and API
  * 
  */
-class StaticTypeAnalyzer {
+class StaticTypeAnalyzer implements ITypeAnalyzer {
 	
-// begin TODO: externalize this
-	def isBoolean(Type type){
-		return type != null && type.name == "boolean";	
-	}
+	@Inject TypeLibraryLocation$Registry libraries
+	ErrorAcceptor acceptor
 	
-	def isInteger(Type type){
-		return type != null && (type.name =="integer" || type.name =="int");
+	def void setErrorAcceptor(ErrorAcceptor acceptor2) {
+		acceptor = acceptor2
 	}
 	
-	def isReal(Type type){
-		return type != null && type.name == "real";	
+	def dispatch inferType(Statement statement){
+		null
 	}
-// end TODO
 	
-	def dispatch check(Statement statement){
-		null
+	def check(Statement stmt) {
+		stmt.inferType
 	}
 	
 	/**
 	 * Check Variable assignments
 	 */
-	def dispatch check(AssignmentExpression assignment){
-		var valueType = assignment.expression.check
-		var type = assignment.varRef.check
-		if(type == typeof(Boolean) && !(valueType == typeof(Boolean))){
-			error("Can not assign a value of type " + valueType.simpleName + " to a variable of type " + type)
-		}
-		else if(type == typeof(Number) && !(valueType == typeof(Number))){
-			error("Can not assign a value of type " + valueType.simpleName + " to a variable of type " + type)
+	def dispatch inferType(AssignmentExpression assignment){
+		var valueType = assignment.expression.inferType
+		var type = assignment.varRef.inferType
+		
+		if(!isAssignable(type, valueType)){
+			error("Can not assign a value of type " + valueType.name + " to a variable of type " + type.name)
+			return null 
 		}
-		return null 
+		return type
 	}
 	/**
 	 * Check Event value assignments
 	 */
-	def dispatch check(EventRaisingExpression eventRaising){
-		var valueType = eventRaising.value.check
-		var type = eventRaising.event.check
-		if(type == typeof(Boolean) && !(valueType == typeof(Boolean))){
-			error("Can not assign a value of type " + valueType.simpleName + " to an event of type " + type)
-		}
-		else if (type == typeof(Number) && !(valueType == typeof(Number))){
-			error("Can not assign a value of type " + valueType.simpleName + " to an event of type " + type)
+	def dispatch inferType(EventRaisingExpression eventRaising){
+		var valueType = eventRaising.value.inferType
+		var type = eventRaising.event.inferType
+		
+		if(!isAssignable(type, valueType)){
+			error("Can not assign a value of type " + valueType.name + " to a variable of type " + type.name)
+			return null 
 		}
-		return null 
+		return type
 	}
 	
-	
-	
-	def dispatch check(LogicalAndExpression expression){
-		assertIsBoolean(expression.leftOperand.check, '&&')
-		assertIsBoolean(expression.rightOperand.check, '&&')
-		typeof(Boolean)
+	def dispatch inferType(LogicalAndExpression expression){
+		return assertBooleanTypes(expression.leftOperand.inferType,
+			expression.rightOperand.inferType,'&&')
+	}
+	def dispatch inferType(LogicalOrExpression expression){
+		return assertBooleanTypes(expression.leftOperand.inferType,
+			expression.rightOperand.inferType,'||')
 	}
-	def dispatch check(LogicalOrExpression expression){
-		assertIsBoolean(expression.leftOperand.check,'||')
-		assertIsBoolean(expression.rightOperand.check,'||')
-		typeof(Boolean)
+	def assertBooleanTypes(Type left, Type right, String literal) {
+		if (assertIsBoolean(left,literal) != null
+			&& assertIsBoolean(right, literal) != null) {
+				return combine(left, right)
+			}
+		return null;
 	}
-	def dispatch check(LogicalNotExpression expression){
-		assertIsBoolean(expression.operand.check,'!')
-		typeof(Boolean)
+	def dispatch inferType(LogicalNotExpression expression){
+		val type = expression.operand.inferType
+		return assertIsBoolean(type,'!')
 	}
-	def dispatch check(BitwiseAndExpression expression){
-		assertIsNumber(expression.leftOperand.check,'&')
-		assertIsNumber(expression.rightOperand.check,'&')
-		typeof(Number)
+	def dispatch inferType(BitwiseAndExpression expression){
+		return assertNumericalTypes(expression.leftOperand.inferType, 
+			expression.rightOperand.inferType,'&')
 	}
-	def dispatch check(BitwiseOrExpression expression){
-		assertIsNumber(expression.leftOperand.check,'|')
-		assertIsNumber(expression.rightOperand.check,'|')
-		typeof(Number)
+	def dispatch inferType(BitwiseOrExpression expression){
+		return assertNumericalTypes(expression.leftOperand.inferType, 
+			expression.rightOperand.inferType,'|')
 	}
-	def dispatch check(BitwiseXorExpression expression){
-		assertIsNumber(expression.leftOperand.check,'^')
-		assertIsNumber(expression.rightOperand.check,'^')
-		typeof(Number)
+	def dispatch inferType(BitwiseXorExpression expression){
+		return assertNumericalTypes(expression.leftOperand.inferType, 
+			expression.rightOperand.inferType,'^')
 	}
-	def dispatch check(LogicalRelationExpression expression){ 
-		var leftType = expression.leftOperand.check
-		var rightType = expression.rightOperand.check
-		if(leftType != rightType){
+	def dispatch inferType(LogicalRelationExpression expression){ 
+		val leftType = expression.leftOperand.inferType
+		val rightType = expression.rightOperand.inferType
+		val combined = combine(leftType, rightType)
+		if(combined == null){
 			error("Incompatible operands " +leftType.name + " and " + rightType.name + " 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(leftType.^boolean && rightType.^boolean){
 			if(expression.operator != RelationalOperator::EQUALS && expression.operator != RelationalOperator::NOT_EQUALS){
 				error("operator '" + expression.operator.literal + "' can not be applied to boolean values!")
+				return null
 			}
 		}
-		return typeof(Boolean) 
+		return combined
 		
 	}
-	def dispatch check(NumericalAddSubtractExpression expression){
-		assertIsNumber(expression.leftOperand.check, expression.operator.literal)
-		assertIsNumber(expression.rightOperand.check, expression.operator.literal)
-		typeof(Number)
+	
+	def assertNumericalTypes(Type left, Type right, String literal) {
+		if (assertIsNumber(left, literal) != null
+			&& assertIsNumber(right, literal) != null) {
+				return combine(left, right)
+		}
+		return null;
+	}
+	
+	def dispatch inferType(NumericalAddSubtractExpression expression){
+		return assertNumericalTypes(expression.leftOperand.inferType, 
+			expression.rightOperand.inferType, expression.operator.literal
+		)
 	}
-	def dispatch check(NumericalMultiplyDivideExpression expression){
-		assertIsNumber(expression.leftOperand.check, expression.operator.literal)
-		assertIsNumber(expression.rightOperand.check, expression.operator.literal)
-		typeof(Number)
+	def dispatch inferType(NumericalMultiplyDivideExpression expression){
+		return assertNumericalTypes(expression.leftOperand.inferType, 
+			expression.rightOperand.inferType, expression.operator.literal
+		)
 	}
-	def dispatch check(NumericalUnaryExpression expression){
-		assertIsNumber(expression.operand.check, expression.operator.literal)
-		typeof(Number)
+	def dispatch Type inferType(NumericalUnaryExpression expression){
+		val type = expression.operand.inferType
+		return assertIsNumber(type, expression.operator.literal)
 	}	
-	def dispatch check(PrimitiveValueExpression expression){
-		expression.value.type
+	def dispatch inferType(PrimitiveValueExpression expression){
+		val Type t = expression.value.getType
+		return t
 	}
-	def dispatch check(ShiftExpression expression){
+	def dispatch inferType(ShiftExpression expression){
 		//TODO: Implement me
 	}
-	def dispatch check(ConditionalExpression expression){
-		//TODO: Implement me
+	def dispatch inferType(ConditionalExpression expression){
+		val condType = expression.condition.inferType
+		if (!condType.^boolean) {
+			error("Condition type have to be boolean")
+			return null;
+		}
+		val trueType = expression.trueCase.inferType
+		val falseType = expression.falseCase.inferType
+		return combine(trueType, falseType)
 	} 
 	
-	def dispatch check(FeatureCall featureCall){
-		return featureCall.feature.type.toJavaType
+	def dispatch inferType(FeatureCall featureCall){
+		return featureCall.feature.type
 	}
 	
-	def dispatch check (TypedElementReferenceExpression expression){
+	def dispatch inferType(TypedElementReferenceExpression expression){
 		var reference  = expression.reference
 		if(reference instanceof VariableDefinition){
-			return (reference as VariableDefinition).type.toJavaType
+			return (reference as VariableDefinition).type
 		}
 		if(reference instanceof EventDefinition){
-			return typeof(Boolean)
+			return createBoolean
 		}
 		null
 		
@@ -195,47 +216,142 @@ class StaticTypeAnalyzer {
 //			return (declaration as VariableDefinition).type.toJavaType
 //		}
 //		return null;
-//	}
-	def dispatch check(EventValueReferenceExpression expression){
+//	}	
+
+	def createBoolean() {
+		val type = TypesFactory::eINSTANCE.createType()
+		type.name = "boolean"
+		return type
+	}
+	def dispatch inferType(EventValueReferenceExpression expression){
 		//TODO: Implement me
 	}
 	
-	def dispatch type(IntLiteral literal){
-		return typeof(Number)
+	def dispatch getType(IntLiteral literal){
+		return createInteger
+	}
+
+	def createInteger() {
+		val type = TypesFactory::eINSTANCE.createType()
+		type.name = "integer"
+		return type
 	} 
 	
-	def dispatch type(BoolLiteral bool){
-		return typeof(Boolean)
+	def dispatch getType(BoolLiteral bool){
+		return createBoolean
 	}
 	
-	def dispatch type(RealLiteral literal){
-		return typeof(Number)
+	def dispatch getType(RealLiteral literal){
+		return createReal
 	}
-	
-	def toJavaType(Type type){
-		if(isBoolean(type)){
-			return typeof(Boolean)
-		}
-		else if(isInteger(type)){
-			return typeof(Number)
-		}
-		else if(isReal(type)){
-			return typeof(Number)
-		} 
-		return typeof(Void)
+	def dispatch getType(StringLiteral literal){
+		return createString
+	}
+	def createReal() {
+		val type = TypesFactory::eINSTANCE.createType()
+		type.name = "real"
+		return type
+	}
+	def createString() {
+		val type = TypesFactory::eINSTANCE.createType()
+		type.name = "string"
+		return type
 	}
 	
-	def assertIsNumber(Object object, String operator){
-		if(!(object == typeof(Number)))
+//	def toJavaType(Type type){
+//		if(isBoolean(type)){
+//			return typeof(Boolean)
+//		}
+//		else if(isInteger(type)){
+//			return typeof(Number)
+//		}
+//		else if(isReal(type)){
+//			return typeof(Number)
+//		} 
+//		return typeof(Void)
+//	}
+	
+	def Type assertIsNumber(Type object, String operator){
+		if(!object.real && !object.integer) {
 			error("operator '" +operator+"' can only be applied to numbers!")
+			return null
+		}
+		return object
 	}
-	def assertIsBoolean(Object object, String operator){
-		if(!(object == typeof(Boolean)))
+	def Type assertIsBoolean(Type object, String operator){
+		if(!object.^boolean) {
 			error("operator '" +operator+"' can only be applied to boolean values!")
+		}
+		return object
 	}
 	
 	def error(String msg){
-		throw new TypeCheckException(msg)
+		if (acceptor != null) {
+			acceptor.acceptError(msg)
+		}
+	}
+	
+	
+	override isBoolean(Type type){
+		return type != null && type.name == "boolean";	
+	}
+	
+	override isInteger(Type type){
+		return type != null && (type.name =="integer" || type.name =="int");
+	}
+	
+	override isReal(Type type){
+		return type != null && type.name == "real";	
+	}
+	override isString(Type type) {
+		return type != null && type.name == "string";	
+	}
+	def dispatch inferType(Expression expr) {
+		return null;
+	}
+	
+	override isAssignable(Type expected, Type actual) {
+		if (expected.equals(combine(expected, actual))) {
+			return true
+		}
+		if ((expected.integer || expected.real) && (actual.integer || actual.real)) {
+			return true
+		}
+		return false
+	}
+	
+	override combine(Type typeOne, Type typeTwo) {
+		if (typeOne.equals(typeTwo) 
+			|| typeOne.name.equals(typeTwo.name)) {
+			return typeOne;
+		}
+		val typesOne = typeOne.allSuperTypes
+		val typesTwo = typeTwo.allSuperTypes
+		
+		val superType = typesOne.findFirst(t|typesTwo.contains(t))
+		if (superType != null) {
+			return superType
+		}
+		
+		return null;
+	}
+	
+	def allSuperTypes(Type type) {
+		val types = <Type>newLinkedHashSet()
+		types.add(type)
+		var newSuperTypes = <Type>newArrayList()
+		newSuperTypes.addAll(type.superTypes)
+		while (!newSuperTypes.empty) {
+			val oldSuperTypes = newSuperTypes
+			newSuperTypes = <Type>newArrayList()
+			for (superType : oldSuperTypes) {
+				if (!types.contains(superType)) {
+					types.add(superType)
+					newSuperTypes.addAll(superType.superTypes)
+				}
+			}
+		}
+		return types
 	}
 
 }

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

@@ -12,13 +12,13 @@
 package org.yakindu.sct.model.stext.validation;
 
 /**
- * checked Exception thrown by the {@link StaticTypeAnalyzer} if a type
+ * runtime Exception thrown by the {@link StaticTypeAnalyzer} if a type
  * conformance check fails.
  * 
  * @author andreas muelder - Initial contribution and API
  * 
  */
-public class TypeCheckException extends Exception {
+public class TypeCheckException extends RuntimeException {
 
 	private static final long serialVersionUID = 1L;
 

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 503 - 321
plugins/org.yakindu.sct.model.stext/xtend-gen/org/yakindu/sct/model/stext/validation/StaticTypeAnalyzer.java