[MLton] mlb support

Matthew Fluet fluet@cs.cornell.edu
Mon, 26 Jul 2004 17:57:32 -0400 (EDT)


I've added preliminary support for warn-unused annotations to mlbs.  This
is the last item that I definitely wanted to support before merging.
Since there wasn't much response to Steve's MLton-user post on the def/use
flags, I'd like to propose dropping -show-basis-used and having
-show-basis print the basis of the input or derived mlb and having
-show-def-use print the def/use info for the whole program.

Here's how I'm currently exposing warnUnused annotations.  Suggestions
welcome.

In the external language, I have:
  ann := ...
       | warnUnused {true|false}
       | warnLocalUnused {true|false}

In the compiler, I have:
  structure WarnUnused : sig
     datatype t = No | Local | All
  end
  warnUnused : WarnUnused.t list ref

warnUnused defaults to [No] if -warn-unused false and to [All] if
-warn-unused true.  Note that this means that warnUnused will always be a
non-empty list.

Upon entering an annotation, warnUnused is modified as follows:

annotation             | effect
-----------------------|---------------------------
warnUnused true        | List.push(warnUnused, All)
warnUnused false       | List.push(warnUnused, No)
warnLocalUnused true   | List.push(warnUnused, Local)
warnLocalUnused false  | List.push(warnUnused,
                                   valOf (List.peek(!warnUnused, fn z =>
                                                    z <> Local)))

I'm not quite happy with the behavior of warnLocalUnused false; but I
don't know what would be better.  Unfortunately, "local" is a keyword in
the .mlb grammar.

During elaboration, if  List.first(!warnUnused) = No
then every extension of the environment forces the extension to be used.
This is done by modifying the newUses function in the generic extend
function of elaborate-env.fun to check the warnUnused control in addition
to the forceUsed argument.  Steve, is this the right place to do the
force?

Upon leaving an annotation that pushed a Local onto warnUnused,
everything that is currently in scoped is marked as used, using
ElaborateEnv.forceUsed.


This accomodates a few useful idoms.  A library to ship out the door would
probably be delivered as:

lib.mlb:
  ann warnLocalUnused true in
  ...
  end

warnLocalUnused should give warnings on unused function arguments, unused
val decs in a let exp, etc.  That is, things that are unused in their
locally defined scope.  Furthermore, it will quell unused warnings about
delivered elements that aren't used by the rest of the program.  This is
essentially how I would like to deliver the Basis Library, CML, MLton Lib,
etc.

On the other hand, I would probably migrate the sources.cm files in the
mlton sources to look like

ast/sources.mlb:
  ann warnUnused true in
  local
    ../../lib/mlton/sources.mlb
    ../control/sources.mlb
    admits-equality.sig
    ...
  in
    signature ADMITS_EQUALITY
    ...
  end
  end

This way, we keep some modularity, but will be warned if something doesn't
get used by the rest of the sources.
(Note that the warnUnused true won't affect the included .mlb files, since
they are elaborated in a clean annotation environment.)