aimx/
typedef.rs

1//! Type definitions for the AIM expression grammar.
2//!
3//! This module provides type definitions and parsing for the type system used
4//! in the AIM expression language. It includes basic types like Bool, Date,
5//! Number, Task, and Text, as well as array variants and special types like
6//! Closure, Eval, Format, and Node.
7//!
8//! The `Typedef` enum represents the complete type system for AIM expressions,
9//! supporting type checking, casting operations, and function signature validation.
10//! Type definitions are used throughout the expression evaluation system to ensure
11//! type safety and enable automatic type promotion.
12//!
13//! # Supported Types
14//!
15//! ## Basic Types
16//! - `Any` - Any type (wildcard type that matches any value)
17//! - `Bool` - Boolean values (`true`/`false`)
18//! - `Date` - Date and time values
19//! - `Number` - 64-bit floating point numbers
20//! - `Task` - Task primitives with status and text
21//! - `Text` - String values
22//!
23//! ## Array Types
24//! - `Any[]` - Array of any values (heterogeneous)
25//! - `Bool[]` - Arrays of boolean values
26//! - `Date[]` - Arrays of date values
27//! - `Number[]` - Arrays of number values
28//! - `Task[]` - Arrays of task values
29//! - `Text[]` - Arrays of text values
30//!
31//! ## Special Types
32//! - `Closure` - Closure expression type (anonymous functions)
33//! - `Eval` - Evaluation results (inference output)
34//! - `Format` - Formatting instructions (output formatting)
35//! - `Node` - Node references (workflow references)
36//!
37//! # Type Promotion Rules
38//!
39//! AIMX uses an intuitive type promotion strategy where the left operand's type
40//! generally dictates the conversion for the right operand. This allows for
41//! expressive, convenient formulas while preserving type safety.
42//!
43//! # Examples
44//!
45//! ```text
46//! // Type casting examples
47//! (Bool)true        // cast to boolean
48//! (Number)"123"     // cast to number
49//! (Text[])items     // cast to text array
50//!
51//! // Function signature examples
52//! task.done()       // requires Typedef::Task
53//! numbers.sum()     // requires Typedef::NumberArray
54//! text.upper()      // requires Typedef::Text
55//! ```
56//!
57//! # Usage
58//!
59//! Type definitions are primarily used for:
60//! - Type casting operations in expressions
61//! - Function signature validation
62//! - Method dispatch based on receiver type
63//! - Type checking during expression evaluation
64//!
65//! See also: [`parse_typedef`], [`parse_literal_type`], [`Typedef`]
66
67use nom::{
68    IResult,
69    error::Error,
70    Err as NomErr,
71    branch::alt,
72    bytes::complete::tag,
73    combinator::opt,
74    Parser,
75};
76use crate::{
77    Writer,
78    ContextLike,
79    ExpressionLike,
80    Value,
81};
82use std::fmt;
83use anyhow::{anyhow, Result};
84
85/// Represents type definitions in the AIM expression grammar.
86/// 
87/// The `Typedef` enum provides a complete type system for the AIM expression
88/// language, including basic types, array types, and special-purpose types.
89/// These type definitions are used throughout the expression evaluation system
90/// for type checking, casting operations, function signature validation, and
91/// method dispatch.
92/// 
93/// # Type Safety and Promotion
94/// 
95/// AIMX uses a robust type system with automatic type promotion. The system
96/// follows a left-operand-first strategy where the left operand's type determines
97/// how the right operand is promoted. This provides expressive power while
98/// maintaining type safety.
99/// 
100/// # Variants
101/// 
102/// ## Basic Types
103/// * `Any` - Wildcard type that matches any value
104/// * `Bool` - Boolean values (`true`/`false`)
105/// * `Date` - Date and time values
106/// * `Number` - 64-bit floating point numbers
107/// * `Task` - Task primitives with status and text
108/// * `Text` - String values
109/// 
110/// ## Array Types
111/// * `Array` - Array of any values (heterogeneous)
112/// * `BoolArray` - Arrays of boolean values
113/// * `DateArray` - Arrays of date values
114/// * `NumberArray` - Arrays of number values
115/// * `TaskArray` - Arrays of task values
116/// * `TextArray` - Arrays of text values
117/// 
118/// ## Special Types
119/// * `Closure` - Closure expression type (anonymous functions)
120/// * `Eval` - Evaluation result type (inference output)
121/// * `Format` - Formatting instruction type (output formatting)
122/// * `Node` - Node reference type (workflow references)
123/// 
124/// # Examples
125/// 
126/// ```rust
127/// use aimx::typedef::Typedef;
128/// 
129/// // Basic type checking
130/// assert!(Typedef::Bool.is_bool());
131/// assert!(Typedef::NumberArray.is_array());
132/// 
133/// // Type conversion
134/// let text_type = Typedef::Text;
135/// assert_eq!(text_type.as_string(), "Text");
136/// 
137/// // Array type recognition
138/// let number_array = Typedef::NumberArray;
139/// assert!(number_array.is_number());
140/// assert!(number_array.is_array());
141/// ```
142/// 
143/// See also: [`parse_typedef`], [`parse_literal_type`]
144#[derive(Debug, Clone, PartialEq)]
145pub enum Typedef {
146    /// Any type
147    Any,
148    /// Generic Array
149    Array,
150    /// Boolean type
151    Bool,
152    /// Array of boolean values
153    BoolArray,
154    /// Date and time type
155    Date,
156    /// Array of date values
157    DateArray,
158    /// Number (64-bit float) type
159    Number,
160    /// Array of number values
161    NumberArray,
162    /// Task primitive type
163    Task,
164    /// Array of task values
165    TaskArray,
166    /// Text/string type
167    Text,
168    /// Array of text values
169    TextArray,
170
171    /// Closure expression type
172    Closure,
173    /// Evaluation result type
174    Eval,
175    /// Formatting instruction type
176    Format,
177    /// Node reference type
178    Node,
179}
180
181impl Typedef {
182    /// Check if this type definition represents the Any type.
183    /// 
184    /// # Returns
185    /// 
186    /// * `bool` - True if this is the Any type, false otherwise
187    pub fn is_any(&self) -> bool {
188        match self {
189            Typedef::Any | Typedef::Array => true,
190            _ => false,
191        }
192    }
193
194    /// Check if this type definition represents the Any Array type.
195    /// 
196    /// # Returns
197    /// 
198    /// * `bool` - True if this is the Any Array type, false otherwise
199    pub fn is_any_array(&self) -> bool {
200        match self {
201            Typedef::Array => true,
202            _ => false,
203        }
204    }
205    
206    /// Check if this type definition represents a Bool or BoolArray type.
207    /// 
208    /// # Returns
209    /// 
210    /// * `bool` - True if this is a Bool or BoolArray type, false otherwise
211    pub fn is_bool(&self) -> bool {
212        match self {
213            Typedef::Bool | Typedef::BoolArray => true,
214            _ => false,
215        }
216    }
217    
218    /// Check if this type definition represents a Date or DateArray type.
219    /// 
220    /// # Returns
221    /// 
222    /// * `bool` - True if this is a Date or DateArray type, false otherwise
223    pub fn is_date(&self) -> bool {
224        match self {
225            Typedef::Date | Typedef::DateArray => true,
226            _ => false,
227        }
228    }
229    
230    /// Check if this type definition represents a Number or NumberArray type.
231    /// 
232    /// # Returns
233    /// 
234    /// * `bool` - True if this is a Number or NumberArray type, false otherwise
235    pub fn is_number(&self) -> bool {
236        match self {
237            Typedef::Number | Typedef::NumberArray => true,
238            _ => false,
239        }
240    }
241    
242    /// Check if this type definition represents a Task or TaskArray type.
243    /// 
244    /// # Returns
245    /// 
246    /// * `bool` - True if this is a Task or TaskArray type, false otherwise
247    pub fn is_task(&self) -> bool {
248        match self {
249            Typedef::Task | Typedef::TaskArray => true,
250            _ => false,
251        }
252    }
253    
254    /// Check if this type definition represents a Text or TextArray type.
255    /// 
256    /// # Returns
257    /// 
258    /// * `bool` - True if this is a Text or TextArray type, false otherwise
259    pub fn is_text(&self) -> bool {
260        match self {
261            Typedef::Text | Typedef::TextArray => true,
262            _ => false,
263        }
264    }
265    
266    /// Check if this type definition represents a Literal type.
267    /// 
268    /// Literal types are the basic value types that can be directly represented
269    /// in expressions without requiring complex evaluation.
270    /// 
271    /// # Returns
272    /// 
273    /// * `bool` - True if this is a Literal type, false otherwise
274    pub fn is_literal(&self) -> bool {
275        match self {
276            Typedef::Bool
277            | Typedef::Number
278            | Typedef::Date
279            | Typedef::Task
280            | Typedef::Text => true,
281            _ => false,
282        }
283    }
284
285    /// Convert this type definition to its corresponding literal type.
286    /// 
287    /// This method strips array qualifiers and returns the base literal type.
288    /// For example, `NumberArray` becomes `Number`, `TextArray` becomes `Text`.
289    /// Special types remain unchanged.
290    /// 
291    /// # Returns
292    /// 
293    /// * `Typedef` - The corresponding literal type
294    /// 
295    /// # Examples
296    /// 
297    /// ```rust
298    /// use aimx::typedef::Typedef;
299    /// 
300    /// assert_eq!(Typedef::NumberArray.as_literal(), Typedef::Number);
301    /// assert_eq!(Typedef::Text.as_literal(), Typedef::Text);
302    /// assert_eq!(Typedef::Closure.as_literal(), Typedef::Closure);
303    /// ```
304    pub fn as_literal(&self) -> Self {
305       match self {
306            Typedef::Any | Typedef::Array => Typedef::Any,
307            Typedef::Bool | Typedef::BoolArray => Typedef::Bool,
308            Typedef::Number | Typedef::NumberArray => Typedef::Number,
309            Typedef::Date | Typedef::DateArray => Typedef::Date,
310            Typedef::Task | Typedef::TaskArray => Typedef::Task,
311            Typedef::Text | Typedef::TextArray => Typedef::Text,
312            Typedef::Closure => Typedef::Closure,
313            Typedef::Eval => Typedef::Eval,
314            Typedef::Format => Typedef::Format,
315            Typedef::Node => Typedef::Node,
316        }
317    }
318
319    /// Check if this type definition represents an array type.
320    /// 
321    /// # Returns
322    /// 
323    /// * `bool` - True if this is an array type, false otherwise
324    pub fn is_array(&self) -> bool {
325        match self {
326            Typedef::Array
327            | Typedef::BoolArray
328            | Typedef::NumberArray
329            | Typedef::DateArray
330            | Typedef::TaskArray
331            | Typedef::TextArray => true,
332            _ => false,
333        }
334    }
335
336    /// Convert this type definition to its corresponding array type.
337    /// 
338    /// This method adds array qualifiers to literal types. For example,
339    /// `Number` becomes `NumberArray`, `Text` becomes `TextArray`.
340    /// Special types remain unchanged.
341    /// 
342    /// # Returns
343    /// 
344    /// * `Typedef` - The corresponding array type
345    /// 
346    /// # Examples
347    /// 
348    /// ```rust
349    /// use aimx::typedef::Typedef;
350    /// 
351    /// assert_eq!(Typedef::Number.as_array(), Typedef::NumberArray);
352    /// assert_eq!(Typedef::TextArray.as_array(), Typedef::TextArray);
353    /// assert_eq!(Typedef::Closure.as_array(), Typedef::Closure);
354    /// ```
355    pub fn as_array(&self) -> Self {
356       match self {
357            Typedef::Any | Typedef::Array => Typedef::Array,
358            Typedef::Bool | Typedef::BoolArray => Typedef::BoolArray,
359            Typedef::Number | Typedef::NumberArray => Typedef::NumberArray,
360            Typedef::Date | Typedef::DateArray => Typedef::DateArray,
361            Typedef::Task | Typedef::TaskArray => Typedef::TaskArray,
362            Typedef::Text | Typedef::TextArray => Typedef::TextArray,
363            Typedef::Closure => Typedef::Closure,
364            Typedef::Eval => Typedef::Eval,
365            Typedef::Format => Typedef::Format,
366            Typedef::Node => Typedef::Node,
367        }
368    }
369
370    /// Check if this type definition represents the Format type.
371    /// 
372    /// # Returns
373    /// 
374    /// * `bool` - True if this is the Format type, false otherwise
375    pub fn is_format(&self) -> bool {
376        match self {
377            Typedef::Format => true,
378            _ => false,
379        }
380    }
381    
382    /// Check if this type definition represents the Eval type.
383    /// 
384    /// # Returns
385    /// 
386    /// * `bool` - True if this is the Eval type, false otherwise
387    pub fn is_eval(&self) -> bool {
388        match self {
389            Typedef::Eval => true,
390            _ => false,
391        }
392    }
393    
394    /// Check if this type definition represents a Node type.
395    /// 
396    /// # Returns
397    /// 
398    /// * `bool` - True if this is a Node type, false otherwise
399    pub fn is_node(&self) -> bool {
400        match self {
401            Typedef::Node => true,
402            _ => false,
403        }
404    }
405    
406    /// Check if this type definition represents the Closure type.
407    /// 
408    /// # Returns
409    /// 
410    /// * `bool` - True if this is the Closure type, false otherwise
411    pub fn is_closure(&self) -> bool {
412        match self {
413            Typedef::Closure => true,
414            _ => false,
415        }
416    }
417    
418    /// Check if this type definition represents an special type.
419    /// 
420    /// Special types are those that don't represent literal values but rather
421    /// serve specific purposes in the expression system.
422    /// 
423    /// # Returns
424    /// 
425    /// * `bool` - True if this is a Format, Eval, Node or Closure type, false otherwise
426    pub fn is_special(&self) -> bool {
427        match self {
428            Typedef::Closure
429            | Typedef::Format
430            | Typedef::Eval
431            | Typedef::Node => true,
432            _ => false,
433        }
434    }
435
436    /// Get the string representation of this type definition.
437    /// 
438    /// Returns the canonical string representation used in AIM expressions.
439    /// This is the same format that would appear in type casting operations.
440    /// 
441    /// # Returns
442    /// 
443    /// * `&'static str` - The string representation of the type
444    /// 
445    /// # Examples
446    /// 
447    /// ```rust
448    /// use aimx::typedef::Typedef;
449    /// 
450    /// assert_eq!(Typedef::Bool.as_string(), "Bool");
451    /// assert_eq!(Typedef::NumberArray.as_string(), "Number[]");
452    /// assert_eq!(Typedef::Closure.as_string(), "Closure");
453    /// ```
454    pub fn as_string(&self) -> &'static str {
455        match self {
456            Typedef::Any => "Any",
457            Typedef::Array => "Any[]",
458            Typedef::Bool => "Bool",
459            Typedef::BoolArray => "Bool[]",
460            Typedef::Date => "Date",
461            Typedef::DateArray => "Date[]",
462            Typedef::Number => "Number",
463            Typedef::NumberArray => "Number[]",
464            Typedef::Task => "Task",
465            Typedef::TaskArray => "Task[]",
466            Typedef::Text => "Text",
467            Typedef::TextArray => "Text[]",
468
469            Typedef::Closure => "Closure",
470            Typedef::Eval => "Eval",
471            Typedef::Format => "Format",
472            Typedef::Node => "Node",
473        }
474    }
475}
476
477/// Parse a type definition from a string according to the AIM expression grammar syntax.
478/// 
479/// This function parses type names and array markers to create the appropriate
480/// Typedef variant. It supports both basic types and array types.
481/// 
482/// # Supported Type Names
483/// - `Any` - Wildcard type that matches any value
484/// - `Bool` - Boolean type
485/// - `Date` - Date type
486/// - `Number` - Number type
487/// - `Task` - Task type
488/// - `Text` - Text type
489/// 
490/// # Special Types
491/// - `Eval` - Evaluation type
492/// - `Format` - Format type
493/// - `Node` - Node type
494/// 
495/// # Arguments
496/// 
497/// * `input` - A string slice containing the type definition to parse
498/// 
499/// # Returns
500/// 
501/// * `IResult<&str, Typedef>` - A nom result with remaining input and parsed type definition
502/// 
503/// # Examples
504/// 
505/// ```rust
506/// use aimx::typedef::{parse_typedef, Typedef};
507/// 
508/// assert_eq!(parse_typedef("Bool"), Ok(("", Typedef::Bool)));
509/// assert_eq!(parse_typedef("Number[]"), Ok(("", Typedef::NumberArray)));
510/// assert_eq!(parse_typedef("Text[]"), Ok(("", Typedef::TextArray)));
511/// ```
512pub fn parse_typedef(input: &str) -> IResult<&str, Typedef> {
513
514    // Parse type marker
515    let (input, type_marker) = alt((
516        tag("Any"),
517        tag("Bool"),
518        tag("Date"),
519        tag("Number"),
520        tag("Task"),
521        tag("Text"),
522
523        tag("Closure"),
524        tag("Eval"),
525        tag("Format"),
526        tag("Node"),
527    )).parse(input)?;
528
529    // Parse array marker if present
530    let (input, array_marker) = opt(tag("[]")).parse(input)?;
531    let is_array = array_marker.is_some();
532
533    let typedef = match (type_marker, is_array) {
534        ("Any", false) => Typedef::Any,
535        ("Any", true) => Typedef::Array,
536        ("Bool", false) => Typedef::Bool,
537        ("Bool", true) => Typedef::BoolArray,
538        ("Date", false) => Typedef::Date,
539        ("Date", true) => Typedef::DateArray,
540        ("Number", false) => Typedef::Number,
541        ("Number", true) => Typedef::NumberArray,
542        ("Task", false) => Typedef::Task,
543        ("Task", true) => Typedef::TaskArray,
544        ("Text", false) => Typedef::Text,
545        ("Text", true) => Typedef::TextArray,
546
547        ("Closure", false) => Typedef::Closure,
548        ("Eval", false) => Typedef::Eval,
549        ("Format", false) => Typedef::Format,
550        ("Node", false) => Typedef::Node,
551        _ => return Err(NomErr::Failure(Error::new(input, nom::error::ErrorKind::Fail))),
552    };
553
554    Ok((input, typedef))
555}
556
557/// Parse a literal type definition from a string.
558/// 
559/// This function is similar to [`parse_typedef`] but only accepts literal types
560/// (Bool, Date, Number, Task, Text) and does not support array types or special types.
561/// It's used in contexts where only basic value types are expected.
562/// 
563/// # Arguments
564/// 
565/// * `input` - A string slice containing the literal type definition to parse
566/// 
567/// # Returns
568/// 
569/// * `IResult<&str, Typedef>` - A nom result with remaining input and parsed literal type
570/// 
571/// # Examples
572/// 
573/// ```rust
574/// use aimx::typedef::{parse_literal_type, Typedef};
575/// 
576/// assert_eq!(parse_literal_type("Bool"), Ok(("", Typedef::Bool)));
577/// assert_eq!(parse_literal_type("Number"), Ok(("", Typedef::Number)));
578/// assert_eq!(parse_literal_type("Text"), Ok(("", Typedef::Text)));
579/// ```
580pub fn parse_literal_type(input: &str) -> IResult<&str, Typedef> {
581    // Parse type marker
582    let (input, type_marker) = alt((
583        tag("Bool"),
584        tag("Date"),
585        tag("Number"),
586        tag("Task"),
587        tag("Text"),
588    )).parse(input)?;
589    let typedef = match type_marker {
590        "Bool" => Typedef::Bool,
591        "Date" => Typedef::Date,
592        "Number" => Typedef::Number,
593        "Task" => Typedef::Task,
594        "Text" => Typedef::Text,
595        _ => unreachable!(),
596    };
597    Ok((input, typedef))
598}
599
600impl ExpressionLike for Typedef {
601    fn evaluate(&self, _context: &mut dyn ContextLike) -> Result<Value> {
602        Err(anyhow!("Typedef cannot be evaluated"))
603    }
604    
605    fn write(&self, writer: &mut Writer) {
606        writer.write_str(self.as_string());
607    }
608    fn to_sanitized(&self) -> String {
609        let mut writer = Writer::sanitizer();
610        writer.write_str(self.as_string());
611        writer.finish()
612    }
613    fn to_formula(&self) -> String {
614        let mut writer = Writer::formulizer();
615        writer.write_str(self.as_string());
616        writer.finish()
617    }
618}
619
620impl fmt::Display for Typedef {
621    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
622        let mut writer = Writer::stringizer();
623        writer.write_str(self.as_string());
624        write!(f, "{}", writer.finish())
625    }
626}
627