trilean/
skleene.rs

1// Copyright 2015 Pierre Talbot (IRCAM)
2
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6
7//     http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15/// `SKleene` is a structure implementing the strong Kleene's three-valued logic (see README.md and the truth tables below).
16
17use skleene::SKleene::*;
18use core::ops::*;
19use core::fmt;
20
21#[derive(Clone, Copy, PartialEq, Eq, Debug)]
22pub enum SKleene
23{
24  False = 0,
25  True = 1,
26  Unknown = 2
27}
28
29const NOT_TABLE: [SKleene; 3] =
30  // False, True, Unknown
31     [True, False, Unknown];
32const AND_TABLE: [[SKleene; 3]; 3] =
33  /* False */   [[ False, False, False ],
34  /* True  */    [ False, True, Unknown],
35  /* Unknown */  [ False, Unknown, Unknown]
36  ];
37
38const OR_TABLE: [[SKleene; 3]; 3] =
39  //               False, True, Unknown
40  /* False */   [[ False, True, Unknown ],
41  /* True  */    [ True, True, True],
42  /* Unknown */  [ Unknown, True, Unknown]
43  ];
44
45impl SKleene
46{
47  pub fn and(self, rhs: SKleene)-> SKleene {
48    AND_TABLE[self as usize][rhs as usize]
49  }
50
51  pub fn or(self, rhs: SKleene) -> SKleene {
52    OR_TABLE[self as usize][rhs as usize]
53  }
54
55  pub fn from_bool(b: bool) -> SKleene {
56    NOT_TABLE[(!b) as usize]
57  }
58}
59
60impl Not for SKleene
61{
62  type Output = SKleene;
63
64  fn not(self) -> SKleene {
65    NOT_TABLE[self as usize]
66  }
67}
68
69impl BitAnd for SKleene
70{
71  type Output = Self;
72  fn bitand(self, rhs: Self) -> Self {
73    self.and(rhs)
74  }
75}
76
77impl BitOr for SKleene
78{
79  type Output = Self;
80  fn bitor(self, rhs: Self) -> Self {
81    self.or(rhs)
82  }
83}
84
85
86impl fmt::Display for SKleene
87{
88  fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
89    match self {
90      False => write!(f, "false"),
91      True => write!(f, "true"),
92      Unknown => write!(f, "unknown"),
93    }
94  }
95}
96
97#[test]
98fn test_not() {
99  assert_eq!(!True, False);
100  assert_eq!(!False, True);
101  assert_eq!(!Unknown, Unknown);
102}
103
104#[test]
105fn test_and() {
106  let f = |a: SKleene, b, e| {
107    assert_eq!(a.and(b), e);
108    assert_eq!(b.and(a), e);
109    assert_eq!(a & b, e);
110  };
111  f(True, True, True);
112  f(True, False, False);
113  f(True, Unknown, Unknown);
114  f(False, False, False);
115  f(False, Unknown, False);
116  f(Unknown, Unknown, Unknown);
117}
118
119#[test]
120fn test_or() {
121  let f = |a: SKleene, b, e| {
122    assert_eq!(a.or(b), e);
123    assert_eq!(b.or(a), e);
124    assert_eq!(a | b, e);
125  };
126  f(True, True, True);
127  f(True, False, True);
128  f(True, Unknown, True);
129  f(False, False, False);
130  f(False, Unknown, Unknown);
131  f(Unknown, Unknown, Unknown);
132}
133
134#[test]
135fn test_from_bool() {
136  assert_eq!(SKleene::from_bool(true), True);
137  assert_eq!(SKleene::from_bool(false), False);
138}