I've been making substantial progress over the last couple of days, which is a welcome change after a couple of frustrating months.
The last few months have seen a lot of hard effort, with very little to show for it. I'd been focused primarily on getting debugging working - being able to inspect Tart data structures in the debugger. Unfortunately, it seems that LLVM's facilities for generating debug information aren't very robust - if you make even the smallest mistake in calling the debug factory functions, it will silently write out bad debugging data without telling you. In addition, the available tools for inspecting and checking DWARF debugging data are very primitive, producing at best a raw text dump of the debugging structures, requiring you to manually trace the cross references between debug entries. Nor is gdb particularly helpful in terms of it's error messages. Add to this the fact that DWARF itself is extremely complex, and that even a small program will produce many kilobytes of debugging data, and you can begin to see why it takes so long to get this stuff right.
The key to breaking this logjam was my attending of the LLVM developer's conference last week. I was able to talk directly to the people working on the parts of LLVM that deal with debugging info. I was able to clarify a number of critical points which I had not been able to do over email conversations. (I've noticed that any email question sent to the llvm-dev mailing list has approximately a 50% chance of being answered, so getting answers takes persistence.)
It took me a few days to be able to apply everything that I learned at the conference, with a lot of trial and error involved. During this time, I was at the Hacker's Conference, and I spent about half my time at the conference staring at my laptop working on Tart. Although I felt bad about not paying attention to the conference sessions, I really felt driven to try and get this stuff working.
As a result, the debug stuff is working much better. I can now set breakpoints, examine function parameters and data structures (although examining local variables is still not working).
In addition, I've also made progress switching over to the new, compressed reflection metadata. The old system has been completely removed, and the unit test framework has been switched over to use the new system.
In other news, I read last night on Slashdot the announcement of the
Gosu programming language, which has a lot of similarities to Tart. In fact, it's quite discouraging to me to see how many of my ideas have been developed independently - discouraging because they have a shipping product and I don't. That being said, there are a few things that I think they didn't get right, and a few things that seem faddish, but none of these are serious.
I think the biggest difference between Gosu and Tart is that Gosu targets the JVM, whereas Tart produces native binaries. I'm not sure which of those two paths will prove to be smarter in the long run. Obviously, it's a lot easier to write a new language for the JVM, since you get a lot of stuff for free - garbage collection, a huge class library, and so on. The benefits to producing native executables is more subtle - a quicker startup time, ability to run on platforms that don't have a JVM, and so on.
There are also a number of downsides to native executables - for example, a lot of stuff has to be pre-generated (like type adapter functions for reflection) which can be generated dynamically as needed in the JVM. This potentially makes the native executable much larger than the equivalent Java .class file. Also, there's no way to do HotSpot-style profile-guided optimization, which you could do with a JVM.
In any case, each time someone comes out with a programming language that is similar to Tart or fulfills a similar need (Go, Gosu, Scala, etc.), it means that the chances of Tart achieving any sort of widespread adoption gets smaller. Nevertheless, I'm not ready to quit yet... :)