Click here to Skip to main content
15,881,172 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 372.8K   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.Linq;

namespace Anonymus
{
	public abstract class CodeProcessor
	{
		public abstract bool Process(CodeScopeNode Scope);
	}

    public class CodeScopeNode : ScopeNode
    {
		public List<Command> Commands = new List<Command>();
		public bool AllPathJumpAway;

		public override IEnumerable<IdContainer> EnumChildren
		{
			get
			{
				return Commands.Union(base.EnumChildren);
			}
		}

		public IEnumerable<CodeScopeNode> EnumScopes
		{
			get
			{
				foreach (var Command in Commands)
					foreach (var e in Command.EnumScopes)
						yield return e;
			}
		}

		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 bool FinishCodeChk()
		{
			var Ret = base.FinishCodeChk();
			var Unreachable = false;

			foreach (var Comm in Commands)
				if (Unreachable != Comm.Unreachable && Comm.ChkUnreachable)
				{
					Unreachable = Comm.Unreachable;
					if (Unreachable) State.Messages.Add(MessageId.UnreacheableCode, Comm.Code);
				}

			return Ret;
		}

		public override bool ChkCodeRec(CodeChkData Data, ref bool Succeeded)
		{
			return ChkCodeRec(Data, 0, ref Succeeded);
		}

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

			for (var i = StartIndex; i < Commands.Count; i++)
				if (Commands[i].ChkCodeRec(Data, ref Succeeded))
				{
					AllPathJumpAway = true;
					return true;
				}

			return false;
		}

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

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

		public CodeScopeNode(IdContainer Parent, PString[] Source)
			: base(Parent, Source)
        {
        }

        public bool AddCommand(PString Code, Command Comm, bool ChkUnreachable = true)
        {
            var LComm = LastCommand;
			if (LComm!= null)
			{
				if (LComm is WhileCommand)
				{
					var C = LComm as WhileCommand;
					if (C.DoWhile && C.Condition == null)
					{
						State.Messages.Add(MessageId.MustWhile, LComm.Code);
						Commands.RemoveAt(Commands.Count - 1);
						return false;
					}
				}

				else if (LComm is SwitchCommand)
				{
					var Switch = LComm as SwitchCommand;
					if (Switch.Conditions.Count == 0)
					{
						State.Messages.Add(MessageId.SwitchNoCaseDef, Switch.Code);
						return false;
					}
				}
			}

			Comm.CommIndex = Commands.Count;
			Comm.Code = Code;
            Comm.ChkUnreachable = ChkUnreachable;
			Commands.Add(Comm);
            return true;
        }

        public bool AddExpressionCommand(PString Line, ExpressionNode Node, bool ChkUnreachable = true)
        {
            return AddCommand(Line, CreateExpressionCommand(Node), ChkUnreachable);
        }

		public EmptyCommand CreateEmptyCommand()
		{
			var Ret = new EmptyCommand(this);
			State.Arch.OnNewContainer(Ret);
			return Ret;
		}

		public ExpressionCommand CreateExpressionCommand(ExpressionNode Node)
		{
			var Ret = new ExpressionCommand(this, Node);
			State.Arch.OnNewContainer(Ret);
			return Ret;
		}

		public LabelCommand CreateLabelCommand(int Label)
		{
			var Ret = new LabelCommand(this, Label);
			State.Arch.OnNewContainer(Ret);
			return Ret;
		}

		public GotoCommand CreateGotoCommand(PString Label)
		{
			var Ret = new GotoCommand(this, Label);
			State.Arch.OnNewContainer(Ret);
			return Ret;
		}

		public BreakCommand CreateBreakCommand(int Label)
		{
			var Ret = new BreakCommand(this, Label);
			State.Arch.OnNewContainer(Ret);
			return Ret;
		}

		public ContinueCommand CreateContinueCommand(int Label)
		{
			var Ret = new ContinueCommand(this, Label);
			State.Arch.OnNewContainer(Ret);
			return Ret;
		}

		public RetCommand CreateRetCommand(int Label, bool Chk)
		{
			var Ret = new RetCommand(this, Label, Chk);
			State.Arch.OnNewContainer(Ret);
			return Ret;
		}

		public LoopCommand CreateLoopCommand()
		{
			var Ret = new LoopCommand(this);
			State.Arch.OnNewContainer(Ret);
			return Ret;
		}

		public WhileCommand CreateWhileCommand(ExpressionNode Condition, bool DoWhile = false)
		{
			var Ret = new WhileCommand(this, Condition, DoWhile);
			State.Arch.OnNewContainer(Ret);
			return Ret;
		}

