type variable =
    string;;

type literal =
  | LEntier of int
  | LBooleen of bool;;

type type_ =
  | TEntier
  | TBooleen
  | TFonction of type_ * type_;;

type operation =
  | OPlus
  | OMoins
  | OFois
  | ODivise
  | OEgal
  | OMineur
  | OEt
  | OOu;;

type expression =
  | ELitteral of literal
  | EVariable of variable
  | EOperation of expression * operation * expression
  | EFonction of variable * type_ * expression
  | EAppel of expression * expression
  | ESi of expression * expression * expression
  | ESoit of variable * type_ * expression * expression;;

type toplevel_form =
  | TSoit of variable * type_ * expression;;

type program =
  | PBase of expression
  | PRecursif of toplevel_form * program;;

type value =
  | VEntier of int
  | VBooleen of bool
  | VFonction of environment * variable * expression
and environment =
    (variable * value) list;; (* the first binding has precedence *)

let string_of_value value =
  match value with
    | VEntier i ->
      string_of_int i
    | VBooleen b ->
      string_of_bool b
    | VFonction(rho, x, e) ->
      "#<fonction>";;
