Click here to Skip to main content
15,896,557 members
Articles / High Performance Computing / Vectorization

Bird Programming Language: Part 1

Rate me:
Please Sign up or sign in to vote.
4.92/5 (129 votes)
1 Jan 2013GPL312 min read 385.2K   2.7K   153  
A new general purpose language that aims to be fast, high level and simple to use.
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Linq;

namespace Anonymus
{
	public enum CommRecognizerRes
	{
		UnknownOp,
		Succeeded,
		Failed,
	}

	public abstract class CommRecognizer
	{
		public virtual CommRecognizerRes Recognize(PString Code, PString Word, PString Line, int Index, CodeScopeNode Scope)
		{
			return CommRecognizerRes.UnknownOp;
		}

		public virtual T GetRecognizer<T>() where T : ExprRecognizer
		{
			if (this is T) return this as T;
			else return null;
		}
	}

	public enum ScopeRelation
	{
		Or,
		And,
		Other,
	}

	public delegate bool CommFunc(CodeScopeNode Scope);

	public abstract class Command : IdContainer
    {
		public PString Code;
        public bool ChkUnreachable = true;
		public bool Unreachable = true;
		public int CommIndex;

		public abstract IEnumerable<ExpressionNode> EnumExpressions { get; }

		public override Variable CreateVariable(PString Name, Type Type, ModifierList Mods = null)
		{
			var Ret = new LocalVariable(this, Name, Type);
			if (Mods != null && !Mods.Apply(this, Ret)) return null;
			return Ret;
		}

		public override void InitCodeChk(bool Unreachable = true)
		{
			base.InitCodeChk();
			this.Unreachable = Unreachable;
		}

		public Command(IdContainer Parent)
			: base(Parent)
		{
		}

		public override MultiPlugIn GetPlugIn()
		{
			return new LocalPlugIn(this);
		}

		public virtual IEnumerable<CodeScopeNode> EnumScopes
		{
			get
			{
				foreach (var e in EnumChildren)
				{
					var Scope = e as CodeScopeNode;
					if (Scope != null) yield return Scope;
				}
			}
		}

		public virtual void GetAsmCode(Compiler Compiler)
        {
        }

		public virtual IEnumerable<CodeScopeNode> GetRunScopes(bool RunScopes = true)
		{
			if (RunScopes)
			{
				foreach (var e in EnumScopes)
					yield return e;
			}
			
			yield break;
		}

		public override void CalcExprRegs()
		{
			foreach (var Expr in EnumExpressions)
				State.Arch.CalcExprDataPos(State, this, Expr);

			base.CalcExprRegs();
		}

		public override bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
		{
			base.ChkCodeRec(Data, ref Succeeded);

			foreach (var Expr in EnumExpressions)
			{
				var D = Expr.Vars;
				foreach (var Node in D.AssignedIds)
					Data.OnAssign(State, Node.Id, null);

				foreach (var Node in D.UsedBeforeAssignIds)
				{
					var Id = Data.GetId(Node.Id);
					if (Id != null) continue;

					var Local = Node.Id as LocalVariable;
					if (Local != null && !Local.PreAssigned)
					{
						State.Messages.Add(MessageId.UnassignedVar, Node.Code);
						Succeeded = false;
					}
				}
			}

			Unreachable = false;
			foreach (var Ch in EnumScopes)
				if (Ch.ChkCodeRec(Data, ref Succeeded)) return true;

			return false;
		}
    }

    public class EmptyCommand : Command
    {
        public EmptyCommand(IdContainer Parent)
			: base(Parent)
        {
        }

		public override IEnumerable<ExpressionNode> EnumExpressions
		{ get { yield break; } }
    }

    public class LabelCommand : Command
    {
		public int Label;

		public LabelCommand(IdContainer Parent, int Label)
			: base(Parent)
        {
            this.Label = Label;
        }

		public override void GetAsmCode(Compiler Compiler)
        {
			Compiler.Label(Label);
        }

		public override IEnumerable<ExpressionNode> EnumExpressions
		{ get { yield break; } }
    }

    public abstract class JumpCommand : Command
    {
		public int Label;
		public bool CodeChk = false;

		public JumpCommand(IdContainer Parent, int Label)
			: base(Parent)
        {
            this.Label = Label;
        }

