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.constants.IntegerConstant; import org.simantics.scl.compiler.constants.LongConstant; 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.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 EIntegerLiteral extends SimplifiableExpression { public String value; public EVariable constraint; public EIntegerLiteral(String value) { this.value = value; } @Override public void collectVars(TObjectIntHashMap allVars, TIntHashSet vars) { } public String getValue() { return value; } private Expression tryToConvertToPrimitive(Type requiredType) { if(requiredType.equals(Types.INTEGER)) return new ELiteral(new IntegerConstant(Integer.parseInt(value))); else 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.LONG)) return new ELiteral(new LongConstant(Long.parseLong(value))); else return null; } @Override public Expression checkBasicType(TypingContext context, Type requiredType) { requiredType = Types.canonical(requiredType); try { Expression primitive = tryToConvertToPrimitive(requiredType); if(primitive != null) return primitive; } catch(NumberFormatException e) { context.getErrorLog().log(getLocation(), "Invalid number format."); } setType(requiredType); constraint = new EVariable(location, null); constraint.setType(Types.pred(Types.RING, requiredType)); context.addConstraintDemand(constraint); return this; } @Override protected void updateType() throws MatchException { throw new InternalCompilerError(); } @Override public Expression simplify(SimplificationContext context) { try { Expression primitive = tryToConvertToPrimitive(Types.canonical(getType())); if(primitive != null) return primitive; return context.apply( context.getConstant(Names.Prelude_fromInteger, getType()), constraint.simplify(context), context.literal(new IntegerConstant(Integer.parseInt(value))) ); } catch(NumberFormatException e) { context.getErrorLog().log(getLocation(), "Invalid number format (maybe too long for the expected number type)."); return this; } } @Override public Expression resolve(TranslationContext context) { return this; } @Override public Expression resolveAsPattern(TranslationContext context) { return this; } @Override public Expression replace(ReplaceContext context) { EIntegerLiteral copy = new EIntegerLiteral(value); copy.setType(getType().replace(context.tvarMap)); copy.constraint = (EVariable)constraint.replace(context); return copy; } @Override public boolean isEffectful() { return false; } @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); } @Override public boolean isPattern(int arity) { return arity == 0; } @Override public Expression accept(ExpressionTransformer transformer) { return transformer.transform(this); } }