Click here to Skip to main content
15,883,795 members
Articles / Programming Languages / ASM

Bird Programming Language: Part 3

Rate me:
Please Sign up or sign in to vote.
4.88/5 (5 votes)
1 Jan 2013GPL35 min read 29.8K   282   14  
A new general purpose language that aims to be fast, high level and simple to use.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Numerics;

namespace Bird
{
	public enum ConstValueType : byte
	{
		Unknown,
		Integer,
		Float,
		Double,
		String,
		Char,
		Boolean,
		Zero,
		Structure,
		Null,
	}

	public static class Constants
	{
		public static bool CompareTupleValues(ConstValue Value, Predicate<ConstValue> Func)
		{
			if (Value is StructuredValue)
			{
				var SValue = Value as StructuredValue;
				for (var i = 0; i < SValue.Members.Count; i++)
					if (!Func(SValue.Members[i])) return false;

				return true;
			}

			return Func(Value);
		}

		public static ConstExpressionNode GetDefaultValue(Identifier Id, CodeString Code)
		{
			var Type = Id.RealId is Type ? Id.RealId as Type : Id.TypeOfSelf;
			return new ConstExpressionNode(Type, new ZeroValue(), Code);
		}

		public static ExpressionNode GetDefaultValue(PluginRoot Plugin, Identifier Id, CodeString Code)
		{
			return Plugin.NewNode(GetDefaultValue(Id, Code));
		}

		public static ConstExpressionNode GetDefaultValue(IdContainer Container, CodeString Code)
		{
			return GetDefaultValue(Container.GlobalContainer.CommonIds.Auto, Code);
		}

		public static ConstValueType TranslateConstValueType(ConstValueType Type)
		{
			if (Type == ConstValueType.Null || Type == ConstValueType.Zero || Type == ConstValueType.Structure)
				return ConstValueType.Unknown;

			return Type;
		}

		public static bool RecognizeString(CodeString Code, PluginRoot Plugin, out String Out)
		{
			Out = null;
			ConstValue Value;

			var StringType = Plugin.State.GlobalContainer.CommonIds.String;
			if (!Constants.Recognize(Code, StringType, Plugin, out Value))
				return false;

			if (Value is StringValue) Out = (Value as StringValue).Value;
			else if (!(Value is NullValue)) throw new ApplicationException();
			return true;
		}

		public static bool Recognize(CodeString Code, Identifier Type, PluginRoot Plugin, out ConstValue Out)
		{
			Out = null;
			var State = Plugin.State;
			var Node = Expressions.Recognize(Code, Plugin, true);

			if (!(Node.Type.RealId is StringType))
			{
				var TypeMngrPlugin = Plugin.GetPlugin<TypeMngrPlugin>();
				Node = TypeMngrPlugin.Convert(Node, Type, Code);
				if (Node == null) return false;
			}

			if (!(Node is ConstExpressionNode))
			{
				State.Messages.Add(MessageId.MustBeConst, Code);
				return false;
			}

			var CNode = Node as ConstExpressionNode;
			Out = CNode.Value;
			return true;
		}

		public static ConstExpressionNode CreateConstNode(IdContainer Container, Type RetType, CodeString Code)
		{
			var Plugin = new PluginForGlobals(Container);
			Plugin.GetPlugin<TypeMngrPlugin>().RetType = RetType;
			return Expressions.CreateExpression(Code, Plugin) as ConstExpressionNode;
		}

		public static ConstExpressionNode CreateCStrNode(IdContainer Container, CodeString Code)
		{
			return CreateConstNode(Container, Container.GlobalContainer.CommonIds.String, Code);
		}

		public static ConstExpressionNode CreateCIntNode(IdContainer Container, CodeString Code)
		{
			var Type = Container.GlobalContainer.CommonIds.Int32;
			return CreateConstNode(Container, Type, Code);
		}

		public static ConstExpressionNode CreateCUIntNode(IdContainer Container, CodeString Code)
		{
			var Type = Container.GlobalContainer.CommonIds.UInt32;
			return CreateConstNode(Container, Type, Code);
		}

		public static ConstExpressionNode GetStringValue(IdContainer Container, string Value, CodeString Code)
		{
			var Tp = Container.GlobalContainer.CommonIds.String;
			return new ConstExpressionNode(Tp, new StringValue(Value), Code);
		}

		public static ConstExpressionNode GetBoolValue(IdContainer Container, bool Value, CodeString Code)
		{
			var Tp = Container.GlobalContainer.CommonIds.Boolean;
			return new ConstExpressionNode(Tp, new BooleanValue(Value), Code);
		}

		public static ConstExpressionNode GetCharValue(IdContainer Container, char Value, CodeString Code)
		{
			var Tp = Container.GlobalContainer.CommonIds.Char;
			return new ConstExpressionNode(Tp, new CharValue(Value), Code);
		}

		public static ConstExpressionNode GetNullValue(IdContainer Container, CodeString Code)
		{
			var Type = Container.GlobalContainer.CommonIds.Null;
			return new ConstExpressionNode(Type, new NullValue(), Code);
		}

