aimx/expressions/
primary.rs

1//! Primary expression parsing and evaluation for the AIMX grammar.
2//!
3//! This module provides the infrastructure for parsing and evaluating **primary expressions**,
4//! which form the foundation of the AIMX (Agentic Inference Markup Expressions) language.
5//! Primary expressions represent the most fundamental building blocks that all other
6//! expressions are built upon, including literals, variable references, and parenthesized
7//! expressions.
8//!
9//! Primary expressions have the highest precedence in the AIMX grammar hierarchy and are
10//! the first expressions parsed when building the abstract syntax tree (AST).
11//!
12//! # Primary Expression Types
13//!
14//! - **Literals** - Boolean, Date, Number, Task, and Text values
15//! - **References** - Variable and field references using dot notation
16//! - **Parentheses** - Grouped expressions `(expression)` that override precedence
17//!
18//! # Examples
19//!
20//! ```text
21//! 42                // number literal
22//! "hello"           // text literal
23//! true              // boolean literal
24//! foo               // simple variable reference
25//! data.items        // chained field reference
26//! (1 + 2) * 3       // parenthesized expression
27//! ```
28//!
29//! # AST Flattening Optimization
30//!
31//! The `Primary` enum includes variants for all higher-level expression types as part of an
32//! AST flattening optimization. This allows expressions that consist solely of primary
33//! components to be evaluated more efficiently without deep recursion through the expression
34//! hierarchy.
35//!
36//! # Usage
37//!
38//! Primary expressions are typically used internally by the AIMX parser but can also be
39//! used directly for parsing simple expressions or when working with literals and references
40//! in isolation.
41//!
42//! ```rust
43//! use aimx::{Primary};
44//! use aimx::expressions::{parse_primary};
45//! use aimx::Literal;
46//!
47//! // Parse a simple literal
48//! let (remaining, primary) = parse_primary("42").unwrap();
49//! assert_eq!(remaining, "");
50//! assert!(matches!(primary, Primary::Literal(Literal::Number(_))));
51//!
52//! // Parse a reference
53//! let (remaining, primary) = parse_primary("variable_name").unwrap();
54//! assert_eq!(remaining, "");
55//! assert!(matches!(primary, Primary::Reference(_)));
56//! ```
57
58use nom::{
59    IResult,
60    Parser,
61    branch::alt,
62    character::complete::{char, multispace0},
63    combinator::map,
64};
65use crate::{
66    ContextLike,
67    Expression,
68    ExpressionLike,
69    parse_expression,
70    expressions::{
71        Additive,
72        Closure,
73        Conditional,
74        Equality,
75        LogicalAnd, 
76        LogicalOr,
77        Multiplicative,
78        Postfix,
79        parse_reference,
80        Relational,
81        Unary,
82    },
83    Literal,
84    parse_literal,
85    Reference,
86    Value,
87    Writer, 
88};
89use std::fmt;
90use anyhow::Result;
91
92/// Represents a primary expression in the AIMX grammar.
93///
94/// Primary expressions are the fundamental building blocks of expressions in
95/// the AIMX language. They include literal values, variable references, and
96/// parenthesized expressions. Primary expressions form the base of the
97/// expression hierarchy, with other expression types building upon them.
98///
99/// The `Primary` enum uses AST flattening optimization, where it includes
100/// variants for all higher-level expression types. This allows expressions
101/// that consist solely of primary components to be evaluated more efficiently
102/// without deep recursion through the expression hierarchy.
103///
104/// # Variants
105///
106/// - [`Literal`](Primary::Literal) - A literal value (Bool, Date, Number, Task, Text, or Empty)
107/// - [`Reference`](Primary::Reference) - A variable or field reference
108/// - [`Parentheses`](Primary::Parentheses) - A parenthesized expression
109/// - [`Postfix`](Primary::Postfix) - Postfix operations (method calls, indexing, function calls)
110/// - [`Unary`](Primary::Unary) - Unary operations (logical NOT, arithmetic negation, casts)
111/// - [`Multiplicative`](Primary::Multiplicative) - Multiplicative operations (`*`, `/`, `%`)
112/// - [`Additive`](Primary::Additive) - Additive operations (`+`, `-`)
113/// - [`Relational`](Primary::Relational) - Relational operations (`<`, `<=`, `>`, `>=`)
114/// - [`Equality`](Primary::Equality) - Equality operations (`=`, `!=`)
115/// - [`LogicalAnd`](Primary::LogicalAnd) - Logical AND operations (`&`, `&&`)
116/// - [`LogicalOr`](Primary::LogicalOr) - Logical OR operations (`|`, `||`)
117/// - [`Conditional`](Primary::Conditional) - Conditional operations (`?`, `:`)
118/// - [`Closure`](Primary::Closure) - Closure operations (`=>`)
119///
120/// # AST Flattening
121///
122/// The flattened variants (Postfix through Closure) are populated during parsing
123/// when an expression contains higher-level operators but can be represented
124/// efficiently within the `Primary` enum. This optimization reduces AST depth
125/// and improves evaluation performance.
126///
127/// # Examples
128///
129/// ```rust
130/// use aimx::{Primary};
131/// use aimx::expressions::{parse_primary};
132/// use aimx::Literal;
133///
134/// // Parse a literal expression
135/// let (_, primary) = parse_primary("42").unwrap();
136/// assert!(matches!(primary, Primary::Literal(Literal::Number(_))));
137///
138/// // Parse a reference expression
139/// let (_, primary) = parse_primary("variable_name").unwrap();
140/// assert!(matches!(primary, Primary::Reference(_)));
141///
142/// // Parse a parenthesized expression
143/// let (_, primary) = parse_primary("(1 + 2)").unwrap();
144/// assert!(matches!(primary, Primary::Parentheses(_)));
145/// ```
146///
147/// # See Also
148///
149/// - [`crate::expressions::parse_primary`] - Function to parse primary expressions from text
150/// - [`ExpressionLike`] - Trait for expression evaluation
151/// - [`Literal`] - Literal value representation
152/// - [`Reference`] - Variable reference representation
153#[derive(Debug, Clone, PartialEq)]
154pub enum Primary {
155    /// A literal value such as a number, text string, boolean, date, or task
156    Literal(Literal),
157    /// A variable or field reference
158    Reference(Reference),
159    /// A parenthesized expression
160    Parentheses(Expression),
161
162    // Flattened abstract syntax tree
163    Postfix(Postfix),
164    Unary(Unary),
165    Multiplicative(Multiplicative),
166    Additive(Additive),
167    Relational(Relational),
168    Equality(Equality),
169    LogicalAnd(LogicalAnd),
170    LogicalOr(LogicalOr),
171    Conditional(Conditional),
172    Closure(Closure),
173}
174
175impl Primary {
176    /// Check if this primary expression is a literal value.
177    ///
178    /// Returns `true` if this `Primary` variant is [`Literal`](Primary::Literal),
179    /// `false` otherwise.
180    ///
181    /// # Examples
182    ///
183    /// ```rust
184    /// use aimx::{Primary};
185    /// use aimx::expressions::{parse_primary};
186    /// use aimx::Literal;
187    ///
188    /// let (_, literal) = parse_primary("42").unwrap();
189    /// assert!(literal.is_literal());
190    ///
191    /// let (_, reference) = parse_primary("variable").unwrap();
192    /// assert!(!reference.is_literal());
193    /// ```
194    pub fn is_literal(&self) -> bool {
195        match self {
196            Primary::Literal(_) => true,
197            _ => false,
198        }
199    }
200    
201    /// Check if this primary expression is a variable or field reference.
202    ///
203    /// Returns `true` if this `Primary` variant is [`Reference`](Primary::Reference),
204    /// `false` otherwise.
205    ///
206    /// # Examples
207    ///
208    /// ```rust
209    /// use aimx::{Primary};
210    /// use aimx::expressions::{parse_primary};
211    ///
212    /// let (_, reference) = parse_primary("variable").unwrap();
213    /// assert!(reference.is_reference());
214    ///
215    /// let (_, literal) = parse_primary("42").unwrap();
216    /// assert!(!literal.is_reference());
217    /// ```
218    pub fn is_reference(&self) -> bool {
219        match self {
220            Primary::Reference(_) => true,
221            _ => false,
222        }
223    }
224}
225
226/// Parse a primary expression from text input.
227///
228/// This function parses the fundamental building blocks of expressions in the
229/// AIMX grammar, including literal values, references, and parenthesized expressions.
230/// It serves as the base parser for the expression grammar hierarchy and is used
231/// internally by higher-level parsers to handle the highest precedence expressions.
232///
233/// # Arguments
234///
235/// * `input` - A string slice containing the primary expression to parse
236///
237/// # Returns
238///
239/// Returns an [`IResult<&str, Primary>`] containing:
240/// - The remaining unparsed input
241/// - A parsed [`Primary`] expression
242///
243/// # Grammar
244///
245/// The primary expression grammar follows:
246/// ```text
247/// primary = literal | reference | '(' expression ')'
248/// ```
249///
250/// Where:
251/// - `literal` represents any valid literal value (number, text, boolean, date, task)
252/// - `reference` represents a variable or field reference
253/// - `expression` represents any valid AIMX expression
254///
255/// # Examples
256///
257/// ```rust
258/// use aimx::{Primary};
259/// use aimx::expressions::{parse_primary};
260/// use aimx::Literal;
261///
262/// // Parse a number literal
263/// let (remaining, primary) = parse_primary("42").unwrap();
264/// assert_eq!(remaining, "");
265/// assert!(matches!(primary, Primary::Literal(Literal::Number(_))));
266///
267/// // Parse a text literal
268/// let (remaining, primary) = parse_primary("\"hello\"").unwrap();
269/// assert_eq!(remaining, "");
270/// assert!(matches!(primary, Primary::Literal(Literal::Text(_))));
271///
272/// // Parse a variable reference
273/// let (remaining, primary) = parse_primary("variable_name").unwrap();
274/// assert_eq!(remaining, "");
275/// assert!(matches!(primary, Primary::Reference(_)));
276///
277/// // Parse a parenthesized expression
278/// let (remaining, primary) = parse_primary("(1 + 2)").unwrap();
279/// assert_eq!(remaining, "");
280/// assert!(matches!(primary, Primary::Parentheses(_)));
281/// ```
282///
283/// # See Also
284///
285/// - [`crate::expressions::parse_parentheses`] - Function for parsing parenthesized expressions
286/// - [`crate::literal::parse_literal`] - Function for parsing literal values
287/// - [`crate::expressions::reference::parse_reference`] - Function for parsing references
288pub fn parse_primary(input: &str) -> IResult<&str, Primary> {
289    alt((
290        map(parse_literal, Primary::Literal),
291        map(parse_reference, Primary::Reference),
292        map(parse_parentheses, |expression| Primary::Parentheses(expression)),
293    )).parse(input)
294}
295
296/// Parse a parenthesized expression.
297///
298/// This function parses expressions enclosed in parentheses, which are used
299/// to override operator precedence or group subexpressions. Parentheses allow
300/// explicit control over the evaluation order of complex expressions.
301///
302/// # Arguments
303///
304/// * `input` - A string slice containing the parenthesized expression to parse
305///
306/// # Returns
307///
308/// Returns an [`IResult<&str, Expression>`] containing:
309/// - The remaining unparsed input
310/// - A parsed [`Expression`] representing the parenthesized content
311///
312/// # Grammar
313///
314/// The parenthesized expression grammar follows:
315/// ```text
316/// parentheses = '(' S? expression S? ')'
317/// ```
318///
319/// Where `expression` represents any valid AIMX expression. Empty parentheses
320/// `()` are parsed as [`Expression::Empty`].
321///
322/// # Examples
323///
324/// ```rust
325/// use aimx::{Primary};
326/// use aimx::expressions::{parse_parentheses};
327/// use aimx::{Expression, Literal};
328///
329/// // Parse empty parentheses
330/// let (remaining, expr) = parse_parentheses("()").unwrap();
331/// assert_eq!(remaining, "");
332/// assert!(matches!(expr, Expression::Empty));
333///
334/// // Parse a simple parenthesized literal
335/// let (remaining, expr) = parse_parentheses("(42)").unwrap();
336/// assert_eq!(remaining, "");
337/// // The result will depend on how the inner expression "42" is parsed
338/// // It could be Expression::Primary(_) for simple literals
339///
340/// // Parse a complex parenthesized expression
341/// let (remaining, expr) = parse_parentheses("(1 + 2 * 3)").unwrap();
342/// assert_eq!(remaining, "");
343/// // The result depends on the specific expression parsed
344/// ```
345///
346/// # Implementation Details
347///
348/// This function handles:
349/// - Empty parentheses `()` by returning [`Expression::Empty`]
350/// - Whitespace around the parentheses
351/// - Recursive parsing of the inner expression
352/// - Proper error handling for mismatched parentheses
353///
354/// # See Also
355///
356/// - [`crate::expression::parse_expression`] - Function for parsing the inner expression
357/// - [`Expression::Empty`] - The variant returned for empty parentheses
358/// - [`Primary::Parentheses`] - The variant used when parenthesized expressions are parsed as primary expressions
359pub fn parse_parentheses(input: &str) -> IResult<&str, Expression> {
360    let (input, _) = char('(').parse(input)?;
361    let (input, _) = multispace0.parse(input)?;
362    if input.starts_with(')') {
363        let (input, _) = char(')').parse(input)?;
364        return Ok((input, Expression::Empty));
365    }
366    let (input, expression) = parse_expression(input)?;
367    let (input, _) = char(')').parse(input)?;
368    Ok((input, expression))
369}
370
371impl ExpressionLike for Primary {
372    /// Evaluate this primary expression within the given context.
373    ///
374    /// This method recursively evaluates the primary expression, delegating
375    /// to the appropriate evaluation methods for each variant. The evaluation
376    /// follows the AST flattening optimization where higher-level expression
377    /// variants are evaluated directly without recursion through the expression
378    /// hierarchy.
379    ///
380    /// # Arguments
381    ///
382    /// * `context` - The evaluation context providing variable values and function implementations
383    ///
384    /// # Returns
385    ///
386    /// Returns a [`Result<Value>`] containing the evaluated value if successful,
387    /// or an error if evaluation fails.
388    ///
389    /// # Evaluation Strategy
390    ///
391    /// - [`Literal`](Primary::Literal) expressions return their literal value
392    /// - [`Reference`](Primary::Reference) expressions look up the variable in the context
393    /// - [`Parentheses`](Primary::Parentheses) expressions evaluate the inner expression
394    /// - Flattened variants delegate to their respective evaluation methods
395    ///
396    /// # Examples
397    ///
398    /// ```rust
399    /// use aimx::{Primary};
400    /// use aimx::expressions::{parse_primary};
401    /// use aimx::{ContextLike, ExpressionLike, Literal};
402    ///
403    /// let mut context = aimx::Context::new();
404    /// 
405    /// // Evaluate a literal
406    /// let primary = Primary::Literal(Literal::Number(42.0));
407    /// let result = primary.evaluate(&mut context).unwrap();
408    /// assert_eq!(result.to_string(), "42");
409    /// ```
410    ///
411    /// # See Also
412    ///
413    /// - [`ExpressionLike`] - The trait being implemented
414    /// - [`Value`] - The result type returned by evaluation
415    /// - [`ContextLike`] - The context trait for evaluation
416    fn evaluate(&self, context: &mut dyn ContextLike) -> Result<Value> {
417        match self {
418            Primary::Literal(literal) => {
419                if literal.is_empty() {
420                    Ok(Value::Empty)
421                }
422                else {
423                    Ok(Value::Literal(literal.clone()))
424                }
425            }
426            Primary::Reference(reference) => reference.evaluate(context),
427            Primary::Parentheses(expression) => expression.evaluate(context),
428
429            Primary::Postfix(postfix) => postfix.evaluate(context),
430            Primary::Unary(unary) => unary.evaluate(context),
431            Primary::Multiplicative(multiplicative) => multiplicative.evaluate(context),
432            Primary::Additive(additive) => additive.evaluate(context),
433            Primary::Relational(relational) => relational.evaluate(context),
434            Primary::Equality(equality) => equality.evaluate(context),
435            Primary::LogicalAnd(logical_and) => logical_and.evaluate(context),
436            Primary::LogicalOr(logical_or) => logical_or.evaluate(context),
437            Primary::Conditional(conditional) => conditional.evaluate(context),
438            Primary::Closure(closure) => closure.evaluate(context),
439        }
440    }
441
442    /// Write this primary expression to a [`Writer`] for formatting.
443    ///
444    /// This method recursively writes the primary expression to the provided
445    /// writer, producing a formatted representation suitable for display
446    /// or serialization.
447    ///
448    /// # Arguments
449    ///
450    /// * `writer` - The writer to write the formatted expression to
451    ///
452    /// # Writing Strategy
453    ///
454    /// - [`Literal`](Primary::Literal) expressions write their literal representation
455    /// - [`Reference`](Primary::Reference) expressions write the reference path
456    /// - [`Parentheses`](Primary::Parentheses) expressions write parentheses around the inner expression
457    /// - Flattened variants delegate to their respective write methods
458    fn write(&self, writer: &mut Writer) {
459        match self {
460            Primary::Literal(literal) => literal.write(writer),
461            Primary::Reference(reference) => reference.write(writer),
462            Primary::Parentheses(expression) => {
463                writer.write_char('(');
464                expression.write(writer);
465                writer.write_char(')');
466            },
467
468            Primary::Postfix(postfix) => postfix.write(writer),
469            Primary::Unary(unary) => unary.write(writer),
470            Primary::Multiplicative(multiplicative) => multiplicative.write(writer),
471            Primary::Additive(additive) => additive.write(writer),
472            Primary::Relational(relational) => relational.write(writer),
473            Primary::Equality(equality) => equality.write(writer),
474            Primary::LogicalAnd(logical_and) => logical_and.write(writer),
475            Primary::LogicalOr(logical_or) => logical_or.write(writer),
476            Primary::Conditional(conditional) => conditional.write(writer),
477            Primary::Closure(closure) => closure.write(writer),
478        }
479    }
480    
481    /// Convert this primary expression to a sanitized string representation.
482    ///
483    /// Sanitized expressions are suitable for display purposes and may
484    /// omit certain implementation details or sensitive information.
485    ///
486    /// # Returns
487    ///
488    /// Returns a [`String`] containing the sanitized expression representation.
489    fn to_sanitized(&self) -> String {
490        let mut writer = Writer::sanitizer();
491        self.write(&mut writer);
492        writer.finish()
493    }
494    
495    /// Convert this primary expression to its original formula representation.
496    ///
497    /// The formula representation attempts to reconstruct the original
498    /// expression text as it was parsed, suitable for use in formulas
499    /// or serialization.
500    ///
501    /// # Returns
502    ///
503    /// Returns a [`String`] containing the formula representation.
504    fn to_formula(&self) -> String {
505        let mut writer = Writer::formulizer();
506        self.write(&mut writer);
507        writer.finish()
508    }
509}
510
511impl fmt::Display for Primary {
512    /// Format this primary expression as a string.
513    ///
514    /// This implementation delegates to the [`write`](ExpressionLike::write) method
515    /// using a string-based writer, producing a human-readable representation
516    /// of the expression.
517    ///
518    /// # Arguments
519    ///
520    /// * `f` - The formatter to write the string representation to
521    ///
522    /// # Returns
523    ///
524    /// Returns [`fmt::Result`] indicating success or failure of formatting.
525    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
526        let mut writer = Writer::stringizer();
527        self.write(&mut writer);
528        write!(f, "{}", writer.finish())
529    }
530}