1#[allow(unused_imports)]
8use crate::Aim;
9use crate::{
10 aim::{ContextLike, WriterLike, Writer},
11 expressions::{ExpressionLike, parse_accessor},
12 functions::FunctionRegistry,
13 values::Value,
14};
15use anyhow::{Result, anyhow};
16use nom::{
17 Err as NomErr, IResult, Parser,
18 branch::alt,
19 bytes::complete::tag,
20 character::complete::{alpha1, alphanumeric1, multispace0},
21 combinator::{map, recognize},
22 error::Error,
23 multi::many0_count,
24 sequence::pair,
25};
26use std::{
27 fmt, path::PathBuf, sync::Arc
28};
29use once_cell::sync::OnceCell;
30
31#[derive(Debug, Clone, PartialEq, Eq, Hash)]
39pub enum Reference {
40 One(Arc<str>),
42 Two(Arc<str>, Arc<str>),
44 Three(Arc<str>, Arc<str>, Arc<str>),
46 Four(Arc<str>, Arc<str>, Arc<str>, Arc<str>),
48}
49
50impl Reference {
51 #[doc = include_str!("../docs/reference/new.md")]
53 pub fn new(identifier: Arc<str>) -> Arc<Self> {
54 Arc::new(Reference::One(identifier))
55 }
56
57 #[doc = include_str!("../docs/reference/workspace.md")]
59 pub fn workspace() -> Arc<Self> {
60 static GLOBAL: OnceCell<Arc<Reference>> = OnceCell::new();
61 GLOBAL.get_or_init(|| Reference::new(Arc::from("_"))).clone()
62 }
63
64 #[doc = include_str!("../docs/reference/inference.md")]
66 pub fn inference() -> Arc<Self> {
67 static GLOBAL: OnceCell<Arc<Reference>> = OnceCell::new();
68 GLOBAL.get_or_init(|| Reference::new(Arc::from("inference"))).clone()
69 }
70
71 #[doc = include_str!("../docs/reference/context.md")]
73 pub fn context() -> Arc<Self> {
74 static GLOBAL: OnceCell<Arc<Reference>> = OnceCell::new();
75 GLOBAL.get_or_init(|| Reference::new(Arc::from("context"))).clone()
76 }
77
78 #[doc = include_str!("../docs/reference/status.md")]
80 pub fn status() -> Arc<Self> {
81 static GLOBAL: OnceCell<Arc<Reference>> = OnceCell::new();
82 GLOBAL.get_or_init(|| Reference::new(Arc::from("status"))).clone()
83 }
84
85 #[doc = include_str!("../docs/reference/tool.md")]
87 pub fn tool() -> Arc<Self> {
88 static GLOBAL: OnceCell<Arc<Reference>> = OnceCell::new();
89 GLOBAL.get_or_init(|| Reference::new(Arc::from("tool"))).clone()
90 }
91
92 #[doc = include_str!("../docs/reference/workflow.md")]
94 pub fn workflow() -> Arc<Self> {
95 static GLOBAL: OnceCell<Arc<Reference>> = OnceCell::new();
96 GLOBAL.get_or_init(|| Reference::new(Arc::from("workflow"))).clone()
97 }
98
99 #[doc = include_str!("../docs/reference/parse.md")]
101 pub fn parse(input: &str) -> Result<Arc<Self>> {
102 match parse_reference(input) {
103 Ok((_, reference)) => Ok(reference),
104 Err(_) => Err(anyhow!("Invalid reference ~{}", input)),
105 }
106 }
107
108 #[doc = include_str!("../docs/reference/handle.md")]
110 pub fn handle(&self) -> Arc<str> {
111 let mut writer = Writer::formulizer();
112 match self {
113 Reference::One(one) =>
114 writer.write_str(one),
115 Reference::Two(one, two) => {
116 writer.write_str(one);
117 writer.write_char('_');
118 writer.write_str(two);
119 }
120 Reference::Three(one, two, three) => {
121 writer.write_str(one);
122 writer.write_char('_');
123 writer.write_str(two);
124 writer.write_char('_');
125 writer.write_str(three);
126 }
127 Reference::Four(one, two, three, four) => {
128 writer.write_str(one);
129 writer.write_char('_');
130 writer.write_str(two);
131 writer.write_char('_');
132 writer.write_str(three);
133 writer.write_char('_');
134 writer.write_str(four);
135 }
136 }
137 Arc::from(writer.finish())
138 }
139
140 #[doc = include_str!("../docs/reference/identifier.md")]
142 pub fn identifier(&self) -> Arc<str> {
143 match self {
144 Reference::One(one) => one.clone(),
145 Reference::Two(_, two) => two.clone(),
146 Reference::Three(_, _, three) => three.clone(),
147 Reference::Four(_, _, _, four) => four.clone(),
148 }
149 }
150
151 pub fn base(&self) -> Arc<str> {
153 match self {
154 Reference::One(one) => one.clone(),
155 Reference::Two(one, _) => one.clone(),
156 Reference::Three(one, _, _) => one.clone(),
157 Reference::Four(one, _, _, _) => one.clone(),
158 }
159 }
160
161 pub fn depth(&self) -> usize {
162 match self {
163 Reference::One{..} => 1,
164 Reference::Two{..} => 2,
165 Reference::Three{..} => 3,
166 Reference::Four{..} => 4,
167 }
168 }
169
170 pub fn is_level_below(&self, reference: &Reference) -> bool {
171 match self {
172 Reference::One{..} => {
173 match reference {
174 Reference::One{..} => false,
175 _ => true,
176 }
177 },
178 Reference::Two{..} => {
179 match reference {
180 Reference::Three{..}
181 | Reference::Four{..} => true,
182 _ => false,
183 }
184 }
185 Reference::Three{..} => {
186 match reference {
187 Reference::Four{..} => true,
188 _ => false,
189 }
190 }
191 Reference::Four{..} => false,
192 }
193 }
194
195 pub fn contains_root(&self) -> bool {
196 &*self.base() == "_"
197 }
198
199 pub fn to_path(&self) -> PathBuf {
200 if self.contains_root() {
201 PathBuf::from("workspace.aim")
202 } else {
203 let path = PathBuf::from("workspace");
204 match self {
205 Reference::One(one) => {
206 path.join(format!("{}.aim", one))
207 }
208 Reference::Two(one, two) => {
209 path.join(one.as_ref())
210 .join(format!("{}.aim", two))
211 }
212 Reference::Three(one, two, three) => {
213 path.join(one.as_ref())
214 .join(two.as_ref())
215 .join(format!("{}.aim", three))
216 }
217 Reference::Four(one, two, three, four) => {
218 path.join(one.as_ref())
219 .join(two.as_ref())
220 .join(three.as_ref())
221 .join(format!("{}.aim", four))
222 }
223 }
224 }
225 }
226
227 #[doc = include_str!("../docs/reference/rename.md")]
229 pub fn rename_child(&self, identifier: Arc<str>) -> Reference {
230 match self {
231 Reference::One(_) => Reference::One(
232 identifier
233 ),
234 Reference::Two(one, _) => Reference::Two(
235 one.clone(),
236 identifier,
237 ),
238 Reference::Three(one, two, _) => Reference::Three(
239 one.clone(),
240 two.clone(),
241 identifier,
242 ),
243 Reference::Four(one, two, three, _) => Reference::Four(
244 one.clone(),
245 two.clone(),
246 three.clone(),
247 identifier,
248 ),
249 }
250 }
251
252 #[doc = include_str!("../docs/reference/parent.md")]
254 pub fn get_parent(&self) -> Result<Reference> {
255 match self {
256 Reference::One(..) => Err(anyhow!("Reference {} has no parent", self)),
257 Reference::Two(one, _) => Ok(Reference::One(
258 one.clone(),
259 )),
260 Reference::Three(one, two, _) => Ok(Reference::Two(
261 one.clone(),
262 two.clone(),
263 )),
264 Reference::Four(one, two, three, _) => Ok(Reference::Three(
265 one.clone(),
266 two.clone(),
267 three.clone(),
268 )),
269 }
270 }
271
272 #[doc = include_str!("../docs/reference/child.md")]
274 pub fn add_child(&self, identifier: Arc<str>) -> Result<Reference> {
275 if self.contains_root() {
276 match self {
277 Reference::One(_) => Ok(Reference::One(
278 identifier)
279 ),
280 Reference::Two(_, two) => Ok(Reference::Two(
281 two.clone(),
282 identifier,
283 )),
284 Reference::Three(_, two, three) => Ok(Reference::Three(
285 two.clone(),
286 three.clone(),
287 identifier,
288 )),
289 Reference::Four(_, two, three, four) => Ok(Reference::Four(
290 two.clone(),
291 three.clone(),
292 four.clone(),
293 identifier,
294 )),
295 }
296 } else {
297 match self {
298 Reference::One(one) => Ok(Reference::Two(
299 one.clone(),
300 identifier)
301 ),
302 Reference::Two(one, two) => Ok(Reference::Three(
303 one.clone(),
304 two.clone(),
305 identifier,
306 )),
307 Reference::Three(one, two, three) => Ok(Reference::Four(
308 one.clone(),
309 two.clone(),
310 three.clone(),
311 identifier,
312 )),
313 Reference::Four(..) => Err(anyhow!("Cannot append {} to {} scope~{}", identifier, self, identifier)),
314 }
315 }
316 }
317
318 #[doc = include_str!("../docs/reference/normalize.md")]
320 pub fn combine_and_normalize(&self, reference: &Reference) -> Result<Reference> {
321 match self {
322 Reference::One(one) => match reference {
323 Reference::One(ref_one) => Ok(Reference::Two(one.clone(), ref_one.clone())),
324 Reference::Two(ref_one, ref_two) => Ok(Reference::Three(
325 one.clone(),
326 ref_one.clone(),
327 ref_two.clone(),
328 )),
329 Reference::Three(ref_one, ref_two, ref_three) => Ok(Reference::Four(
330 one.clone(),
331 ref_one.clone(),
332 ref_two.clone(),
333 ref_three.clone(),
334 )),
335 Reference::Four(..) => Err(anyhow!(
336 "Cannot normalize {} within {} scope~{}",
337 reference,
338 self,
339 reference
340 )),
341 },
342 Reference::Two(one, two) => match reference {
343 Reference::One(ref_one) => {
344 Ok(Reference::Three(one.clone(), two.clone(), ref_one.clone()))
345 }
346 Reference::Two(ref_one, ref_two) => Ok(Reference::Four(
347 one.clone(),
348 two.clone(),
349 ref_one.clone(),
350 ref_two.clone(),
351 )),
352 _ => Err(anyhow!(
353 "Cannot normalize {} within {} scope~{}",
354 reference,
355 self,
356 reference
357 )),
358 },
359 Reference::Three(one, two, three) => match reference {
360 Reference::One(ref_one) => Ok(Reference::Four(
361 one.clone(),
362 two.clone(),
363 three.clone(),
364 ref_one.clone(),
365 )),
366 _ => Err(anyhow!(
367 "Cannot normalize {} within {} scope~{}",
368 reference,
369 self,
370 reference
371 )),
372 },
373 Reference::Four(..) => Err(anyhow!(
374 "Cannot normalize {} within {} scope~{}",
375 reference,
376 self,
377 reference
378 )),
379 }
380 }
381
382 #[doc = include_str!("../docs/reference/print.md")]
384 pub fn print(&self, writer: &mut Writer) {
385 match self {
386 Reference::One(one) =>
387 writer.write_str(one),
388 Reference::Two(one, two) => {
389 writer.write_str(one);
390 writer.write_char('.');
391 writer.write_str(two);
392 }
393 Reference::Three(one, two, three) => {
394 writer.write_str(one);
395 writer.write_char('.');
396 writer.write_str(two);
397 writer.write_char('.');
398 writer.write_str(three);
399 }
400 Reference::Four(one, two, three, four) => {
401 writer.write_str(one);
402 writer.write_char('.');
403 writer.write_str(two);
404 writer.write_char('.');
405 writer.write_str(three);
406 writer.write_char('.');
407 writer.write_str(four);
408 }
409 }
410 }
411}
412
413impl PartialEq<str> for Reference {
414 fn eq(&self, other: &str) -> bool {
415 match self {
416 Reference::One(s) => **s == *other,
417 _ => false,
418 }
419 }
420}
421
422impl PartialEq<Reference> for str {
423 fn eq(&self, other: &Reference) -> bool {
424 match other {
425 Reference::One(s) => **s == *self,
426 _ => false,
427 }
428 }
429}
430
431pub fn parse_identifier(input: &str) -> IResult<&str, &str> {
439 map(
440 recognize(pair(
441 alt((alpha1, tag("_"))),
442 many0_count(alt((alphanumeric1, tag("_")))),
443 )),
444 |s: &str| s,
445 )
446 .parse(input)
447}
448
449pub fn parse_arc_identifier(input: &str) -> IResult<&str, Arc<str>> {
450 let (input, identifer) = parse_identifier(input)?;
451 Ok((input, Arc::from(identifer)))
452}
453
454pub fn parse_reference(input: &str) -> IResult<&str, Arc<Reference>> {
476 let registry = match FunctionRegistry::read_lock() {
477 Ok(guard) => guard,
478 Err(_) => {
479 return Err(NomErr::Failure(Error::new(
480 input,
481 nom::error::ErrorKind::Fail,
482 )));
483 }
484 };
485
486 let (input, one) = parse_arc_identifier(input)?;
488 let (input, _) = multispace0.parse(input)?;
489
490 if &*one == "_" || (input.starts_with('(') && registry.handler_exists(one.clone())) {
492 return Err(NomErr::Failure(Error::new(
493 input,
494 nom::error::ErrorKind::Fail,
495 )));
496 }
497
498 if let Ok((remainder, _)) = parse_accessor(input) {
500 let (remainder, two) = parse_arc_identifier(remainder)?;
501 let (remainder, _) = multispace0.parse(remainder)?;
502
503 if remainder.starts_with('(') && registry.handler_exists(two.clone()) {
505 return Ok((input, Arc::new(Reference::One(one))));
506 }
507
508 let input = remainder;
509
510 if let Ok((remainder, _)) = parse_accessor(input) {
511 let (remainder, three) = parse_arc_identifier(remainder)?;
512 let (remainder, _) = multispace0.parse(remainder)?;
513
514 if remainder.starts_with('(') && registry.handler_exists(three.clone()) {
516 return Ok((input, Arc::new(Reference::Two(one, two))));
517 }
518
519 let input = remainder;
520
521 if let Ok((remainder, _)) = parse_accessor(input) {
522 let (remainder, four) = parse_arc_identifier(remainder)?;
523 let (remainder, _) = multispace0.parse(remainder)?;
524
525 if remainder.starts_with('(') && registry.handler_exists(four.clone()) {
527 return Ok((input, Arc::new(Reference::Three(one, two, three))));
528 }
529
530 Ok((remainder, Arc::new(Reference::Four(one, two, three, four))))
531 } else {
532 Ok((input, Arc::new(Reference::Three(one, two, three))))
533 }
534 } else {
535 Ok((input, Arc::new(Reference::Two(one, two))))
536 }
537 } else {
538 Ok((input, Arc::new(Reference::One(one))))
539 }
540}
541
542impl ExpressionLike for Reference {
543 fn evaluate(&self, context: &mut dyn ContextLike) -> Result<Arc<Value>> {
552 context.get_value(self)
553 }
554
555 fn to_formula(&self) -> String {
557 let mut writer = Writer::formulizer();
558 self.print(&mut writer);
559 writer.finish()
560 }
561}
562
563impl WriterLike for Reference {
564 fn write(&self, writer: &mut Writer) {
565 self.print(writer);
566 }
567}
568
569impl fmt::Display for Reference {
570 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
571 write!(f, "{}", self.to_stringized())
572 }
573}