Rodrigo B. de Oliveira


User Name: bamboo
Full Name: Rodrigo B. de Oliveira

Developer on the boo programming language and Bamboo.Prevalence.

Also known as Bamboo.

bamboozled
("digital breeding in a universe of natural selection")
Boo is now available as a Programming Language for SourceForge projects

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.

Environment Based Programming Design Pattern

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)

Experience boojay with monolipse followup II - Working on Windows
...
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!

Experience boojay with monolipse follow up

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

Summing up:

Enjoy!


Boo 0.9 - Introducing Type Member Macros

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.

Boo 0.9 is here!

Also known as the best boo release ever its chief weapons are:

  • Generator macros [BOO-1077] - macros are no longer limited to returning a single statement or block and instead are able to yield an indefinite number of nodes:
    macro printLines:
        for arg in printLines.Arguments:
            yield [| System.Console.WriteLine($arg) |]
        
    printLines "silly", "silly", "silly"

  • Nestable macros [BOO-1120] - macro definitions can be nested to allow for context sensitive keywords:
    macro given:
        macro when:
            yield [| print "given.when" |]

        yield

    macro alert:
        macro when:
            yield [| print "alert.when" |]
        yield
   
    given:
        when // given.when
    
    alert:
        when // alert.when

  • Type member macros [BOO-415] - macros can be used in class definition bodies:
    macro ThreadStatic:
        case [| ThreadStatic $name as $type |]:
            yield [|
                [System.ThreadStatic] static $name as $type
            |]
    
    class Environments:
        private ThreadStatic _current as Environment

  • Pattern matching [BOO-1106] - simple but powerful object pattern matching with the match/case/otherwise macros:
   import Boo.Lang.PatternMatching
    
    def Eval(e as Expression) as int:
        match e:
            case Const(Value):
                return Value

            case InfixExpression(Operator: "+", Left, Right):
                return Eval(Left) + Eval(Right)
                
            case InfixExpression(Operator: "-", Left, Right):
                return Eval(Left) - Eval(Right)

  • Support for generic extension methods [BOO-937] - LINQ style extension methods:
    import System.Linq.Enumerable from System.Core
    
    [Extension]
    def MakeString[of T](source as T*):
        return join(source, ", ")
    
    evenDoubles = range(10).Where({ i as int | i % 2 == 0 }).Select({ i as int | i * 2 })
    print evenDoubles.MakeString()

  • Generic parameter constraints [BOO-935] and Generic parameter type inference [BOO-1102]:
    def Using[of T(System.IDisposable)](value as T, block as System.Action[of T]):
        try:
            block(value)
        ensure:
            value.Dispose()
    
    Using(System.IO.File.OpenText("TFM.TXT"), { reader | print reader.ReadLine() })

  • Strict mode [BOO-1115] - strict mode changes a few compiler rules: default visibility for members is private, method parameter types and return types must be explicitly declared among other things
  • Asymmetric property accessor visibility [BOO-1094]
    class Song:
        Name as string:
            public get:
                return _name
            internal set:
                _name = value
        ...

    def ToHex(n as int):
        return "0x${n:x4}"
    
    print ToHex(42)

This release is brought to you by Avishay Lavie, Cedric Vivier, Daniel Grunwald, Marcus Griep and yours truly.

Full change log is here.

Download it from here and have fun!

boo, ometa and extensible parsing I

Meanwhile in a repository not far away:

    namespace metaboo

    import Boo.Lang.Compiler
    import Boo.Lang.Compiler.Ast
    import Boo.OMeta
    import Boo.OMeta.Parser

    syntax Units:
        atom = mass | super
        mass = (integer >> value as Expression, "kg") ^ [| Mass($value, "kg") |]

    syntax Ranges:
        atom = integer_range | super
        integer_range = (integer >> begin as Expression, DOT, DOT, integer >> end as Expression) ^ [| range($begin, $end) |]

    def parse(code as string):
        compiler = BooCompiler()
        compiler.Parameters.References.Add(System.Reflection.Assembly.GetExecutingAssembly())
        compiler.Parameters.Input.Add(IO.StringInput("code", code))
        compiler.Parameters.Pipeline = CompilerPipeline()
        compiler.Parameters.Pipeline.Add(BooParserStep())
        return compiler.Run()

    code = """
    import metaboo.Units
    import metaboo.Ranges

    a = 3kg
    print a
    for i in 1..3:
        print i
    """

    result = parse(code)
    assert 0 == len(result.Errors), result.Errors.ToString()
    assert 1 == len(result.CompileUnit.Modules)
    print result.CompileUnit.Modules[0].ToCodeString()

And the output is, of course:

	import metaboo.Units
	import metaboo.Ranges
	
	a = Mass(3, 'kg')
	print a
	for i in range(1, 3):
		print i

cdesign proponentsists

That's really funny :)

It's a copy'n'paste culture indeed.

boo 0.8.2 is here

Yeah, it's that time again!

As usual lots and lots of improvements in this new release including:

With many many kudos to Avishay Lavie, Cédric Vivier and Marcus Griep!

Cédric deserves special mention for working on all fronts and really pushing for the release. Superb work!

What? - http://boo.codehaus.org/

Download - http://boo.codehaus.org/Download

Official irc channel - irc://irc.codehaus.org/boo

Have fun!

Write Once, Sharpen, Run Anywhere

When I joined Db4objects a few years ago my first assignment was to research and implement a decent solution for getting db4o to work on the .net platform.

There was already some investigation going on on using the Eclipse JDT API as the basis for a source to source translator which proved to be a wise choice in the long run.

Eventually sharpen was born and after a lot of love we finally reached a point where the translated c# code would look really good.

People would get really interested every time sharpen was mentioned but for several reasons it wasn't publicly available.

Until now. Hooray!

I'm really looking forward to what people will build on top of that.


Why Design?

Another great Ted talk. I particularly love the sequence from 7:08 to 7:40.

I'm the man. The final man. You know, we've been mutating for 4 billion years but now because it's me we've stopped.

Except this time is true. :)

Towards Extensible Parsing

Almost four years ago the first feature request was entered into the boo issue tracker.

There should be a way to extend the parser so it could recognize custom measurement unit literals such as 1kg and 2cm.

Since then boo has improved a lot but with no solution for BOO-1 in the horizon.

I think I'm getting close to solve it in a interesting way using PEGs implemented as a graph of expression objects.

PEGs are very likable. Conceptually simple and composable.

Take the PEG that recognizes integer expressions involving the + and * operators:

grammar <- spaces addition eof
addition <- term ("+" spaces term)*
term <- factor ("*" spaces factor)*
factor <- [0-9]+ spaces
spaces <- (' ' / '\t')*
eof <- !.

where:

() means grouping.

* means zero or more matches.

+ means one or more matches.

/ is the prioritized choice operator. If the first expression succeeds, the whole expression succeeds. If the first expression fails, it backtracks and evaluates the second expression.

! is the not predicate operator which succeeds if its operand fails. It never consumes any input.

. matches any input.

The grammar can be translated to boo very simply using the peg macro from Boo.Pegs:

import Boo.Pegs

peg:
    grammar = spaces, addition, eof
    addition = term, --("+", spaces, term)
    term = factor, --("*", spaces, factor)
    factor = ++[0-9], spaces
    spaces = --(' ' / '\t')
    eof = not any()
    
assert grammar.Match(PegContext("  6*6 + 6 "))

I had to be a little creative in mapping the PEG operators to valid boo expressions because as it must be clear by now boo doesn't allow the introduction of completely new syntax and that's what the fuss is all about here.

I actually like the way it looks.

Implementing something more useful such as expression evaluation on top of that requires a few semantic actions operating a stack:

import Boo.Pegs
import System.Collections.Generic

stack = Stack[of int]()
push = stack.Push
pop = stack.Pop

peg:
    grammar = spaces, addition, eof
    addition = term, --("+", spaces, term, { push(pop() + pop()) })
    term = factor, --("*", spaces, factor, { push(pop() * pop()) })
    factor = ++[0-9], { push(int.Parse($text)) }, spaces
    spaces = --(' ' / '\t')
    eof = not any()
    
assert grammar.Match(PegContext("  6*6 + 6 "))
assert 42 == pop()

Semantic actions are just closures that get executed as matching succeeds. $text returns the text matched so far by the current rule.

Beautiful.

The underlying implementation based on a graph of expression objects really shines when one considers what it takes to extend the grammar above with support for hexadecimal literals:

peg:
    // rebind
    factor.Expression = hex_number / factor.Expression
    hex_number = "0x", ++hex_digit, { push(int.Parse($text[2:], NumberStyles.HexNumber)) }, spaces
    hex_digit = [0-9, a-f, A-F]
assert grammar.Match(PegContext("  0xa*2 + 11*0x02"))
assert 42 == pop()

It's not yet clear how this extensibility mechanism will be exposed at the boo language level but the simplicity at the peg level is encouraging.

One last feature worth pointing out is the ability to match based on a previously matched rule. For instance, the closing tag of a xml element must match the name in the starting tag:

import Boo.Pegs

peg:
    element = '<', tag, '>', content, '', @tag, '>'
    tag = ++(a-z)
    content = --(element / text)
    text = not "<", any()
    
