Today is a very exciting day for me. The day I start working full-time for Unity!

This is great for many reasons.

First of all I'll be working on stuff very close to my heart: language and tools development. My #1 job at Unity is to make sure UnityScript remains the best language for game development inside Unity3D. A lot of love will go into friendlier error messages, long awaited features such as closures and generics, more reliability and great IDE support.

Boo users will like to know that UnityScript is written in Boo and it's based on the Boo compilation framework. Improving UnityScript means improving Boo.

And after 15 years in the computer industry I'm finally working very close to what got me into it in the first place: gaming. Believe it or not I had plans of becoming a journalist in my youth but SEGA saved me!

Back to work now, I have a game to write. :D

Boo 0.9.2 is here!

| 1 Comment

You read it right and it was about time!

Boo 0.9.2 is mostly a maintainance release, yet it introduces a few new features worth highlighting:

* Unsafe code support including pointer manipulation for richer interoperability with native code [BOO-1202]

    unsafe ptr as long = astruct:
        ptr = 0
        ++ptr

* Generic array/matrix constructors [BOO-1203]

    a = array[of int](3) #create an array of 3 ints
    m = matrix[of int](3, 3) #create a 3x3 int matrix

* Literal regular expression options [BOO-1237]

    /boo/i.IsMatch("BOO") #case-insensitive match

* Boo now runs on medium-trust environments [BOO-1215] (such as Mosso ASP.NET platform)

On top of the usual bug fixes, this release significantly improves generated IL, resulting in up to 40% leaner assemblies among other performance improvements.

Contributed to this release: Cedric Vivier, Daniel Grunwald, Dmitry Malyshev, Greg Nagel, Joao Braganca, Martinho Fernandes, Paul Lange and yours truly.

As usual you can download it from here. The change log is here.

Have fun!

After a long wait boo is finally available as a programming language category on Source Forge.

Now go and improve the categorization of your boo projects.

Motivations:

  • You want to decouple the different components of a system;
  • You want to minimize the scope of their dependencies;
  • You are developing a system that needs to support dynamic reconfigurability;
  • You want a simple programming model that stirs you in the direction of better dependency management.

Environment Based Programming* is a design pattern founded on a very simple principle:

  • Code executes in an environment that provides it with all its needs.

This principle can be completely captured in C# with the following API:

    namespace EnvironmentBasedProgramming
    {
        public delegate void Code();
    
        public interface IEnvironment
        {
            Need Provide<Need>();
        }
    
        public static class Environments
        {   
            /// <summary>
            /// Executes code in a given environment.
            /// </summary>
            public static void With(IEnvironment environment, Code code);
        }
    
        /// <summary>
        /// Used by code to fulfill its needs.
        /// </summary>
        public static class My<Need>
        {
            public static Need Instance { get; }
        }
    }

To make it all concrete I'll use Martin Fowler's naive example specially for the contrast with the dependency management approaches he documents in his article. The MovieLister component provides a list of movies directed by a particular director. In order to fulfill its contract it needs the list of all known movies, something that a MovieFinder service would provide:

    interface IMovieFinder
    {
        IEnumerable<Movie> FindAll();
    }
    
    class MovieLister
    {
        public IEnumerable<Movie> MoviesDirectedBy(string directorName)
        {
            var movies = My<IMovieFinder>.Instance.FindAll();
            foreach (var movie in movies)
                if (movie.Director == directorName)
                    yield return movie;
        }
    }

Notice how the code express its needs using the My idiom.

MovieLister can now be executed in a suitable environment using the With primitive:

    Environments.With(environment, delegate
    {
        foreach (var movie in new MovieLister().MoviesDirectedBy("Terry Jones"))
            Console.WriteLine(movie.Title);
    });

A suitable environment in this case would have to deliver a valid IMoveFinder instance upon request. The following implementation should suffice:

    class DummyMovieFinder : IMovieFinder
    {   
        public IEnumerable<Movie> FindAll()
        {
            yield return new Movie {Director = "Terry Jones", Title = "Erik The Viking"};
            yield return new Movie {Director = "Terry Gilliam", Title = "Fear and Loathing in Las Vegas"};
        }
    }

The missing piece in the puzzle is the final EBP building block - ClosedEnvironment:

    public class ClosedEnvironment : IEnvironment
    {
        private readonly object[] _bindings;

        public ClosedEnvironment(params object[] bindings)
        {
            _bindings = bindings;
        }
        
        public T Provide<T>()
        {
            foreach (var binding in _bindings)
                if (binding is T)
                    return (T) binding;
            return default(T);
        }
    }