		public ForCommand CreateForCommand(ExpressionNode Condition, ExpressionNode Loop, ExpressionNode Init)
		{
			var Ret = new ForCommand(this, Condition, Loop, Init);
			State.Arch.OnNewContainer(Ret);
			return Ret;
		}

		public ConditionCommand CreateConditionCommand()
		{
			var Ret = new ConditionCommand(this);
			State.Arch.OnNewContainer(Ret);
			return Ret;
		}

		public AsmCommand CreateAsmCommand()
		{
			var Ret = new AsmCommand(this);
			State.Arch.OnNewContainer(Ret);
			return Ret;
		}

		public SwitchCommand CreateSwitchCommand()
		{
			var Ret = new SwitchCommand(this);
			State.Arch.OnNewContainer(Ret);
			return Ret;
		}

		public Command LastCommand
		{
			get
			{
				var CommCount = Commands.Count;
				if (CommCount > 0) return Commands[CommCount - 1];
				else return null;
			}
		}

		public bool RecognizeCommand(PString Code, int LineIndex)
		{
			var FLine = Code.Copy();
			var Line = Code.Copy();
			var Word = Line.Word();

			return RecognizeCommand(FLine, Word, Line, LineIndex);
		}

		public bool RecognizeCommand(PString Code, PString Word, PString Line, int LineIndex)
		{
			var Rec = State.Language.CommRecognizer;
			var Res = Rec.Recognize(Code, Word, Line, LineIndex, this);
			if (Res == CommRecognizerRes.Succeeded)
				return true;
			else if (Res == CommRecognizerRes.Failed)
				return false;
			else if (Res == CommRecognizerRes.UnknownOp)
			{
				State.Messages.Add(MessageId.NotExpected, Code);
				return false;
			}
			else
				throw new Exception("ERROR");
        }

        public bool CopyRetVal(PString Code)
        {
            var FuncScope = this.FuncScope;
            if (FuncScope.TmpRetVal != null)
            {
                var PlugIn = GetPlugIn();
                if (!PlugIn.Begin()) return false;
                var SrcVar = PlugIn.NewNode(new IdExpressionNode(FuncScope.TmpRetVal, Code));
                var DstVar = PlugIn.NewNode(new IdExpressionNode(FuncScope.RetVar, Code));
                if (SrcVar == null || DstVar == null) return false;

                var AssignmentCh = new List<ExpressionNode>() { DstVar, SrcVar };
                var Assignment = PlugIn.NewNode(new OpExpressionNode(Operator.Assignment, AssignmentCh, Code));
                if (Assignment == null) return false;

                if ((Assignment = PlugIn.End(Assignment)) == null) return false;
                if (!AddExpressionCommand(Code, Assignment)) return false;
            }

            return true;
        }

		public static bool NeedReturnVal(Type RetType)
		{
			if (RetType is VoidType) return false;
            if (RetType is NamedFuncRetType) return false;

			if (RetType is TupleType)
			{
				var Tuple = RetType as TupleType;
				if (Tuple.Named) return false;
			}

			return true;
		}

        public virtual bool ProcessCode()
        {
			return State.Language.CodeProcessor.Process(this);
        }

		public virtual void GetAsmCode(Compiler Compiler)
        {
			Compiler.Container = this;
            foreach (var e in Commands)
				if (!e.Unreachable) e.GetAsmCode(Compiler);
        }