		public override void GetAsmCode(Compiler Compiler)
        {
			Compiler.Jump(Label);
        }

		public override IEnumerable<ExpressionNode> EnumExpressions
		{ get { yield break; } }

    }

	public class GotoCommand : JumpCommand
	{
		public LabelCommand JumpTo;
		public PString LabelName;

		public GotoCommand(IdContainer Parent, PString LabelName)
			: base(Parent, -1)
        {
			this.LabelName = LabelName;
        }

		public override bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
		{
			base.ChkCodeRec(Data, ref Succeeded);

			if (!CodeChk)
			{
				Unreachable = false;
				CodeChk = true;

				var SParent = JumpTo.Parent as CodeScopeNode;
				SParent.ChkCodeRec(Data, JumpTo.CommIndex, ref Succeeded);
				CodeChk = false;
			}

			return true;
		}
	}

	public class BreakCommand : JumpCommand
	{
		public BreakCommand(IdContainer Parent, int Label)
			: base(Parent, Label)
        {
        }

		public override bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
		{
			if (!CodeChk)
			{
				Unreachable = false;
				CodeChk = true;

				var Breakable = GetScope<BreakableCommand>();
				var SParent = Breakable.Parent as CodeScopeNode;
				SParent.ChkCodeRec(Data, Breakable.CommIndex + 1, ref Succeeded);
				CodeChk = false;
			}

			return true;
		}
	}

	public class ContinueCommand : JumpCommand
	{
		public ContinueCommand(IdContainer Parent, int Label)
			: base(Parent, Label)
		{
		}

		public override bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
		{
			Unreachable = false;
			CodeChk = true;
			return true;
		}
	}

    public class RetCommand : JumpCommand
    {
		public bool Chk;

		public RetCommand(IdContainer Parent, int Label, bool Chk)
            : base(Parent, Label)
        {
			this.Chk = Chk;
        }

		public override bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
		{
			base.ChkCodeRec(Data, ref Succeeded);

			if (Chk)
			{
				var FS = FuncScope;
				if (FS.RetMembers != null && !FS.ChkRetMembers(Data, Code))
					Succeeded = false;
			}

			return true;
		}
    }

	public enum ConditionRes
	{
		True,
		Unknown,
		False,
	}

	public class SwitchCommand : ConditionCommand
	{
		public ExpressionNode Node;

		public SwitchCommand(IdContainer Parent)
			: base(Parent)
		{
		}
	}

	public class CondPart : IdContainer
	{
		public ExpressionNode Condition;
		public CodeScopeNode Then, Else;

		public CondPart(ConditionCommand Parent)
			: base(Parent)
		{
		}

		public override IEnumerable<IdContainer> EnumChildren
		{
			get
			{
				yield return Then;
				if (Else != null) yield return Else;
			}
		}

		public override MultiPlugIn GetPlugIn()
		{
			return new LocalPlugIn(this);
		}

		public override Variable CreateVariable(PString Name, Type Type, ModifierList Mods = null)
		{
			var Ret = new LocalVariable(this, Name, Type);
			if (Mods != null && !Mods.Apply(this, Ret)) return null;
			return Ret;
		}
	}

	public class ConditionCommand : Command
	{
		public List<CondPart> Conditions = new List<CondPart>();

		public ConditionCommand(IdContainer Parent)
			: base(Parent)
		{
		}

		public CondPart LastCondition
		{
			get
			{
				if (Conditions.Count > 0)
					return Conditions[Conditions.Count - 1];

				return null;
			}
		}

		static bool ChkCodeRec(CodeScopeNode Scope, CodeChkData Data, List<CodeChkData> Datas, ref bool Failed)
		{
			var Ret = true;
			var NewData = Data.Copy();
			if (!Scope.ChkCodeRec(NewData, ref Failed)) Ret = false;
			Datas.Add(NewData);
			return Ret;
		}

		public override bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
		{
			Unreachable = false;
			var Datas = new List<CodeChkData>();
			var Ret = true;

			foreach (var e in Conditions)
			{
				if (!ChkCodeRec(e.Then, Data, Datas, ref Succeeded)) Ret = false;

				if (e.Else != null)
				{
					if (!ChkCodeRec(e.Else, Data, Datas, ref Succeeded)) Ret = false;
					Data.Vars.AddRange(Datas.Intersect().Vars);
					return Ret;
				}
			}

			return false;
		}

