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 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
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.IO;

namespace Bird
{
	public abstract class CondBranch
	{
	}

	public class JumpCodeBranch : CondBranch
	{
		public int Label;

		public JumpCodeBranch(int Label)
		{
			this.Label = Label;
		}
	}

	public class CodeCondBranch : CondBranch
	{
		public Action<CodeGenerator> GetCode;

		public CodeCondBranch(Action<CodeGenerator> GetCode)
		{
			this.GetCode = GetCode;
		}
	}

	public abstract class Instruction
	{
		public bool Skip = false;
	}

	public class LabelInstruction : Instruction
	{
		public int Label;
		public string Name;

		public LabelInstruction(int Label, string Name = null)
		{
			this.Label = Label;
			this.Name = Name;
		}

		public string LabelName
		{
			get { return Name == null ? "_" + Label : Name;	}
		}
	}

	public class JumpInstruction : Instruction
	{
		public int Label;
		public string Name;

		public JumpInstruction(int Label, string Name = null)
		{
			this.Label = Label;
			this.Name = Name;
		}

		public string LabelName
		{
			get { return Name == null ? "_" + Label : Name; }
		}
	}

	public sealed class ReplaceableJumpInstruction : JumpInstruction
	{
		public ReplaceableJumpInstruction(int Label)
			: base(Label)
		{
		}
	}

	public class StrInstruction : Instruction
	{
		public string Instruction;

		public StrInstruction(string Instruction)
		{
			this.Instruction = Instruction;
		}
	}

	public class InstructionContainer
	{
		public List<Instruction> Instructions = new List<Instruction>();
		public Dictionary<int, int> LabelPositions;

		public InstructionContainer()
		{
		}

		public void Add(Instruction Instruction)
		{
			if (Instruction is LabelInstruction)
			{
				var LblIns = Instruction as LabelInstruction;
				if (LabelPositions == null) LabelPositions = new Dictionary<int, int>();
				LabelPositions.Add(LblIns.Label, Instructions.Count);
			}

			Instructions.Add(Instruction);
		}

		public void Add(InstructionContainer InsContainer)
		{
			var Count = Instructions.Count;
			Instructions.AddRange(InsContainer.Instructions);

			if (InsContainer.LabelPositions != null)
			{
				foreach (var e in InsContainer.LabelPositions)
					LabelPositions.Add(e.Key, e.Value + Count);
			}
		}

		public void Add(string Str)
		{
			if (Str.Trim() == "mov dword[ebp - 12], _GetInt") { ; }
			Instructions.Add(new StrInstruction(Str));
		}

		public void Jump(int Label)
		{
			if (Label < 0) throw new ArgumentException(null, "Label");
			Instructions.Add(new ReplaceableJumpInstruction(Label));
		}

		public void Jump(string Label)
		{
			Instructions.Add(new JumpInstruction(-1, Label));
		}

		public void Label(string Label)
		{
			Instructions.Add(new LabelInstruction(-1, Label));
		}

		public void Label(int Label)
		{
			if (LabelPositions == null) LabelPositions = new Dictionary<int, int>();
			LabelPositions.Add(Label, Instructions.Count);

			var Ins = new LabelInstruction(Label);
			Instructions.Add(Ins);
		}

		public void Reset()
		{
			Instructions = new List<Instruction>();
			LabelPositions = new Dictionary<int, int>();
		}

		public void Insert(int Index, InstructionContainer InsContainer)
		{
			var P = InsContainer.Instructions.Count - 1;
			if (LabelPositions != null)
			{
				foreach (var e in LabelPositions.Keys.ToArray())
					if (LabelPositions[e] >= Index) LabelPositions[e] += P;
			}

			Instructions.InsertRange(Index, InsContainer.Instructions);
			if (InsContainer.LabelPositions != null)
			{
				foreach (var e in InsContainer.LabelPositions)
					LabelPositions.Add(e.Key, e.Value + Index);
			}
		}

