V10/cmd/sml/doc/differences

This file attempts to list differences between the Edinburgh compiler
and SML of New Jersey, as an aid to converting programs to run under
the new compiler.  Items that are likely to break old code are
annotated with "!!!".  The version of the Edinburgh compiler we have
used for comparison is quite old, and many of these differences may
not apply to the latest version.  Users who find other differences can
help keep this file up to date by sending mail to:

       macqueen%research.att.com@relay.cs.net


Pervasives

* The type of use is different; it is now applied to strings instead
  of string lists.  Users who prefer the old version of use can
  redefine it:
       val use = app use    !!!

* Structure Byte_array has been renamed ByteArray, and there have been
  significant changes in the structure itself, including renaming of
  functions to parallel those in the structure Array, and the addition
  of a new exception Range.  The new signature BYTEARRAY is defined in
  boot/perv.sig.  As before, ByteArray is not opened by default in
  the pervasive environment.  !!!

* Strings and byte arrays are not limited to 65535 characters as they
  were in the Edinburgh system.

* There have been significant changes in the IO interface.  The BasicIO
  and ExtendedIO structures have been replaced by structure IO, which
  matches signatures BasicIO and IO (signature ExtendedIO has been eliminated).
  The IO and BASICIO signatures can be found in boot/perv.sig.

* IO.input and IO.output are curried. !!!

* IO.can_input now returns the number of characters which can be read from
  an instream without blocking.

* List.exists has been curried. !!!

* List.@ now associates to the right.

* The type of exportML has changed:
       val exportML : string -> bool
  The string is the file to export to, and the boolean returned distinguishes
  between a new ML process (true) and the return from exportML (false).
  In the Edinburgh system, exportML returned the new process to top level;
  in our system, the new process takes up exactly where exportML would have
  returned to.

* The obsolete exception Varstruct is not supported; Bind should
  be used instead.  !!!


Core

* We use the new exception syntax.  !!!

* We use the new form of numeric record labels, for example {2=5,3=true}. !!!

* Record label abbreviations work only in patterns, not in expressions:  !!!
      val a = 4 val b = {a,c=3}    
	    does not work on our system, but these will:
      val a = 4 val b = {a=a,c=3} 
      fun f {a : int, c = 3} = ... 


Modules

* Functors may have free references to structures that are not parameters.

* Sharing constraints are now components of signatures.

* Functor parameter syntax is slightly different:  !!!
  Two styles of functor syntax are now supported.  The parameter list following
  the functor name in a functor declaration can consist either of a single
  structure name with a signature, or it can consist of a sequence of specifications
  like those in the body of a signature.  For example:
       functor F(X: sig structure A: SA and B: SB end) =
       struct
	 ... X.A ... X.B ...
       end
   or
       functor F'(structure A: SA and B: SB) =
       struct
	 ... A ... B ...
       end
  Corresponding functor applications would have the forms
       F(<strexp>)
   or
       F'(structure A = <strexp> and B = <strexp>)


All of the features above are documented in the manual (???).


Undocumented features of our compiler:

* val cd : string -> unit
   allows you to change working directories without leaving ML.

* val exportFn : string * (string list*string list -> unit) -> unit
   exportFn takes a string and a function, and exports the function
   to the file specified by the string.  Only the function itself and
   code it is dependent on are exported; this will be much smaller
   than the file produced by exportML (which contains the entire
   compiler).  The exported function will be applied to a list of
   command-line arguments and a list of the (Unix) environment on startup.
   Because exportFn "throws away" the compiler by forcing a special
   garbage collection, it never returns.

* Two functions are provided which allow the user to construct and
   execute ML code on the fly:
	    val open_string : string -> instream
	    val use_stream : instream -> unit
   use_stream is like use except that it is applied to an instream
   rather than a file name.  open_string converts a string to
   an instream.

* A structure System is present in the initial environment.  The structure
  contains special values used by the compiler, which for the most
  part should be left alone.  Two substructures may be of some
  use: System.Control contains a number of flags which control
	compiler behavior.  They are not documented anywhere,
	and some have unobvious functions, so it is unwise to play
	with those which seem cryptic.
       System.Timer contains some elementary timing functions.
  Both have signatures defined in boot/system.sig, and both are
  subject to change at any time.

* System.version : string
   a string identifying the version and origin date of the compiler.

* exception SystemCall of string
   may be raised by the functions system and cd, or in
   unusual failures of system calls.

* exception Real of string
   may be raised by generic exceptions like overflow
   encountered in floating point operations.

* exception Overflow
   is raised by integer overflow (bigints are not supported).