		public override bool DeclareVariables(List<Variable> Variables, GetIdMode IdMode = GetIdMode.Everywhere)
		{
			var Ret = base.DeclareVariables(Variables, IdMode);
			foreach (var e in Variables)
				if (e != null && e.InitValue != null && !AddExpressionCommand(e.InitString, e.InitValue))
					Ret = false;

			return Ret;
		}
    }

	public enum GetAsmCodeMode
	{
		Code,
		Data,
	}

	public abstract class FuncScopeNode : CodeScopeNode
	{
		public PString Name;
		public FunctionType Type;
		public string AsmCode;

		public Dictionary<string, LabelCommand> Labels = new Dictionary<string, LabelCommand>();
		public List<GotoCommand> Gotos = new List<GotoCommand>();

		public LocalVariable Self;
		public List<LocalVariable> Params;

		public int RetLabel;
		public LocalVariable RetVar;
		public LocalVariable TmpRetVal;
		public List<Identifier> RetMembers;

		public abstract void CreateAsmCode();

		public FuncScopeNode(IdContainer Parent, PString Name, FunctionType Type, bool IsStatic, PString[] Source)
			: base(Parent, Source)
		{
			this.Type = Type;
			this.Name = Name;

			RetLabel = State.NextLabelIndex;
			RetVar = new LocalVariable(this, new PString("__ret_value_"), Type.RetType);
			RetVar.RetVar = true;

			Params = new List<LocalVariable>();
			foreach (var e in Type.Params)
			{
				var Var = new LocalVariable(this, e.Name, e.Type);
				Var.PreAssigned = true;
				Var.IsParameter = true;
				Params.Add(Var);
			}

			if (Parent is StructuredTypeScope && !IsStatic)
			{
				var StructuredParent = Parent as StructuredTypeScope;
				var SelfType = (Type)StructuredParent.Type;
				if (SelfType is ValueType) SelfType = SelfType.CreateRefType();

				Self = CreateVariable(new PString("this"), SelfType) as LocalVariable;
				Self.ReadOnly = true;
				Self.PreAssigned = true;
				Params.Add(Self);
			}

			if (RetVar.Type is TupleType)
			{
				var Tuple = RetVar.Type as TupleType;
				if (Tuple.Named)
				{
					RetMembers = new List<Identifier>();
					foreach (MemberVariable e in Tuple.Members)
						RetMembers.Add(new PackedMemberId(this, e.Name, e.Type, RetVar, e));
				}
			}
			else if (RetVar.Type is NamedFuncRetType)
			{
				var Named = RetVar.Type as NamedFuncRetType;
				var RType = Named.Child;

				TmpRetVal = new LocalVariable(this, Named.Name, RType);
				State.Arch.OnNewIdentifier(TmpRetVal);
			}
		}

		public bool ProcessLabels()
		{
			var RetValue = true;
			foreach (var Goto in Gotos)
			{
				var LblCmd = GetLabelCmd(Goto.LabelName.String);
				if (LblCmd == null)
				{
					State.Messages.Add(MessageId.UnknownLabel, Goto.LabelName);
					RetValue = false;
				}
				else
				{
					Goto.JumpTo = LblCmd;
					Goto.Label = LblCmd.Label;
				}
			}

			return RetValue;
		}

		public LabelCommand GetLabelCmd(string Name)
		{
			foreach (var e in Labels.Keys)
				if (e == Name) return Labels[e];

			return null;
		}

		public override T GetIdRec<T>(PString Name, GetIdMode Mode = GetIdMode.Everywhere,
			bool SearchedInBasicTypes = false)
		{
			if (Name.String == "this" && Self != null)
				return Self as T;

			if (RetMembers != null)
			{
				foreach (var e in RetMembers)
					if (e.Name.String == Name.String && e is T)
						return e as T;
			}

			if (TmpRetVal != null && TmpRetVal is T && TmpRetVal.Name.String == Name.String)
				return TmpRetVal as T;

			foreach (var e in Params)
				if (e.Name.String == Name.String && e is T)
					return e as T;

			return base.GetIdRec<T>(Name, Mode, SearchedInBasicTypes);
		}

		public string GetFunctionCode()
		{
			if (AsmCode == null)
				CreateAsmCode();

			return AsmCode;
		}

		public bool ChkRetMembers(CodeChkData Data, PString Command = null)
		{
			if (RetMembers == null) return true;

			var RetValue = true;
			foreach (var e in RetMembers)
				if (!Data.IsAssigned(e))
				{
					if (Command == null) State.Messages.Add(MessageId.UnassignedVar, e.Name);
					else State.Messages.Add(MessageId.UnassignedVar2, Command, e.Name.String);
					RetValue = false;
				}

			return RetValue;
		}

		public override bool ProcessCode()
		{
			var Ret = base.ProcessCode();
			if (!ProcessLabels()) Ret = false;

			if (TmpRetVal != null && !CopyRetVal(Name))
				Ret = false;

			var RetLComm = CreateLabelCommand(RetLabel);
			if (!AddCommand(null, RetLComm, false)) Ret = false;

			if (Ret)
			{
				InitCodeChk();
				var Data = new CodeChkData();
				ChkCodeRec(Data, ref Ret);

				if (!RetLComm.Unreachable)
				{
					if (NeedReturnVal(Type.RetType))
					{
						State.Messages.Add(MessageId.NotAllPathReturn, Name);
						Ret = false;
					}

					if (!ChkRetMembers(Data))
						Ret = false;
				}

				RetLComm.Unreachable = false;
				if (!FinishCodeChk()) Ret = false;
			}

			return Ret;
		}
	}

}

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