package dolmen_model

  1. Overview
  2. Docs

Source file eval.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120

(* This file is free software, part of dolmen. See file "LICENSE" for more information *)

(* Type definitions *)
(* ************************************************************************* *)

module E = Dolmen.Std.Expr
module B = Dolmen.Std.Builtin
module Term = Dolmen.Std.Expr.Term
module Var = Dolmen.Std.Expr.Term.Var
module Cst = Dolmen.Std.Expr.Term.Const


(* Exceptions *)
(* ************************************************************************* *)

exception Quantifier
exception Partial_model
exception Incomplete_match
exception Unhandled_builtin of Cst.t
exception Undefined_variable of Var.t
exception Undefined_constant of Cst.t

(* Builtins *)
(* ************************************************************************* *)

let builtins (l : Env.builtins list) : Env.builtins =
  let rec aux ~eval env c = function
    | [] -> None
    | b :: r ->
      begin match b ~eval env c with
        | Some _ as res -> res
        | None -> aux ~eval env c r
      end
  in
  (fun ~eval env c -> aux ~eval env c l)


(* Evaluation *)
(* ************************************************************************* *)

let rec eval env (e : Term.t) : Value.t =
  (* Format.eprintf "[eval] @[<hov>%a -> ?@]@." Term.print e; *)
  let r =
    match e.term_descr with
    | Var v -> eval_var env v
    | Cst c -> eval_cst env c
    | App (f, ty_args, t_args) -> eval_apply env f ty_args t_args
    | Binder (b, body) -> eval_binder env b body
    | Match (t, arms) -> eval_match env t arms
  in
  (* Format.eprintf "[eval] @[<hov>%a -> %a@]@." Term.print e Value.print r; *)
  r

and eval_var env v =
  match Model.Var.find_opt v (Env.model env) with
  | Some value -> value
  | None -> raise (Undefined_variable v)

and eval_cst env (c : Cst.t) =
  match c.builtin with
  | B.Base ->
    begin match Model.Cst.find_opt c (Env.model env) with
      | Some value -> value
      | None -> raise (Undefined_constant c)
    end
  | _ ->
    begin match Env.builtins env ~eval env c with
      | Some res -> res
      | None -> raise (Unhandled_builtin c)
    end

and eval_apply env f ty_args args =
  Fun.apply ~eval env (eval env f) ty_args args

and eval_binder env b body =
  match (b : E.binder) with
  | Let_seq l ->
    let env =
      List.fold_left (fun env (v, expr) ->
          let value = eval env expr in
          Env.update_model env (Model.Var.add v value)
        ) env l
    in
    eval env body
  | Let_par l ->
    (* Note: this parrallel treatment is not strictly speaking necessary,
       since for typed expressions, there is no shadowing of variables,
       and we have pure logic semantics (e.g. no side-effects of evaluating
       expressions), but let's keep that for now and potentially change that
       later. *)
    let l' = List.map (fun (v, expr) -> v, eval env expr) l in
    let env =
      List.fold_left (fun env (v, value) ->
          Env.update_model env (Model.Var.add v value)
        ) env l'
    in
    eval env body
  | Lambda (tys, params) ->
    begin match params with
      | [] -> eval env body
      | _ -> Fun.mk_clos @@ Fun.lambda tys params body
    end
  | Exists (_tys, _terms)
  | Forall (_tys, _terms) ->
    raise Quantifier

and eval_match_aux env scrutinee = function
  | [] -> raise Incomplete_match
  | (pat, arm) :: r ->
    begin match Adt.pattern_match env pat scrutinee with
      | None -> eval_match_aux env scrutinee r
      | Some env -> eval env arm
    end

and eval_match env scrutinee arms =
  let scrutinee = eval env scrutinee in
  eval_match_aux env scrutinee arms