@Override public void visit(ASTExpr expr) { final Either<TypeSymbol, String> baseType = expr.getBase().get().getType(); final Either<TypeSymbol, String> exponentType = expr.getExponent().get().getType(); if (baseType.isError()) { expr.setType(baseType); return; } if (exponentType.isError()) { expr.setType(exponentType); return; } else if (isNumeric(baseType.getValue()) && isNumeric(exponentType.getValue())) { if (isInteger(baseType.getValue()) && isInteger(exponentType.getValue())) { expr.setType(Either.value(getIntegerType())); return; } else if (isUnit(baseType.getValue())) { if (!isInteger(exponentType.getValue())) { final String errorMsg = ERROR_CODE + " " + AstUtils.print(expr.get_SourcePositionStart()) + " : " + "With a Unit base, the exponent must be an integer."; expr.setType(Either.error(errorMsg)); error(errorMsg, expr.get_SourcePositionStart()); return; } UnitRepresentation baseRep = new UnitRepresentation(baseType.getValue().getName()); Either<Integer, String> numericValue = calculateNumericValue( expr.getExponent() .get()); // calculate exponent value if exponent composed of literals if (numericValue.isValue()) { expr.setType( Either.value( getTypeIfExists((baseRep.pow(numericValue.getValue())).serialize()).get())); return; } else { final String errorMsg = numericValue.getError(); expr.setType(Either.error(errorMsg)); error(errorMsg, expr.get_SourcePositionStart()); return; } } else { expr.setType(Either.value(getRealType())); return; } } // Catch-all if no case has matched final String errorMsg = ERROR_CODE + " " + AstUtils.print(expr.get_SourcePositionStart()) + " : " + "Cannot determine the type of the expression: " + baseType.getValue().prettyPrint() + "**" + exponentType.getValue().prettyPrint(); expr.setType(Either.error(errorMsg)); error(errorMsg, expr.get_SourcePositionStart()); }
public void visit(ASTEquation astEquation) { if (astEquation.getRhs().getType().isError()) { warn( ERROR_CODE + ": Error in Expression type calculation: " + astEquation.getRhs().getType().getError()); return; } if (!astEquation.getEnclosingScope().isPresent()) { warn(ERROR_CODE + "Enclosing scope not present. Run ScopeCreator"); return; } // Resolve LHS Variable String varName = astEquation.getLhs().getSimpleName(); Scope enclosingScope = astEquation.getEnclosingScope().get(); Optional<VariableSymbol> varSymbol = NESTMLSymbols.resolve(varName, enclosingScope); TypeSymbol varType; if (!varSymbol.isPresent()) { warn(ERROR_CODE + " Error while resolving the variable to be derived in ODE: " + varName); return; } // Derive varType varType = varSymbol.get().getType(); if (varType.getType() != TypeSymbol.Type.UNIT && varType != getRealType()) { warn( ERROR_CODE + "Type of LHS Variable in ODE is neither a Unit nor real at: " + astEquation.get_SourcePositionStart() + ". Skipping."); return; } UnitRepresentation varUnit = new UnitRepresentation(varType.getName()); UnitRepresentation derivedVarUnit = varUnit.deriveT(astEquation.getLhs().getDifferentialOrder().size()); // get type of RHS expression TypeSymbol typeFromExpression = astEquation.getRhs().getType().getValue(); if (typeFromExpression.getType() != TypeSymbol.Type.UNIT && typeFromExpression != getRealType()) { warn( ERROR_CODE + "Type of ODE is neither a Unit nor real at: " + astEquation.get_SourcePositionStart()); return; } UnitRepresentation unitFromExpression = new UnitRepresentation(typeFromExpression.getName()); // set any of the units to ignoreMagnitude unitFromExpression.setIgnoreMagnitude(true); // do the actual test: if (!unitFromExpression.equals(derivedVarUnit)) { // remove magnitude for clearer error message derivedVarUnit.setMagnitude(0); unitFromExpression.setMagnitude(0); warn( ERROR_CODE + "Type of (derived) variable " + astEquation.getLhs().toString() + " is: " + derivedVarUnit.prettyPrint() + ". This does not match Type of RHS expression: " + unitFromExpression.prettyPrint() + " at: " + astEquation.get_SourcePositionStart() + ". Magnitudes are ignored in ODE Expressions"); } }