CS 451 Programming Paradigms
ML Assignment Two: Final vmtester.sml File


(********************************************************************)
(*                 TYPE DECLARATIONS                                *)
(********************************************************************)
datatype token = INT of int | REG of int | LOC of int |
                 VPUT | LPUT | WRI | PUT | ADD | MUL | SUB

type state = ( (int * int) * (int * int * int * int) )
(********************************************************************)



(********************************************************************)
(*               SIGNATURE  DECLARATIONS                            *)
(********************************************************************)
signature VMPROCESS = 
  sig
    val execute : int -> unit
  end

signature VIRTMACH = 
  sig 
    val interpret : token list * state * int -> token list * state
  end

signature PROGRAM =
  sig
     val sourceFile : TextIO.instream
     val resultFile : TextIO.outstream
  end
(********************************************************************)




(********************************************************************)
(*                   PROGRAM INSTANCE CREATION                      *)
(********************************************************************)
structure ProgOne : PROGRAM = 
struct
  val sourceFile = TextIO.openIn("progone.vm")
  val resultFile = TextIO.openOut("progone.out")
end

structure ProgTwo : PROGRAM = 
struct
  val sourceFile = TextIO.openIn("progtwo.vm")
  val resultFile = TextIO.openOut("progtwo.out")
end

structure ProgThree : PROGRAM = 
struct
  val sourceFile = TextIO.openIn("progthree.vm")
  val resultFile = TextIO.openOut("progthree.out")
end
(********************************************************************)



(*****************************************************************************)
(*                          VIRTUAL MACHINE FUNCTOR                          *)
(*****************************************************************************)
functor makeVirtualMachine(val outfile : TextIO.outstream) : VIRTMACH = 
struct

exception Syntax of string
val outf : TextIO.outstream = outfile;
fun syntaxError s = raise (Syntax s)


(*======================FUNCTIONS YOU MUST WRITE=====================*)
fun printState : state -> unit 
     (* state -> output to file *)
		 (* Prints an output to the outfile that looks like
					Registers: 1 2
					Memory: 1 0 0 4
     *)

fun regStore : int * int * state -> state
     (* reg#, value, oldstate -> newstate *)
		 (* Puts value in reg# and returns the newstate tuple *)
		 (* Raises exception Syntax with appropriate message if # is not 1 or 2 *)

fun memStore : int * int * state -> state
     (* mem#, value, oldstate -> newstate *)
		 (* Puts value in mem# and returns the newstate tuple *)
		 (* Raises exception Syntax with appropriate message if # is not 1 - 4 *)

fun regGet : int * state -> int 
     (* reg#, state -> value *)
		 (* Returns the value in reg# obtained from the state *)
		 (* Raises exception Syntax with appropriate message if # is not 1 or 2 *)

fun memGet : int * state  -> int
     (* mem#, state -> value *)
		 (* Returns the value in mem# obtained from the state *)
		 (* Raises exception Syntax with appropriate message if # is not 1 - 4 *)

fun stmt : token * token * token * state -> state 
     (* three tokens from the token list, oldstate -> newstate *)
		 (* This is the heart of the parsing.  Given three tokens
				that have been successfully removed from the token list by stmts,
				match on the particulars and do the processing.  Match also
				many different incorrect combinations/range violations and
				raise exception Syntax with appropriate messages *)

fun stmts : token list * state * int -> token list * state 
     (* old token list, oldstate, instruction count -> (new token list, newstate) *) 
		 (* If the token list is empty, close the outfile and return the tuple (nil,s) 
				where s  is state.  Otherwise try to match three tokens from the list, 
				using them to call stmt.  That result is the newstate.  Print it,
				and then if the instruction count not zero recurse, decrementing the count.
				If it is zero, print to outfile the line "======> CONTEXT SWITCH" and
				return the tuple (remaining token list, newstate).
				Also raise exception Syntax if there is no successful match. *)

(*===================================================================*)

fun interpret(tokenStream : token list, s : state, numInstr : int ) : token list * state  =
  stmts(tokenStream,s,numInstr)
  handle 
   Syntax s => (TextIO.output(outf,"Syntax error: "^s^"\n"); (nil,((0,0),(0,0,0,0))) ) 

end 
(*********************************************************************************)




(*********************************************************************)
(*                          VMPROCESS FUNCTOR                          *)
(*********************************************************************)
functor makeVMProcess(prog : PROGRAM ) : VMPROCESS
=
struct


(******************************************)
(* Some utilities for the parsing process *)
(******************************************)
exception Invalid_Register of int
exception Invalid_Memory of int 
exception Lexical of string

fun regError k = raise (Invalid_Register k)
fun memError k = raise (Invalid_Memory k)
fun lexicalError s = raise (Lexical s)

fun token(s : string) : token =
  if Char.isDigit(String.sub(s,0)) orelse (String.sub(s,0) = #"~")
  then case Int.fromString(s)
       of SOME n => if (String.size(Int.toString(n))=String.size(s))
                    then INT n
                    else lexicalError ("Bad numeric token "^s)
       |  NONE   => lexicalError ("Bad numeric token "^s)
  else
    if String.size(s)=2
    then
      if (String.sub(s,0) = #"r")
      then
        if Char.isDigit(String.sub(s,1))
        then case Int.fromString(Char.toString(String.sub(s,1)))
             of SOME n => if (n<1) orelse (n>2)
                          then regError(n)
                          else REG n
             |  NONE   => lexicalError ("Bad register token "^s)
        else lexicalError("Bad register token "^s)
      else
        if (String.sub(s,0) = #"l")
        then
          if Char.isDigit(String.sub(s,1))
          then case (Int.fromString(Char.toString(String.sub(s,1))))
               of SOME n => if (n<1) orelse (n>4)
                            then memError(n)
                            else LOC n
               |  NONE   => lexicalError ("Bad token "^s)
          else lexicalError("Bad memory location token "^s)
        else lexicalError("Bad memory location or register token "^s)
    else
      case s
         of "vput"  => VPUT
         |  "put"   => PUT
         |  "add"   => ADD
         |  "mul"   => MUL
         |  "sub"   => SUB
         |  "lput"  => LPUT
         |  "wri"   => WRI
         |    _     => lexicalError ("Bad token "^s)

fun getStrings(infile: TextIO.instream) : string list =
  String.tokens Char.isSpace (TextIO.input infile)

     
(***********************************************)
(* Local state for tracking execution progress *)
(***********************************************)

val sourceFile : TextIO.instream = prog.sourceFile;
val resultFile : TextIO.outstream = prog.resultFile;
structure virtmach : VIRTMACH = makeVirtualMachine(val outfile  = resultFile);

(*======================CODE YOU MUST WRITE=====================*)
val tokencoding : token list ref
       (* set this equal to a reference to the result of mapping  
					token over the result of getStrings applied to sourceFile 
          and handle exceptions here *)

(*****************************************************)
(*   Provide int ref's for                           *)
(*                                                   *)
(*   reg1, reg2, mem1, mem2, mem3, and mem4          *)
(*                                                   *)
(*   and initialize them to reference values of zero *)
(*****************************************************)

fun setState : state -> unit 
      (* newstate -> reference variables for state updated *)

fun getState : unit -> state
      (* no arguments -> current state tuple *)

fun execute : int -> unit 
      (* number of instructions to process -> output of state at each instruction to file *)
			(*                                      and update of state and remaining token list *)
(*==============================================================*)

end
(******************************************************************)



[ Back to CS451: The ML Segment ]