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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
//! Simple expression construction.
//!
//! This module defines an expression type that is able to describe simple expressions composed of
//! constants, variables, and applications.
//!
//! # Usage
//!
//! To construct expressions, the API provides the functions `cst`, `var`, and `app` which
//! construct constants, variables, and applications respectively. The corresponding `Exp` enum
//! variants can be used directly but require a call to `Box::new` to construct each value of the
//! `App` tuple.
//!
//! These functions allow the expressions to be constructed similarly to how they would be in
//! functional languages like OCaml, for example:
//!
//! ```
//! use knube::exp::{cst, var, app};
//!
//! let e = app(app(cst("f"), cst("a")), var("x"));
//! ```
//!
//! Which would translate to the expression `((f a) x)` (OCaml style) or `f(a)(x)` (Rust style).
//! This crate uses the Rust style to display expressions.
/// An alias to make functions signatures returning expressions easier to read and write.
pub type ExpBox = ;
/// A simple expression, as described in the module documentation.
///
/// This recursive form is what we study in class. Other implementations might be completely
/// different.
/// Constructs a constant with the given name.
///
/// Constant names are usually single letters close to the beginning of the alphabet, i.e. `a`,
/// `b`, `f`, etc.
/// Constructs a variable with the given name. Variables are just identifiers, they don't hold any
/// value.
///
/// Variable names, similarly to constant names, are usually a single letter. However their name is
/// usually a letter close to the end of the alphabet, i.e. `x`, `y`, etc.
/// Constructs an application with the given left and right expressions.
///
/// Applications would translate to functions calls, i.e. if `left` is `f` and `right` is `x`, then
/// `app(left, right)` is `(f x)` or `f(x)` depending on the style.
use PartialEq;
/// The comparison is done as follows:
///
/// - `Cst(a) == Cst(b)` *iff* `a == b`, where `a` and `b` are strings.
/// - `Var(a) == Var(b)` *iff* `a == b`, where `a` and `b` are strings.
/// - `App(a, b) == App(c, d)` *iff* `(a == c) && (b == d)`, where `a`, `b`, `c`, and `d` are
/// expressions.
///
/// This definition of the equality operator matches the behavior of OCaml's sum type comparison.
use fmt;
/// Formats the expressions using the Rust style of expressions.
///
/// The expressions are formatted as follows:
///
/// - Variables and constants are replaced by their name. For example `Cst("a")` becomes `a`
/// and `Cst("x")` becomes `x`.
/// - Applications are replaced by a function call. For example `App(Cst("f"), Var("x"))` becomes `f(x)`.