package minicaml

  1. Overview
  2. Docs

Source file types.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
(** A value identifier*)
type ide = string
[@@deriving show, eq, ord]

(** The type representing Abstract Syntax Tree expressions *)
type expr =
  | Unit
  | Integer of int
  | Boolean of bool
  | String of string
  | Symbol of ide
  | List of expr list
  | Cons of expr * expr
  | Dict of (expr * expr) list
  (* Numerical Operations *)
  | Plus of expr * expr
  | Sub of expr * expr
  | Mult of expr * expr
  | Eq of expr * expr
  | Gt of expr * expr
  | Lt of expr * expr
  | Ge of expr * expr
  | Le of expr * expr
  (* Boolean operations *)
  | And of expr * expr
  | Or of expr * expr
  | Not of expr
  (* Control flow and functions *)
  | IfThenElse of expr * expr * expr
  | Let of (ide * expr) list * expr
  | Letlazy of (ide * expr) list * expr
  | Letrec of ide * expr * expr
  | Letreclazy of ide * expr * expr
  | Lambda of ide list * expr
  | Apply of expr * expr list
  | Sequence of expr list
  | Pipe of expr * expr
  [@@deriving show { with_path = false }, eq, ord]

(** A type useful for evaluating files, stating if a command is
an expression or simply a "global" declaration (appended to environment) *)
type command =
  | Expr of expr
  | Def of (ide * expr) list
  | Defrec of (ide * expr) list
  [@@deriving show { with_path = false }, eq, ord]

(** A purely functional environment type, parametrized *)
type 'a env_t = (string * 'a) list [@@deriving show { with_path = false }, eq, ord]

(** A type that represents an evaluated (reduced) value *)
type evt =
  | EvtUnit
  | EvtInt of int         [@compare compare]
  | EvtBool of bool       [@equal (=)] [@compare compare]
  | EvtString of string   [@equal (=)] [@compare compare]
  | EvtList of evt list   [@equal (=)]
  | EvtDict of (evt * evt) list [@equal (=)]
  | Closure of ide list * expr * (type_wrapper env_t) [@equal (=)]
  (** RecClosure keeps the function name in the constructor for recursion *)
  | RecClosure of ide * ide list * expr * (type_wrapper env_t) [@equal (=)]
  (** Abstraction that permits treating primitives as closures *)
  | PrimitiveAbstraction of (ide * int * (type_wrapper env_t))
  [@@deriving show { with_path = false }, eq, ord]
and type_wrapper =
  | LazyExpression of expr
  | AlreadyEvaluated of evt
  [@@deriving show { with_path = false }]
(* Wrapper type that allows both AST expressions and
evaluated expression for lazy evaluation *)

(* Generate a list of parameter names to use in the primitive abstraction *)
let generate_prim_params n = 
  Array.to_list(Array.make n 'a' |> Array.mapi (fun i c -> int_of_char c + i |> char_of_int |> Printf.sprintf "%c"))


let rec show_unpacked_evt e = match e with
  | EvtInt v -> string_of_int v
  | EvtBool v -> string_of_bool v
  | EvtString v -> "\"" ^ (String.escaped v) ^ "\""
  | EvtList l -> "[" ^ (String.concat "; " (List.map show_unpacked_evt l)) ^ "]"
  | EvtDict d -> "{" ^ 
    (String.concat ", " 
      (List.map (fun (x,y) -> show_unpacked_evt x ^ ":" ^ show_unpacked_evt y) d)) 
      ^ "}"
  | Closure (params, _, _) -> "(fun " ^ (String.concat " " params) ^ " -> ... )"
  | RecClosure (name, params, _, _) -> name ^ " = (rec fun " ^ (String.concat " " params) ^ " -> ... )"
  | PrimitiveAbstraction (name, numargs, _ ) -> name ^ " = " ^ "(fun " ^ (generate_prim_params numargs |> String.concat " ") ^ " -> ... )"
  | _ -> show_evt e

(** An environment of already evaluated values  *)
type env_type = type_wrapper env_t

(** A recursive type representing a stacktrace frame *)
type stackframe =
  | StackValue of int * expr * stackframe
  | EmptyStack
  [@@deriving show { with_path = false }]

(** Push an AST expression into a stack
  @param s The stack where to push the expression
  @param e The expression to push
*)
let push_stack (s: stackframe) (e: expr) = match s with
  | StackValue(d, ee, ss) -> StackValue(d+1, e, StackValue(d, ee, ss))
  | EmptyStack -> StackValue(1, e, EmptyStack)

(** Pop an AST expression from a stack *)
let pop_stack (s: stackframe) = match s with
  | StackValue(_, _, ss) -> ss
  | EmptyStack -> failwith "Stack underflow"

exception UnboundVariable of string
exception TooManyArgs of string
exception WrongBindList
exception WrongPrimitiveArgs
exception TypeError of string
exception ListError of string
exception DictError of string
exception SyntaxError of string