So I'm hand-writing a parser for something, and I wanted to use a design
pattern that automates some of the backtracking. Basically, I'm parsing
from an indexible sequence of tokens. If a sub-parse fails, I want to back
the input token index up in parallel with backing up the parse stack. The
following code would work:

class Parser {
  ParseSomeNonTerminal(...)
  {
    int tokPos = m_tokenPos;
    try {
      var first = ParseFirstThing(...);  // may throw
      var second = ParseSecondThing(...); // may throw

      // success
      return new SomeAST(first, second);
    }
    catch {
      m_tokenPos = saveTokPos;
      throw;
    }
  }
}

But it's a lot of crud to have to write for a repetitive pattern. If this
pattern is pervasive, it seems more compact and more readable to do
something like:

class Parser {
  ParseSomeNonTerminal(...)
  {
    using (var marker = new InputMarker(tokenStream)) {
      var first = ParseFirstThing(...);  // may throw
      var second = ParseSecondThing(...); // may throw

      // success
      marker.disarm();
      return new SomeAST(first, second);
    }
  }
}

and then use the Dispose() method of the InputMarker class to do the
unwinding. Note that what I *really* want here isn't quite "using", because
I only want to unwind the pointer if an exception is thrown, but C# doesn't
have a convenient shortcut for that.

But what I stumbled into here is a sneaky issue concerning the relationship
between IDisposable and finalization. This is a use case where we want the
Disposable pattern (because of the using clause), but we do *not* want
finalization. I really want a stack-based canary pattern here. If a marker
ever gets a finalization call, something is desperately wrong.

In later versions of BitC, when I was introducing the mixfix support, I
decided that the block construct { ... ] should be treated as a thunk (a
function taking no arguments). In that scheme, The semantics of LET is "IN
(environment extended with bindings) EVAL body-thunk".

The cute part of this is that something like USING becomes something you
can specify in the mixfix engine, which totally removes it from the core
language.


shap
_______________________________________________
bitc-dev mailing list
[email protected]
http://www.coyotos.org/mailman/listinfo/bitc-dev

Reply via email to