Is it safe to have an ordered tyvar without equality?


Think about

let h f =
	let r = f 3 4
	in let h = f 7
	in r + h 2

Do we somehow need to have two different versions of f inside h?



We have to be careful with error messages involving hofs.
If we have "h f x" where f has the wrong type we get messages
like "found string, needed int" where we should really have
"found string -> int, needed int -> int".  Similar things 
happen for arrays.


If you have mutually recursive (or even nonterminating) functions
then they have polymorphic return type.  If we actually use one 
of these then the return type should be unified with a ground type;
however, this doesn't happen, so the functions are eliminated. 
Why does this happen?

What about v==>w for lamargs in Normalise?

What about lambda-lifting functions inside classdefs?  There's some
code to deal with this,  but it may put the lifted version in the wrong
place.  People probably shouldn't be using hofs inside classes anyway.

In Lam.sml, can we have mutually recursive lam$ functions? Probably not.

In NAsyntval.fixExp,  should recursive applications of functions
be marked as LOCAL?  What happens if we have partial recursive
applications?  Be careful in Lib.sml,  where several things are marked
as LOCAL that are strictly GLOBAL;  maybe this gets fixed in NAsyntfn.

Do something about adding the error function.  This
may be related to the problems we have with non-terminating
functions with types like int -> 'a.

Bug in Type.reconVal or Mono.monoVar:  consider

  type t = X of int
  let q h = ()
  let g k = X(k)
  let eval p =
	match p with X(q) -> 
	  match g q with X(t) -> t

In reconVal, q wasn't given a MONO annotation;  but then 
in monoVar there's a check whether q is a function arg.
Here it isn't, so we look it up using getFunty and assume
it's a local if we don't find it.  But in this case we DO
find it since there's a global called q so we go on to the
second case, which calls getMono, causing an error.
The same thing happens with 

  let eval p = let q = 7 in match g q with X(t) -> t

I've patched this up (temporarily) by giving all locals 
an empty MONO annotation in Type.reconVal.  This still
causes errors because we try to monomorphise functions
when we shouldn't. (Gosh:  I'd already realised that
we had to deal with this -- see below -- but my supposed
fix didn't work, probably becuase I didn't deal with locals
properly. *)

---
Can still end up with unused registers in Grail occasionally;
things like "let val k = c val t = k" with k never used.

---

Problem with supermakers : try "camelot -a1 Class".
Does normalisation do the wrong thing??

---
If you define map but never apply it then the associated
datatype will have no entries.  Warning?

---

(Fixed, but just in case we delete it)
In Mono.monoVar, need to check if x is arg because of stuff
like "let app f r = ..." where there's a global function called f

----

Do we really have to eliminate polymorphism if we only have 
one diamond type? 
-- YES: need different getfield/putfield instrcuitns for real/float/ref

Trying to fix the type problem.
recon' contains a call to resolveType.  Why is this?
In the id id example, we have "let t0 = id id in t0 ..."
recon gets a reasonable type '5 for id id,  but then
resolveType changes it back to the global type of
id: '2 -> '2.



map still fails: Mono problem??
Put some stuff in monoFuntype to deal with this.
Check this again.
Oh dear.  It has to do with "let m = map in m f (m g l)"



(Nonterminating) mutual recursion stil fails

Still a problem with over-applied functions (wrong apply$ method)

---------

We probably need to get monomorphisation to 
monomorphise type ascriptions.

---------
Consider this:

(* Program 1 *)

let add x y = x+y

let main args = 
	let t = add 7
	in print_int_newline (t 4)

(* Program 2 *)

let update f x a y = if y=x then a else f y

let test () = 
	let u1 = update z 1 "dog"
	in let u2 = update u1 2 "cat"
	in let u3 = update u2 3 "badger"
	in let u4 = update u3 4 "elephant"
	in let u5 = update u4 5 "wombat"
	in let u6 = update u5 6 "eric"
	in let u7 = update u6 7 "fox"
	in let u8 = update u7 9 "weasel"
	in update u8 44 "ferret"

