Search code examples
computer-sciencesmlsmlnj

SML interpreter.My Div func is working but i am having issue with my Minus func. I want it to give an error when the passed error is not a number


datatype exp = Int of int | Minus of exp * exp | Div of exp * exp;


datatype value = CVal of int 
               | FnVal of string * exp * (string * value) list 
               | Error of string;

fun eval (Int x) _ = CVal x 
  | eval (Div (e1, e2)) ctx = let val (CVal x) = eval e1 ctx
                                  val (CVal y) = eval e2 ctx
                              in if y = 0
                                 then Error "Division by zero error"
                                 else CVal (x div y)
                              end
  | eval (Minus (e1, e2)) ctx = let val (CVal x) = eval e1 ctx
                                    val (CVal y) = eval e2 ctx
                                in if x <> Int orelse y <> Int
                                   then Error "Minus error : not an integer"
                                   else CVal (x - y)
                                end;

Solution

  • Int is not a value, it's a constructor. You can't compare it to anything.
    It's also a constructor of exp values, not of integers.

    If you look at your definition,

    datatype value = CVal of int 
    ...
    

    it's clear that x and ymust be integers, just like in the division case.
    If you want to check types, you need to do that for division too, and you need to do that before you match with CVal x and CVal y.

    This gets very messy if you try do it all in a single function, so I would write some evaluation-helper functions; something like this:

    fun divide (CVal _) (CVal 0) = Error "Division by zero"
      | divide (CVal x) (CVal y) = CVal (x div y)
      | divide _ _ = Error "Division error: not an integer";
    
    fun subtract (CVal x) (CVal y) = CVal (x - y)
      | subtract _ _ = Error "Subtraction error: not an integer";
    
    fun eval (Int x) _ = CVal x 
      | eval (Div (e1, e2)) ctx = let val x = eval e1 ctx
                                      val y = eval e2 ctx
                                  in
                                      divide x y
                                  end
      | eval (Minus (e1, e2)) ctx = let val x = eval e1 ctx
                                        val y = eval e2 ctx
                                    in
                                        subtract x y
                                    end;