Stack Storage and Garbage Collection

Recently, I ran across Mike Vanier’s page containing his opinions on Scalable Computer Programming Languages. I agree almost entirely with his list:

  • garbage collection
  • no pointers or pointer arithmetic
  • a foreign function interface to the C language
  • static type checking with type inference
  • support for exception handling
  • run-time error checking for errors that can’t be caught at compile time, like array bounds violations and division by zero
  • support for assertions and design by contract
  • a powerful, statically checked module system
  • support for object-oriented programming
  • support for functional programming
  • structural macros
  • support for components
  • a simple, consistent and readable syntaxn

But I do want to pick on garbage collection.

A couple weeks back I was implementing the Parser for the compilers class I’ll be teaching in fall. I want the Parser to print out which grammar rules it called during recursive descent, so that I can use that output as a check on student implementations.

Because the implementation is in Java, I resorted to calling two functions in each grammar method: enterRule(String rule) and exitRule(String rule). The call to exitRule is necessary for tracking indentation level in the output.

What I really wanted was a decorator, that would automatically intercept calls to the grammar methods inserting an enterRule and exitRule. I attempted to accomplish this via reflection, but gave up when I discovered that the compiler optimizes the self-dispatch to recursive methods (when one grammar rule calls another).

Had this been C++ I would have implemented a scope guard object. It’s constructor would make a call to enterRule, and the destructor would call exitRule. I don’t trust this pattern in Java though, because it doesn’t provide a distinction between heap-allocated and stack-allocated objects. The call to exitRule, must be made at the time the grammar rule exits, which happens to coincide with the time a function-scope stack-allocated object destructs.

So I would add some detail to the above list: Either I need compile-time, type-checked decorators, or I need the language to distinguish between allocations on the stack vs heap. I’m fine if the garbage collector non-deterministically destructs heap-allocated objects, but I want stack-allocated objects to destruct at the time their scope pops.

Even better: maybe the ideal language would provide some statically verified mechanism for aspect-oriented crosscuts.