assert element.Match(PegContext("<foo><bar>Hello</bar></foo>"))

I've found the idea for the last match operator @ first described in this article. Great idea.

I've been also greatly inspired by conversations I've had with Massi who's exploring similar territory and Jb during the last Mono Meeting in Barcelona Madrid and with Cedric over a beer in Paris. I think Massi will be pleased to know that I haven't given any thoughts to performance leaving all the fun to him.

Extensible parsing. Soon in a boo compiler close to you.


Anthropomorphism on Computer Science

It was more than twenty years ago that Dijkstra wrote against the perils of anthropomorphism on science. And here we stand building whole industries on top of it.

But is it programming dominantly math? Or is it mainly human communication?

Maybe we swung too far to the the latter. I speculate that the current rise of functional programming can also be attributed to its  liberating effect - one is no longer expected to attribute proper intent to entities before a program can be seen to make sense.

As a constant reminder of that I'm tempted to use a different font for my programming.

Dijkstra Font
boo 0.8.1 is here

Lots of improvements in this release including a simpler way for writing macros, support for nested functions, a better interactive interpreter, error messages that include suggestions for misspelled names, exception filters, exception fault handlers and for loop IDisposeable.Dispose integration.

With many many kudos to Avishay Lavie, Cédric Vivier, Daniel Grunwald and Marcus Griep!

What? - http://boo.codehaus.org/
Download - http://boo.codehaus.org/Download
Official irc channel - irc://irc.codehaus.org/boo

Have fun!

arc is out

Paul Graham's arc language is finally out.

"One of the things you'll discover as you learn more about macros is how much day-to-day coding in other languages consists of manually generating macro expansions."

Amem!
Make the world a better place with boo

Gaiaware has just announced the Gaia Programming Contest. A contest "... about creating an Ajax Application that will serve as a meeting place for people dedicated to solving environmental issues...".

Very good but there's more: "... no Close Source dependencies can be used which means that the end product must be compilable on Mono ...". Great!

Of course people using boo and db4o have a huge headstart. So what are you waiting for?

And now for something completely different...

Dennis Kucinich for emperor!

Fractally reuseable software

It's reuseable as whole and any individual piece you look at it's just as reuseable.

Yeah, I'm enjoying the Criptonomicom so far.

Boo Babel

As I went through the conference memories I recovered this one conversation I had with Jim Purbrick after the boo presentation.

His idea would be to have boo as the language for building languages in Second Life.

Niiiiice.

Back From the Mono Summit 07

What a great experience.

A chance to interact live with a dear friend. Free Software, Hacking, Women, Futurama, McDonalds, love spreading, Militant Atheism, Monty Python, Douglas Adams and the French Way.

Had lots of interesting exchange of ideas with Massi, ranging from "extensible parsing through composeable PEGs with  optimal performance" to Carlos Castañeda, Jesus Christ, meta-physics, religion and Pink Floyd. The Cryptonomicon really got me.

Got to put a face on Joachim and see how really cool Unity is.

Jeroen IKVM Frijters is a funny guy!

On Thursday I got to talk about db4o which led me to meet a few db4o users hanging around the conference.

Pedro Santos had an interesting question, how to monitor and control the usage of computational resources in a managed client/server application? In other words, how a sysadmin can make sure a specific client won't DOS the application?

For .NET servers running on Windows there are performance counters, what about Mono servers running on Linux?

I've also got to spread the gospel about boo for which I got a hugely positive response.

Thomas "Gaia" Hansen seemed to really get it and so we had lots of interesting discussions on how to take over the world boo style.

Jackson wants to hack on better nullable type support for boo!

Mark wants an extensible language where NullReferenceExceptions are impossible.

Miguel reassured me once again mcs won't be rewritten on top of the boo compiler infrastructure :)

The presentation material is here.

Looking forward to the next one.

Claiming Technorati

Following Carl's steps I'm also claiming my blog by publishing a link to my Technorati Profile.

Mono Summit 2007

So it's official now, I'll be speaking at the Mono Summit 2007.

It will be great to see you there!

Many thanks to the great folks at db4o for sponsoring my trip.

How to listen to music with your whole body

Evelyn Glennie shares with us just how.

Amazing presentation by an amazing human being/musician.

Atheists come out of your closets

Richard Dawkins: An atheist's call to arms.

Larry Lessig: How creativity is being strangled by the law

Lessig gives an inspiring talk on how creativity is being strangled by the law.

Quoting JB: "We need more of him"

We certainly do. We certainly do.

The multiverse as a breadth first search algorithm

I had the most fascinating dream last night, very complex and full of details and by its very nature impossible for me to describe it. It was mix of the Tao, The Hitchhiker's Guide to The Galaxy, Big Bang Theory and Computer Science and if I was to sum it all up it would be something like "the multiverse as a breadth-first search algorithm".

So what would be the optimal universe configuration? Looking from where I stand it's hard to believe it's going to be ours.

I don't believe I'm the first one to think it that way so now I'm googling for references. Drop me a line if you know of any.

Update 1: this seems to be close enough so I'm definitely getting it.

Update 2: I got depth-first and breadth-first mixed up :)

MockingBoo with meta programming facilities

Oren talks about a simple but interesting macro to aid with mocking. I decided to see if and how the latest meta programming facilities I've been working on are actually useful. Here's the complete application, what do you think?

    namespace Adapter

    import Boo.Lang.Compiler
    import Boo.Lang.Compiler.Ast
    import Boo.Lang.Compiler.Ast.Visitors
    import Boo.Lang.Compiler.TypeSystem
    import Boo.Lang.Compiler.MetaProgramming

    class AdapterMacro(AbstractAstMacro):
        def Expand(macro as MacroStatement):
            if macro.Arguments.Count != 1 or not macro.Arguments[0] isa ReferenceExpression:
                raise "adapter must be called with a single argument"

            entity = NameResolutionService.Resolve(macro.Arguments[0].ToString())
            raise "adapter only accept types" unless entity.EntityType == EntityType.Type
            BuildType(macro, entity)

        def GetModule(node as Node) as Boo.Lang.Compiler.Ast.Module:
            return node.GetAncestor(NodeType.Module)

        def BuildType(macro as MacroStatement, type as IType):
            adapterInterface = [|
                interface $("I" + type.Name):
                    pass
            |]

            adapter = [|
                class $(type.Name + "Adapter")($adapterInterface):

                    theTarget as $(type.FullName)

                    def constructor(target as $(type.FullName)):
                        theTarget = target
            |]

            GetModule(macro).Members.Add(adapter)
            GetModule(macro).Members.Add(adapterInterface)

            for member in type.GetMembers():
                AddMethod(adapter, adapterInterface,  member) if member isa IMethod

            BooPrinterVisitor(System.Console.Out).Visit(adapterInterface)
            BooPrinterVisitor(System.Console.Out).Visit(adapter)

        def AddMethod(adapter as ClassDefinition,
                adapterInterface as InterfaceDefinition,
                method as IMethod):

            if not method.IsPublic: return
            if method.IsStatic: return
            if method.ReturnType.IsByRef: return
            if method.ReturnType.IsArray: return

            interfaceMethod = [|
                def $(method.Name)() as $(method.ReturnType.FullName):
                    pass
            |]

            forwarder = interfaceMethod.CloneNode()

            forwardInvocation = [| theTarget.$(method.Name)() |]
            for param in method.GetParameters():
                if param.IsByRef or param.Type.IsArray:
                    return

                forwarder.Parameters.Add(
                    ParameterDeclaration(
                        Name: param.Name,
                        Type: SimpleTypeReference(param.Type.FullName)))

                interfaceMethod.Parameters.Add(
                    ParameterDeclaration(
                        Name: param.Name,
                        Type: SimpleTypeReference(param.Type.FullName)))

                forwardInvocation.Arguments.Add(ReferenceExpression(param.Name))


            adapterInterface.Members.Add(interfaceMethod)
            adapter.Members.Add(forwarder)

            if method.ReturnType == TypeSystemServices.VoidType:
                forwarder.Body.Add(forwardInvocation)
            else:
                forwarder.Body.Add([| return $forwardInvocation |])


    code = [|
        import Adapter

        adapter int

        print Int32Adapter(42) isa IInt32
    |]

    try:
        module = compile(code, typeof(AdapterMacro).Assembly)
        module.EntryPoint.Invoke(null, (null,))
    except x as CompilationErrorsException:
        print x.Errors.ToString(true)

boojay does eclipse

boojay does eclipse
Today history was made. The first eclipse plugin written in boo and compiled down to java bytecodes by boojay has come to life. The plugin is a direct translation of the the plugin described here.
And the boo code:

    """
    Hello World eclipse plugin.

    A direct translation of
    http://www.eclipse.org/articles/Article-Your%20First%20Plug-in/YourFirstPlugin.html
    to boo.
    """
    namespace HelloWorldPlugin

    import org.eclipse.ui
    import org.eclipse.jface.action
    import org.eclipse.jface.dialogs
    import org.eclipse.jface.viewers

    class HelloWorldAction(IWorkbenchWindowActionDelegate):

        activeWindow as IWorkbenchWindow

        def run(proxyAction as IAction):
            shell = activeWindow.getShell()
            MessageDialog.openInformation(shell, "Hello from boojay!", "Hello World!")

        def init(window as IWorkbenchWindow):
            activeWindow = window

        def dispose():
            pass

        def selectionChanged(proxyAction as IAction, selection as ISelection):
            pass


