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

Bird Programming Language: Part 3

, 1 Jan 2013 GPL3
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Numerics;

namespace Bird
{
	public enum StructureBaseFlags : byte
	{
		None = 0,
		Virtual = 1,
		Unreal = 2,
	}

	public struct StructureBase
	{
		public StructureBaseFlags Flags;
		public Identifier Base;
		public CodeString Declaration;
		public CodeString Name;
		public int Offset;

        public StructureBase(CodeString Declaration, CodeString Name = new CodeString(),
            StructureBaseFlags Flags = StructureBaseFlags.None)
		{
			this.Base = null;
			this.Declaration = Declaration;
			this.Name = Name;
			this.Offset = -1;
			this.Flags = Flags;
		}

        public StructureBase(Identifier Identifier, StructureBaseFlags Flags = StructureBaseFlags.None)
        {
            this.Base = Identifier;
            this.Declaration = new CodeString();
            this.Name = new CodeString();
            this.Offset = -1;
            this.Flags = Flags;
        }
	}

	public struct VirtualListNode
	{
		public VirtualListNode[] Children;
		public MemberFunction[] Virtuals;

		public void Override(MemberFunction Old, MemberFunction New)
		{
			for (var i = 0; i < Virtuals.Length; i++)
				if (Virtuals[i] == Old) Virtuals[i] = New;

			for (var i = 0; i < Children.Length; i++)
				Children[i].Override(Old, New);
		}

		public VirtualListNode Copy()
		{
			var Ret = new VirtualListNode();
			Ret.Children = new VirtualListNode[Children.Length];
			for (var i = 0; i < Children.Length; i++)
				Ret.Children[i] = Children[i].Copy();

			Ret.Virtuals = Virtuals.ToArray();
			return Ret;
		}
	}

	public abstract class StructuredType : Type
	{
		public StructuredScope StructuredScope;
		public StructureBase[] BaseStructures;
		public Guid? Guid;
		public int VarSize;

		public VirtualListNode Virtuals;
		public AutoAllocatedList<MemberFunction> OldVirtuals;
		public bool HasFunctionTable;
		public int FunctionTableIndex = -1;

        public List<IdentifierFound> SearchBase(IdContainer Container, string Name, Predicate<Identifier> Func = null)
		{
			var Out = new List<IdentifierFound>();
			SearchBase(Container, Name, Out, Func);
			return Out;
		}

		public bool IsSubstructureOf(Identifier Id)
		{
			for (var i = 0; i < BaseStructures.Length; i++)
			{
				var BaseId = BaseStructures[i].Base;
				if (BaseId.IsEquivalent(Id)) return true;

				var Structure = BaseId.UnderlyingStructureOrRealId as StructuredType;
				if (Structure != null && Structure.IsSubstructureOf(Id)) return true;
			}

			return false;
		}

		public void SearchBase(IdContainer Container, string Name, List<IdentifierFound> Out, Predicate<Identifier> Func = null)
		{
			for (var i = 0; i < BaseStructures.Length; i++)
				if (Name == null || BaseStructures[i].Name.IsEqual(Name))
				{
					if (Func == null || Func(BaseStructures[i].Base))
						Out.Add(new IdentifierFound(Container, BaseStructures[i].Base));
				}

			if (Out.Count == 0)
			{
				for (var i = 0; i < BaseStructures.Length; i++)
				{
					var BaseId = BaseStructures[i].Base;
					var Structure = BaseId.UnderlyingStructureOrRealId as StructuredType;
					if (Structure != null) Structure.SearchBase(Container, Name, Out, Func);
				}
			}
		}

		public override void Update()
		{
			Children = new Identifier[BaseStructures.Length];
			for (var i = 0; i < BaseStructures.Length; i++)
				Children[i] = BaseStructures[i].Base;

			base.Update();
		}

		public string FunctionTableLabel
		{
			get { return AssemblyName + "_%FunctionTable"; }
		}

		public bool HasNonstaticConstructor
		{
			get
			{
				for (var i = 0; i < StructuredScope.IdentifierList.Count; i++)
				{
					var Ctor = StructuredScope.IdentifierList[i] as Constructor;
					if (Ctor != null && (Ctor.Flags & IdentifierFlags.Static) == 0)
						return true;
				}

				return false;
			}
		}