		public static ConstExpressionNode GetUIntPtrValue(IdContainer Container, int Val, CodeString Code)
        {
            var Type = Container.GlobalContainer.CommonIds.UIntPtr;
            return new ConstExpressionNode(Type, new IntegerValue(Val), Code);
		}
		
		public static ConstExpressionNode GetIntPtrValue(IdContainer Container, int Val, CodeString Code)
        {
            var Type = Container.GlobalContainer.CommonIds.IntPtr;
            return new ConstExpressionNode(Type, new IntegerValue(Val), Code);
		}

		public static ConstExpressionNode GetIntValue(IdContainer Container, int Val, CodeString Code, bool AutoConvert = false)
		{
			var IntType = Container.GlobalContainer.CommonIds.Int32;
			var Flags = AutoConvert ? ExpressionFlags.AutoConvert : ExpressionFlags.None;
			return new ConstExpressionNode(IntType, new IntegerValue(Val), Code, Flags);
		}

        public static ConstExpressionNode GetUIntValue(IdContainer Container, uint Val, CodeString Code)
        {
            var IntType = Container.GlobalContainer.CommonIds.UInt32;
            return new ConstExpressionNode(IntType, new IntegerValue(Val), Code);
        }

		public static ConstExpressionNode GetLongValue(IdContainer Container, long Val, CodeString Code)
		{
			var IntType = Container.GlobalContainer.CommonIds.Int64;
			return new ConstExpressionNode(IntType, new IntegerValue(Val), Code);
		}

		public static ConstExpressionNode GetDoubleValue(IdContainer Container, double Val, CodeString Code)
		{
			var DoubleType = Container.GlobalContainer.CommonIds.Double;
			return new ConstExpressionNode(DoubleType, new DoubleValue(Val), Code);
		}

		public static ConstExpressionNode GetFloatValue(IdContainer Container, float Val, CodeString Code)
		{
			var DoubleType = Container.GlobalContainer.CommonIds.Single;
			return new ConstExpressionNode(DoubleType, new FloatValue(Val), Code);
		}

		public static Type GetDefaultType(IdContainer Container, ConstValueType Type)
		{
			var Global = Container.GlobalContainer;
			if (Type == ConstValueType.Integer) return Container.GlobalContainer.CommonIds.Int32;
			if (Type == ConstValueType.Double) return Container.GlobalContainer.CommonIds.Double;
			if (Type == ConstValueType.Float) return Container.GlobalContainer.CommonIds.Single;
			if (Type == ConstValueType.String) return Global.CommonIds.String;
			if (Type == ConstValueType.Char) return Global.CommonIds.Char;
			if (Type == ConstValueType.Boolean) return Global.CommonIds.Boolean;
			throw new ApplicationException();
		}
	}

	public abstract class ConstValue
	{
		public abstract byte[] ToByteArray();
		public abstract ConstValue Copy();
		public abstract bool IsEqual(ConstValue Value);
		public abstract ConstValue DoOperation(ConstValue Src, Operator Op);
		public abstract ConstValue Convert(ConstValueType To);
		public abstract ConstValueType Type { get; }

		public virtual ConstValue GetMember(int Index)
		{
			throw new NotImplementedException();
		}

		public virtual ConstValue DoOperation(ConstValue Src, Operator Op, Identifier Type)
		{
			return DoOperation(Src, Op);
		}

		public virtual ConstValue Convert(Identifier To)
		{
			var Type = To.RealId as Type;
			return Convert(Type.ConstValueType);
		}

		public StructuredValue CreateStructure(int Count)
		{
			var Members = new List<ConstValue>();
			for (var i = 0; i < Count; i++)
				Members.Add(Copy());

			return new StructuredValue(Members);
		}

		public virtual double Double
		{
			get { throw new InvalidOperationException(); }
		}

		public virtual bool CheckBounds(Identifier Type)
		{
			return true;
		}

		public bool CheckBounds(CompilerState State, Identifier Type, CodeString Code)
		{
			if (!CheckBounds(Type))
			{
				State.Messages.Add(MessageId.ConstOutOfRange, Code);
				return false;
			}

			return true;
		}

		public ConstExpressionNode ToExpression(IdContainer Container, CodeString Code)
		{
			var T = Constants.GetDefaultType(Container, Type);
			if (!CheckBounds(Container.State, T, Code)) return null;
			return new ConstExpressionNode(T, this, Code);
		}

		public ConstExpressionNode ToExpression(CompilerState State, Identifier Type, CodeString Code)
		{
			if (!CheckBounds(State, Type, Code)) return null;
			return new ConstExpressionNode(Type, this, Code);
		}

		public ExpressionNode ToExpression(PluginRoot Plugin, CodeString Code)
		{
			var Node = ToExpression(Plugin.Container, Code);
			return Node == null ? null : Plugin.NewNode(Node);
		}

