An Example of Object-Oriented Features

Here we give an example of using the object-oriented features in Camelot. The code below, together with the two standard utility functions rev and len for list reversal and length, defines a program for Sun's MIDP platform (as described in midp), which runs on devices such as PalmOS PDAs. The program displays the list of primes in an interval. Two numbers are entered into the first page of the GUI, and when a button is pressed a second screen appears with the list of primes, calculated using the sieve of Eratosthenes, along with a button leading back to the initial display.

This example has been compiled with our current compiler implementation, and executed on a PalmOS device.

class primes = javax.microedition.midlet.MIDlet with
  implement javax.microedition.lcdui.CommandListener

  field exitCommand: javax.microedition.lcdui.Command
  field goCommand: javax.microedition.lcdui.Command
  field doneCommand: javax.microedition.lcdui.Command
  field mainForm: javax.microedition.lcdui.Form
  (* lower and upper limits: *)
  field lltf: javax.microedition.lcdui.TextField  
  field ultf: javax.microedition.lcdui.TextField  
  field display: javax.microedition.lcdui.Display

  maker () = 
    let _ = display <- 
      (javax.microedition.lcdui.Display.getDisplay     
        (this:> javax.microedition.midlet.MIDlet)) 
    in let _ = goCommand <-
      (new javax.microedition.lcdui.Command 
      "Go" javax.microedition.lcdui.Command.SCREEN 1)
    in let _ = exitCommand <-
      (new javax.microedition.lcdui.Command 
      "Exit" javax.microedition.lcdui.Command.SCREEN  2)
    in let t = new javax.microedition.lcdui.Form "Primes"
    in let ll = new javax.microedition.lcdui.TextField 
        "Lower limit:" "" 10 
        javax.microedition.lcdui.TextField.NUMERIC
    in let _ = lltf <- ll
    in let _ = t#append ll
    in let ul = new javax.microedition.lcdui.TextField 
        "Upper limit:" "" 10 
        javax.microedition.lcdui.TextField.NUMERIC
    in let _ = ultf <- ul
    in let _ = t#append ul
    in let _ = t#addCommand (this#goCommand)
    in let _ = t#addCommand (this#exitCommand)
    in let _ = mainForm <- t
    in t#setCommandListener this

  method startApp (): unit = 
    this#display#setCurrent (this#mainForm)
  method pauseApp (): unit = ()
  method destroyApp (b:bool): unit = ()
  method commandAction 
           (cmd: javax.microedition.lcdui.Command) 
           (s: javax.microedition.lcdui.Displayable)
           : unit =
    if cmd#equals (this#exitCommand)     
    then let _ = this#destroyApp false 
         in this#notifyDestroyed ()
    (* create & display list of primes *)
    else if cmd#equals (this#goCommand)  
    then 
      let    lower_limit = int_of_string 
                            (this#lltf#getString())
      in let upper_limit = int_of_string 
                            (this#ultf#getString())
      in let primes = 
               new javax.microedition.lcdui.Form "Primes"
      in let _ = appendPrimes lower_limit upper_limit primes
      in let done = new javax.microedition.lcdui.Command 
                 "Done" 
                 javax.microedition.lcdui.Command.SCREEN 1
      in let _ = doneCommand <- done
      in let _ = primes#addCommand done
      in let _ = primes#setCommandListener this
      in let _ = 
        javax.microedition.lcdui.AlertType.INFO#playSound 
          (this#display)
      in this#display#setCurrent primes
   (* back to main form *)
    else if cmd#equals (this#doneCommand) then  
      this#display#setCurrent (this#mainForm)
    else ()
end
(* Generate a list of prime numbers in an interval [a..b] *)
(* Integer square roots *)
let increase k n = if (k+1)*(k+1) > n then k else k+1
let rec intsqrt n = if n = 0 then 0 
                    else increase (2*(intsqrt (n/4))) n

(* n is divisible by no member of l which is <= sqrt n *)
let isPrime n l lim =  
   match l with 
     [] -> true 
   | h::t -> h <= lim && n mod h <> 0 && isPrime n t lim 

(* generate list of primes between n and top *)
let make1 n top acc = 
  if n > top then rev acc []
  else if isPrime n acc n then make1 (n+2) top (n::acc)
  else make1 (n+2) top acc

let makeSmallPrimes top = make1 3 top [2] 
let makePrimes n top smallPrimes =
  if n > top then []
  else if isPrime n smallPrimes n then 
    n::(makePrimes (n+2) top smallPrimes)
  else makePrimes (n+2) top smallPrimes

let appList l (f: javax.microedition.lcdui.Form) =
  match l with [] -> ()
  | (h::t)@_ -> let _ = f#append ( (string_of_int h)^"\n")
                in appList t f

let appendPrimes bot top 
      (f: javax.microedition.lcdui.Form) =
  let smallPrimes = makeSmallPrimes (intsqrt top)
  in let primes = makePrimes (bot + 1 - bot mod 2) 
                    top smallPrimes
  in let s = (string_of_int (len primes)) ^ " primes\n"
  in let _ = f#append s
  in appList primes f