1use std::fmt;
2
3use crate::prelude::*;
4
5#[derive(Clone)]
6pub struct FnSetBody {
7 pub params_def_with_set: Vec<ParamGroupWithSet>,
8 pub dom_facts: Vec<OrAndChainAtomicFact>,
9 pub ret_set: Box<Obj>,
10}
11
12impl FnSetBody {
13 pub fn new(
14 params_def_with_set: Vec<ParamGroupWithSet>,
15 dom_facts: Vec<OrAndChainAtomicFact>,
16 ret_set: Obj,
17 ) -> Self {
18 Self {
19 params_def_with_set,
20 dom_facts,
21 ret_set: Box::new(ret_set),
22 }
23 }
24
25 pub fn get_params(&self) -> Vec<String> {
26 let mut ret = Vec::with_capacity(ParamGroupWithSet::number_of_params(
27 &self.params_def_with_set,
28 ));
29 for param_def_with_set in &self.params_def_with_set {
30 ret.extend(param_def_with_set.params.iter().cloned());
31 }
32 ret
33 }
34}
35
36#[derive(Clone)]
37pub struct FnSet {
38 pub body: FnSetBody,
39}
40
41impl FnSet {
42 pub fn new(
43 params_and_their_sets: Vec<ParamGroupWithSet>,
44 dom_facts: Vec<OrAndChainAtomicFact>,
45 ret_set: Obj,
46 ) -> Result<Self, RuntimeError> {
47 let fn_set = FnSet {
48 body: FnSetBody::new(params_and_their_sets, dom_facts, ret_set),
49 };
50 check_fn_set_has_no_duplicate_fn_set_free_parameter(&fn_set)?;
51 Ok(fn_set)
52 }
53
54 pub fn from_body(body: FnSetBody) -> Result<Self, RuntimeError> {
55 let fn_set = FnSet { body };
56 check_fn_set_has_no_duplicate_fn_set_free_parameter(&fn_set)?;
57 Ok(fn_set)
58 }
59
60 pub fn get_params(&self) -> Vec<String> {
61 self.body.get_params()
62 }
63}
64
65#[derive(Clone)]
67pub struct AnonymousFn {
68 pub body: FnSetBody,
69 pub equal_to: Box<Obj>,
70}
71
72impl AnonymousFn {
73 pub fn new(
74 params_and_their_sets: Vec<ParamGroupWithSet>,
75 dom_facts: Vec<OrAndChainAtomicFact>,
76 ret_set: Obj,
77 equal_to: Obj,
78 ) -> Result<Self, RuntimeError> {
79 let anonymous_fn = AnonymousFn {
80 body: FnSetBody::new(params_and_their_sets, dom_facts, ret_set),
81 equal_to: Box::new(equal_to),
82 };
83 check_anonymous_fn_has_no_duplicate_fn_set_free_parameter(&anonymous_fn)?;
84 Ok(anonymous_fn)
85 }
86}
87
88#[derive(Clone)]
90pub enum FnSetSpace {
91 Set(FnSet),
92 Anon(AnonymousFn),
93}
94
95impl FnSetSpace {
96 pub fn params(&self) -> &Vec<ParamGroupWithSet> {
97 match self {
98 FnSetSpace::Set(f) => &f.body.params_def_with_set,
99 FnSetSpace::Anon(a) => &a.body.params_def_with_set,
100 }
101 }
102
103 pub fn dom(&self) -> &Vec<OrAndChainAtomicFact> {
104 match self {
105 FnSetSpace::Set(f) => &f.body.dom_facts,
106 FnSetSpace::Anon(a) => &a.body.dom_facts,
107 }
108 }
109
110 pub fn ret_set_obj(&self) -> Obj {
111 match self {
112 FnSetSpace::Set(f) => (*f.body.ret_set).clone(),
113 FnSetSpace::Anon(a) => (*a.body.ret_set).clone(),
114 }
115 }
116
117 pub fn binding(&self) -> ParamObjType {
118 match self {
119 FnSetSpace::Set(_) => ParamObjType::FnSet,
120 FnSetSpace::Anon(_) => ParamObjType::FnSet,
121 }
122 }
123
124 pub fn from_ret_obj(obj: Obj) -> Result<Self, RuntimeError> {
125 match obj {
126 Obj::FnSet(f) => Ok(FnSetSpace::Set(f)),
127 Obj::AnonymousFn(a) => Ok(FnSetSpace::Anon(a)),
128 _ => Err(RuntimeError::from(WellDefinedRuntimeError(
129 RuntimeErrorStruct::new_with_just_msg(format!(
130 "expect return set of function space to be `fn` or anonymous fn, got {}",
131 obj
132 )),
133 ))),
134 }
135 }
136}
137
138impl fmt::Display for FnSetBody {
139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 let params_with_sets_display: Vec<String> = self
141 .params_def_with_set
142 .iter()
143 .map(|g| g.to_string())
144 .collect();
145 write!(
146 f,
147 "{} {} {}",
148 FN_LOWER_CASE,
149 brace_vec_colon_vec_to_string(¶ms_with_sets_display, &self.dom_facts),
150 self.ret_set
151 )
152 }
153}
154
155impl fmt::Display for FnSet {
156 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
157 write!(f, "{}", self.body)
158 }
159}
160
161impl fmt::Display for AnonymousFn {
162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163 let params_with_sets_display: Vec<String> = self
164 .body
165 .params_def_with_set
166 .iter()
167 .map(|g| g.to_string())
168 .collect();
169 write!(
170 f,
171 "{}{} {} {}{}{}",
172 ANONYMOUS_FN_PREFIX,
173 brace_vec_colon_vec_to_string(¶ms_with_sets_display, &self.body.dom_facts),
174 self.body.ret_set,
175 LEFT_CURLY_BRACE,
176 self.equal_to,
177 RIGHT_CURLY_BRACE,
178 )
179 }
180}
181
182impl From<FnSet> for Obj {
183 fn from(fs: FnSet) -> Self {
184 Obj::FnSet(fs)
185 }
186}
187
188impl From<AnonymousFn> for Obj {
189 fn from(af: AnonymousFn) -> Self {
190 Obj::AnonymousFn(af)
191 }
192}