		public bool HasParameterLessCtor
		{
			get
			{
				var HasConstructor = false;
				for (var i = 0; i < StructuredScope.IdentifierList.Count; i++)
				{
					var Ctor = StructuredScope.IdentifierList[i] as Constructor;
					if (Ctor == null || (Ctor.Flags & IdentifierFlags.Static) != 0) continue;

					var Type = Ctor.TypeOfSelf.RealId as TypeOfFunction;
					if (Type.Children.Length == 1) return true;
					HasConstructor = true;
				}

				return !HasConstructor;
			}
		}

		public override void GetAssembly(CodeGenerator CG, GetAssemblyMode Mode)
		{
			if (Mode == GetAssemblyMode.InitedValues && HasFunctionTable)
			{
				CG.InsContainer.Label(FunctionTableLabel);
				for (var i = 0; i < OldVirtuals.Count; i++)
					CG.DeclareLabelPtr(OldVirtuals[i].AssemblyName);

				CG.InsContainer.Add("\n");
			}

			base.GetAssembly(CG, Mode);
		}

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

		public MemberVariable GetMemberAt(int Offset, int Size = 1)
		{
			if (Offset < 0) throw new ArgumentOutOfRangeException("Offset");

			var Members = StructuredScope.IdentifierList;
			for (var i = 0; i < Members.Count; i++)
			{
				var NextOffset = InstanceSize;
				if (i < Members.Count - 1)
				{
					var NextVar = Members[i + 1] as MemberVariable;
					if (NextVar != null) NextOffset = NextVar.Offset;
				}

				var Var = Members[i] as MemberVariable;
				if (Var != null && Var.Offset >= Offset && Offset + Size <= NextOffset)
					return Var;
			}

			return null;
		}

		public bool TrueForAllMembers(Predicate<Identifier> Func)
		{
			return StructuredScope.IdentifierList.TrueForAll(Func);
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			if (Op == Operator.Member || Op == Operator.NewObject) return true;
			if (Op == Operator.Equality || Op == Operator.Inequality) return true;
			return base.CanOpApplied_Base(Op, SrcType);
		}
		
		public bool NewCalculateLayout()
		{
			if (!LayoutCalculated)
			{
				if (!base.CalculateLayout())
					return false;

				LayoutCalculated = true;
			}

			return true;
		}

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

				VarSize = 0;
				LayoutCalculated = true;
				return CalculateOffsets();
			}

