Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Bird Programming Language: Part 1

, 1 Jan 2013
A new general purpose language that aims to be fast, high level and simple to use.
Bird-noexe.zip
Bird
Archives
crt2.o
crtbegin.o
crtend.o
libadvapi32.a
libcomctl32.a
libcomdlg32.a
libgcc.a
libgdi32.a
libglu32.a
libkernel32.a
libmingw32.a
libmingwex.a
libmoldname.a
libmsvcrt.a
libopengl32.a
libshell32.a
libstdc++.a
libuser32.a
libwinmm.a
libwsock32.a
Libraries
BirdCore
Array.bird
BigInteger.bird
BinaryRW.bird
BirdCore.a
BirdCore.blib
CategoryData.dat
Console.bird
Convert.bird
Debug.bird
Entry.bird
Environment.bird
Exception.bird
Float.bird
LEB128.bird
Math.bird
Memory.bird
Object.bird
Random.bird
Reflection.bird
StandardC.bird
Stream.bird
String.bird
ToLowerData.dat
ToUpperData.dat
Types.bird
ValueType.bird
Win32.bird
x86Helper.bird
BlitzMax
.bmx
Launcher.bmx.gui.release.win32.x86.o
appstub.release.win32.x86.a
bank.release.win32.x86.a
bankstream.release.win32.x86.a
blitz.release.win32.x86.a
BlitzMax.a
BlitzMax.bird
BlitzMax.blib
d3d7max2d.release.win32.x86.a
d3d9max2d.release.win32.x86.a
directx.release.win32.x86.a
dxgraphics.release.win32.x86.a
event.release.win32.x86.a
filesystem.release.win32.x86.a
font.release.win32.x86.a
glgraphics.release.win32.x86.a
glmax2d.release.win32.x86.a
graphics.release.win32.x86.a
hook.release.win32.x86.a
keycodes.release.win32.x86.a
Launcher.bmx
libpng.release.win32.x86.a
linkedlist.release.win32.x86.a
math.release.win32.x86.a
max2d.release.win32.x86.a
opengl.release.win32.x86.a
pixmap.release.win32.x86.a
pngloader.release.win32.x86.a
polledinput.release.win32.x86.a
standardio.release.win32.x86.a
stdc.release.win32.x86.a
stream.release.win32.x86.a
system.release.win32.x86.a
textstream.release.win32.x86.a
win32.release.win32.x86.a
zlib.release.win32.x86.a
PrgLinec.bmx
Samples
Circles
Circles.bird
CppMain.bird
Fire
Fire.bird
Higher Order Functions
C#
Higher Order Functions.v11.suo
Properties
Test.bird
msvcrt.lib
Reflection
Reflection.bird
Squares
Squares.bird
Template
Template.bird
Source
Base
Bird.v11.suo
Expressions
Identifiers
Languages
NativeCode
Properties
Recognizers
Expressions
Scopes
x86
Thumbs.db
Bird.zip
crt2.o
crtbegin.o
crtend.o
libadvapi32.a
libcomctl32.a
libcomdlg32.a
libgcc.a
libgdi32.a
libglu32.a
libkernel32.a
libmingw32.a
libmingwex.a
libmoldname.a
libmsvcrt.a
libopengl32.a
libshell32.a
libstdc++.a
libuser32.a
libwinmm.a
libwsock32.a
Binaries
ar.exe
Bird.exe
fasm.exe
ld.exe
libiconv-2.dll
libintl-8.dll
Array.bird
BigInteger.bird
BinaryRW.bird
BirdCore.a
BirdCore.blib
CategoryData.dat
Console.bird
Convert.bird
Debug.bird
Entry.bird
Environment.bird
Exception.bird
Float.bird
LEB128.bird
Math.bird
Memory.bird
Object.bird
Random.bird
Reflection.bird
StandardC.bird
Stream.bird
String.bird
ToLowerData.dat
ToUpperData.dat
Types.bird
ValueType.bird
Win32.bird
x86Helper.bird
Launcher.bmx.gui.release.win32.x86.o
appstub.release.win32.x86.a
bank.release.win32.x86.a
bankstream.release.win32.x86.a
blitz.release.win32.x86.a
BlitzMax.a
BlitzMax.bird
BlitzMax.blib
d3d7max2d.release.win32.x86.a
d3d9max2d.release.win32.x86.a
directx.release.win32.x86.a
dxgraphics.release.win32.x86.a
event.release.win32.x86.a
filesystem.release.win32.x86.a
font.release.win32.x86.a
glgraphics.release.win32.x86.a
glmax2d.release.win32.x86.a
graphics.release.win32.x86.a
hook.release.win32.x86.a
keycodes.release.win32.x86.a
Launcher.bmx
libpng.release.win32.x86.a
linkedlist.release.win32.x86.a
math.release.win32.x86.a
max2d.release.win32.x86.a
opengl.release.win32.x86.a
pixmap.release.win32.x86.a
pngloader.release.win32.x86.a
polledinput.release.win32.x86.a
standardio.release.win32.x86.a
stdc.release.win32.x86.a
stream.release.win32.x86.a
system.release.win32.x86.a
textstream.release.win32.x86.a
win32.release.win32.x86.a
zlib.release.win32.x86.a
PrgLinec.bmx
PrgLinec.exe
Circles.bird
CppMain.bird
Fire.bird
Higher Order Functions.v11.suo
Test.bird
msvcrt.lib
Reflection.bird
Squares.bird
Template.bird
Bird.v11.suo
Thumbs.db
examples.zip
Examples
As.exe
AsLibs.a
PerfTest
Launcher.bmx
Squares
.bmx
Launcher.bmx
Template
Launcher.bmx
source.zip
Anonymus 7_1
Anonymus.csproj.user
Anonymus.idc
Anonymus.pidb
Anonymus.suo
Anonymus.userprefs
Base
Expressions
Lib
Long
LongDivTest.bmx
ULongConv.bmx
Math
MISZ
AsLibs.a
PerfTest
Launcher.bmx
Squares
Launcher.bmx
Template
Launcher.bmx
PrgLinec.bmx
PrgLinec.exe
Properties
Scopes
Txt
Asm.docx
Code.docx
Lib.aslib
~$Code.docx
x86
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Numerics;