Which allows the environment for the example to be defined as:

    var environment = new ClosedEnvironment(new DummyMovieFinder());

Component activation and lifetime are not aspects dealt directly with by EBP and are better treated as different environment strategies (one can easily imagine an environment that automatically instantiates components based on naming conventions or metadata).

The complete listings follow.

The example:

    namespace EnvironmentBasedProgramming.NaiveExample
    {
        using System;
        using System.Collections.Generic;
    
        class Movie
        {
            public string Title { get; set; }
            public string Director { get; set; }
        }
    
        interface IMovieFinder
        {
            IEnumerable<Movie> FindAll();
        }
    
        class MovieLister
        {
            public IEnumerable<Movie> MoviesDirectedBy(string directorName)
            {
                var movies = My<IMovieFinder>.Instance.FindAll();
                foreach (var movie in movies)
                    if (movie.Director == directorName)
                        yield return movie;
            }
        }
    
        class Program
        {
            static void Main(string[] args)
            {
                var environment = new ClosedEnvironment(new DummyMovieFinder());
                Environments.With(environment, delegate
                {
                    PrintMoviesDirectedBy("Terry Jones");
                });
            }
    
            private static void PrintMoviesDirectedBy(string directorName)
            {
                foreach (var movie in new MovieLister().MoviesDirectedBy(directorName))
                    Console.WriteLine(movie.Title);
            }
    
            class DummyMovieFinder : IMovieFinder
            {   
                public IEnumerable<Movie> FindAll()
                {
                    yield return new Movie {Director = "Terry Jones", Title = "Erik The Viking"};
                    yield return new Movie {Director = "Terry Gilliam", Title = "Fear and Loathing in Las Vegas"};
                }
            }
        }
    }

The minimalist EBP framework written for this article:

    namespace EnvironmentBasedProgramming
    {
        using System;
    
        public delegate void Code();
    
        public interface IEnvironment
        {
            Need Provide<Need>();
        }
    
        public static class Environments
        {   
            /// <summary>
            /// Executes code in a given environment.
            /// </summary>
            public static void With(IEnvironment environment, Code code)
            {
                IEnvironment previous = _environment;
                _environment = environment;
                try
                {
                    code();
                }
                finally
                {
                    _environment = previous;
                }
            }
    
            private static IEnvironment _environment;
    
            internal static IEnvironment Current
            {
                get { return _environment; }
            }
        }
    
        /// <summary>
        /// Used by code to fulfill its needs.
        /// </summary>
        public static class My<Need>
        {
            public static Need Instance
            {
                get
                {
                    var current = Environments.Current;
                    if (current == null)
                        throw new InvalidOperationException("No environment to provide '" + typeof(Need) + "'.");
                    return current.Provide<Need>();
                }
            }
        }
    
        public class ClosedEnvironment : IEnvironment
        {
            private readonly object[] _bindings;
    
            public ClosedEnvironment(params object[] bindings)
            {
                _bindings = bindings;
            }
            
            public T Provide<T>()
            {
                foreach (var binding in _bindings)
                    if (binding is T)
                        return (T) binding;
                return default(T);
            }
        }
    }

In a future article I'll explore environment chaining and convention based service discovery. Thoughts?

* or to use a name more to the style of Martin Fowler: Dynamically Scoped Service Locator (not to be confused with Dynamic Service Locator)

...
What do I need to do to get it to work on Windows?
I've got mono + eclipse + rcp + monolipse installed. Eclipse's DMONO_HOME variable points the right place.
I've got Boo 0.9 in a folder, but I'm not sure if it's the right place or if I need to do anything else. ...
What's missing?
--Søren, February 12, 2009 06:21 AM

Thanks for the question. The eclipse plugins expects the boo assemblies to be in the mono GAC and it also expects to find the boo compiler under $MONO_HOME/lib/boo, something that can be easily arranged by running nant in the boo source folder (yes, windows users need a source distro or a svn checkout for now):

$ nant install -D:mono.prefix=c:/dotnet/mono-2.2

Enjoy!

Very cool man.

BTW what's the name of the song in the background? :)

--Andrés G. Aragoneses, February 6, 2009 09:52 PM

Thanks, Andrés. The song is Take Five. I love it.

