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