let main args =
	let n = int_of_string (get args 0)
	in let f = test ()
	in print_string_newline (f n)


(* end *)

In program 1 we want 'add 7' to return T1_add(7),  which is then assigned
to t and later evaluated.

In program 2 we want test() to create an object T1_update (...) which is 
then returned and bound to f.  We don't want it to return T1_test(()).
That'll probably defer the creation of the T1_update object until
f is actually applied,  which we don't want since it'll (maybe?) 
repeat the computation every time f is evaluated.  Anyway,  it doesn't work.

----

idid.cmlt still doesn't quite work.
But that's down to the typechecker giving the wrong types.
(same for map)

Clean up the horrible mess that I've made of the application functions.


Can we ever have type t$ = T_f of t$2 * t$2 ???
Yes:  consider compose: (i->i) -> (i->i) -> (i->i)

mut.cmlt no longer compiles because of polymorphic return type

Monomorphisation still has problems:  look at app2.cmlt

Also trouble with eg "let add3' (x:int) = add3 4 5"

Need to think about updating types:  it's a bit like Brian's monomorphisation 
problem.

Need deeper defunctionalisation

Consider an application 'f g h ...' with g a polymorphic function.
Monomorphisation (maybe) won't spot the g has to be monomorphised.
OOPS:  the code for doing this was commented out.  WHY???
Because it runs into problems with stuff like ?t2.