Awesome! You've just made me reinstall Eclipse! ;)

The url in the post did not work for me, have had to use http instead of https.

Another more disturbing issue, it insists for mono in /usr/local/bin probably /usr/bin would be a safer default, I tried to change it in preferences but it doesn't seem to change anything.. I think I've sent you a patch about it looong time ago but cannot find it anymore ;(

Also maybe you should change the repository name to 'Monolipse' instead of 'file:/Users/rodrigob/projects/monolipse/update-site/ - artifacts' ;)

--Cedric, February 7, 2009 05:33 AM

Thanks, Cedric. I prefer /usr/local for my mono version and /usr for the system's mono version. Configuration via user interface is not yet implemented and I couldn't find the patch here, I hope that now that it's out there more people will contribute and this project might even realize its full potential. For now you need to start eclipse passing the MONO_HOME system property like this:

    eclipse -data /path/to/workspace -vmargs -DMONO_HOME=/usr

The same will work on windows.

Enjoy!

Experience boojay with monolipse

| 5 Comments

Summing up:

Enjoy!


Let's consider the simple issue of defining a thread local variable. In .net this can be achieved rather efficiently through a static field annotated with the System.ThreadStatic attribute:

    class WithPerThreadState:
        [System.ThreadStatic] static _state as PerThreadState

The problem with that is that there's redundancy (we have to say static twice) and there's noise (square brackets). If we're doing this more than once in a code base it would be good to avoid repeating ourselves. We should be able to hide the unnecessary implementation details of a thread static variable behind a macro and more succinctly say:

    class WithPerThreadState:
        ThreadStatic _state as PerThreadState

And now we are:

    macro ThreadStatic:
        case [| ThreadStatic $name as $type |]:
            yield [|
                [System.ThreadStatic] static $name as $type
            |]

This example makes use of some of the most important improvements to macro expression in boo 0.9. Let's dissect it block by block:

    macro ThreadStatic:
        ...

Friendly macro definition using the macro macro. Yes, that's correct. For the boo compiler a macro is simply a type that implements a specific interface and optionally adheres to the "Macro" suffix naming convention. The macro macro generates the required boilerplate.

    ...
        case [| ThreadStatic $name as $type |]:
            ...

The optional case clauses of a macro definition pattern match against the macro application and execute the body of the first matching case. The particular pattern we see here with the [| |] brackets is a code pattern. Pattern matching is a whole new feature in itself, for now it should suffice to say that $variableName inside a code pattern captures the code appearing at that position in the variable variableName. The case will only succeed if the macro was applied with a single as expression as its argument in which case the left operand of the as expression is made available through the name variable and its right operand through the type variable.

        ...
            yield [|
                [System.ThreadStatic] static $name as $type
            |]

yield means macros are generators. They can produce many nodes of different types. In this particular case the macro is producing a single field declaration node expressed with a code literal*. The $ inside a code literal is the splice operator: its operand is evaluated and the resulting node inserted into the code tree.

The usual modifiers can be used to control the visibility of members generated by the macro:

        public ThreadStatic State as PerThreadState

Modifiers and attributes are automatically propagated to every node yielded by the macro. **

There's much more to be said on these new capabilities but I'll leave that for another day. For now these test cases might help.

Happy meta hacking!

* I've referred to these [| |] entities as code patterns before. That's correct. Code patterns are code literals used in a pattern matching context such as the case in the ThreadStatic example.

** macros can also control how modifiers and attributes are handled by modifying the code tree directly.

Recent Comments

  • Fernando Zapata: Looks great :), any progress on this front? read more
  • Fernando Zapata: Looks good Rodrigo :). I'm looking forward to give it read more
  • col000r: yay! some unityscript love! read more
  • Daniel: Blz Rodrigo!?! Se não me engano vc é brasileiro, então read more
  • Andrew: Congrats, Rodrigo! read more
  • Miguel de Icaza: Congratulations Rodrigo! These are great news! Any chance you could read more
  • Chris: Congrats! I always wanted to be in the gaming industry. read more
  • Nicholas Blumhardt: Great news Rodrigo! ...for both yourself and the Boo fans read more
  • Sandy: Great stuff, congratulations! Unity's a pretty great community member, so read more
  • Jayro: Bamba... Good news! Like they say in Timbuktu..."Mazaltov"! All the read more

Find recent content on the main index or look in the archives to find all content.