[MLton] Re: exene example

Lukasz S Ziarek lziarek@cs.purdue.edu
Wed, 31 Aug 2005 16:22:36 -0500


Stephen Weeks wrote:

>Luke sent a large (>5M) email to Matthew, and it looks like Matthew
>resent it to the MLton list, at which point mailman complained because
>the message was too large.  Matthew approved it, and that hung mailman
>on mlton.org because python is slow as a dog.  I killed it, since I
>don't really want such a huge message to go out to the list 60 people.
>
>The discussion certainly belongs on the list, but huge examples like
>that should be placed at URLs or sent via email off list.  So, Luke,
>could you please resend your mail to the whole list sans huge example,
>and place the example at a URL (preferred) or email it just to
>Matthew.  Thanks.
>  
>
(here is a resend of the email, with some more examples added)

Mathew,

Here is the non working copy of eXene and a MLton with all apropriate 
changes to the basis and CML needed to build exene.  The main change to 
MLton was adding a packword16 functor (also the reason why i cannot 
compile with keep exception history true), its located where packword32 
is.  There are a few additions to CML which I will explain shortly.  To 
build a runable with exene, simply go to 
portExene/eXene/examples/triangle  and build the sources.mlb there.  To 
edit the triangles example edit mltontri.sml.  This verion of exene 
dumps a lot of output to the screen, what you are looking for is:


exenedebugphil: xio ending bc of SysErr txt=(Interrupted system call) 
msg=(Interrupted system call) name=intr)  thrown in xio

which is handled in eXene/lib/protocol/xio.sml

----
fun loop () = (
       CML.send (outCh, getMsg());
       loop ())
     in
           loop () handle LostReply => (print "exenedebugphil: xio 
ending bc of LostReply thrown in xio\n"; CML.exit())

                        | Fail(cause) => (print ("exenedebugphil: xio 
ending bc of Fail (" ^ cause ^ ") thrown in xio\n"); CML.exit())
                        | OS.SysErr (cause, SOME (err)) =>(print 
("exenedebugphil: xio ending bc of SysErr txt=("
                                                                   ^ cause
                                                                   ^ ") 
msg=("
                                                                   ^ 
OS.errorMsg err
                                                                   ^ ") 
name="
                                                                   ^ 
OS.errorName err
                                                                   ^ ")  
thrown in xio\n"); raise OS.SysErr (cause, SOME (err)))
                        (*| _ => (print "exenedebugphil: xio ending bc 
of some other exn thrown in xio\n"; CML.exit())*)
     end
-----


This is the code that causes the system call interrupted error, also in 
xio.sml


----

fun readVec (n, hdr) = let
               val _ = print "exenedebugphil:xio.readVec start\n"
               val _ = MLton.Thread.atomicBegin()
       fun read (0, [v]) = v
         | read (0, vl) = W8V.concat(List.rev vl)
         | read (n, vl) = let
             val v = let   val _ = print "exenedebugphil:xio.readVec 
before socket\n"
                                 val _ = print 
("exenedebugphil:xio.readVec n=" ^ Int.toString n ^ "\n")
                                 val ret = check(fn => 
Socket.recvVec(sock, n))
                                 val _ = print 
"exenedebugphil:xio.readVec after socket\n"
                             in ret
                             end
             in
           case (W8V.length v)
              of 0 => raise Fail "Socket closed"
                | len => read (n - len, v::vl)
           (* end case *)
             end
        val ret = read (n, hdr)
        val _ = MLton.Thread.atomicEnd()
        in ret
        end
-----

If you remove the atomics, the error should go away, though exene will 
not work.  In the above example code, the check function is our spin 
lock, allowing only one Socket call at a time.



Type inference issues....

For whatever reason we had many problems with infering option types in 
this exene build.  Please take a look at the following example also in 
xio.sml

---
     fun gobbleAndFlush arg = let

       fun loop arg =
                    let val _ = MLton.Thread.atomicBegin()
                    in
                     if CML.isEmpty (reqCh)
                     then (MLton.Thread.atomicEnd(); arg)
                     else let val req = (CML.recv reqCh)
                              val _ = MLton.Thread.atomicEnd()
                              in case req
                                  of RequestFlush => loop arg
                       | RequestQuit => quit()
                       | (Request req) => loop (doRequest(req, arg))
                       | (RequestAndChk req) => loop (doRequestAndChk 
(req, arg))
                       | (RequestReply req) => loop (doRequestReply 
(req, arg))
                       | (RequestReplies req) =>
                           loop (doRequestReplies (req, arg))
                       | (RequestExposures req) =>
                           loop (doRequestExposures (req, arg))
                              end
                  end

(*
       fun loop arg = (case (CML.recvPoll (reqCh))
              of NONE => arg
           | (SOME RequestFlush) => loop arg
           | (SOME RequestQuit) => quit()
           | (SOME(Request req)) => loop (doRequest(req, arg))
           | (SOME(RequestAndChk req)) => loop (doRequestAndChk (req, arg))
           | (SOME(RequestReply req)) => loop (doRequestReply (req, arg))
           | (SOME(RequestReplies req)) =>
               loop (doRequestReplies (req, arg))
           | (SOME(RequestExposures req)) =>
               loop (doRequestExposures (req, arg))
             (* end case *))

*)
       val res = loop arg        in
         CML.send(outCh, OutFlush);
         res
       end

---

The original code is commented out, but will not type check, our fix is 
the uncommented out code.  Basically we just returned a bool and based 
on the bool did the appropriate thing.  NJ, will however, compile the 
commented out code. Here are the Mlton typecheck errors.
-------
Error: ../../lib/protocol/xio.sml 474.18.
  Case object and rules disagree.
    object type:  [??? option]
    rules expect: [req_msg option]
    in: case (CML.recvPoll (reqCh)) of (NON  ...  estExposures (req, arg)))
compilation aborted: parseAndElaborate reported errors
-----
With type anntations on the various variables...
-------
Error: ../../lib/protocol/xio.sml 474.18.
  Case object and rules disagree.
    object type:  [req_msg option]
    rules expect: [req_msg option]
    in: case (CML.recvPoll (reqCh)) of (NON  ...  estExposures (req, arg)))
compilation aborted: parseAndElaborate reported errors
------

Another such example in the widgets with no type annotations:

 fun handleReq (GetShades c) = let
                val rgb = EXB.rgbOfColor c
                in
                  case rgbFind rgb of NONE => allocShade (c,rgb) | s => s
                end

--------------------
Error: ../../widgets/util/shade-server.sml 119.19.
Case object and rules disagree.
  object type:  [{base: Drawing.pen, dark: Drawing.pen, light: 
Drawing.pen} option]
  rules expect: [{base: Drawing.pen, dark: Drawing.pen, light: 
Drawing.pen} option]
  in: case rgbFind rgb of (NONE) => (allo  ...  de (c, rgb)) | (s) => (s)
compilation aborted: parseAndElaborate reported errors
---------------------


If you have any questions please send mail to me and philip, we can 
explain anything that might not be clear.

thank you very much!
Luke