		public ExpressionNode ToExpression(PluginRoot Plugin, Identifier Type, CodeString Code)
		{
			var Node = ToExpression(Plugin.State, Type, Code);
			return Node == null ? null : Plugin.NewNode(Node);
		}

		byte[] AdjustBytes(int Size, bool Signed)
		{
			var Bytes = ToByteArray();
			if (Bytes.Length < Size)
			{
				var Old = Bytes;
				Bytes = new byte[Size];

				for (var i = 0; i < Old.Length; i++)
					Bytes[i] = Old[i];

				if (Signed && Bytes.Length > 0 && (Bytes[Old.Length - 1] & 0x80) != 0)
				{
					for (var i = Old.Length; i < Size; i++)
						Bytes[i] = 255;
				}
			}

			return Bytes;
		}

		public virtual unsafe long GetSigned(int Offset, int Size)
		{
			var Bytes = AdjustBytes(Offset + Size, true);
			fixed (byte* pBytes = Bytes)
			{
				var pBytesOffset = pBytes + Offset;
				if (Size == 1) return (long)(*(sbyte*)pBytesOffset);
				else if (Size == 2) return (long)(*(short*)pBytesOffset);
				else if (Size == 4) return (long)(*(int*)pBytesOffset);
				else if (Size == 8) return (*(long*)pBytesOffset);
				else throw new ApplicationException();
			}
		}

		public virtual unsafe ulong GetUnsigned(int Offset, int Size)
		{
			var Bytes = AdjustBytes(Offset + Size, false);
			fixed (byte* pBytes = Bytes)
			{
				var pBytesOffset = pBytes + Offset;
				if (Size == 1) return (ulong)(*(byte*)pBytesOffset);
				else if (Size == 2) return (ulong)(*(ushort*)pBytesOffset);
				else if (Size == 4) return (ulong)(*(uint*)pBytesOffset);
				else if (Size == 8) return (*(ulong*)pBytesOffset);
				else throw new ApplicationException();
			}
		}
	}

	public class StructuredValue : ConstValue
	{
		public List<ConstValue> Members;

		public StructuredValue(List<ConstValue> Members)
		{
			this.Members = Members;
		}

		public StructuredValue()
		{
			this.Members = new List<ConstValue>();
		}

		public override ConstValue GetMember(int Index)
		{
			return Members[Index];
		}

		public override byte[] ToByteArray()
		{
			throw new NotImplementedException();
		}

		public override ConstValue Copy()
		{
			return new StructuredValue(Members.ToList());
		}

		public override string ToString()
		{
			return "{" + String.Join(", ", Members) + "}";
		}

		public override bool IsEqual(ConstValue Value)
		{
			var StructuredValue = Value as StructuredValue;
			if (StructuredValue == null) return false;

			if (StructuredValue.Members.Count != Members.Count)
				return false;

			for (var i = 0; i < Members.Count; i++)
			{
				if (!Members[i].IsEqual(StructuredValue.Members[i]))
					return false;
			}

			return true;
		}

		public override ConstValueType Type
		{
			get { return ConstValueType.Structure; }
		}

		public override ConstValue Convert(ConstValueType To)
		{
			throw new ApplicationException();
		}

		public StructuredValue Convert(ConstValueType[] To)
		{
			if (To.Length != Members.Count)
				throw new ArgumentException("Invalid length", "To");

			var Ret = new List<ConstValue>();
			for (var i = 0; i < Members.Count; i++)
				Ret.Add(Members[i].Convert(To[i]));

			if (Ret.Contains(null)) return null;
			else return new StructuredValue(Ret);
		}

		public override ConstValue Convert(Identifier To)
		{
			if (To.RealId is StructuredType)
			{
				var SType = To.RealId as StructuredType;
				var SMembers = SType.StructuredScope.IdentifierList;
				if (SMembers.Count != Members.Count) return null;

				var Ret = new List<ConstValue>();
				for (var i = 0; i < Members.Count; i++)
					Ret.Add(Members[i].Convert(SMembers[i].TypeOfSelf));

				if (Ret.Contains(null)) return null;
				else return new StructuredValue(Ret);
			}

			return base.Convert(To);
		}

		StructuredValue ForAllMembers(Func<ConstValue, ConstValue> Func)
		{
			var NewMembers = new List<ConstValue>();
			for (var i = 0; i < Members.Count; i++)
			{
				var NewVal = Func(Members[i]);
				if (NewVal == null) return null;
				NewMembers.Add(NewVal);
			}

			return new StructuredValue(NewMembers);
		}

		StructuredValue ForAllMembers(StructuredValue Src, Func<ConstValue, ConstValue, ConstValue> Func)
		{
			var NewMembers = new List<ConstValue>();
			for (var i = 0; i < Members.Count; i++)
			{
				var NewVal = Func(Members[i], Src.Members[i]);
				if (NewVal == null) return null;
				NewMembers.Add(NewVal);
			}

			return new StructuredValue(NewMembers);
		}

