//
// constant.cs: Constants.
//
// Author:
// Miguel de Icaza (miguel@ximian.com)
//
// (C) 2001 Ximian, Inc.
//
//
namespace Mono.CSharp {
using System;
using System.Reflection.Emit;
///
/// Base class for constants and literals.
///
public abstract class Constant : Expression {
protected Constant ()
{
eclass = ExprClass.Value;
}
///
/// This is different from ToString in that ToString
/// is supposed to be there for debugging purposes,
/// and is not guaranteed to be useful for anything else,
/// AsString() will provide something that can be used
/// for round-tripping C# code. Maybe it can be used
/// for IL assembly as well.
///
public abstract string AsString ();
override public string ToString ()
{
return AsString ();
}
///
/// This is used to obtain the actual value of the literal
/// cast into an object.
///
public abstract object GetValue ();
///
/// Constants are always born in a fully resolved state
///
public override Expression DoResolve (EmitContext ec)
{
return this;
}
}
public class BoolConstant : Constant {
public readonly bool Value;
public BoolConstant (bool val)
{
type = TypeManager.bool_type;
Value = val;
}
override public string AsString ()
{
return Value ? "true" : "false";
}
public override object GetValue ()
{
return (object) Value;
}
public override void Emit (EmitContext ec)
{
if (Value)
ec.ig.Emit (OpCodes.Ldc_I4_1);
else
ec.ig.Emit (OpCodes.Ldc_I4_0);
}
}
public class ByteConstant : Constant {
public readonly byte Value;
public ByteConstant (byte v)
{
type = TypeManager.byte_type;
Value = v;
}
public override void Emit (EmitContext ec)
{
IntLiteral.EmitInt (ec.ig, Value);
}
public override string AsString ()
{
return Value.ToString ();
}
public override object GetValue ()
{
return Value;
}
}
public class CharConstant : Constant {
public readonly char Value;
public CharConstant (char v)
{
type = TypeManager.char_type;
Value = v;
}
public override void Emit (EmitContext ec)
{
IntLiteral.EmitInt (ec.ig, Value);
}
static public string descape (char c)
{
switch (c){
case '\a':
return "\\a";
case '\b':
return "\\b";
case '\n':
return "\\n";
case '\t':
return "\\t";
case '\v':
return "\\v";
case '\r':
return "\\r";
case '\\':
return "\\\\";
case '\f':
return "\\f";
case '\0':
return "\\0";
case '"':
return "\\\"";
case '\'':
return "\\\'";
}
return c.ToString ();
}
public override string AsString ()
{
return "\"" + descape (Value) + "\"";
}
public override object GetValue ()
{
return Value;
}
}
public class SByteConstant : Constant {
public readonly sbyte Value;
public SByteConstant (sbyte v)
{
type = TypeManager.sbyte_type;
Value = v;
}
public override void Emit (EmitContext ec)
{
IntLiteral.EmitInt (ec.ig, Value);
}
public override string AsString ()
{
return Value.ToString ();
}
public override object GetValue ()
{
return Value;
}
}
public class ShortConstant : Constant {
public readonly short Value;
public ShortConstant (short v)
{
type = TypeManager.short_type;
Value = v;
}
public override void Emit (EmitContext ec)
{
IntLiteral.EmitInt (ec.ig, Value);
}
public override string AsString ()
{
return Value.ToString ();
}
public override object GetValue ()
{
return Value;
}
}
public class UShortConstant : Constant {
public readonly ushort Value;
public UShortConstant (ushort v)
{
type = TypeManager.ushort_type;
Value = v;
}
public override void Emit (EmitContext ec)
{
IntLiteral.EmitInt (ec.ig, Value);
}
public override string AsString ()
{
return Value.ToString ();
}
public override object GetValue ()
{
return Value;
}
}
public class IntConstant : Constant {
public readonly int Value;
public IntConstant (int v)
{
type = TypeManager.int32_type;
Value = v;
}
static public void EmitInt (ILGenerator ig, int i)
{
switch (i){
case -1:
ig.Emit (OpCodes.Ldc_I4_M1);
break;
case 0:
ig.Emit (OpCodes.Ldc_I4_0);
break;
case 1:
ig.Emit (OpCodes.Ldc_I4_1);
break;
case 2:
ig.Emit (OpCodes.Ldc_I4_2);
break;
case 3:
ig.Emit (OpCodes.Ldc_I4_3);
break;
case 4:
ig.Emit (OpCodes.Ldc_I4_4);
break;
case 5:
ig.Emit (OpCodes.Ldc_I4_5);
break;
case 6:
ig.Emit (OpCodes.Ldc_I4_6);
break;
case 7:
ig.Emit (OpCodes.Ldc_I4_7);
break;
case 8:
ig.Emit (OpCodes.Ldc_I4_8);
break;
default:
if (i >= -128 && i <= 127){
ig.Emit (OpCodes.Ldc_I4_S, (sbyte) i);
} else
ig.Emit (OpCodes.Ldc_I4, i);
break;
}
}
public override void Emit (EmitContext ec)
{
EmitInt (ec.ig, Value);
}
public override string AsString ()
{
return Value.ToString ();
}
public override object GetValue ()
{
return Value;
}
}
public class UIntConstant : Constant {
public readonly uint Value;
public UIntConstant (uint v)
{
type = TypeManager.uint32_type;
Value = v;
}
public override void Emit (EmitContext ec)
{
IntLiteral.EmitInt (ec.ig, unchecked ((int) Value));
}
public override string AsString ()
{
return Value.ToString ();
}
public override object GetValue ()
{
return Value;
}
}
public class LongConstant : Constant {
public readonly long Value;
public LongConstant (long v)
{
type = TypeManager.int64_type;
Value = v;
}
public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
EmitLong (ig, Value);
}
static public void EmitLong (ILGenerator ig, long l)
{
ig.Emit (OpCodes.Ldc_I8, l);
}
public override string AsString ()
{
return Value.ToString ();
}
public override object GetValue ()
{
return Value;
}
}
public class ULongConstant : Constant {
public readonly ulong Value;
public ULongConstant (ulong v)
{
type = TypeManager.uint64_type;
Value = v;
}
public override void Emit (EmitContext ec)
{
ILGenerator ig = ec.ig;
LongLiteral.EmitLong (ig, unchecked ((long) Value));
}
public override string AsString ()
{
return Value.ToString ();
}
public override object GetValue ()
{
return Value;
}
}
public class FloatConstant : Constant {
public readonly float Value;
public FloatConstant (float v)
{
type = TypeManager.float_type;
Value = v;
}
public override void Emit (EmitContext ec)
{
ec.ig.Emit (OpCodes.Ldc_R4, Value);
}
public override string AsString ()
{
return Value.ToString ();
}
public override object GetValue ()
{
return Value;
}
}
public class DoubleConstant : Constant {
public readonly double Value;
public DoubleConstant (double v)
{
type = TypeManager.double_type;
Value = v;
}
public override void Emit (EmitContext ec)
{
ec.ig.Emit (OpCodes.Ldc_R8, Value);
}
public override string AsString ()
{
return Value.ToString ();
}
public override object GetValue ()
{
return Value;
}
}
public class DecimalConstant : Constant {
public readonly decimal Value;
public DecimalConstant (decimal d)
{
type = TypeManager.decimal_type;
Value = d;
}
override public string AsString ()
{
return Value.ToString ();
}
public override object GetValue ()
{
return (object) Value;
}
public override void Emit (EmitContext ec)
{
throw new Exception ("Implement me");
}
}
public class StringConstant : Constant {
public readonly string Value;
public StringConstant (string s)
{
type = TypeManager.string_type;
Value = s;
}
// FIXME: Escape the string.
override public string AsString ()
{
return "\"" + Value + "\"";
}
public override object GetValue ()
{
return Value;
}
public override void Emit (EmitContext ec)
{
ec.ig.Emit (OpCodes.Ldstr, Value);
}
}
}