package org.eclipse.iee.translator.antlr.translator; import java.util.List; import java.util.Map; import org.antlr.v4.runtime.ParserRuleContext; import org.antlr.v4.runtime.tree.ParseTree; import org.antlr.v4.runtime.tree.RuleNode; import org.eclipse.iee.core.document.source.IVariableType; import org.eclipse.iee.core.document.source.VariableType; import org.eclipse.iee.translator.antlr.math.MathBaseVisitor; import org.eclipse.iee.translator.antlr.math.MathParser.ExpressionContext; import org.eclipse.iee.translator.antlr.math.MathParser.FloatNumberContext; import org.eclipse.iee.translator.antlr.math.MathParser.FunctionDefinitionContext; import org.eclipse.iee.translator.antlr.math.MathParser.IntNumberContext; import org.eclipse.iee.translator.antlr.math.MathParser.InternalFunctionContext; import org.eclipse.iee.translator.antlr.math.MathParser.IntervalParameterContext; import org.eclipse.iee.translator.antlr.math.MathParser.MatrixContext; import org.eclipse.iee.translator.antlr.math.MathParser.MatrixElementContext; import org.eclipse.iee.translator.antlr.math.MathParser.MatrixRowContext; import org.eclipse.iee.translator.antlr.math.MathParser.MethodCallContext; import org.eclipse.iee.translator.antlr.math.MathParser.ParameterContext; import org.eclipse.iee.translator.antlr.math.MathParser.PowerContext; import org.eclipse.iee.translator.antlr.math.MathParser.RangeExprContext; import org.eclipse.iee.translator.antlr.math.MathParser.StandardFunctionContext; import org.eclipse.iee.translator.antlr.math.MathParser.VariableAssignmentContext; import org.eclipse.iee.translator.antlr.math.MathParser.VariableContext; import com.google.common.collect.Maps; public class TypeVisitior extends MathBaseVisitor<IVariableType> { private ExternalTranslationContext fExternalContext; private Map<ParseTree, IVariableType> types = Maps.newHashMap(); private Scope scope = new Scope(null); public TypeVisitior(ExternalTranslationContext fExternalContext) { this.fExternalContext = fExternalContext; } @Override public IVariableType visit(ParseTree tree) { if (types.containsKey(tree)) { return types.get(tree); } IVariableType result = super.visit(tree); types.put(tree, result); return result; } @Override public IVariableType visitChildren(RuleNode tree) { if (types.containsKey(tree)) { return types.get(tree); } IVariableType result = super.visitChildren(tree); types.put(tree, result); return result; } @Override public IVariableType visitVariableAssignment(VariableAssignmentContext ctx) { return visit(ctx.value); } @Override public IVariableType visitIntNumber(IntNumberContext ctx) { return VariableType.DOUBLE; } @Override public IVariableType visitFloatNumber(FloatNumberContext ctx) { return VariableType.DOUBLE; } @Override public IVariableType visitMatrix(MatrixContext ctx) { return VariableType.MATRIX; } @Override public IVariableType visitMatrixElement(MatrixElementContext ctx) { return VariableType.DOUBLE; } @Override public IVariableType visitMatrixRow(MatrixRowContext ctx) { return VariableType.MATRIX; } @Override public IVariableType visitPower(PowerContext ctx) { if (types.containsKey(ctx)) { return types.get(ctx); } IVariableType result; IVariableType left = visit(ctx.left); String right = ctx.right.getText(); if (VariableType.MATRIX.equals(left) && right.matches("T")) { result = VariableType.MATRIX; } else { result = VariableType.DOUBLE; } types.put(ctx, result); return result; } @Override public IVariableType visitVariable(VariableContext ctx) { if (types.containsKey(ctx)) { return types.get(ctx); } IVariableType result; String text = ctx.getText(); String name = fExternalContext.translateName(text); IVariableType variableType = scope.getVariableType(text); if (variableType == null) { variableType = getScope(ctx).getVariableType(text); if (variableType == null) { variableType = fExternalContext.getVariableType(name); if (variableType == null) { throw new IllegalArgumentException("Unknown variable " + text); } } } result = variableType; types.put(ctx, result); return variableType; } private Scope getScope(ParserRuleContext ctx) { Scope scope; if (ctx.getParent() != null) { scope = new Scope(getScope(ctx.getParent())); } else { scope = new Scope(null); } if (ctx instanceof InternalFunctionContext) { List<ParameterContext> params = ((InternalFunctionContext) ctx).params; for (int i = 0; i < params.size(); i++) { if (params.get(i) instanceof IntervalParameterContext) { IntervalParameterContext param = (IntervalParameterContext) params .get(i); String paramVariable = param.variable.getText(); scope.addVariable(paramVariable, VariableType.DOUBLE); } } } else if (ctx instanceof StandardFunctionContext) { List<ExpressionContext> params = ((StandardFunctionContext) ctx).params; for (ExpressionContext expressionContext : params) { scope.addVariable(expressionContext.getText(), VariableType.DOUBLE); } } else if (ctx instanceof FunctionDefinitionContext) { StandardFunctionContext name = ((FunctionDefinitionContext) ctx).name; List<ExpressionContext> params = name.params; for (ExpressionContext expressionContext : params) { scope.addVariable(expressionContext.getText(), VariableType.DOUBLE); } } return scope; } @Override public IVariableType visitStandardFunction(StandardFunctionContext ctx) { String text = ctx.name.getText(); IVariableType functionType = fExternalContext.getFunctionType(text); if (functionType == null) { throw new IllegalArgumentException("Unknown function " + text); } return functionType; } @Override public IVariableType visitInternalFunction(InternalFunctionContext ctx) { if (types.containsKey(ctx)) { return types.get(ctx); } IVariableType result; scope = new Scope(scope); for (int i = 0; i < ctx.params.size(); i++) { if (ctx.params.get(i) instanceof IntervalParameterContext) { IntervalParameterContext param = (IntervalParameterContext) ctx.params .get(i); String paramVariable = param.variable.getText(); scope.addVariable(paramVariable, VariableType.DOUBLE); } } scope = scope.getParent(); result = VariableType.DOUBLE; types.put(ctx, result); return result; } @Override public IVariableType visitRangeExpr(RangeExprContext ctx) { return VariableType.RANGE; } @Override public IVariableType visitFunctionDefinition(FunctionDefinitionContext ctx) { if (types.containsKey(ctx)) { return types.get(ctx); } IVariableType result; scope = new Scope(scope); StandardFunctionContext name = ctx.name; List<ExpressionContext> params = name.params; for (ExpressionContext expressionContext : params) { scope.addVariable(expressionContext.getText(), VariableType.DOUBLE); } result = visit(ctx.value); scope = scope.getParent(); types.put(ctx, result); return result; } @Override public IVariableType visitMethodCall(MethodCallContext ctx) { if (types.containsKey(ctx)) { return types.get(ctx); } IVariableType result; ExpressionContext container = ctx.container; IVariableType containerType = visit(container); String text = ctx.func.name.getText(); IVariableType methodType = containerType.getMethodType(text); if (methodType == null) { throw new IllegalArgumentException("Unknown method " + text); } result = methodType; types.put(ctx, result); return result; } @Override protected IVariableType aggregateResult(IVariableType aggregate, IVariableType nextResult) { if (nextResult == aggregate) { return aggregate; } else if (nextResult == null) { return aggregate; } else if (aggregate == null) { return nextResult; } else if ((VariableType.DOUBLE.equals(aggregate) && VariableType.INT.equals(nextResult)) || (VariableType.DOUBLE.equals(nextResult) && VariableType.INT.equals(aggregate))) { return VariableType.DOUBLE; } else if (((VariableType.DOUBLE.equals(aggregate) || VariableType.INT.equals(aggregate)) && VariableType.MATRIX.equals(nextResult)) || ((VariableType.DOUBLE.equals(nextResult) || VariableType.INT.equals(nextResult)) && VariableType.MATRIX.equals(aggregate))) { return VariableType.MATRIX; } throw new RuntimeException(); } }