		StructuredValue ForAllMembers(Identifier Type, Func<ConstValue, Identifier, ConstValue> Func)
		{
			var SType = Type.RealId as StructuredType;
			var SMembers = SType.StructuredScope.IdentifierList;
			if (SMembers.Count != Members.Count)
				throw new ArgumentException(null, "Type");

			var NewMembers = new List<ConstValue>();
			for (var i = 0; i < Members.Count; i++)
			{
				var NewType = SMembers[i].TypeOfSelf;
				var NewVal = Func(Members[i], NewType);
				if (NewVal == null) return null;
				NewMembers.Add(NewVal);
			}

			return new StructuredValue(NewMembers);
		}

		StructuredValue ForAllMembers(StructuredValue Src, Identifier Type, Func<ConstValue, ConstValue, Identifier, ConstValue> Func)
		{
			var SType = Type.RealId as StructuredType;
			var SMembers = SType.StructuredScope.IdentifierList;
			if (SMembers.Count != Members.Count)
				throw new ArgumentException(null, "Type");

			var NewMembers = new List<ConstValue>();
			for (var i = 0; i < Members.Count; i++)
			{
				var NewType = SMembers[i].TypeOfSelf;
				var NewVal = Func(Members[i], Src.Members[i], NewType);
				if (NewVal == null) return null;
				NewMembers.Add(NewVal);
			}

			return new StructuredValue(NewMembers);
		}

		public override ConstValue DoOperation(ConstValue Src, Operator Op, Identifier Type)
		{
			if (Op == Operator.UnaryPlus || Op == Operator.Negation || Op == Operator.Complement)
				return ForAllMembers(Type, (x, t) => x.DoOperation(null, Op, t));

			if (!(Src is StructuredValue))
				Src = Src.CreateStructure(Members.Count);

			var SSrc = Src as StructuredValue;
			return ForAllMembers(SSrc, Type, (x, y, t) => x.DoOperation(y, Op, t));
		}

		public override ConstValue DoOperation(ConstValue Src, Operator Op)
		{
			if (Op == Operator.UnaryPlus || Op == Operator.Negation || Op == Operator.Complement)
				return ForAllMembers(x => x.DoOperation(null, Op));

			if (!(Src is StructuredValue))
				Src = Src.CreateStructure(Members.Count);

			var SSrc = Src as StructuredValue;
			return ForAllMembers(SSrc, (x, y) => x.DoOperation(y, Op));
		}

		public override bool CheckBounds(Identifier Type)
		{
			if (Type.RealId is StructType)
			{
				var ValueType = Type.RealId as StructType;
				var Ids = ValueType.StructuredScope.IdentifierList;
				if (Ids.Count != Members.Count) return false;

				for (var i = 0; i < Members.Count; i++)
				{
                    if (!Members[i].CheckBounds(Ids[i].TypeOfSelf)) 
						return false;
				}
			}
			else if (Type.RealId is NonrefArrayType)
			{
				var NonrefArrayType = Type.RealId as NonrefArrayType;
				var TypeOfValues = NonrefArrayType.TypeOfValues;
				var Dimensions = NonrefArrayType.Lengths;
				if (Dimensions == null) return false;

				var Length = 1;
				for (var i = 0; i < Dimensions.Length; i++)
					Length *= Dimensions[i];

				if (Length != Members.Count) 
					return false;

				for (var i = 0; i < Members.Count; i++)
				{
					if (!Members[i].CheckBounds(TypeOfValues))
						return false;
				}

				return true;
			}
			else
			{
				return false;
			}

			return true;
		}
	}

	public class IntegerValue : ConstValue
	{
		public BigInteger Value;

		public IntegerValue(BigInteger Value)
		{
			this.Value = Value;
		}

		public override double Double
		{
			get { return (double)Value; }
		}

		public override ConstValueType Type
		{
			get { return ConstValueType.Integer; }
		}

		public override byte[] ToByteArray()
		{
			return Value.ToByteArray();
		}

		public override string ToString()
		{
			return Value.ToString();
		}

		public override ConstValue Copy()
		{
			return new IntegerValue(Value);
		}

		public override bool IsEqual(ConstValue Value)
		{
			var IValue = Value as IntegerValue;
			return IValue != null && IValue.Value == this.Value;
		}

		public override ConstValue DoOperation(ConstValue Src, Operator Op, Identifier Type)
		{
			if (Op == Operator.Complement)
			{
				return new IntegerValue(DataStoring.WrapToType(~Value, Type));
			}
			else if (Operators.IsShift(Op))
			{
				var Val = Value << (int)(Src as IntegerValue).Value;
				return new IntegerValue(DataStoring.WrapToType(Val, Type));
			}

			return base.DoOperation(Src, Op, Type);
		}