		public int JumpsTo(int Label)
		{
			var InsIndex = LabelPositions[Label];
			for (var i = InsIndex; i < Instructions.Count; i++)
			{
				var Ins = Instructions[i];
				if (Ins is JumpInstruction)
				{
					var JumpIns = Ins as JumpInstruction;
					return JumpsTo(JumpIns.Label);
				}
				else if (Ins is LabelInstruction)
				{
					var LabelIns = Ins as LabelInstruction;
					Label = LabelIns.Label;
					continue;
				}

				break;
			}

			return Label;
		}

		public string EncodeToText(InstructionEncoder Encoder)
		{
			var StrBuilder = new StringBuilder();
			for (var i = 0; i < Instructions.Count; i++)
			{
				var Ins = Instructions[i];
				if (!Ins.Skip) 
					StrBuilder.Append(Encoder.EncodeToText(Ins));
			}

			return StrBuilder.ToString();
		}
	}

	public abstract class InstructionEncoder
	{
		public abstract string EncodeToText(Instruction Instruction);
	}

	public abstract class CodeGenerator
	{
		public CompilerState State;
		public IdContainer Container;

		public InstructionContainer InsContainer;
		public Dictionary<int, InstructionContainer> ReplaceJumps;

		public abstract void EmitExpression(ExpressionNode Node);
		public abstract void EmitCondition(ExpressionNode Node, CondBranch Then, CondBranch Else, int NextLabel = -1);
		public abstract void EmitCondition(ExpressionNode Node, int Then, int Else, bool ElseAfterCondition);

		public abstract void Align(int Align);
		public abstract void DeclareFile(string FileName);
		public abstract void DeclareLabelPtr(string Label);
		public abstract void DeclareLabelPtr(int Label);
		public abstract void DeclareUnknownBytes(int Count);
		public abstract void DeclareZeroBytes(int Count);
		public abstract void Declare(Identifier Type, ConstValue Data);
		public abstract void Store(string String, bool WideString = true, bool ZeroTerminated = true);

		public CodeGenerator(CompilerState State)
		{
			this.State = State;
			this.InsContainer = new InstructionContainer();
		}

		public void DeclareNull()
		{
			DeclareZeroBytes(State.Arch.RegSize);
		}

		public void Declare(ConstExpressionNode Value)
		{
			Declare(Value.Type.RealId as Type, Value.Value);
		}

		public void Declare(bool Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Boolean, new BooleanValue(Value));
		}

		public void Declare(string Value)
		{
			Declare(Container.GlobalContainer.CommonIds.String, new StringValue(Value));
		}

