aimx/
literal.rs

1//! Literal value parsing and representation for the AIM expression grammar.
2//!
3//! This module defines the [`Literal`] enum that represents literal values in expressions,
4//! including booleans, numbers, text, dates, and tasks. It provides parsing functions
5//! for literal values and comprehensive type conversion capabilities.
6//!
7//! Literal values are the fundamental building blocks of AIM expressions. They represent
8//! concrete values that don't require evaluation and serve as the basis for type promotion
9//! and conversion operations throughout the expression evaluation system.
10//!
11//! # Literal Types
12//!
13//! - **`Empty`** - Represents an empty or null value
14//! - **`Bool`** - Boolean values (`true` or `false`)
15//! - **`Date`** - Date and time values using the `jiff` crate's `DateTime`
16//! - **`Number`** - 64-bit floating point numbers
17//! - **`Task`** - Task primitives with optional status and text description
18//! - **`Text`** - UTF-8 string values
19//!
20//! # Type Conversion Rules
21//!
22//! AIMX uses intuitive type conversion rules that follow these principles:
23//!
24//! - **Boolean conversion**: Non-zero numbers, non-empty text, existing dates are `true`
25//! - **Date conversion**: Numbers as Unix timestamps, text as date strings
26//! - **Number conversion**: Boolean true=1/false=0, dates as timestamps, parsable text
27//! - **Task conversion**: Status from boolean/numbers, text from any convertible value
28//! - **Text conversion**: String representation of any value
29//!
30//! # Examples
31//!
32//! ```rust
33//! use aimx::literal::Literal;
34//! use aimx::typedef::Typedef;
35//!
36//! // Creating literals
37//! let bool_literal = Literal::from_bool(true);
38//! let number_literal = Literal::from_number(42.0);
39//! let text_literal = Literal::from_text("hello".to_string());
40//!
41//! // Type checking
42//! assert!(bool_literal.is_bool());
43//! assert!(number_literal.is_number());
44//! assert!(text_literal.is_text());
45//!
46//! // Type conversion
47//! let number_as_text = number_literal.clone().as_text().unwrap();
48//! assert!(number_as_text.is_text());
49//! assert_eq!(number_as_text.to_string(), "42");
50//!
51//! // Type matching
52//! assert!(number_literal.is_type(&Typedef::Number));
53//! assert!(number_literal.is_type(&Typedef::Any));
54//! ```
55//!
56//! # Parsing
57//!
58//! The module provides parsing functions for all literal types:
59//!
60//! - [`parse_literal`] - Main parser for any literal type
61//! - [`parse_bool`] - Boolean parser (`true`/`false`)
62//! - [`parse_task`] - Task parser (`[status] description`)
63//!
64//! See also: [`parse_date`], [`parse_number`], [`parse_text`] in the [`crate::literals`] module
65
66use crate::{
67    ContextLike,
68    ExpressionLike, 
69    literals::{parse_date, parse_number, parse_text},
70    Typedef,
71    Writer,
72    Value,
73};
74use jiff::civil::DateTime;
75use nom::{
76    IResult, Parser,
77    branch::alt,
78    bytes::complete::tag,
79    character::complete::{char, multispace0},
80    combinator::{map, opt},
81};
82use std::fmt;
83use anyhow::{anyhow, Result};
84use std::cmp::{Ordering};
85
86/// Represents a literal value in the AIM expression grammar.
87///
88/// The `Literal` enum encapsulates all fundamental value types that can appear
89/// directly in AIM expressions, without requiring evaluation. Literals form
90/// the basis of the type system and provide the primary mechanism for type
91/// conversion and promotion throughout the expression evaluation pipeline.
92///
93/// # Literal Variants
94///
95/// Each variant represents a specific data type with its own semantics:
96///
97/// - **`Empty`** - Represents an empty or null value. Used as a placeholder
98///   when no meaningful value is present or appropriate. This variant has
99///   special handling in comparison operations and type conversion.
100///
101/// - **`Bool(bool)`** - Boolean values, representing logical true/false states.
102///   Booleans have straightforward truthiness semantics and can be converted
103///   to numbers (1/0) or text ("true"/"false") as needed.
104///
105/// - **`Date(DateTime)`** - Date and time values using the `jiff` crate's
106///   `DateTime` type. Dates support conversion from Unix timestamps (numbers)
107///   and ISO 8601-style date strings while maintaining timezone awareness.
108///
109/// - **`Number(f64)`** - 64-bit floating point numbers. The primary numeric
110///   type used throughout AIMX, supporting arithmetic operations, mathematical
111///   functions, and various conversion contexts.
112///
113/// - **`Task(Option<bool>, String)`** - Task primitives with optional status
114///   and description text. Tasks are a unique semantic type in AIMX that
115///   represent work items in agentic workflows. Status can be `Some(true)`
116///   (completed), `Some(false)` (failed), or `None` (pending).
117///
118/// - **`Text(String)`** - UTF-8 string values. Text literals support the full
119///   Unicode character set and provide comprehensive string manipulation
120///   capabilities through built-in functions.
121///
122/// # Type System Integration
123///
124/// Literals implement comprehensive type checking and conversion capabilities:
125///
126/// - **Type Matching**: The [`Literal::is_type`] method checks compatibility with [`Typedef`]
127/// - **Type Resolution**: The [`Literal::get_type`] method returns the literal's type
128/// - **Type Conversion**: Various `as_*` methods handle type promotion
129/// - **Type Casting**: The [`Literal::as_type`] method converts to match another literal's type
130///
131/// # Operator Implementations
132///
133/// The `Literal` type implements several important traits:
134///
135/// - **`PartialEq`** and **`Eq`** - Equality comparison for all literal types
136/// - **`PartialOrd`** and **`Ord`** - Consistent ordering across different literal types
137/// - **`ExpressionLike`** - Integration with the expression evaluation system
138/// - **`Display`** - Human-readable string representation
139///
140/// # Examples
141///
142/// ## Creating Literals
143///
144/// ```rust
145/// use aimx::literal::Literal;
146///
147/// // Using constructor functions
148/// let bool_lit = Literal::from_bool(true);
149/// let number_lit = Literal::from_number(42.5);
150/// let text_lit = Literal::from_text("hello".to_string());
151///
152/// // Direct enum construction
153/// let task_lit = Literal::Task(Some(true), "Completed task".to_string());
154/// let empty_lit = Literal::Empty;
155/// ```
156///
157/// ## Type Conversion
158///
159/// ```rust
160/// use aimx::literal::Literal;
161///
162/// let number = Literal::from_number(42.0);
163/// 
164/// // Convert number to text
165/// let as_text = number.clone().as_text().unwrap();
166/// assert_eq!(as_text.to_string(), "42");
167/// 
168/// // Convert number to boolean (non-zero is true)
169/// let as_bool = number.as_bool();
170/// assert!(as_bool.to_bool());
171/// ```
172///
173/// ## Type Checking
174///
175/// ```rust
176/// use aimx::literal::Literal;
177/// use aimx::typedef::Typedef;
178///
179/// let date_lit = Literal::Date(jiff::civil::DateTime::new(2023, 1, 1, 0, 0, 0, 0).unwrap());
180/// 
181/// assert!(date_lit.is_date());
182/// assert!(date_lit.is_type(&Typedef::Date));
183/// assert!(date_lit.is_type(&Typedef::Any));
184///
185/// let date_type = date_lit.get_type().unwrap();
186/// assert_eq!(date_type, Typedef::Date);
187/// ```
188///
189/// # See Also
190///
191/// - [`Typedef`] - The type definition system used for type checking
192/// - [`Value`] - The runtime value representation that wraps literals
193/// - [`parse_literal`] - Function for parsing literal values from strings
194#[derive(Debug, Clone, PartialEq)]
195pub enum Literal {
196    /// Represents an empty or null value.
197    ///
198    /// Empty literals are used when no meaningful value is available or appropriate.
199    /// They have special behavior in comparisons and type conversions:
200    /// - Empty compared to empty text is considered equal
201    /// - Cannot be converted to most specific types except boolean (false)
202    /// - Used as default values in various contexts
203    Empty,
204    
205    /// A boolean value representing logical true or false.
206    ///
207    /// Boolean literals participate in logical operations and can be converted
208    /// to numbers (1 for true, 0 for false) or text ("true"/"false").
209    Bool(bool),
210    
211    /// A date and time value using the `jiff` crate's DateTime type.
212    ///
213    /// Date literals support comprehensive date/time operations including
214    /// date arithmetic, formatting, and timezone-aware operations.
215    Date(DateTime),
216    
217    /// A 64-bit floating point number.
218    ///
219    /// Number literals are the primary numeric type in AIMX, supporting
220    /// mathematical operations, functions, and various numeric conversions.
221    Number(f64),
222    
223    /// A task primitive with optional status and description text.
224    ///
225    /// Tasks are a semantic type unique to AIMX, representing work items
226    /// in agentic workflows. The status can be:
227    /// - `Some(true)` - Completed task
228    /// - `Some(false)` - Failed task  
229    /// - `None` - Pending task
230    ///
231    /// Tasks have special numeric semantics: completed=1, failed=-1, pending=0.
232    Task(Option<bool>, String),
233    
234    /// A UTF-8 string value.
235    ///
236    /// Text literals support the full Unicode character set and provide
237    /// comprehensive string manipulation through built-in functions.
238    Text(String),
239}
240
241impl Literal {
242    /// Check if this literal matches the specified type.
243    ///
244    /// # Arguments
245    ///
246    /// * `typedef` - The type definition to check against
247    ///
248    /// # Returns
249    ///
250    /// Returns `true` if this literal matches the specified type, `false` otherwise.
251    pub fn is_type(&self, typedef: &Typedef) -> bool {
252        match self {
253            Literal::Empty => false,
254            Literal::Bool(_) => typedef.is_bool() | typedef.is_any(),
255            Literal::Date(_) => typedef.is_date() | typedef.is_any(),
256            Literal::Number(_) => typedef.is_number() | typedef.is_any(),
257            Literal::Task(..) => typedef.is_task() | typedef.is_any(),
258            Literal::Text(_) => typedef.is_text() | typedef.is_any(),
259        }
260    }
261
262    /// Get the type of this literal.
263    ///
264    /// # Returns
265    ///
266    /// Returns a `Result<Typedef>` containing the type of this literal,
267    /// or an error if this is an Empty literal.
268    pub fn get_type(&self) -> Result<Typedef> {
269        match self {
270            Literal::Empty => Err(anyhow!("Expecting type, found Empty")),
271            Literal::Bool(_) => Ok(Typedef::Bool),
272            Literal::Date(_) => Ok(Typedef::Date),
273            Literal::Number(_) => Ok(Typedef::Number),
274            Literal::Task(..) => Ok(Typedef::Task),
275            Literal::Text(_) => Ok(Typedef::Text),
276        }
277    }
278
279    /// Convert this literal to match the type of another literal.
280    ///
281    /// This method performs type conversion according to the grammar's
282    /// type promotion rules, converting this literal to match the type
283    /// of the provided reference literal.
284    ///
285    /// # Arguments
286    ///
287    /// * `literal` - The reference literal whose type determines the conversion
288    ///
289    /// # Returns
290    ///
291    /// Returns a `Result<Literal>` containing the converted literal or an error
292    /// if conversion is not possible.
293    pub fn as_type(self, literal: &Literal) -> Result<Literal> {
294        match literal {
295            Literal::Empty => Err(anyhow!("Expecting type as {}, found Empty", literal.type_as_string())),
296            Literal::Bool(_) => Ok(self.as_bool()),
297            Literal::Date(_) => self.as_date(),
298            Literal::Number(_) => self.as_number(),
299            Literal::Task(..) => self.as_task(),
300            Literal::Text(_) => self.as_text(),
301        }
302    }
303
304    pub fn to_type(self, typedef: &Typedef) -> Result<Literal> {
305        match typedef {
306            Typedef::Any => Ok(self),
307            Typedef::Bool => Ok(self.as_bool()),
308            Typedef::Date => self.as_date(),
309            Typedef::Number => self.as_number(),
310            Typedef::Task => self.as_task(),
311            Typedef::Text => self.as_text(),
312            _ => Err(anyhow!("Expecting literal type, found {}", typedef.to_string())),
313        }
314    }
315
316    /// Check if this literal is empty.
317    pub fn is_empty(&self) -> bool {
318        match self {
319            Literal::Empty => true,
320            _ => false,
321        }
322    }
323
324    /// Check if this literal represents a boolean value.
325    pub fn is_bool(&self) -> bool {
326        match self {
327            Literal::Bool(_) => true,
328            _ => false,
329        }
330    }
331
332    /// Create a boolean literal from a boolean value.
333    pub fn from_bool(b: bool) -> Self {
334        Literal::Bool(b)
335    }
336
337    /// Convert this literal to a boolean representation.
338    ///
339    /// Performs type conversion to boolean according to the grammar's
340    /// truthiness rules:
341    /// - Numbers: 0 is false, non-zero is true
342    /// - Text: Empty string is false, non-empty is true
343    /// - Dates: Always true (they exist)
344    /// - Tasks: Status determines value, no status is false
345    ///
346    /// This function provides an implicit error free conversion from any
347    /// literal to bool specifically for the conditional ternary operator
348    /// making a type safe error free check possible.
349    ///
350    /// e.g. `user.birthday ? user.birthday : _`
351    pub fn as_bool(self) -> Literal {
352        match self {
353            Literal::Empty => Literal::Bool(false),
354            Literal::Bool(_) => self,
355            Literal::Date(_) => {
356                // Check for non-zero days
357                if let Ok(number) = self.as_number() {
358                    number.as_bool()
359                }
360                else {
361                    Literal::Bool(false)
362                }
363            }
364            Literal::Number(number) => Literal::Bool(number != 0.0),
365            Literal::Task(status, _) => match status {
366                Some(state) => Literal::Bool(state),
367                None => Literal::Bool(false),
368            },
369            Literal::Text(text) => Literal::Bool(!text.is_empty()),
370        }
371    }
372
373    /// Extract a boolean value from this literal.
374    ///
375    /// This is a convenience method for when you specifically need a `bool` value.
376    pub fn to_bool(&self) -> bool {
377        match self {
378            Literal::Empty => false,
379            Literal::Bool(b) => *b,
380            Literal::Date(_) => {
381                // Check for non-zero days
382                if let Ok(number) = self.to_number() {
383                    number != 0.0
384                }
385                else {
386                    false
387                }
388            }
389            Literal::Number(number) => *number != 0.0,
390            Literal::Task(status, _) => match *status {
391                Some(state) => state,
392                None => false,
393            },
394            Literal::Text(text) => !text.is_empty(),
395        }
396    }
397
398    /// Check if this literal represents a date value.
399    pub fn is_date(&self) -> bool {
400        match self {
401            Literal::Date(_) => true,
402            _ => false,
403        }
404    }
405
406    /// Create a date literal from a DateTime value.
407    pub fn from_date(d: DateTime) -> Self {
408        Literal::Date(d)
409    }
410
411    /// Convert this literal to a date representation.
412    ///
413    /// Attempts to convert the literal to a date according to the grammar's
414    /// conversion rules:
415    /// - Boolean: true becomes Unix epoch + 1 second, false becomes Unix epoch
416    /// - Number: Interpreted as Unix timestamp
417    /// - Text: Parsed as date if possible
418    /// - Task: Text component parsed as date if possible
419    pub fn as_date(self) -> Result<Literal> {
420        match self {
421            Literal::Empty => Err(anyhow!("Expecting type as Date, found Empty")),
422            Literal::Bool(state) => {
423                // Convert boolean to timestamp: true = 1, false = 0
424                let timestamp = if state { 1i64 } else { 0i64 };
425                match DateTime::new(1970, 1, 1, 0, 0, 0, 0) {
426                    Ok(epoch) => {
427                        // Add the timestamp seconds to the epoch
428                        match jiff::Span::new().try_seconds(timestamp) {
429                            Ok(duration) => {
430                                match epoch.checked_add(duration) {
431                                    Ok(new_dt) => Ok(Literal::Date(new_dt)),
432                                    Err(_) => Ok(Literal::Date(epoch)),
433                                }
434                            },
435                            Err(_) => Ok(Literal::Date(epoch)),
436                        }
437                    },
438                    Err(_) => Err(anyhow!("Failed to create Date from Bool")),
439                }
440            },
441            Literal::Date(_) => Ok(self),
442            Literal::Number(number) => {
443                // Convert number to timestamp (assuming it's a Unix timestamp)
444                let timestamp = number as i64;
445                match DateTime::new(1970, 1, 1, 0, 0, 0, 0) {
446                    Ok(epoch) => {
447                        // Add the timestamp seconds to the epoch
448                        match jiff::Span::new().try_seconds(timestamp) {
449                            Ok(duration) => {
450                                match epoch.checked_add(duration) {
451                                    Ok(new_dt) => Ok(Literal::Date(new_dt)),
452                                    Err(_) => Err(anyhow!("Failed to create Date from Number({})", number)),
453                                }
454                            },
455                            Err(_) => Err(anyhow!("Failed to create Date from Number({})", number)),
456                        }
457                    },
458                    Err(_) => Err(anyhow!("Failed to create Date from Number({})", number)),
459                }
460            },
461            Literal::Task(_, text) => {
462                // Try to parse the task text as a date
463                match parse_date(&text) {
464                    Ok((_, date)) => Ok(Literal::Date(date)),
465                    Err(_) => Err(anyhow!("Failed to parse Task text as Date")),
466                }
467            },
468            Literal::Text(text) => {
469                // Try to parse the text as a date
470                match parse_date(&text) {
471                    Ok((_, date)) => Ok(Literal::Date(date)),
472                    Err(_) => Err(anyhow!("Failed to parse Text({}) as Date", text)),
473                }
474            },
475        }
476    }
477
478    /// Check if this literal represents a number value.
479    pub fn is_number(&self) -> bool {
480        match self {
481            Literal::Number(_) => true,
482            _ => false,
483        }
484    }
485
486    /// Create a number literal from an f64 value.
487    pub fn from_number(n: f64) -> Self {
488        Literal::Number(n)
489    }
490
491    /// Convert this literal to a number representation.
492    ///
493    /// Attempts to convert the literal to a number according to the grammar's
494    /// conversion rules:
495    /// - Boolean: false becomes 0, true becomes 1
496    /// - Date: Converted to Unix timestamp
497    /// - Text: Parsed as number if it represents a valid numeric literal
498    /// - Task: Status determines value (true=1, false=-1, none=0)
499    pub fn as_number(self) -> Result<Literal> {
500        match self {
501            Literal::Empty => Err(anyhow!("Expecting type as Number, found Empty")),
502            Literal::Bool(state) => Ok(Literal::Number(if state { 1.0 } else { 0.0 })),
503            Literal::Date(dt) => {
504                if let Ok(utc_dt) = dt.to_zoned(jiff::tz::TimeZone::UTC) {
505                    let seconds = utc_dt.timestamp().as_second();
506                    Ok(Literal::Number(seconds as f64))
507                } else {
508                    Ok(Literal::Number(0.0))
509                }
510            }
511            Literal::Number(_) => Ok(self),
512            Literal::Task(status, _) => match status {
513                Some(state) => Ok(Literal::Number(if state { 1.0 } else { -1.0 })),
514                None => Ok(Literal::Number(0.0)),
515            },
516            Literal::Text(text) => match text.parse::<f64>() {
517                Ok(number) => Ok(Literal::Number(number)),
518                Err(_) => Err(anyhow!("Expecting Text as Number, found \"{}\"", text)),
519            },
520        }
521    }
522
523    /// Extract a numeric value from this literal.
524    ///
525    /// This is a convenience method for when you specifically need a `f64` number.
526    pub fn to_number(&self) -> Result<f64> {
527        match self {
528            Literal::Empty => Err(anyhow!("Expecting type as Number, found Empty")),
529            Literal::Bool(state) => Ok(if *state { 1.0 } else { 0.0 }),
530            Literal::Date(dt) => {
531                if let Ok(utc_dt) = dt.to_zoned(jiff::tz::TimeZone::UTC) {
532                    let seconds = utc_dt.timestamp().as_second();
533                    Ok(seconds as f64)
534                } else {
535                    Ok(0.0)
536                }
537            }
538            Literal::Number(number) => Ok(*number),
539            Literal::Task(status, _) => match *status {
540                Some(state) => Ok(if state { 1.0 } else { -1.0 }),
541                None => Ok(0.0),
542            },
543            Literal::Text(text) => match text.parse::<f64>() {
544                Ok(number) => Ok(number),
545                Err(_) => Err(anyhow!("Expecting Text as Number, found \"{}\"", text)),
546            },
547        }
548    }
549
550    /// Check if this literal represents a task value.
551    pub fn is_task(&self) -> bool {
552        match self {
553            Literal::Task(..) => true,
554            _ => false,
555        }
556    }
557
558    /// Create a task literal from status and text.
559    pub fn from_task(status: Option<bool>, task: String) -> Self {
560        Literal::Task(status, task)
561    }
562
563    /// Convert this literal to a task representation.
564    ///
565    /// Converts the literal to a task according to the grammar's conversion rules:
566    /// - Boolean: Status becomes the boolean value, text becomes "true"/"false"
567    /// - Date: No status, text becomes date string
568    /// - Number: Status based on sign (positive=true, negative=false, zero=none), text becomes number string
569    /// - Text: No status, text remains the same
570    pub fn as_task(self) -> Result<Literal> {
571        match self {
572            Literal::Empty => Err(anyhow!("Expecting type as Task, found Empty")),
573            Literal::Bool(state) => Ok(Literal::Task(Some(state), state.to_string())),
574            Literal::Date(dt) => Ok(Literal::Task(None, dt.to_string())),
575            Literal::Number(number) => {
576                let status = if number > 0.0 {
577                    Some(true)
578                } else if number < 0.0 {
579                    Some(false)
580                } else {
581                    None
582                };
583                Ok(Literal::Task(status, number.to_string()))
584            }
585            Literal::Task(..) => Ok(self),
586            Literal::Text(text) => Ok(Literal::Task(None, text)),
587        }
588    }
589
590    /// Check if this literal represents a text value.
591    pub fn is_text(&self) -> bool {
592        match self {
593            Literal::Text(_) => true,
594            _ => false,
595        }
596    }
597
598    /// Create a text literal from a String.
599    pub fn from_text(t: String) -> Self {
600        Literal::Text(t)
601    }
602
603    /// Convert this literal to a text representation.
604    ///
605    /// Converts the literal to text according to the grammar's conversion rules:
606    /// - Boolean: "true" or "false"
607    /// - Date: Formatted as date string
608    /// - Number: Formatted as string
609    /// - Task: Text component of the task
610    pub fn as_text(self) -> Result<Literal> {
611        match self {
612            Literal::Empty => Err(anyhow!("Expecting type as Text, found Empty")),
613            Literal::Bool(state) => Ok(Literal::Text(state.to_string())),
614            Literal::Date(dt) => Ok(Literal::Text(dt.to_string())),
615            Literal::Number(number) => Ok(Literal::Text(number.to_string())),
616            Literal::Task(_, text) => Ok(Literal::Text(text)),
617            Literal::Text(_) => Ok(self),
618        }
619    }
620
621    /// Get a string representation of this literal's type.
622    pub fn type_as_string(&self) -> &'static str {
623        match self {
624            Literal::Empty => "Empty",
625            Literal::Bool(_) => "Bool",
626            Literal::Date(_) => "Date",
627            Literal::Number(_) => "Number",
628            Literal::Task(..) => "Task",
629            Literal::Text(_) => "Text",
630        }
631    }
632
633    // Helper function to get type order for consistent sorting
634    fn type_order(&self) -> u8 {
635        match self {
636            Literal::Empty => 0,
637            Literal::Bool(_) => 1,
638            Literal::Number(_) => 2,
639            Literal::Date(_) => 3,
640            Literal::Text(_) => 4,
641            Literal::Task(..) => 5,
642        }
643    }
644
645    fn type_promote(self, literal: &Literal) -> Result<Literal> {
646        match literal {
647            Literal::Task(..) => {
648                match self {
649                    Literal::Text(t) => Ok(Literal::Task(None, t)),
650                    Literal::Date(dt) => Ok(Literal::Task(None, dt.to_string())),
651                    Literal::Number(n) => Ok(Literal::Task(None, n.to_string())),
652                    //Literal::Bool(b) => Ok(Literal::Task(Some(b), "".to_owned())),
653                    _ => Err(anyhow!("Type promote to Task failed")),
654                }
655            }
656            Literal::Text(_) => {
657                match self {
658                    Literal::Date(dt) => Ok(Literal::Text(dt.to_string())),
659                    Literal::Number(n) => Ok(Literal::Text(n.to_string())),
660                    //Literal::Bool(b) => Ok(Literal::Text(b.to_string())),
661                    _ => Err(anyhow!("Type promote to Text failed")),
662                }
663            }
664            Literal::Date(_) => {
665                match self {
666                    Literal::Number(number) => {
667                        // Convert number to timestamp (assuming it's a Unix timestamp)
668                        let timestamp = number as i64;
669                        match DateTime::new(1970, 1, 1, 0, 0, 0, 0) {
670                            Ok(epoch) => {
671                                // Add the timestamp seconds to the epoch
672                                match jiff::Span::new().try_seconds(timestamp) {
673                                    Ok(duration) => {
674                                        match epoch.checked_add(duration) {
675                                            Ok(new_dt) => Ok(Literal::Date(new_dt)),
676                                            Err(_) => Err(anyhow!("Failed to create Date from Number({})", number)),
677                                        }
678                                    },
679                                    Err(_) => Err(anyhow!("Failed to create Date from Number({})", number)),
680                                }
681                            },
682                            Err(_) => Err(anyhow!("Failed to create Date from Number({})", number)),
683                        }
684                    },
685                    _ => Err(anyhow!("Type promote to Date failed")),
686                }
687            }
688            Literal::Number(_) => {
689                match self {
690                    Literal::Bool(b) => Ok(Literal::Number(if b { 1.0 } else { 0.0 })),
691                    _ => Err(anyhow!("Type promote to Task failed")),
692                }
693            }
694            _ => Err(anyhow!("Type promote failed")),
695        }
696    }
697
698}
699
700impl PartialOrd for Literal {
701    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
702        // Check for special cases
703        match (self, other) {
704            (Literal::Text(t), Literal::Bool(b)) => {
705                match t.parse::<bool>() {
706                    Ok(a) => return a.partial_cmp(b),
707                    _ => {},
708                }
709            }
710            (Literal::Bool(a), Literal::Text(t)) => {
711                match t.parse::<bool>() {
712                    Ok(b) => return a.partial_cmp(&b),
713                    _ => {},
714                }                
715            }
716            (Literal::Text(t), Literal::Number(b)) => {
717                match t.parse::<f64>() {
718                    Ok(a) => return a.partial_cmp(b),
719                    _ => {},
720                }
721            }
722            (Literal::Number(a), Literal::Text(t)) => {
723                match t.parse::<f64>() {
724                    Ok(b) => return a.partial_cmp(&b),
725                    _ => {},
726                }                
727            }
728            (Literal::Text(t), Literal::Empty) | (Literal::Empty, Literal::Text(t)) => {
729                if t.len() == 0 {
730                    return Some(Ordering::Equal);
731                }
732            }
733            _ => {}
734        }
735        // Define a consistent ordering by type first, then value
736        // Type ordering: Empty < Bool < Number < Date < Task < Text
737        let self_type_order = self.type_order();
738        let other_type_order = other.type_order();
739        
740        if self_type_order > other_type_order {
741            match other.clone().type_promote(self) {
742                Ok(that) => self.partial_cmp(&that),
743                _ => Some(Ordering::Greater)
744            }
745        } else if self_type_order < other_type_order {
746            match self.clone().type_promote(other) {
747                Ok(this) => this.partial_cmp(other),
748                _ => Some(Ordering::Less)
749            }
750        } else {
751            // Same type, compare values
752            match (self, other) {
753                (Literal::Empty, Literal::Empty) => Some(Ordering::Equal),
754                (Literal::Bool(a), Literal::Bool(b)) => a.partial_cmp(b),
755                (Literal::Date(a), Literal::Date(b)) => a.partial_cmp(b),
756                (Literal::Number(a), Literal::Number(b)) => a.partial_cmp(b),
757                (Literal::Task(status1, text1), Literal::Task(status2, text2)) => {
758                    // Order by status first: Some(true) > None > Some(false)
759                    match (status1, status2) {
760                        (Some(true), Some(false)) => Some(Ordering::Greater),
761                        (Some(true), None) => Some(Ordering::Greater),
762                        (None, Some(true)) => Some(Ordering::Less),
763                        (None, Some(false)) => Some(Ordering::Greater),
764                        (Some(false), Some(true)) => Some(Ordering::Less),
765                        (Some(false), None) => Some(Ordering::Less),
766                        // Same status types or both None, compare texts
767                        (Some(true), Some(true)) | (Some(false), Some(false)) | (None, None) => text1.partial_cmp(text2),
768                    }
769                },
770                (Literal::Text(a), Literal::Text(b)) => a.partial_cmp(b),
771                _ => Some(Ordering::Equal), // This shouldn't happen due to type ordering check above
772            }
773        }
774    }
775}
776
777impl Eq for Literal {}
778
779impl Ord for Literal {
780    fn cmp(&self, other: &Self) -> Ordering {
781        // Use partial_cmp, but provide a fallback for None cases
782        self.partial_cmp(other).unwrap_or(Ordering::Equal)
783    }
784}
785
786/// Parse a literal value from input text according to AIM grammar rules.
787///
788/// This is the main entry point for parsing literal values in AIM expressions.
789/// It attempts to parse the input as one of the supported literal types:
790/// boolean, date, number, task, or text. The parser uses a precedence order
791/// that matches the grammar's operator precedence rules.
792///
793/// # Supported Literal Types
794///
795/// - **Boolean**: `true` or `false` (case-sensitive)
796/// - **Date**: Various date formats supported by [`parse_date`]
797/// - **Number**: Floating-point numbers with optional sign and decimal point
798/// - **Task**: Task literals with optional status: `[+] text`, `[-] text`, `[ ] text`
799/// - **Text**: Quoted strings using [`parse_text`]
800///
801/// # Arguments
802///
803/// * `input` - A string slice containing the literal to parse
804///
805/// # Returns
806///
807/// * `IResult<&str, Literal>` - A nom parser result containing:
808///   - Remaining input after parsing the literal
809///   - Parsed `Literal` value
810///
811/// # Examples
812///
813/// ```rust
814/// use aimx::{parse_literal, Literal};
815///
816/// // Parse boolean
817/// let (remaining, literal) = parse_literal("true").unwrap();
818/// assert_eq!(remaining, "");
819/// assert_eq!(literal, Literal::Bool(true));
820///
821/// // Parse number
822/// let (remaining, literal) = parse_literal("42.5").unwrap();
823/// assert_eq!(remaining, "");
824/// assert_eq!(literal, Literal::Number(42.5));
825///
826/// // Parse task
827/// let (remaining, literal) = parse_literal("[+] 'Complete task'").unwrap();
828/// assert_eq!(remaining, "");
829/// assert_eq!(literal, Literal::Task(Some(true), "Complete task".to_string()));
830///
831/// // Parse text
832/// let (remaining, literal) = parse_literal("'hello world'").unwrap();
833/// assert_eq!(remaining, "");
834/// assert_eq!(literal, Literal::Text("hello world".to_string()));
835/// ```
836///
837/// # Error Handling
838///
839/// Returns a nom error if the input cannot be parsed as any supported literal type.
840/// The parser will try each type in order until one succeeds or all fail.
841///
842/// # See Also
843///
844/// - [`parse_bool`] - Boolean-specific parser
845/// - [`parse_task`] - Task-specific parser
846/// - [`parse_date`], [`parse_number`], [`parse_text`] - Type-specific parsers in [`crate::literals`] module
847pub fn parse_literal(input: &str) -> IResult<&str, Literal> {
848    let (input, _) = multispace0.parse(input)?;
849    let (input, literal) = alt((
850        map(parse_bool, Literal::Bool),
851        map(parse_date, Literal::Date),
852        map(parse_number, Literal::Number),
853        map(parse_task, |(status, text)| Literal::Task(status, text)),
854        map(parse_text, Literal::Text),
855    ))
856    .parse(input)?;
857    let (input, _) = multispace0.parse(input)?;
858    Ok((input, literal))
859}
860
861/// Parse a boolean literal: `true` or `false`.
862///
863/// This parser recognizes the exact string literals `"true"` and `"false"`
864/// (case-sensitive) as boolean values. It does not accept variations like
865/// `TRUE`, `True`, or numeric representations.
866///
867/// # Arguments
868///
869/// * `input` - A string slice containing the boolean literal to parse
870///
871/// # Returns
872///
873/// * `IResult<&str, bool>` - A nom parser result containing:
874///   - Remaining input after parsing the boolean
875///   - Parsed `bool` value (`true` or `false`)
876///
877/// # Examples
878///
879/// ```rust
880/// use aimx::parse_bool;
881///
882/// let (remaining, value) = parse_bool("true").unwrap();
883/// assert_eq!(remaining, "");
884/// assert_eq!(value, true);
885///
886/// let (remaining, value) = parse_bool("false and more").unwrap();
887/// assert_eq!(remaining, " and more");
888/// assert_eq!(value, false);
889/// ```
890///
891/// # Error Handling
892///
893/// Returns a nom error if the input does not start with `"true"` or `"false"`.
894/// The parser is exact and does not perform case conversion or fuzzy matching.
895pub fn parse_bool(input: &str) -> IResult<&str, bool> {
896    alt((map(tag("true"), |_| true), map(tag("false"), |_| false))).parse(input)
897}
898
899/// Parse a task literal: `[status] description`.
900///
901/// Task literals have a specific syntax that includes an optional status
902/// indicator followed by a text description. The status can be:
903/// - `+` or omitted: Represents a completed task (`Some(true)`)
904/// - `-`: Represents a failed task (`Some(false)`)
905/// - Empty space ` `: Represents a pending task (`None`)
906///
907/// # Syntax
908///
909/// ```text
910/// [status] description
911/// ```
912///
913/// Where `status` is optional and can be:
914/// - `+` for completed (positive)
915/// - `-` for failed (negative)  
916/// - ` ` (space) or omitted for pending
917///
918/// # Arguments
919///
920/// * `input` - A string slice containing the task literal to parse
921///
922/// # Returns
923///
924/// * `IResult<&str, (Option<bool>, String)>` - A nom parser result containing:
925///   - Remaining input after parsing the task
926///   - Tuple with optional status (`Some(bool)`) and description text
927///
928/// # Examples
929///
930/// ```rust
931/// use aimx::parse_task;
932///
933/// // Completed task
934/// let (remaining, (status, text)) = parse_task("[+] 'Complete assignment'").unwrap();
935/// assert_eq!(remaining, "");
936/// assert_eq!(status, Some(true));
937/// assert_eq!(text, "Complete assignment");
938///
939/// // Failed task
940/// let (remaining, (status, text)) = parse_task("[-] 'Failed attempt'").unwrap();
941/// assert_eq!(remaining, "");
942/// assert_eq!(status, Some(false));
943/// assert_eq!(text, "Failed attempt");
944///
945/// // Pending task
946/// let (remaining, (status, text)) = parse_task("[ ] 'Pending review'").unwrap();
947/// assert_eq!(remaining, "");
948/// assert_eq!(status, None);
949/// assert_eq!(text, "Pending review");
950/// ```
951///
952/// # Error Handling
953///
954/// Returns a nom error if the input does not follow the task literal syntax:
955/// - Missing opening bracket `[`
956/// - Missing closing bracket `]`
957/// - Invalid status character (only `+`, `-`, or space allowed)
958///
959/// # See Also
960///
961/// - [`Literal::Task`] - The task literal variant
962/// - [`parse_text`] - Used to parse the task description text
963pub fn parse_task(input: &str) -> IResult<&str, (Option<bool>, String)> {
964    let (input, _) = char('[').parse(input)?;
965    let (input, _) = multispace0.parse(input)?;
966
967    // Parse optional status
968    let (input, status) =
969        opt(alt((map(char('+'), |_| true), map(char('-'), |_| false)))).parse(input)?;
970
971    let (input, _) = multispace0.parse(input)?;
972    let (input, _) = char(']').parse(input)?;
973    let (input, _) = multispace0.parse(input)?;
974
975    // Parse the task text (take everything until end or significant delimiter)
976    let (input, text) = parse_text(input)?;
977    Ok((input, (status, text)))
978}
979
980impl ExpressionLike for Literal {
981    fn evaluate(&self, _context: &mut dyn ContextLike) -> Result<Value> {
982        Ok(Value::Literal(self.clone()))
983    }
984
985    fn write(&self, writer: &mut Writer) {
986        writer.print_literal(self);
987    }
988    fn to_sanitized(&self) -> String {
989        let mut writer = Writer::sanitizer();
990        writer.print_literal(self);
991        writer.finish()
992    }
993    fn to_formula(&self) -> String {
994        let mut writer = Writer::formulizer();
995        writer.print_literal(self);
996        writer.finish()
997    }
998}
999
1000impl fmt::Display for Literal {
1001    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1002        let mut writer = Writer::stringizer();
1003        writer.print_literal(self);
1004        write!(f, "{}", writer.finish())
1005    }
1006}
1007