		public override ConstValue DoOperation(ConstValue Src, Operator Op)
		{
			var ISrc = Src as IntegerValue;
			if (Op == Operator.Add) return new IntegerValue(Value + ISrc.Value);
			if (Op == Operator.Subract) return new IntegerValue(Value - ISrc.Value);
			if (Op == Operator.Multiply) return new IntegerValue(Value * ISrc.Value);
			if (Op == Operator.Divide) return new IntegerValue(Value / ISrc.Value);
			if (Op == Operator.Modolus) return new IntegerValue(Value % ISrc.Value);
			if (Op == Operator.ShiftLeft) return ISrc.Value > 0xFFFF ? null : new IntegerValue(Value << (int)ISrc.Value);
			if (Op == Operator.ShiftRight) return ISrc.Value > 0xFFFF ? null : new IntegerValue(Value >> (int)ISrc.Value);

			if (Op == Operator.BitwiseAnd) return new IntegerValue(Value & ISrc.Value);
			if (Op == Operator.BitwiseOr) return new IntegerValue(Value | ISrc.Value);
			if (Op == Operator.BitwiseXor) return new IntegerValue((Value | ISrc.Value) & ~(Value & ISrc.Value));

			if (Op == Operator.Complement) return new IntegerValue(~Value);
			if (Op == Operator.Negation) return new IntegerValue(-Value);
			if (Op == Operator.UnaryPlus) return new IntegerValue(Value);

			if (Op == Operator.Equality) return new BooleanValue(Value == ISrc.Value);
			if (Op == Operator.Inequality) return new BooleanValue(Value != ISrc.Value);
			if (Op == Operator.Greater) return new BooleanValue(Value > ISrc.Value);
			if (Op == Operator.GreaterEqual) return new BooleanValue(Value >= ISrc.Value);
			if (Op == Operator.Less) return new BooleanValue(Value < ISrc.Value);
			if (Op == Operator.LessEqual) return new BooleanValue(Value <= ISrc.Value);
			throw new ApplicationException();
		}

		public override ConstValue Convert(ConstValueType To)
		{
			if (To == ConstValueType.Integer) return new IntegerValue(Value);
			if (To == ConstValueType.Double) return new DoubleValue((double)Value);
			if (To == ConstValueType.Float) return new FloatValue((float)Value);
			if (To == ConstValueType.String) return new StringValue(Value.ToString());

			if (To == ConstValueType.Char)
			{
				if (Value > char.MaxValue || Value < char.MinValue) return null;
				else return new CharValue((char)Value);
			}

			throw new ApplicationException();
		}

		public override bool CheckBounds(Identifier Type)
		{
			if (Type.RealId is NonFloatType)
			{
				var NonFlt = Type.RealId as NonFloatType;
				return NonFlt.MinValue <= Value && NonFlt.MaxValue >= Value;
			}
			else if (Type.RealId is PointerType || Type.RealId is ClassType)
			{
				return true;
			}
			else if (Type.RealId is EnumType)
			{
				var EType = Type.RealId as EnumType;
				if (EType.TypeOfValues == null) return true;
				else return CheckBounds(EType.TypeOfValues);
			}
			else if (Type.RealId is ObjectType)
			{
				return false;
			}

			throw new ApplicationException();
		}
	}

	public class DoubleValue : ConstValue
	{
		public double Value;

		public DoubleValue(double Value)
		{
			this.Value = Value;
		}

		public override double Double
		{
			get { return Value; }
		}

		public override ConstValueType Type
		{
			get { return ConstValueType.Double; }
		}

		public unsafe override byte[] ToByteArray()
		{
			fixed (double* PValue = &Value)
			{
				var Ret = new byte[sizeof(double)];
				for (var i = 0; i < sizeof(double); i++)
					Ret[i] = ((byte*)PValue)[i];

				return Ret;
			}
		}

		public unsafe byte[] GetFloatBytes()
		{
			var Float = (float)Value;
			var PValue = &Float;
			var Ret = new byte[sizeof(float)];
			for (var i = 0; i < sizeof(float); i++)
				Ret[i] = ((byte*)PValue)[i];

			return Ret;
		}

		public override string ToString()
		{
			return Value.ToString();
		}

		public override ConstValue Copy()
		{
			return new DoubleValue(Value);
		}

		public override bool IsEqual(ConstValue Value)
		{
			var FValue = Value as DoubleValue;
			return FValue != null && FValue.Value == this.Value;
		}

		public override ConstValue DoOperation(ConstValue Src, Operator Op)
		{
			var FSrc = Src as DoubleValue;
			if (Op == Operator.Add) return new DoubleValue(Value + FSrc.Value);
			if (Op == Operator.Subract) return new DoubleValue(Value - FSrc.Value);
			if (Op == Operator.Multiply) return new DoubleValue(Value * FSrc.Value);
			if (Op == Operator.Divide) return new DoubleValue(Value / FSrc.Value);
			if (Op == Operator.Modolus) return new DoubleValue(Value % FSrc.Value);
			if (Op == Operator.Negation) return new DoubleValue(-Value);
			if (Op == Operator.UnaryPlus) return new DoubleValue(Value);

			if (Op == Operator.Equality) return new BooleanValue(Value == FSrc.Value);
			if (Op == Operator.Inequality) return new BooleanValue(Value != FSrc.Value);
			if (Op == Operator.Greater) return new BooleanValue(Value > FSrc.Value);
			if (Op == Operator.GreaterEqual) return new BooleanValue(Value >= FSrc.Value);
			if (Op == Operator.Less) return new BooleanValue(Value < FSrc.Value);
			if (Op == Operator.LessEqual) return new BooleanValue(Value <= FSrc.Value);
			throw new ApplicationException();
		}

