Camelot library functions and built-in datatypes and operators 
==============================================================

Here are some predefined Camelot functions.  Some of these are built
in and some correspond to Java methods in Camelotlib.class.  The names
(which are mostly the same as the OCaml equivalents) are generally
self-explanatory.  If one of these functions is called with a bad
argument (like int_of_string "seventythree") then it'll usually
print out an error message and halt the program;  it's possible
that some errors might escape as Java exceptions. 

If you want to make your own library function then put the Java
version in Camelotlib.java and then look in Perv.sml.  There's a big
list near the end  which tells the compiler how to convert Camelot
functions into Java method calls, and you have to put a new entry in
there.  The entries consist of quadruples (Camelot function name,
[Camelot argument types], Camelot return type, Java name): look for
print_string for an example.  If you get this wrong you might get an
"incompatible class change exception" or something similar. 
Remember to rebuild the compiler after adding stuff.

Note that things in Camelotlib can't refer to Camelot datatypes since
you have to know the layout of the diamond class to do this, and this
isn't determined until compile time. Instead, it is possible to define
library functions in Lib.sml, which are compiled just like normal
Camelot functions, and hence can use datatypes (but must be written in
Camelot abstract syntax).

Datatypes
=========
Standard datatypes are defined in Lib.sml. At present these are:

type 'a list = !Nil$ | Cons$ of 'a 
type 'a option = !NONE | SOME of 'a

Standard list syntax is converted at parse time to use of the list
datatype as defined above. 

Printing
========

print_int: int -> unit
print_float: float -> unit
print_string: string -> unit
print_char: char -> unit

print_newline: unit -> unit
print_int_newline: int -> unit
print_float_newline: float -> unit
print_string_newline: string -> unit
print_char_newline: char -> unit


Conversions
==========

int_of_float: float -> int
float_of_int: int -> float

int_of_string: string -> int
string_of_int: int -> string

float_of_string: string -> float
string_of_float: float -> string

string_of_char: char -> string

code: char -> int
    Return ascii code of character.  This can also be written as "int_of_char".
chr:  int -> char
    The inverse of "code".  This function can also be written as "char_of_int".


String operations
=================

string_length: string -> int
append_string: string -> string -> string
same_string: string -> string -> bool
   Returns 'true' if s and t are identical strings, otherwise false.

string_compare: string -> string -> int
  "string_compare s t" is -1 if s precedes t lexicographically, 0 if s and t
   are identical strings,  and 1 otherwise.

substring: string -> int -> int -> string
  "substring s a l" is the substring of s of length l starting at position a.
  The first character of s is at position 0.  A runtime error will occur if
  the position or length is out of bounds.

getc: string -> int -> char
  "getc s n" returns the nth character of s,  starting from 0.


Characters and strings
----------------------
    Literal characters are enclosed in single quotes.  Various
    escape sequences can be used,  including '\n', '\t' and '\a'. Also,
    '\nnn' can be used to obtain the character with decimal (not octal) 
    ascii code nnn.  These escape sequences can also be used in strings.
	
    No comparison operators are provided for characters,  so "code" must be
    used to convert characters to integers for comparison.  For example

    let isAlpha c = (code 'a' <= code c && code c <= code 'z')
		 || (code 'A' <= code c && code c <= code 'Z')


    let isSpace c = code c = code ' '

    This isn't as bad as it looks.  Camelot represents characters by integers
    and "code" is just there to keep the type system happy.  The above compiles
    directly into integer comparisons.



File input
==========
  A Camelot program can read input from files.  Only one file can be open at 
  a time.  Due to Java restrictions it doesn't seem to be possible to open 
  standard input in such a manner that eof can be detected before reading
  (you have to try reading a line and if you get null you're at the end,
  but we can't deal with this in Camelot).  This means that input can only 
  be taken from a file,  and not from standard input.

  All output takes place to the standard output.

open_input: string -> unit
  Open the named file for input.  An error will occur if a file is already open.

close_input: unit -> unit
  Close the currently open file.  Another file can then be opened if required.

eof: unit -> bool
  Return 'true' if the end of the current file has been reached, 'false' otherwise.
  An error will occur if no file is open.

read_line: unit -> string
  Read a line from the current file,  discarding the newline at the end.
  An error will occur if the end of the file has been reached,  so calls
  to read_line should be preceded by a check that eof() is false.

read_char: unit -> char
  Read a single character from the current file.  The file is regarded as 
  a stream of bytes,  so read_char may return '\n' or other control characters.
  Again,  use eof() before read_char.



Array Operations
================

empty: int -> 'a -> 'a array
   'empty n x' returns an empty array of length n,  depending only on the type of x
   (the value of x is ignored).  I wonder what happens if x is a member of some
   user-defined datatype?

make:  int -> 'a -> 'a array
   'make n x' is supposed to create an array of length n with all entries initialised
    to x,  but it's not implemented.

arraylength: 'a array -> int
get:   'a array -> int -> 'a
set:   'a array -> int -> 'a -> unit
