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