		public CondPart CreateCondition()
		{
			var Ret = new CondPart(this);
			State.Arch.OnNewContainer(Ret);
			var L = LastCondition;

			if (L != null && L.Condition == null)
				Conditions.Insert(Conditions.Count - 1, L);
			else Conditions.Add(Ret);

			return Ret;
		}

		public bool HasElseNIf()
		{
			var L = LastCondition;
			return L == null || L.Condition == null || L.Else != null;
		}

		public override IEnumerable<ExpressionNode> EnumExpressions
		{
			get
			{
				foreach (var e in Conditions)
				{
					if (e.Condition != null)
						yield return e.Condition;
				}
			}
		}

		public override IEnumerable<IdContainer> EnumChildren
		{
			get
			{
				return Conditions;
			}
		}

		object GetElse(CondPart Part, int Index)
		{
			if (Part.Else != null) return Part.Else;
			else if (Index < Conditions.Count - 1) return Index + 1;
			else return null;
		}

		void CalcElse(Compiler Comp, CondPart Part, int Index)
		{
			if (Part.Else != null) Part.Else.GetAsmCode(Comp);
			else if (Index < Conditions.Count - 1) CalcAsmCode(Comp, Index + 1);
		}

		CondBranch GetDefCondBranch(object Obj)
		{
			CodeCondBranchFunc Func = null;
			if (Obj is CodeScopeNode)
			{
				var Scope = Obj as CodeScopeNode;
				Func = (Comp) => { Scope.GetAsmCode(Comp); };
			}
			else if (Obj is int)
			{
				Func = (Comp) => { CalcAsmCode(Comp, (int)Obj); };
			}
			else
			{
				throw new Exception("ERROR");
			}

			return new CodeCondBranch(Func);
		}

		Command GetCommand(object Obj)
		{
			var Scope = Obj as CodeScopeNode;
			if (Scope == null || Scope.Commands.Count != 1)
				return null;

			return Scope.Commands[0];
		}

		int NextLabel;
		void CalcAsmCode(Compiler Compiler, int Index)
		{
			var Part = Conditions[Index];

			var Res = ConditionRes.True;
			if (Part.Condition != null)
				Res = Part.Condition.ConditionResult;

			switch (Res)
			{
				case ConditionRes.Unknown:
					var Else = GetElse(Part, Index);
					var Cond = Part.Condition;
					var ThenCmd = GetCommand(Part.Then);
					var ElseCmd = GetCommand(Else);

					var Branches = State.Arch.GetBraches(Compiler, GlobalScope, ThenCmd, ElseCmd, ref Cond);
					if (Branches[0] == null) Branches[0] = GetDefCondBranch(Part.Then);
					if (Branches[1] == null && Else != null) Branches[1] = GetDefCondBranch(Else);

					Compiler.GetConditionCode(Cond, Branches[0], Branches[1], NextLabel: NextLabel,
						ThenAllPathJumpAway: Part.Then.AllPathJumpAway);

					break;

				case ConditionRes.True:
					Part.Then.GetAsmCode(Compiler);
					break;

				case ConditionRes.False:
					CalcElse(Compiler, Part, Index);
					break;
			}
		}

		public override void GetAsmCode(Compiler Compiler)
		{
			NextLabel = State.NextLabelIndex;
			CalcAsmCode(Compiler, 0);
			Compiler.Label(NextLabel);
		}

		public override IEnumerable<CodeScopeNode> GetRunScopes(bool RunScopes = true)
		{
			bool Run = true;
			foreach (var e in Conditions)
			{
				var Res = ConditionRes.False;
				if (Run)
				{
					if (e.Condition == null) Res = ConditionRes.True;
					else Res = e.Condition.ConditionResult;
				}

				if (Res == ConditionRes.True) Run = false;

				if ((Res != ConditionRes.False) == RunScopes) yield return e.Then;
				if ((Res != ConditionRes.True) == RunScopes && e.Else != null) yield return e.Else;
			}
		}

		public override IEnumerable<CodeScopeNode> EnumScopes
		{
			get
			{
				foreach (var e in Conditions)
				{
					yield return e.Then;
					if (e.Else != null) yield return e.Else;
				}
			}
		}
	}

