AjLisp: a Lisp interpreter in .NET

I’m a fan of writing interpreters, specially Lisp ones. My first Lisp interpreter was wrote in early 80s, using 808x Intel assembler language. Yes, it was a very geek work. Once of the tricky things to implement in such interpreter is the garbage collector. Since mid 90s, we have Java language and class library, as a main stream technology with a decent garbage collector. This century, .NET is the new language platform to use with GC.

In 2005, Martin Salias and me gave a TechNight session,  here, at Buenos Aires, Argentina, at Microsoft local office, about languages written using .NET. It was the first time I presented F#, P# and other interesting language implemented using the .NET framework. After that session, I traveled to Mar del Plata, to give another session about ASP.NET. It’s a beatiful city, in front of the Atlantic ocean, a city I arrange to visit every year. During the trip, AjLisp was born.

It was an Lisp-like interpreter written in VB.NET. This last weekend, I ported it to C# (I use a SharpDevelop menu option to translate VB.NET to C# code, do you know another tool?). The original code was used some weeks ago at my post about VPL:

Lisp-like interpreter using DSS and VPL

The new C# version is published in Google Code at:


I like Google Code: it has support for SVN, then I’m using my local TortoiseSVN client to commit the change to the project.

The solution

It has three project:

AjLisp: the core project, a library, that can be invoked from your application.

AjLisp.Tests: all test fixtures, using NUnit 2.2.8. If you don’t use NUnit, you can remove this project from the solution.

AjLisp.Console: a simple console interface.

The types

The base interface are IAtom:

public interface IAtom { bool IsAtom(); }

and IList:

public interface IList { SymbolicExpression First { get; set; } SymbolicExpression Rest { get; set; } bool IsList(); }

All types then derive from SymbolicExpression:

namespace AjLisp.Types { public abstract class SymbolicExpression : IList, IAtom { ....

I implemented the common types used in Lisp, like List, Atom, Identifier, Function (to invoke primitives or lambdas), True, Nil…:

An Environment class is provided to keep values under names. Each environment can have a parent environment, so we have a chain of them.

The Interpreter class is the main one: it has an Environment and defines some names for initial primitives:


public class Interpreter { private Environment environment = new Environment(); public Interpreter() { Define("nil", Nil.Value); Define("t", True.Value); Define("cons", new SubrCons()); Define("first", new SubrFirst()); Define("car", new SubrFirst()); Define("rest", new SubrRest()); Define("cdr", new SubrRest()); Define("list", new SubrList()); Define("quote", new FSubrQuote()); Define("append", new SubrAppend()); Define("cond", new FSubrCond()); Define("atom", new SubrAtom()); Define("eval", new SubrEval()); Define("null", new SubrNull()); Define("lambda", new FSubrLambda()); Define("progn", new FSubrProgN()); Define("flambda", new FSubrFLambda()); Define("nlambda", new FSubrNLambda()); Define("mlambda", new FSubrMLambda()); Define("numberp", new SubrNumberP()); Define("functionp", new SubrFunctionP()); Define("idp", new SubrIdP()); Define("define", new FSubrDefine()); Define("definef", new FSubrDefineF()); Define("definen", new FSubrDefineN()); Define("definem", new FSubrDefineM()); Define("eq", new SubrEq()); Define("if", new FSubrIf()); Define("let", new FSubrLet()); Define("lets", new FSubrLetS()); Define("set", new SubrSet()); Define("consp", new SubrConsP()); Define("less", new SubrLess()); Define("greater", new SubrGreater()); Define("plus", new SubrPlus()); Define("difference", new SubrDifference()); Define("times", new SubrTimes()); Define("quotient", new SubrQuotient()); Define("remainder", new SubrRemainder()); } ....

You can write your own primitives and add them to this constructor.

The primitives

The interpreter has the usual primitives:

There are primitives that, before evaluation, evaluate their arguments. They are classes deriving from Subr:

public abstract class Subr : Function { public abstract SymbolicExpression Execute(SymbolicExpression args, Environment env); public override SymbolicExpression Apply(SymbolicExpression form, Environment env) { return Execute(form.Rest.Evaluate(env), env); } }

form.First is the function, and form.Rest is the list of arguments. To evaluate the form, Function uses an environment object.

Other primitives don’t evaluate the received arguments, they are FSubr:

public abstract class FSubr : Function { public abstract SymbolicExpression Execute(SymbolicExpression args, Environment env); public override SymbolicExpression Apply(SymbolicExpression form, Environment env) { return Execute(form.Rest, env); } }

One of the most interesting primitives, is lambda implementation, named FSubrLambda:

public class FSubrLambda : FSubr { public override SymbolicExpression Execute(SymbolicExpression args, Environment env) { return new SubrClosure(args.First, env, args.Rest); } }

It creates a Closure, a way to have to remember the current environment in a future invocation of the lambda expression. I implemented NLambda, FLambda, MLambda behavior: N stands for NonSpread (it manages the list of arguments as one argument), F means the arguments are not evaluated prior to invocation, and M is for Macro (I have to test and rewrite this functionality).

The tests

All functionality is covered by test. I configured the AjLisp.Tests library project to run NUnit GUI:

The console

AjLisp.Console is a simple console program. You can enter and evaluate sexpressions:

It is so simple, that you must close it using Control-C ;-).

Next steps

I want to improve some points:

  • Rewrite some classes and base interface
  • Manage and invocation of .NET native objects
  • Real and Integer treatment (using double dispatch to evaluate arithmetic ops, now they are used as double values)
  • Macro expansion
  • Better console
  • Some library examples
  • A minimal manual

The idea is to extends this mini language to be used as the basis for a distributed agent programming language. It should be nice to port to Java. Then, the agents behavior and state could be written in this language, and it could travel to other nodes in a grid.

But I’m dreaming. For now, this is current status: it’s working, and I had fun written this stuff. Enjoy it!

Angel “Java” Lopez

13 thoughts on “AjLisp: a Lisp interpreter in .NET

  1. Pingback: Closures in F# « Angel “Java” Lopez on Blog

  2. Pingback: AjBasic: an open source Basic-like interpreter « Angel “Java” Lopez on Blog

  3. Pingback: Closures en F# | Buanzolandia

  4. Pingback: Closures en F# - Angel "Java" Lopez

  5. Pingback: La inteligencia artificial y yo | Buanzolandia

  6. Pingback: Artificial Intelligence links and resources « Angel “Java” Lopez on Blog

  7. Pingback: Lord of the REPLs (Read Eval Print Loops) and CodePad « Angel “Java” Lopez on Blog

  8. Pingback: Lord of the REPLs (Read Eval Print Loops) y CodePad - Angel "Java" Lopez

  9. Pingback: AjLisp family: implementing lisp interpreters in C# « Angel “Java” Lopez on Blog

  10. Pingback: La familia AjLisp: implementado intérpretes Lisp en C# - Angel "Java" Lopez

  11. Pingback: Refactoreando AjLisp: un intérprete Lisp escrito en C# - Angel "Java" Lopez

  12. Pingback: Closures: Links, News and Resources (1) « Angel “Java” Lopez on Blog

  13. Meghan

    I’ve been browsing online more than 2 hours today, yet I never found any interesting article like yours. It is pretty worth enough for me. In my opinion, if all webmasters and bloggers made good content as you did, the net will be a lot more useful than ever before.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s