boojay discussion group

If you think it makes sense to have a JVM backend for the boo programming language, join us.

boo 0.8 is here

This release includes bug fixes, performance improvements and better meta-programming capabilities [1].

Special thanks to Marcus Griep, Nick Fortune and Matt McElheny!

What? - http://boo.codehaus.org/
Download - http://boo.codehaus.org/Download
Official irc channel - irc://irc.codehaus.org/boo


Complete change log here.
Have fun!
[1] see the 'match' and 'data' macros in the boo-extensions project for examples

A honest Halo 3 review

Yeah, I won't be playing Halo 3 unless I get one for free (hint, hint).

Introducing boojay

Consider the following simple application for a moment:

import org.eclipse.swt
import org.eclipse.swt.widgets

display = Display()
shell = Shell(display)
shell.setText("Hello!")
shell.setSize(200, 200)
shell.open()

while not shell.isDisposed():
    if not display.readAndDispatch():
        display.sleep()
        
display.dispose()

A boo application using the SWT java GUI library. Thanks to IKVM that's not only possible but very simple as well.

So what's the news? Well, Friday morning I was chatting with Klaus and he said to me "if you get boo to emit java bytecodes I'll do all my stuff in boo". How's that for a challenge? :)

Thanks again to IKVM, ObjectWeb ASM and the extensible boo pipeline architecture after a weekend of relaxed hacking boojay was born.

UPDATE: Just in case it's not clear, the generated class files DO NOT require IKVM in any way and can be executed in any compliant JVM.

A Pattern Matching facility for boo

I've finally took some time off this weekend to implement a simple object pattern matching facility as part of the newly created boo-extensions project.

Here's some code using the new 'match' and 'data' macros to implement an expression evaluator:

import Boo.PatternMatching
import Boo.Adt

def eval(e as Expression) as int:
   match e:
      case Const(value):
        return value
      case Add(left, right):
        return eval(left) + eval(right)

def simplify(e as Expression) as Expression:
    match e:
        case Add(left: Const(value: 0), right):
            return simplify(right)
        case Add(left, right: Const(value: 0)):
            return simplify(left)
        case Add(left, right):
            return Add(simplify(left), simplify(right))
        case _:
            return _

data Expression = Const(value as int) | Add(left as Expression, right as Expression)

e = Add(Add(Const(19), Const(0)), Add(Const(0), Const(23)))

print simplify(e)
print eval(e)
print eval(simplify(e))

'match' coupled with our recently acquired quasiquoting capabilities makes writing macros for boo a pleasant endeavour actually.

Dont believe me? Take a look at the data macro again.

Something I must read...

This is a Lisp tutorial worth reading.

Frink

This is so nice.

Boo 0.7.9 is here!

This release includes bug fixes, improves on generic support and introduces a few metaprogramming facilities (still on early stage).

Many thanks to the growing boo community!

What? - http://boo.codehaus.org/
Download - http://boo.codehaus.org/Download
Official irc channel - irc://irc.codehaus.org/boo

Full change log here.

Have fun!

One Week With Scala

It all really started when Bob Pasker asked me if db4o worked with scala. That kind of subtext is usually all I need to start exploring another programming language. Specially one of such a tasty functional flavor.

My experiment was to port a simple time tracking application I wrote for myself some time ago from .net/boo to jvm/scala.

The application works as a tray icon that lets you right-click your way through projects and tasks. There's no reporting interface other than a REPL window that allows you to execute arbitrary code against the app's object model :)

It actually took me only a week to get it up and running on the three major platforms I work with (windows, linux and macosx) thanks to scala, db4o and swt.

My impression so far is pretty darn good.

Scala is a beautiful language.

The tight integration with java means great tools such as db4o work out of the box.

And the eclipse support goes as far as supporting eclipse plugins written in scala (niiiice).

If you do java you should really be giving scala a ride.

You can find the application at http://code.google.com/p/sttracker/.

There's a readme with instructions on how to get it running either through eclipse or ant.

Even if you dont care about the time tracking functionality at all I think the SWT REPL window should give you some fun :)

Good luck, Lessig

I had the privilege to attend to Lessig's talk at the FISL some time ago. It really moved me.

I wish him the best of luck on his new crusade.

Boo meta methods II

By the way named arguments can also be used with meta methods:

    a = dict(A: "foo", B: "bar")
Possible implementation:
    [meta]
    def dict(keywords as (ExpressionPair)):
        h = [| {} |]
        for pair in keywords:
            h.Items.Add([| $((pair.First as ReferenceExpression).Name): $(pair.Second) |])
        return h
Keyword arguments are all collected into an array passed as the first argument to the meta method. That way, meta methods can still do pattern matching on the number and types of expression arguments.
Boo meta methods

Boo meta methods are methods that take code trees as input and return code trees as output. In addition they must be marked with the MetaAttribute for the compiler to recognize them as so.

The compiler invokes meta methods during the type resolution phase and replaces the code tree at the point of invocation with the code tree returned by the meta method.

Multiple overloads can be specified in which case the types of the code tree arguments will be used for the purpose of overload resolution.

An example, assert

Assert can be invoked with one or two arguments:

    assert x is null // use the code as the assertion message
    assert x is not null, "x shouldn't be null" // custom exception or string

One way of implementing assert would be:

    [meta] def assert(condition as Expression):
        return [|
            if not $condition:
                raise AssertionFailedException($(condition.ToCodeString()))
        |]
    
    [meta] def assert(condition as Expression, exception as Expression):
        return [|
            if not $condition:
                raise $exception
        |]
Where [| |] are the quasi-quotation delimiters. A quasi-quote evaluates its body as a code tree expression.

$ is generally called the "splice" operator and it means "evaluate me at compilation time".

Alternatively, assert could declare a variable parameter list:

    [meta] def assert(*arguments as (Expression)):
        condition = arguments[0]
        if len(arguments) > 1:
            // assuming 2 arguments
            exception = arguments[1]
        else:
            exception = [| AssertionFailedException($(condition.ToCodeString())) |]
        return [|
            if not $condition:
                raise $exception
        |] 

An interesting aspect of boo's splicing semantics is exemplified by the subexpression:

    [| AssertionFailedException($(condition.ToCodeString())) |]
The splice application $(condition.ToCodeString()) automatically lifts the string value returned by ToCodeString to a proper StringLiteralExpression.

Another example, using

'using' provides for deterministic disposal of resources. The argument should implement the IDisposable interface to have its Dispose method called
at the end of a provided code block.

For instance, the following code:

    using socket=OpenConnection():
        socket.Send("ping")
should be expanded to something equivalent to:
    socket=OpenConnection()
    try:
        socket.Send("ping")
    ensure:
        if socket isa IDisposable: (socket as IDisposable).Dispose()
A possible implementation for 'using' follows:
    [meta] def using(e as Expression, block as BlockExpression):
        temp = uniqueName()
        return [|
            $temp = $e
            try:
                $(block.Body)
            ensure:
                if $temp isa IDisposable: ($temp as IDisposable).Dispose()
        |]

More about quasi-quotation

Due to the reuse of syntactic elements in different contexts the parser needs to follow some conventions in order to infer the meaning of a quasi-quote expression.

Take the quasi-quote [| a as string |]. What does it mean? If we were to interpret it as an expression it would mean a try cast expression. If we were to interpret it as a type member it would mean a field definition.

For the inline form the convention is to try to interpret it as either an expression or an expression pair or an import declaration or a namespace declaration.

The block form is first probed for a type member definition then for a single statement, then for a block of statements.and then for a module.

Example:

    e = [| a as string |]
assert e isa TryCastExpression

f = [|
a as string
|]
assert f isa Field

m = [|
namespace Spam

print "Spam! "*3
|]
assert m isa Module

It should be possible to specify the exact context of quasi-quotation by using some special syntax but the specific details are not clear at this point.

Soon to reach a svn repository near you.

Oh, yeah, and many thanks to the people behind Template Haskell!

Boo 0.7.8 is here

Boo 0.7.8 is here!

With many thanks to the people who contributed for this release: Andrew Davey, Avishay Lavie, Cedric Vivier, Chris Prinos, Doug Holton, Jim Lewis and Max Bolingbroke.

What? - http://boo.codehaus.org/
Download - http://boo.codehaus.org/Download
Official irc channel - irc://irc.codehaus.org/boo

Highlights for this release include dramatic improvements to dynamic dispatching performance, a friendlier DSL syntax and of course bug fixes. This is also the last release to support .net 1.1.

Full change log here.

DSL-friendly syntax II

My good friend JB has just let me know it was his idea.

Sorry, JB :)

DSL-friendly syntax

Georges showed me today how he was using a boo DSL to generate HTML:

   1:html() do:
   2:    body() do:
   3:        text("Hello, world!")

The idea is to use nested closures to represent the hierarchy of tags:

   1:        
   2:callable Block()
   3:
   4:def blockTag(tagName as string, block as Block):
   5:    print "<${tagName}>"
   6:    block()
   7:    print "</${tagName}>"
   8:    
   9:def html(block as Block):
  10:    blockTag("html", block)
  11:    
  12:def body(block as Block):
  13:    blockTag("body", block)
  14:
  15:def text(s as string):
  16:    print s