	public abstract class BreakableCommand : Command
	{
		public int BreakLabel;
		public int ContinueLabel;

		public BreakableCommand(IdContainer Parent)
			: base(Parent)
		{
			BreakLabel = State.NextLabelIndex;
			ContinueLabel = State.NextLabelIndex;
		}
	}

	public class LoopCommand : BreakableCommand
	{
		public CodeScopeNode InnerScope;

		public LoopCommand(IdContainer Parent)
			: base(Parent)
		{
		}

		public override IEnumerable<IdContainer> EnumChildren
		{
			get
			{
				yield return InnerScope;

				foreach (var e in base.EnumChildren)
					yield return e;
			}
		}

		public override IEnumerable<ExpressionNode> EnumExpressions
		{ get { yield break; } }

		public override void GetAsmCode(Compiler Compiler)
        {
			Compiler.Label(ContinueLabel);
			if (InnerScope != null) InnerScope.GetAsmCode(Compiler);
			Compiler.Jump(ContinueLabel);
			Compiler.Label(BreakLabel);
        }
	}

	public class WhileCommand : LoopCommand
    {
        public ExpressionNode Condition;
        public bool DoWhile;

		ConditionRes _WillRun;
		bool _WillRun_Calced = false;
		public ConditionRes WillRun
		{
			get
			{
				if (!_WillRun_Calced) _WillRun = WillInnerScopeRun();
				return _WillRun;
			}
		}

		public WhileCommand(IdContainer Parent, ExpressionNode Condition, bool DoWhile = false)
            : base(Parent)
        {
            this.Condition = Condition;
            this.DoWhile = DoWhile;
        }

        private void GetConditionCode(bool JumpIfNot, int Then, Compiler Compiler)
        {
            var OpC = Condition as OpExpressionNode;
            var Last = OpC == null ? false : OpC.Operator == Operator.Or;
            if (!JumpIfNot) Last = !Last;
            Compiler.CalcCondAsmCode(Condition, Then, BreakLabel, Operator.Nothing, Last);
        }

		public void GetAsmCodeWExp(Compiler Compiler, ExpressionNode Loop = null, bool ChkFirst = true)
        {
            if (WillRun == ConditionRes.False) return;
            var Then = State.NextLabelIndex;
            var CondLbl = State.NextLabelIndex;

            //--------------------------------------------------------
            ReplaceJumpsFunc Func = C =>
            {
                GetConditionCode(!ChkFirst, Then, C);
                if (ChkFirst) C.Jump(BreakLabel);
                else C.Jump(Then);
            };

            Compiler.SetJumpReplacing(CondLbl, Func);

            //--------------------------------------------------------
			if (ChkFirst)
			{
				Compiler.Label(CondLbl);
                GetConditionCode(ChkFirst, Then, Compiler);
			}

			Compiler.Label(Then);
			if (InnerScope != null) InnerScope.GetAsmCode(Compiler);

			Compiler.Label(ContinueLabel);
			if (Loop != null) Compiler.GetExprCode(Loop);

			if (!ChkFirst)
			{
                Compiler.Label(CondLbl);
                GetConditionCode(ChkFirst, Then, Compiler);
			}
			else
			{
				Compiler.Jump(CondLbl);
			}

			Compiler.Label(BreakLabel);
        }

		public virtual ConditionRes WillInnerScopeRun()
		{
			return Condition.ConditionResult;
		}

		public override IEnumerable<CodeScopeNode> GetRunScopes(bool RunScopes = true)
		{
			if (RunScopes)
			{
				if (WillRun != ConditionRes.False)
					yield return InnerScope;
			}
			else
			{
				if (WillRun == ConditionRes.False)
					yield return InnerScope;
			}
		}

		public override void GetAsmCode(Compiler Compiler)
        {
			GetAsmCodeWExp(Compiler, null, !DoWhile);
        }

		public override IEnumerable<ExpressionNode> EnumExpressions
		{ get { yield return Condition; } }
    }

    public class ForCommand : WhileCommand
    {
        public ExpressionNode Loop, Init;
		public bool WillRunCalced = false;

		public ForCommand(IdContainer Parent, ExpressionNode Condition, ExpressionNode Loop, ExpressionNode Init)
            : base(Parent, Condition, false)
        {
            this.Loop = Loop;
			this.Init = Init;
        }

