Click here to Skip to main content
15,885,546 members
Articles / Programming Languages / ASM

Bird Programming Language: Part 3

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

namespace Bird
{
	public class WithScopeNode : CodeScopeNode
	{
		public Dictionary<Identifier, PackedMemberId> Ids = new Dictionary<Identifier, PackedMemberId>();
		public ExpressionNode WithNode;

		public WithScopeNode(IdContainer Parent, CodeString Code, ExpressionNode Node)
			: base(Parent, Code)
		{
			WithNode = Node;
		}

		public override bool GetContainerId(string Name, List<IdentifierFound> Out, Predicate<Identifier> Func = null)
		{
			var RetValue = base.GetContainerId(Name, Out, Func);
			var Type = WithNode.Type as StructuredType;

			foreach (var e in Identifiers.SearchMember(this, Type, Name, Func))
			{
				PackedMemberId Id;
				if (!Ids.TryGetValue(e.Identifier, out Id))
				{
					Id = new PackedMemberId(this, new CodeString(),
						e.Identifier.TypeOfSelf, WithNode, e.Identifier);

					Ids.Add(e.Identifier, Id);
				}

				if (Func(Id))
				{
					Out.Add(new IdentifierFound(this, Id));
					RetValue = true;
				}
			}

			return RetValue;
		}
	}
	
	public class CodeScopeNode : ScopeNode
	{
		public bool DisableLastChild;
		public IFinishableCommRecognizer LastCommRecognizer;
		public IdContainer LastAddedContainer;
		public CheckingMode CheckingMode;

		public override bool IsAlreadyDefined(string Name, Predicate<Identifier> Func = null)
		{
			Predicate<IdContainer> ContainerFunc = x =>
				Identifiers.Search(x, x.IdentifierList, Name, Func).Count == 0;

			return !TrueForAllParent<IdContainer>(ContainerFunc, FunctionScope.Parent);
		}

		public bool AddFinishableCommand(IdContainer Container, IFinishableCommRecognizer Recognizer)
		{
			if (!FinishLastCommand())
				return false;

			LastAddedContainer = Container;
			LastCommRecognizer = Recognizer;

			DisableLastChild = false;
			Children.Add(Container);
			return true;
		}

		public bool AddCommand(IdContainer Container)
		{
			if (!FinishLastCommand())
				return false;

			DisableLastChild = false;
			Children.Add(Container);
			return true;
		}

		public bool FinishLastCommand()
		{
			if (LastCommRecognizer != null)
			{
				LastCommRecognizer.Finish(LastAddedContainer);
				MarkFinished();
			}

			return true;
		}

		public void MarkFinished()
		{
			LastAddedContainer = null;
			LastCommRecognizer = null;
		}

		public bool BasicConstructorCommands()
		{
			if (FunctionScope.ConstructorCall != null)
			{
				Children.Add(new Command(this, FunctionScope.ConstructorCall.Code, CommandType.Expression)
				{
					Expressions = new List<ExpressionNode>() { FunctionScope.ConstructorCall },
				});
			}

			return AssignInitValues();
		}

		public bool AssignInitValues()
		{
			var Plugin = GetPlugin();
			var RetValue = true;
			var Scope = FunctionScope.Parent;

			for (var i = 0; i < Scope.IdentifierList.Count; i++)
			{
				var Var = Scope.IdentifierList[i] as MemberVariable;
				if (Var != null)
				{
					if (!Var.InitString.IsValid) continue;

					Plugin.Reset();
					if (!Var.CalcValue(Plugin, BeginEndMode.Both, true))
						RetValue = false;

					Children.Add(new Command(this, Var.InitString, CommandType.Expression)
					{
						Expressions = new List<ExpressionNode>() { Var.InitValue }
					});
				}
			}

			return RetValue;
		}

		public override Variable OnCreateVariable(CodeString Name, Identifier Type, List<Modifier> Mods = null)
		{
			var Ret = CreateVariableHelper(Name, Type, Mods);
			if (Ret == null) Ret = new LocalVariable(this, Name, Type);
			return Ret;
		}

		public override PluginRoot GetPlugin()
		{
			return new PluginForCodeScope(this);
		}

