package dyvil.tools.compiler.ast.constant;

import dyvil.tools.compiler.ast.annotation.IAnnotation;
import dyvil.tools.compiler.ast.context.IContext;
import dyvil.tools.compiler.ast.expression.IValue;
import dyvil.tools.compiler.ast.expression.LiteralConversion;
import dyvil.tools.compiler.ast.generic.ITypeContext;
import dyvil.tools.compiler.ast.type.IType;
import dyvil.tools.compiler.ast.type.builtin.Types;
import dyvil.tools.compiler.backend.MethodWriter;
import dyvil.tools.compiler.backend.exception.BytecodeException;
import dyvil.tools.parsing.marker.MarkerList;
import dyvil.tools.parsing.position.ICodePosition;

public class FloatValue implements IConstantValue
{
	private static FloatValue NULL;

	protected ICodePosition position;
	protected float         value;

	public FloatValue(float value)
	{
		this.value = value;
	}

	public FloatValue(ICodePosition position, float value)
	{
		this.position = position;
		this.value = value;
	}

	public static FloatValue getNull()
	{
		if (NULL == null)
		{
			NULL = new FloatValue(0F);
		}
		return NULL;
	}

	@Override
	public ICodePosition getPosition()
	{
		return this.position;
	}

	@Override
	public void setPosition(ICodePosition position)
	{
		this.position = position;
	}

	@Override
	public int valueTag()
	{
		return FLOAT;
	}

	@Override
	public boolean isPrimitive()
	{
		return true;
	}

	@Override
	public IType getType()
	{
		return Types.FLOAT;
	}

	@Override
	public IValue withType(IType type, ITypeContext typeContext, MarkerList markers, IContext context)
	{
		if (type == Types.FLOAT)
		{
			return this;
		}
		if (Types.isExactType(type, Types.DOUBLE))
		{
			return new DoubleValue(this.position, this.value);
		}
		if (Types.isExactType(type, Types.FLOAT))
		{
			return this;
		}

		final IAnnotation annotation = type.getAnnotation(Types.FROMFLOAT_CLASS);
		if (annotation != null)
		{
			return new LiteralConversion(this, annotation).withType(type, typeContext, markers, context);
		}
		return null;
	}

	@Override
	public boolean isType(IType type)
	{
		return Types.isSuperType(type, Types.FLOAT) || type.getAnnotation(Types.FROMFLOAT_CLASS) != null;
	}

	@Override
	public int getTypeMatch(IType type)
	{
		final int i = IConstantValue.super.getTypeMatch(type);
		if (i != MISMATCH)
		{
			return i;
		}
		if (type.getAnnotation(Types.FROMFLOAT_CLASS) != null)
		{
			return CONVERSION_MATCH;
		}
		return 0;
	}

	@Override
	public int intValue()
	{
		return (int) this.value;
	}

	@Override
	public long longValue()
	{
		return (long) this.value;
	}

	@Override
	public float floatValue()
	{
		return this.value;
	}

	@Override
	public double doubleValue()
	{
		return this.value;
	}

	@Override
	public Float toObject()
	{
		return this.value;
	}

	@Override
	public int stringSize()
	{
		return Float.toString(this.value).length();
	}

	@Override
	public boolean toStringBuilder(StringBuilder builder)
	{
		builder.append(this.value);
		return true;
	}

	@Override
	public void writeExpression(MethodWriter writer, IType type) throws BytecodeException
	{
		writer.visitLdcInsn(this.value);

		if (type != null)
		{
			Types.FLOAT.writeCast(writer, type, this.getLineNumber());
		}
	}

	@Override
	public String toString()
	{
		if (!Float.isFinite(this.value))
		{
			return String.valueOf(this.value);
		}
		return this.value + "F";
	}

	@Override
	public void toString(String prefix, StringBuilder buffer)
	{
		buffer.append(this.value);
		if (Float.isFinite(this.value))
		{
			buffer.append('F');
		}
	}
}

@@ -1698,37 +1698,37 @@
 %7D%0A%09%09if (Types.is
-Exact
+Super
 Type(type, Types

Fix float literal boxing