		public override ConstValue Convert(ConstValueType To)
		{
			if (To == ConstValueType.Double) return new DoubleValue(Value);
			if (To == ConstValueType.Float) return new FloatValue((float)Value);
			if (To == ConstValueType.Integer) return new IntegerValue((BigInteger)Value);
			if (To == ConstValueType.String) return new StringValue(Value.ToString());
			throw new ApplicationException();
		}

		public override bool CheckBounds(Identifier Type)
		{
			if (Type.RealId is FloatType) return true;
			else if (Type.RealId is ObjectType) return false;
			else throw new ApplicationException();
		}
	}

	public class FloatValue : ConstValue
	{
		public float Value;

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

		public override ConstValueType Type
		{
			get { return ConstValueType.Float; }
		}

		public override double Double
		{
			get { return Value; }
		}

		public unsafe override byte[] ToByteArray()
		{
			fixed (float* PValue = &Value)
			{
				var Ret = new byte[sizeof(double)];
				for (var i = 0; i < sizeof(double); i++)
					Ret[i] = ((byte*)PValue)[i];

				return Ret;
			}
		}

		public override string ToString()
		{
			return Value.ToString();
		}

		public override ConstValue Copy()
		{
			return new FloatValue(Value);
		}

		public override bool IsEqual(ConstValue Value)
		{
			var FValue = Value as FloatValue;
			return FValue != null && FValue.Value == this.Value;
		}

		public override ConstValue DoOperation(ConstValue Src, Operator Op)
		{
			var FSrc = Src as FloatValue;
			if (Op == Operator.Add) return new FloatValue(Value + FSrc.Value);
			if (Op == Operator.Subract) return new FloatValue(Value - FSrc.Value);
			if (Op == Operator.Multiply) return new FloatValue(Value * FSrc.Value);
			if (Op == Operator.Divide) return new FloatValue(Value / FSrc.Value);
			if (Op == Operator.Modolus) return new FloatValue(Value % FSrc.Value);
			if (Op == Operator.Negation) return new FloatValue(-Value);
			if (Op == Operator.UnaryPlus) return new FloatValue(Value);

			if (Op == Operator.Equality) return new BooleanValue(Value == FSrc.Value);
			if (Op == Operator.Inequality) return new BooleanValue(Value != FSrc.Value);
			if (Op == Operator.Greater) return new BooleanValue(Value > FSrc.Value);
			if (Op == Operator.GreaterEqual) return new BooleanValue(Value >= FSrc.Value);
			if (Op == Operator.Less) return new BooleanValue(Value < FSrc.Value);
			if (Op == Operator.LessEqual) return new BooleanValue(Value <= FSrc.Value);
			throw new ApplicationException();
		}

		public override ConstValue Convert(ConstValueType To)
		{
			if (To == ConstValueType.Double) return new DoubleValue((double)Value);
			if (To == ConstValueType.Float) return new FloatValue(Value);
			if (To == ConstValueType.Integer) return new IntegerValue((BigInteger)Value);
			if (To == ConstValueType.String) return new StringValue(Value.ToString());
			throw new ApplicationException();
		}

		public override bool CheckBounds(Identifier Type)
		{
			if (Type.RealId is FloatType) return true;
			else if (Type.RealId is ObjectType) return false;
			else throw new ApplicationException();
		}
	}

	public class StringValue : ConstValue
	{
		public string Value;

		public StringValue(string Value)
		{
			this.Value = Value;
		}

		public override ConstValueType Type
		{
			get { return ConstValueType.String; }
		}

		public override byte[] ToByteArray()
		{
			throw new NotImplementedException();
		}

		public override string ToString()
		{
			return Value;
		}

		public override ConstValue Copy()
		{
			return new StringValue(Value);
		}

		public override bool IsEqual(ConstValue Value)
		{
			var SData = Value as StringValue;
			return SData != null && SData.Value == this.Value;
		}

		public override ConstValue DoOperation(ConstValue Src, Operator Op)
		{
			var SSrc = Src as StringValue;
			if (Op == Operator.Add) return new StringValue(Value + SSrc.Value);
			if (Op == Operator.Equality) return new BooleanValue(Value == SSrc.Value);
			if (Op == Operator.Inequality) return new BooleanValue(Value != SSrc.Value);
			throw new ApplicationException();
		}

		public override ConstValue Convert(ConstValueType To)
		{
			if (To == ConstValueType.String) return new StringValue(Value);
			throw new ApplicationException();
		}

		public override bool CheckBounds(Identifier Type)
		{
			if (Type.RealId is StringType) return true;
			else if (Type.RealId is ObjectType) return false;
			else throw new ApplicationException();
		}
	}