It works pretty well except that all those do keywords and parenthesis kind of get in the way of clarity for that particular use case.

What we really would like to write is something like:

   1:html:
   2:    body:
   3:        text "Hello, world!"

Which is clearer and more to the point.

Boo actually allows one to do such a thing by extending the language with macros.

Boo macros are objects that are invoked by the compiler during the compilation process to expand or transform the AST in a hopefully useful way.

Whenever the Boo parser finds code in the form: name expression_list (block)? it creates a MacroStatement node that will be later handled to a macro object for expansion.

Let's define our html, body and text macros for our DSL:

   1:import Boo.Lang.Compiler
   2:import Boo.Lang.Compiler.Ast
   3:
   4:class AbstractTagMacro(AbstractAstMacro):
   5:"""
   6:Maps a macro to a DSL method invocation.
   7:"""
   8:    override def Expand(node as MacroStatement):
   9:        invocation = MethodInvocationExpression(Target: ReferenceExpression(TagName))
  10:        invocation.Arguments.Add(CallableBlockExpression(Body: node.Block)) 
  11:        return ExpressionStatement(invocation)
  12:        
  13:    abstract TagName as string:
  14:        get:
  15:            pass
  16:
  17:class HtmlMacro(AbstractTagMacro):
  18:    override TagName:
  19:        get: return "html"
  20:        
  21:class BodyMacro(AbstractTagMacro):
  22:    override TagName:
  23:        get: return "body"
  24:        
  25:class TextMacro(AbstractAstMacro):
  26:    override def Expand(node as MacroStatement):
  27:        invocation = MethodInvocationExpression(Target: ReferenceExpression("text"))
  28:        invocation.Arguments = node.Arguments
  29:        return ExpressionStatement(invocation)

