ConstantExpression
using CLanguage.Compiler;
using CLanguage.Interpreter;
using CLanguage.Types;
using System;
using System.Runtime.CompilerServices;
namespace CLanguage.Syntax
{
[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
public class ConstantExpression : Expression
{
public static readonly ConstantExpression Zero = new ConstantExpression(0);
public static readonly ConstantExpression One = new ConstantExpression(1);
public static readonly ConstantExpression NegativeOne = new ConstantExpression(-1);
public static readonly ConstantExpression True = new ConstantExpression(true);
public static readonly ConstantExpression False = new ConstantExpression(false);
public object Value { get; set; }
public CType ConstantType { get; set; }
public ConstantExpression(object val, CType type)
: this(val)
{
ConstantType = type;
}
public ConstantExpression(object val)
{
Value = val;
if (Value is string)
ConstantType = CPointerType.PointerToConstChar;
else if (Value is bool) {
ConstantType = CBasicType.Bool;
} else if (Value is byte) {
ConstantType = CBasicType.UnsignedChar;
} else if (Value is char) {
ConstantType = CBasicType.SignedChar;
} else if (Value is ushort) {
ConstantType = CBasicType.UnsignedShortInt;
} else if (Value is short) {
ConstantType = CBasicType.SignedShortInt;
} else if (Value is uint) {
ConstantType = CBasicType.UnsignedInt;
} else if (Value is int) {
ConstantType = CBasicType.SignedInt;
} else if (Value is ulong) {
ConstantType = CBasicType.UnsignedLongInt;
} else if (Value is long) {
ConstantType = CBasicType.SignedLongInt;
} else if (Value is float) {
ConstantType = CBasicType.Float;
} else if (Value is double) {
ConstantType = CBasicType.Double;
} else {
ConstantType = CBasicType.SignedInt;
}
}
public override CType GetEvaluatedCType(EmitContext ec)
{
return ConstantType;
}
protected override void DoEmit(EmitContext ec)
{
Value x = EvalConstant(ec);
ec.Emit(OpCode.LoadConstant, x);
}
public override string ToString()
{
return Value.ToString();
}
public override Value EvalConstant(EmitContext ec)
{
CIntType cIntType = ConstantType as CIntType;
if (cIntType != null) {
int byteSize = cIntType.GetByteSize(ec);
if (cIntType.Signedness != Signedness.Signed) {
switch (byteSize) {
case 1:
return (byte)Convert.ToInt64(Value);
case 2:
return (ushort)Convert.ToInt64(Value);
case 4:
return (uint)Convert.ToInt64(Value);
case 8:
return Convert.ToUInt64(Value);
default:
throw new NotSupportedException("Unsigned integral constants with type '" + ConstantType?.ToString() + "'");
}
}
switch (byteSize) {
case 1:
return (sbyte)Convert.ToInt64(Value);
case 2:
return (short)Convert.ToInt64(Value);
case 4:
return (int)Convert.ToInt64(Value);
case 8:
return Convert.ToInt64(Value);
default:
throw new NotSupportedException("Signed integral constants with type '" + ConstantType?.ToString() + "'");
}
}
if (ConstantType is CBoolType)
return (byte)(((bool)Value) ? 1 : 0);
CFloatType cFloatType = ConstantType as CFloatType;
if (cFloatType != null) {
if (cFloatType.Bits != 64)
return Convert.ToSingle(Value);
return Convert.ToDouble(Value);
}
string text = Value as string;
if (text != null)
return ec.GetConstantMemory(text);
throw new NotSupportedException("Non-basic constants with type '" + ConstantType?.ToString() + "'");
}
}
}