		public override void GetAsmCode(Compiler Compiler)
        {
			if (Init != null) Compiler.GetExprCode(Init);
			GetAsmCodeWExp(Compiler, Loop, WillInnerScopeRun() != ConditionRes.True);
        }

		public override ConditionRes WillInnerScopeRun()
		{
			var Res = base.WillInnerScopeRun();
			if (Res != ConditionRes.Unknown) return Res;

			ExpressionNode AssignTo = null;
			Variable AssignVar = null;

			if (Init is OpExpressionNode)
			{
				var OpNode = Init as OpExpressionNode;
				if (OpNode.Operator == Operator.Assignment)
				{
					var Ch = OpNode.Children;
					AssignTo = Ch[1];
					OpNode.GetAssignVar(ref AssignVar);
				}
			}

			if (AssignVar != null && !AssignTo.IdUsed())
			{
				var ConstAssignTo = AssignTo as ConstExpressionNode;
				if (ConstAssignTo == null) return ConditionRes.Unknown;

				var OpCondition = Condition as OpExpressionNode;
				if (OpCondition == null) return ConditionRes.Unknown;
				var Op = OpCondition.Operator;
				var Ch = OpCondition.Children;

				if (!Operators.IsRelEqualityOp(Op)) return ConditionRes.Unknown;
				var IdCh0 = Ch[0] as IdExpressionNode;
				if (IdCh0 == null || IdCh0.Id != AssignVar) return ConditionRes.Unknown;
				var ConstCh1 = Ch[1] as ConstExpressionNode;
				if (ConstCh1 == null) return ConditionRes.Unknown;

				var NewCh = new List<ExpressionNode>() { ConstAssignTo, ConstCh1 };
				var NewNode = new OpExpressionNode(Op, NewCh, null);
				var Ret = ConstExpressionNode.DoOps(this, NewNode);
				return Ret.ConditionResult;
			}

			return ConditionRes.Unknown;
		}

		public override IEnumerable<ExpressionNode> EnumExpressions
		{
			get
			{
				yield return Loop;
				yield return Init;
				yield return Condition;
			}
		}
    }

    public class ExpressionCommand : Command
    {
        public ExpressionNode Expression;

		public ExpressionCommand(IdContainer Parent, ExpressionNode Expression)
			: base(Parent)
        {
            this.Expression = Expression;
        }

		public override IEnumerable<ExpressionNode> EnumExpressions
		{ get { yield return Expression; } }

        public override void GetAsmCode(Compiler Compiler)
        {
            // sb.Append("\n\t; " + Expression.CompData().Code.String + "\n");
            Compiler.GetExprCode(Expression);
        }
    }

    public class AsmCommand : Command
    {
        public List<object> List = new List<object>();

        public AsmCommand(IdContainer Parent)
			: base(Parent)
        {
        }

        public bool Process(CompilerState State, PString AsmCode)
        {
            var Ret = true;
            var Pos = AsmCode.IndexOf('$');
			var PlugIn = GetPlugIn();

            while (Pos != -1)
            {
                List.Add(AsmCode.String.Substring(0, Pos));
                AsmCode = AsmCode.Substring(Pos + 1);
                var VarName = AsmCode.Word();

				var Node = PlugIn.NewNode(new StrExpressionNode(VarName));
                if (!(Node is IdExpressionNode))
                {
                    State.Messages.Add(MessageId.AsmNotRId, VarName);
                    Node = null;
                }

                if (Node == null) Ret = false;
                else List.Add(Node);

                Pos = AsmCode.IndexOf('$');
            }

            if (AsmCode.String != "")
                List.Add(AsmCode.String);

            return Ret;
        }

        public override void GetAsmCode(Compiler Compiler)
        {
			Compiler.Append("\t");
            foreach (var e in List)
            {
				if (e is string) Compiler.Append(e as string);
#warning WARNING
				//else if (e is ExpressionNode) Compiler.Append(Compiler.GetPositionString((e as ExpressionNode), null));
                else throw new Exception("ERROR");
            }

			Compiler.Append("\n");
        }

		public override IEnumerable<ExpressionNode> EnumExpressions
		{ get { yield break; } }
    }

}

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