Now we can write code as we wanted to in the first place but there are a few issues with macros:

  • writing macros demand a in depth knowledge of the compiler object model (oh, you didn't notice it?)
  • macros cannot be used in the same assembly defining them (the compiler needs to instantiate them after all, right?)

Enter BOO-835. It's now possible to use regular method definitions to create DSLs:

   1:callable Block()
   2:
   3:def blockTag(tagName as string, block as Block):
   4:    print "<${tagName}>"
   5:    block()
   6:    print "</${tagName}>"
   7:    
   8:def html(block as Block):
   9:    blockTag "html", block
  10:    
  11:def body(block as Block):
  12:    blockTag "body", block
  13:    
  14:def text(s as string):
  15:    print s
  16:    
  17:html:
  18:    body:
  19:        text "Hello, world!"

The code landed in the repository just a few minutes ago so feel free to try it while it's hot.

Updated: jira issue code was wrong.

Monster Muck Mashup

I am impressed.

Domain model persistence on the naked CLR

Oren asks:

   "Assuming that you have no access to tooling, and you don't have the resources to built NHibernate-sque framework, how would you approach building a Domain Driven application on the naked CLR?"

The most interesting part of the question for me is "and you don't have the resources to built NHibernate" because it immediately goes to the seemingly basic assumption most people have these days that "Persistence => SQL".

While it might be certainly true that a relational backend is a given for most enterprisey scenarios it is certainly not true that all persistent applications have to go through the pain.

Once upon a time a team with 4 people (2 developers, 2 web designers) built the web content management system for the 3rd largest TV station in Brazil on top of System.Runtime.Serialization using the Object Prevalence architecture.

Yeah, skin naked CLR.

If your specific application can't afford keeping all its objects in memory all the time and you don't mind putting a little clothes on, there's db4o.


Did I say 10x improvement?

I've applied the same optimization technique to static method and binary operator dispatching and now we have:

int*int: 1.1115984

list*int: 5.0773008

dynamicDispatch: 4.2661344

staticDispatch 1.4921456

Niiiice.

Changes checked in by the way.

10x improvement for dynamic dispatching OR how it took me 4 years to optimize duck typing

Around 4 years ago (!) there was this discussion about how to support some dynamic language features on top of mono. One of the topics was optimizing dynamic dispatching and apparently my suggestion was redirected to nul.

4 years later here I am finally implementing the idea in order to take boo's dynamic dispatching performance to the next level.

Before the optimization:

$ build/booi performance/duckoperators.boo
int*int: 1.101584
list*int: 29.0217312
dynamicDispatch: 51.9484224
staticDispatch 1.4921456

Each line reports how long it takes to execute the described operation with dynamic dispatching 5_000_000 times (except the last line which executes the same operation as the line before it but with static dispatching).

The first line tells us that it takes 1.10 seconds for boo to multiply two integer objects using dynamic dispatching.
The second line says boo takes 29.02 seconds to multiply a List instance by an integer using dynamic dispatching (dynamic dispatch over static methods).
The third line which is the most interesting one for our purposes here says that boo takes roughly 52 seconds to dynamically dispatch 5_000_000 instance method calls.

We can see a huge overhead over static dispatching.

After the optimization:

$ build/booi performance/duckoperators.boo
int*int: 1.101584
list*int: 27.755072
dynamicDispatch: 4.055832
staticDispatch 1.4821312

Niiiiiice.

So this first stab got it from 52 seconds down to 4 seconds. Not bad at all. A few changes and we'll have the same benefits for dynamic dispatching over static methods.

I hope this will have a huge impact on environments that rely heavily on dynamic dispatching such as Brail.

Unfortunately though this optimization is only available when building for the .NET 2.0 profile.

Soon in a source code repository near you.

On my way to the DLR Compiler Lab

I've just arrived in Seattle for the Microsoft DLR Compiler Lab. JB will be here soon and I heard Miguel is joining us as well. Fun!

Looking forward to getting my first Boo Silverlight application running.

One of the questions I'm here for is should we migrate Boo's duck typing support to be based on the DLR? On the pros side we get better integration with all the DLR languages and perhaps better performance when executing dynamic code. On the cons side it's an additional dependency (and not a very mature one for that matter).

Thoughts?

Overload Resolution rehaul

I started reviewing the overload resolution code in the boo compiler this week. Very old and, let's say, very interesting code. It was based on a fuzzy scoring system I have no idea how I came up with. Well, these things happen.

The new code is based on the concepts discussed here. Thanks Avish and Daniel for that!

A few test cases (mostly varargs related) had to be reviewed to comply with the improved behavior so expect a few compilation errors when updating to the new code and please let us know of any strange behavior.

Db4o, Activation and Transparent Activation I

Life looks good so let's consider a very simple data structure. A linked list:

   1:import System.Collections
   2:
   3:class LinkedList(IEnumerable):
   4:    
   5:    _head as Node
   6:    
   7:    def constructor(*values):
   8:        for value in values:
   9:            Add(value)
  10:    
  11:    def Add(value):
  12:        _head = Node(value, _head)
  13:        
  14:    def GetEnumerator():
  15:        node = _head
  16:        while node is not null:
  17:            yield node.Value
  18:            node = node.Next
  19:            
  20:    class Node:
  21:    
  22:        _value as object    
  23:        _next as Node
  24:        
  25:        def constructor(value, next as Node):
  26:            _value = value
  27:            _next = next
  28:
  29:        Value:
  30:            get:
  31:                return _value
  32:            
  33:        Next:
  34:            get:
  35:                return _next

Our LinkedList class can be used like this:

   1:list = LinkedList("Eric Idle",
   2:                "John Cleese",
   3:                "Graham Chapman",
   4:                "Terry Gilliam",
   5:                "Terry Jones",
   6:                "Michael Palim")
   7:for item in list:
   8:    print item

Which unsurprisingly gives the following output:

Michael Palim
Terry Jones
Terry Gilliam
Graham Chapman
John Cleese
Eric Idle

Now let's move on and store our beautifully crafted LinkedList instance with Db4o:

   1:
   2:using container = Db4oFactory.OpenFile(fname):
   3:    container.Set(list)
   4:

Some time later:

   1:
   2:using container = Db4oFactory.OpenFile(fname):
   3:    list = container.Query(LinkedList).Next()
   4:    for item in list:
   5:        print item or "<null>"
   6:

Which gives:

Michael Palim
Terry Jones
Terry Gilliam
Graham Chapman
<null>

Uh, oh... What's going on?

Activation is going on, that's what it is.

Activation is the process of populating the attributes of an object with previously stored data.

Db4o activates an object the first time it is retrieved from the database and whenever instructed to do so by the application through IObjectContainer.Activate.

During activation Db4o will also follow the references in the object graph activating any referenced objects until a configured activation depth is reached.

We can make sense of the output if we consider that Db4o has its default activation depth set to 5.

When activating the list Db4o will follow the LinkedList._head reference and activate the first node, then follow the Node._next reference and so on until it reaches the 5th node which it's not activated further and has its members set to null.

Now that we can understand the output has life gotten any easier?

Well, we can ask Db4o to activate the list to the depth of 7:

   1:
   2:using container = Db4oFactory.OpenFile(configuration, fname):
   3:    list = container.Query(LinkedList).Next()
   4:    container.Activate(list, 7)
   5:    for item in list:
   6:        print item or "<null>"

Which gives us the correct output but smells funny.

Application logic shouldn't have to worry about activation depth and all that. And how are we supposed to track the required activation depth for these dynamic object graphs?

Enter Transparent Activation.

Transparent Activation works by giving the objects in the system the responsibility of activating themselves before accessing any attribute. The activation must happen through a provided activator object which keeps track of everything needed for activation to work. The activator object is made available to any object that implements the IActivatable interface:

   1:
   2:class LinkedList(IEnumerable , IActivatable):
   3:    
   4:    _head as Node
   5:    
   6:    transient _activator as IActivator
   7:    
   8:    def constructor(*values):
   9:        for value in values:
  10:            Add(value)
  11:    
  12:    def Add(value):
  13:        Activate()
  14:        _head = Node(value, _head)
  15:        
  16:    def GetEnumerator():
  17:        Activate()
  18:        node = _head
  19:        while node is not null:
  20:            yield node.Value
  21:            node = node.Next
  22:  

  23:    def IActivatable.Bind(activator as IActivator):
  24:        _activator = activator
  25:        
  26:    def Activate():
  27:        if _activator is null: return
  28:        _activator.Activate()
  29:        

  30:    class Node(IActivatable):
  31:
  32:        _value as object
  33:
  34:        _next as Node
  35:        
  36:        transient _activator as IActivator
  37:        
  38:        def constructor(value, next as Node):
  39:            _value = value
  40:            _next = next
  41:
  42:        Value:
  43:            get:
  44:                Activate()
  45:                return _value
  46:            
  47:        Next:
  48:            get:
  49:                Activate()
  50:                return _next
  51:        

  52:        def IActivatable.Bind(activator as IActivator):
  53:            _activator = activator
  54:            
  55:        private def Activate():
  56:            if _activator is null: return
  57:            _activator.Activate()

  58:            

The application just needs to enable Transparent Activation once and then everything should work as expected (no more explicit Activate calls from the application):

   1:                    
   2:configuration = Db4oFactory.NewConfiguration()
   3:configuration.Add(TransparentActivationSupport())
   4:
   5:using container = Db4oFactory.OpenFile(configuration, fname):
   6:    list = container.Query(LinkedList).Next()
   7:    for item in list:
   8:        print item or "<null>"

Life looks better but what about all that boilerplate code that must go into the object model?

The next Db4o release will ship with an instrumentation tool capable of injecting the right IL instructions into an object model to make it Transparent Activation ready.

If you are curious to see this code in action grab it here.

In a next blog entry I'll go into how to encapsulate this logic behind a smart boo attribute.

Boo 0.7.7 is here

Boo 0.7.7 is finally here!

With special thanks to Avishay Lavie, Cedric Vivier and all the nice people who contributed to this release: Andy Bulka, Arron Washington, Chris Peterson, Daniel Grunwald, Dominik Zablotny, Doug Holton, Hans-Christian Holm, J Bryan Kelly, Jaroslaw Kowalski, Joshua W. Biagio, Marcus Griep, mfowle, Miguel de Icaza, Posti Laatikko, Sergio Rubio, Snaury, Szymon Wrozynski.

What? - http://boo.codehaus.org/
Download - http://boo.codehaus.org/Download

Highlights for this release include:
* More complete/stable generics support (now usable in WSA mode too).
* Support for using generic types with either external type parameters
(List of int) or internal ones (List of MyClass)
* Support for consuming generic methods.
* Generators and Iterators are now generic
* Support for the new "Type of *" syntax for referencing generic definitions.
* Improved type inference on generic types (this is work in progress).
* Fixed bug with multiple symbols on the same line when debugging
boo-generated assemblies.
* Fixed checked/unchecked inconsistencies and added new
"-checked[+/-]" option to booc.
* String handling optimized and generates Gendarme/FXcop-compliant assemblies.
* Automatic stub are now created when not implementing abstract
orinterface methods from base class.
* Verify pipeline is now available on Mono too.
* Lots of other fixes and improvements

Check the full change log here.

Best wishes and stay beautiful!

db4o 6.0 is out!

Feel the love!

Pair Programming and Free Play

I'm finally reading Free Play again. Always a pleasure.

I've also been pair programming a lot. Another pleasure:

"Some jobs are too big to handle alone, or simply more fun when done with friends. Either case leads us into the fruitful and challenging field of collaboration. Artists working together play out yet another aspect of the power of limits. There is another personality and style to pull with and push against. Each collaborator brings to the work a different set of strengths and resistances. We provide both irritation and inspiration for each other - the grist for each other's pearl making.

We need to remind ourselves here of what is obviously true but not often enough said: that different personality styles have different creative styles. There is no one idea of creativity that can describe it all. Therefore, in collaborating with others we round up, as in any relationship, an enlarged self, a more versatile creativity."

I could quote the whole chapter but hey, do yourself a favor and get the book.

A Comparison of Ruby and Boo

An interesting article by Kartik Vaddadi comparing Ruby and Boo.

I found Boo's subtext "it is about the whole experience" quite present as I went through the article. Many runtime facilities were replaced by compiler extensibility facilities so tool support was not sacrificed.

It's always a good feeling when I start #develop 2.0 or MonoDevelop.

Cirque du Soleil

Just got back from Corteo. WOW! What an experience! I'm feeling really good. If you have the chance don't miss it.

And this is only two days after having the pleasure of listening to Charlie Haden's Liberation Orchestra live.

Yeah, I'm feeling really good.

Cecil.FlowAnalysis is in

I've just finished updating the cecil repository with our latest contributions:

  • Cecil.FlowAnalysis
  • a very humble but functional test suite

Have fun!

Prevayler FUD

Martin Fowler blogged about in memory databases and I could not help reading the excerpt about Prevayler at the end as FUD:


Prevayler got a lot of attention for taking this kind of approach. People I know who tried it found it's tight coupling to the in-memory objects and lack of migration tools caused serious problems.

There are two assertions there, let me take them apart:

  • "People who tried it found its lack of migration tools caused serious problems." I can definitely understand that. Object prevalence and related native object persistence technologies enable you to be so agile in your development that the lack of proper migration tools is irritating. That's why Bamboo.Prevalence includes a simple but effective migration tool out of the box.

  • "People who tried it found its tight coupling to the in-memory objects caused serious problems." Well, tight coupling to in-memory objects is also called OOP in some circles. That's the single most important reason I would choose object prevalence technology whenever allowed by the project requirements. Ah, the things you are allowed to do when you get that intimate to your objects.

Native Queries (under the hood)

We are having a discussion about NativeQueries on castleproject-devel and I decided to wrap up the discussion here by describing some of the details and shared goodies of our implementation.

> Can I assume that you're using the new GetMethodIL (or something like that)?

We are using the Mono.Cecil API not the reflection API.

Simply because Cecil's version of GetMethodBody is so much better and it already worked on most platforms we support. One of our first contributions was to get Cecil running on the Compact Framework. After some conditional compilation fun (among other things) Cecil now works on mono, ms.net 1.1, ms.net 2.0, cf 1.0 and cf 2.0. Pretty cool.

> This is just freaking cool. And the idea is awesome.

Yeah, we think so too! (:

> If you cache the > execution plans, I suppose you can get a very good performance out of it. >

Currently we are not even caching the execution plans and the performance it's pretty close to the raw query execution performance one would get from the underlying query api.

But, yes, caching the execution plans (or transformed expression trees in our case) is the next logical step.

> This is a whole different way of thinking about how to mess with the > code...! > I've only heard about Cecil until now, wasn't aware that it was operational > on this level. Are there are docs yet, or is it read the code to find out? >

The Cecil object model is pretty self documenting.

The code we are contributing to cecil is a little more involved but still easy to follow if you stick to the public API.

It basically allows you to get high level control flow graphs out of method definitions. These high level cfgs can also contain decompiled expression trees (an expression tree is a structure pretty similar to a bound boo ast).

Here's a simple but complete example that uses Cecil and our contributed code (Cecil.FlowAnalysis) to dump the body of a method:

import System
import Mono.Cecil
import Cecil.FlowAnalysis
import Cecil.FlowAnalysis.ActionFlow
import Cecil.FlowAnalysis.CodeStructure

class Address:
    [property(State)]
    _state as string
    
class Customer:
    [property(Address)]
    _address as Address
    
class Predicate:
    def Match(c as Customer):
        return c.Address.State == "SP"

def GetMatchMethod():
    asm = AssemblyFactory.GetAssembly(typeof(Predicate).Module.FullyQualifiedName)
    return asm.MainModule.Types["Predicate"].Methods.GetMethod("Match")[0]

cfg = FlowGraphFactory.CreateControlFlowGraph(GetMatchMethod())
// a cfg is at the IL instruction level it is good for
// low level IL optimization and simple analysis

afg = FlowGraphFactory.CreateActionFlowGraph(cfg)
// an afg is at the statement/expression level
// good for code analysis

// print the interesting blocks
for block in afg.Blocks:
    expression as IExpression = null
    
    if block isa IReturnActionBlock:
        expression = (block as IReturnActionBlock).Expression
        Console.Write("return ")
    elif block isa IAssignActionBlock:
        expression = (block as IAssignActionBlock).AssignExpression
        
    continue if expression is null
    
    // expression is an ast like expression tree
    // which supports visitors
    // it is more like a bound ast (with all references
    // pointing to the right Mono.Cecil entities)
    //

    // ExpressionPrinter is a handy visitor
    print ExpressionPrinter.ToString(expression)

The code above will print:

    local0 = string.op_Equality(c.get_Address().get_State(), "SP")
    return local0
Going from that to a high performant query native to the underlying engine is a fun ride!
running breezy now

Ubuntu breezy installed without a hiccup on my AMD64. Then jdk 5, eclipse and skype.

Fingers crossed to install vmware player... What a nice surprise!

I simply ran the installer script and it worked!

So now I'm back to having linux as my main environment with Windows virtual machines.

What a nice day! Let's see how mono goes...

Miguel, Bamboo and Anders

I still have to blog about my great PDC experience but here it goes a quickie.

Anders having fun with boo and mono (or Miguel having fun with boo and c# or Bamboo having fun with mono and c#):

static typing is not about safety

Via Martin Fowler:
"""
Static types give me the same feeling of safety as the announcement that my seat cushion can be used as a floatation device.

--Don Roberts
"""

Most people seem to think of static typing mainly as a safety net. I even had used that same term before. Well, as it turns out static typing is mainly about providing two things:

  • better tools: editing tools (think code completion), code navigation tools (think 'show type hierarchy', 'call hierarchy', 'goto base method'), refactoring tools (think 'rename', 'change signature');
  • better performance: compilers, optimizers and the runtime environment can do a much better job when type information is available (and do it much faster);

And that's why boo is statically typed, because is the whole experience that counts.

Free Culture

Thank you Lessig!

Mono Meeting at the Microsoft PDC

Count me in.

eclipseness

Georges and I have been working on a set of eclipse plugins for boo development. There are several reasons I decided to give eclipse a try:

  • I've been spending the last year working pretty much 50/50 on java and .net projects - this is to say that I've been using eclipse a lot and got used to it;
  • I've also been in charge of writing some eclipse plugins so I got the expertise;
  • eclipse's architecture is pretty well thought out (I'm not saying the other ides' out there are not - I'm only familiar with eclipse's);
  • there are lots of plugins out there and lots of information about writing eclipse plugins - I'm sure you will agree this is in clear contrast with the other environments;
  • the PDE environment is pretty mature and TDD plugin development is a reality;
  • lots of other tools/frameworks/languages are already eclipsed and we get those for free: java, c++, antlr, cvs, svn, python, ruby, byecycle...
  • I need a pleasant and smoother cross platform experience as I develop software for different platforms: we have already used the plugins under windows, linux and macosx and everything worked like a charm (well, sort of :));

What we already have:

  • syntax highlighting (and of course we inherit most of eclipse's editing features like editor navigation and history);
  • boo projects;
  • background builders which report errors as you save the files;
  • local library references, gac references and internal project references (I would have to explain a little more);
  • launching (run as boo application, run as boo script);
  • nunit integration (run as nunit test);
  • interactive interpreter with code completion;
  • stack trace navigation (click on a file:line information and have that file open in the editor);

It's already ok for my everyday, cross platform use but YMMV as usual.

The glorious screenshots (click to enlarge):


The contributed boo perspective on my ubuntu system


The background builder reports errors and warnings as you save the files


Some MacOSX love from Georges


Code completion on my ubuntu system


NUnit integration (running on windows)

The plugins will move to the boo repository soon. Stay tuned.

Going to the PDC

Working for db4o is really a joy.

Not only I get to work on a great product which is changing and will keep changing the way many people
develop software but also get to work and talk with very smart guys very frequently.

And now for the extra sugar they are sponsoring my trip to the PDC.

So if are you going to the PDC and want to exchange some ideas on object oriented databases,
agile programming languages, agile software development, drumming and/or lucid dreaming,
let me know!

The father of C# talks about boo...

http://www.microsoft-watch.com/article2/0,2180,1837434,00.asp

"Then I say, is it really necessary to have such strong typing in the name of tersity? I don't think it is, necessarily.

I actually think that an even better world is a world where (a language) is terse, but it is still strongly typed."

Agreed, Anders :)

Byecycle - Aesthetic Programming for Eclipse

Byecycle is an auto-arranging dependency analysis plug-in for Eclipse. Its goal is to make you feel sick when you see bad code and to make you feel happy when you see good code.

Visit the Byecycle home page for more details.

subtext

Yeah. This got me thinking. Thanks.

VMWare on SuSE 9.2/AMD64 absolutely rocks

I had to write an eclipse plugin some time ago. I just can't live without TDD. TDD with eclipse plugins is a pain in the neck because of eclipse startup and execution times. In my old development machine (a PIV 2.2Mhz notebook), the entire test suite takes 125 seconds to run. After weeks of intensive development I figured I had two options either buy a faster workstation or go nuts.

I bought myself a AMD64 3200+ workstation.

Here's the time figures for the different development environments I tried:

Notebook, Windows XP Home, Eclipse 3.1, jdk 1.5.0_01 (client vm): 125.7s
Workstation, Windows XP Pro, Eclipse 3.1, jdk 1.5.0_01 (client vm): 57.8s
Workstation, Windows XP Pro, Eclipse 3.1, jdk 1.5.0_01 (server vm): 61.3s
Workstation, SuSE 9.2 64bit, Eclipse 3.1, jdk 1.5.0_01 64bit (server vm): 61s
Workstation, SuSE 9.2 32bit inside VMWare running on SuSE 9.2 64bit, jdk 1.5.0_02 32bit (client vm): 59.2s

I find absolutely amazing that running eclipse inside a 32bit SuSE 9.2 VMWare under SuSE 9.2 64bit runs at the same speed of eclipse under Windows XP Pro.

These VMWare guys really know what they are doing.

Quick update: I've just tried running the smae SuSE 9.2 32bit inside a VMWare running on Windows XP Pro 64bit and the full test suite took only 57s!!!! So it seems that I've finally found my development enviroment setup.

boo 0.5 is here

Spread the word, boo 0.5 is out!!

Lots of goodies in this release.

Thanks to the growing boo community for making this ride so fun.

Special thanks go in random moustache size order to *Daniel Grunwald*, *Ian MacLean*, *Latexer*, *Bill Wood*, *Doug Holton*, *Aaron Washington* and *Scott Fleckenstein*.

Hey you all, have fun!

db4oboobrowser is online

What happens when you mix a developer looking for some fun, a great open source object database engine and a wrist friendly programming language?

I tell you what happens: db4o boo object browser

Database Atrophy

"You have to understand that most of these people are not ready to be unplugged. And many of them are so inurred, so hopelessly dependent on the system, that they will fight to protect it.

...

Yet, their strength and their speed are still based in a world that is built on rules.
Because of that, they will never be as strong or as fast as you can be."

Yes, Klaus is finally blogging.

Nested types dont work on .net 2.0


I just can't buy this "we don't have resources to fix it before Whidbey" shit. Come on!!!! You're f$#$@#$ Microsoft! You have billions of dollars. Hire someone else to fix it.


What are you looking at??!?!?

boo in 2005


Happy new year everybody!

Some things boo related I'd like to see in 2005.

boo in boo

metaboo?

I want to have the Boo.Lang.Compiler assembly "ported" to boo.

Boo.Lang.Interpreter would be merged with it in the process and we might even gain eval, compile, exec, locals builtins in the process :)

In the process we would also incorporate the necessary improvements to finally being able to use the case insensitive dialect (or the white space agnostic one).

better type inference

The current system fails to infer types on recursive definitions.

generics

I'd really would like to hear some thoughts on this one. But my intention is to start boo in boo from day one having .net 2.0 (mono 2.0 profile) as a requirement.

eclipse-like experience

After spending some time with java and eclipse it was clear to me that it is all about the experience. The eclipse IDE can make even a verbose and limited language like java seem very useable.

What I really would like to see in a boo focused IDE:

  • refactoring support: "rename type/field/method/event" and "extract method" are my favorite ones
  • call hierarchy browser
  • find unused methods/types/fields

The nice thing is that this is so easy to implement :D

Ok, maybe not so easy but who doesn't like a challenge for a change?

I'm not sure if SharpDevelop is the way to go though...

VS.NET language binding walkthrough

This looks interesting.

Interesting... What about a boo language service for VS.NET?

SharpDevelop and boo - looking good

Class viewer, code folding, code completion and a boo interactive console. Life is good indeed!

Kudos to Daniel Grunwald.

Compiler pipelines and compiler profiles

A compiler pipeline is a named sequence of compiler steps. Pipelines are like compilation recipes: CompileToFile, CompileToMemory, Parse, ResolveExpressions, etc.

The good thing about the pipeline abstraction is that it is pretty easy to hook into the compilation process to do all sort of things (see how easy it was to implement the interactive interpreter).

The bad thing about the way pipelines are implemented today is that if you want to customize, let's say, the parser (maybe you don't like syntactically significant white space), you have to change every single pipeline your application is going to use. For a clear example of why the current pipelien architecture is bad, think of the Boo Explorer application. It uses 3 pipeline definitions:

  • Parse: for the document outline view
  • ResolveExpressions: code completion
  • InteractiveInterpreter custom pipeline

