Substitution Rules

Grammar

Expressions

  e ::= c                        (* constants *)
    | id                       (* variables *)
    | (fn id => e)             (* anonymous functions *) 
    | e1(e2)                   (* function applications *)
    | u e                      (* unary operations, ~, not, etc. *)
    | e1 b e2                  (* binary operations, +,*,etc. *)
    | (if e then e1 else e2)   (* if expressions *)
    | let d in e end           (* let expressions *)

Declarations

  d ::= val id = e               (* value declarations *)
    | fun id(id1) = e          (* function declarations *)

Values

  v ::= c                        (* constant values *)
    | (fn id => e)             (* anonymous functions *)

Rule #E1 [constants]

  eval(c) = c

Rule #E2 [anonymous functions]

  eval(fn id => e) = (fn id => e)

Rule #E3 [function calls]

  eval(e1(e2)) = v'  where
  (0) eval(e1) = (fn id => e)
  (1) eval(e2) = v
  (2) substitute([(id,v)],e) = e'
  (3) eval(e') = v'

Lazy version

  eval(e1(e2)) = v'  where
  (0) eval(e1) = (fn id => e)
  (1) substitute([(id,e2)],e) = e'
  (2) eval(e') = v'

Rule #E4 [unary operators]

  eval(u e) = v where
  (0) eval(e) = v'
  (1) v = apply_unop(u,v')

Rule #E5 [binary operators]

  eval(e1 b e2) = v where
  (0) eval(e1) = v1
  (1) eval(e2) = v2
  (2) v = apply_binop(b,v1,v2)

Rule #E6 [if expressions]

  eval(if e then e1 else e2) = v' where
  (0) eval(e) = v
  (1) if v = true then v' = eval(e1)
  (2) if v = false then v' = eval(e2)

Alternate semantics that evaluates both branches

  eval(if e then e1 else e2) = v' where
  (0) eval(e) = v
  (1) eval(e1) = v1
  (2) eval(e2) = v2
  (3) if v = true then v1
  (4) if v = false then v2

Rule #D1[val declarations]

  eval_decl(val p = e) = S where
  (0) eval(e) = v
  (1) create substitution S = [(p, v)]

Rule #E7 [let expressions]

  eval(let d in e end) = v where
  (0) eval_decl(d) = S
  (1) substitute(S,e) = e'
  (2) eval(e') = v

Rule #D2[fun declarations]

  eval_decl(fun f x = e) = [(f, fun f x = e)]

Rule #E8[fun expressions]

  eval(fun f x = e) = (fn x => e') where
    substitute([(f, fun f x = e)], e) = e'.