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 ) -> Self {
47 FnSet {
48 body: FnSetBody::new(params_and_their_sets, dom_facts, ret_set),
49 }
50 }
51
52 pub fn get_params(&self) -> Vec<String> {
53 self.body.get_params()
54 }
55}
56
57#[derive(Clone)]
59pub struct AnonymousFn {
60 pub body: FnSetBody,
61 pub equal_to: Box<Obj>,
62}
63
64impl AnonymousFn {
65 pub fn new(
66 params_and_their_sets: Vec<ParamGroupWithSet>,
67 dom_facts: Vec<OrAndChainAtomicFact>,
68 ret_set: Obj,
69 equal_to: Obj,
70 ) -> Self {
71 AnonymousFn {
72 body: FnSetBody::new(params_and_their_sets, dom_facts, ret_set),
73 equal_to: Box::new(equal_to),
74 }
75 }
76}
77
78#[derive(Clone)]
80pub enum FnSetSpace {
81 Set(FnSet),
82 Anon(AnonymousFn),
83}
84
85impl FnSetSpace {
86 pub fn params(&self) -> &Vec<ParamGroupWithSet> {
87 match self {
88 FnSetSpace::Set(f) => &f.body.params_def_with_set,
89 FnSetSpace::Anon(a) => &a.body.params_def_with_set,
90 }
91 }
92
93 pub fn dom(&self) -> &Vec<OrAndChainAtomicFact> {
94 match self {
95 FnSetSpace::Set(f) => &f.body.dom_facts,
96 FnSetSpace::Anon(a) => &a.body.dom_facts,
97 }
98 }
99
100 pub fn ret_set_obj(&self) -> Obj {
101 match self {
102 FnSetSpace::Set(f) => (*f.body.ret_set).clone(),
103 FnSetSpace::Anon(a) => (*a.body.ret_set).clone(),
104 }
105 }
106
107 pub fn binding(&self) -> ParamObjType {
108 match self {
109 FnSetSpace::Set(_) => ParamObjType::FnSet,
110 FnSetSpace::Anon(_) => ParamObjType::FnSet,
111 }
112 }
113
114 pub fn from_ret_obj(obj: Obj) -> Result<Self, RuntimeError> {
115 match obj {
116 Obj::FnSet(f) => Ok(FnSetSpace::Set(f)),
117 Obj::AnonymousFn(a) => Ok(FnSetSpace::Anon(a)),
118 _ => Err(RuntimeError::from(WellDefinedRuntimeError(
119 RuntimeErrorStruct::new_with_just_msg(format!(
120 "expect return set of function space to be `fn` or anonymous fn, got {}",
121 obj
122 )),
123 ))),
124 }
125 }
126}
127
128impl fmt::Display for FnSetBody {
129 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130 let params_with_sets_display: Vec<String> = self
131 .params_def_with_set
132 .iter()
133 .map(|g| format!("{} {}", vec_to_string_join_by_comma(&g.params), g.set))
134 .collect();
135 write!(
136 f,
137 "{} {} {}",
138 FN_LOWER_CASE,
139 brace_vec_colon_vec_to_string(¶ms_with_sets_display, &self.dom_facts),
140 self.ret_set
141 )
142 }
143}
144
145impl fmt::Display for FnSet {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 write!(f, "{}", self.body)
148 }
149}
150
151impl fmt::Display for AnonymousFn {
152 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
153 let params_with_sets_display: Vec<String> = self
154 .body
155 .params_def_with_set
156 .iter()
157 .map(|g| format!("{} {}", vec_to_string_join_by_comma(&g.params), g.set))
158 .collect();
159 write!(
160 f,
161 "{}{} {} {}{}{}",
162 ANONYMOUS_FN_PREFIX,
163 brace_vec_colon_vec_to_string(¶ms_with_sets_display, &self.body.dom_facts),
164 self.body.ret_set,
165 LEFT_CURLY_BRACE,
166 self.equal_to,
167 RIGHT_CURLY_BRACE,
168 )
169 }
170}
171
172impl From<FnSet> for Obj {
173 fn from(fs: FnSet) -> Self {
174 Obj::FnSet(fs)
175 }
176}
177
178impl From<AnonymousFn> for Obj {
179 fn from(af: AnonymousFn) -> Self {
180 Obj::AnonymousFn(af)
181 }
182}