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.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)

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