namespace Bird
{
	public enum CallingConvention : byte
	{
		Unknown,
		StdCall,
		CDecl,
		BirdCall,
	}

	public enum TypeConversion : byte
	{
		Automatic,
		Convertable,
		Nonconvertable,
	}

	[Flags]
	public enum TypeFlags : byte
	{
		None = 0,
		CanBeArrayType = 1,
		CanBeReference = 2,
		CanBePointer = 4,
		CanBeVariable = 8,
		CanBeEverything = CanBeArrayType | CanBeReference | 
			CanBePointer | CanBeVariable,

		UnfixedSize = 16,
		ReferenceValue = 32,
		NoDefaultBase = 64,
	}

	public abstract class Type : Identifier
	{
		public TypeFlags TypeFlags = TypeFlags.CanBeEverything;
		public ConstValueType ConstValueType = ConstValueType.Unknown;
		public int Size;
		public int Align;
		public int InstanceSize = -1;
		public bool LayoutCalculated = false;

		public override bool IsInstanceIdentifier
		{
			get { return false; }
		}

		public override Identifier TypeOfSelf
		{
			get { return Container.GlobalContainer.CommonIds.TypeOfType; }
		}
		
		public Type(IdContainer Container, CodeString Name)
			: base(Container, Name)
		{
			this.Name = Name;
		}

		public virtual bool CanOpApplied(Operator Op, Type SrcType)
		{
			if (CanOpApplied_Base(Op, SrcType))
				return true;

			var RType = RealId as Type;
			if (RType != this && RType != null)
				return RType.CanOpApplied_Base(Op, SrcType);

			return false;
		}

		internal virtual bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			if (Op == Operator.Assignment)
				return true;

			return false;
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			if (Identifiers.IsBoxing(this, To))
				return TypeConversion.Automatic;

			if (IsEquivalent(To)) return TypeConversion.Automatic;

			if (To.RealId is TupleType)
			{
				var Tuple = To.RealId as TupleType;
				var Members = Tuple.StructuredScope.IdentifierList;
				var Conv = TypeConversion.Automatic;

				for (var i = 0; i < Members.Count; i++)
				{
					var Member = Members[i] as MemberVariable;
					var MemberType = Member.Children[0];

					var MemberConv = CanConvert(MemberType);
					if (MemberConv == TypeConversion.Nonconvertable)
					{
						Conv = TypeConversion.Nonconvertable;
					}
					else if (MemberConv == TypeConversion.Convertable)
					{
						if (Conv == TypeConversion.Automatic)
							Conv = TypeConversion.Convertable;
					}
				}

				if (Conv != TypeConversion.Nonconvertable)
					return Conv;
			}