		public CodeScopeNode(IdContainer Parent, CodeString Code)
			: base(Parent, Code)
		{
			var CodeScopeParent = GetParent<CodeScopeNode>(FunctionScope);
			if (CodeScopeParent != null) CheckingMode = CodeScopeParent.CheckingMode;
		}

		public bool Return(ExpressionNode Node, CodeString Code)
		{
			var FS = FunctionScope;
			var VoidType = GlobalContainer.CommonIds.Void;
			var RetType = FS.Type.RetType;

			if (Node != null)
			{
				var Func = FunctionScope.Function;
				if (Func is Constructor || Func is Destructor)
				{
					State.Messages.Add(MessageId.CannotReturn, Code);
					return false;
				}

				if (RetType.RealId is VoidType)
				{
					var TypeStrs = new[] { Node.Type.Name.ToString(), RetType.Name.ToString() };
					State.Messages.Add(MessageId.CannotConvert, Code, TypeStrs);
					return false;
				}

				Children.Add(new Command(this, Code, CommandType.Return)
				{
					Expressions = new List<ExpressionNode>() { Node },
					Label = FS.ReturnLabel,
				});
			}
			else
			{
				if (FS.NeedsReturnVal)
				{
					var TypeStrs = new[] { VoidType.Name.ToString(), RetType.Name.ToString() };
					State.Messages.Add(MessageId.CannotConvert, Code, TypeStrs);
					return false;
				}

				if (!CopyRetVal(Code)) 
					return false;

				Children.Add(new Command(this, Code, CommandType.Return)
				{
					Label = FS.ReturnLabel,
				});
			}

			return true;
		}

		public IdContainer LastChild
		{
			get
			{
				var CommCount = Children.Count;
				if (CommCount > 0 && !DisableLastChild)
					return Children[CommCount - 1];
				else return null;
			}
		}

		public bool RecognizeCommand(CodeString Code)
		{
			var Recs = State.Language.CommRecognizers;
            for (var i = 0; i < Recs.Length; i++)
			{
				var Res = Recs[i].Recognize(this, Code);
				if (Res != SimpleRecResult.Unknown)
					return Res != SimpleRecResult.Failed;
			}

			State.Messages.Add(MessageId.NotExpected, Code);
			return false;
		}

		public bool CopyRetVal(CodeString Code, Identifier Id)
		{
			var Plugin = GetPlugin();
			if (!Plugin.Begin()) return false;

			var Node = Plugin.NewNode(new IdExpressionNode(Id, Code));
			if (Node == null || Plugin.End(ref Node) == PluginResult.Failed) 
				return false;

			Children.Add(new Command(this, Code, CommandType.Return)
			{
				Expressions = new List<ExpressionNode>() { Node },
				Label = FunctionScope.ReturnLabel,
			});

			return true;
		}

		public bool CopyRetVal(CodeString Code, ExpressionNode SrcVar)
		{
			var Plugin = GetPlugin();
			var Node = SrcVar.Copy(Plugin, Code: Code);
			if (Node == null) return false;

			Children.Add(new Command(this, Code, CommandType.Return)
			{
				Expressions = new List<ExpressionNode>() { Node },
				Label = FunctionScope.ReturnLabel,
			});

			return true;
		}

		public bool CopyRetVal(CodeString Code)
		{
			var FS = FunctionScope;
			if (!(FS.Type.RetType is VoidType))
			{
				if (FS.Function is Constructor) return CopyRetVal(Code, FS.SelfVariable);
			}

			return true;
		}

		public virtual bool ProcessCode()
		{
			if (!State.Language.CodeProcessor.Process(this))
				return false;

			return FinishLastCommand();
		}

		public override void GetAssembly(CodeGenerator CG, GetAssemblyMode Mode = GetAssemblyMode.Code)
		{
			CG.Container = this;
			for (var i = 0; i < Children.Count; i++)
				Children[i].GetAssembly(CG);
		}

		public override bool DeclareVariables(Variable[] Variables, GetIdMode IdMode = GetIdMode.Everywhere)
		{
			var Ret = base.DeclareVariables(Variables, IdMode);
            for (var i = 0; i < Variables.Length; i++)
			{
				var e = Variables[i];
				if (e != null && e.InitValue != null)
				{
					Children.Add(new Command(this, e.InitString, CommandType.Expression)
					{
						Expressions = new List<ExpressionNode>() { e.InitValue },
					});
				}
			}

			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