package org.simantics.scl.compiler.elaboration.expressions; import org.simantics.scl.compiler.common.exceptions.InternalCompilerError; import org.simantics.scl.compiler.common.names.Names; import org.simantics.scl.compiler.constants.DoubleConstant; import org.simantics.scl.compiler.constants.FloatConstant; import org.simantics.scl.compiler.elaboration.contexts.ReplaceContext; import org.simantics.scl.compiler.elaboration.contexts.SimplificationContext; import org.simantics.scl.compiler.elaboration.contexts.TranslationContext; import org.simantics.scl.compiler.elaboration.contexts.TypingContext; import org.simantics.scl.compiler.errors.ErrorLog; import org.simantics.scl.compiler.errors.Locations; import org.simantics.scl.compiler.types.Type; import org.simantics.scl.compiler.types.Types; import org.simantics.scl.compiler.types.exceptions.MatchException; import gnu.trove.map.hash.TObjectIntHashMap; import gnu.trove.set.hash.TIntHashSet; public class ERealLiteral extends SimplifiableExpression { public String value; public EVariable constraint; public ERealLiteral(String value) { this.value = value; } @Override public void collectVars(TObjectIntHashMap allVars, TIntHashSet vars) { } private Expression tryToConvertToPrimitive(ErrorLog errorLog, Type requiredType) { if(requiredType.equals(Types.DOUBLE)) return new ELiteral(new DoubleConstant(Double.parseDouble(value))); else if(requiredType.equals(Types.FLOAT)) return new ELiteral(new FloatConstant(Float.parseFloat(value))); else if(requiredType.equals(Types.INTEGER)) { errorLog.log(location, "Cannot convert real literal to Integer."); return new EError(); } else if(requiredType.equals(Types.LONG)) { errorLog.log(location, "Cannot convert real literal to Long."); return new EError(); } else return null; } @Override public Expression checkBasicType(TypingContext context, Type requiredType) { requiredType = Types.canonical(requiredType); Expression primitive = tryToConvertToPrimitive(context.getErrorLog(), requiredType); if(primitive != null) return primitive; else { setType(requiredType); constraint = new EVariable(location, null); constraint.setType(Types.pred(Types.REAL, requiredType)); context.addConstraintDemand(constraint); return this; } } @Override protected void updateType() throws MatchException { throw new InternalCompilerError("TODO"); } @Override public Expression simplify(SimplificationContext context) { Expression primitive = tryToConvertToPrimitive(context.getErrorLog(), getType()); if(primitive != null) return primitive; return context.apply( context.getConstant(Names.Prelude_fromDouble, getType()), constraint.simplify(context), context.literal(new DoubleConstant(Double.parseDouble(value))) ); } @Override public Expression resolve(TranslationContext context) { return this; } @Override public Expression resolveAsPattern(TranslationContext context) { return new ELiteral(new DoubleConstant(Double.parseDouble(value))); } @Override public Expression replace(ReplaceContext context) { ERealLiteral copy = new ERealLiteral(value); copy.setType(getType().replace(context.tvarMap)); return copy; } @Override public void setLocationDeep(long loc) { if(location == Locations.NO_LOCATION) { location = loc; if(constraint != null) constraint.setLocationDeep(loc); } } @Override public void accept(ExpressionVisitor visitor) { visitor.visit(this); } public String getValue() { return value; } @Override public Expression accept(ExpressionTransformer transformer) { return transformer.transform(this); } }