	public class CharValue : ConstValue
	{
		public char Value;

		public CharValue(char Value)
		{
			this.Value = Value;
		}

		public override ConstValueType Type
		{
			get { return ConstValueType.Char; }
		}

		public override string ToString()
		{
			return Value.ToString();
		}

		public unsafe override byte[] ToByteArray()
		{
			fixed (char* PValue = &Value)
			{
				var Ret = new byte[sizeof(char)];
				for (var i = 0; i < sizeof(char); i++)
					Ret[i] = ((byte*)PValue)[i];

				return Ret;
			}
		}

		public override ConstValue Copy()
		{
			return new CharValue(Value);
		}

		public override bool IsEqual(ConstValue Value)
		{
			var CValue = Value as CharValue;
			return CValue != null && CValue.Value == this.Value;
		}

		public override ConstValue DoOperation(ConstValue Src, Operator Op)
		{
			var CSrc = Src as CharValue;
			if (Op == Operator.Add) return new CharValue((char)(Value + CSrc.Value));
			if (Op == Operator.Subract) return new CharValue((char)(Value - CSrc.Value));
			if (Op == Operator.Multiply) return new CharValue((char)(Value * CSrc.Value));
			if (Op == Operator.Divide) return new CharValue((char)(Value / CSrc.Value));
			if (Op == Operator.Modolus) return new CharValue((char)(Value % CSrc.Value));
			//if (Op == Operator.ShiftLeft) return CSrc.Value > 0xFFFF ? null : new CharValue(Value << (int)CSrc.Value);
			//if (Op == Operator.ShiftRight) return CSrc.Value > 0xFFFF ? null : new CharValue(Value >> (int)CSrc.Value);

			if (Op == Operator.BitwiseAnd) return new CharValue((char)(Value & CSrc.Value));
			if (Op == Operator.BitwiseOr) return new CharValue((char)(Value | CSrc.Value));
			if (Op == Operator.BitwiseXor) return new CharValue((char)((Value | CSrc.Value) & ~(Value & CSrc.Value)));

			if (Op == Operator.Complement) return new CharValue((char)(~Value));
			if (Op == Operator.Negation) return new CharValue((char)(-Value));
			if (Op == Operator.UnaryPlus) return new CharValue(Value);

			if (Op == Operator.Equality) return new BooleanValue(Value == CSrc.Value);
			if (Op == Operator.Inequality) return new BooleanValue(Value != CSrc.Value);
			if (Op == Operator.Greater) return new BooleanValue(Value > CSrc.Value);
			if (Op == Operator.GreaterEqual) return new BooleanValue(Value >= CSrc.Value);
			if (Op == Operator.Less) return new BooleanValue(Value < CSrc.Value);
			if (Op == Operator.LessEqual) return new BooleanValue(Value <= CSrc.Value);
			throw new ApplicationException();
		}

		public override ConstValue Convert(ConstValueType To)
		{
			if (To == ConstValueType.Integer) return new IntegerValue(new BigInteger((int)Value));
			if (To == ConstValueType.Char) return new CharValue(Value);
			if (To == ConstValueType.String) return new StringValue(Value.ToString());
			throw new ApplicationException();
		}

		public override bool CheckBounds(Identifier Type)
		{
			if (Type.RealId is CharType) return true;
			else if (Type.RealId is ObjectType) return false;
			else throw new ApplicationException();
		}
	}

	public class BooleanValue : ConstValue
	{
		public bool Value;

		public BooleanValue(bool Value)
		{
			this.Value = Value;
		}

		public override ConstValueType Type
		{
			get { return ConstValueType.Boolean; }
		}

		public override string ToString()
		{
			return Value.ToString();
		}

		public unsafe override byte[] ToByteArray()
		{
			fixed (bool* PValue = &Value)
			{
				var Ret = new byte[sizeof(bool)];
				for (var i = 0; i < sizeof(bool); i++)
					Ret[i] = ((byte*)PValue)[i];

				return Ret;
			}
		}

		public override ConstValue Copy()
		{
			return new BooleanValue(Value);
		}

		public override bool IsEqual(ConstValue Value)
		{
			var BValue = Value as BooleanValue;
			return BValue != null && BValue.Value == this.Value;
		}

		public override ConstValue DoOperation(ConstValue Src, Operator Op)
		{
			var BSrc = Src as BooleanValue;
			if (Op == Operator.Equality) return new BooleanValue(Value == BSrc.Value);
			if (Op == Operator.Inequality) return new BooleanValue(Value != BSrc.Value);
			
			if (Op == Operator.And) return new BooleanValue(Value && BSrc.Value);
			if (Op == Operator.Or) return new BooleanValue(Value || BSrc.Value);
			if (Op == Operator.Not) return new BooleanValue(!Value);
			throw new ApplicationException();
		}

		public override ConstValue Convert(ConstValueType To)
		{
			if (To == ConstValueType.Boolean) return new BooleanValue(Value);
			if (To == ConstValueType.String) return new StringValue(Value.ToString());
			throw new ApplicationException();
		}