Can aliasing ( eg 'let t = f in  ... t x ...') confuse monomorphisation?
[Probably not, now that we've got the LOCAL extern value]

Bad let-floating for some examples [So re-float]
Need more args for hofs [OK]
Need functions of high higher order
The procedure for rebuilding funblocks is fucked
Use lambda-lifting to eliminate LAMvals during normalisation 
(then we won't need LAMval in Normsyn)



====

The == for boolean eqaulity is confusing lfd_infer

For some reason Steffen's program sorts constructors into
alphabetical order.  This is problematic when we read rich
types back into the Camelot compiler.

====
Three versions of absyn (Normsyn, asdl version, Michal's Haskell version)
all have slightly different ideas of locations.

Actually, -od doesn't work. (fn names missing in contexts: could be
my fault)

====
Look at getTypeSuffix and understand exactly what's going on;
coalesce it with getConSuffix.


If someone writes a function called f_1 and a polymorphic function
called f then monomorphisation may generate another function called
f_1.  Presumably a similar remark applies to types.

====

I've now rewritten Mono to keep a lot of stuff in hash tables
instead of using accumulators;  maybe we could speed up
typechecking by doing the same thing for type constraints in
Type.sml.  On reflection, this may not work:  look at the 
code for type reconstruction for IFexp for instance.

=====

I've put in checks for escaping types variables in type
delarations,  but there are still problems with unused 
variables in mutually recursive types (it's not 
syntactically obvious that type vars aren't ultimately bound).

======

There are still problems with free type variables in type 
definitions: consider

type ('a, 'b) t = A | B of ('a,'b) t

let f x = match x with 
	A -> 0
 | B (n) -> 5

let p () = f (B(A))

See a similar problem below

Weed out polymorphic values early (prevent fns with polymorphic
return type)

If you define two methods with the same name and identical 
argument types but different return types then you get an
odd error message.  This error should be checked for explicitly.

======

* It would be useful to have a global function somewhere which
  would tell you if a constructor is heap-free.  Code to do this
  appears in several different places.  This might be a little more
  difficult than it appears since monomorphisation can produce 
  extra type definitions.

======
* method 
   m (a: string list) : unit = exp
  gives that there is no applicable method for obj#m["x"]
  Change typechecker's method types thingy, probably need to change
  monomorphisation too.

* Something odd happens with 
   type ('a, 'b) t = A | B of 'a t

* When we're defining local fns in Phi.sml,  do we really need to supply
  them with the list of all local variables?  maybe we can do away with
  this now that we have sensible arglists.

=======
* Should string = java.lang.String in all contexts? Should we be able
  to do "foo".length(), i.e. should string be just an abbreviation?

* Perhaps represent Camelot classes with Java inner classes (well,
  nested top-level classes). Work out how to call Camelot code from
  Java, invoking methods in Camelot classes works fine but they may
  then not refer to code from the main program. Possibly we should
  also allow functions to be local to a Camelot class to let us write
  libraries in Camelot.

* Report the use of deprecated classes, methods and fields

=======
* We probably need to get the lexer to spot stuff like
  "int list".  This might be unpleasant because we won't
   know the name of the type until after monomorphisation.
   Also, what about "unit list", "unit array" etc.?
   ???? WHAT IS THIS SUPPOSED TO MEAN ????

* Phi has problems with "if e then ..." when e is too complicated.
  Eg,  
	if let y = f(x) in y=0 then ...
  doesn't go down too well.

* Something odd happens with 
   type ('a, 'b) t = A | B of 'a t

* When we're defining local fns in Phi.sml,  do we really need to supply
  them with the list of all local variables?  maybe we can do away with
  this now that we have sensible arglists.

* If the user gets the type of "start" wrong then the
  error messages aren't very helpful because they occur
  in invisible functions.  We could add a constraint
  for the type of the start function, but this is tricky
  because we don't know in advance the name of the type
  to which string list monomorphises.

* Look at Phi.matchResult - maybe some dodgy code left over

* Do something about higher-order functions.

* There's still a bug in gdf wrt checking arguments.  Now that 
  we have good arglists generated by the Camelot compiler
  maybe this can be fixed.

* In most cases we don't need a dedicated link field in the
  diamond class.

* Stephen's modules.

* Typechecking problem for constructors:  see CHANGES.

* Fix match statments so that they only extract fields which are 
  needed.

* Implement "make" and "empty" for arrays properly.

* Errors in Phi and Mono don't have locations.

* Diamond.getDiamondName has a nasty fix to deal with
  the handling of "free" in Perv.sml.  This needs to be
  fixed anyway,  but it'll cause trouble if we ever use
  multiple diamond types.

* where String array instead of int array is found, error is confusing:
  An expression of type
    int
  was found in a context where an expression of type
    string
  was expected

* This is related to the confusing error message for function arguments.
  A single constraint is generated for the entire function type,  and
  when unification fails the error message points to the whole arglist. *)

-----------------------
DONE:

* Need typed identifiers for things like
   let f (x:int) = ...
  but this'll need a new term in the absyn.

* No built-in lists. Now semi built-in.

* There's a nasty bit in Diamond.tyToGTy where free type variables
  are instantiated to string arrays;  this is to fix a problem
  with the type of main,  but causes unpleasant errors when functions
  have unused arguments.

  Maybe this is now OK

* Remove inner class names from abstract syntax?  Perhaps only
  insert them at the last moment.

* Fix unit/void problem.  Maybe.

* Fix monomorphisation.  (Polymorphism + Michal's bug)

* Typecheck ! annotations. In progress.

* Linearity checking (including a check that arguments to
  "free" aren't used subsequently). Partially done.

* Problem with booleans and ints. I don't understand it!
* It's fixed now.

* Make sure that comparisons work with floats as well as ints.

* Be careful where we allow constructors:  stuff like "if x=A then ..."
  should be disallowed.
  - Done: = now only applies to integers.

* Units in datatypes: seems to be OK,  but I had problems earlier.
  - Added explicit check for this is Syncheck
  
* Unused polymorphic arguments can pass through monomorphisation:
   let f x y = y let main a=print_string_newline(f[](get a 0))
  So can ones which are used:
   let f x = x let main args=let _= f[]in()
  Solution:  (a) ignore it; (b) print a message suggesting that 
  the user should add type annotations; (c) ?
  - dealt with this by (b).

* mosmldep doesn't find some hidden dependencies? (open?)
  - The problem is that if you say

      local structure A = Absyn in ...

    in Perv.sml, say, then mosmldep doesn't spot that Perv depends
    on Absyn (according to the manual this is deliberate,  for 
    backward compatibility).  I've "fixed" this by putting 
    "val required = ()" at the top of things like Perv.sml. Now
    you can say

	local
	   structure A = Absyn
           val () = Absyn.required
 	   ...

    and the dependency will be found.

* Syncheck:  can write "match x with A(n)@n -> ..."
  - Added check for this

* How should we deal with funblocks in Mono???
  Maybe we don't need to do anything.  After we've monomorphised
  there's no problem (???) with mutual recursion,  so we can
  safely put each function in its own funblock.  
  But can we?  Is there no danger of functions being declared in
  the wrong order after monomorphisation?
  That didn't seem to be happening.  Anyway,  I put in some code to 
  reorder the functions after monomorphisation.
  - Now there's some code to reassemble minimal funblacks after 
    monomorphisation and arrange them in a reasonable order.

* This is strange:  if you have

   type ('a, 'b) p = Pair of 'a * 'b

   let f p = match p with Pair (x,y) -> g x
   and g x = f (Pair(x,x))
   and h n = n+1

   let start args = g 7

  then it compiles and runs successfully,  with g having type int -> unit.
  How does this happen??
  - Ahah.  It's because start has return type unit.

* Got rid of all the funtys in Type.sml
* Did lots of stuff to syntax printing/parsing to 
  get compiler to reingest OO programs 

* Still something odd about local var consolidation.
  Look at contains.cmlt
  It's the tail-call optimisation: if you have 
   let f (a,b,c,d) = ... in f (a+1,b,c,d)
  then code gets generated to shuffle b,c and d about.

  - Changed Optimise.sml to avoid this.  Did I introduce any new problems?

*  Problem with local var consolidation: try 

   type t = T 
   let len x = match x with [] -> 0 | _::t -> 1+len t
   let app f l = match f with T -> len l
   let main args = print_int_newline (app T [1;2;3;4;5;6;7])

   (l gets replaced by f at some point)

   >>>> THIS IS NOW OK:  but when we have [1;2;3;4] eg we get 

   val r1 = ...
   val r0 = ...
   val r1 = ...
   val r0 = ...
 
 - This should be correct now.  The first problem was caused by the 
   fact that method arguments weren't being made to interfere with 
   each other, and so could be merged.  The second problem lay in
   the interference procdures, where live-in variables were being
   used in a context where the live-out ones should have been used.

* We should probably allow stuff like "fun x y -> x+y" .  This shouldn't be
  too hard.  

  - It wasn't


* Mono problem: try 

	let m = map
	in let w = m (add 7) (m mul2 iargs)

  The monomorphisation procedure doesn't know that it 
  has to generate a monomorphised version of map.

  - Now it does,  but we don't allow polymorphic let-statements
    (eg,  if we put "let m = map in ..." then m must only be used
     with a single type in "...")


* Where does the freelist get initialised to null?
  Do we need a class initialiser?

  - Static fields are initialised to zero values when the class is loaded.


* HO fns with unit args give datatypes with unit args,  then error.

  - Datatypes with unit args are now permitted.


* It's tempting to make 'u name = string * 'u.
  This might be a little tricky since there are places
  where we compare names for equality and this might
  fail for the same name in different places.

  - I've now done this and it appears to be OK.


* Type.typeProg returns something called funTys.
  It appears that this is never used,  so it might be safe to
  get rid of it.

  - It's gone now. It also returned cnames'; that was passed to 
    Mono.monomorphise, but then never used.
