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 *)
type type_enviroment =
    (variable * type_) list;; (* the first binding has precedence *)

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

let rec string_of_type type_=
  match type_ with
    | TEntier -> "entier"
    | TBooleen -> "booléen"
    | TFonction(de, a) ->
      "(" ^ 
        (string_of_type de)
        ^ " -> " ^
        (string_of_type a)
      ^ ")";;