Now imagine that you want to use your custom parser step with boox. How would you do it? See the problem? You would have to change code in a lot of places (inside and outside boox!) just to plug in your custom parser.

Another use case would be making boo case insensitive (Hi Doug!).

I was talking about this with Carl Rosenberger (db4o) and he asked me what the problem was :). He replied with something along these lines: "just use some sort of dictionary to hold all the configurable services and make the pipelines aware of it".

Simple.

Let's baptize this glorified dictionary then: Compiler Profile.

A compiler profile represents a set of services that should be used by any given compiler pipeline. Each service in a profile is identified by a well known name (it's not yet clear to me if the name will be something like a string or a System.Type reference). I see the following services right now:

  • Parser - don't like to rely on white space?
  • Comparer
  • OverloadResolutionService - want to implement different rules for overloaded methods resolution?
  • TypeSystemServices - want different builtin type names? Different type compatibility rules?

The good thing about this model is that a specific service or profile could be even specified in the command line:

	booc -profile:caseinsensitive foo.boo
	boox -service parser:MyCustomParser,MyCustomAssembly foo.boo

The way I see it it should be very easy to write a, let's say, vb.net compiler based on boo just by providing the right services.

I plan to include this profile thing in the next major refactoring when I'll translate Boo.Lang.Compiler from c# to boo. Thoughts?

Sovereign Computing

From the looney who came up with prevayler: Sovereign Computing.

Are you ready to join the crowd and make it happen? Too scared?

Sovereign Computing

DON'T PANIC

Nice teaser but I just can't wait to see Sam Rockwell playing Zaphod.

booish meets java II
Doug reminded me that we don't actually need the jbooish stub to explore the java libraries:

$ ./booish
>>> load("d:/dotnet/ikvm/bin/IKVM.GNU.Classpath.dll")
>>> import java.lang
>>> System.getProperty("java.vendor")
'Jeroen Frijters'
>>>
booish meets java
rodrigob@bambook /cygdrive/d/dev/boo/build
$ ./ikvm -classpath "booish.jar;." jbooish
>>> v = Class.forName("java.util.Vector").newInstance()
[]
>>> v.add("Hello")
true
>>> v.add("Java!")
true
>>> v
[Hello, Java!]
>>>


How to
  1. download ikvm
  2. unpack the binaries to your boo build or bin directory
  3. ikvmstub booish.exe
  4. create a little java stub that instantiates booish.InteractiveInterpreter, let's call it jbooish, mine is at the end of this entry
  5. javac -classpath "$CLASSPATH;.;booish.jar" jbooish.java
  6. ./ikvm -classpath "booish.jar;." jbooish
  7. boo your way through the java libraries!
Is this nice or what? Now I get to work with boo even when I work with java.

jbooish.java
import cli.booish.InteractiveInterpreter;

public class jbooish {
    public static void main(String[] args) {
        InteractiveInterpreter interpreter = new InteractiveInterpreter();
        interpreter.set_RememberLastValue(true);
        interpreter.SetValue("Class", jbooish.class);
        interpreter.ConsoleLoopEval();
    }
}
it feels like the old c++ days
I did fell in love with java once.

I guess that after years of reinterpret_cast<void**>(&spUnk.p), java seemed like nothing but a beautiful sunday morning.

Reading a char array from a file the java way
    public static char[] readChars(File file) throws IOException {
        FileInputStream stream = new FileInputStream(file);
        try {            
            // HACK: assume 1 byte per char
            char[] buffer = new char[(int)file.length()];            
            InputStreamReader reader = new InputStreamReader(stream);
            reader.read(buffer);
            return buffer;
        } finally {
            stream.close();
        }
    }


Reading a char array from a file the .net way
def readChars(fname as string):
    using reader=File.OpenText(fname):
        return reader.ReadToEnd().ToCharArray()


java api quirk of the day

Q. How do you get a list of files matching a specific wildcard?
A. java.io.File.listFiles(FilenameFilter)

FilenameFilter??? What's wrong with Directory.GetFiles("*.boo")?

And by the way we don't even have a java.io.Directory, it's everything on java.io.File. F#?%#!a a...

Ok, let's just breath... I'll need my yoga classes more than ever now that I'll be doing lots of java.

Eclipse JDT is déjà vu all over

I'm working a lot with the Eclipse JDT core model lately (yes, yes, I confess, I'm doing lots of java lately :-)).