			if (RealId != this) return RealId.CanConvert(To);
			else return TypeConversion.Nonconvertable;
		}
	}

	public class TypeOfType : Type
	{
		public TypeOfType(IdContainer Container, CodeString Name)
			: base(Container, Name)
		{
			UndeclaredIdType = UndeclaredIdType.Type;
			TypeFlags = TypeFlags.None;
		}

		public override bool IsEquivalent(Identifier Id)
		{
			return Id.RealId is TypeOfType;
		}
	}

	public class AutomaticType : Type
	{
		public AutomaticType(IdContainer Container, CodeString Name)
			: base(Container, Name)
		{
			UndeclaredIdType = UndeclaredIdType.Auto;
			TypeFlags = TypeFlags.CanBeVariable;
		}

		public override bool IsEquivalent(Identifier Id)
		{
			return Id.RealId is AutomaticType;
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			if (Op == Operator.Assignment) return true;
			return base.CanOpApplied_Base(Op, SrcType);
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			return TypeConversion.Automatic;
		}
	}

	public class NullType : AutomaticType
	{
		public NullType(IdContainer Container, CodeString Name)
			: base(Container, Name)
		{
			this.UndeclaredIdType = UndeclaredIdType.Null;
		}

		public override bool IsEquivalent(Identifier Id)
		{
			return Id.RealId is NullType;
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			var RTo = To.RealId as Type;
			if (RTo is PointerType || RTo is TypeOfFunction ||
				(RTo.TypeFlags & Bird.TypeFlags.ReferenceValue) != 0)
			{
				return TypeConversion.Automatic;
			}

			return TypeConversion.Nonconvertable;
		}
	}

	public class PointerType : Type
	{
		public Type Child
		{
			get { return Children[0].RealId as Type; }
		}

		public override void Update()
		{
			GenerateName();
			CalculateAccess();
		}

		public PointerType(IdContainer Container, CodeString Name, Identifier Child)
			: base(Container, Name)
		{
			Setup();
			this.Children = new Identifier[] { Child };
		}

		public PointerType(IdContainer Container, Identifier Child, bool DoUpdate = true)
			: base(Container, new CodeString())
		{
			Setup();

			this.Children = new Identifier[] { Child };
			if (Child != null) Access = Child.Access;
			if (DoUpdate) Update();
		}

		private void Setup()
		{
			UndeclaredIdType = UndeclaredIdType.Pointer;
			ConstValueType = ConstValueType.Unknown;
			Size = Container.State.Arch.RegSize;
			Align = this.Size;
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			if (Operators.IsRelEquality(Op) && SrcType is PointerType) return true;

			if (!(Child is VoidType))
			{
				if (Operators.IsIncDec(Op)) return true;
				if ((Op == Operator.Add || Op == Operator.Subract) && SrcType is NonFloatType) return true;
				if (Op == Operator.Index) return true;
			}

			return base.CanOpApplied_Base(Op, SrcType);
		}

		public override bool IsEquivalent(Identifier Id)
		{
			var PType = Id.RealId as PointerType;
			return PType != null && Child.IsEquivalent(PType.Child);
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			if (To.RealId is PointerType)
			{
				var PTo = To.RealId as PointerType;
				if (PTo.Child is VoidType || PTo.Child.IsEquivalent(Child))
					return TypeConversion.Automatic;
				else return TypeConversion.Convertable;
			}

			if (To.RealId is NonFloatType && (To.RealId as NonFloatType).Size == Size)
				return TypeConversion.Convertable;

			if (To.RealId is TypeOfFunction && Child is VoidType)
				return TypeConversion.Convertable;

			return base.CanConvert(To);
		}
	}

	public abstract class BuiltinType : Type
	{
		public StructuredType UnderlyingType;

		public BuiltinType(IdContainer Container, CodeString Name)
			: base(Container, Name)
		{
			
		}

		public override bool IsEquivalent(Identifier Id)
		{
			return UnderlyingType == Id || base.IsEquivalent(Id);
		}

		public override bool HasScopes
		{
			get
			{
				return UnderlyingType != null && UnderlyingType.HasScopes;
			}
		}

		public override IEnumerable<ScopeNode> EnumScopes
		{
			get
			{
				if (HasScopes)
				{
					foreach (var e in UnderlyingType.EnumScopes)
						yield return e;
				}
			}
		}

		public override bool CanOpApplied(Operator Op, Type SrcType)
		{
			if (CanOpApplied_Base(Op, SrcType))
				return true;

			if (UnderlyingType != null)
			{
				if (UnderlyingType.CanOpApplied_Base(Op, SrcType))
					return true;
			}

			return false;
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			return base.CanConvert(To);
		}
	}

	public class ObjectType : BuiltinType
	{
		public ObjectType(IdContainer Container, CodeString Name)
			: base(Container, Name)
		{
			this.UndeclaredIdType = UndeclaredIdType.Object;
			this.TypeFlags |= TypeFlags.ReferenceValue;
			this.ConstValueType = ConstValueType.Unknown;
			this.Size = this.Align = Container.State.Arch.RegSize;
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			return base.CanOpApplied_Base(Op, SrcType) || Operators.IsRefEquality(Op) ||
				Op == Operator.Equality || Op == Operator.Inequality;
		}

		public override bool IsEquivalent(Identifier Id)
		{
			return Id.RealId is ObjectType || base.IsEquivalent(Id);
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			if (To.RealId is ObjectType) return TypeConversion.Automatic;
			if (Identifiers.IsBoxing(To, this)) return TypeConversion.Convertable;

			if (Identifiers.IsSubtypeOf(To, this))
				return TypeConversion.Convertable;

			return base.CanConvert(To);
		}

		public override bool CalculateLayout()
		{
			if (!LayoutCalculated && UnderlyingType != null)
			{
				if (!base.CalculateLayout()) return false;
				if (!UnderlyingType.CalculateLayout()) return false;

				InstanceSize = UnderlyingType.InstanceSize;
				LayoutCalculated = true;
				return true;
			}

			return true;
		}
	}

	public class StringType : BuiltinType
	{
		public StringType(IdContainer Container, CodeString Name)
			: base(Container, Name)
		{
			this.UndeclaredIdType = UndeclaredIdType.String;
			this.TypeFlags |= TypeFlags.ReferenceValue;
			this.ConstValueType = ConstValueType.String;
			this.Size = this.Align = Container.State.Arch.RegSize;
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			return base.CanOpApplied_Base(Op, SrcType) || ((Op == Operator.Add ||
				Op == Operator.Equality || Op == Operator.Inequality) && SrcType is StringType);
		}

		public override bool IsEquivalent(Identifier Id)
		{
			return Id.RealId is StringType || base.IsEquivalent(Id);
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			if (To.RealId is ObjectType) return TypeConversion.Automatic;
			return base.CanConvert(To);
		}

		public override bool CalculateLayout()
		{
			if (!LayoutCalculated && UnderlyingType != null)
			{
				if (!base.CalculateLayout()) return false;
				if (!UnderlyingType.CalculateLayout()) return false;

				InstanceSize = UnderlyingType.InstanceSize;
				LayoutCalculated = true;
				return true;
			}

			return true;
		}
	}

	public class VoidType : BuiltinType
	{
		public VoidType(IdContainer Container, CodeString Name)
			: base(Container, Name)
		{
			UndeclaredIdType = UndeclaredIdType.Void;
			TypeFlags = TypeFlags.CanBePointer;
		}

		public override bool IsEquivalent(Identifier Id)
		{
			return Id.RealId is VoidType || base.IsEquivalent(Id);
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			return TypeConversion.Nonconvertable;
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			return false;
		}
	}

	public class NamespaceType : Type
	{
		public NamespaceType(IdContainer Container, CodeString Name)
			: base(Container, Name)
		{
			UndeclaredIdType = UndeclaredIdType.Namespace;
			TypeFlags = TypeFlags.None;
		}

		public override bool IsEquivalent(Identifier Id)
		{
			return Id.RealId is NamespaceType;
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			return TypeConversion.Nonconvertable;
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			return false;
		}
	}

	public abstract class NumberType : BuiltinType
	{
		public NumberType(IdContainer Container, CodeString Name, int Size)
			: base(Container, Name)
		{
			this.Size = Size;
			this.Align = Size;
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			if (Operators.IsIncDec(Op))
				return true;

			if (Operators.IsRelEquality(Op) || Operators.IsArithmetical(Op) || Operators.IsRange(Op))
			{
				if (SrcType is NumberType)
					return Container.GetRetType(this, SrcType) != null;

				if (SrcType is TupleType)
				{
					var Tuple = SrcType as TupleType;
                    return Tuple.TrueForAllMembers(x =>
                    {
                        var xType = x.TypeOfSelf.RealId as Type;
                        return this.CanOpApplied(Op, xType);
                    });
				}
			}

			if (base.CanOpApplied_Base(Op, SrcType)) return true;
			return false;
		}

		public override bool IsEquivalent(Identifier Id)
		{
			if (base.IsEquivalent(Id))
				return true;

			var NType = Id.RealId as NumberType;
			if (NType == null || !GetType().IsEquivalentTo(NType.GetType()))
				return false;

			return Size == NType.Size;
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			var NTo = To.RealId as NumberType;
			if (NTo != null) return TypeConversion.Convertable;
			return base.CanConvert(To);
		}
	}

	public abstract class NonFloatType : NumberType
	{
		public BigInteger MinValue;
		public BigInteger MaxValue;

		public NonFloatType(IdContainer Container, CodeString Name, int Size)
			: base(Container, Name, Size)
		{
			this.ConstValueType = ConstValueType.Integer;
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			if ((Op == Operator.Add || Op == Operator.Subract) && SrcType is PointerType &&
				!((SrcType as PointerType).Child is VoidType)) return true;

			if (base.CanOpApplied_Base(Op, SrcType) || Op == Operator.Complement) return true;
			if ((Operators.IsShift(Op) || Operators.IsBitwise(Op)) && SrcType is NonFloatType) return true;
			return false;
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			if (To.RealId is FloatType) return TypeConversion.Automatic;
            if (To.RealId is CharType) return TypeConversion.Convertable;

            if (To.RealId is EnumType)
			{
				var Res = CanConvert((To.RealId as EnumType).TypeOfValues);
				if (Res == TypeConversion.Nonconvertable) return Res;
				else return TypeConversion.Convertable;
			}

            var PTo = To.RealId as PointerType;
			if (PTo != null && PTo.Size == Size)
				return TypeConversion.Convertable;

			return base.CanConvert(To);
		}
	}

	public class SignedType : NonFloatType
	{
		public SignedType(IdContainer Container, CodeString Name, int Size)
			: base(Container, Name, Size)
		{
			MaxValue = BigInteger.Pow(2, Size * 8 - 1) - 1;
			MinValue = -BigInteger.Pow(2, Size * 8 - 1);

			if (Size == 1) UndeclaredIdType = UndeclaredIdType.SByte;
			else if (Size == 2) UndeclaredIdType = UndeclaredIdType.Int16;
			else if (Size == 4) UndeclaredIdType = UndeclaredIdType.Int32;
			else if (Size == 8) UndeclaredIdType = UndeclaredIdType.Int64;
			else throw new ApplicationException();
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			return Op == Operator.UnaryPlus || Op == Operator.Negation || base.CanOpApplied_Base(Op, SrcType);
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			var STo = To.RealId as SignedType;
			if (STo != null && STo.Size >= Size)
				return TypeConversion.Automatic;

			return base.CanConvert(To);
		}
	}

	public class UnsignedType : NonFloatType
	{
		public UnsignedType(IdContainer Container, CodeString Name, int Size)
			: base(Container, Name, Size)
		{
			MaxValue = BigInteger.Pow(2, Size * 8) - 1;
			MinValue = new BigInteger(0);

			if (Size == 1) UndeclaredIdType = UndeclaredIdType.Byte;
			else if (Size == 2) UndeclaredIdType = UndeclaredIdType.UInt16;
			else if (Size == 4) UndeclaredIdType = UndeclaredIdType.UInt32;
			else if (Size == 8) UndeclaredIdType = UndeclaredIdType.UInt64;
			else throw new ApplicationException();
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			if (To.RealId is NumberType)
			{
				var NTo = To.RealId as NumberType;
				if (NTo is UnsignedType && NTo.Size >= Size)
					return TypeConversion.Automatic;

				if (NTo is SignedType && NTo.Size > Size)
					return TypeConversion.Automatic;
			}

			return base.CanConvert(To);
		}
	}

	public class CharType : BuiltinType
	{
		public CharType(IdContainer Container, CodeString Name)
			: base(Container, Name)
		{
			this.Size = 2;
			this.Align = 2;
			this.ConstValueType = ConstValueType.Char;
			this.UndeclaredIdType = UndeclaredIdType.Char;
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			if (SrcType == null)
			{
				if (Operators.IsIncDec(Op)) return true;
				if (Op == Operator.Complement || Op == Operator.Negation || Op == Operator.UnaryPlus) 
					return true;
			}
			else if (SrcType.RealId is NumberType || SrcType.RealId is CharType)
			{
				if (Operators.IsRelEquality(Op) || Operators.IsArithmetical(Op)) return true;
				if ((Operators.IsShift(Op) || Operators.IsBitwise(Op))) return true;
			}

			return base.CanOpApplied_Base(Op, SrcType);
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			if (To.RealId is NonFloatType)
				return TypeConversion.Convertable;

			return base.CanConvert(To);
		}

		public override bool IsEquivalent(Identifier Id)
		{
			return Id.RealId is CharType || base.IsEquivalent(Id);
		}
	}

	public class FloatType : NumberType
	{
		public FloatType(IdContainer Container, CodeString Name, int Size)
			: base(Container, Name, Size)
		{
			if (Size == 4)
			{
				this.ConstValueType = ConstValueType.Float;
				this.UndeclaredIdType = UndeclaredIdType.Single;
			}
			else if (Size == 8)
			{
				this.ConstValueType = ConstValueType.Double;
				this.UndeclaredIdType = UndeclaredIdType.Double;
			}
			else
			{
				throw new ApplicationException();
			}
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			return base.CanOpApplied_Base(Op, SrcType) || Op == Operator.UnaryPlus || Op == Operator.Negation;
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			var FTo = To.RealId as FloatType;
			if (FTo != null && FTo.Size >= Size)
				return TypeConversion.Automatic;

			return base.CanConvert(To);
		}
	}

	public class BooleanType : BuiltinType
	{
		public BooleanType(IdContainer Container, CodeString Name)
			: base(Container, Name)
		{
			this.Size = 1;
			this.Align = 1;
			this.ConstValueType = ConstValueType.Boolean;
			this.UndeclaredIdType = UndeclaredIdType.Boolean;
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			if (Op == Operator.Not) return true;
			if (SrcType is BooleanType && (Operators.IsLogical(Op) || Op == Operator.Equality || Op == Operator.Inequality))
				return true;

			return base.CanOpApplied_Base(Op, SrcType);
		}

		public override bool IsEquivalent(Identifier Id)
		{
			return Id.RealId is BooleanType || base.IsEquivalent(Id);
		}
	}

	public class FlagType : EnumType
	{
		public FlagType(IdContainer Container, CodeString Name, Type TypeOfValues)
			: base(Container, Name, TypeOfValues)
		{
			this.DeclaredIdType = DeclaredIdType.Flag;
		}

		public FlagType(IdContainer Container, CodeString Name, CodeString Str_TypeOfValues)
			: base(Container, Name, Str_TypeOfValues)
		{
			this.Str_TypeOfValues = Str_TypeOfValues;
			this.DeclaredIdType = DeclaredIdType.Flag;
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			return base.CanOpApplied_Base(Op, SrcType) || Operators.IsBitwise(Op);
		}
	}

	public class EnumType : Type
	{
		public CodeString Str_TypeOfValues;
		public EnumScope EnumScope;

		public Type TypeOfValues
		{
			get
			{
				if (Children[0] == null) return null;
				return Children[0].RealId as Type;
			}
		}

		public override void Update()
		{
			this.Size = TypeOfValues.Size;
			this.Align = TypeOfValues.Align;
		}

		public override bool HasScopes
		{
			get { return true; }
		}

		public override IEnumerable<ScopeNode> EnumScopes
		{
			get { yield return EnumScope; }
		}

		public EnumType(IdContainer Container, CodeString Name, Identifier TypeOfValues)
			: base(Container, Name)
		{
			this.Children = new Identifier[] { TypeOfValues };
			this.ConstValueType = ConstValueType.Integer;
			this.DeclaredIdType = DeclaredIdType.Enum;
			Update();
		}

		public EnumType(IdContainer Container, CodeString Name, CodeString Str_TypeOfValues)
			: base(Container, Name)
		{
			this.Str_TypeOfValues = Str_TypeOfValues;
			this.ConstValueType = ConstValueType.Integer;
			this.DeclaredIdType = DeclaredIdType.Enum;
			this.Children = new Identifier[] { null };
		}

		public ConstVariable GetValue(string Name)
		{
			var Res = EnumScope.GetContainerId(Name, x => x is ConstVariable);
			if (Res.Count == 0) return null;
			else if (Res.Count == 1) return Res[0].Identifier as ConstVariable;
			else throw new ApplicationException();
		}

		public ConstVariable GetValue(CompilerState State, CodeString Name)
		{
			var Ret = GetValue(Name.ToString());
			if (Ret == null)
				State.Messages.Add(MessageId.UnknownId, Name);

			return Ret;
		}

		public ConstVariable GetValue(BigInteger Value)
		{
			var Members = EnumScope.IdentifierList;
			for (var i = 0; i < Members.Count; i++)
			{
				var EnumVal = Members[i] as ConstVariable;
				if (EnumVal == null) continue;

				var Val = EnumVal.ConstInitValue as IntegerValue;
				if (Val != null && Val.Value == Value) return EnumVal;
			}

			return null;
		}
		
		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			return base.CanOpApplied_Base(Op, SrcType) ||
				Op == Operator.Equality || Op == Operator.Inequality;
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			if (TypeOfValues.CanConvert(To) != TypeConversion.Nonconvertable)
				return TypeConversion.Convertable;

			return base.CanConvert(To);
		}
	}

	public enum ReferenceMode : byte
	{
		Unsafe,
		IdMustBeAssigned,
		IdGetsAssigned,
	}

	public class ReferenceType : Type
	{
		public ReferenceMode Mode;

		public Type Child
		{
			get { return Children[0].RealId as Type; }
		}

		public override void Update()
		{
			GenerateName();
			CalculateAccess();
		}

		public ReferenceType(IdContainer Container, CodeString Name, Identifier Child, ReferenceMode Mode, bool DoUpdate = true)
			: base(Container, Name)
		{
			Setup();
			this.Children = new Identifier[] { Child };
			this.Mode = Mode;
			if (Child != null) Access = Child.Access;
			if (DoUpdate) Update();
		}

		private void Setup()
		{
			UndeclaredIdType = UndeclaredIdType.Reference;
			ConstValueType = ConstValueType.Integer;
			TypeFlags = TypeFlags.CanBeVariable;
			Size = Container.State.Arch.RegSize;
			Align = Size;
		}

		public ReferenceType(IdContainer Container, Identifier Child, ReferenceMode Mode, bool Calc = true)
			: base(Container, new CodeString())
		{
			Setup();
			this.Children = new Identifier[] { Child };
			this.Mode = Mode;
			if (Child != null) Access = Child.Access;
			if (Calc) Update();
		}

		public override bool IsEquivalent(Identifier Id)
		{
			var RType = Id.RealId as ReferenceType;
			if (RType == null) return false;

			if (Mode != RType.Mode) return false;
			return Child.IsEquivalent(RType.Child);
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			var RType = To.RealId as ReferenceType;
			if (RType == null) return TypeConversion.Nonconvertable;

			if (Child.IsEquivalent(RType.Child)) return TypeConversion.Automatic;
			if (Child is AutomaticType) return TypeConversion.Automatic;
			return TypeConversion.Nonconvertable;
		}
	}

	public class TypeOfFunction : Type
	{
		public CallingConvention CallConv;

		public Type RetType
		{
			get { return Children[0].RealId as Type; }
		}

		public override void Update()
		{
			GenerateName();
			CalculateAccess();
		}

		public TypeOfFunction(IdContainer Container, CallingConvention Conv, Identifier[] Children, bool Calc = true)
			: base(Container, new CodeString())
		{
			if (Conv == CallingConvention.Unknown)
				throw new ApplicationException();

			this.UndeclaredIdType = UndeclaredIdType.Function;
			this.Size = Container.State.Arch.RegSize;
			this.Align = this.Size;

			this.Children = Children;
			this.CallConv = Conv;
			if (Calc) Update();
		}

		public TypeOfFunction(IdContainer Container, CallingConvention Conv, Identifier RetType, 
			FunctionParameter[] Params, bool Calc = true) : base(Container, new CodeString())
		{
			if (Conv == CallingConvention.Unknown)
				throw new ApplicationException();

			if (Params != null)
			{
                Children = new Identifier[Params.Length + 1];
				Children[0] = RetType;
				Params.CopyTo(Children, 1);
			}
			else
			{
				Children = new Identifier[] { RetType };
			}

			this.UndeclaredIdType = UndeclaredIdType.Function;
			this.Size = Container.State.Arch.RegSize;
			this.Align = this.Size;
			this.CallConv = Conv;
			if (Calc) Update();
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			if (To.RealId is PointerType)
			{
				var PTo = To.RealId as PointerType;
				if (PTo.Child is VoidType) return TypeConversion.Convertable;
			}
			else if (To.RealId is NonstaticFunctionType)
			{
				var FTo = To.RealId as NonstaticFunctionType;
				if (IsEquivalent(FTo.Child)) return TypeConversion.Automatic;
			}

			return base.CanConvert(To);
		}

		public override bool IsEquivalent(Identifier Id)
		{
			var FType = Id as TypeOfFunction;
			if (FType == null) return false;

			if (CallConv != FType.CallConv) return false;
			if (!RetType.IsEquivalent(FType.RetType)) return false;

			var C = Children.Length;
			if (C != FType.Children.Length) return false;

			for (var i = 1; i < C; i++)
			{
				if (!Children[i].TypeOfSelf.IsEquivalent(FType.Children[i].TypeOfSelf))
					return false;
			}

			return true;
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			if (Op == Operator.Call || Op == Operator.Equality || Op == Operator.Inequality) 
				return true;

			return base.CanOpApplied_Base(Op, SrcType);
		}

		public Type[] GetTypes()
		{
			var Ret = new Type[Children.Length - 1];
			for (var i = 1; i < Children.Length; i++)
				Ret[i - 1] = Children[i].TypeOfSelf.RealId as Type;

			return Ret;
		}

		public int RequiredParameters
		{
			get
			{
				for (var i = 1; i < Children.Length; i++)
				{
					var Param = Children[i] as FunctionParameter;
					if (Param.ConstInitValue != null) return i - 1;
				}

				return Children.Length - 1;
			}
		}

		public FunctionParameter GetParameter(string Name)
		{
			for (var i = 1; i < Children.Length; i++)
			{
				var Param = Children[i] as FunctionParameter;
				if (Param.Name.IsEqual(Name)) return Param;
			}

			return null;
		}
	}

	public abstract class ArrayType : BuiltinType
	{
		public int Dimensions;

		public ArrayType(IdContainer Container, Identifier TypeOfVals)
			: base(Container, new CodeString())
		{
			this.Children = new Identifier[] { TypeOfVals };
		}

		public Type TypeOfValues
		{
			get { return Children[0].RealId as Type; }
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			if (To.RealId is PointerType)
			{
				var PTo = To.RealId as PointerType;
				if (PTo.Child is VoidType)
					return TypeConversion.Automatic;

				var ThisChild = TypeOfValues;
				if (ThisChild is AutomaticType || PTo.Child.IsEquivalent(ThisChild)) 
					return TypeConversion.Automatic;
			}

			return base.CanConvert(To);
		}
	}

	public class RefArrayType : ArrayType
	{
		public RefArrayType(IdContainer Container, Identifier TypeOfVals, int Dimensions, bool Update = true)
			: base(Container, TypeOfVals)
		{
			var Arch = Container.State.Arch;
			this.Align = Arch.RegSize;
			this.Size = Arch.RegSize;
			this.UndeclaredIdType = UndeclaredIdType.RefArrayType;
			this.Dimensions = Dimensions;
			this.TypeFlags |= TypeFlags.ReferenceValue;
			if (Update) this.Update();
		}

		public override void Update()
		{
			GenerateName();
			CalculateAccess();
		}

		public override bool IsEquivalent(Identifier Id)
		{
			if (Id.RealId is RefArrayType)
			{
				var Arr = Id.RealId as RefArrayType;
				if (Arr.Dimensions != Dimensions) return false;
				if (!Arr.TypeOfValues.IsEquivalent(TypeOfValues))
					return false;

				return true;
			}

			return base.IsEquivalent(Id);
		}
		
		public int OffsetToDimensions
		{
			get
			{
				var Base = Container.GlobalContainer.CommonIds.Array;
				if (Base == null) return 0;

				return (Identifiers.GetMember(Container.State, Base,
					new CodeString("Dimensions")) as MemberVariable).Offset;
			}
		}

		public int OffsetToData
		{
			get
			{
				var Arch = Container.State.Arch;
				return OffsetToDimensions + Arch.RegSize * Dimensions;
			}
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			if (Children[0].RealId is AutomaticType && To.RealId is RefArrayType)
				return TypeConversion.Automatic;

			var Base = Container.GlobalContainer.CommonIds.Array;
			if (To.RealId is ObjectType || To.IsEquivalent(Base))
				return TypeConversion.Automatic;

			if (To.RealId is PointerAndLength && Dimensions == 1)
			{
				var PAndLTo = To.RealId as PointerAndLength;
				var PAndLChild = PAndLTo.Child.RealId as Type;
				var ThisChild = TypeOfValues;

				if (ThisChild is AutomaticType || PAndLChild.IsEquivalent(ThisChild))
					return TypeConversion.Automatic;
			}

			return base.CanConvert(To);
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			if (Operators.IsRefEquality(Op) || Op == Operator.Equality ||
				Op == Operator.Inequality || Op == Operator.Member)
			{
				return true;
			}

			return base.CanOpApplied_Base(Op, SrcType);
		}

		public override bool CalculateLayout()
		{
			if (!LayoutCalculated)
			{
				if (!base.CalculateLayout()) return false;

				var Base = Container.GlobalContainer.CommonIds.Array;
				var SBase = Base.UnderlyingStructureOrRealId as StructuredType;
				if (!Base.CalculateLayout()) return false;

				InstanceSize = SBase.InstanceSize;
				LayoutCalculated = true;
			}

			return true;
		}
	}

	public class NonrefArrayType : ArrayType
	{
		public int[] Lengths;
		public int ElementSize;
		public int Pow2Size;

		public int Length
		{
			get
			{
				var Ret = Lengths[0];
				for (var i = 1; i < Lengths.Length; i++)
					Ret *= Lengths[i];

				return Ret;
			}
		}

		public NonrefArrayType(IdContainer Container, Identifier TypeOfVals, int[] Lengths, bool Calc = true)
			: base(Container, TypeOfVals)
		{
			this.Lengths = Lengths;
			this.Dimensions = Lengths == null ? 1 : Lengths.Length;
			this.UndeclaredIdType = UndeclaredIdType.NonrefArrayType;

			if (Lengths == null) TypeFlags |= TypeFlags.UnfixedSize;
			if (Calc) Update();
		}

		public override void Update()
		{
			this.Align = TypeOfValues.Align;
			GenerateName();
			CalculateAccess();
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			if (To.RealId is NonrefArrayType)
			{
				if (Children[0].RealId is AutomaticType)
					return TypeConversion.Automatic;

				var FTo = To.RealId as NonrefArrayType;
				if (FTo.TypeOfValues.IsEquivalent(TypeOfValues) && Lengths == null)
					return TypeConversion.Convertable;
			}

			if (To.RealId is PointerAndLength && Lengths != null && Lengths.Length == 1)
			{
				var PAndLTo = To.RealId as PointerAndLength;
				var PAndLChild = PAndLTo.Child.RealId as Type;
				var ThisChild = TypeOfValues;

				if (ThisChild is AutomaticType || PAndLChild.IsEquivalent(ThisChild))
					return TypeConversion.Automatic;
			}

			if (To.RealId is RefArrayType && Lengths != null)
			{
				var ArrTo = To.RealId as RefArrayType;
				var ArrChild = ArrTo.TypeOfValues;
				var ThisChild = TypeOfValues;

				if (ArrTo.Dimensions == Lengths.Length)
				{
					if (ThisChild is AutomaticType || ArrChild.IsEquivalent(ThisChild))
						return TypeConversion.Automatic;
				}
			}

			return base.CanConvert(To);
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			if (Op == Operator.Index) return true;

			if (Lengths == null) return false;
			return base.CanOpApplied_Base(Op, SrcType);
		}

		public void CalcSize()
		{
			if (Lengths == null) return;

			var ValType = TypeOfValues;
			ElementSize = DataStoring.AlignWithIncrease(ValType.Size, ValType.Align);

			var Size = ElementSize;
			foreach (var e in Lengths)
				Size *= e;

			Pow2Size = Container.State.CalcPow2Size(Size);
			this.Size = Pow2Size;
		}

		public override bool IsEquivalent(Identifier Id)
		{
			var FArr = Id.RealId as NonrefArrayType;
			if (FArr != null && FArr.TypeOfValues.IsEquivalent(TypeOfValues))
			{
				if (FArr.Lengths == null && Lengths == null)
					return true;

				if (FArr.Lengths.Length != Lengths.Length) 
					return false;

				for (var i = 0; i < Lengths.Length; i++)
					if (Lengths[i] != FArr.Lengths[i]) return false;

				return true;
			}

			return false;
		}

		public override bool CalculateLayout()
		{
			CalcSize();
			return base.CalculateLayout();
		}
	}
}

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)

About the Author

Dávid Kocsis
Student
Hungary Hungary
I've been programming for 8 years. My first big project was a remake of a nice bomberman game called Dyna Blaster. When i was little i played a lot with it. Now i'm working on a new programming language and code generator.
I would like to work with someone, so feel free to contact me about it.

| Advertise | Privacy | Mobile
Web03 | 2.8.140721.1 | Last Updated 1 Jan 2013
Article Copyright 2011 by Dávid Kocsis
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid