My pet project Casper has come quite a long way since I’ve last written about it. For a long while, I was quite stuck, and being busy with school, work, and such, I shelved the project.  Eventually, during a hacking spree of sorts, I figured out a way to more elegantly pass function parameters. From there, things sort of snowballed. Various small improvements came from using Shark to analyze the code. The biggest improvement came from the new memory allocator and collector. That’s right, Casper now uses the Hans-Demers-Weiser Garbage Collector to manage memory, albeit naïvely. This has gotten the execution of the recursive fib down to something under two tenths of a second on my machine, depending on the compiler optimizations you use. In my tests, this is faster than any other interpreted language I know of, including Lua, my golden standard.

As I said earlier, features just started snowballing after a certain point. I’ve decided to write the standard library for Casper entierly in Casper itself, using certain macros I’ve termed VMBuiltins (these begin with a dollar sign) to access really low level VM bits. This method has a certain charm to it, and allows me to work quickly without recompiling a whole bunch of C++. Most recently Casper has gained syntax and code emission support for ‘for’ blocks. A couple of bug fixes, and new parser support has lead to an iterative version of the fib program I’m so very fond of.

def print(int)
	int
	$PrintInt
end

def fib(x)
	a = 1
	b = 1

	for i = 3, i < x+1, i=i+1 in
		c = a + b
		a = b
		b = c
	end

	b
end

def main()
	print(int: fib(x: 40))
end

-------------------------------
time ./casper tests/fib/iterative_fib.cas
102334155

real	0m0.017s
user	0m0.001s
sys	0m0.003s

It’s almost enough to make me want to cry. I spent the better part of a year improving recursive dispatch performance, and this iterative version seriously hits the problem out of the park. I suppose it really is all in the algorithm you use!

I’ve also spent a considerable amount of time in code cleanup. For example, all Ariel bytecode is now automatically generated using X-Macros from a single definition file. In terms of forward thinking, I’ve also introduced Boost as a dependency. BOOST_FOREACH is a godsend on its own, but I’m also looking for ways to further its reach. It’s a great library; I hope that this makes a number of potential problems just disappear.

Looking to the future, I’d like to work more heavily on a custom garbage collector and memory allocator. I’m interested in using LLVM to output native machine code (there’re already hooks in the VM to switch into native code). Using boost, I plan on first making use of boost::program_options to clean up the driver. Also, serializing the parsed programs using boost::serialization may become a bigger win as the parsing and AST manipulation become more complex. Finally, I want to work on error reporting and the standard library for the new year. I’ll keep you posted.