			return true;
		}

		public virtual bool CalculateOffsets()
		{
			var Members = StructuredScope.IdentifierList;
			for (var i = 0; i < Members.Count; i++)
			{
				var MemVar = Members[i] as MemberVariable;
				if (MemVar != null)
				{
                    var Type = MemVar.TypeOfSelf.RealId as Type;

                    var Struct = Type as StructType;
					if (Struct != null && !Struct.CalculateLayout()) return false;

					MemVar.Offset = DataStoring.AlignWithIncrease(VarSize, Type.Align);
                    VarSize = MemVar.Offset + Type.Size;
				}
			}

			InstanceSize = Container.State.CalcPow2Size(VarSize);
			return true;
		}

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

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

		public void CalcVirtuals()
		{
			OldVirtuals.Clear();

			var BaseStructures = this.BaseStructures;
			if ((TypeFlags & Bird.TypeFlags.ReferenceValue) == 0)
				BaseStructures = Identifiers.GetUnrealBases(this);

			if (BaseStructures.Length == 1)
			{
				var Base = BaseStructures[0].Base;
				var SBase = Base.UnderlyingStructureOrRealId as StructuredType;

				SBase.CalcVirtuals();
				OldVirtuals.AddRange(SBase.OldVirtuals);
			}
			else if (BaseStructures.Length > 1)
			{
				throw new NotImplementedException();
			}

			var Members = StructuredScope.IdentifierList;
			for (var i = 0; i < Members.Count; i++)
			{
				var Id = Members[i];
				if ((Id.Flags & IdentifierFlags.Virtual) != 0)
				{
					if (Id is MemberFunction)
					{
						ProcessVirtual(Id as MemberFunction);
					}
					else if (Id is Property)
					{
						var Property = Id as Property;
						var PropertyMembers = Property.PropertyScope.IdentifierList;

						for (var j = 0; j < PropertyMembers.Count; j++)
						{
							var Func = PropertyMembers[j] as MemberFunction;
							if (Func != null) ProcessVirtual(Func);
						};
					}
				}
			}

			if ((Flags & IdentifierFlags.Abstract) == 0)
				HasFunctionTable = OldVirtuals.Count > 0;
		}

		private void ProcessVirtual(MemberFunction Func)
		{
			Func.SetUsed();
			if ((Func.Flags & IdentifierFlags.Override) != 0)
			{
                var Overridden = Func.OverriddenId.RealId as MemberFunction;
                Func.VirtualIndex = Overridden.VirtualIndex;
				OldVirtuals[Func.VirtualIndex] = Func;
			}
			else
			{
				Func.VirtualIndex = OldVirtuals.Count;
				OldVirtuals.Add(Func);
			}
		}

		public override void GetGlobalPointers(List<string> Out)
		{
			if (HasFunctionTable)
			{
				FunctionTableIndex = Out.Count;
				Out.Add(FunctionTableLabel);
			}
			else
			{
				FunctionTableIndex = -1;
			}
		}
	}

	public class ClassType : StructuredType
	{
		public override bool CalculateOffsets()
		{
			CalcVirtuals();

			if (BaseStructures.Length > 0)
			{
				if (BaseStructures.Length > 1)
					throw new NotImplementedException();

				var Base = BaseStructures[0].Base;
				var SBase = Base.UnderlyingStructureOrRealId as StructuredType;
				if (!SBase.CalculateLayout()) return false;

				VarSize = SBase.InstanceSize;
			}
			else
			{
				VarSize = 0;
			}

			return base.CalculateOffsets();
		}

		public ClassType(IdContainer Container, CodeString Name, Identifier[] Children = null)
			: base(Container, Name)
		{
			this.Size = Container.State.Arch.RegSize;
			this.ConstValueType = ConstValueType.Unknown;
			this.DeclaredIdType = DeclaredIdType.Class;
			this.TypeFlags |= TypeFlags.ReferenceValue;

			this.Align = this.Size;
			this.Children = Children;
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			if (Identifiers.IsSubtypeOf(this, To)) return TypeConversion.Automatic;
			else if (Identifiers.IsSubtypeOf(To, this)) return TypeConversion.Convertable;
			else if (Identifiers.IsBoxing(To, this)) return TypeConversion.Convertable;
			else return base.CanConvert(To);
		}

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

	public class StructType : StructuredType
	{
		public StructType(IdContainer Container, CodeString Name, Identifier[] Children = null)
			: base(Container, Name)
		{
			this.Children = Children;
			this.DeclaredIdType = DeclaredIdType.Struct;
		}

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

			return base.CanConvert(To);
		}

		public bool CheckAlign()
		{
			var State = Container.State;
			for (var i = 0; i < StructuredScope.IdentifierList.Count; i++)
			{
				var Member = StructuredScope.IdentifierList[i] as MemberVariable;
				if (Member != null && Member.Align > Align)
				{
					State.Messages.Add(MessageId.NotAlignedEnough, Member.Declaration);
					return false;
				}
			}

			return true;
		}

		public override bool CalculateLayout()
		{
			var Members = StructuredScope.IdentifierList;
			for (var i = 0; i < Members.Count; i++)
				if (!Members[i].CalculateLayout()) return false;

			return base.CalculateLayout();
		}

		public override bool CalculateOffsets()
		{
			CalcVirtuals();
			if (!base.CalculateOffsets())
				return false;

			Size = InstanceSize;
			if (Align == 0)
				Align = Math.Min(Size, Container.State.Arch.MaxStructPow2Size);

			return CheckAlign();
		}
	}

	public class NonstaticFunctionType : TupleType
	{
		public Identifier Child
		{
			get { return Children[0]; }
		}

		public NonstaticFunctionType(IdContainer Container, Identifier Child, bool DoUpdate = true)
			: base(Container, new CodeString(), true)
		{
			Children = new Identifier[1] { Child };
			if (Child != null && !(Child is TypeOfFunction))
				throw new ArgumentException(null, "Child");

			this.UndeclaredIdType = UndeclaredIdType.NonstaticFunctionType;
			var Scope = new StructuredScope(Container, new CodeString(), this);
			StructuredScope = Scope;

			var SelfType = Container.GlobalContainer.CommonIds.Object;
			var Self = new MemberVariable(Scope, new CodeString("Self"), SelfType);
			Self.Access = IdentifierAccess.Public;
			Scope.IdentifierList.Add(Self);

			var PointerType = Container.GlobalContainer.CommonIds.VoidPtr;
			var Pointer = new MemberVariable(Scope, new CodeString("Pointer"), PointerType);
			Pointer.Access = IdentifierAccess.Public;
			Scope.IdentifierList.Add(Pointer);

			if (DoUpdate) Update();
		}

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

	public class PointerAndLength : TupleType
	{
		public Identifier PointerType
		{
			get
			{
				var Members = StructuredScope.IdentifierList;
				return Members[0].Children[0];
			}
		}

		public Identifier Child
		{
			get
			{
				return PointerType.RealId.Children[0];
			}
		}

		public PointerAndLength(TupleType Tuple, bool DoUpdate = true)
			: base(Tuple.Container, new CodeString(), true)
        {
            this.UndeclaredIdType = UndeclaredIdType.PointerAndLength;
			StructuredScope = Tuple.StructuredScope;
			if (DoUpdate) Update();
		}

		public PointerAndLength(IdContainer Container, Identifier Child, bool DoUpdate = true)
			: base(Container, new CodeString(), true)
		{
            this.UndeclaredIdType = UndeclaredIdType.PointerAndLength;
			var Scope = new StructuredScope(Container, new CodeString(), this);
			StructuredScope = Scope;

			var PointerType = new PointerType(Container, Child, DoUpdate);
			var Pointer = new MemberVariable(Scope, new CodeString("Pointer"), PointerType);
			Pointer.Access = IdentifierAccess.Public;
			Scope.IdentifierList.Add(Pointer);

            var LengthType = Container.GlobalContainer.CommonIds.UIntPtr;
			var Length = new MemberVariable(Scope, new CodeString("Length"), LengthType);
			Length.Access = IdentifierAccess.Public;
			Scope.IdentifierList.Add(Length);

			if (DoUpdate) Update();
		}

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

			return base.CanConvert(To);
		}

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

	public class TupleType : StructType
	{
		public bool Named = false;

		public TupleType(IdContainer Container, CodeString Name, bool Named)
			: base(Container, Name)
		{
			this.UndeclaredIdType = UndeclaredIdType.Tuple;
			this.DeclaredIdType = DeclaredIdType.Unknown;
			this.Named = Named;

			this.BaseStructures = new StructureBase[0];
		}

		public TupleType(IdContainer Container, List<Identifier> Members)
			: base(Container, new CodeString())
		{
			this.UndeclaredIdType = UndeclaredIdType.Tuple;
			this.DeclaredIdType = DeclaredIdType.Unknown;
			var Scope = new StructuredScope(Container, new CodeString(), this);

			if (Members != null)
			{
				Scope.IdentifierList = Members;
				for (var i = 0; i < Members.Count; i++)
					Members[i].Container = Scope;
			}

			this.StructuredScope = Scope;
			this.BaseStructures = new StructureBase[0];
			Update();
		}

		public TupleType(IdContainer Container, StructuredScope StructuredTypeScope)
			: base(Container, new CodeString())
		{
			this.UndeclaredIdType = UndeclaredIdType.Tuple;
			this.DeclaredIdType = DeclaredIdType.Unknown;
			this.StructuredScope = StructuredTypeScope;
			Update();
		}

		public bool OnlyHasNumberMembers
		{
			get
			{
				var Members = StructuredScope.IdentifierList;
				for (var i = 0; i < Members.Count; i++)
				{
					if (!(Members[i].TypeOfSelf.RealId is NumberType))
						return false;
				}

				return true;
			}
		}

		public override void CalculateAccess()
		{
			Access = IdentifierAccess.Public;
			var Members = StructuredScope.IdentifierList;
			for (var i = 0; i < Members.Count; i++)
			{
				var MemberAccess = Members[i].TypeOfSelf.Access;
				Access = Identifiers.IdAccessIntersect(Access, MemberAccess);
			}
		}

		public override void Update()
		{
			var Members = StructuredScope.IdentifierList;
			if (Members.Count > 0)
			{
				Named = Members[0].Name.IsValid;
				for (var i = 0; i < Members.Count; i++)
				{
					if (Members[i].Name.IsValid != Named)
						throw new ApplicationException();

					var MemberType = Members[i].TypeOfSelf;
					var RMemberType = MemberType.RealId as Type;

					if ((RMemberType.TypeFlags & TypeFlags.CanBeVariable) == 0 ||
						RMemberType is AutomaticType)
					{
						TypeFlags &= ~TypeFlags.CanBeEverything;
					}
				}
			}
			else
			{
				Named = false;
			}

			GenerateName();
			CalculateAccess();
		}

		public override bool IsEquivalent(Identifier Id)
		{
			var V = Id.RealId as TupleType;
			if (V != null)
			{
				var Members = StructuredScope.IdentifierList;
				var VMembers = V.StructuredScope.IdentifierList;

				if (VMembers.Count != Members.Count) return false;
				for (var i = 0; i < Members.Count; i++)
				{
					var Var1 = VMembers[i] as MemberVariable;
					var Var2 = Members[i] as MemberVariable;
					if (Var1 == null || Var2 == null) return false;

					if (!Var2.TypeOfSelf.IsEquivalent(Var1.TypeOfSelf)) return false;
				}

				return true;
			}

			return base.IsEquivalent(Id);
		}

		public override TypeConversion CanConvert(Identifier To)
		{
			var Members = StructuredScope.IdentifierList;

			var V = To.RealId as TupleType;
			if (V != null)
			{
				var VMembers = V.StructuredScope.IdentifierList;
				if (VMembers.Count != Members.Count) return TypeConversion.Nonconvertable;
				else if (Members.Count == 0) return TypeConversion.Automatic;

				var Automatic = true;
				for (var i = 0; i < Members.Count; i++)
				{
					var Var1 = Members[i] as MemberVariable;
					var Var2 = VMembers[i] as MemberVariable;
					if (Var1 == null || Var2 == null) return TypeConversion.Nonconvertable;

					var Res = Var1.TypeOfSelf.CanConvert(Var2.TypeOfSelf);
					if (Res == TypeConversion.Convertable) Automatic = false;
					else if (Res == TypeConversion.Nonconvertable) return Res;
				}

				if (Automatic) return TypeConversion.Automatic;
				else return TypeConversion.Convertable;
			}

			return base.CanConvert(To);
		}

		internal override bool CanOpApplied_Base(Operator Op, Type SrcType)
		{
			if (Operators.IsRelEquality(Op) || Operators.IsArithmetical(Op) || Operators.IsRange(Op))
			{
				var TupleSrc = SrcType.RealId as TupleType;
				if (TupleSrc == null)
				{
					return TrueForAllMembers(x =>
                    {
                        var xType = x.TypeOfSelf.RealId as Type;
                        return xType.CanOpApplied(Op, SrcType);
                    });
				}
				else
				{
					var Members = StructuredScope.IdentifierList;
					var VMembers = TupleSrc.StructuredScope.IdentifierList;

					if (VMembers.Count != Members.Count) return false;
					else if (Members.Count == 0) return true;

					for (var i = 0; i < Members.Count; i++)
					{
						var Var1 = Members[i] as MemberVariable;
						var Var2 = VMembers[i] as MemberVariable;
						if (Var1 == null || Var2 == null) return false;

                        var Type1 = Var1.TypeOfSelf.RealId as Type;
                        var Type2 = Var2.TypeOfSelf.RealId as Type;
                        if (!Type1.CanOpApplied(Op, Type2)) return false;
					}

					return true;
				}
			}

			if (Op == Operator.UnaryPlus || Op == Operator.Negation || 
				Op == Operator.Complement || Operators.IsIncDec(Op))
			{
				var Members = StructuredScope.IdentifierList;
				for (var i = 0; i < Members.Count; i++)
				{
					var Var = Members[i] as MemberVariable;
                    var Type = Var.TypeOfSelf.RealId as Type;
                    if (Var == null || !Type.CanOpApplied(Op, null))
						return false;
				}

				return true;
			}

			return base.CanOpApplied_Base(Op, SrcType);
		}
	}

}

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)

Share

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 | Terms of Use | Mobile
Web03 | 2.8.150414.1 | Last Updated 1 Jan 2013
Article Copyright 2012 by Dávid Kocsis
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid