COMP3161/9164 Concepts of Programming Languages
Term 3, 2025

Evaluator Code

Here is the sketch code of the evaluator that was written during the lecture. The point of the exercise is to show what is special about the C-machine: its steps match closely to the steps of a "reasonable" implementation of MinHS. By comparison, the steps of the M-machine are steps of an inefficient implementation, one that repeatedly performs syntactic substitutions.



-- Firstly, the syntax of MinHS taken from the week 4 demo code.

data BinOp = Plus | Minus | Times | Equals
  deriving (Show, Eq)

data Type = Bool | IntType | FunType Type Type
  deriving (Show, Eq)

data MinHS =
    Num Int
  | Lit Bool
  | If MinHS MinHS MinHS
  | BinOp BinOp MinHS MinHS
  | Apply MinHS MinHS
  -- For now we comment out the HOAS features so that we can derive
  -- a printer for MinHS syntax

  -- | RecFun Type Type (MinHS -> MinHS -> MinHS)
    -- Added as a bit of a hack to make the pretty-printer work
  -- | NameTag String
    -- Added as a bit of a hack to make the type-checker work
  -- | TypeTag Type
  deriving Show

-- Type for values being returned.
data Value =
    IntVal Int
  | BoolVal Bool
  -- | FunVal Type Type (MinHS -> MinHS -> MinHS)
  deriving Show

-- Type for "frames", partially-evaluated expressions.
data Frame =
    -- BinOp bop □ e2
    BinOp1 BinOp () MinHS
    -- BinOp bop e1 □
  | BinOp2 BinOp Value ()
    -- If □ e2 e3
  | If1 () MinHS MinHS
  deriving Show

-- Type of configuration of the C-machine.
data MachineConfig =
    EvalExpression MinHS [Frame]
  | ReturnValue Value [Frame]
  deriving Show

evalBinOp :: BinOp -> Value -> Value -> Value
evalBinOp Plus (IntVal n) (IntVal m) = IntVal (n + m)
evalBinOp bop v1 v2 = error ("evalBinOp: unimplemented: " ++ show bop)

-- The evaluator for the C-machine.
-- Note that this function doesn't recurse, and each step can be
-- performed in O(1) in principle.
evalMachine :: MachineConfig -> MachineConfig
evalMachine (ReturnValue v []) = error ("evalMachine: finished")
evalMachine (EvalExpression (Num n) st) = ReturnValue (IntVal n) st
-- Need to put BinOp bop □ e2 on the stack.
evalMachine (EvalExpression (BinOp bop e1 e2) st) =
    EvalExpression e1 (BinOp1 bop () e2 : st)
evalMachine (ReturnValue v1 (BinOp1 bop () e2 : st)) =
    EvalExpression e2 (BinOp2 bop v1 () : st)
evalMachine (ReturnValue v2 (BinOp2 bop v1 () : st)) =
    ReturnValue (evalBinOp bop v1 v2) st

-- Repeat evalMachine until a final state is found and
-- produce the whole trace of execution steps.
evalSteps :: MachineConfig -> [MachineConfig]
evalSteps (ReturnValue v []) = [ReturnValue v []]
evalSteps config = config : evalSteps (evalMachine config)


-- Roughly the example syntax from the slides.
example :: MinHS
example = BinOp Plus (BinOp Plus (Num 3) (Num 4)) (Num 5)

example_init = EvalExpression example []


2025-12-05 Fri 11:50

Announcements RSS