		public override bool CheckBounds(Identifier Type)
		{
			if (Type.RealId is BooleanType) return true;
			else if (Type.RealId is ObjectType) return false;
			else throw new ApplicationException();
		}
	}

	public class ZeroValue : ConstValue
	{
		public ZeroValue()
		{
		}

		public override ConstValueType Type
		{
			get { return ConstValueType.Zero; }
		}

		public override ConstValue GetMember(int Index)
		{
			return new ZeroValue();
		}

		public override bool IsEqual(ConstValue Value)
		{
			return Value is ZeroValue;
		}

		public override ConstValue Copy()
		{
			return new ZeroValue();
		}

		public override bool CheckBounds(Identifier Type)
		{
			return true;
		}

		public override ConstValue Convert(ConstValueType To)
		{
			return new ZeroValue();
		}

		public override ConstValue DoOperation(ConstValue Src, Operator Op)
		{
			throw new ApplicationException();
		}

		public override byte[] ToByteArray()
		{
			throw new ApplicationException();
		}

		public override unsafe long GetSigned(int Offset, int Size)
		{
			return 0;
		}

		public override unsafe ulong GetUnsigned(int Offset, int Size)
		{
			return 0;
		}

		public override string ToString()
		{
			return "0";
		}
	}

	public class NullValue : ConstValue
	{
		public NullValue()
		{
		}

		public override ConstValueType Type
		{
			get { return ConstValueType.Null; }
		}

		public override ConstValue GetMember(int Index)
		{
			throw new ApplicationException();
		}

		public override bool IsEqual(ConstValue Value)
		{
			return Value is NullValue;
		}

		public override ConstValue Copy()
		{
			return new NullValue();
		}

		public override bool CheckBounds(Identifier Type)
		{
			if (Type.RealId is ObjectType || Type.RealId is StringType || Type.RealId is RefArrayType ||
				Type.RealId is ClassType || Type.RealId is PointerType || Type.RealId is NullType)
			{
				return true;
			}

			throw new ApplicationException();
		}

		public override ConstValue Convert(Identifier To)
		{
			if (To.RealId is ObjectType || To.RealId is StringType || To.RealId is RefArrayType ||
				To.RealId is ClassType || To.RealId is PointerType || To.RealId is NullType)
			{
				return new NullValue();
			}
			
			throw new ApplicationException();
		}

		public override ConstValue Convert(ConstValueType To)
		{
			throw new ApplicationException();
		}

		public override ConstValue DoOperation(ConstValue Src, Operator Op)
		{
			throw new ApplicationException();
		}

		public override byte[] ToByteArray()
		{
			throw new ApplicationException();
		}

		public override unsafe long GetSigned(int Offset, int Size)
		{
			return 0;
		}

		public override unsafe ulong GetUnsigned(int Offset, int Size)
		{
			return 0;
		}

		public override string ToString()
		{
			return "0";
		}
	}

	public class ConstExpressionNode : ExpressionNode
	{
		public ConstValue Value;

		public char Char
		{
			get { return (Value as CharValue).Value; }
		}

		public BigInteger Integer
		{
			get { return (Value as IntegerValue).Value; }
		}

		public double Double
		{
			get { return (Value as DoubleValue).Value; }
		}

		public double Float
		{
			get { return (Value as FloatValue).Value; }
		}

		public double CDouble
		{
			get { return Value.Double; }
		}

		public string String
		{
			get { return (Value as StringValue).Value; }
		}

		public bool Bool
		{
			get { return (Value as BooleanValue).Value; }
		}

		public bool CheckBounds()
		{
			return Value.CheckBounds(Type.RealId as Type);
		}

		public bool CheckBounds(CompilerState State)
		{
			return Value.CheckBounds(State, Type, Code);
		}

		public override ConditionResult ConditionResult
		{
			get { return Bool ? ConditionResult.True : ConditionResult.False; }
		}

		public bool IsEqual(ConstExpressionNode Node)
		{
			return Value.IsEqual(Node.Value);
		}

		public ConstExpressionNode(Identifier Type, ConstValue Value, CodeString Code, ExpressionFlags Flags = ExpressionFlags.None)
			: base(Code, Flags)
		{
			if (!(Type is AutomaticType))
			{
				var RType = Type.RealId as Type;
				var T = Constants.TranslateConstValueType(Value.Type);

				if ((RType.ConstValueType != T && T != ConstValueType.Unknown) || !Value.CheckBounds(Type))
					throw new ApplicationException();
			}

			this.Type = Type;
			this.Value = Value;
		}

		protected override ExpressionNode Copy_WithoutLinkedNodes(CompilerState State, CodeString Code, Func<ExpressionNode, ExpressionNode> Func)
		{
			if (!Code.IsValid) Code = this.Code;
			return new ConstExpressionNode(Type, Value, Code, Flags);
		}

		public override string ToString()
		{
			return Value.ToString();
		}
	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


Written By
Software Developer
Hungary Hungary
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions