[MLton] can mlbasis rename the top-level?

Matthew Fluet fluet@cs.cornell.edu
Tue, 6 Sep 2005 21:28:19 -0400 (EDT)


> Quoting Stephen Weeks <sweeks@sweeks.com>:
>>> Or take "}>}" as the closing delimiter.
>>
>> :-).  Yes, that definitely is easiest, for all tools involved.  I'm
>> fine with that if others are.
>
> I'm not convinced that implementation difficulty should be the most
> important concern.

It's not just work on the developers part.  The more complicated the 
implementation, the harder it is to get it right.  And, particularly with 
lexing/parsing, it is quite easy to get it wrong in ways that aren't 
particularly illuminating to the end user.

> I'd rather have a coherent language than one that
> is the easiest to parse.

That's a fair point, but I don't think that symbolic delimiters breaks the 
coherence in an unacceptable way.  I look at it from this point of view: 
the ML Basis System is there to provide a mechanism for programming in the 
very large, where you need a way to organize potentially conflicting 
name-spaces in libraries.  It is not there to be your default programming 
environment.  So, you pay a small cost (in this case, the visual 
delimiter) to use it for a secondary purpose.

> The MLB syntax already uses mostly keywords
> as delimiters. If symbolic delimiters are preferred, then is it really
> that much more difficult to use plain parentheses, ( and ), as
> delimiters like ML-Yacc does (but recognizing string literals and
> comments)?

>From the implementation point of view, no it isn't any more difficult. 
But, think of it from the user's point of view.  Suppose I have:

local
   $(SML_LIB)/basis/basis.mlb
   $(SML_LIB)/smlnj-lib/Util/smlnj-lib.mlb
in
(
   structure IntOptionRedBlackMap =
     RedBlackMapFn(type ord_key = int option
                   val compare = fn (x, y) =>
                                 (case (x, y) of
                                     (NONE, NONE) => EQUAL
                                   | (NONE, SOME y) => LESS
                                   | (SOME x, NONE) => GREATER
                                   | (SOME x, SOME y) => Int.compare (x, y))
)
end

Did you catch the unclosed parethesis?  If so, then you are a better 
reader than I.  (And, yes, emacs would give a hint as well.)  But, suppose 
you sent this to mlton.  What's likely to happen is that you completely 
throw the parser off.  Worse, if you had an extra close parenthesis in the 
middle of the SML code (i.e., ending the embedded SML early), then you're 
likely to have a horribly opaque MLB parse error pointing into the middle 
of what is manifestly SML code.

On the other hand, it's very easy to verify that {<{ and }>} properly 
delimit the SML code.  Concerns about those tokens appearing in the 
embedded SML in comments or string constants notwithstanding, it's really 
easy to lex the contents into string and let the SML parser have its way.

Similarly, if you try counting {local,let,sig,struct}...end blocks, an SML 
parse error might manifest itself as an inexplicable MLB parse error.

Yes, these would go away if you merged the grammars, but its not clear to 
me that you can even merge the grammars in a reasonable manner that 
handles the extra MLB keywords.