I find it amazing how the Eclipse AST model is similar to one of the first AST models I designed for the boo compiler. Even some classes and interfaces have the same name (!!). The déjà vu climax was org.eclipse.jdt.core.dom.IBinding. It's been a long time (+8 months) since I renamed IBinding to IEntity but still...

Do we have an explanation to that? Strikingly similar artifacts created independently of each other.

Patterns of software? or patterns of the nature itself?

And apparently GWB pulled it off again...
Amen, Hammett.
debugging boo code

After tweaking the EmitAssembly.EmitDebugInfo code a little I was able to get the debugger running.

Not for me but I know some people that just can't live without decent debugging capabilities... Now they can try boo and debug away.

Here's a shot of examples/fibonacci.boo being debugged:

InteractiveInterpreter meets Gtk

The source code is here

System.Windows.Forms meets booish
woohoo! booish is alive!
$ booi extras/booish/booish.boo
>>> e = i*2 for i in range(3)
>>> print(join(e))
0 2 4
>>> a = 2**4
>>> print(a)
16
>>> ^Z
towards a boo interactive shell

Interactive language shells are cool. If you don't agree go read something else.

An interactive boo shell is probably the number one request I receive and finally the good news is that yesterday as I was leaving the elevator I had this very clear vision on how I could implement it. The great news is that it won't be too hard. In fact, if you compile boo from the subversion repository you can already take a look at the initial design of the InteractiveInterpreter class in the src/booish directory.

Sample code? ok. Here it goes:

interpreter = InteractiveInterpreter()
interpreter.SetValue("name", "boo")
interpreter.SetValue("age", 3)

interpreter.Eval("""
print(name)
print(age)
age += 1
""")

assert 4 == interpreter.GetValue("age")

interpreter.Eval("age = 42")
assert 42 == interpreter.GetValue("age")

interpreter.Eval("""
value = 3
print(value*2)
""")

assert 3 == interpreter.GetValue("value")

interpreter.Eval("x2 = { return value }")

x2 as callable = interpreter.GetValue("x2")
assert 3 == x2()

cool, eh?
Maybe you'll start using boo now, hammett? ;-)

tableless cross-browser menu thing

Webdesigning me? Nah... Just the old javascript/CSS/XHTML reality check every now and then.

So here it goes to Leonardo:

   1:<html>
   2:<head>
   3:<style>
   4:.body
   5:{
   6:    font-family: verdana;
   7:    font-size: 10pt;
   8:}
   9:
  10:.menuItem, .menuItemHover
  11:{    
  12:    background-color: blue;
  13:    font-weight: bold;
  14:    padding: 5px;
  15:    color: white;
  16:    display: inline;
  17:    cursor: pointer;
  18:}
  19:
  20:.menuItemHover
  21:{
  22:    background-color: lightblue;
  23:}
  24:</style>
  25:
  26:<script language="javascript">
  27:document.onmouseover = function(ev)
  28:{
  29:    var element = getEventTarget(ev);
  30:    if ("menuItem" == element.className)
  31:    {
  32:        element.className = "menuItemHover";
  33:    }
  34:}
  35:
  36:document.onmouseout = function(ev)
  37:{
  38:    var element = getEventTarget(ev);
  39:    if ("menuItemHover" == element.className)
  40:    {
  41:        element.className = "menuItem";
  42:    }
  43:}
  44:
  45:function getEventTarget(ev)
  46:{
  47:    return (ev && ev.target) || window.event.srcElement;
  48:}
  49:
  50:</script>
  51:</head>
  52:<body>
  53:
  54:<div id="menuBar">
  55:<div class="menuItem">
  56:<img src="images/arrow.gif" />
  57:About US
  58:</div>
  59:<div class="menuItem">
  60:<img src="images/arrow.gif" />
  61:Products
  62:</div>
  63:</div>
  64:
  65:
  66:</body>
  67:</html>


The same old few conclusions:
  • CSS has really nice features, how can be people not using it more?
  • tableless html is easier to read, easier to write, easier to change (at least if you are using jedit such as myself)
  • tableless html is easier to relayout (think skins)
so again, why do we still have deeply nested tables everywhere? Dreamweaver?

generator methods... looking good!

Tough weekend but I've finally got generator methods to work.

Integrating generator methods with generator expressions with closures was a good challenge... Next! :)

And before I go I shall leave you with this amazing piece of cra... hmm... code:


b = 5
g = def ():
    a = 0
    yield { return a }
    yield { return ++a }
    yield { a = b; return { return (a+b)*i for i in range(3) } }
    assert 5 == a
    
    
for f in g():
    item = f()  
    if item isa callable:
        b = 3
        print(join(cast(callable, item)(), ", "))
    else:
        print(item)
which prints:
0
1
0, 8, 16
Understand why and you'll understand boo's main features.

For the cat lovers out there

The Infinite Cat Project.

I'm still deciding on which of my cats will go first...

Type inference in boo

I've finally set some time aside to write about boo's type inference mechanism.