		public void Declare(float Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Single, new DoubleValue(Value));
		}

		public void Declare(double Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Double, new DoubleValue(Value));
		}

		public void Declare(long Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Int64, new IntegerValue(Value));
		}

		public void Declare(ulong Value)
		{
			Declare(Container.GlobalContainer.CommonIds.UInt64, new IntegerValue(Value));
		}

		public void Declare(int Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Int32, new IntegerValue(Value));
		}

		public void Declare(uint Value)
		{
			Declare(Container.GlobalContainer.CommonIds.UInt32, new IntegerValue(Value));
		}

		public void Declare(short Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Int32, new IntegerValue(Value));
		}

		public void Declare(ushort Value)
		{
			Declare(Container.GlobalContainer.CommonIds.UInt16, new IntegerValue(Value));
		}

		public void Declare(sbyte Value)
		{
			Declare(Container.GlobalContainer.CommonIds.SByte, new IntegerValue(Value));
		}

		public void Declare(byte Value)
		{
			Declare(Container.GlobalContainer.CommonIds.Byte, new IntegerValue(Value));
		}

		public InstructionContainer ExecuteOnTempInsContainer(Action Action)
		{
			var InsContainer = new InstructionContainer();
			var OldInsContainer = this.InsContainer;
			this.InsContainer = InsContainer;

			Action();
			this.InsContainer = OldInsContainer;
			return InsContainer;
		}

		public InstructionContainer SetJumpReplacing(int Label, Action Action)
		{
			var InsContainer = ExecuteOnTempInsContainer(Action);
			SetJumpReplacing(Label, InsContainer);
			return InsContainer;
		}

		public void SetJumpReplacing(int Label, InstructionContainer InsContainer)
		{
			if (ReplaceJumps == null) ReplaceJumps = new Dictionary<int, InstructionContainer>();
			ReplaceJumps.Add(Label, InsContainer);
		}

		public virtual void SkipUnnecessaryJumps()
		{
			for (var i = 0; i < InsContainer.Instructions.Count; i++)
				InsContainer.Instructions[i].Skip = false;

			for (var i = 0; i < InsContainer.Instructions.Count; i++)
			{
				var JumpIns = InsContainer.Instructions[i] as JumpInstruction;
				if (JumpIns != null && !JumpIns.Skip)
				{
					var SkipInstructions = JumpIns is ReplaceableJumpInstruction;
					JumpIns.Label = InsContainer.JumpsTo(JumpIns.Label);

					for (var SkipPos = i + 1; SkipPos < InsContainer.Instructions.Count; SkipPos++)
					{
						var SIns = InsContainer.Instructions[SkipPos];
						if (SIns is LabelInstruction)
						{
							var SLabelIns = SIns as LabelInstruction;
							if (SLabelIns.Label == JumpIns.Label)
							{
								JumpIns.Skip = true;
								break;
							}
						}
						else if (SIns is JumpInstruction)
						{
							if (SkipInstructions) SIns.Skip = true;
							if (SIns is ReplaceableJumpInstruction && !SkipInstructions)
								break;
						}
						else
						{
							break;
						}
					}
				}
			}
		}

		public virtual void SkipUnnecessaryLabels()
		{
			var FS = Container.FunctionScope;
			for (var i = 0; i < InsContainer.Instructions.Count; i++)
			{
				var Ins = InsContainer.Instructions[i] as LabelInstruction;
				if (Ins != null && !FS.NeverSkippedLabels.Contains(Ins.Label))
					Ins.Skip = true;
			}

			for (var i = 0; i < InsContainer.Instructions.Count; i++)
			{
				var JumpIns = InsContainer.Instructions[i] as JumpInstruction;
				if (JumpIns != null && !JumpIns.Skip)
				{
					var JumpsTo = InsContainer.LabelPositions[JumpIns.Label];
					InsContainer.Instructions[JumpsTo].Skip = false;
				}
			}
		}

		public virtual void ProcessJumps()
		{
			SkipUnnecessaryJumps();

			if (ReplaceJumps != null)
			{
				var Instructions = InsContainer.Instructions;
				var Count = 0;
				Reset();

				for (var i = 0; i < Instructions.Count; i++)
				{
					var Ins = Instructions[i];
					if (!Ins.Skip)
					{
						var JIns = Ins as ReplaceableJumpInstruction;
						if (JIns != null && ReplaceJumps.ContainsKey(JIns.Label))
						{
							InsContainer.Add(ReplaceJumps[JIns.Label]);
							Count++;
							continue;
						}

						InsContainer.Add(Ins);
					}
				}

				if (Count > 0) ProcessJumps();
			}
		}

		public virtual void Optimize()
		{
			ProcessJumps();
			SkipUnnecessaryLabels();
		}

		public void Reset()
		{
			InsContainer.Reset();
		}
	}

	public interface IArchitecture
	{
		int RegSize { get; }
		int MaxStructPow2Size { get; }

		bool ProcessIdentifier(Identifier Id);
		bool ProcessFunction(Function Func);
		bool CreateAssembly(Function Func);
		void GetAssembly(CodeGenerator CG, Function Function);
		bool Compile(CompilerState State, CodeFile[] CodeFiles);


		bool IsSimpleCompareNode(ExpressionNode Node);
		CondBranch[] GetBranches(GlobalContainer Global, Command Then,
			Command Else, ref ExpressionNode Condition);
	}
}

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.141223.1 | Last Updated 1 Jan 2013
Article Copyright 2011 by Dávid Kocsis
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid