Archive for the ‘ProS’ Category

Continuation passing

Posted: June 3, 2009 in c#, ProS

While working on version 0.3 of ProS I had the following requirement:

When given a list of statements that all return a value of IProcessor (That interface defines a method called Process) call each processors process method in turn and pass the result of the execution to the next processor in the list if and only if the result is null. At the same time the sequence of calls needs to be wrapped in a new IProcessor object so that the entire sequence can be part of another sequence.

After trying a few different approaches I ended up with using continuation passing. But what is that?

given two methods:

public int GetRandomInt()

{

return new Random().GetNext();

}

public void DoSomethingWithAnInt(int i)

{

Console.WriteLine(i.ToString());

}

a main could look like this:

public int main()

{

var i = GetRandomInt();

DoSomethingWithAnInt(i);

}

if we wanted to turn that into continuation passing we would have to change the first method and make it something like

public void GetRandomInt(Action<int> doSomethingWithAnInt)

{

var i = new Random().GetNext();

doSomeThingWithAnInt(i);

}

and main would then simply be

public int main()

{

GetRandomInt(DoSomethingWithAnInt);

}

This is actually more common than what you might think at first. Think of any Async call in .NET you’ll probably remember that one of the arguments is an AsynCallback. That call back is the continuation of the Async call. So for implementing asyncromeous behaviour the continuation passing style is very straight forward, simply pass what you want executed when the first call completes.

I need to represent a tree where each node is a decision point. E.g I might need to represent the code structure

if(a())

{

DoA();

}

else if (b())

{

DoB();

}

else

{

throw new InvalioperationException(“No sensible default action”);

}

however a() and b() is not known compile time and the number of if’s is not known either.

I ended up with a class called ContinuationProcessor that looks similiar to this:

public class ContinuationProcessor<T> : Irpocessor<T>

{

public ContinuationProcessor(ContinuationProcessor<T> continuation, IProcessor<T> processor,Func<object[],bool> condition)

{

//initialize the private fields

}

//This method is defined in IProcessor

public T Process(T obj, params object[] arguments)

{

T processedObj = null;

if(condition((new object[]{processedObj}).Concat(arguments)))

{

processedObj = processor.Process(obj,arguments);

}

if(continuation != null)

{

processedObj =  continuation.Process(processedObj,arguments);

}

return processedObj;

}

}

So it ends up not being true continuation passing since I end up returning a value, but it does make it possible to represent an arbitrary number of decision points together with the code that should be executed in case the associated decision is taken.

It’s a lot of fun writing code that represent code, but it gives me a headache trying to debug it…

Advertisement

Just finished v0.2 actually there’s not that much new to v0.2. It simple adds a property production to the language as well. The syntax is similar to the one used in c#

A long the way I had quite a few strange experiences. The one that took me the longest to find a solution for was the fact that new LanguageCompiler(new Grammar()) (languageCompiler is a Irnoy class) ment to differrent things depending on how I used my compiler. If I used it with the Grammar Explorer from the Irony project or in the VS SDK hive everything worked fine, but using it stand alone to compile to a .dll new Grammar() suddenly turn it self into instanciating the Irony GRammar class instead of the PRoS Grammar.

Never figured out why but I can only say it’s a good thing to have the source code of the Libraries you’re using when you have to hunt down the reason to why they throw a null refererance exception.

Guess that the next thing I’ll include is a propperty setter or more advanced caching than the simple property

I’ve decided to write a post for if not all the incremental versions of ProS then at least quite a few of them. My goal is to make addition to ProS and the rebuild ProS using those additions. The reasons for this approach are mainly two. I get a good idea of what’s working and what’s not and I might just get new ideas a long the way.

Reading a book written by the team who originally created SharpDeveloper (an Open Source IDE for c#) I learn the concept of “eating your own shit” as they called it. The Search and replace functionality had been lacking and at some point they realized that the developer doing that part of the IDE was him self using UltraEdit (or some other tool) when he needed to search and replace. With that in mind they decided that going forth they could only use SharpDeveloper for their development.

It’s the same thing I’m trying to do here, though my goal is not to make a Turing_complete. Actually I’m not sure it’s even Turing incomplete 😉 So writing all of ProS in ProS will not be an option.

The first version is little more than a configurable object factory. Except for things such as using, types and values there’s really only one contruct to the language: The constructor.

The cunstructor gives the option of creating what well end up being a method returning an instance of an object. The syntax is

constructor returnType Name(arguments) : objectType

{

statements

}

The constructor is a keyword say: “next is the definition of a constructor. arguments hav the c like syntaks: type name and multiple arguments a seperated by a comma.

Statements can in this version only be used for setting ctor (which is the term I’ll use for class constructors to not confuse them with ProS constrcutor and by the way the term class is intentional) arguments. A stament could look like

number = 10;

That would tell the ProS compiler that each time this constructor is call the value passed for the arument number to the ctor must be 10. The argument names must match ctor argument names as well, and there must be a ctor with a list of arguments that matches the total of arguments and statements.

A complete example could look like the below:


using
Irony.Compiler;
using
Motologi.ProSLanguageService;
using
Motologi.ProSLanguageService.Compilers;
alias
tokenCompiler = ITokenCompiler;


class
Compilers{
constructor
tokenCompiler Alias(AstNode node) : AliasCompiler {

}
constructor
tokenCompiler Using(AstNode node) : UsingCompiler{

}
constructor
tokenCompiler Argument(AstNode node, TypeEmitter typeEmitter) : ArgumentCompiler{

}
constructor
tokenCompiler ArgumentValue(int position, bool isForStaticMethod):ArgumentValueCompiler{
}


constructor
tokenCompiler Class(AstNode node, TypeEmitter typeEmitter):ClassCompiler{

}
constructor
tokenCompiler Configuration(AstNode node, TypeEmitter typeEmitter):ConfigurationCompiler{

}
constructor
tokenCompiler Constructor(AstNode node, TypeEmitter typeEmitter):ConstructorCompiler{
}


constructor
tokenCompiler Identifier(AstNode node, TypeEmitter typeEmitter):IdentifierCompiler{

}
constructor
tokenCompiler Int(AstNode node, TypeEmitter typeEmitter):IntCompiler{
}


constructor
tokenCompiler Statement(AstNode node, TypeEmitter typeEmitter):StatementCompiler{

}
constructor
tokenCompiler String(AstNode node, TypeEmitter typeEmitter):StringCompiler{
}


constructor
tokenCompiler Type(AstNode node, TypeEmitter typeEmitter):TypeCompiler{
}
}

That class declaration is the inner workings of the ProS compiler ver 0.2. The result is two classes. One is called Injector and the other is called Compilers. The class Compilers is what is directly defined in the above code. For each of the construct there’ll be one static method on the class Compilers. The method will take the arguments listen in the argumentslist for the constructor and will return an instance of the type specified after ‘:’ I.e TypeCompiler for the last constructor.

The Injector class is nothing more than a container. For all the constructs defined in all classes there’ll be an over over of a method called Get. In essence it’s a large factory that given an ID and a set of arguments will return an object.

In contrast with say Windsor’s ServiceContainer or similar in other reflection based frameworks the list of arguments is type checked compile type.

The approach of compiling the dependency configuration does impose some other (sometimes strange) issues. So the gain in type safety and performance is not for free. But some of those issues can be resolved with delayed compilation. So that the types mentioned above wont be created until runtime. I have a plan of adressing just that in a later version of ProS. For now I’ll dig into ProS ver 0.2 using the above configuration