Comments (here or in confluence) are welcome.

Vote against Bush

Hey you! Yeah, you, the ones deciding the fate of the empire during the next few days.

Have in mind that whatever you decide will have a huge impact on the life of everyone else on this planet (and maybe the universe, how greedy can those in power become?) so please vote against Bush!

And if you haven't made up your mind yet or were thinking on not voting just because everyone sucks, please, be the voice of those without one and vote against Bush!

Please?

boo 0.4 is out

Grab yours here!

Tons of improvements in this version, true closures are my favorite one since they allow ruby-like things such as:

def each(items, closure as callable):
    for item in items:
         closure(item)

items = [1, 2, 3, 4, 5]
value = 0
each(items) do (item as int):
     value += item
print(value)


In this example the closure is constructed with the do keyword and is automagically passed as the last argument to the each function. Cool or what?

Holy circumflexes!

What ever happened to C++?

Mono.GetOptions rules

I had to create a little (because boo code tends to be terse) console utility for a customer. The utility had to deal with lots of different command line options, that kind of thing. So I saw it as my opportunity to finally meet Mono.GetOptions.
What a nice tool!

import Mono.GetOptions from Mono.GetOptions

class CommandLineOptions(Options):

    def constructor(argv):
        ProcessArgs(argv)

    [Option("thumbnail width", "width")]
    public Width = 70

    [Option("thumbnail height", "height")]
    public Height = 70

    [Option("output file", "output")]
    public OutputFileName = ""

    [Option("input file", "input")]
    public InputFileName = ""

    [Option("encoding quality level (1-100), default is 75",  "encoding-quality")]
    public EncodingQuality = 75L

    IsValid as bool:
        get:
            return (0 == len(RemainingArguments) and
                        len(OutputFileName) > 0 and
                        len(InputFileName) > 0 and
                        Width > 0 and
                        Height > 0)

options = CommandLineOptions(argv)
if options.IsValid:	
    for field in typeof(CommandLineOptions).GetFields():
        print("${field.Name}: ${field.GetValue(options)}")
else:
    options.DoHelp()
Fire this script with
booi GetOptions.boo
and you'll already see a pretty professional looking help.
My heart would be filled of joy every time I needed to add support for a new parameter :)

Very nice work Rafael!

The Dark Side of The Moon and The Wizard of OZ

Simply amazing!

Just watch and check the coincidences for yourself. It's quite a trip.

Setting properties/fields/events at construct-time

Edd Dumbill talks about one of the IronPython niceties here.

boo also allows it and it works not only with properties but with events and fields too:

import System

class Button:

    [property(Text)]
    _text = ""

    public Width = 0

    event Click as EventHandler
	
    def RaiseClick():
        self.Click(self, EventArgs.Empty)

b = Button(Text: "Click me", Width: 10, Click: )
print(b.Text)
print(b.Width)
b.RaiseClick()

Cool or what?

Back to the notebook
It's been some time now since my notebook (as in "A light, portable computer that is generally thinner than a laptop") went to the repair shop and I feel extremely free.

I've been spending much more time with my family and friends ( including my books, comics and CDs). I still haven't got back to playing the drums but I'm sure I will... eventually.

Cutting straight to the chase I decided to finally work on issue BOO-17 (automatic callable type conversion and adaptation) so I grabbed my notebook (as in "A book of blank pages for notes") and programmed away. Programming on paper can be so much easier sometimes! A simple solution was already there just waiting for me to uncover it.

The problem I was trying to solve was twofold: first, delegate types (callables) are name equivalent not structurally equivalent in the CLI type system, in other words, the following valid boo code can not be directly translated to IL for being deemed unverifiable:
callable Function()

def foo():
   pass
   
# the following line silently generates a
# new (anonymous) callable type structurally
# equivalent to the declared callable Function1
# above
a = foo

fn as Function
fn = a
fn()
Second, boo compatibility rules for callable references go beyond simple structural equivalence, a RVALUE callable reference can be assigned to any LVALUE reference if any of the following conditions is true:
  • their types are the same (name equivalence)
  • their types are structurally equivalent (same number of arguments, arguments all of the same type, same return type)
  • the callable on the right takes the same number of arguments or less and all of them are assignment compatible with the arguments of the callable on the left
Example:
import System

def click1():
    print("clicked!")
	
def click2(sender):
	print("${sender} clicked!")
	
def click3(sender as string):
	print("${sender} clicked!")
	
handler as EventHandler

handler = click1
handler(null, EventArgs.Empty)

handler = click2
handler("foo", EventArgs.Empty)

handler = click3
handler("bar", EventArgs.Empty)

The Solution

It's actually pretty simple and it works for both cases: get the compiler to generate an adaptor class containing:
      a single argument constructor taking the RVALUE reference
      a method strictly compatible with the LVALUE reference
      a factory method that will take the RVALUE reference and return a LVALUE compatible reference
The only thing left to do is to replace the RVALUE reference by the factory method invocation. Making it all more concrete, the compiler must transform code like this:
callable Function()

def click():
    print("clicked!")
	
fn as Function = click

handler as EventHandler = fn
Into something like this:
callable Function()

class __Adaptor0__:

    __callable__ as Function

    def constructor(value as Function):
        self.__callable__ = value

    def Invoke(sender as object, args as System.EventArgs) as void:
        self.__callable__()

    static def Adapt(value as Function) as System.EventHandler:
        adapted = __Adaptor0__(value)
        return adapted.Invoke

def click():
    print("clicked!")

fn as Function = click
handler as EventHandler = __Adaptor0__.Adapt(fn)
Unfortunately my current notebook can't run unit tests yet :)
It’s way past time to fix it
Nice essay on Patents and Linux.
And just in case you are wondering I totally agree.
Weapons of mass destruction

I've finally had the chance to watch Fahrenheit 9/11 last night. One of the funniest pieces I've seen in a long time.
The americans on the line behind us didn't seem to understand why I laughed all the way through.
Homer Simpson puts it best: "It's funny because it's true!".

Sun Ship

I have never heard anything like that.

The Sun Ship of John Coltrane, Elvin Jones, McCoy Tyner and Jimmy Garrision took me far far away to the deepest and darkest corners of the universe.

Ohm.

An even flow of love that irradiates from the very essence of the existence.

IronPython

The 0.6 version of IronPython was just released. I still don't know how to feel about Jim being hired by MS though.

Anyway, I've just played a little with it and it looks great!

The distro comes with a System.Windows.Forms example that I decided to translate to boo just for the fun of it:

import System.Windows.Forms from System.Windows.Forms
import System.Drawing from System.Drawing

f = Form(Text:"Windows fun with boo",
         HelpButton: true,
         MinimizeBox: false,
		 MaximizeBox: false,
		 FormBorderStyle: FormBorderStyle.FixedDialog,
		 StartPosition: FormStartPosition.CenterScreen)		 

b1 = Button(Text:"Say Something", Location:Point(30,30), Size:Size(100,30))
b1.Click += callable:
    l = Label(Text:"boo is Alive!", ForeColor:Color.Red)
    l.Location = Point(30, 50+f.Controls.Count*25)
    f.Controls.Add(l)

f.Controls.Add(b1)
f.ShowDialog()



The future seems brighter on .net land.

Great hackers

If you haven't read it yet here's another great essay by Paul Graham.

Graham says:

The programmers you'll be able to hire to work on a Java project won't be as smart as the ones you could get to work on a project written in Python.

s/Python/boo/ and it is still true! :)

Writing tests for boo

Soooo... I've decided to spend most of my free time this weekend polishing the way test cases for boo are written. Hopefully I made it so easy that new feature requests and bug reports will already come with lots of attached test cases.

Thoughts/comments/suggestions/criticisms? Let me know.

When I was 29

The guys had a surprise for me today:


From left to right: Leo, Andre, me and Carlos

Oh, guys! I hate you so much. :)

Boo Explorer for linux

boo users on windows can already count on a simple but very effective way to edit and run their boo scripts: boox. boox even features code completion! (You're the man, GB!).

The somewhat bad news (at least for me) is that I'm no longer a happy boox user since my notebook went to the repair shop two weeks ago.

The good news is that now I got a real chance and the motivation to create a similar tool for my fellow linux users. I hope to finally learn some gtk programming techniques along the way.

So here's my first shot at creating Boo Explorer for linux: a dumb GtkSourceView based editor with boo syntax highlighting enabled.

import System
import Gtk from "gtk-sharp"
import GtkSourceView from "gtksourceview-sharp"

def window_Delete(sender, args as DeleteEventArgs):
   Application.Quit()
   args.RetVal = true

Application.Init()	
booSourceLanguage = SourceLanguagesManager().GetLanguageFromMimeType("text/x-boo")
buffer = SourceBuffer(booSourceLanguage, Highlight: true)	
sourceView = SourceView(buffer, ShowLineNumbers: true, AutoIndent: true)
window = Window("Simple Boo Editor",
                           DefaultWidth:  600,
                           DefaultHeight: 400,
                           DeleteEvent: window_Delete)
window.Add(sourceView)
window.ShowAll()
Application.Run()

Now I just need to learn how to add a menubar, a toolbar, a statusbar, a tree view (document outline), how to handle accelerator keys then I'm pretty much set :-)