Skip to main content

sigil_parser/
parser.rs

1//! Recursive descent parser for Sigil.
2//!
3//! Handles polysynthetic pipe chains, morpheme expressions, and evidentiality.
4
5use crate::ast::*;
6use crate::lexer::{Lexer, Token};
7use crate::span::{Span, Spanned};
8use thiserror::Error;
9
10#[derive(Error, Debug)]
11pub enum ParseError {
12    #[error("Unexpected token: expected {expected}, found {found:?} at {span}")]
13    UnexpectedToken {
14        expected: String,
15        found: Token,
16        span: Span,
17    },
18    #[error("Unexpected end of file")]
19    UnexpectedEof,
20    #[error("Invalid number literal: {0}")]
21    InvalidNumber(String),
22    #[error("Parse error: {0}")]
23    Custom(String),
24    #[error("Deprecated Rust syntax '{rust}' at {span}. Use Sigil's native syntax: {sigil}")]
25    DeprecatedRustSyntax {
26        rust: String,
27        sigil: String,
28        span: Span,
29    },
30}
31
32/// Maps deprecated Rust keywords to their Sigil equivalents
33fn rust_to_sigil(keyword: &str) -> &'static str {
34    match keyword {
35        "fn" => "rite (function declaration)",
36        "let" => "≔ (definition)",
37        "mut" => "Δ (delta/mutable)",
38        "const" => "◆ (diamond/const)",
39        "struct" => "Σ (sigma) or 'sigil'",
40        "enum" => "ᛈ (perthro rune)",
41        "trait" => "Θ (theta)",
42        "impl" => "⊢ (turnstile)",
43        "mod" => "scroll",
44        "use" => "invoke",
45        "pub" => "☉ (sun/public)",
46        "if" => "⎇ (branch)",
47        "else" => "⎉ (alternative)",
48        "match" => "⌥ (option)",
49        "while" => "⟳ (cycle)",
50        "for" => "∀ (forall)",
51        "in" => "∈ (element-of)",
52        "break" => "⊗ (tensor/break)",
53        "continue" => "↻ (cycle-arrow)",
54        "return" => "⤺ (return-arrow)",
55        "async" => "⌛ (hourglass)",
56        _ => "(see docs)",
57    }
58}
59
60pub type ParseResult<T> = Result<T, ParseError>;
61
62/// Quantum gate names recognized in pipe syntax (e.g., `q|H`, `q|CNOT(q2)`).
63/// These are treated specially to distinguish pipe from bitwise OR in expressions like `x|H`.
64/// To add new gates, extend this list - it's the single source of truth for the parser.
65const QUANTUM_GATES: &[&str] = &[
66    // Single-qubit gates
67    "H", "X", "Y", "Z", "S", "T",
68    // Rotation gates (parameterized)
69    "Rx", "Ry", "Rz",
70    // Two-qubit gates
71    "CNOT", "CZ", "SWAP",
72    // Three-qubit gates
73    "Toffoli", "Fredkin",
74    // Register operations
75    "H_all", "X_all",
76];
77
78/// Quantum operations (measurement, queries, etc.)
79const QUANTUM_OPS: &[&str] = &[
80    // Measurement
81    "measure", "measure_all", "measure_both", "measure_basis", "measure_partial",
82    // Queries
83    "probability_of",
84    // Register operations
85    "apply_at",
86];
87
88/// Recursive descent parser for Sigil.
89pub struct Parser<'a> {
90    lexer: Lexer<'a>,
91    current: Option<(Token, Span)>,
92    /// Tracks whether we're parsing a condition (if/while/for) where < is comparison not generics
93    in_condition: bool,
94    /// Tracks if we have a pending `>` from splitting `>>` (Shr) in generic contexts
95    pending_gt: Option<Span>,
96}
97
98impl<'a> Parser<'a> {
99    pub fn new(source: &'a str) -> Self {
100        let mut lexer = Lexer::new(source);
101        let current = lexer.next_token();
102        Self {
103            lexer,
104            current,
105            in_condition: false,
106            pending_gt: None,
107        }
108    }
109
110    /// Parse a complete source file.
111    pub fn parse_file(&mut self) -> ParseResult<SourceFile> {
112        // Parse inner attributes first (#![...])
113        let mut attrs = Vec::new();
114        while matches!(self.current_token(), Some(Token::HashBang)) {
115            attrs.push(self.parse_inner_attribute()?);
116        }
117
118        // Build crate config from attributes
119        let config = self.build_crate_config(&attrs);
120
121        let mut items = Vec::new();
122        while !self.is_eof() {
123            // Note: parse_item calls collect_doc_comments() internally to capture
124            // evidential doc comments (//!, //~, //?, //◊, //‽) before items.
125            // We only skip regular comments here, not doc comments.
126            while self.check_regular_comment() {
127                self.advance();
128            }
129            if self.is_eof() {
130                break;
131            }
132            let item = self.parse_item()?;
133            // Filter out cfg-disabled items by checking their outer attributes
134            let should_include = match &item.node {
135                Item::Function(f) => self.evaluate_cfg_condition(&f.attrs.outer_attrs),
136                Item::Struct(s) => self.evaluate_cfg_condition(&s.attrs.outer_attrs),
137                _ => true,
138            };
139            if should_include {
140                items.push(item);
141            }
142        }
143        Ok(SourceFile {
144            attrs,
145            config,
146            items,
147        })
148    }
149
150    /// Parse an inner attribute: `#![name]` or `#![name(args)]`
151    fn parse_inner_attribute(&mut self) -> ParseResult<Attribute> {
152        self.expect(Token::HashBang)?;
153        self.expect(Token::LBracket)?;
154
155        let name = self.parse_ident()?;
156        let args = self.parse_attr_args()?;
157
158        self.expect(Token::RBracket)?;
159
160        Ok(Attribute {
161            name,
162            args,
163            is_inner: true,
164        })
165    }
166
167    /// Parse an outer attribute: `#[name]` or `#[name(args)]` or `@[name]` or `@[name(args)]`
168    /// The `@[]` syntax is the preferred Sigil style.
169    /// Also supports the shorthand `@[Clone, Debug]` which expands to `@[derive(Clone, Debug)]`
170    fn parse_outer_attribute(&mut self) -> ParseResult<Attribute> {
171        // Accept either # or @ as attribute prefix
172        let is_at_syntax = self.check(&Token::At);
173        if is_at_syntax {
174            self.advance();
175        } else {
176            self.expect(Token::Hash)?;
177        }
178        self.expect(Token::LBracket)?;
179
180        let name = self.parse_attr_name()?;
181
182        // Check for @[Ident, Ident, ...] shorthand for derive
183        // Only applies to @ syntax when we see a comma after the first identifier
184        if is_at_syntax && self.check(&Token::Comma) && !self.check(&Token::LParen) {
185            // This is the shorthand @[Clone, Debug] syntax - convert to derive
186            let mut args = vec![AttrArg::Ident(name)];
187            while self.consume_if(&Token::Comma) {
188                if self.check(&Token::RBracket) {
189                    break; // Trailing comma
190                }
191                args.push(AttrArg::Ident(self.parse_attr_name()?));
192            }
193            self.expect(Token::RBracket)?;
194
195            // Return as derive attribute
196            Ok(Attribute {
197                name: Ident {
198                    name: "derive".to_string(),
199                    evidentiality: None,
200                    affect: None,
201                    span: self.current_span(),
202                },
203                args: Some(AttrArgs::Paren(args)),
204                is_inner: false,
205            })
206        } else {
207            let args = self.parse_attr_args()?;
208            self.expect(Token::RBracket)?;
209
210            Ok(Attribute {
211                name,
212                args,
213                is_inner: false,
214            })
215        }
216    }
217
218    /// Evaluate a cfg condition to determine if the annotated item should be included.
219    /// Returns true if the condition is satisfied, false if the item should be skipped.
220    /// For the interpreter, `debug_assertions` is always true (interpreter = debug mode).
221    fn evaluate_cfg_condition(&self, attrs: &[Attribute]) -> bool {
222        for attr in attrs {
223            if attr.name.name == "cfg" {
224                if let Some(AttrArgs::Paren(args)) = &attr.args {
225                    // Check the cfg argument
226                    for arg in args {
227                        match arg {
228                            AttrArg::Ident(ident) => {
229                                // Simple cfg like #[cfg(debug_assertions)]
230                                if ident.name == "debug_assertions" {
231                                    // In interpreter mode, debug_assertions is true
232                                    return true;
233                                }
234                                // Unknown cfg - default to true
235                                return true;
236                            }
237                            AttrArg::KeyValue { key, value } => {
238                                // Key-value cfg like #[cfg(target_os = "linux")]
239                                return self.evaluate_cfg_key_value(&key.name, value);
240                            }
241                            AttrArg::Nested(nested_attr) => {
242                                // cfg(not(...)) or cfg(all(...)) or cfg(any(...))
243                                if nested_attr.name.name == "not" {
244                                    // Evaluate the negated condition
245                                    if let Some(AttrArgs::Paren(inner_args)) = &nested_attr.args {
246                                        for inner_arg in inner_args {
247                                            match inner_arg {
248                                                AttrArg::Ident(inner_ident) => {
249                                                    if inner_ident.name == "debug_assertions" {
250                                                        // not(debug_assertions) = false in interpreter
251                                                        return false;
252                                                    }
253                                                }
254                                                AttrArg::KeyValue { key, value } => {
255                                                    return !self.evaluate_cfg_key_value(&key.name, value);
256                                                }
257                                                _ => {}
258                                            }
259                                        }
260                                    }
261                                    // Unknown negated condition - default to false (skip)
262                                    return false;
263                                }
264                                if nested_attr.name.name == "any" {
265                                    // cfg(any(cond1, cond2, ...)) - true if ANY condition matches
266                                    if let Some(AttrArgs::Paren(inner_args)) = &nested_attr.args {
267                                        for inner_arg in inner_args {
268                                            if let AttrArg::KeyValue { key, value } = inner_arg {
269                                                if self.evaluate_cfg_key_value(&key.name, value) {
270                                                    return true;
271                                                }
272                                            }
273                                        }
274                                        return false;
275                                    }
276                                }
277                                // Unknown nested cfg - default to true
278                                return true;
279                            }
280                            _ => {}
281                        }
282                    }
283                }
284            }
285        }
286        // No cfg attribute or couldn't evaluate - include the item
287        true
288    }
289
290    /// Evaluate a cfg key-value pair like `target_os = "linux"`.
291    fn evaluate_cfg_key_value(&self, key: &str, value: &Expr) -> bool {
292        let value_str = match value {
293            Expr::Literal(Literal::String(s)) => s.as_str(),
294            _ => return false,
295        };
296        match key {
297            "target_os" => {
298                // Detect current OS
299                if cfg!(target_os = "linux") {
300                    value_str == "linux"
301                } else if cfg!(target_os = "macos") {
302                    value_str == "macos"
303                } else if cfg!(target_os = "windows") {
304                    value_str == "windows"
305                } else {
306                    false
307                }
308            }
309            "target_arch" => {
310                if cfg!(target_arch = "x86_64") {
311                    value_str == "x86_64"
312                } else if cfg!(target_arch = "aarch64") {
313                    value_str == "aarch64"
314                } else {
315                    false
316                }
317            }
318            _ => false,
319        }
320    }
321
322    /// Parse an attribute name (identifier, keyword, or path like async_trait::async_trait).
323    fn parse_attr_name(&mut self) -> ParseResult<Ident> {
324        let span = self.current_span();
325        let first_name = match self.current_token().cloned() {
326            Some(Token::Ident(name)) => {
327                self.advance();
328                name
329            }
330            // Handle keywords that can be used as attribute names
331            Some(Token::Naked) => {
332                self.advance();
333                "naked".to_string()
334            }
335            Some(Token::Unsafe) => {
336                self.advance();
337                "unsafe".to_string()
338            }
339            Some(Token::Asm) => {
340                self.advance();
341                "asm".to_string()
342            }
343            Some(Token::Volatile) => {
344                self.advance();
345                "volatile".to_string()
346            }
347            Some(Token::Derive) => {
348                self.advance();
349                "derive".to_string()
350            }
351            Some(Token::Simd) => {
352                self.advance();
353                "simd".to_string()
354            }
355            Some(Token::Atomic) => {
356                self.advance();
357                "atomic".to_string()
358            }
359            Some(Token::Macro) => {
360                self.advance();
361                "macro".to_string()
362            }
363            Some(t) => {
364                return Err(ParseError::UnexpectedToken {
365                    expected: "attribute name".to_string(),
366                    found: t,
367                    span,
368                })
369            }
370            None => return Err(ParseError::UnexpectedEof),
371        };
372
373        // Check for path continuation: attr_name::next_segment::...
374        let mut full_name = first_name;
375        while self.consume_if(&Token::MiddleDot) {
376            let segment = match self.current_token().cloned() {
377                Some(Token::Ident(name)) => {
378                    self.advance();
379                    name
380                }
381                Some(t) => {
382                    return Err(ParseError::UnexpectedToken {
383                        expected: "identifier after ::".to_string(),
384                        found: t,
385                        span: self.current_span(),
386                    })
387                }
388                None => return Err(ParseError::UnexpectedEof),
389            };
390            full_name = format!("{}::{}", full_name, segment);
391        }
392
393        Ok(Ident {
394            name: full_name,
395            evidentiality: None,
396            affect: None,
397            span,
398        })
399    }
400
401    /// Parse attribute arguments if present.
402    fn parse_attr_args(&mut self) -> ParseResult<Option<AttrArgs>> {
403        if self.consume_if(&Token::LParen) {
404            let mut args = Vec::new();
405
406            while !self.check(&Token::RParen) {
407                args.push(self.parse_attr_arg()?);
408                if !self.consume_if(&Token::Comma) {
409                    break;
410                }
411            }
412
413            self.expect(Token::RParen)?;
414            Ok(Some(AttrArgs::Paren(args)))
415        } else if self.consume_if(&Token::Eq) {
416            let expr = self.parse_expr()?;
417            Ok(Some(AttrArgs::Eq(Box::new(expr))))
418        } else {
419            Ok(None)
420        }
421    }
422
423    /// Parse a single attribute argument.
424    fn parse_attr_arg(&mut self) -> ParseResult<AttrArg> {
425        match self.current_token().cloned() {
426            Some(Token::StringLit(s)) => {
427                self.advance();
428                Ok(AttrArg::Literal(Literal::String(s)))
429            }
430            Some(Token::IntLit(s)) => {
431                self.advance();
432                Ok(AttrArg::Literal(Literal::Int {
433                    value: s,
434                    base: NumBase::Decimal,
435                    suffix: None,
436                }))
437            }
438            Some(Token::HexLit(s)) => {
439                self.advance();
440                Ok(AttrArg::Literal(Literal::Int {
441                    value: s,
442                    base: NumBase::Hex,
443                    suffix: None,
444                }))
445            }
446            Some(Token::BinaryLit(s)) => {
447                self.advance();
448                Ok(AttrArg::Literal(Literal::Int {
449                    value: s,
450                    base: NumBase::Binary,
451                    suffix: None,
452                }))
453            }
454            Some(Token::OctalLit(s)) => {
455                self.advance();
456                Ok(AttrArg::Literal(Literal::Int {
457                    value: s,
458                    base: NumBase::Octal,
459                    suffix: None,
460                }))
461            }
462            Some(Token::Ident(_)) => {
463                let ident = self.parse_ident()?;
464                self.parse_attr_arg_after_ident(ident)
465            }
466            // Handle keywords that might appear as feature names in attributes
467            Some(Token::Asm) => {
468                let span = self.current_span();
469                self.advance();
470                let ident = Ident {
471                    name: "asm".to_string(),
472                    evidentiality: None,
473                    affect: None,
474                    span,
475                };
476                self.parse_attr_arg_after_ident(ident)
477            }
478            Some(Token::Volatile) => {
479                let span = self.current_span();
480                self.advance();
481                let ident = Ident {
482                    name: "volatile".to_string(),
483                    evidentiality: None,
484                    affect: None,
485                    span,
486                };
487                self.parse_attr_arg_after_ident(ident)
488            }
489            Some(Token::Naked) => {
490                let span = self.current_span();
491                self.advance();
492                let ident = Ident {
493                    name: "naked".to_string(),
494                    evidentiality: None,
495                    affect: None,
496                    span,
497                };
498                self.parse_attr_arg_after_ident(ident)
499            }
500            Some(Token::Packed) => {
501                let span = self.current_span();
502                self.advance();
503                let ident = Ident {
504                    name: "packed".to_string(),
505                    evidentiality: None,
506                    affect: None,
507                    span,
508                };
509                self.parse_attr_arg_after_ident(ident)
510            }
511            Some(Token::Unsafe) => {
512                let span = self.current_span();
513                self.advance();
514                let ident = Ident {
515                    name: "unsafe".to_string(),
516                    evidentiality: None,
517                    affect: None,
518                    span,
519                };
520                self.parse_attr_arg_after_ident(ident)
521            }
522            Some(t) => Err(ParseError::UnexpectedToken {
523                expected: "attribute argument".to_string(),
524                found: t,
525                span: self.current_span(),
526            }),
527            None => Err(ParseError::UnexpectedEof),
528        }
529    }
530
531    /// Helper to continue parsing after an identifier in an attribute argument.
532    fn parse_attr_arg_after_ident(&mut self, ident: Ident) -> ParseResult<AttrArg> {
533        // Check for qualified path like serde::Serialize
534        if self.consume_if(&Token::MiddleDot) || self.consume_if(&Token::MiddleDot) {
535            let mut path_parts = vec![ident.name.clone()];
536            loop {
537                let part = self.parse_ident()?;
538                path_parts.push(part.name);
539                if !self.consume_if(&Token::MiddleDot) && !self.consume_if(&Token::MiddleDot) {
540                    break;
541                }
542            }
543            // Return the full qualified path as an identifier with :: separators
544            let full_path = path_parts.join("::");
545            return Ok(AttrArg::Ident(Ident {
546                name: full_path,
547                evidentiality: None,
548                affect: None,
549                span: ident.span.clone(),
550            }));
551        }
552        // Check for key = value
553        if self.consume_if(&Token::Eq) {
554            let value = self.parse_expr()?;
555            Ok(AttrArg::KeyValue {
556                key: ident,
557                value: Box::new(value),
558            })
559        }
560        // Check for nested attr(...)
561        else if self.check(&Token::LParen) {
562            let args = self.parse_attr_args()?;
563            Ok(AttrArg::Nested(Attribute {
564                name: ident,
565                args,
566                is_inner: false,
567            }))
568        }
569        // Just an identifier
570        else {
571            Ok(AttrArg::Ident(ident))
572        }
573    }
574
575    /// Parse interpolation parts from a string like "hello {name}, you are {age} years old"
576    /// Returns a vector of text segments and expression segments.
577    fn parse_interpolation_parts(&mut self, s: &str) -> ParseResult<Vec<InterpolationPart>> {
578        let mut parts = Vec::new();
579        let mut current_text = String::new();
580        let mut chars = s.chars().peekable();
581        let mut brace_depth = 0;
582        let mut expr_content = String::new();
583        let mut in_expr = false;
584
585        while let Some(c) = chars.next() {
586            if in_expr {
587                if c == '{' {
588                    brace_depth += 1;
589                    expr_content.push(c);
590                } else if c == '}' {
591                    if brace_depth > 0 {
592                        brace_depth -= 1;
593                        expr_content.push(c);
594                    } else {
595                        // End of expression - parse it
596                        in_expr = false;
597                        if !expr_content.is_empty() {
598                            // Parse the expression content
599                            let mut expr_parser = Parser::new(&expr_content);
600                            match expr_parser.parse_expr() {
601                                Ok(expr) => {
602                                    parts.push(InterpolationPart::Expr(Box::new(expr)));
603                                }
604                                Err(_) => {
605                                    // If parsing fails, treat as text
606                                    parts.push(InterpolationPart::Text(format!(
607                                        "{{{}}}",
608                                        expr_content
609                                    )));
610                                }
611                            }
612                        }
613                        expr_content.clear();
614                    }
615                } else {
616                    expr_content.push(c);
617                }
618            } else if c == '{' {
619                if chars.peek() == Some(&'{') {
620                    // Escaped brace {{
621                    chars.next();
622                    current_text.push('{');
623                } else {
624                    // Start of expression
625                    if !current_text.is_empty() {
626                        parts.push(InterpolationPart::Text(current_text.clone()));
627                        current_text.clear();
628                    }
629                    in_expr = true;
630                }
631            } else if c == '}' {
632                if chars.peek() == Some(&'}') {
633                    // Escaped brace }}
634                    chars.next();
635                    current_text.push('}');
636                } else {
637                    current_text.push(c);
638                }
639            } else {
640                current_text.push(c);
641            }
642        }
643
644        // Add any remaining text
645        if !current_text.is_empty() {
646            parts.push(InterpolationPart::Text(current_text));
647        }
648
649        // If we have no parts, add an empty text part
650        if parts.is_empty() {
651            parts.push(InterpolationPart::Text(String::new()));
652        }
653
654        Ok(parts)
655    }
656
657    /// Build crate configuration from parsed inner attributes.
658    fn build_crate_config(&self, attrs: &[Attribute]) -> CrateConfig {
659        let mut config = CrateConfig::default();
660        let mut linker = LinkerConfig::default();
661        let mut has_linker_config = false;
662
663        for attr in attrs {
664            match attr.name.name.as_str() {
665                "no_std" => config.no_std = true,
666                "no_main" => config.no_main = true,
667                "feature" => {
668                    if let Some(AttrArgs::Paren(args)) = &attr.args {
669                        for arg in args {
670                            if let AttrArg::Ident(ident) = arg {
671                                config.features.push(ident.name.clone());
672                            }
673                        }
674                    }
675                }
676                "target" => {
677                    let mut target = TargetConfig::default();
678                    if let Some(AttrArgs::Paren(args)) = &attr.args {
679                        for arg in args {
680                            if let AttrArg::KeyValue { key, value } = arg {
681                                if let Expr::Literal(Literal::String(s)) = value.as_ref() {
682                                    match key.name.as_str() {
683                                        "arch" => target.arch = Some(s.clone()),
684                                        "os" => target.os = Some(s.clone()),
685                                        "abi" => target.abi = Some(s.clone()),
686                                        _ => {}
687                                    }
688                                }
689                            }
690                        }
691                    }
692                    config.target = Some(target);
693                }
694                // Linker configuration attributes
695                "linker_script" => {
696                    if let Some(AttrArgs::Eq(value)) = &attr.args {
697                        if let Expr::Literal(Literal::String(s)) = value.as_ref() {
698                            linker.script = Some(s.clone());
699                            has_linker_config = true;
700                        }
701                    }
702                }
703                "entry_point" => {
704                    if let Some(AttrArgs::Eq(value)) = &attr.args {
705                        if let Expr::Literal(Literal::String(s)) = value.as_ref() {
706                            linker.entry_point = Some(s.clone());
707                            has_linker_config = true;
708                        }
709                    }
710                }
711                "base_address" => {
712                    if let Some(AttrArgs::Eq(value)) = &attr.args {
713                        if let Expr::Literal(Literal::Int { value: s, base, .. }) = value.as_ref() {
714                            let addr = Self::parse_int_value(s, *base);
715                            linker.base_address = Some(addr);
716                            has_linker_config = true;
717                        }
718                    }
719                }
720                "stack_size" => {
721                    if let Some(AttrArgs::Eq(value)) = &attr.args {
722                        if let Expr::Literal(Literal::Int { value: s, base, .. }) = value.as_ref() {
723                            let size = Self::parse_int_value(s, *base);
724                            linker.stack_size = Some(size);
725                            has_linker_config = true;
726                        }
727                    }
728                }
729                "link" => {
730                    // #![link(flag = "-nostdlib", flag = "-static")]
731                    if let Some(AttrArgs::Paren(args)) = &attr.args {
732                        for arg in args {
733                            if let AttrArg::KeyValue { key, value } = arg {
734                                if key.name == "flag" {
735                                    if let Expr::Literal(Literal::String(s)) = value.as_ref() {
736                                        linker.flags.push(s.clone());
737                                        has_linker_config = true;
738                                    }
739                                }
740                            }
741                        }
742                    }
743                }
744                _ => {}
745            }
746        }
747
748        if has_linker_config {
749            config.linker = Some(linker);
750        }
751
752        config
753    }
754
755    /// Parse an integer value from string with given base.
756    fn parse_int_value(s: &str, base: NumBase) -> u64 {
757        // Strip prefix based on base
758        let (stripped, radix) = match base {
759            NumBase::Binary => (
760                s.strip_prefix("0b").or(s.strip_prefix("0B")).unwrap_or(s),
761                2,
762            ),
763            NumBase::Octal => (
764                s.strip_prefix("0o").or(s.strip_prefix("0O")).unwrap_or(s),
765                8,
766            ),
767            NumBase::Decimal => (s, 10),
768            NumBase::Hex => (
769                s.strip_prefix("0x").or(s.strip_prefix("0X")).unwrap_or(s),
770                16,
771            ),
772            NumBase::Vigesimal => (
773                s.strip_prefix("0v").or(s.strip_prefix("0V")).unwrap_or(s),
774                20,
775            ),
776            NumBase::Duodecimal => (
777                s.strip_prefix("0d").or(s.strip_prefix("0D")).unwrap_or(s),
778                12,
779            ),
780            NumBase::Sexagesimal => (
781                s.strip_prefix("0s").or(s.strip_prefix("0S")).unwrap_or(s),
782                60,
783            ),
784            NumBase::Explicit(r) => (s, r as u32),
785        };
786        // Remove underscores (numeric separators) and parse
787        let clean: String = stripped.chars().filter(|c| *c != '_').collect();
788        u64::from_str_radix(&clean, radix).unwrap_or(0)
789    }
790
791    // === Token utilities ===
792
793    pub(crate) fn current_token(&self) -> Option<&Token> {
794        self.current.as_ref().map(|(t, _)| t)
795    }
796
797    pub(crate) fn current_span(&self) -> Span {
798        self.current.as_ref().map(|(_, s)| *s).unwrap_or_default()
799    }
800
801    pub(crate) fn advance(&mut self) -> Option<(Token, Span)> {
802        let prev = self.current.take();
803        self.current = self.lexer.next_token();
804        prev
805    }
806
807    pub(crate) fn is_eof(&self) -> bool {
808        self.current.is_none()
809    }
810
811    /// Strip float type suffix (f16, f32, f64, f128) from a literal string.
812    /// Handles both `2.0f64` and `2.0_f64` forms.
813    /// Returns (numeric_value, optional_suffix).
814    fn strip_float_suffix(s: &str) -> (String, Option<String>) {
815        for suffix in &["f128", "f64", "f32", "f16"] {
816            if s.ends_with(suffix) {
817                let before = &s[..s.len() - suffix.len()];
818                // Strip optional underscore separator (e.g., 2.0_f64 -> 2.0)
819                let value = before.strip_suffix('_').unwrap_or(before).to_string();
820                return (value, Some(suffix.to_string()));
821            }
822        }
823        (s.to_string(), None)
824    }
825
826    pub(crate) fn expect(&mut self, expected: Token) -> ParseResult<Span> {
827        match &self.current {
828            Some((token, span))
829                if std::mem::discriminant(token) == std::mem::discriminant(&expected) =>
830            {
831                let span = *span;
832                self.advance();
833                Ok(span)
834            }
835            Some((Token::DeprecatedRustKeyword(kw), span)) => {
836                Err(ParseError::DeprecatedRustSyntax {
837                    rust: kw.clone(),
838                    sigil: rust_to_sigil(kw).to_string(),
839                    span: *span,
840                })
841            }
842            Some((Token::DeprecatedColonColon, span)) => {
843                Err(ParseError::DeprecatedRustSyntax {
844                    rust: "::".to_string(),
845                    sigil: "· (middledot) for path separator".to_string(),
846                    span: *span,
847                })
848            }
849            Some((token, span)) => Err(ParseError::UnexpectedToken {
850                expected: format!("{:?}", expected),
851                found: token.clone(),
852                span: *span,
853            }),
854            None => Err(ParseError::UnexpectedEof),
855        }
856    }
857
858    /// Expect one of several tokens (for contextual symbol parsing).
859    /// Used to accept both keyword and symbol alternatives (e.g., `in` or `∈`).
860    pub(crate) fn expect_one_of(&mut self, expected: &[Token]) -> ParseResult<Span> {
861        match &self.current {
862            Some((Token::DeprecatedRustKeyword(kw), span)) => {
863                Err(ParseError::DeprecatedRustSyntax {
864                    rust: kw.clone(),
865                    sigil: rust_to_sigil(kw).to_string(),
866                    span: *span,
867                })
868            }
869            Some((Token::DeprecatedColonColon, span)) => {
870                Err(ParseError::DeprecatedRustSyntax {
871                    rust: "::".to_string(),
872                    sigil: "· (middledot) for path separator".to_string(),
873                    span: *span,
874                })
875            }
876            Some((token, span)) => {
877                let current_discriminant = std::mem::discriminant(token);
878                for exp in expected {
879                    if current_discriminant == std::mem::discriminant(exp) {
880                        let span = *span;
881                        self.advance();
882                        return Ok(span);
883                    }
884                }
885                Err(ParseError::UnexpectedToken {
886                    expected: expected.iter().map(|t| format!("{:?}", t)).collect::<Vec<_>>().join(" or "),
887                    found: token.clone(),
888                    span: *span,
889                })
890            }
891            None => Err(ParseError::UnexpectedEof),
892        }
893    }
894
895    /// Check if current token matches any of the expected tokens.
896    pub(crate) fn check_one_of(&self, expected: &[Token]) -> bool {
897        match &self.current {
898            Some((token, _)) => {
899                let current_discriminant = std::mem::discriminant(token);
900                expected.iter().any(|exp| current_discriminant == std::mem::discriminant(exp))
901            }
902            None => false,
903        }
904    }
905
906    pub(crate) fn check(&self, expected: &Token) -> bool {
907        matches!(&self.current, Some((token, _)) if std::mem::discriminant(token) == std::mem::discriminant(expected))
908    }
909
910    /// Check for deprecated Rust syntax and emit helpful error.
911    /// Returns Err if deprecated syntax is found, Ok(()) otherwise.
912    pub(crate) fn check_deprecated(&self) -> ParseResult<()> {
913        match &self.current {
914            Some((Token::DeprecatedRustKeyword(kw), span)) => {
915                Err(ParseError::DeprecatedRustSyntax {
916                    rust: kw.clone(),
917                    sigil: rust_to_sigil(kw).to_string(),
918                    span: *span,
919                })
920            }
921            Some((Token::DeprecatedColonColon, span)) => {
922                Err(ParseError::DeprecatedRustSyntax {
923                    rust: "::".to_string(),
924                    sigil: "· (middledot) for path separator".to_string(),
925                    span: *span,
926                })
927            }
928            Some((Token::DeprecatedAmpMut, span)) => {
929                Err(ParseError::DeprecatedRustSyntax {
930                    rust: "&mut".to_string(),
931                    sigil: "&Δ (reference to mutable) or just Δ for mutable binding".to_string(),
932                    span: *span,
933                })
934            }
935            _ => Ok(()),
936        }
937    }
938
939    /// Peek at the next token (after current) without consuming anything.
940    pub(crate) fn peek_next(&mut self) -> Option<&Token> {
941        self.lexer.peek().map(|(t, _)| t)
942    }
943
944    /// Peek n tokens ahead (0 = next token after current, 1 = token after that, etc.)
945    pub(crate) fn peek_n(&mut self, n: usize) -> Option<&Token> {
946        self.lexer.peek_n(n).map(|(t, _)| t)
947    }
948
949    pub(crate) fn consume_if(&mut self, expected: &Token) -> bool {
950        if self.check(expected) {
951            self.advance();
952            true
953        } else {
954            false
955        }
956    }
957
958    /// Check if a token is any kind of comment (including evidential doc comments)
959    fn is_comment_token(tok: &Token) -> bool {
960        matches!(tok, Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
961            || tok.is_doc_comment()
962    }
963
964    /// Skip any comments (including evidential doc comments)
965    pub(crate) fn skip_comments(&mut self) {
966        while let Some(tok) = self.current_token() {
967            if Self::is_comment_token(&tok) {
968                self.advance();
969            } else {
970                break;
971            }
972        }
973    }
974
975    /// Check if the current token is a comment
976    pub(crate) fn current_is_comment(&self) -> bool {
977        self.current_token().map(|t| Self::is_comment_token(&t)).unwrap_or(false)
978    }
979
980    /// Check if the current token is a regular (non-doc) comment
981    /// This skips regular comments but preserves doc comments for collection
982    fn check_regular_comment(&self) -> bool {
983        matches!(
984            self.current_token(),
985            Some(Token::LineComment(_)) | Some(Token::TildeComment(_)) | Some(Token::BlockComment(_))
986        )
987    }
988
989    /// Collect doc comments preceding the next item (skipping regular comments)
990    /// Returns Vec<DocComment> to attach to the parsed item
991    pub(crate) fn collect_doc_comments(&mut self) -> Vec<crate::ast::DocComment> {
992        use crate::ast::{DocComment, Evidentiality};
993
994        let mut doc_comments = Vec::new();
995
996        while let Some((tok, span)) = self.current.clone() {
997            // Check if it's a doc comment token
998            match &tok {
999                Token::DocCommentVerified(content) => {
1000                    doc_comments.push(DocComment::new(
1001                        Evidentiality::Known,
1002                        false,
1003                        content.clone(),
1004                        span,
1005                    ));
1006                    self.advance();
1007                }
1008                Token::DocCommentVerifiedInner(content) => {
1009                    doc_comments.push(DocComment::new(
1010                        Evidentiality::Known,
1011                        true,
1012                        content.clone(),
1013                        span,
1014                    ));
1015                    self.advance();
1016                }
1017                Token::DocCommentReported(content) => {
1018                    doc_comments.push(DocComment::new(
1019                        Evidentiality::Reported,
1020                        false,
1021                        content.clone(),
1022                        span,
1023                    ));
1024                    self.advance();
1025                }
1026                Token::DocCommentReportedInner(content) => {
1027                    doc_comments.push(DocComment::new(
1028                        Evidentiality::Reported,
1029                        true,
1030                        content.clone(),
1031                        span,
1032                    ));
1033                    self.advance();
1034                }
1035                Token::DocCommentUncertain(content) => {
1036                    doc_comments.push(DocComment::new(
1037                        Evidentiality::Uncertain,
1038                        false,
1039                        content.clone(),
1040                        span,
1041                    ));
1042                    self.advance();
1043                }
1044                Token::DocCommentUncertainInner(content) => {
1045                    doc_comments.push(DocComment::new(
1046                        Evidentiality::Uncertain,
1047                        true,
1048                        content.clone(),
1049                        span,
1050                    ));
1051                    self.advance();
1052                }
1053                Token::DocCommentPredicted(content) => {
1054                    doc_comments.push(DocComment::new(
1055                        Evidentiality::Predicted,
1056                        false,
1057                        content.clone(),
1058                        span,
1059                    ));
1060                    self.advance();
1061                }
1062                Token::DocCommentPredictedInner(content) => {
1063                    doc_comments.push(DocComment::new(
1064                        Evidentiality::Predicted,
1065                        true,
1066                        content.clone(),
1067                        span,
1068                    ));
1069                    self.advance();
1070                }
1071                Token::DocCommentParadox(content) => {
1072                    doc_comments.push(DocComment::new(
1073                        Evidentiality::Paradox,
1074                        false,
1075                        content.clone(),
1076                        span,
1077                    ));
1078                    self.advance();
1079                }
1080                Token::DocCommentParadoxInner(content) => {
1081                    doc_comments.push(DocComment::new(
1082                        Evidentiality::Paradox,
1083                        true,
1084                        content.clone(),
1085                        span,
1086                    ));
1087                    self.advance();
1088                }
1089                Token::DocComment(content) => {
1090                    // Legacy /// comments map to Reported (default)
1091                    doc_comments.push(DocComment::new(
1092                        Evidentiality::Reported,
1093                        false,
1094                        content.clone(),
1095                        span,
1096                    ));
1097                    self.advance();
1098                }
1099                // Skip regular comments but don't break
1100                Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_) => {
1101                    self.advance();
1102                }
1103                // Stop on non-comment tokens
1104                _ => break,
1105            }
1106        }
1107
1108        doc_comments
1109    }
1110
1111    /// Check if the current token is `>`, including pending `>` from split `>>`.
1112    pub(crate) fn check_gt(&self) -> bool {
1113        self.pending_gt.is_some() || self.check(&Token::Gt)
1114    }
1115
1116    /// Expect a `>` token, handling the case where `>>` (Shr) needs to be split.
1117    /// This is necessary for nested generics like `Vec<Option<T>>`.
1118    pub(crate) fn expect_gt(&mut self) -> ParseResult<Span> {
1119        // First check if we have a pending `>` from a previous split
1120        if let Some(span) = self.pending_gt.take() {
1121            return Ok(span);
1122        }
1123
1124        match &self.current {
1125            Some((Token::Gt, span)) => {
1126                let span = *span;
1127                self.advance();
1128                Ok(span)
1129            }
1130            Some((Token::Shr, span)) => {
1131                // Split `>>` into two `>` tokens
1132                // Take the first `>` now and save the second for later
1133                let span = *span;
1134                self.pending_gt = Some(span);
1135                self.advance();
1136                Ok(span)
1137            }
1138            Some((token, span)) => Err(ParseError::UnexpectedToken {
1139                expected: "Gt".to_string(),
1140                found: token.clone(),
1141                span: *span,
1142            }),
1143            None => Err(ParseError::UnexpectedEof),
1144        }
1145    }
1146
1147    /// Consume a `>` if present, handling pending `>` from split `>>`.
1148    fn consume_gt(&mut self) -> bool {
1149        if self.pending_gt.is_some() {
1150            self.pending_gt = None;
1151            return true;
1152        }
1153        if self.check(&Token::Gt) {
1154            self.advance();
1155            return true;
1156        }
1157        // Also handle `>>` - split it and return first `>`
1158        if self.check(&Token::Shr) {
1159            let span = self.current_span();
1160            self.pending_gt = Some(span);
1161            self.advance();
1162            return true;
1163        }
1164        false
1165    }
1166
1167    /// Check if the current token can start a new item.
1168    /// Used to make semicolons optional in Sigil.
1169    fn can_start_item(&self) -> bool {
1170        matches!(
1171            self.current_token(),
1172            Some(
1173                Token::Pub
1174                    | Token::Fn
1175                    | Token::Async
1176                    | Token::Struct
1177                    | Token::Enum
1178                    | Token::Trait
1179                    | Token::Impl
1180                    | Token::Type
1181                    | Token::Mod
1182                    | Token::Use
1183                    | Token::Const
1184                    | Token::Static
1185                    | Token::Actor
1186                    | Token::Extern
1187                    | Token::Hash
1188                    | Token::At
1189                    | Token::Naked
1190                    | Token::Packed
1191                    | Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_)
1192                    | Token::DocComment(_)
1193                    // Plurality keywords
1194                    | Token::Alter
1195                    | Token::Headspace
1196                    | Token::Reality
1197                    | Token::CoCon
1198            )
1199        ) || (matches!(self.current_token(), Some(Token::On)) && self.peek_next_is_trigger())
1200    }
1201
1202    /// Check if peek is the Trigger token (for "on trigger" detection)
1203    fn peek_next_is_trigger(&self) -> bool {
1204        // This is a workaround since we can't mutably borrow in can_start_item
1205        false // Will be true when "on trigger" is seen
1206    }
1207
1208    /// Check if the current token can start a new statement in a block.
1209    /// Used to make semicolons optional in Sigil's advanced syntax.
1210    fn can_start_stmt(&self) -> bool {
1211        // Check for keywords that can be used as identifiers (expressions)
1212        if let Some(token) = self.current_token() {
1213            if Self::keyword_as_ident(token).is_some() {
1214                return true;
1215            }
1216        }
1217        matches!(
1218            self.current_token(),
1219            Some(
1220                Token::Let
1221                    | Token::If
1222                    | Token::Match
1223                    | Token::Loop
1224                    | Token::While
1225                    | Token::ForAll
1226                    | Token::Return
1227                    | Token::Tensor
1228                    | Token::CycleArrow
1229                    | Token::Ident(_)
1230                    | Token::SelfLower
1231                    | Token::SelfUpper
1232                    | Token::LParen
1233                    | Token::LBracket
1234                    | Token::LBrace
1235                    // Literals can start expression statements (e.g., final return value)
1236                    | Token::StringLit(_)
1237                    | Token::IntLit(_)
1238                    | Token::FloatLit(_)
1239                    | Token::True
1240                    | Token::False
1241                    | Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_)
1242                    | Token::DocComment(_)
1243            )
1244        ) || self.can_start_item()
1245    }
1246
1247    /// Consume semicolon if present, or skip if next token can start an item.
1248    /// This makes semicolons optional in Sigil's advanced syntax.
1249    fn expect_semi_or_item_start(&mut self) -> ParseResult<()> {
1250        if self.consume_if(&Token::Semi) {
1251            return Ok(());
1252        }
1253        if self.can_start_item() || self.is_eof() || self.check(&Token::RBrace) {
1254            // Semicolon is optional before a new item, EOF, or closing brace
1255            return Ok(());
1256        }
1257        let span = self.current_span();
1258        Err(ParseError::UnexpectedToken {
1259            expected: "`;` or new item".to_string(),
1260            found: self.current_token().cloned().unwrap_or(Token::Semi),
1261            span,
1262        })
1263    }
1264
1265    // === Item parsing ===
1266
1267    fn parse_item(&mut self) -> ParseResult<Spanned<Item>> {
1268        // Check for deprecated Rust syntax and emit helpful error
1269        self.check_deprecated()?;
1270
1271        let start_span = self.current_span();
1272
1273        // Collect doc comments first (SGDOC)
1274        let doc_comments = self.collect_doc_comments();
1275
1276        // Collect outer attributes (#[...] or @[...])
1277        let mut outer_attrs = Vec::new();
1278        while self.check(&Token::Hash) || self.check(&Token::At) {
1279            outer_attrs.push(self.parse_outer_attribute()?);
1280        }
1281
1282        let visibility = self.parse_visibility()?;
1283
1284        let item = match self.current_token() {
1285            Some(Token::Fn) | Some(Token::Async) => {
1286                Item::Function(self.parse_function_with_doc_comments(visibility, outer_attrs, doc_comments)?)
1287            }
1288            Some(Token::Struct) => {
1289                Item::Struct(self.parse_struct_with_doc_comments(visibility, outer_attrs, doc_comments)?)
1290            }
1291            Some(Token::Enum) => Item::Enum(self.parse_enum_with_doc_comments(visibility, doc_comments)?),
1292            Some(Token::Trait) => Item::Trait(self.parse_trait_with_doc_comments(visibility, doc_comments)?),
1293            Some(Token::Impl) => Item::Impl(self.parse_impl_with_doc_comments(doc_comments)?),
1294            Some(Token::Unsafe) => {
1295                // unsafe impl, unsafe fn, unsafe trait
1296                self.advance(); // consume 'unsafe'
1297                match self.current_token() {
1298                    Some(Token::Impl) => Item::Impl(self.parse_impl_with_doc_comments(doc_comments)?),
1299                    Some(Token::Fn) | Some(Token::Async) => {
1300                        Item::Function(self.parse_function_with_doc_comments(visibility, outer_attrs, doc_comments)?)
1301                    }
1302                    Some(Token::Trait) => Item::Trait(self.parse_trait_with_doc_comments(visibility, doc_comments)?),
1303                    Some(t) => {
1304                        return Err(ParseError::UnexpectedToken {
1305                            expected: "impl, fn, or trait after unsafe".to_string(),
1306                            found: t.clone(),
1307                            span: self.current_span(),
1308                        })
1309                    }
1310                    None => return Err(ParseError::UnexpectedEof),
1311                }
1312            }
1313            Some(Token::Type) => Item::TypeAlias(self.parse_type_alias(visibility)?),
1314            Some(Token::Mod) => Item::Module(self.parse_module_with_doc_comments(visibility, doc_comments)?),
1315            Some(Token::Use) => Item::Use(self.parse_use(visibility)?),
1316            Some(Token::Const) => {
1317                // Check if this is `const fn` (const function) or just `const X: T = ...`
1318                if self.peek_next().map(|t| matches!(t, Token::Fn | Token::Async)) == Some(true) {
1319                    Item::Function(self.parse_function_with_doc_comments(visibility, outer_attrs, doc_comments)?)
1320                } else {
1321                    Item::Const(self.parse_const_with_doc_comments(visibility, doc_comments)?)
1322                }
1323            }
1324            Some(Token::Static) => Item::Static(self.parse_static_with_doc_comments(visibility, doc_comments)?),
1325            Some(Token::Actor) => Item::Actor(self.parse_actor(visibility)?),
1326            Some(Token::Extern) => Item::ExternBlock(self.parse_extern_block()?),
1327            Some(Token::Macro) | Some(Token::MacroRules) | Some(Token::Rune) => Item::Macro(self.parse_macro_def(visibility)?),
1328            Some(Token::Naked) => {
1329                // naked fn -> function with naked attribute
1330                Item::Function(self.parse_function_with_doc_comments(visibility, outer_attrs, doc_comments)?)
1331            }
1332            Some(Token::Packed) => {
1333                // packed struct -> struct with packed attribute
1334                Item::Struct(self.parse_struct_with_doc_comments(visibility, outer_attrs, doc_comments)?)
1335            }
1336            // Plurality items (DAEMONIORUM extensions)
1337            Some(Token::Alter) => {
1338                use crate::plurality::PluralityParser;
1339                Item::Plurality(crate::plurality::PluralityItem::Alter(
1340                    self.parse_alter_def(visibility)?,
1341                ))
1342            }
1343            Some(Token::Headspace) => {
1344                use crate::plurality::PluralityParser;
1345                Item::Plurality(crate::plurality::PluralityItem::Headspace(
1346                    self.parse_headspace_def(visibility)?,
1347                ))
1348            }
1349            Some(Token::Reality) => {
1350                use crate::plurality::PluralityParser;
1351                Item::Plurality(crate::plurality::PluralityItem::Reality(
1352                    self.parse_reality_def(visibility)?,
1353                ))
1354            }
1355            Some(Token::CoCon) => {
1356                use crate::plurality::PluralityParser;
1357                Item::Plurality(crate::plurality::PluralityItem::CoConChannel(
1358                    self.parse_cocon_channel()?,
1359                ))
1360            }
1361            Some(Token::On) => {
1362                // Check if this is a trigger handler: "on trigger ..."
1363                if self.peek_next() == Some(&Token::Trigger) {
1364                    use crate::plurality::PluralityParser;
1365                    Item::Plurality(crate::plurality::PluralityItem::TriggerHandler(
1366                        self.parse_trigger_handler()?,
1367                    ))
1368                } else {
1369                    return Err(ParseError::UnexpectedToken {
1370                        expected: "item".to_string(),
1371                        found: Token::On,
1372                        span: self.current_span(),
1373                    });
1374                }
1375            }
1376            // Macro invocation at item level: `name! { ... }` or `path::to::macro! { ... }`
1377            Some(Token::Ident(_)) => {
1378                // Check if this is a macro invocation (next token after possible path is !)
1379                if self.looks_like_macro_invocation() {
1380                    Item::MacroInvocation(self.parse_macro_invocation()?)
1381                } else {
1382                    return Err(ParseError::UnexpectedToken {
1383                        expected: "item".to_string(),
1384                        found: self.current_token().unwrap().clone(),
1385                        span: self.current_span(),
1386                    });
1387                }
1388            }
1389            Some(token) => {
1390                return Err(ParseError::UnexpectedToken {
1391                    expected: "item".to_string(),
1392                    found: token.clone(),
1393                    span: self.current_span(),
1394                });
1395            }
1396            None => return Err(ParseError::UnexpectedEof),
1397        };
1398
1399        let end_span = self.current_span();
1400        Ok(Spanned::new(item, start_span.merge(end_span)))
1401    }
1402
1403    pub(crate) fn parse_visibility(&mut self) -> ParseResult<Visibility> {
1404        if self.consume_if(&Token::Pub) {
1405            Ok(Visibility::Public)
1406        } else {
1407            Ok(Visibility::Private)
1408        }
1409    }
1410
1411    fn parse_function(&mut self, visibility: Visibility) -> ParseResult<Function> {
1412        self.parse_function_with_doc_comments(visibility, Vec::new(), vec![])
1413    }
1414
1415    fn parse_function_with_attrs(
1416        &mut self,
1417        visibility: Visibility,
1418        outer_attrs: Vec<Attribute>,
1419    ) -> ParseResult<Function> {
1420        self.parse_function_with_doc_comments(visibility, outer_attrs, vec![])
1421    }
1422
1423    fn parse_function_with_doc_comments(
1424        &mut self,
1425        visibility: Visibility,
1426        outer_attrs: Vec<Attribute>,
1427        doc_comments: Vec<crate::ast::DocComment>,
1428    ) -> ParseResult<Function> {
1429        // Parse function attributes from outer attributes
1430        let mut attrs = self.process_function_attrs(&outer_attrs);
1431
1432        // Check for naked keyword before fn
1433        if self.consume_if(&Token::Naked) {
1434            attrs.naked = true;
1435        }
1436
1437        // Check for unsafe keyword before fn
1438        let is_unsafe = self.consume_if(&Token::Unsafe);
1439
1440        // Check for const keyword before fn
1441        let is_const = self.consume_if(&Token::Const);
1442
1443        let is_async = self.consume_if(&Token::Async);
1444        self.expect(Token::Fn)?;
1445
1446        let mut name = self.parse_ident()?;
1447
1448        // Parse optional evidentiality marker on function name: fn load~<T>() or fn predict◊()
1449        // parse_ident only consumes unambiguous markers (~, ◊, ‽), so we also check for ! and ?
1450        if let Some(ev) = self.parse_evidentiality_opt() {
1451            // Store in the name's evidentiality field if not already set
1452            if name.evidentiality.is_none() {
1453                name.evidentiality = Some(ev);
1454            }
1455        }
1456
1457        // Parse optional aspect suffix: ·ing, ·ed, ·able, ·ive
1458        let aspect = match self.current_token() {
1459            Some(Token::AspectProgressive) => {
1460                self.advance();
1461                Some(Aspect::Progressive)
1462            }
1463            Some(Token::AspectPerfective) => {
1464                self.advance();
1465                Some(Aspect::Perfective)
1466            }
1467            Some(Token::AspectPotential) => {
1468                self.advance();
1469                Some(Aspect::Potential)
1470            }
1471            Some(Token::AspectResultative) => {
1472                self.advance();
1473                Some(Aspect::Resultative)
1474            }
1475            _ => None,
1476        };
1477
1478        let generics = self.parse_generics_opt()?;
1479
1480        self.expect(Token::LParen)?;
1481        let params = self.parse_params()?;
1482        self.expect(Token::RParen)?;
1483
1484        let return_type = if self.consume_if(&Token::Arrow) {
1485            Some(self.parse_type()?)
1486        } else {
1487            None
1488        };
1489
1490        // Handle async marker after return type: -> Type⌛
1491        // This is an alternative async syntax: fn foo() -> Result⌛ { ... }
1492        let is_async = is_async || self.consume_if(&Token::Async);
1493
1494        let where_clause = self.parse_where_clause_opt()?;
1495
1496        let body = if self.check(&Token::LBrace) {
1497            Some(self.parse_block()?)
1498        } else {
1499            // Semicolon is optional for trait method signatures when followed by
1500            // another item, a doc comment, or closing brace (Sigil style)
1501            if !self.consume_if(&Token::Semi) {
1502                // If no semicolon, we must be at a valid termination point:
1503                // - Next function/const/type declaration
1504                // - Doc comment (next trait item)
1505                // - Closing brace (end of trait/impl)
1506                // Otherwise it's an error
1507                let valid_terminator = matches!(
1508                    self.current_token(),
1509                    Some(Token::Fn) | Some(Token::Async) | Some(Token::Unsafe)
1510                    | Some(Token::Const) | Some(Token::Type) | Some(Token::Pub)
1511                    | Some(Token::DocComment(_)) | Some(Token::LineComment(_))
1512                    | Some(Token::BlockComment(_)) | Some(Token::TildeComment(_))
1513                    | Some(Token::RBrace) | Some(Token::Hash)
1514                );
1515                if !valid_terminator {
1516                    return match self.current_token().cloned() {
1517                        Some(token) => Err(ParseError::UnexpectedToken {
1518                            expected: "Semi".to_string(),
1519                            found: token,
1520                            span: self.current_span(),
1521                        }),
1522                        None => Err(ParseError::UnexpectedEof),
1523                    };
1524                }
1525            }
1526            None
1527        };
1528
1529        Ok(Function {
1530            doc_comments,
1531            visibility,
1532            is_async,
1533            is_const,
1534            is_unsafe,
1535            attrs,
1536            name,
1537            aspect,
1538            generics,
1539            params,
1540            return_type,
1541            where_clause,
1542            body,
1543        })
1544    }
1545
1546    /// Process outer attributes into FunctionAttrs.
1547    fn process_function_attrs(&self, attrs: &[Attribute]) -> FunctionAttrs {
1548        let mut func_attrs = FunctionAttrs::default();
1549
1550        for attr in attrs {
1551            match attr.name.name.as_str() {
1552                "panic_handler" => func_attrs.panic_handler = true,
1553                "entry" => func_attrs.entry = true,
1554                "no_mangle" => func_attrs.no_mangle = true,
1555                "export" => func_attrs.export = true,
1556                "cold" => func_attrs.cold = true,
1557                "hot" => func_attrs.hot = true,
1558                "test" => func_attrs.test = true,
1559                "naked" => func_attrs.naked = true,
1560                "inline" => {
1561                    func_attrs.inline = Some(match &attr.args {
1562                        Some(AttrArgs::Paren(args)) => {
1563                            if let Some(AttrArg::Ident(ident)) = args.first() {
1564                                match ident.name.as_str() {
1565                                    "always" => InlineHint::Always,
1566                                    "never" => InlineHint::Never,
1567                                    _ => InlineHint::Hint,
1568                                }
1569                            } else {
1570                                InlineHint::Hint
1571                            }
1572                        }
1573                        _ => InlineHint::Hint,
1574                    });
1575                }
1576                "link_section" => {
1577                    if let Some(AttrArgs::Eq(value)) = &attr.args {
1578                        if let Expr::Literal(Literal::String(s)) = value.as_ref() {
1579                            func_attrs.link_section = Some(s.clone());
1580                        }
1581                    }
1582                }
1583                "interrupt" => {
1584                    if let Some(AttrArgs::Paren(args)) = &attr.args {
1585                        if let Some(AttrArg::Literal(Literal::Int { value, base, .. })) =
1586                            args.first()
1587                        {
1588                            let num = Self::parse_int_value(value, *base) as u32;
1589                            func_attrs.interrupt = Some(num);
1590                        }
1591                    }
1592                }
1593                "align" => {
1594                    if let Some(AttrArgs::Paren(args)) = &attr.args {
1595                        if let Some(AttrArg::Literal(Literal::Int { value, base, .. })) =
1596                            args.first()
1597                        {
1598                            let align = Self::parse_int_value(value, *base) as usize;
1599                            func_attrs.align = Some(align);
1600                        }
1601                    }
1602                }
1603                _ => {
1604                    // Store unrecognized attributes
1605                    func_attrs.outer_attrs.push(attr.clone());
1606                }
1607            }
1608        }
1609
1610        func_attrs
1611    }
1612
1613    fn parse_struct_with_doc_comments(
1614        &mut self,
1615        visibility: Visibility,
1616        outer_attrs: Vec<Attribute>,
1617        doc_comments: Vec<crate::ast::DocComment>,
1618    ) -> ParseResult<StructDef> {
1619        let mut result = self.parse_struct_with_attrs_internal(visibility, outer_attrs)?;
1620        result.doc_comments = doc_comments;
1621        Ok(result)
1622    }
1623
1624    fn parse_struct_with_attrs(
1625        &mut self,
1626        visibility: Visibility,
1627        outer_attrs: Vec<Attribute>,
1628    ) -> ParseResult<StructDef> {
1629        self.parse_struct_with_attrs_internal(visibility, outer_attrs)
1630    }
1631
1632    fn parse_struct_with_attrs_internal(
1633        &mut self,
1634        visibility: Visibility,
1635        outer_attrs: Vec<Attribute>,
1636    ) -> ParseResult<StructDef> {
1637        // Parse struct attributes
1638        let mut attrs = StructAttrs::default();
1639        attrs.outer_attrs = outer_attrs.clone();
1640
1641        // Process derive attributes
1642        for attr in &outer_attrs {
1643            if attr.name.name == "derive" {
1644                if let Some(AttrArgs::Paren(args)) = &attr.args {
1645                    for arg in args {
1646                        if let AttrArg::Ident(ident) = arg {
1647                            let derive = Self::parse_derive_trait(&ident.name)?;
1648                            attrs.derives.push(derive);
1649                        }
1650                    }
1651                }
1652            } else if attr.name.name == "simd" {
1653                attrs.simd = true;
1654            } else if attr.name.name == "repr" {
1655                if let Some(AttrArgs::Paren(args)) = &attr.args {
1656                    for arg in args {
1657                        if let AttrArg::Ident(ident) = arg {
1658                            attrs.repr = Some(match ident.name.as_str() {
1659                                "C" => StructRepr::C,
1660                                "transparent" => StructRepr::Transparent,
1661                                "packed" => {
1662                                    attrs.packed = true;
1663                                    StructRepr::C // packed implies C repr
1664                                }
1665                                other => StructRepr::Int(other.to_string()),
1666                            });
1667                        } else if let AttrArg::Nested(nested) = arg {
1668                            if nested.name.name == "align" {
1669                                if let Some(AttrArgs::Paren(align_args)) = &nested.args {
1670                                    if let Some(AttrArg::Literal(Literal::Int { value, .. })) =
1671                                        align_args.first()
1672                                    {
1673                                        if let Ok(n) = value.parse::<usize>() {
1674                                            attrs.align = Some(n);
1675                                        }
1676                                    }
1677                                }
1678                            }
1679                        }
1680                    }
1681                }
1682            }
1683        }
1684
1685        // Check for packed keyword before struct
1686        if self.consume_if(&Token::Packed) {
1687            attrs.packed = true;
1688        }
1689
1690        self.expect(Token::Struct)?;
1691        let name = self.parse_ident()?;
1692
1693        // Evidentiality markers can appear BEFORE or AFTER generics:
1694        // - struct Foo! { ... } - newtype/verified struct
1695        // - struct Bar<T>~ { ... } - reported struct
1696        // - struct Gradient!<S, D, Dev> { ... } - verified struct with generics after evidentiality
1697        // Check for evidentiality BEFORE generics: struct Type!<...>
1698        let _evidentiality_before = self.parse_evidentiality_opt();
1699
1700        let generics = self.parse_generics_opt()?;
1701
1702        // Also check for evidentiality AFTER generics: struct Type<T>!
1703        let _evidentiality_after = self.parse_evidentiality_opt();
1704
1705        // Optional where clause for struct bounds (parsed but not yet stored in AST)
1706        let _ = self.parse_where_clause_opt()?;
1707
1708        let fields = if self.check(&Token::LBrace) {
1709            self.expect(Token::LBrace)?;
1710            let fields = self.parse_field_defs()?;
1711            self.expect(Token::RBrace)?;
1712            StructFields::Named(fields)
1713        } else if self.check(&Token::LParen) {
1714            self.expect(Token::LParen)?;
1715            let types = self.parse_tuple_struct_fields()?;
1716            self.expect(Token::RParen)?;
1717            // Semicolon is optional in Sigil's advanced syntax
1718            self.expect_semi_or_item_start()?;
1719            StructFields::Tuple(types)
1720        } else {
1721            // Semicolon is optional in Sigil's advanced syntax
1722            self.expect_semi_or_item_start()?;
1723            StructFields::Unit
1724        };
1725
1726        Ok(StructDef {
1727            doc_comments: vec![], // TODO: collect doc comments
1728            visibility,
1729            attrs,
1730            name,
1731            generics,
1732            fields,
1733        })
1734    }
1735
1736    fn parse_derive_trait(name: &str) -> ParseResult<DeriveTrait> {
1737        match name {
1738            "Debug" => Ok(DeriveTrait::Debug),
1739            "Clone" => Ok(DeriveTrait::Clone),
1740            "Copy" => Ok(DeriveTrait::Copy),
1741            "Default" => Ok(DeriveTrait::Default),
1742            "PartialEq" => Ok(DeriveTrait::PartialEq),
1743            "Eq" => Ok(DeriveTrait::Eq),
1744            "PartialOrd" => Ok(DeriveTrait::PartialOrd),
1745            "Ord" => Ok(DeriveTrait::Ord),
1746            "Hash" => Ok(DeriveTrait::Hash),
1747            // ECS traits
1748            "Component" => Ok(DeriveTrait::Component),
1749            "Resource" => Ok(DeriveTrait::Resource),
1750            "Bundle" => Ok(DeriveTrait::Bundle),
1751            // Serde traits
1752            "Serialize" => Ok(DeriveTrait::Serialize),
1753            "Deserialize" => Ok(DeriveTrait::Deserialize),
1754            // Custom derive
1755            _ => Ok(DeriveTrait::Custom(name.to_string())),
1756        }
1757    }
1758
1759    fn parse_enum_with_doc_comments(
1760        &mut self,
1761        visibility: Visibility,
1762        doc_comments: Vec<crate::ast::DocComment>,
1763    ) -> ParseResult<EnumDef> {
1764        let mut result = self.parse_enum(visibility)?;
1765        result.doc_comments = doc_comments;
1766        Ok(result)
1767    }
1768
1769    fn parse_enum(&mut self, visibility: Visibility) -> ParseResult<EnumDef> {
1770        self.expect(Token::Enum)?;
1771        let name = self.parse_ident()?;
1772        let generics = self.parse_generics_opt()?;
1773
1774        self.expect(Token::LBrace)?;
1775        let mut variants = Vec::new();
1776        while !self.check(&Token::RBrace) && !self.is_eof() {
1777            // Skip doc comments, line comments, and attributes before variants
1778            while matches!(
1779                self.current_token(),
1780                Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
1781            ) {
1782                self.advance();
1783            }
1784            // Skip any outer attributes (#[...] or @[...])
1785            while self.check(&Token::Hash) || self.check(&Token::At) {
1786                self.parse_outer_attribute()?;
1787            }
1788            // Skip any additional comments after attributes
1789            while matches!(
1790                self.current_token(),
1791                Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
1792            ) {
1793                self.advance();
1794            }
1795            if self.check(&Token::RBrace) {
1796                break;
1797            }
1798            variants.push(self.parse_enum_variant()?);
1799            if !self.consume_if(&Token::Comma) {
1800                break;
1801            }
1802            // Skip trailing comments after comma
1803            while matches!(
1804                self.current_token(),
1805                Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
1806            ) {
1807                self.advance();
1808            }
1809        }
1810        self.expect(Token::RBrace)?;
1811
1812        Ok(EnumDef {
1813            doc_comments: vec![], // TODO: collect doc comments
1814            visibility,
1815            name,
1816            generics,
1817            variants,
1818        })
1819    }
1820
1821    fn parse_enum_variant(&mut self) -> ParseResult<EnumVariant> {
1822        let name = self.parse_ident()?;
1823
1824        let fields = if self.check(&Token::LBrace) {
1825            self.expect(Token::LBrace)?;
1826            let fields = self.parse_field_defs()?;
1827            self.expect(Token::RBrace)?;
1828            StructFields::Named(fields)
1829        } else if self.check(&Token::LParen) {
1830            self.expect(Token::LParen)?;
1831            let types = self.parse_attributed_type_list()?;
1832            self.expect(Token::RParen)?;
1833            StructFields::Tuple(types)
1834        } else {
1835            StructFields::Unit
1836        };
1837
1838        let discriminant = if self.consume_if(&Token::Eq) {
1839            Some(self.parse_expr()?)
1840        } else {
1841            None
1842        };
1843
1844        Ok(EnumVariant {
1845            name,
1846            fields,
1847            discriminant,
1848        })
1849    }
1850
1851    fn parse_trait_with_doc_comments(
1852        &mut self,
1853        visibility: Visibility,
1854        doc_comments: Vec<crate::ast::DocComment>,
1855    ) -> ParseResult<TraitDef> {
1856        let mut result = self.parse_trait(visibility)?;
1857        result.doc_comments = doc_comments;
1858        Ok(result)
1859    }
1860
1861    fn parse_trait(&mut self, visibility: Visibility) -> ParseResult<TraitDef> {
1862        self.expect(Token::Trait)?;
1863        let name = self.parse_ident()?;
1864        let generics = self.parse_generics_opt()?;
1865
1866        let supertraits = if self.consume_if(&Token::Colon) {
1867            self.parse_type_bounds()?
1868        } else {
1869            vec![]
1870        };
1871
1872        self.expect(Token::LBrace)?;
1873        let mut items = Vec::new();
1874        while !self.check(&Token::RBrace) && !self.is_eof() {
1875            // Skip doc comments and line comments before trait items
1876            while matches!(
1877                self.current_token(),
1878                Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
1879            ) {
1880                self.advance();
1881            }
1882            if self.check(&Token::RBrace) {
1883                break;
1884            }
1885            items.push(self.parse_trait_item()?);
1886        }
1887        self.expect(Token::RBrace)?;
1888
1889        Ok(TraitDef {
1890            doc_comments: vec![], // TODO: collect doc comments
1891            visibility,
1892            name,
1893            generics,
1894            supertraits,
1895            items,
1896        })
1897    }
1898
1899    fn parse_trait_item(&mut self) -> ParseResult<TraitItem> {
1900        let visibility = self.parse_visibility()?;
1901
1902        match self.current_token() {
1903            Some(Token::Fn) | Some(Token::Async) | Some(Token::Unsafe) => {
1904                Ok(TraitItem::Function(self.parse_function(visibility)?))
1905            }
1906            Some(Token::Type) => {
1907                self.advance();
1908                let name = self.parse_ident()?;
1909                let bounds = if self.consume_if(&Token::Colon) {
1910                    self.parse_type_bounds()?
1911                } else {
1912                    vec![]
1913                };
1914                self.expect(Token::Semi)?;
1915                Ok(TraitItem::Type { name, bounds })
1916            }
1917            Some(Token::Const) => {
1918                // Check if this is `const fn` or just `const NAME: TYPE;`
1919                if self.peek_next().map(|t| matches!(t, Token::Fn | Token::Async)) == Some(true) {
1920                    Ok(TraitItem::Function(self.parse_function(visibility)?))
1921                } else {
1922                    self.advance();
1923                    let name = self.parse_ident()?;
1924                    self.expect(Token::Colon)?;
1925                    let ty = self.parse_type()?;
1926                    self.expect(Token::Semi)?;
1927                    Ok(TraitItem::Const { name, ty })
1928                }
1929            }
1930            Some(token) => Err(ParseError::UnexpectedToken {
1931                expected: "trait item".to_string(),
1932                found: token.clone(),
1933                span: self.current_span(),
1934            }),
1935            None => Err(ParseError::UnexpectedEof),
1936        }
1937    }
1938
1939    fn parse_impl_with_doc_comments(
1940        &mut self,
1941        doc_comments: Vec<crate::ast::DocComment>,
1942    ) -> ParseResult<ImplBlock> {
1943        let mut result = self.parse_impl()?;
1944        result.doc_comments = doc_comments;
1945        Ok(result)
1946    }
1947
1948    fn parse_impl(&mut self) -> ParseResult<ImplBlock> {
1949        self.expect(Token::Impl)?;
1950        let generics = self.parse_generics_opt()?;
1951
1952        // Parse either `Trait for Type` or just `Type`
1953        let first_type = self.parse_type()?;
1954
1955        // Support both `⊢ Trait ∀ Type` and `⊢ Type : Trait` syntax
1956        let (trait_, self_ty) = if self.consume_if(&Token::ForAll) {
1957            // Traditional syntax: ⊢ Trait ∀ Type (impl Trait for Type)
1958            let self_ty = self.parse_type()?;
1959            let trait_path = match first_type {
1960                TypeExpr::Path(p) => p,
1961                _ => return Err(ParseError::Custom("expected trait path".to_string())),
1962            };
1963            (Some(trait_path), self_ty)
1964        } else if self.consume_if(&Token::Colon) {
1965            // Sigil prose syntax: ⊢ Type : Trait (impl Trait for Type)
1966            let trait_ty = self.parse_type()?;
1967            let trait_path = match trait_ty {
1968                TypeExpr::Path(p) => p,
1969                _ => return Err(ParseError::Custom("expected trait path".to_string())),
1970            };
1971            (Some(trait_path), first_type)
1972        } else {
1973            (None, first_type)
1974        };
1975
1976        // Optional where clause for impl bounds (parsed but not yet stored in AST)
1977        let _ = self.parse_where_clause_opt()?;
1978
1979        self.expect(Token::LBrace)?;
1980        let mut items = Vec::new();
1981        while !self.check(&Token::RBrace) && !self.is_eof() {
1982            // Skip doc comments, line comments, and attributes before impl items
1983            while matches!(
1984                self.current_token(),
1985                Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_)) | Some(Token::Hash)
1986            ) {
1987                if self.check(&Token::Hash) {
1988                    // Skip attribute: #[...] or #![...]
1989                    self.advance();
1990                    self.consume_if(&Token::Bang);
1991                    if self.consume_if(&Token::LBracket) {
1992                        let mut depth = 1;
1993                        while depth > 0 && !self.is_eof() {
1994                            match self.current_token() {
1995                                Some(Token::LBracket) => depth += 1,
1996                                Some(Token::RBracket) => depth -= 1,
1997                                _ => {}
1998                            }
1999                            self.advance();
2000                        }
2001                    }
2002                } else {
2003                    self.advance();
2004                }
2005            }
2006            if self.check(&Token::RBrace) {
2007                break;
2008            }
2009            items.push(self.parse_impl_item()?);
2010        }
2011        self.expect(Token::RBrace)?;
2012
2013        Ok(ImplBlock {
2014            doc_comments: vec![], // TODO: collect doc comments
2015            generics,
2016            trait_,
2017            self_ty,
2018            items,
2019        })
2020    }
2021
2022    fn parse_impl_item(&mut self) -> ParseResult<ImplItem> {
2023        // Parse outer attributes (#[...] or @[...])
2024        let mut outer_attrs = Vec::new();
2025        while self.check(&Token::Hash) || self.check(&Token::At) {
2026            outer_attrs.push(self.parse_outer_attribute()?);
2027        }
2028
2029        let visibility = self.parse_visibility()?;
2030
2031        match self.current_token() {
2032            Some(Token::Fn) | Some(Token::Async) | Some(Token::Unsafe) => {
2033                Ok(ImplItem::Function(self.parse_function_with_attrs(visibility, outer_attrs)?))
2034            }
2035            Some(Token::Type) => Ok(ImplItem::Type(self.parse_type_alias(visibility)?)),
2036            Some(Token::Const) => {
2037                // Check if this is `const fn` or just `const`
2038                if self.peek_next().map(|t| matches!(t, Token::Fn | Token::Async)) == Some(true) {
2039                    Ok(ImplItem::Function(self.parse_function_with_attrs(visibility, outer_attrs)?))
2040                } else {
2041                    Ok(ImplItem::Const(self.parse_const(visibility)?))
2042                }
2043            }
2044            Some(token) => Err(ParseError::UnexpectedToken {
2045                expected: "impl item".to_string(),
2046                found: token.clone(),
2047                span: self.current_span(),
2048            }),
2049            None => Err(ParseError::UnexpectedEof),
2050        }
2051    }
2052
2053    fn parse_type_alias(&mut self, visibility: Visibility) -> ParseResult<TypeAlias> {
2054        self.expect(Token::Type)?;
2055        let name = self.parse_ident()?;
2056        let generics = self.parse_generics_opt()?;
2057        // Handle evidentiality marker after name: type Weights~ = ...
2058        let _evidentiality = self.parse_evidentiality_opt();
2059        self.expect(Token::Eq)?;
2060        let ty = self.parse_type()?;
2061        // Semicolon is optional for type aliases (especially after inline struct types)
2062        self.consume_if(&Token::Semi);
2063
2064        Ok(TypeAlias {
2065            visibility,
2066            name,
2067            generics,
2068            ty,
2069        })
2070    }
2071
2072    fn parse_module_with_doc_comments(
2073        &mut self,
2074        visibility: Visibility,
2075        doc_comments: Vec<crate::ast::DocComment>,
2076    ) -> ParseResult<Module> {
2077        let mut result = self.parse_module(visibility)?;
2078        result.doc_comments = doc_comments;
2079        Ok(result)
2080    }
2081
2082    fn parse_module(&mut self, visibility: Visibility) -> ParseResult<Module> {
2083        self.expect(Token::Mod)?;
2084        let name = self.parse_ident()?;
2085
2086        let items = if self.check(&Token::LBrace) {
2087            self.expect(Token::LBrace)?;
2088            let mut items = Vec::new();
2089            while !self.check(&Token::RBrace) && !self.is_eof() {
2090                // Skip doc comments and line comments before items
2091                while matches!(
2092                    self.current_token(),
2093                    Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
2094                ) {
2095                    self.advance();
2096                }
2097                if self.check(&Token::RBrace) {
2098                    break;
2099                }
2100                items.push(self.parse_item()?);
2101            }
2102            self.expect(Token::RBrace)?;
2103            Some(items)
2104        } else {
2105            // Semicolon is optional in Sigil's advanced syntax
2106            self.expect_semi_or_item_start()?;
2107            None
2108        };
2109
2110        Ok(Module {
2111            doc_comments: vec![], // TODO: collect doc comments
2112            visibility,
2113            name,
2114            items,
2115        })
2116    }
2117
2118    fn parse_use(&mut self, visibility: Visibility) -> ParseResult<UseDecl> {
2119        self.expect(Token::Use)?;
2120        let tree = self.parse_use_tree()?;
2121        // Semicolon is optional in Sigil's advanced syntax
2122        self.expect_semi_or_item_start()?;
2123
2124        Ok(UseDecl { visibility, tree })
2125    }
2126
2127    fn parse_use_tree(&mut self) -> ParseResult<UseTree> {
2128        if self.consume_if(&Token::Star) {
2129            return Ok(UseTree::Glob);
2130        }
2131
2132        if self.check(&Token::LBrace) {
2133            self.expect(Token::LBrace)?;
2134            let mut trees = Vec::new();
2135            while !self.check(&Token::RBrace) {
2136                // Skip comments and attributes inside use groups: #[cfg(...)]
2137                loop {
2138                    if matches!(
2139                        self.current_token(),
2140                        Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
2141                    ) {
2142                        self.advance();
2143                    } else if self.check(&Token::Hash) {
2144                        // Skip attribute: #[...]
2145                        self.skip_attribute()?;
2146                    } else {
2147                        break;
2148                    }
2149                }
2150                if self.check(&Token::RBrace) {
2151                    break;
2152                }
2153                trees.push(self.parse_use_tree()?);
2154                if !self.consume_if(&Token::Comma) {
2155                    break;
2156                }
2157                // Skip comments and attributes after comma
2158                loop {
2159                    if matches!(
2160                        self.current_token(),
2161                        Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
2162                    ) {
2163                        self.advance();
2164                    } else if self.check(&Token::Hash) {
2165                        // Skip attribute: #[...]
2166                        self.skip_attribute()?;
2167                    } else {
2168                        break;
2169                    }
2170                }
2171            }
2172            self.expect(Token::RBrace)?;
2173            return Ok(UseTree::Group(trees));
2174        }
2175
2176        // Handle special keywords that can appear as path segments: crate, super, self
2177        let name = if self.check(&Token::Crate) {
2178            let span = self.current_span();
2179            self.advance();
2180            Ident {
2181                name: "crate".to_string(),
2182                evidentiality: None,
2183                affect: None,
2184                span,
2185            }
2186        } else if self.check(&Token::Super) {
2187            let span = self.current_span();
2188            self.advance();
2189            Ident {
2190                name: "super".to_string(),
2191                evidentiality: None,
2192                affect: None,
2193                span,
2194            }
2195        } else if self.check(&Token::SelfLower) {
2196            let span = self.current_span();
2197            self.advance();
2198            Ident {
2199                name: "self".to_string(),
2200                evidentiality: None,
2201                affect: None,
2202                span,
2203            }
2204        } else if self.check(&Token::Sqrt) {
2205            // Handle sacred constant √2, √3, etc.
2206            let span = self.current_span();
2207            self.advance();
2208            // Check for following integer (e.g., √2)
2209            if let Some(Token::IntLit(n)) = self.current_token().cloned() {
2210                let merged_span = span.merge(self.current_span());
2211                self.advance();
2212                Ident {
2213                    name: format!("√{}", n),
2214                    evidentiality: None,
2215                    affect: None,
2216                    span: merged_span,
2217                }
2218            } else {
2219                Ident {
2220                    name: "√".to_string(),
2221                    evidentiality: None,
2222                    affect: None,
2223                    span,
2224                }
2225            }
2226        } else if self.check(&Token::Phi) {
2227            // Handle φ (golden ratio) as import name
2228            let span = self.current_span();
2229            self.advance();
2230            Ident {
2231                name: "φ".to_string(),
2232                evidentiality: None,
2233                affect: None,
2234                span,
2235            }
2236        } else {
2237            self.parse_ident()?
2238        };
2239
2240        // Handle macro import or evidentiality suffix: Gradients!, MomentEstimate~
2241        // These are valid in use statements for macro types or evidential type aliases
2242        let _evidentiality = self.parse_evidentiality_opt();
2243
2244        // Check for path continuation with · or ::
2245        if self.consume_if(&Token::MiddleDot) || self.consume_if(&Token::MiddleDot) {
2246            let suffix = self.parse_use_tree()?;
2247            return Ok(UseTree::Path {
2248                prefix: name,
2249                suffix: Box::new(suffix),
2250            });
2251        }
2252
2253        // Check for rename
2254        if self.consume_if(&Token::As) {
2255            // Allow underscore as alias: `use foo::Bar as _`
2256            if self.check(&Token::Underscore) {
2257                let span = self.current_span();
2258                self.advance();
2259                let alias = Ident {
2260                    name: "_".to_string(),
2261                    evidentiality: None,
2262                    affect: None,
2263                    span,
2264                };
2265                return Ok(UseTree::Rename { name, alias });
2266            }
2267            let alias = self.parse_ident()?;
2268            return Ok(UseTree::Rename { name, alias });
2269        }
2270
2271        Ok(UseTree::Name(name))
2272    }
2273
2274    fn parse_const_with_doc_comments(
2275        &mut self,
2276        visibility: Visibility,
2277        doc_comments: Vec<crate::ast::DocComment>,
2278    ) -> ParseResult<ConstDef> {
2279        let mut result = self.parse_const(visibility)?;
2280        result.doc_comments = doc_comments;
2281        Ok(result)
2282    }
2283
2284    fn parse_const(&mut self, visibility: Visibility) -> ParseResult<ConstDef> {
2285        self.expect(Token::Const)?;
2286        let name = self.parse_ident()?;
2287        self.expect(Token::Colon)?;
2288        let ty = self.parse_type()?;
2289        self.expect(Token::Eq)?;
2290        let value = self.parse_expr()?;
2291        // Semicolon is optional in Sigil's advanced syntax
2292        self.expect_semi_or_item_start()?;
2293
2294        Ok(ConstDef {
2295            doc_comments: vec![],
2296            visibility,
2297            name,
2298            ty,
2299            value,
2300        })
2301    }
2302
2303    fn parse_static_with_doc_comments(
2304        &mut self,
2305        visibility: Visibility,
2306        doc_comments: Vec<crate::ast::DocComment>,
2307    ) -> ParseResult<StaticDef> {
2308        let mut result = self.parse_static(visibility)?;
2309        result.doc_comments = doc_comments;
2310        Ok(result)
2311    }
2312
2313    fn parse_static(&mut self, visibility: Visibility) -> ParseResult<StaticDef> {
2314        self.expect(Token::Static)?;
2315        let mutable = self.consume_if(&Token::Mut);
2316        let name = self.parse_ident()?;
2317        self.expect(Token::Colon)?;
2318        let ty = self.parse_type()?;
2319        self.expect(Token::Eq)?;
2320        let value = self.parse_expr()?;
2321        // Semicolon is optional in Sigil's advanced syntax
2322        self.expect_semi_or_item_start()?;
2323
2324        Ok(StaticDef {
2325            doc_comments: vec![],
2326            visibility,
2327            mutable,
2328            name,
2329            ty,
2330            value,
2331        })
2332    }
2333
2334    /// Parse a macro definition: `macro name { ... }` or `macro name(...) { ... }`
2335    /// Also supports Rust-style: `macro_rules! name { ... }`
2336    fn parse_macro_def(&mut self, visibility: Visibility) -> ParseResult<MacroDef> {
2337        // Handle `macro`, `macro_rules`, and `rune` keywords
2338        let is_macro_rules = self.check(&Token::MacroRules);
2339        let is_rune = self.check(&Token::Rune);
2340        if is_macro_rules {
2341            self.advance(); // consume 'macro_rules'
2342            self.expect(Token::Bang)?; // consume '!'
2343        } else if is_rune {
2344            self.advance(); // consume 'rune'
2345        } else {
2346            self.expect(Token::Macro)?;
2347        }
2348
2349        let name = self.parse_ident()?;
2350
2351        // For rune definitions, consume the trailing `!` after the name: `rune double! { ... }`
2352        if is_rune {
2353            let _ = self.consume_if(&Token::Bang);
2354        }
2355
2356        // Collect the entire macro body as a string (we don't interpret macros)
2357        // Could be: macro name { ... } or macro name(...) { ... } or macro name($arg:ty) { ... }
2358        let mut body = String::new();
2359        let mut depth = 0;
2360
2361        // Check for optional parameter list (parentheses)
2362        if self.check(&Token::LParen) {
2363            body.push('(');
2364            self.advance();
2365            depth = 1;
2366            while depth > 0 && !self.is_eof() {
2367                match self.current_token() {
2368                    Some(Token::LParen) => {
2369                        depth += 1;
2370                        body.push('(');
2371                    }
2372                    Some(Token::RParen) => {
2373                        depth -= 1;
2374                        if depth > 0 {
2375                            body.push(')');
2376                        }
2377                    }
2378                    Some(tok) => {
2379                        body.push_str(&Self::token_to_source(tok));
2380                        // Don't add space after $ (Dollar) to keep $param together
2381                        if !matches!(tok, Token::Dollar) {
2382                            body.push(' ');
2383                        }
2384                    }
2385                    None => break,
2386                }
2387                self.advance();
2388            }
2389            body.push(')');
2390        }
2391
2392        // Expect the body in braces
2393        self.expect(Token::LBrace)?;
2394        body.push('{');
2395        depth = 1;
2396        while depth > 0 && !self.is_eof() {
2397            match self.current_token() {
2398                Some(Token::LBrace) => {
2399                    depth += 1;
2400                    body.push('{');
2401                }
2402                Some(Token::RBrace) => {
2403                    depth -= 1;
2404                    if depth > 0 {
2405                        body.push('}');
2406                    }
2407                }
2408                Some(Token::LineComment(s)) => {
2409                    body.push_str(&format!("//{}\n", s));
2410                }
2411                Some(tok) => {
2412                    body.push_str(&Self::token_to_source(tok));
2413                    // Don't add space after $ (Dollar) to keep $param together
2414                    if !matches!(tok, Token::Dollar) {
2415                        body.push(' ');
2416                    }
2417                }
2418                None => break,
2419            }
2420            self.advance();
2421        }
2422        body.push('}');
2423
2424        Ok(MacroDef {
2425            visibility,
2426            name,
2427            rules: body,
2428        })
2429    }
2430
2431    /// Check if the current position looks like a macro invocation (ident! or path::ident!)
2432    fn looks_like_macro_invocation(&mut self) -> bool {
2433        // Check if current is identifier
2434        if !matches!(self.current_token(), Some(Token::Ident(_))) {
2435            return false;
2436        }
2437        // Scan ahead for pattern: (ident (:: ident)*) !
2438        // Position 0 = first token after current (peek_n(0)), etc.
2439        let mut pos = 0;
2440        loop {
2441            match self.peek_n(pos) {
2442                Some(Token::Bang) => return true,
2443                Some(Token::MiddleDot) => {
2444                    pos += 1;
2445                    // Next should be an identifier
2446                    match self.peek_n(pos) {
2447                        Some(Token::Ident(_)) => {
2448                            pos += 1;
2449                            continue;
2450                        }
2451                        _ => return false,
2452                    }
2453                }
2454                _ => return false,
2455            }
2456        }
2457    }
2458
2459    /// Convert a token to its source text representation.
2460    fn token_to_source(tok: &Token) -> String {
2461        match tok {
2462            // Keywords (Sigil uses different keyword names internally)
2463            // Native Sigil keywords (must use native forms for macro re-parsing)
2464            Token::Pub => "☉".to_string(),
2465            Token::Static => "static".to_string(),
2466            Token::Mut => "Δ".to_string(),
2467            Token::Const => "const".to_string(),
2468            Token::Let => "≔".to_string(),
2469            Token::Fn => "rite".to_string(),
2470            Token::Struct => "sigil".to_string(),
2471            Token::Enum => "ᛈ".to_string(),
2472            Token::Impl => "⊢".to_string(),
2473            Token::Trait => "aspect".to_string(),
2474            Token::Type => "type".to_string(),
2475            Token::Mod => "scroll".to_string(),
2476            Token::Use => "invoke".to_string(),
2477            Token::ForAll => "∀".to_string(),
2478            Token::ElementOf => "∈".to_string(),
2479            Token::If => "⎇".to_string(),
2480            Token::Else => "⎉".to_string(),
2481            Token::Match => "⌥".to_string(),
2482            Token::While => "⟳".to_string(),
2483            Token::Loop => "loop".to_string(),
2484            Token::Tensor => "⊗".to_string(),
2485            Token::CycleArrow => "↻".to_string(),
2486            Token::Return => "⤺".to_string(),
2487            Token::Yield => "yield".to_string(),
2488            Token::True => "true".to_string(),
2489            Token::False => "false".to_string(),
2490            Token::SelfLower => "self".to_string(),
2491            Token::SelfUpper => "Self".to_string(),
2492            Token::Super => "super".to_string(),
2493            Token::Crate => "tome".to_string(), // Sigil keyword for crate
2494            Token::Where => "where".to_string(),
2495            Token::As => "as".to_string(),
2496            Token::Async => "async".to_string(),
2497            Token::Await => "await".to_string(),
2498            Token::Dyn => "dyn".to_string(),
2499            Token::Extern => "extern".to_string(),
2500            Token::Move => "move".to_string(),
2501            Token::Ref => "ref".to_string(),
2502            Token::Unsafe => "unsafe".to_string(),
2503            Token::On => "on".to_string(),
2504            Token::Actor => "actor".to_string(),
2505            Token::Macro => "macro".to_string(),
2506            Token::MacroRules => "macro_rules".to_string(),
2507            Token::Null => "null".to_string(),
2508            // Identifiers and literals
2509            Token::Ident(s) => s.clone(),
2510            Token::IntLit(s) => s.clone(),
2511            Token::FloatLit(s) => s.clone(),
2512            Token::HexLit(s) => s.clone(),
2513            Token::OctalLit(s) => s.clone(),
2514            Token::BinaryLit(s) => s.clone(),
2515            Token::StringLit(s) => format!("\"{}\"", s),
2516            Token::RawStringLit(s) => format!("r\"{}\"", s),
2517            Token::RawStringDelimited(s) => format!("r#\"{}\"#", s),
2518            Token::MultiLineStringLit(s) => format!("\"\"\"{}\"\"\"", s),
2519            Token::CharLit(c) => format!("'{}'", c),
2520            Token::ByteStringLit(bytes) => {
2521                format!("b\"{}\"", String::from_utf8_lossy(bytes))
2522            }
2523            Token::ByteCharLit(b) => format!("b'{}'", *b as char),
2524            Token::Lifetime(s) => format!("'{}", s),
2525            Token::InterpolatedStringLit(s) => format!("f\"{}\"", s),
2526            // Punctuation
2527            Token::Colon => ":".to_string(),
2528            Token::MiddleDot => "·".to_string(),
2529            Token::Semi => ";".to_string(),
2530            Token::Comma => ",".to_string(),
2531            Token::Dot => ".".to_string(),
2532            Token::DotDot => "..".to_string(),
2533            Token::DotDotEq => "..=".to_string(),
2534            Token::Arrow => "->".to_string(),
2535            Token::FatArrow => "=>".to_string(),
2536            Token::LeftArrow => "<-".to_string(),
2537            Token::Question => "?".to_string(),
2538            Token::Bang => "!".to_string(),
2539            Token::Hash => "#".to_string(),
2540            Token::HashBang => "#!".to_string(),
2541            Token::At => "@".to_string(),
2542            Token::Dollar => "$".to_string(),
2543            Token::Underscore => "_".to_string(),
2544            // Comparison operators
2545            Token::Eq => "=".to_string(),
2546            Token::EqEq => "==".to_string(),
2547            Token::NotEq => "!=".to_string(),
2548            Token::Lt => "<".to_string(),
2549            Token::LtEq => "<=".to_string(),
2550            Token::Gt => ">".to_string(),
2551            Token::GtEq => ">=".to_string(),
2552            // Arithmetic operators
2553            Token::Plus => "+".to_string(),
2554            Token::Minus => "-".to_string(),
2555            Token::Star => "*".to_string(),
2556            Token::Slash => "/".to_string(),
2557            Token::Percent => "%".to_string(),
2558            Token::StarStar => "**".to_string(),
2559            Token::PlusPlus => "++".to_string(),
2560            // Bitwise/logical operators
2561            Token::Amp => "&".to_string(),
2562            Token::AndAnd => "&&".to_string(),
2563            Token::Pipe => "|".to_string(),
2564            Token::OrOr => "||".to_string(),
2565            Token::Caret => "^".to_string(),
2566            Token::Tilde => "~".to_string(),
2567            Token::Shl => "<<".to_string(),
2568            Token::Shr => ">>".to_string(),
2569            // Assignment operators
2570            Token::PlusEq => "+=".to_string(),
2571            Token::MinusEq => "-=".to_string(),
2572            Token::StarEq => "*=".to_string(),
2573            Token::SlashEq => "/=".to_string(),
2574            Token::PercentEq => "%=".to_string(),
2575            Token::AmpEq => "&=".to_string(),
2576            Token::PipeEq => "|=".to_string(),
2577            Token::CaretEq => "^=".to_string(),
2578            Token::ShlEq => "<<=".to_string(),
2579            Token::ShrEq => ">>=".to_string(),
2580            // Delimiters
2581            Token::LParen => "(".to_string(),
2582            Token::RParen => ")".to_string(),
2583            Token::LBrace => "{".to_string(),
2584            Token::RBrace => "}".to_string(),
2585            Token::LBracket => "[".to_string(),
2586            Token::RBracket => "]".to_string(),
2587            Token::MiddleDot => "·".to_string(),
2588            // Morpheme operators
2589            Token::Tau => "τ".to_string(),
2590            Token::Phi => "φ".to_string(),
2591            Token::Sigma => "σ".to_string(),
2592            Token::Rho => "ρ".to_string(),
2593            Token::Alpha => "α".to_string(),
2594            Token::Omega => "ω".to_string(),
2595            Token::Mu => "μ".to_string(),
2596            Token::Lambda => "Λ".to_string(),
2597            Token::LambdaExpr => "λ".to_string(),
2598            Token::Pi => "Π".to_string(),
2599            Token::Delta => "δ".to_string(),
2600            Token::Epsilon => "ε".to_string(),
2601            Token::Zeta => "ζ".to_string(),
2602            Token::Chi => "χ".to_string(),
2603            Token::Nu => "ν".to_string(),
2604            Token::Xi => "ξ".to_string(),
2605            Token::Psi => "ψ".to_string(),
2606            Token::Theta => "θ".to_string(),
2607            Token::Kappa => "κ".to_string(),
2608            Token::Nabla => "∇".to_string(),
2609            // Special symbols
2610            Token::Empty => "∅".to_string(),
2611            Token::Circle => "◯".to_string(),
2612            Token::Infinity => "∞".to_string(),
2613            Token::Async => "⌛".to_string(),
2614            // Comments
2615            Token::LineComment(s) => format!("//{}", s),
2616            Token::TildeComment(s) => format!("~~{}", s),
2617            Token::BlockComment(s) => format!("/*{}*/", s),
2618            Token::DocComment(s) => format!("///{}", s),
2619            // For any other token, use debug format
2620            _ => format!("{:?}", tok),
2621        }
2622    }
2623
2624    /// Parse a macro invocation: `name! { ... }` or `path::to::macro! { ... }`
2625    fn parse_macro_invocation(&mut self) -> ParseResult<MacroInvocation> {
2626        use crate::ast::{MacroDelimiter, MacroInvocation};
2627
2628        // Parse the path (macro name, potentially with ::)
2629        let path = self.parse_type_path()?;
2630
2631        // Expect !
2632        self.expect(Token::Bang)?;
2633
2634        // Determine delimiter and parse body
2635        let (delimiter, open_tok, close_tok) = match self.current_token() {
2636            Some(Token::LBrace) => (MacroDelimiter::Brace, Token::LBrace, Token::RBrace),
2637            Some(Token::LParen) => (MacroDelimiter::Paren, Token::LParen, Token::RParen),
2638            Some(Token::LBracket) => (MacroDelimiter::Bracket, Token::LBracket, Token::RBracket),
2639            Some(tok) => {
2640                return Err(ParseError::UnexpectedToken {
2641                    expected: "macro delimiter ('{', '(', or '[')".to_string(),
2642                    found: tok.clone(),
2643                    span: self.current_span(),
2644                });
2645            }
2646            None => return Err(ParseError::UnexpectedEof),
2647        };
2648
2649        self.advance(); // consume opening delimiter
2650
2651        // Collect body tokens as source text
2652        let mut body = String::new();
2653        let mut depth = 1;
2654
2655        while depth > 0 && !self.is_eof() {
2656            let tok = self.current_token().cloned();
2657            match &tok {
2658                Some(t) if *t == open_tok => {
2659                    depth += 1;
2660                    body.push_str(&Self::token_to_source(t));
2661                    body.push(' ');
2662                }
2663                Some(t) if *t == close_tok => {
2664                    depth -= 1;
2665                    if depth > 0 {
2666                        body.push_str(&Self::token_to_source(t));
2667                        body.push(' ');
2668                    }
2669                }
2670                Some(t) => {
2671                    body.push_str(&Self::token_to_source(t));
2672                    body.push(' ');
2673                }
2674                None => break,
2675            }
2676            self.advance();
2677        }
2678
2679        // For () and [] delimited macros at item level, consume trailing semicolon
2680        if delimiter != MacroDelimiter::Brace {
2681            self.consume_if(&Token::Semi);
2682        }
2683
2684        Ok(MacroInvocation {
2685            path,
2686            delimiter,
2687            tokens: body,
2688        })
2689    }
2690
2691    fn parse_actor(&mut self, visibility: Visibility) -> ParseResult<ActorDef> {
2692        self.expect(Token::Actor)?;
2693        let name = self.parse_ident()?;
2694        let generics = self.parse_generics_opt()?;
2695
2696        self.expect(Token::LBrace)?;
2697
2698        let mut state = Vec::new();
2699        let mut handlers = Vec::new();
2700
2701        while !self.check(&Token::RBrace) && !self.is_eof() {
2702            if self.check(&Token::On) {
2703                handlers.push(self.parse_message_handler()?);
2704            } else {
2705                // Parse state field
2706                let vis = self.parse_visibility()?;
2707                let field_name = self.parse_ident()?;
2708                self.expect(Token::Colon)?;
2709                let ty = self.parse_type()?;
2710
2711                // Optional default value
2712                let default = if self.consume_if(&Token::Eq) {
2713                    Some(self.parse_expr()?)
2714                } else {
2715                    None
2716                };
2717
2718                if !self.check(&Token::RBrace) && !self.check(&Token::On) {
2719                    self.consume_if(&Token::Comma);
2720                }
2721
2722                state.push(FieldDef {
2723                    visibility: vis,
2724                    name: field_name,
2725                    ty,
2726                    default,
2727                });
2728            }
2729        }
2730
2731        self.expect(Token::RBrace)?;
2732
2733        Ok(ActorDef {
2734            visibility,
2735            name,
2736            generics,
2737            state,
2738            handlers,
2739        })
2740    }
2741
2742    /// Parse an extern block: `extern "C" { ... }`
2743    fn parse_extern_block(&mut self) -> ParseResult<ExternBlock> {
2744        self.expect(Token::Extern)?;
2745
2746        // Parse ABI string (default to "C")
2747        let abi = if let Some(Token::StringLit(s)) = self.current_token().cloned() {
2748            self.advance();
2749            s
2750        } else {
2751            "C".to_string()
2752        };
2753
2754        self.expect(Token::LBrace)?;
2755
2756        let mut items = Vec::new();
2757
2758        while !self.check(&Token::RBrace) && !self.is_eof() {
2759            let visibility = self.parse_visibility()?;
2760
2761            match self.current_token() {
2762                Some(Token::Fn) => {
2763                    items.push(ExternItem::Function(
2764                        self.parse_extern_function(visibility)?,
2765                    ));
2766                }
2767                Some(Token::Static) => {
2768                    items.push(ExternItem::Static(self.parse_extern_static(visibility)?));
2769                }
2770                Some(token) => {
2771                    return Err(ParseError::UnexpectedToken {
2772                        expected: "fn or static".to_string(),
2773                        found: token.clone(),
2774                        span: self.current_span(),
2775                    });
2776                }
2777                None => return Err(ParseError::UnexpectedEof),
2778            }
2779        }
2780
2781        self.expect(Token::RBrace)?;
2782
2783        Ok(ExternBlock { abi, items })
2784    }
2785
2786    /// Parse an extern function declaration (no body).
2787    fn parse_extern_function(&mut self, visibility: Visibility) -> ParseResult<ExternFunction> {
2788        self.expect(Token::Fn)?;
2789        let name = self.parse_ident()?;
2790
2791        // Handle evidentiality marker after function name: fn load_safetensors~(...)
2792        let _evidentiality = self.parse_evidentiality_opt();
2793
2794        self.expect(Token::LParen)?;
2795
2796        let mut params = Vec::new();
2797        let mut variadic = false;
2798
2799        while !self.check(&Token::RParen) && !self.is_eof() {
2800            // Check for variadic: ...
2801            if self.check(&Token::DotDot) {
2802                self.advance();
2803                if self.consume_if(&Token::Dot) {
2804                    variadic = true;
2805                    break;
2806                }
2807            }
2808
2809            let pattern = self.parse_pattern()?;
2810            self.expect(Token::Colon)?;
2811            let ty = self.parse_type()?;
2812
2813            params.push(Param { pattern, ty });
2814
2815            if !self.check(&Token::RParen) {
2816                self.expect(Token::Comma)?;
2817            }
2818        }
2819
2820        self.expect(Token::RParen)?;
2821
2822        // Return type
2823        let return_type = if self.consume_if(&Token::Arrow) {
2824            Some(self.parse_type()?)
2825        } else {
2826            None
2827        };
2828
2829        // Extern functions end with semicolon, not a body
2830        self.expect(Token::Semi)?;
2831
2832        Ok(ExternFunction {
2833            visibility,
2834            name,
2835            params,
2836            return_type,
2837            variadic,
2838        })
2839    }
2840
2841    /// Parse an extern static declaration.
2842    fn parse_extern_static(&mut self, visibility: Visibility) -> ParseResult<ExternStatic> {
2843        self.expect(Token::Static)?;
2844        let mutable = self.consume_if(&Token::Mut);
2845        let name = self.parse_ident()?;
2846        self.expect(Token::Colon)?;
2847        let ty = self.parse_type()?;
2848        self.expect(Token::Semi)?;
2849
2850        Ok(ExternStatic {
2851            visibility,
2852            mutable,
2853            name,
2854            ty,
2855        })
2856    }
2857
2858    fn parse_message_handler(&mut self) -> ParseResult<MessageHandler> {
2859        self.expect(Token::On)?;
2860        let message = self.parse_ident()?;
2861
2862        self.expect(Token::LParen)?;
2863        let params = self.parse_params()?;
2864        self.expect(Token::RParen)?;
2865
2866        let return_type = if self.consume_if(&Token::Arrow) {
2867            Some(self.parse_type()?)
2868        } else {
2869            None
2870        };
2871
2872        let body = self.parse_block()?;
2873
2874        Ok(MessageHandler {
2875            message,
2876            params,
2877            return_type,
2878            body,
2879        })
2880    }
2881
2882    // === Type parsing ===
2883
2884    pub(crate) fn parse_type(&mut self) -> ParseResult<TypeExpr> {
2885        // Check for PREFIX evidentiality: !T, ?T, ~T, ‽T (Sigil-style)
2886        if let Some(ev) = self.parse_evidentiality_prefix_opt() {
2887            let inner = self.parse_type()?;
2888            return Ok(TypeExpr::Evidential {
2889                inner: Box::new(inner),
2890                evidentiality: ev,
2891                error_type: None,
2892            });
2893        }
2894
2895        let mut base = self.parse_type_base()?;
2896
2897        // Check if parse_ident already consumed evidentiality on the type name (e.g., Tensor◊)
2898        // If so, we need to extract it and wrap the type properly
2899        // But DON'T return early - there may be additional evidentiality after generics (e.g., Type~<T>!)
2900        let path_evidentiality = if let TypeExpr::Path(ref mut path) = base {
2901            if let Some(last_seg) = path.segments.last_mut() {
2902                last_seg.ident.evidentiality.take()
2903            } else {
2904                None
2905            }
2906        } else {
2907            None
2908        };
2909        if let Some(ev) = path_evidentiality {
2910            base = TypeExpr::Evidential {
2911                inner: Box::new(base),
2912                evidentiality: ev,
2913                error_type: None,
2914            };
2915        }
2916
2917        // Check for evidentiality suffix: T?, T!, T~, T?[Error], T![Error], T~[Error]
2918        if let Some(ev) = self.parse_evidentiality_opt() {
2919            // Check for generics after evidentiality: Type!<T>, Type?<T>
2920            // Pattern: Gradient!<S, D, Dev> where ! is evidentiality, <...> are generics
2921            let base = if self.check(&Token::Lt) && self.peek_looks_like_generic_arg() {
2922                // Apply generics to the inner path type
2923                if let TypeExpr::Path(mut path) = base {
2924                    self.advance(); // consume <
2925                    let types = self.parse_type_list()?;
2926                    self.expect_gt()?;
2927                    // Add generics to the last segment
2928                    if let Some(last) = path.segments.last_mut() {
2929                        last.generics = Some(types);
2930                    }
2931                    TypeExpr::Path(path)
2932                } else {
2933                    base
2934                }
2935            } else {
2936                base
2937            };
2938
2939            // Check for optional error type bracket: ?[ErrorType]
2940            let error_type = if self.check(&Token::LBracket) {
2941                self.advance(); // consume [
2942                let err_ty = self.parse_type()?;
2943                self.expect(Token::RBracket)?; // consume ]
2944                Some(Box::new(err_ty))
2945            } else {
2946                None
2947            };
2948
2949            let mut result = TypeExpr::Evidential {
2950                inner: Box::new(base),
2951                evidentiality: ev,
2952                error_type,
2953            };
2954
2955            // Check for additional evidentiality suffix: Type~<T>! (chained evidentiality)
2956            if let Some(ev2) = self.parse_evidentiality_opt() {
2957                result = TypeExpr::Evidential {
2958                    inner: Box::new(result),
2959                    evidentiality: ev2,
2960                    error_type: None,
2961                };
2962            }
2963
2964            return Ok(result);
2965        }
2966
2967        Ok(base)
2968    }
2969
2970    /// Parse PREFIX evidentiality marker: !T, ?T, ~T, ◊T, ‽T
2971    /// Only consumes the token if followed by valid type start
2972    fn parse_evidentiality_prefix_opt(&mut self) -> Option<Evidentiality> {
2973        match self.current_token() {
2974            Some(Token::Bang) => {
2975                // Check if this is prefix evidentiality or something else
2976                // Peek to see if next token could be a type
2977                if self.peek_is_type_start() {
2978                    self.advance();
2979                    Some(Evidentiality::Known)
2980                } else {
2981                    None
2982                }
2983            }
2984            Some(Token::Question) => {
2985                if self.peek_is_type_start() {
2986                    self.advance();
2987                    Some(Evidentiality::Uncertain)
2988                } else {
2989                    None
2990                }
2991            }
2992            Some(Token::Tilde) => {
2993                if self.peek_is_type_start() {
2994                    self.advance();
2995                    Some(Evidentiality::Reported)
2996                } else {
2997                    None
2998                }
2999            }
3000            Some(Token::Lozenge) => {
3001                if self.peek_is_type_start() {
3002                    self.advance();
3003                    Some(Evidentiality::Predicted)
3004                } else {
3005                    None
3006                }
3007            }
3008            Some(Token::Interrobang) => {
3009                if self.peek_is_type_start() {
3010                    self.advance();
3011                    Some(Evidentiality::Paradox)
3012                } else {
3013                    None
3014                }
3015            }
3016            _ => None,
3017        }
3018    }
3019
3020    /// Check if the next token (after current) could start a type
3021    fn peek_is_type_start(&mut self) -> bool {
3022        match self.peek_next() {
3023            Some(Token::Ident(_)) => true,
3024            Some(Token::SelfUpper) => true,
3025            Some(Token::Amp) => true,
3026            Some(Token::AndAnd) => true,  // Double reference: &&T
3027            Some(Token::Star) => true,
3028            Some(Token::LBracket) => true,
3029            Some(Token::LParen) => true,
3030            Some(Token::Fn) => true,
3031            Some(Token::Underscore) => true,
3032            Some(Token::Simd) => true,
3033            Some(Token::Atomic) => true,
3034            // Nested prefix evidentiality: !!T, !?T, etc.
3035            Some(Token::Bang) => true,
3036            Some(Token::Question) => true,
3037            Some(Token::Tilde) => true,
3038            Some(Token::Interrobang) => true,
3039            _ => false,
3040        }
3041    }
3042
3043    fn parse_type_base(&mut self) -> ParseResult<TypeExpr> {
3044        // Check for deprecated Rust syntax first
3045        if let Some(Token::DeprecatedAmpMut) = self.current_token() {
3046            let span = self.current_span();
3047            return Err(ParseError::DeprecatedRustSyntax {
3048                rust: "&mut".to_string(),
3049                sigil: "&Δ (reference to mutable) or just Δ for mutable binding".to_string(),
3050                span,
3051            });
3052        }
3053
3054        match self.current_token() {
3055            Some(Token::AndAnd) => {
3056                // Double reference: &&T -> &(&T)
3057                self.advance();
3058                // Check for optional lifetime on inner reference: &&'a T
3059                let lifetime = if let Some(Token::Lifetime(lt)) = self.current_token().cloned() {
3060                    self.advance();
3061                    Some(lt)
3062                } else {
3063                    None
3064                };
3065                let mutable = self.consume_if(&Token::Mut);
3066                let inner = self.parse_type()?;
3067                // Inner reference
3068                let inner_ref = TypeExpr::Reference {
3069                    lifetime,
3070                    mutable,
3071                    inner: Box::new(inner),
3072                };
3073                // Outer reference (immutable, no lifetime)
3074                Ok(TypeExpr::Reference {
3075                    lifetime: None,
3076                    mutable: false,
3077                    inner: Box::new(inner_ref),
3078                })
3079            }
3080            Some(Token::Amp) => {
3081                self.advance();
3082                // Check for optional lifetime: &'a T or &'static T
3083                let lifetime = if let Some(Token::Lifetime(lt)) = self.current_token().cloned() {
3084                    self.advance();
3085                    Some(lt)
3086                } else {
3087                    None
3088                };
3089                let mutable = self.consume_if(&Token::Mut);
3090                let inner = self.parse_type()?;
3091                Ok(TypeExpr::Reference {
3092                    lifetime,
3093                    mutable,
3094                    inner: Box::new(inner),
3095                })
3096            }
3097            Some(Token::Star) => {
3098                self.advance();
3099                // Raw pointer: *const T, *mut T, or *!T (evidential pointer)
3100                // Make const/mut optional to support Sigil's *!T syntax
3101                let mutable = if self.consume_if(&Token::Const) {
3102                    false
3103                } else if self.consume_if(&Token::Mut) {
3104                    true
3105                } else {
3106                    // No const/mut - default to immutable (for *!T style)
3107                    false
3108                };
3109                let inner = self.parse_type()?;
3110                Ok(TypeExpr::Pointer {
3111                    mutable,
3112                    inner: Box::new(inner),
3113                })
3114            }
3115            Some(Token::LBracket) => {
3116                self.advance();
3117                // Check for empty brackets or array/shape syntax
3118                if self.check(&Token::RBracket) {
3119                    // Empty array/scalar shape: [] - used for scalar tensors (0-dimensional)
3120                    self.advance();
3121                    // Return as an empty const expression (empty array literal)
3122                    return Ok(TypeExpr::ConstExpr(Box::new(Expr::Array(vec![]))));
3123                }
3124                // Use parse_type_or_lifetime to handle const generic literals like [2, 4]
3125                let first = self.parse_type_or_lifetime()?;
3126                if self.consume_if(&Token::Semi) {
3127                    // Fixed-size array: [Type; size]
3128                    let size = self.parse_expr()?;
3129                    self.expect(Token::RBracket)?;
3130                    Ok(TypeExpr::Array {
3131                        element: Box::new(first),
3132                        size: Box::new(size),
3133                    })
3134                } else if self.consume_if(&Token::Comma) {
3135                    // Multi-element array shape: [A, B, C] or [D, HD/2] for tensor shapes
3136                    // Parse as const expressions to support arithmetic like HD/2
3137                    let first_expr = match first {
3138                        TypeExpr::Path(path) => Expr::Path(path),
3139                        TypeExpr::ConstExpr(expr) => *expr,
3140                        _ => Expr::Path(TypePath {
3141                            segments: vec![PathSegment {
3142                                ident: Ident {
3143                                    name: format!("{:?}", first),
3144                                    evidentiality: None,
3145                                    affect: None,
3146                                    span: Span::new(0, 0),
3147                                },
3148                                generics: None,
3149                            }],
3150                        }),
3151                    };
3152                    let mut elem_exprs = vec![first_expr];
3153                    while !self.check(&Token::RBracket) && !self.is_eof() {
3154                        // Parse dimension as const expression to support HD/2, N*2, etc.
3155                        let dim_expr = self.parse_array_dim_expr()?;
3156                        elem_exprs.push(dim_expr);
3157                        if !self.consume_if(&Token::Comma) {
3158                            break;
3159                        }
3160                    }
3161                    self.expect(Token::RBracket)?;
3162                    Ok(TypeExpr::ConstExpr(Box::new(Expr::Array(elem_exprs))))
3163                } else if matches!(
3164                    self.current_token(),
3165                    Some(Token::Slash)
3166                        | Some(Token::Star)
3167                        | Some(Token::Plus)
3168                        | Some(Token::Minus)
3169                        | Some(Token::Percent)
3170                ) {
3171                    // Dimension expression with arithmetic: [HD/2], [H * HD, D], etc.
3172                    // Convert first to expression and continue parsing as arithmetic
3173                    let first_expr = match first {
3174                        TypeExpr::Path(path) => Expr::Path(path),
3175                        TypeExpr::ConstExpr(expr) => *expr,
3176                        _ => Expr::Path(TypePath {
3177                            segments: vec![PathSegment {
3178                                ident: Ident {
3179                                    name: format!("{:?}", first),
3180                                    evidentiality: None,
3181                                    affect: None,
3182                                    span: Span::new(0, 0),
3183                                },
3184                                generics: None,
3185                            }],
3186                        }),
3187                    };
3188                    // Now parse the operator and rest of expression
3189                    let op = match self.current_token() {
3190                        Some(Token::Slash) => BinOp::Div,
3191                        Some(Token::Star) => BinOp::Mul,
3192                        Some(Token::Plus) => BinOp::Add,
3193                        Some(Token::Minus) => BinOp::Sub,
3194                        Some(Token::Percent) => BinOp::Rem,
3195                        _ => unreachable!(),
3196                    };
3197                    self.advance(); // consume operator
3198                    let right = self.parse_const_expr_primary()?;
3199                    let expr = Expr::Binary {
3200                        left: Box::new(first_expr),
3201                        op,
3202                        right: Box::new(right),
3203                    };
3204
3205                    // Check for more dimensions after the arithmetic: [H * HD, D]
3206                    if self.consume_if(&Token::Comma) {
3207                        let mut elem_exprs = vec![expr];
3208                        while !self.check(&Token::RBracket) && !self.is_eof() {
3209                            let dim_expr = self.parse_array_dim_expr()?;
3210                            elem_exprs.push(dim_expr);
3211                            if !self.consume_if(&Token::Comma) {
3212                                break;
3213                            }
3214                        }
3215                        self.expect(Token::RBracket)?;
3216                        Ok(TypeExpr::ConstExpr(Box::new(Expr::Array(elem_exprs))))
3217                    } else {
3218                        self.expect(Token::RBracket)?;
3219                        Ok(TypeExpr::ConstExpr(Box::new(Expr::Array(vec![expr]))))
3220                    }
3221                } else {
3222                    self.expect(Token::RBracket)?;
3223                    // Check if first is a ConstExpr containing a literal number
3224                    // If so, treat [3] as a single-element shape, not a slice
3225                    match &first {
3226                        TypeExpr::ConstExpr(expr) => {
3227                            if matches!(expr.as_ref(), Expr::Literal(Literal::Int { .. })) {
3228                                // Single-element shape: [3] means shape [3]
3229                                let first_expr = *expr.clone();
3230                                Ok(TypeExpr::ConstExpr(Box::new(Expr::Array(vec![first_expr]))))
3231                            } else {
3232                                // Slice: [Type]
3233                                Ok(TypeExpr::Slice(Box::new(first)))
3234                            }
3235                        }
3236                        // Also handle Path that looks like a number (from parse_type_or_lifetime)
3237                        TypeExpr::Path(path) if path.segments.len() == 1 => {
3238                            let name = &path.segments[0].ident.name;
3239                            if name.chars().all(|c| c.is_ascii_digit()) {
3240                                // Single numeric literal as path: [3] means shape [3]
3241                                let first_expr = Expr::Literal(Literal::Int {
3242                                    value: name.clone(),
3243                                    base: NumBase::Decimal,
3244                                    suffix: None,
3245                                });
3246                                Ok(TypeExpr::ConstExpr(Box::new(Expr::Array(vec![first_expr]))))
3247                            } else {
3248                                // Slice: [Type]
3249                                Ok(TypeExpr::Slice(Box::new(first)))
3250                            }
3251                        }
3252                        _ => {
3253                            // Slice: [Type]
3254                            Ok(TypeExpr::Slice(Box::new(first)))
3255                        }
3256                    }
3257                }
3258            }
3259            Some(Token::LParen) => {
3260                self.advance();
3261                if self.check(&Token::RParen) {
3262                    self.advance();
3263                    return Ok(TypeExpr::Tuple(vec![]));
3264                }
3265                let types = self.parse_type_list()?;
3266                self.expect(Token::RParen)?;
3267                Ok(TypeExpr::Tuple(types))
3268            }
3269            Some(Token::Fn) => {
3270                self.advance();
3271                self.expect(Token::LParen)?;
3272                let params = self.parse_type_list()?;
3273                self.expect(Token::RParen)?;
3274                let return_type = if self.consume_if(&Token::Arrow) {
3275                    Some(Box::new(self.parse_type()?))
3276                } else {
3277                    None
3278                };
3279                Ok(TypeExpr::Function {
3280                    params,
3281                    return_type,
3282                })
3283            }
3284            Some(Token::Impl) => {
3285                // impl Trait - opaque return type
3286                self.advance();
3287                // Parse trait bounds: impl Trait + OtherTrait + 'lifetime
3288                let bounds = self.parse_type_bounds()?;
3289                Ok(TypeExpr::ImplTrait(bounds))
3290            }
3291            Some(Token::Bang) => {
3292                self.advance();
3293                Ok(TypeExpr::Never)
3294            }
3295            Some(Token::Underscore) => {
3296                self.advance();
3297                Ok(TypeExpr::Infer)
3298            }
3299            Some(Token::Lt) => {
3300                // Qualified path: <Type as Trait>::AssociatedType
3301                // or: <Type>::AssociatedType (inherent associated type)
3302                self.advance(); // consume <
3303                let base_type = self.parse_type()?;
3304
3305                // Check for "as Trait" clause
3306                let trait_path = if self.consume_if(&Token::As) {
3307                    Some(self.parse_type_path()?)
3308                } else {
3309                    None
3310                };
3311
3312                self.expect_gt()?; // consume >
3313                // Accept either middledot (·) or :: for path separator after >
3314                if !self.consume_if(&Token::MiddleDot) && !self.consume_if(&Token::MiddleDot) {
3315                    match self.current_token().cloned() {
3316                        Some(found) => {
3317                            return Err(ParseError::UnexpectedToken {
3318                                expected: "path separator (`·` or `::`) after `>`".to_string(),
3319                                found,
3320                                span: self.current_span(),
3321                            });
3322                        }
3323                        None => return Err(ParseError::UnexpectedEof),
3324                    }
3325                }
3326
3327                // Parse the associated type/const path
3328                let mut segments = vec![self.parse_path_segment()?];
3329                while self.consume_if(&Token::MiddleDot) || self.consume_if(&Token::MiddleDot) {
3330                    segments.push(self.parse_path_segment()?);
3331                }
3332
3333                Ok(TypeExpr::QualifiedPath {
3334                    self_type: Box::new(base_type),
3335                    trait_path,
3336                    item_path: TypePath { segments },
3337                })
3338            }
3339            Some(Token::SelfUpper) => {
3340                let span = self.current_span();
3341                self.advance();
3342                let mut segments = vec![PathSegment {
3343                    ident: Ident {
3344                        name: "Self".to_string(),
3345                        evidentiality: None,
3346                        affect: None,
3347                        span,
3348                    },
3349                    generics: None,
3350                }];
3351                // Continue parsing path: Self::AssociatedType, Self::Nested::Type
3352                while self.consume_if(&Token::MiddleDot) || self.consume_if(&Token::MiddleDot) {
3353                    // Check for turbofish: Self::<T>
3354                    if self.check(&Token::Lt) {
3355                        self.advance();
3356                        let types = self.parse_type_list()?;
3357                        self.expect_gt()?;
3358                        if let Some(last) = segments.last_mut() {
3359                            last.generics = Some(types);
3360                        }
3361                        continue;
3362                    }
3363                    segments.push(self.parse_path_segment()?);
3364                }
3365                Ok(TypeExpr::Path(TypePath { segments }))
3366            }
3367            Some(Token::Simd) => {
3368                self.advance();
3369                self.expect(Token::Lt)?;
3370                let element = self.parse_type()?;
3371                self.expect(Token::Comma)?;
3372                let lanes = match self.current_token() {
3373                    Some(Token::IntLit(s)) => {
3374                        let n = s
3375                            .parse::<u8>()
3376                            .map_err(|_| ParseError::Custom("invalid lane count".to_string()))?;
3377                        self.advance();
3378                        n
3379                    }
3380                    _ => return Err(ParseError::Custom("expected lane count".to_string())),
3381                };
3382                self.expect_gt()?;
3383                Ok(TypeExpr::Simd {
3384                    element: Box::new(element),
3385                    lanes,
3386                })
3387            }
3388            Some(Token::Atomic) => {
3389                self.advance();
3390                self.expect(Token::Lt)?;
3391                let inner = self.parse_type()?;
3392                self.expect_gt()?;
3393                Ok(TypeExpr::Atomic(Box::new(inner)))
3394            }
3395            Some(Token::Dyn) => {
3396                // Parse trait object: dyn Trait or dyn Trait + Send + 'static
3397                self.advance();
3398                let bounds = self.parse_type_bounds()?;
3399                Ok(TypeExpr::TraitObject(bounds))
3400            }
3401            Some(Token::Linear) => {
3402                // Linear type: linear T - must be used exactly once
3403                self.advance();
3404                let inner = self.parse_type()?;
3405                Ok(TypeExpr::Linear(Box::new(inner)))
3406            }
3407            Some(Token::Affine) => {
3408                // Affine type: affine T - can be used at most once
3409                self.advance();
3410                let inner = self.parse_type()?;
3411                Ok(TypeExpr::Affine(Box::new(inner)))
3412            }
3413            Some(Token::Relevant) => {
3414                // Relevant type: relevant T - must be used at least once
3415                self.advance();
3416                let inner = self.parse_type()?;
3417                Ok(TypeExpr::Relevant(Box::new(inner)))
3418            }
3419            Some(Token::Struct) => {
3420                // Inline struct type: struct { field: Type, ... }
3421                self.advance();
3422                self.expect(Token::LBrace)?;
3423                let mut fields = Vec::new();
3424                while !self.check(&Token::RBrace) && !self.is_eof() {
3425                    // Skip comments, doc comments, and attributes
3426                    while matches!(
3427                        self.current_token(),
3428                        Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_)) | Some(Token::Hash)
3429                    ) {
3430                        if self.check(&Token::Hash) {
3431                            // Skip attribute: #[...]
3432                            self.advance();
3433                            if self.consume_if(&Token::LBracket) {
3434                                let mut depth = 1;
3435                                while depth > 0 && !self.is_eof() {
3436                                    match self.current_token() {
3437                                        Some(Token::LBracket) => depth += 1,
3438                                        Some(Token::RBracket) => depth -= 1,
3439                                        _ => {}
3440                                    }
3441                                    self.advance();
3442                                }
3443                            }
3444                        } else {
3445                            self.advance();
3446                        }
3447                    }
3448                    if self.check(&Token::RBrace) {
3449                        break;
3450                    }
3451                    // Parse optional visibility
3452                    let visibility = self.parse_visibility()?;
3453                    let name = self.parse_ident()?;
3454                    self.expect(Token::Colon)?;
3455                    let ty = self.parse_type()?;
3456                    fields.push(FieldDef {
3457                        visibility,
3458                        name,
3459                        ty,
3460                        default: None,
3461                    });
3462                    if !self.consume_if(&Token::Comma) {
3463                        break;
3464                    }
3465                }
3466                self.expect(Token::RBrace)?;
3467                Ok(TypeExpr::InlineStruct { fields })
3468            }
3469            Some(Token::Enum) => {
3470                // Inline enum type: enum { Variant1, Variant2(Type), ... }
3471                self.advance();
3472                self.expect(Token::LBrace)?;
3473                let mut variants = Vec::new();
3474                while !self.check(&Token::RBrace) && !self.is_eof() {
3475                    // Skip comments and doc comments
3476                    while matches!(
3477                        self.current_token(),
3478                        Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
3479                    ) {
3480                        self.advance();
3481                    }
3482                    if self.check(&Token::RBrace) {
3483                        break;
3484                    }
3485                    // Parse variant name
3486                    let name = self.parse_ident()?;
3487                    // Parse optional fields
3488                    let fields = if self.check(&Token::LParen) {
3489                        self.advance();
3490                        let mut types = Vec::new();
3491                        while !self.check(&Token::RParen) && !self.is_eof() {
3492                            types.push(self.parse_type()?);
3493                            if !self.consume_if(&Token::Comma) {
3494                                break;
3495                            }
3496                        }
3497                        self.expect(Token::RParen)?;
3498                        StructFields::Tuple(types)
3499                    } else if self.check(&Token::LBrace) {
3500                        self.advance();
3501                        let mut fields = Vec::new();
3502                        while !self.check(&Token::RBrace) && !self.is_eof() {
3503                            let name = self.parse_ident()?;
3504                            self.expect(Token::Colon)?;
3505                            let ty = self.parse_type()?;
3506                            fields.push(FieldDef {
3507                                visibility: Visibility::Private,
3508                                name,
3509                                ty,
3510                                default: None,
3511                            });
3512                            if !self.consume_if(&Token::Comma) {
3513                                break;
3514                            }
3515                        }
3516                        self.expect(Token::RBrace)?;
3517                        StructFields::Named(fields)
3518                    } else {
3519                        StructFields::Unit
3520                    };
3521                    // Parse optional discriminant: N = -1
3522                    let discriminant = if self.consume_if(&Token::Eq) {
3523                        Some(self.parse_expr()?)
3524                    } else {
3525                        None
3526                    };
3527                    variants.push(EnumVariant {
3528                        name,
3529                        fields,
3530                        discriminant,
3531                    });
3532                    if !self.consume_if(&Token::Comma) {
3533                        break;
3534                    }
3535                }
3536                self.expect(Token::RBrace)?;
3537                Ok(TypeExpr::InlineEnum { variants })
3538            }
3539            // Handle crate::, self::, super:: path prefixes in types
3540            Some(Token::Crate) | Some(Token::SelfLower) | Some(Token::Super) => {
3541                let keyword = self.current_token().cloned();
3542                let span = self.current_span();
3543                self.advance();
3544
3545                // Build the first segment from the keyword
3546                // Note: Sigil uses "tome" instead of Rust's "crate"
3547                let keyword_name = match keyword {
3548                    Some(Token::Crate) => "tome",
3549                    Some(Token::SelfLower) => "self",
3550                    Some(Token::Super) => "super",
3551                    _ => unreachable!(),
3552                };
3553                let first_segment = PathSegment {
3554                    ident: Ident {
3555                        name: keyword_name.to_string(),
3556                        evidentiality: None,
3557                        affect: None,
3558                        span,
3559                    },
3560                    generics: None,
3561                };
3562
3563                let mut segments = vec![first_segment];
3564
3565                // Continue parsing path: crate::module::Type
3566                while self.consume_if(&Token::MiddleDot) || self.consume_if(&Token::MiddleDot) {
3567                    // Check for turbofish: crate::<T> (unlikely but possible)
3568                    if self.check(&Token::Lt) {
3569                        self.advance();
3570                        let types = self.parse_type_list()?;
3571                        self.expect_gt()?;
3572                        if let Some(last) = segments.last_mut() {
3573                            last.generics = Some(types);
3574                        }
3575                        continue;
3576                    }
3577                    segments.push(self.parse_path_segment()?);
3578                }
3579                Ok(TypeExpr::Path(TypePath { segments }))
3580            }
3581            _ => {
3582                let path = self.parse_type_path()?;
3583                Ok(TypeExpr::Path(path))
3584            }
3585        }
3586    }
3587
3588    fn parse_type_path(&mut self) -> ParseResult<TypePath> {
3589        let mut segments = Vec::new();
3590        segments.push(self.parse_path_segment()?);
3591
3592        // Don't continue parsing path if there's a pending `>` from split `>>`
3593        // This handles cases like `<T as Trait<U>>::Assoc` where `>>` is split
3594        // and the `::Assoc` belongs to the outer qualified path, not the trait path
3595        //
3596        // MiddleDot (·) handling:
3597        // - For type paths starting with uppercase (HashMap·new), allow · as separator
3598        // - For variable paths starting with lowercase (tag·to_string), DON'T consume ·
3599        //   because those are method calls handled by postfix expression parsing
3600        let first_segment_is_type = segments
3601            .first()
3602            .map(|s| s.ident.name.chars().next().map_or(false, |c| c.is_uppercase()))
3603            .unwrap_or(false);
3604
3605        while !self.pending_gt.is_some() {
3606            // Always allow :: as path separator
3607            // Only allow · for type paths (uppercase first letter)
3608            let is_path_sep = self.consume_if(&Token::MiddleDot)
3609                || (first_segment_is_type && self.consume_if(&Token::MiddleDot));
3610            if !is_path_sep {
3611                break;
3612            }
3613            // Check for turbofish syntax: path::<Type> instead of path::segment
3614            if self.check(&Token::Lt) {
3615                // Parse turbofish generics for the last segment
3616                // Temporarily exit condition context - turbofish is always type context
3617                let was_in_condition = self.in_condition;
3618                self.in_condition = false;
3619                self.advance(); // consume <
3620                let types = self.parse_type_list()?;
3621                self.expect_gt()?;
3622                self.in_condition = was_in_condition;
3623                // Update the last segment with these generics
3624                if let Some(last) = segments.last_mut() {
3625                    last.generics = Some(types);
3626                }
3627                // Continue parsing - there may be more segments after turbofish
3628                // e.g., Option::<T>::None or Vec::<T>::new()
3629                continue;
3630            }
3631            segments.push(self.parse_path_segment()?);
3632        }
3633
3634        Ok(TypePath { segments })
3635    }
3636
3637    fn parse_path_segment(&mut self) -> ParseResult<PathSegment> {
3638        // Handle both identifiers and numeric indices (for tuple field access like tuple·0)
3639        let ident = if let Some(Token::IntLit(idx)) = self.current_token().cloned() {
3640            let span = self.current_span();
3641            self.advance();
3642            Ident {
3643                name: idx,
3644                evidentiality: None,
3645                affect: None,
3646                span,
3647            }
3648        } else {
3649            self.parse_ident()?
3650        };
3651
3652        // Special case: Fn(T) -> R, FnMut(T) -> R, FnOnce(T) -> R trait syntax
3653        // These are function trait bounds with parenthesis-style generics
3654        let is_fn_trait = matches!(ident.name.as_str(), "Fn" | "FnMut" | "FnOnce");
3655        if is_fn_trait && self.check(&Token::LParen) {
3656            self.advance(); // consume (
3657            let param_types = self.parse_type_list()?;
3658            self.expect(Token::RParen)?;
3659            // Check for optional return type: -> R
3660            let return_type = if self.consume_if(&Token::Arrow) {
3661                Some(self.parse_type()?)
3662            } else {
3663                None
3664            };
3665            // Build a tuple type for params and optional return as generics
3666            // Fn(A, B) -> R becomes Fn<(A, B), R>
3667            let mut generics = vec![TypeExpr::Tuple(param_types)];
3668            if let Some(ret) = return_type {
3669                generics.push(ret);
3670            }
3671            return Ok(PathSegment {
3672                ident,
3673                generics: Some(generics),
3674            });
3675        }
3676
3677        // Don't parse generics in condition context (< is comparison, not generics)
3678        // Also check that what follows < looks like a type, not an expression like `self`
3679        // Support both <T> and [T] syntax for type generics (Sigil alternative syntax)
3680        let generics = if !self.is_in_condition()
3681            && self.check(&Token::Lt)
3682            && self.peek_looks_like_generic_arg()
3683        {
3684            self.advance(); // consume <
3685            let types = self.parse_type_list()?;
3686            // Use expect_gt() to handle nested generics with `>>`
3687            self.expect_gt()?;
3688            Some(types)
3689        } else if self.check(&Token::LBracket) && self.peek_looks_like_bracket_generic() {
3690            // Alternative syntax: Type[T] instead of Type<T>
3691            self.advance(); // consume [
3692            let types = self.parse_type_list()?;
3693            self.expect(Token::RBracket)?;
3694            Some(types)
3695        } else {
3696            None
3697        };
3698
3699        Ok(PathSegment { ident, generics })
3700    }
3701
3702    /// Check if [...] after identifier looks like a generic type argument rather than an array
3703    fn peek_looks_like_bracket_generic(&mut self) -> bool {
3704        // Peek after [ to check if it looks like a type parameter
3705        // Be conservative - index expressions like `array[pos + 2..]` should not be treated as generics
3706        match self.peek_next().cloned() {
3707            // For identifiers, use 2-token lookahead to see if it's a type or expression
3708            Some(Token::Ident(name)) => {
3709                // Check what follows the identifier
3710                // Only treat as generic if the identifier looks like a type name (uppercase)
3711                // or is a primitive type (bool, i32, f64, etc.)
3712                let is_type_name = name.chars().next().map_or(false, |c| c.is_uppercase())
3713                    || Self::is_primitive_type(&name);
3714                match self.peek_n(1) {
3715                    // [T] - only treat as generic if T looks like a type name (uppercase)
3716                    // This distinguishes HashMap[String] (generic) from array[index] (indexing)
3717                    Some(Token::RBracket) => is_type_name,
3718                    Some(Token::Comma) => is_type_name,      // [T, U] - but not [a, b] which is array
3719                    Some(Token::MiddleDot) => true, // [T::U]
3720                    Some(Token::Lt) => is_type_name,         // [T<U>]
3721                    Some(Token::LBracket) => is_type_name,   // [T[U]] but not [a[b]] (nested index)
3722                    // Evidentiality markers: [T!], [T?], [T~], [T◊], [T‽]
3723                    Some(Token::Question) => true,
3724                    Some(Token::Bang) => true,
3725                    Some(Token::Tilde) => true,
3726                    Some(Token::Lozenge) => true,
3727                    Some(Token::Interrobang) => true,
3728                    // Associated type binding: [Output = Type]
3729                    Some(Token::Eq) => true,
3730                    // Expression operators indicate index expression, not generics
3731                    Some(Token::Plus) => false,      // [pos + 2]
3732                    Some(Token::Minus) => false,     // [len - 1]
3733                    Some(Token::Star) => false,      // [i * 2]
3734                    Some(Token::Slash) => false,     // [i / 2]
3735                    Some(Token::DotDot) => false,    // [pos..] range
3736                    Some(Token::DotDotEq) => false,  // [0..=n]
3737                    _ => false, // Default to not treating as generics
3738                }
3739            }
3740            Some(Token::SelfUpper) => true, // [Self]
3741            Some(Token::Amp) => true,       // [&T]
3742            // Don't treat [*expr] as generic - could be dereference in index
3743            Some(Token::Star) => false,
3744            Some(Token::Fn) => true,        // [fn(...)]
3745            Some(Token::LParen) => {
3746                // [()] could be tuple type generic or parenthesized expression index
3747                // Look inside the parens to decide:
3748                // - [()] empty tuple - likely type
3749                // - [(T, U)] uppercase identifiers - likely type
3750                // - [(expr)] lowercase identifier or expression - likely index
3751                match self.peek_n(1) {
3752                    Some(Token::RParen) => true,  // [()] empty tuple type
3753                    Some(Token::Ident(name)) => {
3754                        // If identifier starts uppercase, likely a type
3755                        // If lowercase followed by expression ops like 'as', it's an expression
3756                        if name.chars().next().map_or(false, |c| c.is_uppercase()) {
3757                            true  // [(Type...)]
3758                        } else {
3759                            // Check what follows the lowercase identifier
3760                            match self.peek_n(2) {
3761                                Some(Token::As) => false,    // [(n as T)] cast expression
3762                                Some(Token::Plus) => false,  // [(a + b)]
3763                                Some(Token::Minus) => false, // [(a - b)]
3764                                Some(Token::Star) => false,  // [(a * b)]
3765                                Some(Token::Slash) => false, // [(a / b)]
3766                                Some(Token::Dot) => false,   // [(a.b)]
3767                                Some(Token::LBracket) => false, // [(a[i])]
3768                                Some(Token::LParen) => false, // [(f())]
3769                                Some(Token::RParen) => false, // [(x)] single lowercase var - expression
3770                                Some(Token::Comma) => true,   // [(a, b)] could be tuple type, try it
3771                                _ => false  // Default to expression (index)
3772                            }
3773                        }
3774                    }
3775                    _ => false  // Default to not treating as generics
3776                }
3777            }
3778            Some(Token::Dyn) => true,       // [dyn Trait]
3779            Some(Token::Impl) => true,      // [impl Trait]
3780            Some(Token::Underscore) => true, // [_] inferred type
3781            // Path-starting keywords that indicate type paths
3782            Some(Token::Crate) => true,     // [crate::Type]
3783            Some(Token::Super) => true,     // [super::Type]
3784            // Literals indicate expressions, not types
3785            Some(Token::IntLit(_)) => false,
3786            Some(Token::FloatLit(_)) => false,
3787            Some(Token::SelfLower) => false, // [self.x] - expression
3788            // Could be array: [expr; size] or [type; size]
3789            // If it's for generics, there won't be a semicolon
3790            _ => false,
3791        }
3792    }
3793
3794    /// Check if a name is a primitive type (lowercase but still a type)
3795    fn is_primitive_type(name: &str) -> bool {
3796        matches!(
3797            name,
3798            "bool" | "char" | "str"
3799                | "i8" | "i16" | "i32" | "i64" | "i128" | "isize"
3800                | "u8" | "u16" | "u32" | "u64" | "u128" | "usize"
3801                | "f32" | "f64"
3802        )
3803    }
3804
3805    /// Check if what follows < looks like it could be a generic type argument
3806    /// This helps disambiguate `foo<T>` (generics) from `foo < bar` (comparison)
3807    /// We are conservative: only treat as generics if it's clearly a type context
3808    /// Note: When called, self.current is at the < token
3809    fn peek_looks_like_generic_arg(&mut self) -> bool {
3810        // Use peek_next (peek_n(0)) to see what's after <
3811        match self.peek_next().cloned() {
3812            // Clear type starts that don't look like expressions
3813            Some(Token::Amp) => true,   // &T - references are type-like
3814            Some(Token::Star) => {
3815                // *const T or *mut T - pointer types
3816                // *expr - dereference (not a type)
3817                // Look at what follows * to distinguish
3818                match self.peek_n(1) {
3819                    Some(Token::Const) => true,  // *const T - pointer type
3820                    Some(Token::Mut) => true,    // *mut T - pointer type
3821                    _ => false,  // *expr - dereference, not a type
3822                }
3823            }
3824            Some(Token::LBracket) => true, // [T] - slices
3825            Some(Token::LParen) => true, // () - tuple types including unit
3826            Some(Token::Fn) => true,    // fn() - function types
3827            Some(Token::Simd) => true,  // simd<T, N>
3828            Some(Token::Atomic) => true, // atomic<T>
3829            Some(Token::Dyn) => true,   // dyn Trait - trait objects
3830            Some(Token::Impl) => true,  // impl Trait - existential types
3831            Some(Token::SelfUpper) => true, // Self is a type
3832            Some(Token::Crate) => true,     // crate::Type - path starting with crate
3833            Some(Token::Super) => true,     // super::Type - path starting with super
3834            Some(Token::Lifetime(_)) => true, // 'a, 'static - lifetime type args
3835            Some(Token::Underscore) => true, // _ - inferred type
3836            // Evidentiality prefixes on types: !T, ?T, ~T
3837            Some(Token::Bang) => true,
3838            Some(Token::Question) => true,
3839            Some(Token::Tilde) => true,
3840            Some(Token::Interrobang) => true,
3841            // Path-rooted types: crate::Type, super::Type
3842            Some(Token::Crate) => true,
3843            Some(Token::Super) => true,
3844            // For identifiers, we need 2-token lookahead to see what follows
3845            Some(Token::Ident(name)) => {
3846                // peek_n(1) looks at the token after the identifier
3847                // (peek_n(0) = token after <, peek_n(1) = token after that)
3848                let is_type_like = name.chars().next().map_or(false, |c| c.is_uppercase())
3849                    || matches!(name.as_str(),
3850                        // Primitive types are lowercase but are type names
3851                        "u8" | "u16" | "u32" | "u64" | "u128" | "usize"
3852                        | "i8" | "i16" | "i32" | "i64" | "i128" | "isize"
3853                        | "f32" | "f64" | "bool" | "char" | "str"
3854                    );
3855                match self.peek_n(1) {
3856                    // Only treat as generic if clearly followed by generic-context tokens
3857                    Some(Token::Gt) => true,
3858                    Some(Token::Shr) => true,  // >> which may close nested generics
3859                    // For comma: only treat as generic if identifier looks like a type name
3860                    // This distinguishes `HashMap<K, V>` (generic) from `x < y,` (comparison in match)
3861                    Some(Token::Comma) => is_type_like,
3862                    Some(Token::MiddleDot) => true,  // T::U path
3863                    Some(Token::Lt) => true,   // T<U> nested generic
3864                    Some(Token::LBracket) => true, // T[U] bracket generic
3865                    // Evidentiality markers after type name: T?, T!, T~, T◊, T‽
3866                    Some(Token::Question) => true,
3867                    Some(Token::Bang) => true,
3868                    Some(Token::Tilde) => true,
3869                    Some(Token::Lozenge) => true,
3870                    Some(Token::Interrobang) => true,
3871                    // Associated type bindings: <Item = Type>
3872                    Some(Token::Eq) => true,
3873                    // Trait bounds: <T: Trait>
3874                    Some(Token::Colon) => true,
3875                    _ => false,
3876                }
3877            }
3878            // NOT a type - likely comparison with expression
3879            Some(Token::SelfLower) => false, // self is an expression
3880            // Integer literals in generics: const generic values like Type<50257, 1024>
3881            // Only treat as generic if followed by comma or closing >
3882            Some(Token::IntLit(_)) => {
3883                match self.peek_n(1) {
3884                    Some(Token::Comma) => true, // <50257, 1024, ...>
3885                    Some(Token::Gt) => true,    // <50257>
3886                    Some(Token::Shr) => true,   // <50257>> nested
3887                    _ => false, // <5 + x> - comparison
3888                }
3889            }
3890            Some(Token::FloatLit(_)) => false,
3891            Some(Token::StringLit(_)) => false,
3892            Some(Token::True) | Some(Token::False) => false,
3893            Some(Token::Null) => false,
3894            _ => false, // Default to not parsing as generics if uncertain
3895        }
3896    }
3897
3898    /// Check if the token after | looks like a pipe operation
3899    /// This distinguishes `expr|τ{...}` (pipe) from `a | b` (bitwise OR)
3900    fn peek_looks_like_pipe_op(&mut self) -> bool {
3901        match self.peek_next() {
3902            // Greek letters for morpheme operations
3903            Some(Token::Tau) => true,      // |τ{...} transform
3904            Some(Token::Phi) => true,      // |φ{...} filter
3905            Some(Token::Sigma) => true,    // |σ sort
3906            Some(Token::Struct) => true,   // |Σ (uppercase sigma tokenized as Struct) - neural sum
3907            Some(Token::Rho) => true,      // |ρ+ reduce
3908            Some(Token::Pi) => true,       // |Π product
3909            Some(Token::Alpha) => true,    // |α first
3910            Some(Token::Omega) => true,    // |ω last
3911            Some(Token::Mu) => true,       // |μ middle
3912            Some(Token::Chi) => true,      // |χ choice
3913            Some(Token::Nu) => true,       // |ν nth
3914            Some(Token::Xi) => true,       // |ξ slice
3915            Some(Token::Delta) => true,    // |δ diff
3916            Some(Token::Iota) => true,     // |⍳ enumerate
3917            Some(Token::ForAll) => true,   // |∀ forall
3918            Some(Token::Exists) => true,   // |∃ exists
3919            Some(Token::Compose) => true,  // |∘ compose
3920            Some(Token::Bowtie) => true,   // |⋈ zip/join
3921            Some(Token::Integral) => true, // |∫ scan
3922            Some(Token::Partial) => true,  // |∂ diff
3923            Some(Token::Nabla) => true,    // |∇ gradient
3924            Some(Token::GradeUp) => true,  // |⍋ sort ascending
3925            Some(Token::GradeDown) => true, // |⍒ sort descending
3926            Some(Token::Rotate) => true,   // |⌽ reverse
3927            Some(Token::CycleArrow) => true, // |↻ cycle
3928            Some(Token::QuadDiamond) => true, // |⌺ windows
3929            Some(Token::SquaredPlus) => true, // |⊞ chunks
3930            Some(Token::ElementSmallVerticalBar) => true, // |⋳ flatten
3931            Some(Token::Union) => true,    // |∪ unique
3932            // Holographic operators
3933            Some(Token::Lozenge) => true,  // |◊method possibility
3934            Some(Token::BoxSquare) => true,  // |□method necessity/verification
3935            // Keywords for pipe operations
3936            Some(Token::Match) => true,    // |match{...}
3937            Some(Token::Send) => true,     // |send{...}
3938            Some(Token::Recv) => true,     // |recv
3939            Some(Token::Stream) => true,   // |stream{...}
3940            // Protocol tokens
3941            Some(Token::ProtoSend) => true,   // |⇒{...}
3942            Some(Token::ProtoRecv) => true,   // |⇐
3943            Some(Token::ProtoStream) => true, // |≋{...}
3944            Some(Token::Connect) => true,     // |connect
3945            Some(Token::ProtoConnect) => true, // |⊸
3946            Some(Token::Close) => true,       // |close
3947            Some(Token::Timeout) => true,     // |timeout{...}
3948            Some(Token::ProtoTimeout) => true, // |⏱{...}
3949            Some(Token::Retry) => true,       // |retry{...}
3950            // Other pipe operation keywords
3951            Some(Token::Header) => true,   // |header{...}
3952            Some(Token::Body) => true,     // |body{...}
3953            Some(Token::Interrobang) => true, // |‽
3954            // Identifier could be pipe method: |collect, |take, etc.
3955            // But identifiers NOT followed by `(` or `{` are likely bitwise OR operands
3956            Some(Token::Ident(name)) => {
3957                // Known pipe methods that don't require parentheses
3958                // Collection operations that don't require parentheses
3959                let collection_pipe_methods = ["observe", "collect", "sum", "product", "len",
3960                                               "min", "max", "first", "last", "head", "tail",
3961                                               "reverse", "flatten", "enumerate", "encode",
3962                                               // Quantum-holographic methods
3963                                               "error_correct", "quantum_reconstruct", "interfere",
3964                                               "partial_trace", "qh_compress", "is_pure",
3965                                               "apply_noise", "scatter", "teleport", "size",
3966                                               // Neural/Tensor methods
3967                                               "relu", "softmax", "sigmoid", "tanh", "backward", "Σ"];
3968                if collection_pipe_methods.contains(&name.as_str())
3969                    || QUANTUM_GATES.contains(&name.as_str())
3970                    || QUANTUM_OPS.contains(&name.as_str()) {
3971                    return true;
3972                }
3973
3974                // Only treat as pipe method if followed by explicit call syntax
3975                // peek_next() gave us the Ident, peek_n(1) gives us the token after it
3976                // Also handle evidentiality markers: |validate!{...} where ! precedes {
3977                let after_ident = self.peek_n(1);
3978                match after_ident {
3979                    Some(Token::LParen) | Some(Token::LBrace) => true,
3980                    // Evidentiality markers followed by call syntax
3981                    Some(Token::Bang) | Some(Token::Question) | Some(Token::Tilde) | Some(Token::Lozenge) => {
3982                        matches!(self.peek_n(2), Some(Token::LParen) | Some(Token::LBrace))
3983                    }
3984                    _ => false,
3985                }
3986            }
3987            // Reference expression: |&self.field for piping to borrows
3988            Some(Token::Amp) => true,
3989            // Direct closure: |{x => body}
3990            Some(Token::LBrace) => true,
3991            // Keyword tokens that are pipe methods
3992            Some(Token::Interfere) => true,  // |interfere is a pipe method
3993            // Await/Async for async pipe chains
3994            Some(Token::Await) => true,      // |await resolves futures
3995            Some(Token::Async) => true,      // |async (alternative syntax)
3996            // Everything else is likely bitwise OR
3997            _ => false,
3998        }
3999    }
4000
4001    fn parse_type_list(&mut self) -> ParseResult<Vec<TypeExpr>> {
4002        let mut types = Vec::new();
4003        // Check for empty list - also check Shr (>>) for nested generics
4004        if !self.check(&Token::RParen)
4005            && !self.check(&Token::RBracket)
4006            && !self.check(&Token::Gt)
4007            && !self.check(&Token::Shr)
4008            && self.pending_gt.is_none()
4009        {
4010            // Use parse_type_or_lifetime to handle generic args like <'a, T>
4011            types.push(self.parse_type_or_lifetime()?);
4012            // Continue parsing more types while we see commas
4013            // But check for pending_gt BEFORE consuming comma to avoid eating param separators
4014            while !self.pending_gt.is_some()
4015                && !self.check(&Token::Gt)
4016                && !self.check(&Token::Shr)
4017                && self.consume_if(&Token::Comma)
4018            {
4019                // Trailing comma check
4020                if self.check(&Token::RParen)
4021                    || self.check(&Token::RBracket)
4022                    || self.check(&Token::Gt)
4023                    || self.check(&Token::Shr)
4024                {
4025                    break;
4026                }
4027                types.push(self.parse_type_or_lifetime()?);
4028            }
4029        }
4030        Ok(types)
4031    }
4032
4033    /// Parse a type list that may have attributes before each type
4034    /// e.g., `(#[from] Error, #[source] io::Error)`
4035    fn parse_attributed_type_list(&mut self) -> ParseResult<Vec<TypeExpr>> {
4036        let mut types = Vec::new();
4037        if !self.check(&Token::RParen) {
4038            loop {
4039                // Skip any attributes before the type
4040                while self.check(&Token::Hash) {
4041                    self.advance();
4042                    self.consume_if(&Token::Bang); // for #![...]
4043                    if self.consume_if(&Token::LBracket) {
4044                        let mut depth = 1;
4045                        while depth > 0 && !self.is_eof() {
4046                            match self.current_token() {
4047                                Some(Token::LBracket) => depth += 1,
4048                                Some(Token::RBracket) => depth -= 1,
4049                                _ => {}
4050                            }
4051                            self.advance();
4052                        }
4053                    }
4054                }
4055                // Parse the type
4056                types.push(self.parse_type()?);
4057                if !self.consume_if(&Token::Comma) {
4058                    break;
4059                }
4060            }
4061        }
4062        Ok(types)
4063    }
4064
4065    /// Parse tuple struct fields, which may have optional `pub` visibility before each type
4066    /// e.g., `struct Foo(pub String, i32)` or `struct Bar(pub(crate) Type)`
4067    fn parse_tuple_struct_fields(&mut self) -> ParseResult<Vec<TypeExpr>> {
4068        let mut types = Vec::new();
4069        if !self.check(&Token::RParen) {
4070            loop {
4071                // Skip optional visibility modifier (pub, pub(crate), pub(super), etc.)
4072                if self.check(&Token::Pub) {
4073                    self.advance();
4074                    // Handle pub(crate), pub(super), pub(self), pub(in path)
4075                    if self.check(&Token::LParen) {
4076                        self.advance();
4077                        // Skip tokens until matching RParen
4078                        let mut depth = 1;
4079                        while depth > 0 {
4080                            match self.current_token() {
4081                                Some(Token::LParen) => depth += 1,
4082                                Some(Token::RParen) => depth -= 1,
4083                                None => break,
4084                                _ => {}
4085                            }
4086                            self.advance();
4087                        }
4088                    }
4089                }
4090                // Parse the type
4091                types.push(self.parse_type()?);
4092                if !self.consume_if(&Token::Comma) {
4093                    break;
4094                }
4095                // Check for trailing comma
4096                if self.check(&Token::RParen) {
4097                    break;
4098                }
4099            }
4100        }
4101        Ok(types)
4102    }
4103
4104    fn parse_type_bounds(&mut self) -> ParseResult<Vec<TypeExpr>> {
4105        let mut bounds = Vec::new();
4106
4107        // Handle empty bounds: `T: ,` or `[(); K]: ,` (just checking type is well-formed)
4108        if self.check(&Token::Comma) || self.check(&Token::LBrace) || self.check(&Token::Semi) {
4109            return Ok(bounds);
4110        }
4111
4112        bounds.push(self.parse_type_or_lifetime()?);
4113        while self.consume_if(&Token::Plus) {
4114            bounds.push(self.parse_type_or_lifetime()?);
4115        }
4116        Ok(bounds)
4117    }
4118
4119    /// Parse either a type or a lifetime (for trait bounds like `T: Trait + 'static`)
4120    /// Also handles HRTB: `for<'de> Deserialize<'de>`
4121    /// Also handles associated type bindings: `Output = Type`
4122    fn parse_type_or_lifetime(&mut self) -> ParseResult<TypeExpr> {
4123        if let Some(Token::Lifetime(name)) = self.current_token().cloned() {
4124            self.advance();
4125            Ok(TypeExpr::Lifetime(name))
4126        } else if self.check(&Token::ForAll) {
4127            // Higher-ranked trait bound: for<'a, 'b> Trait<'a, 'b>
4128            self.advance(); // consume 'for'
4129            self.expect(Token::Lt)?; // <
4130            let mut lifetimes = Vec::new();
4131            if let Some(Token::Lifetime(lt)) = self.current_token().cloned() {
4132                lifetimes.push(lt);
4133                self.advance();
4134                while self.consume_if(&Token::Comma) {
4135                    if let Some(Token::Lifetime(lt)) = self.current_token().cloned() {
4136                        lifetimes.push(lt);
4137                        self.advance();
4138                    } else {
4139                        break;
4140                    }
4141                }
4142            }
4143            self.expect_gt()?; // >
4144            let bound = self.parse_type()?;
4145            Ok(TypeExpr::Hrtb {
4146                lifetimes,
4147                bound: Box::new(bound),
4148            })
4149        } else if matches!(self.current_token(), Some(Token::Ident(_)))
4150            && self.peek_next() == Some(&Token::Eq)
4151        {
4152            // Associated type binding: `Output = Type`
4153            let name = self.parse_ident()?;
4154            self.expect(Token::Eq)?;
4155            let ty = self.parse_type()?;
4156            Ok(TypeExpr::AssocTypeBinding {
4157                name,
4158                ty: Box::new(ty),
4159            })
4160        } else if matches!(
4161            self.current_token(),
4162            Some(Token::IntLit(_))
4163                | Some(Token::HexLit(_))
4164                | Some(Token::BinaryLit(_))
4165                | Some(Token::OctalLit(_))
4166        ) {
4167            // Const generic: numeric literal or expression in type position like `<32>` or `<3 * D>`
4168            // Parse as expression to handle `3 * D`, `N + 1`, etc.
4169            let expr = self.parse_const_expr_simple()?;
4170            Ok(TypeExpr::ConstExpr(Box::new(expr)))
4171        } else if self.check(&Token::LBrace) {
4172            // Const block expression: `<{N + 1}>`
4173            self.advance();
4174            let expr = self.parse_expr()?;
4175            self.expect(Token::RBrace)?;
4176            Ok(TypeExpr::ConstExpr(Box::new(expr)))
4177        } else {
4178            self.parse_type()
4179        }
4180    }
4181
4182    /// Parse an array dimension expression like `HD/2`, `N*2`, `MAX_SEQ`, or `{ const { if ... } }`
4183    /// Used for tensor shape dimensions: [A, B, HD/2]
4184    fn parse_array_dim_expr(&mut self) -> ParseResult<Expr> {
4185        // Handle const block: { const { ... } } or just { expr }
4186        if self.check(&Token::LBrace) {
4187            self.advance();
4188            let expr = self.parse_expr()?;
4189            self.expect(Token::RBrace)?;
4190            return Ok(expr);
4191        }
4192        // Parse as const expression (identifier or literal followed by optional arithmetic)
4193        self.parse_const_expr_simple()
4194    }
4195
4196    /// Parse a simple const expression for use in type positions like `[3 * D, D]`
4197    /// Handles simple arithmetic: literals, identifiers, and +-*/ operations
4198    /// Stops at: comma, >, ], ), ;
4199    fn parse_const_expr_simple(&mut self) -> ParseResult<Expr> {
4200        let mut lhs = self.parse_const_expr_primary()?;
4201
4202        loop {
4203            match self.current_token() {
4204                Some(Token::Star) => {
4205                    self.advance();
4206                    let rhs = self.parse_const_expr_primary()?;
4207                    lhs = Expr::Binary {
4208                        op: BinOp::Mul,
4209                        left: Box::new(lhs),
4210                        right: Box::new(rhs),
4211                    };
4212                }
4213                Some(Token::Plus) => {
4214                    self.advance();
4215                    let rhs = self.parse_const_expr_primary()?;
4216                    lhs = Expr::Binary {
4217                        op: BinOp::Add,
4218                        left: Box::new(lhs),
4219                        right: Box::new(rhs),
4220                    };
4221                }
4222                Some(Token::Minus) => {
4223                    self.advance();
4224                    let rhs = self.parse_const_expr_primary()?;
4225                    lhs = Expr::Binary {
4226                        op: BinOp::Sub,
4227                        left: Box::new(lhs),
4228                        right: Box::new(rhs),
4229                    };
4230                }
4231                Some(Token::Slash) => {
4232                    self.advance();
4233                    let rhs = self.parse_const_expr_primary()?;
4234                    lhs = Expr::Binary {
4235                        op: BinOp::Div,
4236                        left: Box::new(lhs),
4237                        right: Box::new(rhs),
4238                    };
4239                }
4240                _ => break,
4241            }
4242        }
4243        Ok(lhs)
4244    }
4245
4246    /// Parse a primary element for const expressions
4247    fn parse_const_expr_primary(&mut self) -> ParseResult<Expr> {
4248        match self.current_token().cloned() {
4249            Some(Token::IntLit(_)) | Some(Token::HexLit(_))
4250            | Some(Token::BinaryLit(_)) | Some(Token::OctalLit(_)) => {
4251                let lit = self.parse_literal()?;
4252                Ok(Expr::Literal(lit))
4253            }
4254            Some(Token::Ident(_)) => {
4255                let path = self.parse_type_path()?;
4256                Ok(Expr::Path(path))
4257            }
4258            Some(Token::Underscore) => {
4259                // Inferred dimension: [_, N] means first dimension is inferred
4260                let span = self.current_span();
4261                self.advance();
4262                Ok(Expr::Path(TypePath {
4263                    segments: vec![PathSegment {
4264                        ident: Ident {
4265                            name: "_".to_string(),
4266                            evidentiality: None,
4267                            affect: None,
4268                            span,
4269                        },
4270                        generics: None,
4271                    }],
4272                }))
4273            }
4274            Some(Token::LParen) => {
4275                self.advance();
4276                let expr = self.parse_const_expr_simple()?;
4277                self.expect(Token::RParen)?;
4278                Ok(expr)
4279            }
4280            _ => Err(ParseError::Custom("expected const expression".to_string())),
4281        }
4282    }
4283
4284    // === Expression parsing (Pratt parser) ===
4285
4286    pub fn parse_expr(&mut self) -> ParseResult<Expr> {
4287        // Skip leading comments (line comments, doc comments)
4288        self.skip_comments();
4289        let lhs = self.parse_expr_bp(0)?;
4290
4291        // Check for assignment: expr = value
4292        if self.consume_if(&Token::Eq) {
4293            let value = self.parse_expr()?;
4294            return Ok(Expr::Assign {
4295                target: Box::new(lhs),
4296                value: Box::new(value),
4297            });
4298        }
4299
4300        // Check for compound assignment: expr += value, expr -= value, etc.
4301        // Desugar to: expr = expr op value
4302        let compound_op = match self.current_token() {
4303            Some(Token::PlusEq) => Some(BinOp::Add),
4304            Some(Token::MinusEq) => Some(BinOp::Sub),
4305            Some(Token::StarEq) => Some(BinOp::Mul),
4306            Some(Token::SlashEq) => Some(BinOp::Div),
4307            Some(Token::PercentEq) => Some(BinOp::Rem),
4308            Some(Token::ShlEq) => Some(BinOp::Shl),
4309            Some(Token::ShrEq) => Some(BinOp::Shr),
4310            Some(Token::PipeEq) => Some(BinOp::BitOr),
4311            Some(Token::AmpEq) => Some(BinOp::BitAnd),
4312            Some(Token::CaretEq) => Some(BinOp::BitXor),
4313            _ => None,
4314        };
4315
4316        if let Some(op) = compound_op {
4317            self.advance();
4318            let rhs = self.parse_expr()?;
4319            // Desugar: lhs op= rhs  ->  lhs = lhs op rhs
4320            let binary = Expr::Binary {
4321                left: Box::new(lhs.clone()),
4322                op,
4323                right: Box::new(rhs),
4324            };
4325            return Ok(Expr::Assign {
4326                target: Box::new(lhs),
4327                value: Box::new(binary),
4328            });
4329        }
4330
4331        // Check for Legion compound operators: ⊕=, ∂=, ⫰=
4332        match self.current_token() {
4333            Some(Token::DirectSumEq) => {
4334                // Superposition: field∿ ⊕= pattern
4335                self.advance();
4336                let pattern = self.parse_expr()?;
4337                return Ok(Expr::LegionSuperposition {
4338                    field: Box::new(lhs),
4339                    pattern: Box::new(pattern),
4340                });
4341            }
4342            Some(Token::PartialEq_) => {
4343                // Decay: field∿ ∂= rate
4344                self.advance();
4345                let rate = self.parse_expr()?;
4346                return Ok(Expr::LegionDecay {
4347                    field: Box::new(lhs),
4348                    rate: Box::new(rate),
4349                });
4350            }
4351            Some(Token::InterfereEq) => {
4352                // Interference assign (rare, but supported)
4353                self.advance();
4354                let query = self.parse_expr()?;
4355                return Ok(Expr::LegionInterference {
4356                    query: Box::new(query),
4357                    field: Box::new(lhs),
4358                });
4359            }
4360            _ => {}
4361        }
4362
4363        Ok(lhs)
4364    }
4365
4366    fn parse_expr_bp(&mut self, min_bp: u8) -> ParseResult<Expr> {
4367        let mut lhs = self.parse_prefix_expr()?;
4368
4369        loop {
4370            // Skip comments between binary operators - allows line-continuation style:
4371            // let x = foo()
4372            //     // comment
4373            //     && bar()
4374            self.skip_comments();
4375
4376            // Check for pipe operator - but only if followed by pipe operation token
4377            // Otherwise treat | as bitwise OR for Rust-style code
4378            if self.check(&Token::Pipe) && self.peek_looks_like_pipe_op() {
4379                lhs = self.parse_pipe_chain(lhs)?;
4380                // After pipe chain, check for postfix operators like ? and method calls
4381                lhs = self.parse_postfix_after_pipe(lhs)?;
4382                continue;
4383            }
4384
4385            // Check for binary operators
4386            let op = match self.current_token() {
4387                // Bitwise OR - only reached if not a pipe operation
4388                Some(Token::Pipe) => BinOp::BitOr,
4389                Some(Token::OrOr) => BinOp::Or,
4390                Some(Token::AndAnd) => BinOp::And,
4391                Some(Token::EqEq) => BinOp::Eq,
4392                Some(Token::NotEq) => BinOp::Ne,
4393                Some(Token::Lt) => BinOp::Lt,
4394                Some(Token::LtEq) => BinOp::Le,
4395                Some(Token::Gt) => BinOp::Gt,
4396                Some(Token::GtEq) => BinOp::Ge,
4397                Some(Token::Plus) => BinOp::Add,
4398                Some(Token::Minus) => BinOp::Sub,
4399                Some(Token::Star) => BinOp::Mul,
4400                Some(Token::Slash) => BinOp::Div,
4401                Some(Token::Percent) => BinOp::Rem,
4402                Some(Token::StarStar) => BinOp::Pow,
4403                Some(Token::Amp) => BinOp::BitAnd,
4404                Some(Token::Caret) => BinOp::BitXor,
4405                Some(Token::Shl) => BinOp::Shl,
4406                Some(Token::Shr) => BinOp::Shr,
4407                Some(Token::PlusPlus) => BinOp::Concat,
4408                // Matrix multiplication
4409                Some(Token::At) => BinOp::MatMul,
4410                // Unicode bitwise operators
4411                Some(Token::BitwiseAndSymbol) => BinOp::BitAnd, // ⋏
4412                Some(Token::BitwiseOrSymbol) => BinOp::BitOr,   // ⋎
4413                // Logical/geometric algebra operators
4414                Some(Token::LogicAnd) => BinOp::And, // ∧ (wedge/outer product, parsed as And)
4415                Some(Token::LogicOr) => BinOp::Or,   // ∨ (vee/logical disjunction, parsed as Or)
4416                // Tensor/array operators
4417                Some(Token::CircledDot) => BinOp::Hadamard,     // ⊙ element-wise multiply
4418                Some(Token::Tensor) => BinOp::TensorProd,       // ⊗ tensor product
4419                Some(Token::Convolve) => BinOp::Convolve,       // ⊛ convolution/merge
4420                // Legion operators handled specially below
4421                Some(Token::Interfere) | Some(Token::Distribute) | Some(Token::Broadcast)
4422                | Some(Token::Gather) | Some(Token::Consensus) | Some(Token::ConfidenceHigh) => {
4423                    // Handle Legion operators specially
4424                    lhs = self.parse_legion_operator(lhs)?;
4425                    continue;
4426                }
4427                _ => {
4428                    // Check for range operators: .. and ..=
4429                    // Range has very low precedence (lower than all binary ops)
4430                    // Only parse range if min_bp is low enough (i.e., we're not inside
4431                    // a higher-precedence expression like i+1..)
4432                    // Range binding power is 0 - lower than any binary operator
4433                    if min_bp == 0 && (self.check(&Token::DotDot) || self.check(&Token::DotDotEq)) {
4434                        let inclusive = self.consume_if(&Token::DotDotEq);
4435                        if !inclusive {
4436                            self.advance(); // consume ..
4437                        }
4438                        // Parse end of range (optional for open ranges like `0..`)
4439                        let end = if self.check(&Token::Semi)
4440                            || self.check(&Token::RBrace)
4441                            || self.check(&Token::Comma)
4442                            || self.check(&Token::RParen)
4443                            || self.check(&Token::RBracket)
4444                            || self.check(&Token::LBrace)
4445                        {
4446                            None
4447                        } else {
4448                            Some(Box::new(self.parse_expr_bp(0)?))
4449                        };
4450                        lhs = Expr::Range {
4451                            start: Some(Box::new(lhs)),
4452                            end,
4453                            inclusive,
4454                        };
4455                        continue;
4456                    }
4457                    break;
4458                }
4459            };
4460
4461            let (l_bp, r_bp) = infix_binding_power(op);
4462            if l_bp < min_bp {
4463                break;
4464            }
4465
4466            self.advance();
4467            // Skip comments before RHS - allows:
4468            // a ||  // comment
4469            //   b
4470            self.skip_comments();
4471            let rhs = self.parse_expr_bp(r_bp)?;
4472
4473            lhs = Expr::Binary {
4474                left: Box::new(lhs),
4475                op,
4476                right: Box::new(rhs),
4477            };
4478        }
4479
4480        Ok(lhs)
4481    }
4482
4483    fn parse_prefix_expr(&mut self) -> ParseResult<Expr> {
4484        match self.current_token() {
4485            Some(Token::Minus) => {
4486                self.advance();
4487                let expr = self.parse_prefix_expr()?;
4488                Ok(Expr::Unary {
4489                    op: UnaryOp::Neg,
4490                    expr: Box::new(expr),
4491                })
4492            }
4493            Some(Token::Bang) | Some(Token::LogicNot) => {
4494                self.advance();
4495                let expr = self.parse_prefix_expr()?;
4496                Ok(Expr::Unary {
4497                    op: UnaryOp::Not,
4498                    expr: Box::new(expr),
4499                })
4500            }
4501            Some(Token::Star) => {
4502                self.advance();
4503                let expr = self.parse_prefix_expr()?;
4504                Ok(Expr::Unary {
4505                    op: UnaryOp::Deref,
4506                    expr: Box::new(expr),
4507                })
4508            }
4509            // Double dereference: **expr
4510            Some(Token::StarStar) => {
4511                self.advance();
4512                let inner = self.parse_prefix_expr()?;
4513                // Desugar **x to *(*x)
4514                let first_deref = Expr::Unary {
4515                    op: UnaryOp::Deref,
4516                    expr: Box::new(inner),
4517                };
4518                Ok(Expr::Unary {
4519                    op: UnaryOp::Deref,
4520                    expr: Box::new(first_deref),
4521                })
4522            }
4523            Some(Token::Amp) => {
4524                self.advance();
4525                let op = if self.consume_if(&Token::Mut) {
4526                    UnaryOp::RefMut
4527                } else {
4528                    UnaryOp::Ref
4529                };
4530                let expr = self.parse_prefix_expr()?;
4531                Ok(Expr::Unary {
4532                    op,
4533                    expr: Box::new(expr),
4534                })
4535            }
4536            // Prefix evidentiality markers: ?expr, ~expr, ‽expr
4537            Some(Token::Question) => {
4538                self.advance();
4539                let expr = self.parse_prefix_expr()?;
4540                Ok(Expr::Evidential {
4541                    expr: Box::new(expr),
4542                    evidentiality: Evidentiality::Uncertain,
4543                })
4544            }
4545            Some(Token::Tilde) => {
4546                self.advance();
4547                let expr = self.parse_prefix_expr()?;
4548                Ok(Expr::Evidential {
4549                    expr: Box::new(expr),
4550                    evidentiality: Evidentiality::Reported,
4551                })
4552            }
4553            Some(Token::Interrobang) => {
4554                self.advance();
4555                let expr = self.parse_prefix_expr()?;
4556                Ok(Expr::Evidential {
4557                    expr: Box::new(expr),
4558                    evidentiality: Evidentiality::Paradox,
4559                })
4560            }
4561            // Move closure: move |params| body or move λ(params) { body }
4562            Some(Token::Move) => {
4563                self.advance();
4564                if self.check(&Token::LambdaExpr) {
4565                    self.parse_lambda_closure(true)
4566                } else {
4567                    self.parse_pipe_closure_with_move(true)
4568                }
4569            }
4570            // Lambda closure expression: λ(params) [→ RetType] { body }
4571            Some(Token::LambdaExpr) => self.parse_lambda_closure(false),
4572            // Pipe-style closure: |params| body or || body
4573            Some(Token::Pipe) | Some(Token::OrOr) => self.parse_pipe_closure_with_move(false),
4574            _ => self.parse_postfix_expr(),
4575        }
4576    }
4577
4578    /// Parse a pipe-style closure: |params| body or || body or move |params| body
4579    fn parse_pipe_closure_with_move(&mut self, is_move: bool) -> ParseResult<Expr> {
4580        let params = if self.consume_if(&Token::OrOr) {
4581            // || body - no parameters
4582            Vec::new()
4583        } else {
4584            // |params| body
4585            self.expect(Token::Pipe)?;
4586            let mut params = Vec::new();
4587            if !self.check(&Token::Pipe) {
4588                loop {
4589                    // Parse parameter pattern (possibly with type)
4590                    let pattern = self.parse_pattern()?;
4591                    let ty = if self.consume_if(&Token::Colon) {
4592                        Some(self.parse_type()?)
4593                    } else {
4594                        None
4595                    };
4596                    params.push(ClosureParam { pattern, ty });
4597                    if !self.consume_if(&Token::Comma) {
4598                        break;
4599                    }
4600                    if self.check(&Token::Pipe) {
4601                        break;
4602                    }
4603                }
4604            }
4605            self.expect(Token::Pipe)?;
4606            params
4607        };
4608
4609        // Optional return type annotation: |params| -> Type { body }
4610        let return_type = if self.consume_if(&Token::Arrow) {
4611            Some(self.parse_type()?)
4612        } else {
4613            None
4614        };
4615
4616        let body = self.parse_expr()?;
4617        Ok(Expr::Closure {
4618            params,
4619            return_type,
4620            body: Box::new(body),
4621            is_move,
4622        })
4623    }
4624
4625    /// Parse a lambda closure expression: λ(params) [→ RetType] { body }
4626    /// Produces the same Expr::Closure as pipe closures, so no interpreter changes needed.
4627    fn parse_lambda_closure(&mut self, is_move: bool) -> ParseResult<Expr> {
4628        self.expect(Token::LambdaExpr)?; // consume λ
4629
4630        // Parse parameter list: λ(params)
4631        self.expect(Token::LParen)?;
4632        let mut params = Vec::new();
4633        if !self.check(&Token::RParen) {
4634            loop {
4635                let pattern = self.parse_pattern()?;
4636                let ty = if self.consume_if(&Token::Colon) {
4637                    Some(self.parse_type()?)
4638                } else {
4639                    None
4640                };
4641                params.push(ClosureParam { pattern, ty });
4642                if !self.consume_if(&Token::Comma) {
4643                    break;
4644                }
4645                if self.check(&Token::RParen) {
4646                    break;
4647                }
4648            }
4649        }
4650        self.expect(Token::RParen)?;
4651
4652        // Optional return type: → RetType
4653        let return_type = if self.consume_if(&Token::Arrow) {
4654            Some(self.parse_type()?)
4655        } else {
4656            None
4657        };
4658
4659        // Body must be a block: { ... }
4660        let body = self.parse_block_or_closure()?;
4661
4662        Ok(Expr::Closure {
4663            params,
4664            return_type,
4665            body: Box::new(body),
4666            is_move,
4667        })
4668    }
4669
4670    /// Parse macro tokens: collects all tokens inside matching delimiters
4671    fn parse_macro_tokens(&mut self) -> ParseResult<String> {
4672        // Determine delimiter type
4673        let (open, close) = match self.current_token() {
4674            Some(Token::LParen) => (Token::LParen, Token::RParen),
4675            Some(Token::LBracket) => (Token::LBracket, Token::RBracket),
4676            Some(Token::LBrace) => (Token::LBrace, Token::RBrace),
4677            _ => {
4678                return Err(ParseError::Custom(
4679                    "expected '(', '[', or '{' for macro invocation".to_string(),
4680                ))
4681            }
4682        };
4683
4684        self.advance(); // consume opening delimiter
4685        let mut tokens = String::new();
4686        let mut depth = 1;
4687
4688        while depth > 0 && !self.is_eof() {
4689            if self.check(&open) {
4690                depth += 1;
4691            } else if self.check(&close) {
4692                depth -= 1;
4693                if depth == 0 {
4694                    break;
4695                }
4696            }
4697
4698            // Collect token text (approximate - this is a simplified approach)
4699            if let Some((token, span)) = &self.current {
4700                // Skip comment tokens inside macro invocations
4701                if matches!(token, Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_)) {
4702                    self.advance();
4703                    continue;
4704                }
4705                // Also skip doc comments inside macros
4706                if token.is_doc_comment() {
4707                    self.advance();
4708                    continue;
4709                }
4710                // Get the source slice for this token
4711                let token_str = match token {
4712                    Token::Ident(s) => s.clone(),
4713                    Token::IntLit(s) => s.clone(),
4714                    Token::FloatLit(s) => s.clone(),
4715                    Token::StringLit(s) => format!("\"{}\"", s.replace('\\', "\\\\").replace('"', "\\\"")),
4716                    Token::CharLit(c) => format!("'{}'", c),
4717                    Token::Comma => ",".to_string(),
4718                    Token::Colon => ":".to_string(),
4719                    Token::MiddleDot => "·".to_string(),
4720                    Token::Dot => ".".to_string(),
4721                    Token::DotDot => "..".to_string(),
4722                    Token::Semi => ";".to_string(),
4723                    Token::LParen => "(".to_string(),
4724                    Token::RParen => ")".to_string(),
4725                    Token::LBrace => "{".to_string(),
4726                    Token::RBrace => "}".to_string(),
4727                    Token::LBracket => "[".to_string(),
4728                    Token::RBracket => "]".to_string(),
4729                    Token::Lt => "<".to_string(),
4730                    Token::Gt => ">".to_string(),
4731                    Token::Eq => "=".to_string(),
4732                    Token::FatArrow => "=>".to_string(),
4733                    Token::Bang => "!".to_string(),
4734                    Token::Question => "?".to_string(),
4735                    Token::Amp => "&".to_string(),
4736                    Token::Pipe => "|".to_string(),
4737                    Token::Underscore => "_".to_string(),
4738                    Token::Plus => "+".to_string(),
4739                    Token::Minus => "-".to_string(),
4740                    Token::Star => "*".to_string(),
4741                    Token::Slash => "/".to_string(),
4742                    Token::Percent => "%".to_string(),
4743                    Token::EqEq => "==".to_string(),
4744                    Token::NotEq => "!=".to_string(),
4745                    Token::LtEq => "<=".to_string(),
4746                    Token::GtEq => ">=".to_string(),
4747                    Token::AndAnd => "&&".to_string(),
4748                    Token::OrOr => "||".to_string(),
4749                    Token::Arrow => "->".to_string(),
4750                    Token::Hash => "#".to_string(),
4751                    Token::At => "@".to_string(),
4752                    Token::Tilde => "~".to_string(),
4753                    // Keywords
4754                    Token::SelfLower => "self".to_string(),
4755                    Token::SelfUpper => "Self".to_string(),
4756                    Token::Let => "let".to_string(),
4757                    Token::Mut => "mut".to_string(),
4758                    Token::Fn => "fn".to_string(),
4759                    Token::If => "if".to_string(),
4760                    Token::Else => "else".to_string(),
4761                    Token::Match => "match".to_string(),
4762                    Token::ForAll => "for".to_string(),
4763                    Token::While => "while".to_string(),
4764                    Token::Loop => "loop".to_string(),
4765                    Token::Tensor => "break".to_string(),
4766                    Token::CycleArrow => "continue".to_string(),
4767                    Token::Return => "return".to_string(),
4768                    Token::Struct => "struct".to_string(),
4769                    Token::Enum => "enum".to_string(),
4770                    Token::Impl => "impl".to_string(),
4771                    Token::Trait => "trait".to_string(),
4772                    Token::Type => "type".to_string(),
4773                    Token::Pub => "pub".to_string(),
4774                    Token::Mod => "mod".to_string(),
4775                    Token::Use => "use".to_string(),
4776                    Token::As => "as".to_string(),
4777                    Token::ElementOf => "in".to_string(),
4778                    Token::True => "true".to_string(),
4779                    Token::False => "false".to_string(),
4780                    Token::Null => "null".to_string(),
4781                    Token::Const => "const".to_string(),
4782                    Token::Static => "static".to_string(),
4783                    Token::Async => "async".to_string(),
4784                    Token::Await => "await".to_string(),
4785                    Token::Move => "move".to_string(),
4786                    Token::Ref => "ref".to_string(),
4787                    Token::Where => "where".to_string(),
4788                    Token::Dyn => "dyn".to_string(),
4789                    Token::Super => "super".to_string(),
4790                    Token::Crate => "tome".to_string(),
4791                    // Sigil-specific tokens
4792                    Token::MiddleDot => "·".to_string(), // Method call operator
4793                    Token::Nabla => "∇".to_string(),     // Gradient/backprop operator
4794                    Token::Tau => "τ".to_string(),       // Morpheme closure marker
4795                    Token::Rho => "ρ".to_string(),       // Reduce morpheme
4796                    Token::Sigma => "σ".to_string(),     // Filter morpheme
4797                    Token::Delta => "δ".to_string(),     // Dual morpheme
4798                    Token::Lambda => "Λ".to_string(),    // Lambda morpheme (uppercase)
4799                    Token::LambdaExpr => "λ".to_string(), // Lambda closure expression
4800                    Token::Pi => "π".to_string(),        // Parallel morpheme
4801                    Token::Phi => "φ".to_string(),       // Phi combinator
4802                    Token::Zeta => "ζ".to_string(),      // Zeta combinator
4803                    Token::Mu => "μ".to_string(),        // Mu combinator
4804                    Token::Theta => "θ".to_string(),     // Theta notation
4805                    Token::Alpha => "α".to_string(),     // First element
4806                    Token::Omega => "ω".to_string(),     // End/terminal
4807                    Token::Epsilon => "ε".to_string(),   // Empty/null
4808                    Token::Chi => "χ".to_string(),       // Random/choice
4809                    Token::Nu => "ν".to_string(),        // Nth element
4810                    Token::Xi => "ξ".to_string(),        // Next in sequence
4811                    Token::Psi => "ψ".to_string(),       // Mental state
4812                    Token::Kappa => "κ".to_string(),     // Callback/continuation
4813                    Token::Iota => "ι".to_string(),      // Enumerate/index
4814                    Token::PlusPlus => "++".to_string(), // Concat
4815                    Token::PlusEq => "+=".to_string(),
4816                    Token::MinusEq => "-=".to_string(),
4817                    Token::StarEq => "*=".to_string(),
4818                    Token::SlashEq => "/=".to_string(),
4819                    Token::AndAnd => "&&".to_string(),   // Logical AND
4820                    Token::OrOr => "||".to_string(),     // Logical OR
4821                    Token::Caret => "^".to_string(),     // XOR
4822                    Token::CaretEq => "^=".to_string(),
4823                    Token::AmpEq => "&=".to_string(),
4824                    Token::PipeEq => "|=".to_string(),
4825                    Token::Shl => "<<".to_string(),      // Left shift
4826                    Token::Shr => ">>".to_string(),      // Right shift
4827                    Token::ShlEq => "<<=".to_string(),
4828                    Token::ShrEq => ">>=".to_string(),
4829                    Token::DotDotEq => "..=".to_string(), // Inclusive range
4830                    Token::Async => "⏳".to_string(), // Await symbol
4831                    Token::Parallel => "‖".to_string(),  // Parallel execution
4832                    Token::Compose => "∘".to_string(),   // Function composition
4833                    Token::ForAll => "∀".to_string(),    // Universal quantification
4834                    Token::Exists => "∃".to_string(),    // Existential quantification
4835                    Token::ElementOf => "∈".to_string(), // Membership test
4836                    Token::Union => "∪".to_string(),     // Set union
4837                    Token::Intersection => "∩".to_string(), // Set intersection
4838                    _ => {
4839                        // Try contextual keywords that can be used as identifiers
4840                        if let Some(ident) = Self::keyword_as_ident(token) {
4841                            ident.to_string()
4842                        } else {
4843                            format!("{:?}", token)
4844                        }
4845                    }
4846                };
4847                // Don't add space before . · :: ( [ { ) ] } , ;
4848                let suppress_space_before = matches!(token,
4849                    Token::Dot | Token::MiddleDot | Token::MiddleDot | Token::LParen | Token::LBracket |
4850                    Token::LBrace | Token::RParen | Token::RBracket | Token::RBrace |
4851                    Token::Comma | Token::Semi | Token::Question);
4852                if !tokens.is_empty() && !suppress_space_before && !tokens.ends_with('.') &&
4853                   !tokens.ends_with("::") && !tokens.ends_with('(') && !tokens.ends_with('[') &&
4854                   !tokens.ends_with('{') {
4855                    tokens.push(' ');
4856                }
4857                tokens.push_str(&token_str);
4858            }
4859            self.advance();
4860        }
4861
4862        self.expect(close)?;
4863        Ok(tokens)
4864    }
4865
4866    /// Check if an expression is a block-ending expression that should not be callable.
4867    /// Block expressions like if/while/match/loop/for return values but should not
4868    /// be directly called like functions.
4869    fn is_non_callable_expr(expr: &Expr) -> bool {
4870        matches!(
4871            expr,
4872            Expr::If { .. }
4873                | Expr::While { .. }
4874                | Expr::Match { .. }
4875                | Expr::Loop { .. }
4876                | Expr::For { .. }
4877                | Expr::Block(_)
4878                | Expr::Unsafe(_)
4879        )
4880    }
4881
4882    fn parse_postfix_expr(&mut self) -> ParseResult<Expr> {
4883        let mut expr = self.parse_primary_expr()?;
4884
4885        loop {
4886            // Skip comments between postfix operations - allows line-continuation:
4887            // foo()
4888            //     // comment
4889            //     .bar()
4890            self.skip_comments();
4891
4892            match self.current_token() {
4893                Some(Token::LParen) => {
4894                    // Don't treat block-ending expressions as callable
4895                    // This prevents parsing `if {...} (...)` as a call expression
4896                    if Self::is_non_callable_expr(&expr) {
4897                        break;
4898                    }
4899                    self.advance();
4900                    let args = self.parse_expr_list()?;
4901                    self.expect(Token::RParen)?;
4902                    expr = Expr::Call {
4903                        func: Box::new(expr),
4904                        args,
4905                    };
4906                }
4907                Some(Token::LBracket) => {
4908                    self.advance();
4909                    // Support multi-dimensional indexing: arr[.., 0] or arr[i, j, k]
4910                    let first = self.parse_expr()?;
4911                    if self.consume_if(&Token::Comma) {
4912                        // Multi-dimensional index: create tuple of indices
4913                        let mut indices = vec![first];
4914                        while !self.check(&Token::RBracket) && !self.is_eof() {
4915                            indices.push(self.parse_expr()?);
4916                            if !self.consume_if(&Token::Comma) {
4917                                break;
4918                            }
4919                        }
4920                        self.expect(Token::RBracket)?;
4921                        // Represent as index with a tuple expression
4922                        expr = Expr::Index {
4923                            expr: Box::new(expr),
4924                            index: Box::new(Expr::Tuple(indices)),
4925                        };
4926                    } else {
4927                        self.expect(Token::RBracket)?;
4928                        expr = Expr::Index {
4929                            expr: Box::new(expr),
4930                            index: Box::new(first),
4931                        };
4932                    }
4933                }
4934                Some(Token::Dot) => {
4935                    self.advance();
4936                    // Handle `.⌛` as await syntax (alternative to `expr⌛`)
4937                    if self.check(&Token::Async) {
4938                        self.advance();
4939                        let evidentiality = self.parse_evidentiality_opt();
4940                        expr = Expr::Await {
4941                            expr: Box::new(expr),
4942                            evidentiality,
4943                        };
4944                        continue;
4945                    }
4946                    // Handle both named fields (`.field`) and tuple indices (`.0`, `.1`)
4947                    let field = if let Some(Token::IntLit(idx)) = self.current_token() {
4948                        let idx = idx.clone();
4949                        let span = self.current_span();
4950                        self.advance();
4951                        Ident {
4952                            name: idx,
4953                            evidentiality: None,
4954                            affect: None,
4955                            span,
4956                        }
4957                    } else {
4958                        self.parse_ident()?
4959                    };
4960                    // Check for turbofish syntax: method::<Type>(args)
4961                    if self.check(&Token::MiddleDot) {
4962                        self.advance(); // consume ::
4963                        self.expect(Token::Lt)?;
4964                        // Temporarily exit condition context - turbofish is type context
4965                        let was_in_condition = self.in_condition;
4966                        self.in_condition = false;
4967                        let type_args = self.parse_type_list()?;
4968                        self.expect_gt()?;
4969                        self.in_condition = was_in_condition;
4970                        self.expect(Token::LParen)?;
4971                        let args = self.parse_expr_list()?;
4972                        self.expect(Token::RParen)?;
4973                        expr = Expr::MethodCall {
4974                            receiver: Box::new(expr),
4975                            method: field,
4976                            type_args: Some(type_args),
4977                            args,
4978                        };
4979                    } else if self.check(&Token::LParen) {
4980                        self.advance();
4981                        let args = self.parse_expr_list()?;
4982                        self.expect(Token::RParen)?;
4983                        expr = Expr::MethodCall {
4984                            receiver: Box::new(expr),
4985                            method: field,
4986                            type_args: None,
4987                            args,
4988                        };
4989                    } else {
4990                        // Consume optional unambiguous evidentiality markers after field: self.field◊, self.field~
4991                        // Note: don't consume ! or ? here as they have other meanings (! = not, ? = try)
4992                        while self.check(&Token::Tilde) || self.check(&Token::Lozenge) {
4993                            self.advance();
4994                        }
4995                        expr = Expr::Field {
4996                            expr: Box::new(expr),
4997                            field,
4998                        };
4999                    }
5000                }
5001                Some(Token::Question) => {
5002                    // Check if this is Type? { ... } struct literal with evidentiality
5003                    if self.peek_next() == Some(&Token::LBrace) && !self.is_in_condition() {
5004                        if let Expr::Path(ref path) = expr {
5005                            let path = path.clone();
5006                            self.advance(); // consume ?
5007                            self.advance(); // consume {
5008                            let (fields, rest) = self.parse_struct_fields()?;
5009                            self.expect(Token::RBrace)?;
5010                            expr = Expr::Struct { path, fields, rest };
5011                            continue;
5012                        }
5013                    }
5014                    // Evidentiality marker: expr? wraps value as uncertain
5015                    if let Some(ev) = self.parse_evidentiality_opt() {
5016                        expr = Expr::Evidential {
5017                            expr: Box::new(expr),
5018                            evidentiality: ev,
5019                        };
5020                    } else {
5021                        break;
5022                    }
5023                }
5024                // Cast expression: expr as Type  OR  expr → Type
5025                Some(Token::As) | Some(Token::Arrow) => {
5026                    self.advance();
5027                    let ty = self.parse_type()?;
5028                    expr = Expr::Cast {
5029                        expr: Box::new(expr),
5030                        ty,
5031                    };
5032                }
5033                Some(Token::Bang) => {
5034                    // Check for macro invocation: path!(...)  path![...]  path!{...}
5035                    if let Expr::Path(path) = &expr {
5036                        let peeked = self.peek_next();
5037                        // Peek at next token to see if it's a macro delimiter
5038                        // In condition context, don't treat !{ as macro — the { is the if-body block
5039                        let is_macro = match peeked {
5040                            Some(Token::LParen) | Some(Token::LBracket) => true,
5041                            Some(Token::LBrace) => !self.is_in_condition(),
5042                            _ => false,
5043                        };
5044                        if is_macro {
5045                            self.advance(); // consume !
5046                            let tokens = self.parse_macro_tokens()?;
5047                            expr = Expr::Macro {
5048                                path: path.clone(),
5049                                tokens,
5050                            };
5051                            continue;
5052                        }
5053                    }
5054                    // Not a macro, check for evidentiality
5055                    if let Some(ev) = self.parse_evidentiality_opt() {
5056                        expr = Expr::Evidential {
5057                            expr: Box::new(expr),
5058                            evidentiality: ev,
5059                        };
5060                    } else {
5061                        break;
5062                    }
5063                }
5064                Some(Token::Tilde) | Some(Token::Interrobang) | Some(Token::Lozenge) => {
5065                    if let Some(ev) = self.parse_evidentiality_opt() {
5066                        // After evidentiality marker, check for struct literal: Type~ { ... }
5067                        // The evidentiality attaches to the struct type
5068                        if self.check(&Token::LBrace) && !self.is_in_condition() {
5069                            if let Expr::Path(ref path) = expr {
5070                                let path = path.clone();
5071                                self.advance(); // consume {
5072                                let (fields, rest) = self.parse_struct_fields()?;
5073                                self.expect(Token::RBrace)?;
5074                                expr = Expr::Struct { path, fields, rest };
5075                                continue;
5076                            }
5077                        }
5078                        // Wrap in Evidential for non-struct cases
5079                        expr = Expr::Evidential {
5080                            expr: Box::new(expr),
5081                            evidentiality: ev,
5082                        };
5083                    } else {
5084                        break;
5085                    }
5086                }
5087                Some(Token::MiddleDot) => {
5088                    // Qualified path call: Type::method() or path!::method()
5089                    self.advance(); // consume ::
5090                    let method = self.parse_ident()?;
5091                    // Check for turbofish: Type::method::<T>()
5092                    let type_args = if self.check(&Token::MiddleDot) {
5093                        self.advance();
5094                        self.expect(Token::Lt)?;
5095                        let types = self.parse_type_list()?;
5096                        self.expect_gt()?;
5097                        Some(types)
5098                    } else {
5099                        None
5100                    };
5101                    if self.check(&Token::LParen) {
5102                        self.advance();
5103                        let args = self.parse_expr_list()?;
5104                        self.expect(Token::RParen)?;
5105                        // Treat as a static method call - desugar to path::method(args)
5106                        expr = Expr::MethodCall {
5107                            receiver: Box::new(expr),
5108                            method,
5109                            type_args,
5110                            args,
5111                        };
5112                    } else {
5113                        // Field access style: Type::CONST
5114                        expr = Expr::Field {
5115                            expr: Box::new(expr),
5116                            field: method,
5117                        };
5118                    }
5119                }
5120                Some(Token::Async) => {
5121                    self.advance();
5122                    // Check for optional evidentiality marker: ⌛? ⌛! ⌛~ ⌛◊ ⌛‽
5123                    let evidentiality = match self.current_token() {
5124                        Some(Token::Question) => {
5125                            self.advance();
5126                            Some(Evidentiality::Uncertain)
5127                        }
5128                        Some(Token::Bang) => {
5129                            self.advance();
5130                            Some(Evidentiality::Known)
5131                        }
5132                        Some(Token::Tilde) => {
5133                            self.advance();
5134                            Some(Evidentiality::Reported)
5135                        }
5136                        Some(Token::Lozenge) => {
5137                            self.advance();
5138                            Some(Evidentiality::Predicted)
5139                        }
5140                        Some(Token::Interrobang) => {
5141                            self.advance();
5142                            Some(Evidentiality::Paradox)
5143                        }
5144                        _ => None,
5145                    };
5146                    expr = Expr::Await {
5147                        expr: Box::new(expr),
5148                        evidentiality,
5149                    };
5150                }
5151                // Incorporation: expr·verb·noun·action
5152                // Polysynthetic noun incorporation using middle dot
5153                Some(Token::MiddleDot) => {
5154                    // Convert current expr to first segment, then parse chain
5155                    let first_segment = self.expr_to_incorporation_segment(expr.clone())?;
5156                    let mut segments = vec![first_segment];
5157
5158                    while self.consume_if(&Token::MiddleDot) {
5159                        // Handle ·⌛ as await syntax (alternative to `expr⌛`)
5160                        if self.check(&Token::Async) {
5161                            self.advance();
5162                            let evidentiality = self.parse_evidentiality_opt();
5163                            // Build Incorporation from segments collected so far
5164                            expr = if segments.len() == 1 && segments[0].args.is_none() {
5165                                // Single segment without args - restore original expr
5166                                expr.clone()
5167                            } else {
5168                                Expr::Incorporation { segments: segments.clone() }
5169                            };
5170                            expr = Expr::Await {
5171                                expr: Box::new(expr),
5172                                evidentiality,
5173                            };
5174                            // Reset for potential continuation after await
5175                            let first_segment = self.expr_to_incorporation_segment(expr.clone())?;
5176                            segments = vec![first_segment];
5177                            continue;
5178                        }
5179                        // Handle both named methods and tuple indices: ·method() or ·0
5180                        let name = if let Some(Token::IntLit(idx)) = self.current_token().cloned() {
5181                            let span = self.current_span();
5182                            self.advance();
5183                            Ident {
5184                                name: idx,
5185                                evidentiality: None,
5186                                affect: None,
5187                                span,
5188                            }
5189                        } else {
5190                            self.parse_ident()?
5191                        };
5192                        // Handle bracket generics on method: ·method[Type]()
5193                        if self.check(&Token::LBracket) && self.peek_looks_like_bracket_generic() {
5194                            self.advance(); // consume [
5195                            let _generics = self.parse_type_list()?;
5196                            self.expect(Token::RBracket)?;
5197                            // Generics are parsed but currently ignored in incorporation segments
5198                        }
5199                        // Handle angle bracket generics: ·method<Type>()
5200                        if self.check(&Token::Lt) && self.peek_looks_like_generic_arg() {
5201                            self.advance(); // consume <
5202                            let _generics = self.parse_type_list()?;
5203                            self.expect_gt()?;
5204                        }
5205                        let args = if self.check(&Token::LParen) {
5206                            self.advance();
5207                            let args = self.parse_expr_list()?;
5208                            self.expect(Token::RParen)?;
5209                            Some(args)
5210                        } else {
5211                            None
5212                        };
5213                        segments.push(IncorporationSegment { name, args });
5214                    }
5215
5216                    expr = Expr::Incorporation { segments };
5217                }
5218                _ => break,
5219            }
5220        }
5221
5222        Ok(expr)
5223    }
5224
5225    fn parse_primary_expr(&mut self) -> ParseResult<Expr> {
5226        match self.current_token().cloned() {
5227            Some(Token::IntLit(s)) => {
5228                self.advance();
5229                Ok(Expr::Literal(Literal::Int {
5230                    value: s,
5231                    base: NumBase::Decimal,
5232                    suffix: None,
5233                }))
5234            }
5235            Some(Token::BinaryLit(s)) => {
5236                self.advance();
5237                Ok(Expr::Literal(Literal::Int {
5238                    value: s,
5239                    base: NumBase::Binary,
5240                    suffix: None,
5241                }))
5242            }
5243            Some(Token::OctalLit(s)) => {
5244                self.advance();
5245                Ok(Expr::Literal(Literal::Int {
5246                    value: s,
5247                    base: NumBase::Octal,
5248                    suffix: None,
5249                }))
5250            }
5251            Some(Token::HexLit(s)) => {
5252                self.advance();
5253                Ok(Expr::Literal(Literal::Int {
5254                    value: s,
5255                    base: NumBase::Hex,
5256                    suffix: None,
5257                }))
5258            }
5259            Some(Token::VigesimalLit(s)) => {
5260                self.advance();
5261                Ok(Expr::Literal(Literal::Int {
5262                    value: s,
5263                    base: NumBase::Vigesimal,
5264                    suffix: None,
5265                }))
5266            }
5267            Some(Token::SexagesimalLit(s)) => {
5268                self.advance();
5269                Ok(Expr::Literal(Literal::Int {
5270                    value: s,
5271                    base: NumBase::Sexagesimal,
5272                    suffix: None,
5273                }))
5274            }
5275            Some(Token::DuodecimalLit(s)) => {
5276                self.advance();
5277                Ok(Expr::Literal(Literal::Int {
5278                    value: s,
5279                    base: NumBase::Duodecimal,
5280                    suffix: None,
5281                }))
5282            }
5283            Some(Token::FloatLit(s)) => {
5284                self.advance();
5285                let (value, suffix) = Self::strip_float_suffix(&s);
5286                Ok(Expr::Literal(Literal::Float { value, suffix }))
5287            }
5288            Some(Token::StringLit(s)) => {
5289                self.advance();
5290                Ok(Expr::Literal(Literal::String(s)))
5291            }
5292            Some(Token::MultiLineStringLit(s)) => {
5293                self.advance();
5294                Ok(Expr::Literal(Literal::MultiLineString(s)))
5295            }
5296            Some(Token::RawStringLit(s)) | Some(Token::RawStringDelimited(s)) => {
5297                self.advance();
5298                Ok(Expr::Literal(Literal::RawString(s)))
5299            }
5300            // Full range expression: `..` or `..=` (with optional end)
5301            // Handles cases like `.drain(..)` and `[..]`
5302            Some(Token::DotDot) | Some(Token::DotDotEq) => {
5303                let inclusive = self.consume_if(&Token::DotDotEq);
5304                if !inclusive {
5305                    self.advance(); // consume ..
5306                }
5307                // Check if there's an end expression
5308                let end = if self.check(&Token::RParen)
5309                    || self.check(&Token::RBracket)
5310                    || self.check(&Token::Comma)
5311                    || self.check(&Token::Semi)
5312                    || self.check(&Token::RBrace)
5313                {
5314                    None
5315                } else {
5316                    Some(Box::new(self.parse_expr()?))
5317                };
5318                Ok(Expr::Range {
5319                    start: None,
5320                    end,
5321                    inclusive,
5322                })
5323            }
5324            Some(Token::ByteStringLit(bytes)) => {
5325                self.advance();
5326                Ok(Expr::Literal(Literal::ByteString(bytes)))
5327            }
5328            Some(Token::InterpolatedStringLit(s)) => {
5329                self.advance();
5330                // Parse the interpolation parts
5331                let parts = self.parse_interpolation_parts(&s)?;
5332                Ok(Expr::Literal(Literal::InterpolatedString { parts }))
5333            }
5334            Some(Token::SigilStringSql(s)) => {
5335                self.advance();
5336                Ok(Expr::Literal(Literal::SigilStringSql(s)))
5337            }
5338            Some(Token::SigilStringRoute(s)) => {
5339                self.advance();
5340                Ok(Expr::Literal(Literal::SigilStringRoute(s)))
5341            }
5342            Some(Token::CharLit(c)) => {
5343                self.advance();
5344                Ok(Expr::Literal(Literal::Char(c)))
5345            }
5346            Some(Token::ByteCharLit(b)) => {
5347                self.advance();
5348                Ok(Expr::Literal(Literal::ByteChar(b)))
5349            }
5350            Some(Token::True) | Some(Token::Top) => {
5351                self.advance();
5352                Ok(Expr::Literal(Literal::Bool(true)))
5353            }
5354            Some(Token::False) | Some(Token::Bottom) => {
5355                self.advance();
5356                Ok(Expr::Literal(Literal::Bool(false)))
5357            }
5358            Some(Token::Null) => {
5359                self.advance();
5360                Ok(Expr::Literal(Literal::Null))
5361            }
5362            Some(Token::Empty) => {
5363                self.advance();
5364                Ok(Expr::Literal(Literal::Empty))
5365            }
5366            Some(Token::Infinity) => {
5367                // Contextual: ∞ { ... } is a loop, ∞ alone is the infinity literal
5368                if self.peek_next() == Some(&Token::LBrace) {
5369                    // This is a loop expression
5370                    self.advance();
5371                    let body = self.parse_block()?;
5372                    Ok(Expr::Loop { label: None, body })
5373                } else {
5374                    self.advance();
5375                    Ok(Expr::Literal(Literal::Infinity))
5376                }
5377            }
5378            Some(Token::Circle) => {
5379                self.advance();
5380                Ok(Expr::Literal(Literal::Circle))
5381            }
5382            Some(Token::LParen) => {
5383                self.advance();
5384                if self.check(&Token::RParen) {
5385                    self.advance();
5386                    return Ok(Expr::Tuple(vec![]));
5387                }
5388                let expr = self.parse_expr()?;
5389                if self.consume_if(&Token::Comma) {
5390                    let mut exprs = vec![expr];
5391                    while !self.check(&Token::RParen) {
5392                        exprs.push(self.parse_expr()?);
5393                        if !self.consume_if(&Token::Comma) {
5394                            break;
5395                        }
5396                    }
5397                    self.expect(Token::RParen)?;
5398                    Ok(Expr::Tuple(exprs))
5399                } else {
5400                    self.expect(Token::RParen)?;
5401                    Ok(expr)
5402                }
5403            }
5404            Some(Token::LBracket) => {
5405                self.advance();
5406                // Check for empty array
5407                if self.check(&Token::RBracket) {
5408                    self.advance();
5409                    return Ok(Expr::Array(vec![]));
5410                }
5411                // Parse first expression
5412                let first = self.parse_expr()?;
5413                // Check for repeat syntax: [value; count]
5414                if self.consume_if(&Token::Semi) {
5415                    let count = self.parse_expr()?;
5416                    self.expect(Token::RBracket)?;
5417                    return Ok(Expr::ArrayRepeat {
5418                        value: Box::new(first),
5419                        count: Box::new(count),
5420                    });
5421                }
5422                // Otherwise, parse as regular array literal
5423                let mut exprs = vec![first];
5424                while self.consume_if(&Token::Comma) {
5425                    // Skip comments after comma (for trailing comments)
5426                    self.skip_comments();
5427                    if self.check(&Token::RBracket) {
5428                        break; // trailing comma
5429                    }
5430                    exprs.push(self.parse_expr()?);
5431                }
5432                self.skip_comments();
5433                self.expect(Token::RBracket)?;
5434                Ok(Expr::Array(exprs))
5435            }
5436            Some(Token::LBrace) => {
5437                // Could be block or closure
5438                self.parse_block_or_closure()
5439            }
5440            Some(Token::If) => self.parse_if_expr(),
5441            Some(Token::Match) => self.parse_match_expr(),
5442            Some(Token::ForAll) => {
5443                // ∀ is contextually a for-loop: ∀ pattern ∈ iter { ... }
5444                self.advance();
5445                let pattern = self.parse_pattern()?;
5446                self.expect(Token::ElementOf)?;
5447                let iter = self.parse_condition()?;
5448                let body = self.parse_block()?;
5449                Ok(Expr::For {
5450                    label: None,
5451                    pattern,
5452                    iter: Box::new(iter),
5453                    body,
5454                })
5455            }
5456            Some(Token::Unsafe) => {
5457                self.advance();
5458                let block = self.parse_block()?;
5459                Ok(Expr::Unsafe(block))
5460            }
5461            Some(Token::Async) => {
5462                self.advance();
5463                let is_move = self.consume_if(&Token::Move);
5464                let block = self.parse_block()?;
5465                Ok(Expr::Async { block, is_move })
5466            }
5467            Some(Token::Const) => {
5468                // Const block expression: `const { expr }` - compile-time evaluated block
5469                // For now, parse as a regular block expression
5470                self.advance();
5471                let block = self.parse_block()?;
5472                Ok(Expr::Block(block))
5473            }
5474            Some(Token::Lifetime(name)) => {
5475                // Labeled loop: 'label: loop/while/for { ... }
5476                let span = self.current_span();
5477                let label = Ident {
5478                    name: name.clone(),
5479                    evidentiality: None,
5480                    affect: None,
5481                    span,
5482                };
5483                self.advance();
5484                self.expect(Token::Colon)?;
5485                match self.current_token().cloned() {
5486                    Some(Token::Loop) | Some(Token::Infinity) => {
5487                        self.advance();
5488                        let body = self.parse_block()?;
5489                        Ok(Expr::Loop { label: Some(label), body })
5490                    }
5491                    Some(Token::While) => {
5492                        self.advance();
5493                        // Handle while-let: `while let pattern = expr { ... }`
5494                        let condition = if self.consume_if(&Token::Let) {
5495                            let pattern = self.parse_pattern()?;
5496                            self.expect(Token::Eq)?;
5497                            let value = self.parse_condition()?;
5498                            Expr::Let {
5499                                pattern,
5500                                value: Box::new(value),
5501                            }
5502                        } else {
5503                            self.parse_condition()?
5504                        };
5505                        let body = self.parse_block()?;
5506                        Ok(Expr::While {
5507                            label: Some(label),
5508                            condition: Box::new(condition),
5509                            body,
5510                        })
5511                    }
5512                    Some(Token::ForAll) | Some(Token::ForAll) => {
5513                        self.advance();
5514                        let pattern = self.parse_pattern()?;
5515                        self.expect(Token::ElementOf)?;
5516                        let iter = self.parse_condition()?;
5517                        let body = self.parse_block()?;
5518                        Ok(Expr::For {
5519                            label: Some(label),
5520                            pattern,
5521                            iter: Box::new(iter),
5522                            body,
5523                        })
5524                    }
5525                    other => Err(ParseError::UnexpectedToken {
5526                        expected: "loop, while, or for after label".to_string(),
5527                        found: other.unwrap_or(Token::Null),
5528                        span: self.current_span(),
5529                    })
5530                }
5531            }
5532            Some(Token::Loop) | Some(Token::Infinity) => {
5533                self.advance();
5534                let body = self.parse_block()?;
5535                Ok(Expr::Loop { label: None, body })
5536            }
5537            Some(Token::While) => {
5538                self.advance();
5539                // Handle while-let: `while let pattern = expr { ... }`
5540                let condition = if self.consume_if(&Token::Let) {
5541                    let pattern = self.parse_pattern()?;
5542                    self.expect(Token::Eq)?;
5543                    let value = self.parse_condition()?;
5544                    Expr::Let {
5545                        pattern,
5546                        value: Box::new(value),
5547                    }
5548                } else {
5549                    self.parse_condition()?
5550                };
5551                let body = self.parse_block()?;
5552                Ok(Expr::While {
5553                    label: None,
5554                    condition: Box::new(condition),
5555                    body,
5556                })
5557            }
5558            Some(Token::ForAll) | Some(Token::ForAll) => {
5559                self.advance();
5560                let pattern = self.parse_pattern()?;
5561                self.expect(Token::ElementOf)?;
5562                let iter = self.parse_condition()?;
5563                let body = self.parse_block()?;
5564                Ok(Expr::For {
5565                    label: None,
5566                    pattern,
5567                    iter: Box::new(iter),
5568                    body,
5569                })
5570            }
5571            Some(Token::Return) => {
5572                self.advance();
5573                // Check for terminators: ; } or , (in match arms)
5574                let value = if self.check(&Token::Semi)
5575                    || self.check(&Token::RBrace)
5576                    || self.check(&Token::Comma)
5577                {
5578                    None
5579                } else {
5580                    Some(Box::new(self.parse_expr()?))
5581                };
5582                Ok(Expr::Return(value))
5583            }
5584            Some(Token::Tensor) | Some(Token::Tensor) => {
5585                // ⊗ (Tensor) is contextually break at statement start, tensor product in binary position
5586                self.advance();
5587                // Check for optional label: break 'label or break 'label value
5588                let label = if let Some(Token::Lifetime(name)) = self.current_token().cloned() {
5589                    let span = self.current_span();
5590                    let label = Ident {
5591                        name,
5592                        evidentiality: None,
5593                        affect: None,
5594                        span,
5595                    };
5596                    self.advance();
5597                    Some(label)
5598                } else {
5599                    None
5600                };
5601                // Check for terminators: ; } or , (in match arms)
5602                let value = if self.check(&Token::Semi)
5603                    || self.check(&Token::RBrace)
5604                    || self.check(&Token::Comma)
5605                {
5606                    None
5607                } else {
5608                    Some(Box::new(self.parse_expr()?))
5609                };
5610                Ok(Expr::Break { label, value })
5611            }
5612            Some(Token::CycleArrow) | Some(Token::CycleArrow) => {
5613                // ↻ (CycleArrow) is contextually continue at statement start
5614                self.advance();
5615                // Check for optional label: continue 'label
5616                let label = if let Some(Token::Lifetime(name)) = self.current_token().cloned() {
5617                    let span = self.current_span();
5618                    let label = Ident {
5619                        name,
5620                        evidentiality: None,
5621                        affect: None,
5622                        span,
5623                    };
5624                    self.advance();
5625                    Some(label)
5626                } else {
5627                    None
5628                };
5629                Ok(Expr::Continue { label })
5630            }
5631            // Morphemes as standalone expressions
5632            Some(Token::Tau) | Some(Token::Phi) | Some(Token::Sigma) | Some(Token::Rho)
5633            | Some(Token::Lambda) | Some(Token::Pi) => {
5634                let kind = self.parse_morpheme_kind()?;
5635                if self.check(&Token::LBrace) {
5636                    self.advance();
5637                    self.skip_comments();
5638                    // Check for closure pattern: τ{x => expr} or τ{(a, b) => expr}
5639                    let body = if self.looks_like_morpheme_closure() {
5640                        self.parse_morpheme_closure()?
5641                    } else {
5642                        self.parse_expr()?
5643                    };
5644                    self.expect(Token::RBrace)?;
5645                    Ok(Expr::Morpheme {
5646                        kind,
5647                        body: Box::new(body),
5648                    })
5649                } else {
5650                    // Just the morpheme symbol
5651                    Ok(Expr::Morpheme {
5652                        kind,
5653                        body: Box::new(Expr::Path(TypePath {
5654                            segments: vec![PathSegment {
5655                                ident: Ident {
5656                                    name: "_".to_string(),
5657                                    evidentiality: None,
5658                                    affect: None,
5659                                    span: Span::default(),
5660                                },
5661                                generics: None,
5662                            }],
5663                        })),
5664                    })
5665                }
5666            }
5667            // Sacred constants as expressions
5668            Some(Token::Sqrt) => {
5669                // Handle √2, √3, √5, etc. (square root constants)
5670                let span = self.current_span();
5671                self.advance();
5672                let name = if let Some(Token::IntLit(n)) = self.current_token().cloned() {
5673                    let merged_span = span.merge(self.current_span());
5674                    self.advance();
5675                    (format!("√{}", n), merged_span)
5676                } else {
5677                    ("√".to_string(), span)
5678                };
5679                Ok(Expr::Path(TypePath {
5680                    segments: vec![PathSegment {
5681                        ident: Ident {
5682                            name: name.0,
5683                            evidentiality: None,
5684                            affect: None,
5685                            span: name.1,
5686                        },
5687                        generics: None,
5688                    }],
5689                }))
5690            }
5691            Some(Token::Underscore) => {
5692                // Underscore as placeholder in closures
5693                let span = self.current_span();
5694                self.advance();
5695                Ok(Expr::Path(TypePath {
5696                    segments: vec![PathSegment {
5697                        ident: Ident {
5698                            name: "_".to_string(),
5699                            evidentiality: None,
5700                            affect: None,
5701                            span,
5702                        },
5703                        generics: None,
5704                    }],
5705                }))
5706            }
5707            Some(Token::SelfLower) => {
5708                // self keyword as expression
5709                let span = self.current_span();
5710                self.advance();
5711                Ok(Expr::Path(TypePath {
5712                    segments: vec![PathSegment {
5713                        ident: Ident {
5714                            name: "self".to_string(),
5715                            evidentiality: None,
5716                            affect: None,
5717                            span,
5718                        },
5719                        generics: None,
5720                    }],
5721                }))
5722            }
5723            Some(Token::SelfUpper) => {
5724                // Self keyword as expression (struct constructor or path start)
5725                let span = self.current_span();
5726                self.advance();
5727                let mut segments = vec![PathSegment {
5728                    ident: Ident {
5729                        name: "Self".to_string(),
5730                        evidentiality: None,
5731                        affect: None,
5732                        span,
5733                    },
5734                    generics: None,
5735                }];
5736                // Handle Self::method() and other path continuations
5737                while self.consume_if(&Token::MiddleDot) {
5738                    // Check for turbofish syntax: Self::method::<Type>
5739                    if self.check(&Token::Lt) {
5740                        self.advance(); // consume <
5741                        let types = self.parse_type_list()?;
5742                        self.expect_gt()?;
5743                        // Update the last segment with these generics
5744                        if let Some(last) = segments.last_mut() {
5745                            last.generics = Some(types);
5746                        }
5747                        break;
5748                    }
5749                    segments.push(self.parse_path_segment()?);
5750                }
5751                let path = TypePath { segments };
5752                // Check for struct literal: Self { ... }
5753                if self.check(&Token::LBrace) && !self.is_in_condition() {
5754                    self.advance();
5755                    let (fields, rest) = self.parse_struct_fields()?;
5756                    self.expect(Token::RBrace)?;
5757                    Ok(Expr::Struct { path, fields, rest })
5758                } else {
5759                    Ok(Expr::Path(path))
5760                }
5761            }
5762            Some(Token::Ident(_)) => {
5763                let path = self.parse_type_path()?;
5764
5765                // Check for struct literal: Name { ... }
5766                // Note: Name! { ... } is treated as a macro invocation, handled in parse_postfix_expr
5767                // This allows html! { ... } and other macros with brace bodies to work correctly
5768                if self.check(&Token::LBrace) && !self.is_in_condition() {
5769                    self.advance();
5770                    let (fields, rest) = self.parse_struct_fields()?;
5771                    self.expect(Token::RBrace)?;
5772                    Ok(Expr::Struct { path, fields, rest })
5773                } else {
5774                    Ok(Expr::Path(path))
5775                }
5776            }
5777            Some(Token::Asm) => self.parse_inline_asm(),
5778            Some(Token::Volatile) => self.parse_volatile_expr(),
5779            Some(Token::Simd) => self.parse_simd_expr(),
5780            Some(Token::Atomic) => self.parse_atomic_expr(),
5781            // Implicit self field access: `.field` desugars to `self.field`
5782            // This allows more concise method bodies:
5783            //   fn increment(mut self) { .count += 1; }
5784            // instead of:
5785            //   fn increment(mut self) { self.count += 1; }
5786            Some(Token::Dot) => {
5787                let dot_span = self.current_span();
5788                self.advance(); // consume .
5789                match self.current_token() {
5790                    Some(Token::Ident(name)) => {
5791                        let field_name = name.clone();
5792                        let field_span = self.current_span();
5793                        self.advance();
5794                        // Create `self.field` expression
5795                        let self_expr = Expr::Path(TypePath {
5796                            segments: vec![PathSegment {
5797                                ident: Ident {
5798                                    name: "self".to_string(),
5799                                    evidentiality: None,
5800                                    affect: None,
5801                                    span: dot_span,
5802                                },
5803                                generics: None,
5804                            }],
5805                        });
5806                        Ok(Expr::Field {
5807                            expr: Box::new(self_expr),
5808                            field: Ident {
5809                                name: field_name,
5810                                evidentiality: None,
5811                                affect: None,
5812                                span: field_span,
5813                            },
5814                        })
5815                    }
5816                    Some(token) => Err(ParseError::UnexpectedToken {
5817                        expected: "identifier after '.' for implicit self field".to_string(),
5818                        found: token.clone(),
5819                        span: self.current_span(),
5820                    }),
5821                    None => Err(ParseError::UnexpectedEof),
5822                }
5823            }
5824            // Handle contextual keywords as identifiers in expressions
5825            Some(ref token) if Self::keyword_as_ident(token).is_some() => {
5826                let path = self.parse_type_path()?;
5827                // Check for struct literal: Name { ... }
5828                // Note: Don't consume ! here - macro invocations (Name!(...)) are handled in parse_postfix_expr
5829                if self.check(&Token::LBrace) && !self.is_in_condition() {
5830                    self.advance();
5831                    let (fields, rest) = self.parse_struct_fields()?;
5832                    self.expect(Token::RBrace)?;
5833                    Ok(Expr::Struct { path, fields, rest })
5834                } else {
5835                    Ok(Expr::Path(path))
5836                }
5837            }
5838            Some(token) => Err(ParseError::UnexpectedToken {
5839                expected: "expression".to_string(),
5840                found: token,
5841                span: self.current_span(),
5842            }),
5843            None => Err(ParseError::UnexpectedEof),
5844        }
5845    }
5846
5847    /// Parse inline assembly: `asm!("template", ...)`
5848    ///
5849    /// Syntax:
5850    /// ```sigil
5851    /// asm!("template {0} {1}",
5852    ///     out("rax") result,
5853    ///     in("rbx") input,
5854    ///     clobber("rcx", "rdx"),
5855    ///     options(volatile, nostack))
5856    /// ```
5857    fn parse_inline_asm(&mut self) -> ParseResult<Expr> {
5858        self.expect(Token::Asm)?;
5859        self.expect(Token::Bang)?;
5860        self.expect(Token::LParen)?;
5861
5862        // Parse template string
5863        let template = match self.current_token().cloned() {
5864            Some(Token::StringLit(s)) => {
5865                self.advance();
5866                s
5867            }
5868            Some(t) => {
5869                return Err(ParseError::UnexpectedToken {
5870                    expected: "assembly template string".to_string(),
5871                    found: t,
5872                    span: self.current_span(),
5873                });
5874            }
5875            None => return Err(ParseError::UnexpectedEof),
5876        };
5877
5878        let mut outputs = Vec::new();
5879        let mut inputs = Vec::new();
5880        let mut clobbers = Vec::new();
5881        let mut options = AsmOptions::default();
5882
5883        // Parse operands and options
5884        while self.consume_if(&Token::Comma) {
5885            if self.check(&Token::RParen) {
5886                break;
5887            }
5888
5889            match self.current_token().cloned() {
5890                Some(Token::Ident(ref name)) if name == "out" => {
5891                    self.advance();
5892                    let operand = self.parse_asm_operand(AsmOperandKind::Output)?;
5893                    outputs.push(operand);
5894                }
5895                // Handle `in` which is a keyword (Token::ElementOf)
5896                Some(Token::ElementOf) => {
5897                    self.advance();
5898                    let operand = self.parse_asm_operand(AsmOperandKind::Input)?;
5899                    inputs.push(operand);
5900                }
5901                Some(Token::Ident(ref name)) if name == "inout" => {
5902                    self.advance();
5903                    let operand = self.parse_asm_operand(AsmOperandKind::InOut)?;
5904                    outputs.push(operand);
5905                }
5906                Some(Token::Ident(ref name)) if name == "clobber" => {
5907                    self.advance();
5908                    self.expect(Token::LParen)?;
5909                    while !self.check(&Token::RParen) {
5910                        if let Some(Token::StringLit(reg)) = self.current_token().cloned() {
5911                            self.advance();
5912                            clobbers.push(reg);
5913                        } else if let Some(Token::Ident(reg)) = self.current_token().cloned() {
5914                            self.advance();
5915                            clobbers.push(reg);
5916                        }
5917                        if !self.consume_if(&Token::Comma) {
5918                            break;
5919                        }
5920                    }
5921                    self.expect(Token::RParen)?;
5922                }
5923                Some(Token::Ident(ref name)) if name == "options" => {
5924                    self.advance();
5925                    self.expect(Token::LParen)?;
5926                    while !self.check(&Token::RParen) {
5927                        if let Some(Token::Ident(opt)) = self.current_token().cloned() {
5928                            self.advance();
5929                            match opt.as_str() {
5930                                "volatile" => options.volatile = true,
5931                                "nostack" => options.nostack = true,
5932                                "pure" => options.pure_asm = true,
5933                                "readonly" => options.readonly = true,
5934                                "nomem" => options.nomem = true,
5935                                "att_syntax" => options.att_syntax = true,
5936                                _ => {}
5937                            }
5938                        }
5939                        if !self.consume_if(&Token::Comma) {
5940                            break;
5941                        }
5942                    }
5943                    self.expect(Token::RParen)?;
5944                }
5945                _ => break,
5946            }
5947        }
5948
5949        self.expect(Token::RParen)?;
5950
5951        Ok(Expr::InlineAsm(InlineAsm {
5952            template,
5953            outputs,
5954            inputs,
5955            clobbers,
5956            options,
5957        }))
5958    }
5959
5960    /// Parse an assembly operand: `("reg") expr` or `("reg") var => expr`
5961    fn parse_asm_operand(&mut self, kind: AsmOperandKind) -> ParseResult<AsmOperand> {
5962        self.expect(Token::LParen)?;
5963
5964        let constraint = match self.current_token().cloned() {
5965            Some(Token::StringLit(s)) => {
5966                self.advance();
5967                s
5968            }
5969            Some(Token::Ident(s)) => {
5970                self.advance();
5971                s
5972            }
5973            Some(t) => {
5974                return Err(ParseError::UnexpectedToken {
5975                    expected: "register constraint".to_string(),
5976                    found: t,
5977                    span: self.current_span(),
5978                });
5979            }
5980            None => return Err(ParseError::UnexpectedEof),
5981        };
5982
5983        self.expect(Token::RParen)?;
5984
5985        let expr = self.parse_expr()?;
5986
5987        // For inout, check for `=> output`
5988        let output = if kind == AsmOperandKind::InOut && self.consume_if(&Token::FatArrow) {
5989            Some(Box::new(self.parse_expr()?))
5990        } else {
5991            None
5992        };
5993
5994        Ok(AsmOperand {
5995            constraint,
5996            expr,
5997            kind,
5998            output,
5999        })
6000    }
6001
6002    /// Parse volatile memory operations
6003    ///
6004    /// - `volatile read<T>(ptr)` - volatile read from pointer
6005    /// - `volatile write<T>(ptr, value)` - volatile write to pointer
6006    fn parse_volatile_expr(&mut self) -> ParseResult<Expr> {
6007        self.expect(Token::Volatile)?;
6008
6009        match self.current_token().cloned() {
6010            Some(Token::Ident(ref name)) if name == "read" => {
6011                self.advance();
6012
6013                // Optional type parameter <T>
6014                let ty = if self.consume_if(&Token::Lt) {
6015                    let t = self.parse_type()?;
6016                    self.expect_gt()?;
6017                    Some(t)
6018                } else {
6019                    None
6020                };
6021
6022                self.expect(Token::LParen)?;
6023                let ptr = self.parse_expr()?;
6024                self.expect(Token::RParen)?;
6025
6026                Ok(Expr::VolatileRead {
6027                    ptr: Box::new(ptr),
6028                    ty,
6029                })
6030            }
6031            Some(Token::Ident(ref name)) if name == "write" => {
6032                self.advance();
6033
6034                // Optional type parameter <T>
6035                let ty = if self.consume_if(&Token::Lt) {
6036                    let t = self.parse_type()?;
6037                    self.expect_gt()?;
6038                    Some(t)
6039                } else {
6040                    None
6041                };
6042
6043                self.expect(Token::LParen)?;
6044                let ptr = self.parse_expr()?;
6045                self.expect(Token::Comma)?;
6046                let value = self.parse_expr()?;
6047                self.expect(Token::RParen)?;
6048
6049                Ok(Expr::VolatileWrite {
6050                    ptr: Box::new(ptr),
6051                    value: Box::new(value),
6052                    ty,
6053                })
6054            }
6055            Some(t) => Err(ParseError::UnexpectedToken {
6056                expected: "'read' or 'write' after 'volatile'".to_string(),
6057                found: t,
6058                span: self.current_span(),
6059            }),
6060            None => Err(ParseError::UnexpectedEof),
6061        }
6062    }
6063
6064    /// Parse SIMD expressions
6065    ///
6066    /// Syntax:
6067    /// ```sigil
6068    /// simd[1.0, 2.0, 3.0, 4.0]              // SIMD literal
6069    /// simd.splat(1.0, 4)                    // Broadcast value to all lanes
6070    /// simd.add(a, b)                        // SIMD intrinsic
6071    /// simd.shuffle(a, b, [0, 4, 1, 5])      // Shuffle lanes
6072    /// simd.extract(v, 0)                    // Extract element
6073    /// simd.insert(v, 0, val)                // Insert element
6074    /// ```
6075    fn parse_simd_expr(&mut self) -> ParseResult<Expr> {
6076        self.expect(Token::Simd)?;
6077
6078        match self.current_token().cloned() {
6079            Some(Token::LBracket) => {
6080                // SIMD literal: simd[1.0, 2.0, 3.0, 4.0]
6081                self.advance();
6082                let elements = self.parse_expr_list()?;
6083                self.expect(Token::RBracket)?;
6084
6085                // Optional type annotation
6086                let ty = if self.consume_if(&Token::Colon) {
6087                    Some(self.parse_type()?)
6088                } else {
6089                    None
6090                };
6091
6092                Ok(Expr::SimdLiteral { elements, ty })
6093            }
6094            Some(Token::Dot) => {
6095                self.advance();
6096                match self.current_token().cloned() {
6097                    Some(Token::Ident(ref op)) => {
6098                        let op_name = op.clone();
6099                        self.advance();
6100                        self.expect(Token::LParen)?;
6101
6102                        match op_name.as_str() {
6103                            "splat" => {
6104                                let value = self.parse_expr()?;
6105                                self.expect(Token::Comma)?;
6106                                let lanes = match self.current_token() {
6107                                    Some(Token::IntLit(s)) => {
6108                                        let n = s.parse::<u8>().map_err(|_| {
6109                                            ParseError::Custom("invalid lane count".to_string())
6110                                        })?;
6111                                        self.advance();
6112                                        n
6113                                    }
6114                                    _ => {
6115                                        return Err(ParseError::Custom(
6116                                            "expected lane count".to_string(),
6117                                        ))
6118                                    }
6119                                };
6120                                self.expect(Token::RParen)?;
6121                                Ok(Expr::SimdSplat {
6122                                    value: Box::new(value),
6123                                    lanes,
6124                                })
6125                            }
6126                            "shuffle" => {
6127                                let a = self.parse_expr()?;
6128                                self.expect(Token::Comma)?;
6129                                let b = self.parse_expr()?;
6130                                self.expect(Token::Comma)?;
6131                                self.expect(Token::LBracket)?;
6132                                let mut indices = Vec::new();
6133                                loop {
6134                                    match self.current_token() {
6135                                        Some(Token::IntLit(s)) => {
6136                                            let n = s.parse::<u8>().map_err(|_| {
6137                                                ParseError::Custom("invalid index".to_string())
6138                                            })?;
6139                                            indices.push(n);
6140                                            self.advance();
6141                                        }
6142                                        _ => {
6143                                            return Err(ParseError::Custom(
6144                                                "expected index".to_string(),
6145                                            ))
6146                                        }
6147                                    }
6148                                    if !self.consume_if(&Token::Comma) {
6149                                        break;
6150                                    }
6151                                }
6152                                self.expect(Token::RBracket)?;
6153                                self.expect(Token::RParen)?;
6154                                Ok(Expr::SimdShuffle {
6155                                    a: Box::new(a),
6156                                    b: Box::new(b),
6157                                    indices,
6158                                })
6159                            }
6160                            "extract" => {
6161                                let vector = self.parse_expr()?;
6162                                self.expect(Token::Comma)?;
6163                                let index = match self.current_token() {
6164                                    Some(Token::IntLit(s)) => {
6165                                        let n = s.parse::<u8>().map_err(|_| {
6166                                            ParseError::Custom("invalid index".to_string())
6167                                        })?;
6168                                        self.advance();
6169                                        n
6170                                    }
6171                                    _ => {
6172                                        return Err(ParseError::Custom(
6173                                            "expected index".to_string(),
6174                                        ))
6175                                    }
6176                                };
6177                                self.expect(Token::RParen)?;
6178                                Ok(Expr::SimdExtract {
6179                                    vector: Box::new(vector),
6180                                    index,
6181                                })
6182                            }
6183                            "insert" => {
6184                                let vector = self.parse_expr()?;
6185                                self.expect(Token::Comma)?;
6186                                let index = match self.current_token() {
6187                                    Some(Token::IntLit(s)) => {
6188                                        let n = s.parse::<u8>().map_err(|_| {
6189                                            ParseError::Custom("invalid index".to_string())
6190                                        })?;
6191                                        self.advance();
6192                                        n
6193                                    }
6194                                    _ => {
6195                                        return Err(ParseError::Custom(
6196                                            "expected index".to_string(),
6197                                        ))
6198                                    }
6199                                };
6200                                self.expect(Token::Comma)?;
6201                                let value = self.parse_expr()?;
6202                                self.expect(Token::RParen)?;
6203                                Ok(Expr::SimdInsert {
6204                                    vector: Box::new(vector),
6205                                    index,
6206                                    value: Box::new(value),
6207                                })
6208                            }
6209                            _ => {
6210                                // Parse as generic SIMD intrinsic
6211                                let op = Self::parse_simd_op(&op_name)?;
6212                                let args = self.parse_expr_list()?;
6213                                self.expect(Token::RParen)?;
6214                                Ok(Expr::SimdIntrinsic { op, args })
6215                            }
6216                        }
6217                    }
6218                    Some(t) => Err(ParseError::UnexpectedToken {
6219                        expected: "SIMD operation name".to_string(),
6220                        found: t,
6221                        span: self.current_span(),
6222                    }),
6223                    None => Err(ParseError::UnexpectedEof),
6224                }
6225            }
6226            Some(t) => Err(ParseError::UnexpectedToken {
6227                expected: "'[' or '.' after 'simd'".to_string(),
6228                found: t,
6229                span: self.current_span(),
6230            }),
6231            None => Err(ParseError::UnexpectedEof),
6232        }
6233    }
6234
6235    fn parse_simd_op(name: &str) -> ParseResult<SimdOp> {
6236        match name {
6237            "add" => Ok(SimdOp::Add),
6238            "sub" => Ok(SimdOp::Sub),
6239            "mul" => Ok(SimdOp::Mul),
6240            "div" => Ok(SimdOp::Div),
6241            "neg" => Ok(SimdOp::Neg),
6242            "abs" => Ok(SimdOp::Abs),
6243            "min" => Ok(SimdOp::Min),
6244            "max" => Ok(SimdOp::Max),
6245            "eq" => Ok(SimdOp::Eq),
6246            "ne" => Ok(SimdOp::Ne),
6247            "lt" => Ok(SimdOp::Lt),
6248            "le" => Ok(SimdOp::Le),
6249            "gt" => Ok(SimdOp::Gt),
6250            "ge" => Ok(SimdOp::Ge),
6251            "hadd" => Ok(SimdOp::HAdd),
6252            "dot" => Ok(SimdOp::Dot),
6253            "blend" => Ok(SimdOp::Blend),
6254            "load" => Ok(SimdOp::Load),
6255            "store" => Ok(SimdOp::Store),
6256            "load_aligned" => Ok(SimdOp::LoadAligned),
6257            "store_aligned" => Ok(SimdOp::StoreAligned),
6258            "cast" => Ok(SimdOp::Cast),
6259            "widen" => Ok(SimdOp::Widen),
6260            "narrow" => Ok(SimdOp::Narrow),
6261            "sqrt" => Ok(SimdOp::Sqrt),
6262            "rsqrt" => Ok(SimdOp::Rsqrt),
6263            "rcp" => Ok(SimdOp::Rcp),
6264            "floor" => Ok(SimdOp::Floor),
6265            "ceil" => Ok(SimdOp::Ceil),
6266            "round" => Ok(SimdOp::Round),
6267            "and" => Ok(SimdOp::And),
6268            "or" => Ok(SimdOp::Or),
6269            "xor" => Ok(SimdOp::Xor),
6270            "not" => Ok(SimdOp::Not),
6271            "shl" => Ok(SimdOp::Shl),
6272            "shr" => Ok(SimdOp::Shr),
6273            _ => Err(ParseError::Custom(format!(
6274                "unknown SIMD operation: {}",
6275                name
6276            ))),
6277        }
6278    }
6279
6280    /// Parse atomic expressions
6281    ///
6282    /// Syntax:
6283    /// ```sigil
6284    /// atomic.load(ptr, Relaxed)
6285    /// atomic.store(ptr, value, Release)
6286    /// atomic.swap(ptr, value, SeqCst)
6287    /// atomic.compare_exchange(ptr, expected, new, AcqRel, Relaxed)
6288    /// atomic.fetch_add(ptr, value, Acquire)
6289    /// atomic.fence(SeqCst)
6290    /// ```
6291    fn parse_atomic_expr(&mut self) -> ParseResult<Expr> {
6292        self.expect(Token::Atomic)?;
6293        self.expect(Token::Dot)?;
6294
6295        match self.current_token().cloned() {
6296            Some(Token::Ident(ref op)) => {
6297                let op_name = op.clone();
6298                self.advance();
6299
6300                if op_name == "fence" {
6301                    self.expect(Token::LParen)?;
6302                    let ordering = self.parse_memory_ordering()?;
6303                    self.expect(Token::RParen)?;
6304                    return Ok(Expr::AtomicFence { ordering });
6305                }
6306
6307                self.expect(Token::LParen)?;
6308                let ptr = self.parse_expr()?;
6309
6310                let op = Self::parse_atomic_op(&op_name)?;
6311
6312                // Parse value for operations that need it
6313                let value = match op {
6314                    AtomicOp::Load => None,
6315                    _ => {
6316                        self.expect(Token::Comma)?;
6317                        Some(Box::new(self.parse_expr()?))
6318                    }
6319                };
6320
6321                // Parse expected value for compare_exchange
6322                let expected = match op {
6323                    AtomicOp::CompareExchange | AtomicOp::CompareExchangeWeak => {
6324                        self.expect(Token::Comma)?;
6325                        Some(Box::new(self.parse_expr()?))
6326                    }
6327                    _ => None,
6328                };
6329
6330                // Parse memory ordering
6331                self.expect(Token::Comma)?;
6332                let ordering = self.parse_memory_ordering()?;
6333
6334                // Parse failure ordering for compare_exchange
6335                let failure_ordering = match op {
6336                    AtomicOp::CompareExchange | AtomicOp::CompareExchangeWeak => {
6337                        if self.consume_if(&Token::Comma) {
6338                            Some(self.parse_memory_ordering()?)
6339                        } else {
6340                            None
6341                        }
6342                    }
6343                    _ => None,
6344                };
6345
6346                self.expect(Token::RParen)?;
6347
6348                Ok(Expr::AtomicOp {
6349                    op,
6350                    ptr: Box::new(ptr),
6351                    value,
6352                    expected,
6353                    ordering,
6354                    failure_ordering,
6355                })
6356            }
6357            Some(t) => Err(ParseError::UnexpectedToken {
6358                expected: "atomic operation name".to_string(),
6359                found: t,
6360                span: self.current_span(),
6361            }),
6362            None => Err(ParseError::UnexpectedEof),
6363        }
6364    }
6365
6366    fn parse_atomic_op(name: &str) -> ParseResult<AtomicOp> {
6367        match name {
6368            "load" => Ok(AtomicOp::Load),
6369            "store" => Ok(AtomicOp::Store),
6370            "swap" => Ok(AtomicOp::Swap),
6371            "compare_exchange" => Ok(AtomicOp::CompareExchange),
6372            "compare_exchange_weak" => Ok(AtomicOp::CompareExchangeWeak),
6373            "fetch_add" => Ok(AtomicOp::FetchAdd),
6374            "fetch_sub" => Ok(AtomicOp::FetchSub),
6375            "fetch_and" => Ok(AtomicOp::FetchAnd),
6376            "fetch_or" => Ok(AtomicOp::FetchOr),
6377            "fetch_xor" => Ok(AtomicOp::FetchXor),
6378            "fetch_min" => Ok(AtomicOp::FetchMin),
6379            "fetch_max" => Ok(AtomicOp::FetchMax),
6380            _ => Err(ParseError::Custom(format!(
6381                "unknown atomic operation: {}",
6382                name
6383            ))),
6384        }
6385    }
6386
6387    fn parse_memory_ordering(&mut self) -> ParseResult<MemoryOrdering> {
6388        match self.current_token() {
6389            Some(Token::Ident(name)) => {
6390                let ordering =
6391                    match name.as_str() {
6392                        "Relaxed" => MemoryOrdering::Relaxed,
6393                        "Acquire" => MemoryOrdering::Acquire,
6394                        "Release" => MemoryOrdering::Release,
6395                        "AcqRel" => MemoryOrdering::AcqRel,
6396                        "SeqCst" => MemoryOrdering::SeqCst,
6397                        _ => return Err(ParseError::Custom(
6398                            "expected memory ordering (Relaxed, Acquire, Release, AcqRel, SeqCst)"
6399                                .to_string(),
6400                        )),
6401                    };
6402                self.advance();
6403                Ok(ordering)
6404            }
6405            _ => Err(ParseError::Custom("expected memory ordering".to_string())),
6406        }
6407    }
6408
6409    /// Check if the token after `|` looks like a pipe target (function, closure, morpheme)
6410    /// rather than a bitwise OR operand (literal, parenthesized expression)
6411    fn is_pipe_target_ahead(&mut self) -> bool {
6412        // Peek at the token after the pipe (current token is |)
6413        if let Some(next) = self.peek_next().cloned() {
6414            match &next {
6415                // These indicate a pipe target (function call, closure, morpheme)
6416                Token::Ident(_) => true,
6417                Token::SelfLower => true,
6418                Token::SelfUpper => true,
6419                // Morpheme operators (τ, φ, σ, ρ, Π, Σ, etc.)
6420                Token::Tau | Token::Phi | Token::Sigma | Token::Rho
6421                | Token::Lambda | Token::Delta | Token::Mu | Token::Chi
6422                | Token::GradeUp | Token::GradeDown | Token::Rotate
6423                | Token::Iota | Token::ForAll | Token::Exists
6424                | Token::Pi | Token::Async => true,
6425                // Lambda closure expression: λ(params) { body }
6426                Token::LambdaExpr => true,
6427                // Closure syntax |x| or || (lookahead for closure parameter list)
6428                Token::Pipe => true,
6429                Token::OrOr => true,  // Empty closure ||
6430                // Move closure
6431                Token::Move => true,
6432                // Block expression used as pipe target
6433                Token::LBrace => true,
6434                // These indicate bitwise OR (literals, grouping, conditionals)
6435                Token::IntLit(_) | Token::FloatLit(_) | Token::HexLit(_)
6436                | Token::BinaryLit(_) | Token::OctalLit(_) => false,
6437                Token::LParen => false,  // Parenthesized expression = bitwise OR
6438                Token::True | Token::False => false,
6439                Token::If => false,  // if expression as bitwise OR operand
6440                Token::Match => false,  // match expression as bitwise OR operand
6441                // Default to pipe for unknown cases
6442                _ => true,
6443            }
6444        } else {
6445            false  // EOF after |, treat as bitwise OR (will error anyway)
6446        }
6447    }
6448
6449    /// Parse postfix operators that can follow a pipe chain (like ?)
6450    fn parse_postfix_after_pipe(&mut self, mut expr: Expr) -> ParseResult<Expr> {
6451        loop {
6452            // Skip comments to allow method chain continuation across lines
6453            self.skip_comments();
6454
6455            match self.current_token() {
6456                Some(Token::Question) => {
6457                    self.advance();
6458                    expr = Expr::Try(Box::new(expr));
6459                }
6460                // Evidentiality markers after pipe: |await~ marks result as Reported
6461                Some(Token::Tilde) => {
6462                    self.advance();
6463                    expr = Expr::Evidential {
6464                        expr: Box::new(expr),
6465                        evidentiality: Evidentiality::Reported,
6466                    };
6467                }
6468                Some(Token::Bang) => {
6469                    // ! as evidentiality marker (Known) after pipe expression
6470                    self.advance();
6471                    expr = Expr::Evidential {
6472                        expr: Box::new(expr),
6473                        evidentiality: Evidentiality::Known,
6474                    };
6475                }
6476                Some(Token::Dot) => {
6477                    self.advance();
6478                    let field = if let Some(Token::IntLit(idx)) = self.current_token() {
6479                        let idx = idx.clone();
6480                        let span = self.current_span();
6481                        self.advance();
6482                        Ident {
6483                            name: idx,
6484                            evidentiality: None,
6485                            affect: None,
6486                            span,
6487                        }
6488                    } else {
6489                        self.parse_ident()?
6490                    };
6491                    if self.check(&Token::MiddleDot) {
6492                        self.advance();
6493                        self.expect(Token::Lt)?;
6494                        let type_args = self.parse_type_list()?;
6495                        self.expect_gt()?;
6496                        self.expect(Token::LParen)?;
6497                        let args = self.parse_expr_list()?;
6498                        self.expect(Token::RParen)?;
6499                        expr = Expr::MethodCall {
6500                            receiver: Box::new(expr),
6501                            method: field,
6502                            type_args: Some(type_args),
6503                            args,
6504                        };
6505                    } else if self.check(&Token::LParen) {
6506                        self.advance();
6507                        let args = self.parse_expr_list()?;
6508                        self.expect(Token::RParen)?;
6509                        expr = Expr::MethodCall {
6510                            receiver: Box::new(expr),
6511                            method: field,
6512                            type_args: None,
6513                            args,
6514                        };
6515                    } else {
6516                        expr = Expr::Field {
6517                            expr: Box::new(expr),
6518                            field,
6519                        };
6520                    }
6521                }
6522                // MiddleDot method chaining: expr·method()
6523                Some(Token::MiddleDot) => {
6524                    // Convert current expr to first segment, then parse chain
6525                    let first_segment = self.expr_to_incorporation_segment(expr.clone())?;
6526                    let mut segments = vec![first_segment];
6527
6528                    while self.consume_if(&Token::MiddleDot) {
6529                        // Handle ·⌛ as await syntax (alternative to `expr⌛`)
6530                        if self.check(&Token::Async) {
6531                            self.advance();
6532                            let evidentiality = self.parse_evidentiality_opt();
6533                            // Build Incorporation from segments collected so far
6534                            expr = if segments.len() == 1 && segments[0].args.is_none() {
6535                                // Single segment without args - restore original expr
6536                                expr.clone()
6537                            } else {
6538                                Expr::Incorporation { segments: segments.clone() }
6539                            };
6540                            expr = Expr::Await {
6541                                expr: Box::new(expr),
6542                                evidentiality,
6543                            };
6544                            // Reset for potential continuation after await
6545                            let first_segment = self.expr_to_incorporation_segment(expr.clone())?;
6546                            segments = vec![first_segment];
6547                            continue;
6548                        }
6549                        // Handle both named methods and tuple indices: ·method() or ·0
6550                        let name = if let Some(Token::IntLit(idx)) = self.current_token().cloned() {
6551                            let span = self.current_span();
6552                            self.advance();
6553                            Ident {
6554                                name: idx,
6555                                evidentiality: None,
6556                                affect: None,
6557                                span,
6558                            }
6559                        } else {
6560                            self.parse_ident()?
6561                        };
6562                        // Handle bracket generics on method: ·method[Type]()
6563                        if self.check(&Token::LBracket) && self.peek_looks_like_bracket_generic() {
6564                            self.advance(); // consume [
6565                            let _generics = self.parse_type_list()?;
6566                            self.expect(Token::RBracket)?;
6567                        }
6568                        // Handle angle bracket generics: ·method<Type>()
6569                        if self.check(&Token::Lt) && self.peek_looks_like_generic_arg() {
6570                            self.advance(); // consume <
6571                            let _generics = self.parse_type_list()?;
6572                            self.expect_gt()?;
6573                        }
6574                        let args = if self.check(&Token::LParen) {
6575                            self.advance();
6576                            let args = self.parse_expr_list()?;
6577                            self.expect(Token::RParen)?;
6578                            Some(args)
6579                        } else {
6580                            None
6581                        };
6582                        segments.push(IncorporationSegment { name, args });
6583                    }
6584
6585                    expr = Expr::Incorporation { segments };
6586                }
6587                _ => break,
6588            }
6589        }
6590        Ok(expr)
6591    }
6592
6593    /// Parse a pipe chain: `expr|op1|op2|op3`
6594    fn parse_pipe_chain(&mut self, initial: Expr) -> ParseResult<Expr> {
6595        let mut operations = Vec::new();
6596
6597        while self.consume_if(&Token::Pipe) {
6598            let op = self.parse_pipe_op()?;
6599            operations.push(op);
6600        }
6601
6602        Ok(Expr::Pipe {
6603            expr: Box::new(initial),
6604            operations,
6605        })
6606    }
6607
6608    fn parse_pipe_op(&mut self) -> ParseResult<PipeOp> {
6609        match self.current_token() {
6610            Some(Token::Tau) => {
6611                self.advance();
6612                self.expect(Token::LBrace)?;
6613                self.skip_comments();
6614                // Check for closure pattern: τ{x => expr} or τ{(a, b) => expr}
6615                let body = if self.looks_like_morpheme_closure() {
6616                    self.parse_morpheme_closure()?
6617                } else {
6618                    self.parse_expr()?
6619                };
6620                self.expect(Token::RBrace)?;
6621                Ok(PipeOp::Transform(Box::new(body)))
6622            }
6623            Some(Token::Phi) => {
6624                self.advance();
6625                self.expect(Token::LBrace)?;
6626                self.skip_comments();
6627                // Check for closure pattern: φ{x => expr} or φ{(a, b) => expr}
6628                let body = if self.looks_like_morpheme_closure() {
6629                    self.parse_morpheme_closure()?
6630                } else {
6631                    self.parse_expr()?
6632                };
6633                self.expect(Token::RBrace)?;
6634                Ok(PipeOp::Filter(Box::new(body)))
6635            }
6636            Some(Token::Sigma) => {
6637                // σ can be sort morpheme, function call like Σ(dim: -1), or custom comparator σ{a, b => ...}
6638                if self.peek_next() == Some(&Token::LParen) {
6639                    // Parse Σ as a function call: Σ(args)
6640                    let name = Ident {
6641                        name: "Σ".to_string(),
6642                        evidentiality: None,
6643                        affect: None,
6644                        span: self.current_span(),
6645                    };
6646                    self.advance(); // consume Σ
6647                    self.advance(); // consume (
6648                    let args = self.parse_expr_list()?;
6649                    self.expect(Token::RParen)?;
6650                    Ok(PipeOp::Call(Box::new(Expr::Call {
6651                        func: Box::new(Expr::Path(TypePath {
6652                            segments: vec![PathSegment { ident: name, generics: None }],
6653                        })),
6654                        args,
6655                    })))
6656                } else if self.peek_next() == Some(&Token::LBrace) {
6657                    // Custom comparator: σ{a, b => b - a}
6658                    self.advance(); // consume σ
6659                    self.advance(); // consume {
6660                    self.skip_comments();
6661                    let body = if self.looks_like_morpheme_closure() {
6662                        self.parse_morpheme_closure()?
6663                    } else {
6664                        self.parse_expr()?
6665                    };
6666                    self.expect(Token::RBrace)?;
6667                    Ok(PipeOp::SortBy(Box::new(body)))
6668                } else {
6669                    self.advance();
6670                    let field = if self.consume_if(&Token::Dot) {
6671                        Some(self.parse_ident()?)
6672                    } else {
6673                        None
6674                    };
6675                    Ok(PipeOp::Sort(field))
6676                }
6677            }
6678            Some(Token::Rho) => {
6679                self.advance();
6680                // Check for reduction variants: ρ+, ρ*, ρ++, ρ&, ρ|, ρ_sum, ρ_prod, ρ_min, ρ_max, ρ_cat, ρ_all, ρ_any
6681                match self.current_token() {
6682                    Some(Token::Plus) => {
6683                        self.advance();
6684                        Ok(PipeOp::ReduceSum)
6685                    }
6686                    Some(Token::Star) => {
6687                        self.advance();
6688                        Ok(PipeOp::ReduceProd)
6689                    }
6690                    Some(Token::PlusPlus) => {
6691                        self.advance();
6692                        Ok(PipeOp::ReduceConcat)
6693                    }
6694                    Some(Token::Amp) => {
6695                        self.advance();
6696                        Ok(PipeOp::ReduceAll)
6697                    }
6698                    Some(Token::Pipe) => {
6699                        self.advance();
6700                        Ok(PipeOp::ReduceAny)
6701                    }
6702                    Some(Token::Underscore) => {
6703                        self.advance();
6704                        // Parse the variant name: _sum, _prod, _min, _max, _cat, _all, _any
6705                        if let Some(Token::Ident(name)) = self.current_token().cloned() {
6706                            self.advance();
6707                            match name.as_str() {
6708                                "sum" => Ok(PipeOp::ReduceSum),
6709                                "prod" | "product" => Ok(PipeOp::ReduceProd),
6710                                "min" => Ok(PipeOp::ReduceMin),
6711                                "max" => Ok(PipeOp::ReduceMax),
6712                                "cat" | "concat" => Ok(PipeOp::ReduceConcat),
6713                                "all" => Ok(PipeOp::ReduceAll),
6714                                "any" => Ok(PipeOp::ReduceAny),
6715                                _ => Err(ParseError::Custom(format!(
6716                                    "unknown reduction variant: ρ_{}",
6717                                    name
6718                                ))),
6719                            }
6720                        } else {
6721                            Err(ParseError::Custom(
6722                                "expected reduction variant name after ρ_".to_string(),
6723                            ))
6724                        }
6725                    }
6726                    Some(Token::LBrace) => {
6727                        // General reduce: ρ{(acc, x) => ...} or ρ{init, acc, x => acc + x}
6728                        self.advance();
6729                        self.skip_comments();
6730                        if self.looks_like_morpheme_closure() {
6731                            // Direct closure: ρ{acc => expr} or ρ{(acc, x) => acc + x}
6732                            let body = self.parse_morpheme_closure()?;
6733                            self.expect(Token::RBrace)?;
6734                            Ok(PipeOp::Reduce(Box::new(body)))
6735                        } else {
6736                            // Init value + closure: ρ{0, acc, x => acc + x}
6737                            let init = self.parse_expr()?;
6738                            self.expect(Token::Comma)?;
6739                            self.skip_comments();
6740                            let closure = self.parse_morpheme_closure()?;
6741                            self.expect(Token::RBrace)?;
6742                            Ok(PipeOp::ReduceWithInit(Box::new(init), Box::new(closure)))
6743                        }
6744                    }
6745                    _ => Err(ParseError::Custom(
6746                        "expected reduction variant (+, *, ++, &, |, _name) or {body} after ρ"
6747                            .to_string(),
6748                    )),
6749                }
6750            }
6751            // Product reduction: Π - multiply all elements (shorthand for ρ*)
6752            Some(Token::Pi) => {
6753                self.advance();
6754                Ok(PipeOp::ReduceProd)
6755            }
6756            // New access morphemes
6757            Some(Token::Alpha) => {
6758                self.advance();
6759                Ok(PipeOp::First)
6760            }
6761            Some(Token::Omega) => {
6762                self.advance();
6763                Ok(PipeOp::Last)
6764            }
6765            Some(Token::Mu) => {
6766                // μ can be either the "middle" morpheme OR a function call like μ(axis: -1)
6767                // If followed by (, it's a function call - parse as normal expression
6768                if self.peek_next() == Some(&Token::LParen) {
6769                    // Parse μ as a function call: μ(args) - treat as expression piped call
6770                    let name = Ident {
6771                        name: "μ".to_string(),
6772                        evidentiality: None,
6773                        affect: None,
6774                        span: self.current_span(),
6775                    };
6776                    self.advance(); // consume μ
6777                    self.advance(); // consume (
6778                    let args = self.parse_expr_list()?;
6779                    self.expect(Token::RParen)?;
6780                    // Create a call expression and return as PipeOp::Call
6781                    Ok(PipeOp::Call(Box::new(Expr::Call {
6782                        func: Box::new(Expr::Path(TypePath {
6783                            segments: vec![PathSegment { ident: name, generics: None }],
6784                        })),
6785                        args,
6786                    })))
6787                } else {
6788                    self.advance();
6789                    Ok(PipeOp::Middle)
6790                }
6791            }
6792            Some(Token::Chi) => {
6793                self.advance();
6794                Ok(PipeOp::Choice)
6795            }
6796            Some(Token::Nu) => {
6797                self.advance();
6798                // ν can take an optional index: ν{2}
6799                if self.check(&Token::LBrace) {
6800                    self.advance();
6801                    let index = self.parse_expr()?;
6802                    self.expect(Token::RBrace)?;
6803                    Ok(PipeOp::Nth(Box::new(index)))
6804                } else {
6805                    // Default to first element if no index given
6806                    Ok(PipeOp::Nth(Box::new(Expr::Literal(Literal::Int {
6807                        value: "0".to_string(),
6808                        base: NumBase::Decimal,
6809                        suffix: None,
6810                    }))))
6811                }
6812            }
6813            Some(Token::Xi) => {
6814                self.advance();
6815                Ok(PipeOp::Next)
6816            }
6817            // Distinct/unique morpheme: δ - remove duplicates
6818            Some(Token::Delta) => {
6819                self.advance();
6820                Ok(PipeOp::Unique)
6821            }
6822            // Parallel morpheme: ∥τ{f} or parallel τ{f} - wraps another operation
6823            Some(Token::Parallel) => {
6824                self.advance();
6825                // Parse the inner operation to parallelize
6826                let inner_op = self.parse_pipe_op()?;
6827                Ok(PipeOp::Parallel(Box::new(inner_op)))
6828            }
6829            // GPU compute morpheme: ⊛τ{f} or gpu τ{f} - execute on GPU
6830            Some(Token::Gpu) => {
6831                self.advance();
6832                // Parse the inner operation to run on GPU
6833                let inner_op = self.parse_pipe_op()?;
6834                Ok(PipeOp::Gpu(Box::new(inner_op)))
6835            }
6836            Some(Token::Await) => {
6837                self.advance();
6838                Ok(PipeOp::Await)
6839            }
6840            Some(Token::Async) => {
6841                self.advance();
6842                Ok(PipeOp::Await)
6843            }
6844            Some(Token::MiddleDot) => {
6845                self.advance();
6846                let mut prefix = Vec::new();
6847                prefix.push(self.parse_ident()?);
6848
6849                while self.consume_if(&Token::MiddleDot) {
6850                    if self.check(&Token::LBrace) {
6851                        break;
6852                    }
6853                    prefix.push(self.parse_ident()?);
6854                }
6855
6856                let body = if self.check(&Token::LBrace) {
6857                    self.advance();
6858                    let expr = self.parse_expr()?;
6859                    self.expect(Token::RBrace)?;
6860                    Some(Box::new(expr))
6861                } else {
6862                    None
6863                };
6864
6865                Ok(PipeOp::Named { prefix, body })
6866            }
6867            // Match morpheme: |match{ Pattern => expr, ... }
6868            Some(Token::Match) => {
6869                self.advance();
6870                self.expect(Token::LBrace)?;
6871                let mut arms = Vec::new();
6872                while !self.check(&Token::RBrace) && !self.is_eof() {
6873                    // Use parse_or_pattern to support "pat1 | pat2 => expr" arms
6874                    let pattern = self.parse_or_pattern()?;
6875                    let guard = if self.consume_if(&Token::If) {
6876                        Some(self.parse_condition()?)
6877                    } else {
6878                        None
6879                    };
6880                    self.expect(Token::FatArrow)?;
6881                    let body = self.parse_expr()?;
6882                    arms.push(MatchArm {
6883                        pattern,
6884                        guard,
6885                        body,
6886                    });
6887                    // Comma is optional after block bodies, just like in regular match
6888                    self.consume_if(&Token::Comma);
6889                }
6890                self.expect(Token::RBrace)?;
6891                Ok(PipeOp::Match(arms))
6892            }
6893            // Trust boundary / unwrap: |‽ or |‽{mapper}
6894            // Uses interrobang (‽) to signal trust boundary crossing
6895            Some(Token::Interrobang) => {
6896                self.advance();
6897                let mapper = if self.check(&Token::LBrace) {
6898                    self.advance();
6899                    let expr = self.parse_expr()?;
6900                    self.expect(Token::RBrace)?;
6901                    Some(Box::new(expr))
6902                } else {
6903                    None
6904                };
6905                Ok(PipeOp::TryMap(mapper))
6906            }
6907            // Handle self.field as a pipe call: |self.layer becomes Call(self.layer)
6908            Some(Token::SelfLower) | Some(Token::SelfUpper) => {
6909                // Parse self and any field accesses/method calls following it
6910                let expr = self.parse_postfix_expr()?;
6911                Ok(PipeOp::Call(Box::new(expr)))
6912            }
6913            // Gradient/nabla operator: |∇ - backpropagate gradients
6914            Some(Token::Nabla) => {
6915                self.advance();
6916                // ∇ as a simple gradient pipe - creates gradients from tensor
6917                Ok(PipeOp::Method {
6918                    name: Ident {
6919                        name: "∇".to_string(),
6920                        evidentiality: None,
6921                        affect: None,
6922                        span: self.current_span(),
6923                    },
6924                    type_args: None,
6925                    args: vec![],
6926                })
6927            }
6928            // Handle special keyword tokens that are pipe methods
6929            Some(Token::Interfere) => {
6930                self.advance(); // consume 'interfere'
6931                let name = Ident {
6932                    name: "interfere".to_string(),
6933                    evidentiality: None,
6934                    affect: None,
6935                    span: self.current_span(),
6936                };
6937                // Parse optional arguments
6938                let args = if self.check(&Token::LParen) {
6939                    self.advance();
6940                    let args = self.parse_expr_list()?;
6941                    self.expect(Token::RParen)?;
6942                    args
6943                } else {
6944                    vec![]
6945                };
6946                Ok(PipeOp::Method { name, type_args: None, args })
6947            }
6948            // Handle Σ (uppercase sigma) which is tokenized as Struct but used as neural sum in pipe context
6949            Some(Token::Struct) => {
6950                self.advance(); // consume Σ
6951                let name = Ident {
6952                    name: "Σ".to_string(),
6953                    evidentiality: None,
6954                    affect: None,
6955                    span: self.current_span(),
6956                };
6957                // Parse optional arguments like Σ(dim: -1)
6958                let args = if self.check(&Token::LParen) {
6959                    self.advance();
6960                    let args = self.parse_expr_list()?;
6961                    self.expect(Token::RParen)?;
6962                    args
6963                } else {
6964                    vec![]
6965                };
6966                Ok(PipeOp::Method { name, type_args: None, args })
6967            }
6968            // Possibility operator: |◊method(args) or bare |◊
6969            Some(Token::Lozenge) => {
6970                self.advance();
6971                if let Some(Token::Ident(_)) = self.current_token() {
6972                    // |◊method or |◊method(args) - holographic possibility query
6973                    let method = self.parse_ident()?;
6974                    let args = if self.check(&Token::LParen) {
6975                        self.advance();
6976                        let args = self.parse_expr_list()?;
6977                        self.expect(Token::RParen)?;
6978                        args
6979                    } else {
6980                        vec![]
6981                    };
6982                    Ok(PipeOp::Possibility { method, args })
6983                } else {
6984                    // Bare |◊ - extract with Predicted evidentiality
6985                    Ok(PipeOp::PossibilityExtract)
6986                }
6987            }
6988            // Necessity operator: |□method(args) or bare |□
6989            Some(Token::BoxSquare) => {
6990                self.advance();
6991                if let Some(Token::Ident(_)) = self.current_token() {
6992                    // |□method or |□method(args) - holographic necessity verification
6993                    let method = self.parse_ident()?;
6994                    let args = if self.check(&Token::LParen) {
6995                        self.advance();
6996                        let args = self.parse_expr_list()?;
6997                        self.expect(Token::RParen)?;
6998                        args
6999                    } else {
7000                        vec![]
7001                    };
7002                    Ok(PipeOp::Necessity { method, args })
7003                } else {
7004                    // Bare |□ - verify and promote to Known evidentiality
7005                    Ok(PipeOp::NecessityVerify)
7006                }
7007            }
7008            Some(Token::Ident(_)) => {
7009                let name = self.parse_ident()?;
7010
7011                // Special handling for evidence promotion operations BEFORE macro check
7012                // |validate!{predicate} or |validate!(predicate) - validate and promote to Known
7013                // |validate?{predicate} - validate and promote to Uncertain
7014                // |validate~{predicate} - validate and keep as Reported
7015                // |assume!("reason") - assume evidence level
7016                if name.name == "validate" || name.name == "assume" {
7017                    // Check for evidentiality marker followed by { or (
7018                    // NOTE: ! (Bang) is NOT treated as evidence marker here because
7019                    // |validate!{...} should be parsed as a macro invocation (line 6980+).
7020                    // Only ? and ~ are evidence markers for built-in validate.
7021                    let (has_marker, target_evidence) = if self.check(&Token::Question) {
7022                        let peek = self.peek_next();
7023                        if matches!(peek, Some(Token::LBrace) | Some(Token::LParen)) {
7024                            self.advance(); // consume ?
7025                            (true, Evidentiality::Uncertain)
7026                        } else {
7027                            (false, Evidentiality::Known)
7028                        }
7029                    } else if self.check(&Token::Tilde) {
7030                        let peek = self.peek_next();
7031                        if matches!(peek, Some(Token::LBrace) | Some(Token::LParen)) {
7032                            self.advance(); // consume ~
7033                            (true, Evidentiality::Reported)
7034                        } else {
7035                            (false, Evidentiality::Known)
7036                        }
7037                    } else {
7038                        (false, name.evidentiality.unwrap_or(Evidentiality::Known))
7039                    };
7040
7041                    // Check for args - either (args) or {closure}
7042                    if has_marker || self.check(&Token::LParen) || self.check(&Token::LBrace) {
7043
7044                        let args = if self.check(&Token::LParen) {
7045                            self.advance();
7046                            let args = self.parse_expr_list()?;
7047                            self.expect(Token::RParen)?;
7048                            args
7049                        } else if self.check(&Token::LBrace) {
7050                            self.advance();
7051                            self.skip_comments();
7052                            let body = if self.looks_like_morpheme_closure() {
7053                                self.parse_morpheme_closure()?
7054                            } else {
7055                                self.parse_expr()?
7056                            };
7057                            self.expect(Token::RBrace)?;
7058                            vec![body]
7059                        } else {
7060                            vec![]
7061                        };
7062
7063                        if name.name == "validate" {
7064                            if args.is_empty() {
7065                                return Err(ParseError::Custom("validate requires a predicate".to_string()));
7066                            }
7067                            return Ok(PipeOp::Validate {
7068                                predicate: Box::new(args.into_iter().next().unwrap()),
7069                                target_evidence,
7070                            });
7071                        } else {
7072                            // assume
7073                            let reason = args.into_iter().next().map(Box::new);
7074                            return Ok(PipeOp::Assume {
7075                                reason,
7076                                target_evidence,
7077                            });
7078                        }
7079                    }
7080                }
7081
7082                // Check for macro invocation: |macro_name!{ ... } or |macro_name!(...)
7083                if self.check(&Token::Bang) {
7084                    let peek = self.peek_next();
7085                    if matches!(peek, Some(Token::LBrace) | Some(Token::LParen) | Some(Token::LBracket)) {
7086                        self.advance(); // consume !
7087                        let tokens = self.parse_macro_tokens()?;
7088                        let path = TypePath {
7089                            segments: vec![PathSegment { ident: name, generics: None }],
7090                        };
7091                        return Ok(PipeOp::Call(Box::new(Expr::Macro { path, tokens })));
7092                    }
7093                }
7094
7095                // Check for path continuation or turbofish syntax:
7096                // |Tensor::from_slice - path to associated function
7097                // |collect::<String>() - turbofish generics
7098                let mut path_segments = vec![PathSegment { ident: name.clone(), generics: None }];
7099                let type_args = loop {
7100                    if self.check(&Token::MiddleDot) {
7101                        self.advance(); // consume ::
7102                        if self.check(&Token::Lt) {
7103                            // Turbofish: ::<Type>
7104                            self.advance(); // consume <
7105                            let types = self.parse_type_list()?;
7106                            self.expect_gt()?;
7107                            break Some(types);
7108                        } else if let Some(Token::Ident(_)) = self.current_token() {
7109                            // Path continuation: ::segment
7110                            let segment = self.parse_ident()?;
7111                            path_segments.push(PathSegment { ident: segment, generics: None });
7112                            // Continue to check for more segments or turbofish
7113                        } else {
7114                            return Err(ParseError::Custom(
7115                                "expected identifier or '<' after '::'".to_string()
7116                            ));
7117                        }
7118                    } else {
7119                        break None;
7120                    }
7121                };
7122
7123                // If we have a multi-segment path, convert to a path call
7124                let name = if path_segments.len() > 1 {
7125                    // Build a Call expression with the full path
7126                    let path = TypePath { segments: path_segments };
7127                    let args = if self.check(&Token::LParen) {
7128                        self.advance();
7129                        let args = self.parse_expr_list()?;
7130                        self.expect(Token::RParen)?;
7131                        args
7132                    } else {
7133                        vec![]
7134                    };
7135                    return Ok(PipeOp::Call(Box::new(Expr::Call {
7136                        func: Box::new(Expr::Path(path)),
7137                        args,
7138                    })));
7139                } else {
7140                    name
7141                };
7142                let args = if self.check(&Token::LParen) {
7143                    self.advance();
7144                    let args = self.parse_expr_list()?;
7145                    self.expect(Token::RParen)?;
7146                    args
7147                } else if self.check(&Token::LBrace) && !self.in_condition {
7148                    // Handle closure-style argument: |method{closure}
7149                    // But NOT in condition context (for/while/if) where { is the control block
7150                    self.advance();
7151                    self.skip_comments();
7152                    let body = if self.looks_like_morpheme_closure() {
7153                        self.parse_morpheme_closure()?
7154                    } else {
7155                        self.parse_expr()?
7156                    };
7157                    self.expect(Token::RBrace)?;
7158                    vec![body]
7159                } else {
7160                    vec![]
7161                };
7162
7163                // Special handling for evidence promotion operations
7164                if name.name == "validate" {
7165                    let target_evidence = name.evidentiality.unwrap_or(Evidentiality::Known);
7166                    if args.is_empty() {
7167                        return Err(ParseError::Custom("validate requires a predicate: |validate!{predicate}".to_string()));
7168                    }
7169                    return Ok(PipeOp::Validate {
7170                        predicate: Box::new(args.into_iter().next().unwrap()),
7171                        target_evidence,
7172                    });
7173                }
7174                if name.name == "assume" {
7175                    let target_evidence = name.evidentiality.unwrap_or(Evidentiality::Known);
7176                    let reason = args.into_iter().next().map(Box::new);
7177                    return Ok(PipeOp::Assume {
7178                        reason,
7179                        target_evidence,
7180                    });
7181                }
7182
7183                // Check if this is a known builtin function that should be called directly
7184                // rather than treated as a method on the piped value
7185                // Uses QUANTUM_GATES and QUANTUM_OPS constants for extensibility
7186                if QUANTUM_GATES.contains(&name.name.as_str())
7187                    || QUANTUM_OPS.contains(&name.name.as_str()) {
7188                    // Emit PipeOp::Call(Expr::Path) or PipeOp::Call(Expr::Call)
7189                    // This will evaluate the identifier (getting Value::BuiltIn)
7190                    // and call it with the piped value as the first argument
7191                    let path_expr = Expr::Path(TypePath {
7192                        segments: vec![PathSegment { ident: name, generics: None }],
7193                    });
7194                    let call_expr = if args.is_empty() {
7195                        path_expr
7196                    } else {
7197                        Expr::Call {
7198                            func: Box::new(path_expr),
7199                            args,
7200                        }
7201                    };
7202                    return Ok(PipeOp::Call(Box::new(call_expr)));
7203                }
7204
7205                Ok(PipeOp::Method { name, type_args, args })
7206            }
7207
7208            // ==========================================
7209            // Protocol Operations - Sigil-native networking
7210            // ==========================================
7211
7212            // Send: |send{data} or |⇒{data}
7213            Some(Token::Send) | Some(Token::ProtoSend) => {
7214                self.advance();
7215                self.expect(Token::LBrace)?;
7216                let data = self.parse_expr()?;
7217                self.expect(Token::RBrace)?;
7218                Ok(PipeOp::Send(Box::new(data)))
7219            }
7220
7221            // Recv: |recv or |⇐
7222            Some(Token::Recv) | Some(Token::ProtoRecv) => {
7223                self.advance();
7224                Ok(PipeOp::Recv)
7225            }
7226
7227            // Stream: |stream{handler} or |≋{handler}
7228            Some(Token::Stream) | Some(Token::ProtoStream) => {
7229                self.advance();
7230                self.expect(Token::LBrace)?;
7231                let handler = self.parse_expr()?;
7232                self.expect(Token::RBrace)?;
7233                Ok(PipeOp::Stream(Box::new(handler)))
7234            }
7235
7236            // Connect: |connect or |connect{config} or |⊸{config}
7237            Some(Token::Connect) | Some(Token::ProtoConnect) => {
7238                self.advance();
7239                let config = if self.check(&Token::LBrace) {
7240                    self.advance();
7241                    let expr = self.parse_expr()?;
7242                    self.expect(Token::RBrace)?;
7243                    Some(Box::new(expr))
7244                } else {
7245                    None
7246                };
7247                Ok(PipeOp::Connect(config))
7248            }
7249
7250            // Close: |close or |⊗
7251            Some(Token::Close) | Some(Token::Tensor) => {
7252                self.advance();
7253                Ok(PipeOp::Close)
7254            }
7255
7256            // Timeout: |timeout{ms} or |⏱{ms}
7257            Some(Token::Timeout) | Some(Token::ProtoTimeout) => {
7258                self.advance();
7259                self.expect(Token::LBrace)?;
7260                let ms = self.parse_expr()?;
7261                self.expect(Token::RBrace)?;
7262                Ok(PipeOp::Timeout(Box::new(ms)))
7263            }
7264
7265            // Retry: |retry{count} or |retry{count, strategy}
7266            Some(Token::Retry) => {
7267                self.advance();
7268                self.expect(Token::LBrace)?;
7269                let count = self.parse_expr()?;
7270                let strategy = if self.consume_if(&Token::Comma) {
7271                    Some(Box::new(self.parse_expr()?))
7272                } else {
7273                    None
7274                };
7275                self.expect(Token::RBrace)?;
7276                Ok(PipeOp::Retry {
7277                    count: Box::new(count),
7278                    strategy,
7279                })
7280            }
7281
7282            // Header: |header{name, value}
7283            Some(Token::Header) => {
7284                self.advance();
7285                self.expect(Token::LBrace)?;
7286                let name = self.parse_expr()?;
7287                self.expect(Token::Comma)?;
7288                let value = self.parse_expr()?;
7289                self.expect(Token::RBrace)?;
7290                Ok(PipeOp::Header {
7291                    name: Box::new(name),
7292                    value: Box::new(value),
7293                })
7294            }
7295
7296            // Body: |body{data}
7297            Some(Token::Body) => {
7298                self.advance();
7299                self.expect(Token::LBrace)?;
7300                let data = self.parse_expr()?;
7301                self.expect(Token::RBrace)?;
7302                Ok(PipeOp::Body(Box::new(data)))
7303            }
7304
7305            // ==========================================
7306            // Mathematical & APL-Inspired Operations
7307            // ==========================================
7308
7309            // All/ForAll: |∀{p} = check all satisfy predicate
7310            // Universal: |∀ (no braces) = reconstruct whole from parts (sum)
7311            Some(Token::ForAll) => {
7312                self.advance();
7313                // |∀ without braces = Universal Reconstruction (sum)
7314                // |∀{predicate} = check All elements satisfy predicate
7315                if self.current_token() == Some(&Token::LBrace) {
7316                    self.advance(); // consume {
7317                    let pred = self.parse_expr()?;
7318                    self.expect(Token::RBrace)?;
7319                    Ok(PipeOp::All(Box::new(pred)))
7320                } else {
7321                    // No braces - Universal Reconstruction operator
7322                    Ok(PipeOp::Universal)
7323                }
7324            }
7325
7326            // Any/Exists: |∃{p} or |any{p}
7327            Some(Token::Exists) => {
7328                self.advance();
7329                self.expect(Token::LBrace)?;
7330                let pred = self.parse_expr()?;
7331                self.expect(Token::RBrace)?;
7332                Ok(PipeOp::Any(Box::new(pred)))
7333            }
7334
7335            // Compose: |∘{f} or |compose{f}
7336            Some(Token::Compose) => {
7337                self.advance();
7338                self.expect(Token::LBrace)?;
7339                let f = self.parse_expr()?;
7340                self.expect(Token::RBrace)?;
7341                Ok(PipeOp::Compose(Box::new(f)))
7342            }
7343
7344            // Zip/Join: |⋈{other} or |zip{other}
7345            Some(Token::Bowtie) => {
7346                self.advance();
7347                self.expect(Token::LBrace)?;
7348                let other = self.parse_expr()?;
7349                self.expect(Token::RBrace)?;
7350                Ok(PipeOp::Zip(Box::new(other)))
7351            }
7352
7353            // Scan/Integral: |∫{f} or |scan{f}
7354            Some(Token::Integral) => {
7355                self.advance();
7356                self.expect(Token::LBrace)?;
7357                let f = self.parse_expr()?;
7358                self.expect(Token::RBrace)?;
7359                Ok(PipeOp::Scan(Box::new(f)))
7360            }
7361
7362            // Diff/Derivative: |∂ or |diff
7363            Some(Token::Partial) => {
7364                self.advance();
7365                Ok(PipeOp::Diff)
7366            }
7367
7368            // Gradient: |∇{var} or |grad{var}
7369            Some(Token::Nabla) => {
7370                self.advance();
7371                self.expect(Token::LBrace)?;
7372                let var = self.parse_expr()?;
7373                self.expect(Token::RBrace)?;
7374                Ok(PipeOp::Gradient(Box::new(var)))
7375            }
7376
7377            // Sort Ascending: |⍋ or |sort_asc
7378            Some(Token::GradeUp) => {
7379                self.advance();
7380                Ok(PipeOp::SortAsc)
7381            }
7382
7383            // Sort Descending: |⍒ or |sort_desc
7384            Some(Token::GradeDown) => {
7385                self.advance();
7386                Ok(PipeOp::SortDesc)
7387            }
7388
7389            // Reverse: |⌽ or |rev
7390            Some(Token::Rotate) => {
7391                self.advance();
7392                Ok(PipeOp::Reverse)
7393            }
7394
7395            // Cycle: |↻{n} or |cycle{n}
7396            Some(Token::CycleArrow) => {
7397                self.advance();
7398                self.expect(Token::LBrace)?;
7399                let n = self.parse_expr()?;
7400                self.expect(Token::RBrace)?;
7401                Ok(PipeOp::Cycle(Box::new(n)))
7402            }
7403
7404            // Windows: |⌺{n} or |windows{n}
7405            Some(Token::QuadDiamond) => {
7406                self.advance();
7407                self.expect(Token::LBrace)?;
7408                let n = self.parse_expr()?;
7409                self.expect(Token::RBrace)?;
7410                Ok(PipeOp::Windows(Box::new(n)))
7411            }
7412
7413            // Chunks: |⊞{n} or |chunks{n}
7414            Some(Token::SquaredPlus) => {
7415                self.advance();
7416                self.expect(Token::LBrace)?;
7417                let n = self.parse_expr()?;
7418                self.expect(Token::RBrace)?;
7419                Ok(PipeOp::Chunks(Box::new(n)))
7420            }
7421
7422            // Flatten: |⋳ or |flatten
7423            Some(Token::ElementSmallVerticalBar) => {
7424                self.advance();
7425                Ok(PipeOp::Flatten)
7426            }
7427
7428            // Unique: |∪ or |unique
7429            Some(Token::Union) => {
7430                self.advance();
7431                Ok(PipeOp::Unique)
7432            }
7433
7434            // Enumerate: |⍳ or |enumerate
7435            Some(Token::Iota) => {
7436                self.advance();
7437                Ok(PipeOp::Enumerate)
7438            }
7439
7440            // NOTE: Holographic |◊method and |□method ops are handled earlier
7441            // in the Lozenge/BoxSquare arms (with identifier lookahead).
7442
7443            // Reference expression: |&self.field or |&expr
7444            Some(Token::Amp) => {
7445                // Parse as expression - the & starts a reference expression
7446                let expr = self.parse_prefix_expr()?;
7447                Ok(PipeOp::Call(Box::new(expr)))
7448            }
7449
7450            // Direct closure: |{x => body} or |{|args| body}
7451            // This is a bare pipe-to-closure without morpheme operator
7452            Some(Token::LBrace) => {
7453                self.advance();
7454                self.skip_comments();
7455                let body = if self.looks_like_morpheme_closure() {
7456                    self.parse_morpheme_closure()?
7457                } else {
7458                    self.parse_expr()?
7459                };
7460                self.expect(Token::RBrace)?;
7461                Ok(PipeOp::Call(Box::new(body)))
7462            }
7463
7464            Some(token) => Err(ParseError::UnexpectedToken {
7465                expected: "pipe operation".to_string(),
7466                found: token.clone(),
7467                span: self.current_span(),
7468            }),
7469            None => Err(ParseError::UnexpectedEof),
7470        }
7471    }
7472
7473    /// Check if current position looks like a morpheme closure: ident => or (pattern) =>
7474    fn looks_like_morpheme_closure(&mut self) -> bool {
7475        // Simple closure: x => or _ => (may have evidentiality: x~ => or x◊ =>)
7476        if matches!(self.current_token(), Some(Token::Ident(_)) | Some(Token::Underscore)) {
7477            // Check next token - could be => directly or evidentiality marker first
7478            match self.peek_next() {
7479                Some(Token::FatArrow) => return true,
7480                // Multi-param closure: a, b => expr or a, b, c => expr
7481                // In morpheme context {}, comma-separated idents before => is always a closure
7482                Some(Token::Comma) => return true,
7483                // Evidentiality markers: ident~ =>, ident◊ =>, ident‽ =>
7484                Some(Token::Tilde) | Some(Token::Lozenge) | Some(Token::Interrobang) => {
7485                    // Check if => follows the evidentiality marker
7486                    if matches!(self.peek_n(1), Some(Token::FatArrow)) {
7487                        return true;
7488                    }
7489                }
7490                _ => {}
7491            }
7492        }
7493        // Reference pattern closure: &x => or &mut x =>
7494        if matches!(self.current_token(), Some(Token::Amp)) {
7495            // Look ahead: &x => or &mut x =>
7496            if matches!(self.peek_next(), Some(Token::Ident(_))) {
7497                // Check if token after ident is => (possibly with evidentiality in between)
7498                match self.peek_n(1) {
7499                    Some(Token::FatArrow) => return true,
7500                    Some(Token::Tilde) | Some(Token::Lozenge) | Some(Token::Interrobang) => {
7501                        if matches!(self.peek_n(2), Some(Token::FatArrow)) {
7502                            return true;
7503                        }
7504                    }
7505                    _ => {}
7506                }
7507            } else if matches!(self.peek_next(), Some(Token::Mut)) {
7508                // &mut x =>
7509                return true;
7510            }
7511        }
7512        // Tuple pattern closure: (a, b) =>
7513        // We need to look ahead to find ) followed by =>
7514        if matches!(self.current_token(), Some(Token::LParen)) {
7515            // Look ahead to find closing ) and check for =>
7516            // For simplicity, we'll assume if it starts with ( and contains =>, it's a closure
7517            return true;
7518        }
7519        false
7520    }
7521
7522    /// Parse a morpheme closure: x => expr, (a, b) => expr, &x => expr, or a, b => expr
7523    /// For morphemes, (a, b) is a SINGLE tuple parameter pattern, not multiple parameters
7524    /// Multi-param: a, b => expr creates multiple ClosureParam entries
7525    fn parse_morpheme_closure(&mut self) -> ParseResult<Expr> {
7526        let params = if self.check(&Token::LParen) {
7527            // Tuple pattern: (a, b) => expr - treated as single parameter with tuple pattern
7528            self.advance();
7529            let mut patterns = Vec::new();
7530            while !self.check(&Token::RParen) {
7531                let pat = self.parse_pattern()?;
7532                patterns.push(pat);
7533                if !self.consume_if(&Token::Comma) {
7534                    break;
7535                }
7536            }
7537            self.expect(Token::RParen)?;
7538            // Create a single tuple pattern
7539            vec![ClosureParam { pattern: Pattern::Tuple(patterns), ty: None }]
7540        } else if self.check(&Token::Amp) {
7541            // Reference pattern: &x => expr or &mut x => expr
7542            vec![ClosureParam { pattern: self.parse_pattern()?, ty: None }]
7543        } else if self.check(&Token::Underscore) {
7544            // Wildcard pattern: _ => expr
7545            self.advance();
7546            vec![ClosureParam { pattern: Pattern::Wildcard, ty: None }]
7547        } else {
7548            // Simple pattern: x => expr or multi-param: a, b => expr
7549            let name = self.parse_ident()?;
7550            let first = ClosureParam {
7551                pattern: Pattern::Ident {
7552                    mutable: false,
7553                    name,
7554                    evidentiality: None,
7555                },
7556                ty: None,
7557            };
7558            let mut params = vec![first];
7559            // Check for multi-param: a, b => expr
7560            while self.consume_if(&Token::Comma) {
7561                let name = self.parse_ident()?;
7562                params.push(ClosureParam {
7563                    pattern: Pattern::Ident {
7564                        mutable: false,
7565                        name,
7566                        evidentiality: None,
7567                    },
7568                    ty: None,
7569                });
7570            }
7571            params
7572        };
7573        // Accept either => or | as the arrow (for closure-style syntax)
7574        if !self.consume_if(&Token::FatArrow) {
7575            self.expect(Token::Pipe)?;
7576        }
7577        // Skip comments before body (e.g., // explanation after =>)
7578        self.skip_comments();
7579        // Parse body - can be a single expression or a block of statements
7580        // Multi-line closures have statements + final expression, e.g.:
7581        //   let x = ...;
7582        //   y = some_expr;
7583        //   let z = ...;
7584        //   result_expr
7585        // Or compact form: `expr; final_expr`
7586        let body = {
7587            // Multi-statement body - parse statements until closing brace
7588            let mut stmts = Vec::new();
7589            loop {
7590                self.skip_comments();
7591                if self.check(&Token::RBrace) {
7592                    break;
7593                }
7594                if self.check(&Token::Let) {
7595                    stmts.push(self.parse_let_stmt()?);
7596                } else if self.check(&Token::Return) || self.check(&Token::Tensor)
7597                    || self.check(&Token::CycleArrow)
7598                {
7599                    // Control flow - treat as final expression
7600                    break;
7601                } else {
7602                    // Expression (possibly with assignment) - check if statement or final expr
7603                    let expr = self.parse_expr()?;
7604                    // Skip comments after expression (before deciding if final)
7605                    self.skip_comments();
7606                    if self.consume_if(&Token::Semi) {
7607                        // Expression statement with semicolon
7608                        stmts.push(Stmt::Expr(expr));
7609                    } else if self.check(&Token::RBrace) {
7610                        // Final expression at end of block
7611                        if stmts.is_empty() {
7612                            // Single expression, no block needed
7613                            return Ok(Expr::Closure {
7614                                params: params.clone(),
7615                                return_type: None,
7616                                body: Box::new(expr),
7617                                is_move: false,
7618                            });
7619                        }
7620                        return Ok(Expr::Closure {
7621                            params: params.clone(),
7622                            return_type: None,
7623                            body: Box::new(Expr::Block(Block {
7624                                stmts,
7625                                expr: Some(Box::new(expr)),
7626                            })),
7627                            is_move: false,
7628                        });
7629                    } else {
7630                        // Continue without semicolon (statement with omitted semi)
7631                        // This handles: `expr\n let x = ...`
7632                        stmts.push(Stmt::Expr(expr));
7633                    }
7634                }
7635            }
7636            // No final expression
7637            Expr::Block(Block { stmts, expr: None })
7638        };
7639        Ok(Expr::Closure {
7640            params,
7641            return_type: None,
7642            body: Box::new(body),
7643            is_move: false,
7644        })
7645    }
7646
7647    fn parse_morpheme_kind(&mut self) -> ParseResult<MorphemeKind> {
7648        match self.current_token() {
7649            Some(Token::Tau) => {
7650                self.advance();
7651                Ok(MorphemeKind::Transform)
7652            }
7653            Some(Token::Phi) => {
7654                self.advance();
7655                Ok(MorphemeKind::Filter)
7656            }
7657            Some(Token::Sigma) => {
7658                self.advance();
7659                Ok(MorphemeKind::Sort)
7660            }
7661            Some(Token::Rho) => {
7662                self.advance();
7663                Ok(MorphemeKind::Reduce)
7664            }
7665            Some(Token::Lambda) => {
7666                self.advance();
7667                Ok(MorphemeKind::Lambda)
7668            }
7669            Some(Token::Pi) => {
7670                self.advance();
7671                Ok(MorphemeKind::Product)
7672            }
7673            _ => Err(ParseError::Custom("expected morpheme".to_string())),
7674        }
7675    }
7676
7677    fn parse_block_or_closure(&mut self) -> ParseResult<Expr> {
7678        self.expect(Token::LBrace)?;
7679        self.skip_comments();
7680
7681        // Check for anonymous struct literal: `{ ident: expr, ... }`
7682        // Disambiguate from block by checking if current token is Ident followed by Colon
7683        let is_anon_struct = matches!(self.current_token(), Some(Token::Ident(_)))
7684            && matches!(self.peek_next(), Some(Token::Colon));
7685
7686        if is_anon_struct {
7687            let (fields, rest) = self.parse_struct_fields()?;
7688            self.expect(Token::RBrace)?;
7689            let anon_path = TypePath {
7690                segments: vec![PathSegment {
7691                    ident: Ident {
7692                        name: "__anonymous__".to_string(),
7693                        evidentiality: None,
7694                        affect: None,
7695                        span: Span::new(0, 0),
7696                    },
7697                    generics: None,
7698                }],
7699            };
7700            return Ok(Expr::Struct {
7701                path: anon_path,
7702                fields,
7703                rest,
7704            });
7705        }
7706
7707        // Try to detect closure pattern: `{x => ...}` using lookahead
7708        // We check if current is Ident and next is FatArrow without consuming tokens
7709        let is_simple_closure = matches!(self.current_token(), Some(Token::Ident(_)))
7710            && matches!(self.peek_next(), Some(Token::FatArrow));
7711
7712        if is_simple_closure {
7713            let name = self.parse_ident()?;
7714            self.expect(Token::FatArrow)?;
7715            self.skip_comments();
7716            let body = self.parse_expr()?;
7717            self.skip_comments();
7718            self.expect(Token::RBrace)?;
7719            return Ok(Expr::Closure {
7720                params: vec![ClosureParam {
7721                    pattern: Pattern::Ident {
7722                        mutable: false,
7723                        name,
7724                        evidentiality: None,
7725                    },
7726                    ty: None,
7727                }],
7728                return_type: None,
7729                body: Box::new(body),
7730                is_move: false,
7731            });
7732        }
7733
7734        // Parse as block
7735        let mut stmts = Vec::new();
7736        let mut final_expr = None;
7737
7738        while !self.check(&Token::RBrace) && !self.is_eof() {
7739            self.skip_comments();
7740            if self.check(&Token::RBrace) {
7741                break;
7742            }
7743
7744            // Handle statement-level attributes: #[cfg(...)] { ... } or #[attr] let x = ...
7745            if self.check(&Token::Hash) || self.check(&Token::At) {
7746                // Parse and collect attributes
7747                let mut attrs = Vec::new();
7748                while self.check(&Token::Hash) || self.check(&Token::At) {
7749                    attrs.push(self.parse_outer_attribute()?);
7750                    self.skip_comments();
7751                }
7752
7753                // Check cfg conditions - skip statement if cfg evaluates to false
7754                if !self.evaluate_cfg_condition(&attrs) {
7755                    // Skip the following statement/expression
7756                    if self.is_item_start() {
7757                        let _ = self.parse_item()?; // Parse but discard
7758                    } else if self.check(&Token::Let) {
7759                        let _ = self.parse_let_stmt()?; // Parse but discard
7760                    } else {
7761                        let _ = self.parse_expr()?; // Parse but discard
7762                        self.skip_comments();
7763                        self.consume_if(&Token::Semi); // Consume trailing semicolon if present
7764                    }
7765                    continue; // Skip adding to stmts
7766                }
7767
7768                // After attributes, check what follows
7769                if self.is_item_start() {
7770                    // Item with attributes - parse as item
7771                    let item = self.parse_item()?;
7772                    stmts.push(Stmt::Item(Box::new(item.node)));
7773                } else if self.check(&Token::Let) {
7774                    // Let statement with attributes
7775                    stmts.push(self.parse_let_stmt()?);
7776                } else {
7777                    // Expression with attributes (like #[cfg(...)] { block })
7778                    let expr = self.parse_expr()?;
7779                    self.skip_comments();
7780                    if self.consume_if(&Token::Semi) {
7781                        stmts.push(Stmt::Semi(expr));
7782                    } else if self.check(&Token::RBrace) {
7783                        final_expr = Some(Box::new(expr));
7784                    } else {
7785                        stmts.push(Stmt::Expr(expr));
7786                    }
7787                }
7788            } else if self.is_item_start() {
7789                let item = self.parse_item()?;
7790                stmts.push(Stmt::Item(Box::new(item.node)));
7791            } else if self.check(&Token::Let) {
7792                stmts.push(self.parse_let_stmt()?);
7793            } else {
7794                let expr = self.parse_expr()?;
7795                self.skip_comments();
7796                if self.consume_if(&Token::Semi) {
7797                    stmts.push(Stmt::Semi(expr));
7798                } else if self.check(&Token::RBrace) {
7799                    final_expr = Some(Box::new(expr));
7800                } else {
7801                    stmts.push(Stmt::Expr(expr));
7802                }
7803            }
7804        }
7805
7806        self.expect(Token::RBrace)?;
7807
7808        Ok(Expr::Block(Block {
7809            stmts,
7810            expr: final_expr,
7811        }))
7812    }
7813
7814    pub(crate) fn parse_block(&mut self) -> ParseResult<Block> {
7815        match self.parse_block_or_closure()? {
7816            Expr::Block(block) => Ok(block),
7817            _ => Err(ParseError::Custom("expected block".to_string())),
7818        }
7819    }
7820
7821    fn parse_let_stmt(&mut self) -> ParseResult<Stmt> {
7822        self.expect(Token::Let)?;
7823        let pattern = self.parse_pattern()?;
7824        let ty = if self.consume_if(&Token::Colon) {
7825            Some(self.parse_type()?)
7826        } else {
7827            None
7828        };
7829        let init = if self.consume_if(&Token::Eq) {
7830            Some(self.parse_expr()?)
7831        } else {
7832            None
7833        };
7834
7835        // Check for let-else pattern: let PATTERN = EXPR else { ... }
7836        if self.consume_if(&Token::Else) {
7837            let else_branch = Box::new(Expr::Block(self.parse_block()?));
7838            // Optionally consume trailing semicolon (valid in Rust: `let ... else { ... };`)
7839            self.consume_if(&Token::Semi);
7840            Ok(Stmt::LetElse {
7841                pattern,
7842                ty,
7843                init: init.ok_or_else(|| ParseError::Custom("let-else requires initializer".to_string()))?,
7844                else_branch,
7845            })
7846        } else {
7847            // Semicolon is optional in Sigil's advanced syntax
7848            // Consume if present, or allow if next token can start a new statement
7849            if !self.consume_if(&Token::Semi) {
7850                if !self.can_start_stmt() && !self.check(&Token::RBrace) {
7851                    // Check for deprecated Rust syntax first
7852                    self.check_deprecated()?;
7853                    return Err(ParseError::UnexpectedToken {
7854                        expected: "`;` or new statement".to_string(),
7855                        found: self.current_token().cloned().unwrap_or(Token::Semi),
7856                        span: self.current_span(),
7857                    });
7858                }
7859            }
7860            Ok(Stmt::Let { pattern, ty, init })
7861        }
7862    }
7863
7864    fn parse_if_expr(&mut self) -> ParseResult<Expr> {
7865        self.expect(Token::If)?;
7866
7867        // Check for if let pattern = expr form
7868        let condition = if self.consume_if(&Token::Let) {
7869            let pattern = self.parse_or_pattern()?;
7870            self.expect(Token::Eq)?;
7871            let expr = self.parse_condition()?;
7872            Expr::Let {
7873                pattern,
7874                value: Box::new(expr),
7875            }
7876        } else {
7877            self.parse_condition()?
7878        };
7879
7880        let then_branch = self.parse_block()?;
7881        self.skip_comments(); // Skip comments before else
7882        let else_branch = if self.consume_if(&Token::Else) {
7883            if self.check(&Token::If) {
7884                Some(Box::new(self.parse_if_expr()?))
7885            } else {
7886                Some(Box::new(Expr::Block(self.parse_block()?)))
7887            }
7888        } else {
7889            None
7890        };
7891
7892        Ok(Expr::If {
7893            condition: Box::new(condition),
7894            then_branch,
7895            else_branch,
7896        })
7897    }
7898
7899    fn parse_match_expr(&mut self) -> ParseResult<Expr> {
7900        self.expect(Token::Match)?;
7901        // Use parse_condition to prevent { from being parsed as struct literal
7902        let expr = self.parse_condition()?;
7903        self.expect(Token::LBrace)?;
7904
7905        let mut arms = Vec::new();
7906        while !self.check(&Token::RBrace) && !self.is_eof() {
7907            // Skip comments and attributes before match arms: #[cfg(...)]
7908            loop {
7909                if matches!(
7910                    self.current_token(),
7911                    Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
7912                ) {
7913                    self.advance();
7914                } else if self.check(&Token::Hash) {
7915                    // Skip attribute: #[...]
7916                    self.skip_attribute()?;
7917                } else {
7918                    break;
7919                }
7920            }
7921            if self.check(&Token::RBrace) {
7922                break;
7923            }
7924            let pattern = self.parse_or_pattern()?;
7925            let guard = if self.consume_if(&Token::If) {
7926                Some(self.parse_condition()?)
7927            } else {
7928                None
7929            };
7930            self.expect(Token::FatArrow)?;
7931            let body = self.parse_expr()?;
7932            arms.push(MatchArm {
7933                pattern,
7934                guard,
7935                body,
7936            });
7937            // In Rust/Sigil, commas are optional after block-bodied match arms
7938            // So we try to consume a comma, but don't break if absent
7939            self.consume_if(&Token::Comma);
7940            // Skip trailing comments after comma or block
7941            while matches!(
7942                self.current_token(),
7943                Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
7944            ) {
7945                self.advance();
7946            }
7947        }
7948
7949        self.expect(Token::RBrace)?;
7950
7951        Ok(Expr::Match {
7952            expr: Box::new(expr),
7953            arms,
7954        })
7955    }
7956
7957    // === Pattern parsing ===
7958
7959    /// Parse a pattern, handling or-patterns: pat1 | pat2 | pat3
7960    fn parse_or_pattern(&mut self) -> ParseResult<Pattern> {
7961        let first = self.parse_pattern()?;
7962
7963        // Check for | to form or-pattern
7964        if self.check(&Token::Pipe) {
7965            let mut patterns = vec![first];
7966            while self.consume_if(&Token::Pipe) {
7967                patterns.push(self.parse_pattern()?);
7968            }
7969            Ok(Pattern::Or(patterns))
7970        } else {
7971            Ok(first)
7972        }
7973    }
7974
7975    fn parse_pattern(&mut self) -> ParseResult<Pattern> {
7976        // Check for prefix evidentiality markers: ?pattern, !pattern, ~pattern, ◊pattern, ‽pattern
7977        let prefix_ev = match self.current_token() {
7978            Some(Token::Question) => {
7979                self.advance();
7980                Some(Evidentiality::Uncertain)
7981            }
7982            Some(Token::Bang) => {
7983                self.advance();
7984                Some(Evidentiality::Known)
7985            }
7986            Some(Token::Tilde) => {
7987                self.advance();
7988                Some(Evidentiality::Reported)
7989            }
7990            Some(Token::Lozenge) => {
7991                self.advance();
7992                Some(Evidentiality::Predicted)
7993            }
7994            Some(Token::Interrobang) => {
7995                self.advance();
7996                Some(Evidentiality::Paradox)
7997            }
7998            _ => None,
7999        };
8000
8001        // If we had a prefix evidentiality, parse the rest of the pattern
8002        // This handles patterns like `?Some(x)` or `?TypeExpr::Variant { .. }`
8003        if let Some(ev) = prefix_ev {
8004            // Parse the inner pattern and wrap it with evidentiality
8005            let inner_pattern = self.parse_pattern_base()?;
8006            return match inner_pattern {
8007                Pattern::Ident { mutable, name, evidentiality: _ } => {
8008                    // Simple identifier pattern with evidentiality
8009                    Ok(Pattern::Ident {
8010                        mutable,
8011                        name,
8012                        evidentiality: Some(ev),
8013                    })
8014                }
8015                Pattern::Wildcard => {
8016                    // Convert ?_ to Pattern::Ident with name="_" and evidentiality
8017                    // This ensures the interpreter can distinguish ?_ from plain _
8018                    let span = self.current_span();
8019                    Ok(Pattern::Ident {
8020                        mutable: false,
8021                        name: Ident {
8022                            name: "_".to_string(),
8023                            evidentiality: None,
8024                            affect: None,
8025                            span,
8026                        },
8027                        evidentiality: Some(ev),
8028                    })
8029                }
8030                other => {
8031                    // For complex patterns like enum variants, wrap in an Evidential pattern
8032                    // Note: This might need adjustment based on AST capabilities
8033                    // For now, we'll add evidentiality to identifier-based patterns
8034                    // and pass through complex patterns as-is (the `?` means "if Some")
8035                    Ok(other)
8036                }
8037            };
8038        }
8039
8040        self.parse_pattern_base()
8041    }
8042
8043    /// Parse a pattern without considering prefix evidentiality markers
8044    fn parse_pattern_base(&mut self) -> ParseResult<Pattern> {
8045
8046        match self.current_token().cloned() {
8047            Some(Token::Underscore) => {
8048                let span = self.current_span();
8049                self.advance();
8050                // Check for postfix evidentiality: _!
8051                let ev = self.parse_evidentiality_opt();
8052                if ev.is_some() {
8053                    // Convert _! to Pattern::Ident with name="_" and evidentiality
8054                    Ok(Pattern::Ident {
8055                        mutable: false,
8056                        name: Ident {
8057                            name: "_".to_string(),
8058                            evidentiality: None,
8059                            affect: None,
8060                            span,
8061                        },
8062                        evidentiality: ev,
8063                    })
8064                } else {
8065                    Ok(Pattern::Wildcard)
8066                }
8067            }
8068            Some(Token::DotDot) => {
8069                self.advance();
8070                Ok(Pattern::Rest)
8071            }
8072            Some(Token::Mut) => {
8073                self.advance();
8074                // Handle `mut self` specially
8075                let name = if self.check(&Token::SelfLower) {
8076                    let span = self.current_span();
8077                    self.advance();
8078                    Ident {
8079                        name: "self".to_string(),
8080                        evidentiality: None,
8081                        affect: None,
8082                        span,
8083                    }
8084                } else {
8085                    self.parse_ident()?
8086                };
8087                let evidentiality = self.parse_evidentiality_opt();
8088                Ok(Pattern::Ident {
8089                    mutable: true,
8090                    name,
8091                    evidentiality,
8092                })
8093            }
8094            // Ref pattern: ref ident or ref mut ident (binds by reference)
8095            Some(Token::Ref) => {
8096                self.advance();
8097                let mutable = self.consume_if(&Token::Mut);
8098                let name = self.parse_ident()?;
8099                let evidentiality = self.parse_evidentiality_opt();
8100                Ok(Pattern::RefBinding {
8101                    mutable,
8102                    name,
8103                    evidentiality,
8104                })
8105            }
8106            // Reference pattern: &pattern, &mut pattern, &'a pattern, &'a mut pattern
8107            Some(Token::Amp) => {
8108                self.advance();
8109                // Skip optional lifetime annotation in patterns (e.g., &'a self)
8110                if matches!(self.current_token(), Some(Token::Lifetime(_))) {
8111                    self.advance();
8112                }
8113                let mutable = self.consume_if(&Token::Mut);
8114                let inner = self.parse_pattern()?;
8115                Ok(Pattern::Ref {
8116                    mutable,
8117                    pattern: Box::new(inner),
8118                })
8119            }
8120            // Double reference pattern: &&pattern (lexer tokenizes && as AndAnd)
8121            Some(Token::AndAnd) => {
8122                self.advance();
8123                let inner = self.parse_pattern()?;
8124                // Desugar &&x to &(&x)
8125                let inner_ref = Pattern::Ref {
8126                    mutable: false,
8127                    pattern: Box::new(inner),
8128                };
8129                Ok(Pattern::Ref {
8130                    mutable: false,
8131                    pattern: Box::new(inner_ref),
8132                })
8133            }
8134            Some(Token::LParen) => {
8135                self.advance();
8136                let mut patterns = Vec::new();
8137                while !self.check(&Token::RParen) {
8138                    patterns.push(self.parse_pattern()?);
8139                    if !self.consume_if(&Token::Comma) {
8140                        break;
8141                    }
8142                }
8143                self.expect(Token::RParen)?;
8144                // Check for postfix evidentiality on tuple pattern: (a, b)!
8145                let _ev = self.parse_evidentiality_opt();
8146                // Note: Pattern::Tuple doesn't have evidentiality field, so we just consume it
8147                // This allows the let statement to parse correctly
8148                Ok(Pattern::Tuple(patterns))
8149            }
8150            Some(Token::LBracket) => {
8151                self.advance();
8152                let mut patterns = Vec::new();
8153                while !self.check(&Token::RBracket) {
8154                    patterns.push(self.parse_pattern()?);
8155                    if !self.consume_if(&Token::Comma) {
8156                        break;
8157                    }
8158                }
8159                self.expect(Token::RBracket)?;
8160                Ok(Pattern::Slice(patterns))
8161            }
8162            Some(Token::IntLit(_))
8163            | Some(Token::HexLit(_))
8164            | Some(Token::OctalLit(_))
8165            | Some(Token::BinaryLit(_))
8166            | Some(Token::FloatLit(_))
8167            | Some(Token::StringLit(_))
8168            | Some(Token::CharLit(_))
8169            | Some(Token::True)
8170            | Some(Token::False)
8171            | Some(Token::Null) => {
8172                let lit = self.parse_literal()?;
8173                // Check for range pattern: lit..end or lit..=end
8174                if self.check(&Token::DotDot) || self.check(&Token::DotDotEq) {
8175                    let inclusive = self.consume_if(&Token::DotDotEq);
8176                    if !inclusive {
8177                        self.advance(); // consume ..
8178                    }
8179                    // Parse end of range if present
8180                    let end = if matches!(
8181                        self.current_token(),
8182                        Some(Token::IntLit(_)) | Some(Token::HexLit(_)) | Some(Token::OctalLit(_))
8183                            | Some(Token::BinaryLit(_)) | Some(Token::CharLit(_))
8184                    ) {
8185                        let end_lit = self.parse_literal()?;
8186                        Some(Box::new(Pattern::Literal(end_lit)))
8187                    } else {
8188                        None
8189                    };
8190                    Ok(Pattern::Range {
8191                        start: Some(Box::new(Pattern::Literal(lit))),
8192                        end,
8193                        inclusive,
8194                    })
8195                } else {
8196                    Ok(Pattern::Literal(lit))
8197                }
8198            }
8199            // Handle Self as a pattern (e.g., Self { field1 }, Self::Variant)
8200            Some(Token::SelfUpper) => {
8201                let span = self.current_span();
8202                self.advance();
8203
8204                // Build a path starting with "Self"
8205                let mut segments = vec![PathSegment {
8206                    ident: Ident {
8207                        name: "Self".to_string(),
8208                        evidentiality: None,
8209                        affect: None,
8210                        span,
8211                    },
8212                    generics: None,
8213                }];
8214
8215                // Check for path continuation: Self::Variant or Self::Variant::SubVariant
8216                while self.consume_if(&Token::MiddleDot) || self.consume_if(&Token::MiddleDot) {
8217                    let segment_name = self.parse_ident()?;
8218                    segments.push(PathSegment {
8219                        ident: segment_name,
8220                        generics: None,
8221                    });
8222                }
8223
8224                let path = TypePath { segments };
8225
8226                // Check for tuple destructuring: Self(x, y) or Self::Variant(x, y)
8227                if self.check(&Token::LParen) {
8228                    self.advance();
8229                    let mut fields = Vec::new();
8230                    while !self.check(&Token::RParen) {
8231                        fields.push(self.parse_pattern()?);
8232                        if !self.consume_if(&Token::Comma) {
8233                            break;
8234                        }
8235                    }
8236                    self.expect(Token::RParen)?;
8237                    return Ok(Pattern::TupleStruct { path, fields });
8238                }
8239
8240                // Check for struct destructuring: Self { field: x } or Self::Variant { field }
8241                if self.check(&Token::LBrace) {
8242                    self.advance();
8243                    let mut fields = Vec::new();
8244                    let mut rest = false;
8245                    while !self.check(&Token::RBrace) {
8246                        while matches!(
8247                            self.current_token(),
8248                            Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
8249                        ) {
8250                            self.advance();
8251                        }
8252                        if self.check(&Token::RBrace) {
8253                            break;
8254                        }
8255                        if self.consume_if(&Token::DotDot) {
8256                            rest = true;
8257                            if !self.consume_if(&Token::Comma) {
8258                                break;
8259                            }
8260                            continue;
8261                        }
8262                        // Handle binding mode (ref, ref mut/Δ) in struct patterns: { ref x } or { ref Δ x }
8263                        let has_ref = self.consume_if(&Token::Ref);
8264                        let has_mut = has_ref && self.consume_if(&Token::Mut);
8265
8266                        let field_name = self.parse_ident()?;
8267                        let pattern = if self.consume_if(&Token::Colon) {
8268                            Some(self.parse_pattern()?)
8269                        } else if has_ref {
8270                            // Shorthand with binding mode: { ref x } means field x bound by ref
8271                            Some(Pattern::RefBinding {
8272                                mutable: has_mut,
8273                                name: field_name.clone(),
8274                                evidentiality: None,
8275                            })
8276                        } else {
8277                            None
8278                        };
8279                        fields.push(FieldPattern {
8280                            name: field_name,
8281                            pattern,
8282                        });
8283                        if !self.consume_if(&Token::Comma) {
8284                            break;
8285                        }
8286                    }
8287                    self.expect(Token::RBrace)?;
8288                    return Ok(Pattern::Struct { path, fields, rest });
8289                }
8290
8291                // Just Self or Self::Variant as a unit pattern
8292                return Ok(Pattern::Path(path));
8293            }
8294            // Handle crate::, self::, super:: path patterns
8295            Some(Token::Crate) | Some(Token::SelfLower) | Some(Token::Super) => {
8296                let keyword = self.current_token().cloned();
8297                let span = self.current_span();
8298                self.advance();
8299
8300                // These must be followed by :: for a path pattern
8301                if !self.consume_if(&Token::MiddleDot) && !self.consume_if(&Token::MiddleDot) {
8302                    // Just `self` as an identifier pattern
8303                    if matches!(keyword, Some(Token::SelfLower)) {
8304                        return Ok(Pattern::Ident {
8305                            mutable: false,
8306                            name: Ident {
8307                                name: "self".to_string(),
8308                                evidentiality: None,
8309                                affect: None,
8310                                span,
8311                            },
8312                            evidentiality: self.parse_evidentiality_opt(),
8313                        });
8314                    }
8315                    return Err(ParseError::Custom("expected :: after crate/super in path pattern".to_string()));
8316                }
8317
8318                // Build the path starting with tome/self/super
8319                // Note: Sigil uses "tome" instead of Rust's "crate"
8320                let keyword_name = match keyword {
8321                    Some(Token::Crate) => "tome",
8322                    Some(Token::SelfLower) => "self",
8323                    Some(Token::Super) => "super",
8324                    _ => unreachable!(),
8325                };
8326                let mut segments = vec![PathSegment {
8327                    ident: Ident {
8328                        name: keyword_name.to_string(),
8329                        evidentiality: None,
8330                        affect: None,
8331                        span,
8332                    },
8333                    generics: None,
8334                }];
8335
8336                // Parse remaining path segments
8337                loop {
8338                    let segment_name = self.parse_ident()?;
8339                    segments.push(PathSegment {
8340                        ident: segment_name,
8341                        generics: None,
8342                    });
8343
8344                    if !self.consume_if(&Token::MiddleDot) && !self.consume_if(&Token::MiddleDot) {
8345                        break;
8346                    }
8347                }
8348
8349                let path = TypePath { segments };
8350
8351                // Check for tuple destructuring: crate::module::Variant(x)
8352                if self.check(&Token::LParen) {
8353                    self.advance();
8354                    let mut fields = Vec::new();
8355                    while !self.check(&Token::RParen) {
8356                        fields.push(self.parse_pattern()?);
8357                        if !self.consume_if(&Token::Comma) {
8358                            break;
8359                        }
8360                    }
8361                    self.expect(Token::RParen)?;
8362                    return Ok(Pattern::TupleStruct { path, fields });
8363                }
8364
8365                // Check for struct destructuring: crate::module::Variant { field: x }
8366                if self.check(&Token::LBrace) {
8367                    self.advance();
8368                    let mut fields = Vec::new();
8369                    let mut rest = false;
8370                    while !self.check(&Token::RBrace) {
8371                        while matches!(
8372                            self.current_token(),
8373                            Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
8374                        ) {
8375                            self.advance();
8376                        }
8377                        if self.check(&Token::RBrace) {
8378                            break;
8379                        }
8380                        if self.consume_if(&Token::DotDot) {
8381                            rest = true;
8382                            if !self.consume_if(&Token::Comma) {
8383                                break;
8384                            }
8385                            continue;
8386                        }
8387                        // Handle binding mode (ref, ref mut/Δ) in struct patterns
8388                        let has_ref = self.consume_if(&Token::Ref);
8389                        let has_mut = has_ref && self.consume_if(&Token::Mut);
8390
8391                        let field_name = self.parse_ident()?;
8392                        let pattern = if self.consume_if(&Token::Colon) {
8393                            Some(self.parse_pattern()?)
8394                        } else if has_ref {
8395                            Some(Pattern::RefBinding {
8396                                mutable: has_mut,
8397                                name: field_name.clone(),
8398                                evidentiality: None,
8399                            })
8400                        } else {
8401                            None
8402                        };
8403                        fields.push(FieldPattern {
8404                            name: field_name,
8405                            pattern,
8406                        });
8407                        if !self.consume_if(&Token::Comma) {
8408                            break;
8409                        }
8410                    }
8411                    self.expect(Token::RBrace)?;
8412                    return Ok(Pattern::Struct { path, fields, rest });
8413                }
8414
8415                // Just a path pattern (unit variant)
8416                return Ok(Pattern::Path(path));
8417            }
8418            Some(Token::Ident(_)) => {
8419                let name = self.parse_ident()?;
8420
8421                // Check for path continuation :: to form qualified path (e.g., Token::Fn)
8422                if self.consume_if(&Token::MiddleDot) || self.consume_if(&Token::MiddleDot) {
8423                    // Build a path pattern
8424                    let mut segments = vec![PathSegment {
8425                        ident: name,
8426                        generics: None,
8427                    }];
8428
8429                    // Parse remaining path segments
8430                    loop {
8431                        let segment_name = self.parse_ident()?;
8432                        segments.push(PathSegment {
8433                            ident: segment_name,
8434                            generics: None,
8435                        });
8436
8437                        if !self.consume_if(&Token::MiddleDot) && !self.consume_if(&Token::MiddleDot) {
8438                            break;
8439                        }
8440                    }
8441
8442                    let path = TypePath { segments };
8443
8444                    // Check for tuple destructuring: Token::IntLit(x)
8445                    if self.check(&Token::LParen) {
8446                        self.advance();
8447                        let mut fields = Vec::new();
8448                        while !self.check(&Token::RParen) {
8449                            fields.push(self.parse_pattern()?);
8450                            if !self.consume_if(&Token::Comma) {
8451                                break;
8452                            }
8453                        }
8454                        self.expect(Token::RParen)?;
8455                        return Ok(Pattern::TupleStruct { path, fields });
8456                    }
8457
8458                    // Check for struct destructuring: Token::SomeVariant { field: x }
8459                    if self.check(&Token::LBrace) {
8460                        self.advance();
8461                        let mut fields = Vec::new();
8462                        let mut rest = false;
8463                        while !self.check(&Token::RBrace) {
8464                            // Skip comments
8465                            while matches!(
8466                                self.current_token(),
8467                                Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
8468                            ) {
8469                                self.advance();
8470                            }
8471                            if self.check(&Token::RBrace) {
8472                                break;
8473                            }
8474
8475                            // Check for rest pattern: ..
8476                            if self.consume_if(&Token::DotDot) {
8477                                rest = true;
8478                                if !self.consume_if(&Token::Comma) {
8479                                    break;
8480                                }
8481                                continue;
8482                            }
8483
8484                            // Handle binding mode (ref, ref mut/Δ) in struct patterns
8485                            let has_ref = self.consume_if(&Token::Ref);
8486                            let has_mut = has_ref && self.consume_if(&Token::Mut);
8487
8488                            let field_name = self.parse_ident()?;
8489                            let pattern = if self.consume_if(&Token::Colon) {
8490                                Some(self.parse_pattern()?)
8491                            } else if has_ref {
8492                                Some(Pattern::RefBinding {
8493                                    mutable: has_mut,
8494                                    name: field_name.clone(),
8495                                    evidentiality: None,
8496                                })
8497                            } else {
8498                                // Shorthand: field punning
8499                                None
8500                            };
8501                            fields.push(FieldPattern {
8502                                name: field_name,
8503                                pattern,
8504                            });
8505
8506                            if !self.consume_if(&Token::Comma) {
8507                                break;
8508                            }
8509                        }
8510                        self.expect(Token::RBrace)?;
8511                        return Ok(Pattern::Struct { path, fields, rest });
8512                    }
8513
8514                    // Just a path pattern (unit variant)
8515                    return Ok(Pattern::Path(path));
8516                }
8517
8518                // Check for struct pattern with simple identifier: Foo { ... }
8519                if self.check(&Token::LBrace) {
8520                    // Single-segment path for struct pattern
8521                    let path = TypePath {
8522                        segments: vec![PathSegment {
8523                            ident: name,
8524                            generics: None,
8525                        }],
8526                    };
8527                    self.advance();
8528                    let mut fields = Vec::new();
8529                    let mut rest = false;
8530                    while !self.check(&Token::RBrace) {
8531                        while matches!(
8532                            self.current_token(),
8533                            Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
8534                        ) {
8535                            self.advance();
8536                        }
8537                        if self.check(&Token::RBrace) {
8538                            break;
8539                        }
8540                        if self.consume_if(&Token::DotDot) {
8541                            rest = true;
8542                            break;
8543                        }
8544                        // Handle binding mode (ref, ref mut/Δ) in struct patterns
8545                        let has_ref = self.consume_if(&Token::Ref);
8546                        let has_mut = has_ref && self.consume_if(&Token::Mut);
8547
8548                        let field_name = self.parse_ident()?;
8549                        let pattern = if self.consume_if(&Token::Colon) {
8550                            Some(self.parse_pattern()?)
8551                        } else if has_ref {
8552                            Some(Pattern::RefBinding {
8553                                mutable: has_mut,
8554                                name: field_name.clone(),
8555                                evidentiality: None,
8556                            })
8557                        } else {
8558                            None
8559                        };
8560                        fields.push(FieldPattern {
8561                            name: field_name,
8562                            pattern,
8563                        });
8564                        if !self.consume_if(&Token::Comma) {
8565                            break;
8566                        }
8567                    }
8568                    self.expect(Token::RBrace)?;
8569                    return Ok(Pattern::Struct { path, fields, rest });
8570                }
8571
8572                // Check for tuple struct pattern with simple identifier: Foo(x, y)
8573                if self.check(&Token::LParen) {
8574                    let path = TypePath {
8575                        segments: vec![PathSegment {
8576                            ident: name,
8577                            generics: None,
8578                        }],
8579                    };
8580                    self.advance();
8581                    let mut fields = Vec::new();
8582                    while !self.check(&Token::RParen) {
8583                        fields.push(self.parse_pattern()?);
8584                        if !self.consume_if(&Token::Comma) {
8585                            break;
8586                        }
8587                    }
8588                    self.expect(Token::RParen)?;
8589                    return Ok(Pattern::TupleStruct { path, fields });
8590                }
8591
8592                // Simple identifier pattern
8593                let evidentiality = self.parse_evidentiality_opt();
8594                Ok(Pattern::Ident {
8595                    mutable: false,
8596                    name,
8597                    evidentiality,
8598                })
8599            }
8600            Some(Token::SelfLower) => {
8601                // self keyword as pattern in method parameters
8602                let span = self.current_span();
8603                self.advance();
8604                Ok(Pattern::Ident {
8605                    mutable: false,
8606                    name: Ident {
8607                        name: "self".to_string(),
8608                        evidentiality: None,
8609                        affect: None,
8610                        span,
8611                    },
8612                    evidentiality: None,
8613                })
8614            }
8615            // Handle contextual keywords as identifiers in patterns
8616            Some(ref token) if Self::keyword_as_ident(token).is_some() => {
8617                let name = self.parse_ident()?;
8618                let evidentiality = self.parse_evidentiality_opt();
8619                Ok(Pattern::Ident {
8620                    mutable: false,
8621                    name,
8622                    evidentiality,
8623                })
8624            }
8625            Some(token) => Err(ParseError::UnexpectedToken {
8626                expected: "pattern".to_string(),
8627                found: token,
8628                span: self.current_span(),
8629            }),
8630            None => Err(ParseError::UnexpectedEof),
8631        }
8632    }
8633
8634    fn parse_literal(&mut self) -> ParseResult<Literal> {
8635        match self.current_token().cloned() {
8636            Some(Token::IntLit(s)) => {
8637                self.advance();
8638                Ok(Literal::Int {
8639                    value: s,
8640                    base: NumBase::Decimal,
8641                    suffix: None,
8642                })
8643            }
8644            Some(Token::HexLit(s)) => {
8645                self.advance();
8646                Ok(Literal::Int {
8647                    value: s,
8648                    base: NumBase::Hex,
8649                    suffix: None,
8650                })
8651            }
8652            Some(Token::OctalLit(s)) => {
8653                self.advance();
8654                Ok(Literal::Int {
8655                    value: s,
8656                    base: NumBase::Octal,
8657                    suffix: None,
8658                })
8659            }
8660            Some(Token::BinaryLit(s)) => {
8661                self.advance();
8662                Ok(Literal::Int {
8663                    value: s,
8664                    base: NumBase::Binary,
8665                    suffix: None,
8666                })
8667            }
8668            Some(Token::FloatLit(s)) => {
8669                self.advance();
8670                let (value, suffix) = Self::strip_float_suffix(&s);
8671                Ok(Literal::Float { value, suffix })
8672            }
8673            Some(Token::StringLit(s)) => {
8674                self.advance();
8675                Ok(Literal::String(s))
8676            }
8677            Some(Token::CharLit(c)) => {
8678                self.advance();
8679                Ok(Literal::Char(c))
8680            }
8681            Some(Token::True) => {
8682                self.advance();
8683                Ok(Literal::Bool(true))
8684            }
8685            Some(Token::False) => {
8686                self.advance();
8687                Ok(Literal::Bool(false))
8688            }
8689            Some(Token::Null) => {
8690                self.advance();
8691                Ok(Literal::Null)
8692            }
8693            _ => Err(ParseError::Custom("expected literal".to_string())),
8694        }
8695    }
8696
8697    // === Helpers ===
8698
8699    /// Convert an expression to an IncorporationSegment for polysynthetic chains
8700    /// E.g., `path` in `path·file·read` becomes IncorporationSegment { name: "path", args: None }
8701    fn expr_to_incorporation_segment(&self, expr: Expr) -> ParseResult<IncorporationSegment> {
8702        match expr {
8703            Expr::Path(path) if path.segments.len() == 1 => Ok(IncorporationSegment {
8704                name: path.segments[0].ident.clone(),
8705                args: None,
8706            }),
8707            Expr::Call { func, args } => {
8708                match *func {
8709                    Expr::Path(path) => {
8710                        // For paths like `use_context[T]()` or `serde_json::from_value(s)`,
8711                        // use the last segment as the incorporation name
8712                        if let Some(last_seg) = path.segments.last() {
8713                            return Ok(IncorporationSegment {
8714                                name: last_seg.ident.clone(),
8715                                args: Some(args),
8716                            });
8717                        }
8718                        Err(ParseError::Custom(
8719                            "incorporation chain: empty path".to_string(),
8720                        ))
8721                    }
8722                    // Handle method calls like obj.method()·chain
8723                    Expr::Field { expr, field } => {
8724                        Ok(IncorporationSegment {
8725                            name: field.clone(),
8726                            args: Some(std::iter::once(*expr).chain(args).collect()),
8727                        })
8728                    }
8729                    _ => Err(ParseError::Custom(
8730                        "incorporation chain must start with identifier or call".to_string(),
8731                    )),
8732                }
8733            }
8734            // Field access can start an incorporation chain: ctx.navigate·clone()
8735            // We keep the field name and store the object expression as an argument
8736            Expr::Field { expr, field } => {
8737                // Use the field name directly, and store the base object as an argument
8738                // so the interpreter can reconstruct the field access
8739                Ok(IncorporationSegment {
8740                    name: field.clone(),
8741                    args: Some(vec![*expr]), // The object becomes the implicit "self" argument
8742                })
8743            }
8744            // For literals like "string"·to_string(), use a synthetic "__lit__" segment
8745            // The literal itself becomes the argument
8746            Expr::Literal(_) => {
8747                Ok(IncorporationSegment {
8748                    name: Ident {
8749                        name: "__lit__".to_string(),
8750                        evidentiality: None,
8751                        affect: None,
8752                        span: crate::span::Span::default(),
8753                    },
8754                    args: Some(vec![expr]),
8755                })
8756            }
8757            // For unary expressions like *self.field·method(), use a synthetic segment
8758            // The unary expression becomes the argument
8759            Expr::Unary { .. } => {
8760                Ok(IncorporationSegment {
8761                    name: Ident {
8762                        name: "__unary__".to_string(),
8763                        evidentiality: None,
8764                        affect: None,
8765                        span: crate::span::Span::default(),
8766                    },
8767                    args: Some(vec![expr]),
8768                })
8769            }
8770            // For index expressions like arr[i]·method()
8771            Expr::Index { expr: base, index } => {
8772                Ok(IncorporationSegment {
8773                    name: Ident {
8774                        name: "__index__".to_string(),
8775                        evidentiality: None,
8776                        affect: None,
8777                        span: crate::span::Span::default(),
8778                    },
8779                    args: Some(vec![*base, *index]),
8780                })
8781            }
8782            // For any other expression types (if, match, block, closure, etc.)
8783            // Use a synthetic segment to hold the expression as the receiver
8784            other => {
8785                Ok(IncorporationSegment {
8786                    name: Ident {
8787                        name: "__expr__".to_string(),
8788                        evidentiality: None,
8789                        affect: None,
8790                        span: crate::span::Span::default(),
8791                    },
8792                    args: Some(vec![other]),
8793                })
8794            }
8795        }
8796    }
8797
8798    /// Convert a keyword token to its string name for contextual use as identifier
8799    fn keyword_as_ident(token: &Token) -> Option<&'static str> {
8800        match token {
8801            // Common keywords that may be used as field/variable names
8802            Token::Packed => Some("packed"),
8803            Token::As => Some("as"),
8804            Token::Type => Some("type"),
8805            Token::Crate => Some("tome"),
8806            Token::Super => Some("super"),
8807            Token::Mod => Some("scroll"),
8808            Token::Use => Some("invoke"),
8809            Token::Pub => Some("pub"),
8810            Token::Const => Some("const"),
8811            Token::Static => Some("static"),
8812            Token::Extern => Some("extern"),
8813            Token::Unsafe => Some("unsafe"),
8814            Token::Async => Some("async"),
8815            Token::Await => Some("await"),
8816            Token::Move => Some("move"),
8817            Token::Dyn => Some("dyn"),
8818            Token::Atomic => Some("atomic"),
8819            Token::Volatile => Some("volatile"),
8820            Token::Naked => Some("naked"),
8821            Token::Connect => Some("connect"),
8822            Token::Close => Some("close"),
8823            Token::Simd => Some("simd"),
8824            Token::Derive => Some("derive"),
8825            Token::On => Some("on"),
8826            Token::Send => Some("send"),
8827            Token::Recv => Some("recv"),
8828            Token::Stream => Some("stream"),
8829            Token::Timeout => Some("timeout"),
8830            Token::Retry => Some("retry"),
8831            Token::Header => Some("header"),
8832            Token::Body => Some("body"),
8833            Token::Http => Some("http"),
8834            Token::Https => Some("https"),
8835            Token::Ws => Some("ws"),
8836            Token::Wss => Some("wss"),
8837            Token::Grpc => Some("grpc"),
8838            Token::Kafka => Some("kafka"),
8839            Token::Amqp => Some("amqp"),
8840            Token::GraphQL => Some("graphql"),
8841            Token::Actor => Some("actor"),
8842            Token::Saga => Some("saga"),
8843            Token::Scope => Some("scope"),
8844            Token::Rune => Some("rune"),
8845            // Plurality keywords - usable as identifiers in most contexts
8846            Token::Split => Some("split"),
8847            Token::Trigger => Some("trigger"),
8848            Token::Location => Some("location"),
8849            Token::States => Some("states"),
8850            Token::To => Some("to"),
8851            Token::From => Some("from"),
8852            Token::Headspace => Some("headspace"),
8853            Token::CoCon => Some("cocon"),
8854            Token::Reality => Some("reality"),
8855            Token::Layer => Some("layer"),
8856            Token::Anima => Some("anima"),
8857            Token::Struct => Some("sigil"),  // Allow 'sigil' as identifier (maps to Struct token)
8858            // Greek morpheme tokens - allow as identifiers in type/variable contexts
8859            Token::Parallel => Some("Parallel"),
8860            Token::Nu => Some("Nu"),
8861            Token::Lambda => Some("Lambda"),
8862            Token::Delta => Some("Delta"),
8863            Token::Tau => Some("Tau"),
8864            Token::Phi => Some("Phi"),
8865            Token::Sigma => Some("Sigma"),
8866            Token::Rho => Some("Rho"),
8867            Token::Pi => Some("Pi"),
8868            Token::Epsilon => Some("Epsilon"),
8869            Token::Omega => Some("Omega"),
8870            Token::Alpha => Some("Alpha"),
8871            Token::Zeta => Some("Zeta"),
8872            Token::Mu => Some("Mu"),
8873            Token::Chi => Some("Chi"),
8874            Token::Xi => Some("Xi"),
8875            Token::Psi => Some("Psi"),
8876            Token::Theta => Some("Theta"),
8877            Token::Kappa => Some("Kappa"),
8878            Token::Nabla => Some("∇"),
8879            Token::Gpu => Some("Gpu"),
8880            // Legion/communication operators - can be used as identifiers
8881            Token::Broadcast => Some("broadcast"),
8882            Token::Gather => Some("gather"),
8883            Token::Distribute => Some("distribute"),
8884            Token::Interfere => Some("interfere"),
8885            Token::Consensus => Some("consensus"),
8886            // Other contextual keywords
8887            Token::Ref => Some("ref"),
8888            Token::Null => Some("null"),
8889            Token::Fn => Some("rite"),  // Allow 'rite' as identifier (canonical function keyword)
8890            Token::LambdaExpr => Some("λ"),  // Allow 'λ' as identifier in certain contexts
8891            // Substructural type keywords - usable as identifiers in field/variable contexts
8892            Token::Linear => Some("linear"),
8893            Token::Affine => Some("affine"),
8894            Token::Relevant => Some("relevant"),
8895            _ => None,
8896        }
8897    }
8898
8899    pub(crate) fn parse_ident(&mut self) -> ParseResult<Ident> {
8900        match self.current.take() {
8901            Some((Token::Ident(name), span)) => {
8902                self.current = self.lexer.next_token();
8903                // Parse optional UNAMBIGUOUS evidentiality markers after identifier: field◊, value~
8904                // NOTE: Don't consume ! or ? here as they have other meanings (macro!/try?)
8905                let evidentiality = self.parse_unambiguous_evidentiality_opt();
8906                // Parse optional affective markers after identifier
8907                let affect = self.parse_affect_opt();
8908                Ok(Ident {
8909                    name,
8910                    evidentiality,
8911                    affect,
8912                    span,
8913                })
8914            }
8915            Some((ref token, span)) if Self::keyword_as_ident(token).is_some() => {
8916                let mut name = Self::keyword_as_ident(token).unwrap().to_string();
8917                self.current = self.lexer.next_token();
8918                // Check if next token is an identifier starting with underscore
8919                // This handles Greek letter + underscore patterns like λ_Pipeline
8920                if let Some((Token::Ident(suffix), suffix_span)) = &self.current {
8921                    if suffix.starts_with('_') {
8922                        name.push_str(suffix);
8923                        let merged_span = span.merge(*suffix_span);
8924                        self.current = self.lexer.next_token();
8925                        let evidentiality = self.parse_unambiguous_evidentiality_opt();
8926                        let affect = self.parse_affect_opt();
8927                        return Ok(Ident {
8928                            name,
8929                            evidentiality,
8930                            affect,
8931                            span: merged_span,
8932                        });
8933                    }
8934                }
8935                let evidentiality = self.parse_unambiguous_evidentiality_opt();
8936                let affect = self.parse_affect_opt();
8937                Ok(Ident {
8938                    name,
8939                    evidentiality,
8940                    affect,
8941                    span,
8942                })
8943            }
8944            Some((token, span)) => {
8945                self.current = Some((token.clone(), span));
8946                Err(ParseError::UnexpectedToken {
8947                    expected: "identifier".to_string(),
8948                    found: token,
8949                    span,
8950                })
8951            }
8952            None => Err(ParseError::UnexpectedEof),
8953        }
8954    }
8955
8956    fn parse_evidentiality_opt(&mut self) -> Option<Evidentiality> {
8957        // Parse one or more evidentiality markers (e.g., !! or ?!)
8958        // Multiple markers are combined, with the last one taking precedence
8959        let mut ev = None;
8960        loop {
8961            match self.current_token() {
8962                Some(Token::Bang) => {
8963                    self.advance();
8964                    ev = Some(Evidentiality::Known);
8965                }
8966                Some(Token::Question) => {
8967                    self.advance();
8968                    ev = Some(Evidentiality::Uncertain);
8969                }
8970                Some(Token::Tilde) => {
8971                    self.advance();
8972                    ev = Some(Evidentiality::Reported);
8973                }
8974                Some(Token::Lozenge) => {
8975                    self.advance();
8976                    ev = Some(Evidentiality::Predicted);
8977                }
8978                Some(Token::Interrobang) => {
8979                    self.advance();
8980                    ev = Some(Evidentiality::Paradox);
8981                }
8982                _ => break,
8983            }
8984        }
8985        ev
8986    }
8987
8988    /// Parse UNAMBIGUOUS evidentiality markers only: ~, ◊, ‽
8989    /// Does NOT consume ! or ? as they have other meanings (macro!/try?)
8990    fn parse_unambiguous_evidentiality_opt(&mut self) -> Option<Evidentiality> {
8991        let mut ev = None;
8992        loop {
8993            match self.current_token() {
8994                Some(Token::Tilde) => {
8995                    self.advance();
8996                    ev = Some(Evidentiality::Reported);
8997                }
8998                Some(Token::Lozenge) => {
8999                    self.advance();
9000                    ev = Some(Evidentiality::Predicted);
9001                }
9002                Some(Token::Interrobang) => {
9003                    self.advance();
9004                    ev = Some(Evidentiality::Paradox);
9005                }
9006                _ => break,
9007            }
9008        }
9009        ev
9010    }
9011
9012    /// Parse optional affective markers: sentiment, sarcasm, intensity, formality, emotion, confidence
9013    /// Symbols: ⊕ ⊖ ⊜ (sentiment), ⸮ (sarcasm), ↑ ↓ ⇈ (intensity), ♔ ♟ (formality),
9014    ///          ☺ ☹ ⚡ ❄ ✦ ♡ (emotions), ◉ ◎ ○ (confidence)
9015    fn parse_affect_opt(&mut self) -> Option<Affect> {
9016        let mut sentiment = None;
9017        let mut sarcasm = false;
9018        let mut intensity = None;
9019        let mut formality = None;
9020        let mut emotion = None;
9021        let mut confidence = None;
9022        let mut found_any = false;
9023
9024        // Parse all consecutive affective markers
9025        loop {
9026            match self.current_token() {
9027                // Sentiment markers
9028                Some(Token::DirectSum) => {
9029                    self.advance();
9030                    sentiment = Some(Sentiment::Positive);
9031                    found_any = true;
9032                }
9033                Some(Token::AffectNegative) => {
9034                    self.advance();
9035                    sentiment = Some(Sentiment::Negative);
9036                    found_any = true;
9037                }
9038                Some(Token::AffectNeutral) => {
9039                    self.advance();
9040                    sentiment = Some(Sentiment::Neutral);
9041                    found_any = true;
9042                }
9043                // Sarcasm/Irony
9044                Some(Token::IronyMark) => {
9045                    self.advance();
9046                    sarcasm = true;
9047                    found_any = true;
9048                }
9049                // Intensity
9050                Some(Token::IntensityUp) => {
9051                    self.advance();
9052                    intensity = Some(Intensity::Up);
9053                    found_any = true;
9054                }
9055                Some(Token::IntensityDown) => {
9056                    self.advance();
9057                    intensity = Some(Intensity::Down);
9058                    found_any = true;
9059                }
9060                Some(Token::IntensityMax) => {
9061                    self.advance();
9062                    intensity = Some(Intensity::Max);
9063                    found_any = true;
9064                }
9065                // Formality
9066                Some(Token::FormalRegister) => {
9067                    self.advance();
9068                    formality = Some(Formality::Formal);
9069                    found_any = true;
9070                }
9071                Some(Token::InformalRegister) => {
9072                    self.advance();
9073                    formality = Some(Formality::Informal);
9074                    found_any = true;
9075                }
9076                // Emotions (Plutchik's wheel)
9077                Some(Token::EmotionJoy) => {
9078                    self.advance();
9079                    emotion = Some(Emotion::Joy);
9080                    found_any = true;
9081                }
9082                Some(Token::EmotionSadness) => {
9083                    self.advance();
9084                    emotion = Some(Emotion::Sadness);
9085                    found_any = true;
9086                }
9087                Some(Token::EmotionAnger) => {
9088                    self.advance();
9089                    emotion = Some(Emotion::Anger);
9090                    found_any = true;
9091                }
9092                Some(Token::EmotionFear) => {
9093                    self.advance();
9094                    emotion = Some(Emotion::Fear);
9095                    found_any = true;
9096                }
9097                Some(Token::EmotionSurprise) => {
9098                    self.advance();
9099                    emotion = Some(Emotion::Surprise);
9100                    found_any = true;
9101                }
9102                Some(Token::EmotionLove) => {
9103                    self.advance();
9104                    emotion = Some(Emotion::Love);
9105                    found_any = true;
9106                }
9107                // Confidence
9108                Some(Token::ConfidenceHigh) => {
9109                    self.advance();
9110                    confidence = Some(Confidence::High);
9111                    found_any = true;
9112                }
9113                Some(Token::ConfidenceMedium) => {
9114                    self.advance();
9115                    confidence = Some(Confidence::Medium);
9116                    found_any = true;
9117                }
9118                Some(Token::ConfidenceLow) => {
9119                    self.advance();
9120                    confidence = Some(Confidence::Low);
9121                    found_any = true;
9122                }
9123                _ => break,
9124            }
9125        }
9126
9127        if found_any {
9128            Some(Affect {
9129                sentiment,
9130                sarcasm,
9131                intensity,
9132                formality,
9133                emotion,
9134                confidence,
9135            })
9136        } else {
9137            None
9138        }
9139    }
9140
9141    pub(crate) fn parse_generics_opt(&mut self) -> ParseResult<Option<Generics>> {
9142        // Support both <T> and [T] syntax for generics
9143        let use_brackets = if self.consume_if(&Token::Lt) {
9144            false
9145        } else if self.consume_if(&Token::LBracket) {
9146            true
9147        } else {
9148            return Ok(None);
9149        };
9150
9151        let mut params = Vec::new();
9152        // Use check_gt() to handle pending `>` from split `>>` (only for angle brackets)
9153        while !self.is_eof() {
9154            // Skip line comments between generic parameters
9155            self.skip_comments();
9156
9157            if use_brackets {
9158                if self.check(&Token::RBracket) {
9159                    break;
9160                }
9161            } else if self.check_gt() {
9162                break;
9163            }
9164
9165            // Check for lifetime parameter: 'a, 'static, etc.
9166            if let Some(Token::Lifetime(lt)) = self.current_token().cloned() {
9167                self.advance();
9168                params.push(GenericParam::Lifetime(lt));
9169                if !self.consume_if(&Token::Comma) {
9170                    break;
9171                }
9172                continue;
9173            }
9174
9175            // Check for const generic parameter (const N: usize = 10 or just const N)
9176            if self.consume_if(&Token::Const) {
9177                let name = self.parse_ident()?;
9178                // Type annotation is optional: const N: usize or just const N
9179                let ty = if self.consume_if(&Token::Colon) {
9180                    self.parse_type()?
9181                } else {
9182                    TypeExpr::Infer
9183                };
9184                // Parse optional default value: const N: usize = 10
9185                let default = if self.consume_if(&Token::Eq) {
9186                    Some(Box::new(self.parse_expr()?))
9187                } else {
9188                    None
9189                };
9190                params.push(GenericParam::Const { name, ty, default });
9191                if !self.consume_if(&Token::Comma) {
9192                    break;
9193                }
9194                continue;
9195            }
9196
9197            // Type parameter
9198            let name = self.parse_ident()?;
9199            let evidentiality = self.parse_evidentiality_opt();
9200            let bounds = if self.consume_if(&Token::Colon) {
9201                self.parse_type_bounds()?
9202            } else {
9203                vec![]
9204            };
9205            // Parse optional default type: T = DefaultType
9206            let default = if self.consume_if(&Token::Eq) {
9207                Some(self.parse_type()?)
9208            } else {
9209                None
9210            };
9211            params.push(GenericParam::Type {
9212                name,
9213                bounds,
9214                evidentiality,
9215                default,
9216            });
9217
9218            if !self.consume_if(&Token::Comma) {
9219                break;
9220            }
9221        }
9222        // Close the generics
9223        if use_brackets {
9224            self.expect(Token::RBracket)?;
9225        } else {
9226            // Use expect_gt() to handle nested generics with `>>`
9227            self.expect_gt()?;
9228        }
9229
9230        Ok(Some(Generics { params }))
9231    }
9232
9233    pub(crate) fn parse_where_clause_opt(&mut self) -> ParseResult<Option<WhereClause>> {
9234        if !self.consume_if(&Token::Where) {
9235            return Ok(None);
9236        }
9237
9238        let mut predicates = Vec::new();
9239        loop {
9240            self.skip_comments(); // Skip comments between predicates
9241
9242            // Check for expression predicates: EXPR == EXPR (e.g., QH % KVH == 0)
9243            // These start with an identifier followed by an operator other than :
9244            // Try to detect expression predicate by peeking ahead
9245            // Expression predicates have operators like %, ==, !=, <, >, etc.
9246            let is_expr_predicate = if let Some(Token::Ident(_)) = self.current_token() {
9247                // Peek ahead to see if we have an expression operator instead of :
9248                let next = self.peek_next();
9249                matches!(
9250                    next,
9251                    Some(Token::Percent)
9252                        | Some(Token::EqEq)
9253                        | Some(Token::NotEq)
9254                        | Some(Token::Plus)
9255                        | Some(Token::Minus)
9256                        | Some(Token::Star)
9257                        | Some(Token::Slash)
9258                )
9259            } else {
9260                false
9261            };
9262
9263            if is_expr_predicate {
9264                // Parse as expression predicate: EXPR == EXPR or EXPR != EXPR
9265                let _expr = self.parse_expr()?;
9266                // For now, just skip the constraint - we'll store it properly later
9267                self.skip_comments();
9268                if !self.consume_if(&Token::Comma) {
9269                    break;
9270                }
9271                self.skip_comments();
9272                if self.check(&Token::LBrace) {
9273                    break;
9274                }
9275                continue;
9276            }
9277
9278            let ty = self.parse_type()?;
9279
9280            // Check if this is a type bound (T: Trait) or if we should skip
9281            if self.check(&Token::Colon) {
9282                self.advance(); // consume :
9283                let bounds = self.parse_type_bounds()?;
9284                self.skip_comments(); // Skip comments after bounds
9285                predicates.push(WherePredicate { ty, bounds });
9286            } else {
9287                // Not a type bound, might be an expression we couldn't detect earlier
9288                // Just skip this predicate
9289            }
9290
9291            if !self.consume_if(&Token::Comma) {
9292                break;
9293            }
9294            // Stop if we hit a brace
9295            self.skip_comments();
9296            if self.check(&Token::LBrace) {
9297                break;
9298            }
9299        }
9300
9301        Ok(Some(WhereClause { predicates }))
9302    }
9303
9304    pub(crate) fn parse_params(&mut self) -> ParseResult<Vec<Param>> {
9305        let mut params = Vec::new();
9306        while !self.check(&Token::RParen) && !self.is_eof() {
9307            // Skip comments and parameter attributes: @[...] or #[...]
9308            self.skip_comments();
9309            while self.check(&Token::At) || self.check(&Token::Hash) {
9310                self.skip_attribute()?;
9311                self.skip_comments();
9312            }
9313            if self.check(&Token::RParen) {
9314                break;
9315            }
9316            let pattern = self.parse_pattern()?;
9317            // Type annotation is optional - use Infer if not provided
9318            let ty = if self.consume_if(&Token::Colon) {
9319                self.parse_type()?
9320            } else {
9321                TypeExpr::Infer
9322            };
9323            params.push(Param { pattern, ty });
9324            if !self.consume_if(&Token::Comma) {
9325                break;
9326            }
9327        }
9328        Ok(params)
9329    }
9330
9331    /// Skip an attribute (@[...] or #[...]) without parsing its contents
9332    fn skip_attribute(&mut self) -> ParseResult<()> {
9333        // Consume @ or #
9334        if self.check(&Token::At) || self.check(&Token::Hash) {
9335            self.advance();
9336        }
9337        // Consume [...] if present
9338        if self.consume_if(&Token::LBracket) {
9339            let mut depth = 1;
9340            while depth > 0 && !self.is_eof() {
9341                match self.current_token() {
9342                    Some(Token::LBracket) => depth += 1,
9343                    Some(Token::RBracket) => depth -= 1,
9344                    _ => {}
9345                }
9346                self.advance();
9347            }
9348        }
9349        Ok(())
9350    }
9351
9352    fn parse_field_defs(&mut self) -> ParseResult<Vec<FieldDef>> {
9353        let mut fields = Vec::new();
9354        while !self.check(&Token::RBrace) && !self.is_eof() {
9355            // Skip doc comments, line comments, and attributes before fields
9356            while matches!(
9357                self.current_token(),
9358                Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_))
9359            ) || self.check(&Token::Hash) || self.check(&Token::At)
9360            {
9361                if self.check(&Token::Hash) || self.check(&Token::At) {
9362                    self.skip_attribute()?;
9363                } else {
9364                    self.advance();
9365                }
9366            }
9367            if self.check(&Token::RBrace) {
9368                break;
9369            }
9370            let visibility = self.parse_visibility()?;
9371            let name = self.parse_ident()?;
9372            // Optional evidentiality marker after field name: `field~: Type`, `field◊: Type`
9373            let _evidentiality = self.parse_evidentiality_opt();
9374            self.expect(Token::Colon)?;
9375            let ty = self.parse_type()?;
9376            // Parse optional default value: `field: Type = default_expr`
9377            let default = if self.consume_if(&Token::Eq) {
9378                Some(self.parse_expr()?)
9379            } else {
9380                None
9381            };
9382            fields.push(FieldDef {
9383                visibility,
9384                name,
9385                ty,
9386                default,
9387            });
9388            if !self.consume_if(&Token::Comma) {
9389                break;
9390            }
9391        }
9392        Ok(fields)
9393    }
9394
9395    fn parse_expr_list(&mut self) -> ParseResult<Vec<Expr>> {
9396        let mut exprs = Vec::new();
9397        // Skip leading comments
9398        self.skip_comments();
9399        while !self.check(&Token::RParen) && !self.check(&Token::RBracket) && !self.is_eof() {
9400            // Check for named argument syntax: name: expr
9401            // This handles calls like `stack(axis: 0)` or `func(x: 1, y: 2)`
9402            // We detect `ident :` but not `ident ::` (path separator)
9403            let expr = if let Some(Token::Ident(name)) = self.current_token().cloned() {
9404                // Look ahead: is next token `:` (single colon) not `::` (double colon)?
9405                let is_named_arg = self.peek_next() == Some(&Token::Colon);
9406                if is_named_arg {
9407                    let span = self.current_span();
9408                    self.advance(); // consume name
9409                    self.advance(); // consume :
9410                    let value = self.parse_expr()?;
9411                    // Represent as a named argument via NamedArg expression
9412                    Expr::NamedArg {
9413                        name: Ident {
9414                            name,
9415                            evidentiality: None,
9416                            affect: None,
9417                            span,
9418                        },
9419                        value: Box::new(value),
9420                    }
9421                } else {
9422                    self.parse_expr()?
9423                }
9424            } else {
9425                self.parse_expr()?
9426            };
9427            exprs.push(expr);
9428            if !self.consume_if(&Token::Comma) {
9429                break;
9430            }
9431            // Skip comments after comma (e.g., trailing comments on argument lines)
9432            self.skip_comments();
9433        }
9434        Ok(exprs)
9435    }
9436
9437    fn parse_struct_fields(&mut self) -> ParseResult<(Vec<FieldInit>, Option<Box<Expr>>)> {
9438        let mut fields = Vec::new();
9439        let mut rest = None;
9440
9441        while !self.check(&Token::RBrace) && !self.is_eof() {
9442            // Skip comments and attributes before field
9443            while matches!(
9444                self.current_token(),
9445                Some(Token::DocComment(_)) | Some(Token::LineComment(_) | Token::TildeComment(_) | Token::BlockComment(_)) | Some(Token::Hash)
9446            ) {
9447                if self.check(&Token::Hash) {
9448                    // Skip attribute: #[...] or #![...]
9449                    self.advance();
9450                    self.consume_if(&Token::Bang); // optional ! for inner attributes
9451                    if self.consume_if(&Token::LBracket) {
9452                        let mut depth = 1;
9453                        while depth > 0 && !self.is_eof() {
9454                            match self.current_token() {
9455                                Some(Token::LBracket) => depth += 1,
9456                                Some(Token::RBracket) => depth -= 1,
9457                                _ => {}
9458                            }
9459                            self.advance();
9460                        }
9461                    }
9462                } else {
9463                    self.advance();
9464                }
9465            }
9466            if self.check(&Token::RBrace) {
9467                break;
9468            }
9469            if self.consume_if(&Token::DotDot) {
9470                rest = Some(Box::new(self.parse_expr()?));
9471                break;
9472            }
9473
9474            let name = self.parse_ident()?;
9475            let value = if self.consume_if(&Token::Colon) {
9476                Some(self.parse_expr()?)
9477            } else {
9478                None
9479            };
9480            fields.push(FieldInit { name, value });
9481
9482            if !self.consume_if(&Token::Comma) {
9483                break;
9484            }
9485        }
9486
9487        Ok((fields, rest))
9488    }
9489
9490    fn is_item_start(&mut self) -> bool {
9491        match self.current_token() {
9492            Some(Token::Fn)
9493                | Some(Token::Struct)
9494                | Some(Token::Enum)
9495                | Some(Token::Trait)
9496                | Some(Token::Impl)
9497                | Some(Token::Type)
9498                | Some(Token::Mod)
9499                | Some(Token::Use)
9500                | Some(Token::Const)
9501                | Some(Token::Static)
9502                | Some(Token::Actor)
9503                | Some(Token::Pub)
9504                | Some(Token::Extern) => true,
9505            // async is only item start if followed by fn (async fn ...)
9506            // async move { } or async { } are block expressions, not items
9507            Some(Token::Async) => matches!(self.peek_next(), Some(Token::Fn)),
9508            _ => false,
9509        }
9510    }
9511
9512    fn is_in_condition(&self) -> bool {
9513        self.in_condition
9514    }
9515
9516    /// Parse an expression in condition context (< is comparison, not generics)
9517    fn parse_condition(&mut self) -> ParseResult<Expr> {
9518        let was_in_condition = self.in_condition;
9519        self.in_condition = true;
9520        let result = self.parse_expr();
9521        self.in_condition = was_in_condition;
9522        result
9523    }
9524
9525    // ==========================================
9526    // Legion Morpheme Parsing
9527    // ==========================================
9528
9529    /// Parse Legion operators that follow an expression.
9530    /// Handles: ⫰ (interference), ⟁ (distribute), ↠ (broadcast),
9531    ///          ⟀ (gather), ⇢ (consensus), ◉ (resonance)
9532    fn parse_legion_operator(&mut self, lhs: Expr) -> ParseResult<Expr> {
9533        match self.current_token() {
9534            Some(Token::Interfere) => {
9535                // Interference: query ⫰ field
9536                self.advance();
9537                let field = self.parse_expr_bp(15)?; // Higher precedence
9538                Ok(Expr::LegionInterference {
9539                    query: Box::new(lhs),
9540                    field: Box::new(field),
9541                })
9542            }
9543            Some(Token::Distribute) => {
9544                // Distribute: task ⟁ count
9545                self.advance();
9546                let count = self.parse_expr_bp(15)?;
9547                Ok(Expr::LegionDistribute {
9548                    task: Box::new(lhs),
9549                    count: Box::new(count),
9550                })
9551            }
9552            Some(Token::Broadcast) => {
9553                // Broadcast: signal ↠ target
9554                self.advance();
9555                let target = self.parse_expr_bp(15)?;
9556                Ok(Expr::LegionBroadcast {
9557                    signal: Box::new(lhs),
9558                    target: Box::new(target),
9559                })
9560            }
9561            Some(Token::Gather) => {
9562                // Gather: fragments ⟀ (postfix unary)
9563                self.advance();
9564                Ok(Expr::LegionGather {
9565                    fragments: Box::new(lhs),
9566                })
9567            }
9568            Some(Token::Consensus) => {
9569                // Consensus: contributions ⇢ (postfix unary)
9570                self.advance();
9571                Ok(Expr::LegionConsensus {
9572                    contributions: Box::new(lhs),
9573                })
9574            }
9575            Some(Token::ConfidenceHigh) => {
9576                // Resonance: resonance |◉ (postfix unary, dual-purpose token)
9577                self.advance();
9578                Ok(Expr::LegionResonance {
9579                    expr: Box::new(lhs),
9580                })
9581            }
9582            _ => Ok(lhs),
9583        }
9584    }
9585
9586    /// Check if an identifier ends with the Legion field marker ∿
9587    /// Used to parse variable names like `memory∿`
9588    fn is_legion_field_ident(&self, name: &str) -> bool {
9589        name.ends_with('∿')
9590    }
9591}
9592
9593/// Binding power for infix operators.
9594fn infix_binding_power(op: BinOp) -> (u8, u8) {
9595    match op {
9596        BinOp::Or => (1, 2),
9597        BinOp::And => (3, 4),
9598        BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le | BinOp::Gt | BinOp::Ge => (5, 6),
9599        BinOp::BitOr => (7, 8),
9600        BinOp::BitXor => (9, 10),
9601        BinOp::BitAnd => (11, 12),
9602        BinOp::Shl | BinOp::Shr => (13, 14),
9603        BinOp::Add | BinOp::Sub | BinOp::Concat => (15, 16),
9604        BinOp::Mul | BinOp::Div | BinOp::Rem | BinOp::MatMul
9605        | BinOp::Hadamard | BinOp::TensorProd | BinOp::Convolve => (17, 18),
9606        BinOp::Pow => (20, 19), // Right associative
9607    }
9608}
9609
9610#[cfg(test)]
9611mod tests {
9612    use super::*;
9613
9614    #[test]
9615    fn test_parse_function() {
9616        // Simple function with semicolon-terminated statement
9617        let source = "rite hello(name: str) -> str { ⤺ name; }";
9618        let mut parser = Parser::new(source);
9619        let file = parser.parse_file().unwrap();
9620        assert_eq!(file.items.len(), 1);
9621    }
9622
9623    #[test]
9624    fn test_parse_pipe_chain() {
9625        let source = "rite main() { ≔ result = data|τ{_ * 2}|φ{_ > 0}|σ; }";
9626        let mut parser = Parser::new(source);
9627        let file = parser.parse_file().unwrap();
9628        assert_eq!(file.items.len(), 1);
9629    }
9630
9631    #[test]
9632    fn test_parse_async_function() {
9633        let source = "async rite fetch(url: str) -> Response~ { ⤺ client·get(url)|await; }";
9634        let mut parser = Parser::new(source);
9635        let file = parser.parse_file().unwrap();
9636        assert_eq!(file.items.len(), 1);
9637    }
9638
9639    #[test]
9640    fn test_parse_struct() {
9641        let source = "sigil Point { x: f64, y: f64 }";
9642        let mut parser = Parser::new(source);
9643        let file = parser.parse_file().unwrap();
9644        assert_eq!(file.items.len(), 1);
9645    }
9646
9647    #[test]
9648    fn test_parse_actor() {
9649        // Simplified actor without compound assignment
9650        let source = r#"
9651            actor Counter {
9652                state: i64 = 0
9653                on Increment(n: i64) { ⤺ self.state + n; }
9654            }
9655        "#;
9656        let mut parser = Parser::new(source);
9657        let file = parser.parse_file().unwrap();
9658        assert_eq!(file.items.len(), 1);
9659    }
9660
9661    #[test]
9662    fn test_parse_number_bases() {
9663        let source = "rite bases() { ≔ a = 42; ≔ b = 0b101010; ≔ c = 0x2A; ≔ d = 0v22; }";
9664        let mut parser = Parser::new(source);
9665        let file = parser.parse_file().unwrap();
9666        assert_eq!(file.items.len(), 1);
9667    }
9668
9669    #[test]
9670    fn test_parse_labeled_loops() {
9671        // Test labeled loop with break
9672        // Note: ⊗ (Tensor) is the native Sigil break keyword
9673        let source = r#"
9674            rite test() {
9675                'outer: loop {
9676                    'inner: ⟳ true {
9677                        ⊗ 'outer;
9678                    }
9679                }
9680            }
9681        "#;
9682        let mut parser = Parser::new(source);
9683        let file = parser.parse_file().unwrap();
9684        assert_eq!(file.items.len(), 1);
9685
9686        // Test labeled for with continue
9687        // Note: ↻ (CycleArrow) is the native Sigil continue keyword
9688        let source2 = r#"
9689            rite test2() {
9690                'rows: ∀ i ∈ 0..10 {
9691                    'cols: ∀ j ∈ 0..10 {
9692                        ⎇ j == 5 { ↻ 'rows; }
9693                    }
9694                }
9695            }
9696        "#;
9697        let mut parser2 = Parser::new(source2);
9698        let file2 = parser2.parse_file().unwrap();
9699        assert_eq!(file2.items.len(), 1);
9700    }
9701
9702    #[test]
9703    fn test_parse_inline_asm() {
9704        let source = r#"
9705            rite outb(port: u16, value: u8) {
9706                asm!("out dx, al",
9707                    ∈("dx") port,
9708                    ∈("al") value,
9709                    options(nostack));
9710            }
9711        "#;
9712        let mut parser = Parser::new(source);
9713        let file = parser.parse_file().unwrap();
9714        assert_eq!(file.items.len(), 1);
9715
9716        if let Item::Function(func) = &file.items[0].node {
9717            assert_eq!(func.name.name, "outb");
9718        } else {
9719            panic!("Expected function");
9720        }
9721    }
9722
9723    #[test]
9724    fn test_parse_inline_asm_with_outputs() {
9725        let source = r#"
9726            rite inb(port: u16) -> u8 {
9727                ≔ result: u8 = 0;
9728                asm!("∈ al, dx",
9729                    out("al") result,
9730                    ∈("dx") port,
9731                    options(nostack, nomem));
9732                ⤺ result;
9733            }
9734        "#;
9735        let mut parser = Parser::new(source);
9736        let file = parser.parse_file().unwrap();
9737        assert_eq!(file.items.len(), 1);
9738    }
9739
9740    #[test]
9741    fn test_parse_volatile_read() {
9742        let source = r#"
9743            rite read_mmio(addr: *Δ u32) -> u32 {
9744                ⤺ volatile read<u32>(addr);
9745            }
9746        "#;
9747        let mut parser = Parser::new(source);
9748        let file = parser.parse_file().unwrap();
9749        assert_eq!(file.items.len(), 1);
9750    }
9751
9752    #[test]
9753    fn test_parse_volatile_write() {
9754        let source = r#"
9755            rite write_mmio(addr: *Δ u32, value: u32) {
9756                volatile write<u32>(addr, value);
9757            }
9758        "#;
9759        let mut parser = Parser::new(source);
9760        let file = parser.parse_file().unwrap();
9761        assert_eq!(file.items.len(), 1);
9762    }
9763
9764    #[test]
9765    fn test_parse_naked_function() {
9766        let source = r#"
9767            naked rite interrupt_handler() {
9768                asm!("push rax; push rbx; call handler_impl; pop rbx; pop rax; iretq",
9769                    options(nostack));
9770            }
9771        "#;
9772        let mut parser = Parser::new(source);
9773        let file = parser.parse_file().unwrap();
9774        assert_eq!(file.items.len(), 1);
9775
9776        if let Item::Function(func) = &file.items[0].node {
9777            assert!(func.attrs.naked, "Function should be naked");
9778        } else {
9779            panic!("Expected function");
9780        }
9781    }
9782
9783    #[test]
9784    fn test_parse_packed_struct() {
9785        let source = r#"
9786            packed sigil GDTEntry {
9787                limit_low: u16,
9788                base_low: u16,
9789                base_middle: u8,
9790                access: u8,
9791                granularity: u8,
9792                base_high: u8,
9793            }
9794        "#;
9795        let mut parser = Parser::new(source);
9796        let file = parser.parse_file().unwrap();
9797        assert_eq!(file.items.len(), 1);
9798
9799        if let Item::Struct(s) = &file.items[0].node {
9800            assert!(s.attrs.packed, "Struct should be packed");
9801            assert_eq!(s.name.name, "GDTEntry");
9802            if let StructFields::Named(fields) = &s.fields {
9803                assert_eq!(fields.len(), 6);
9804            } else {
9805                panic!("Expected named fields");
9806            }
9807        } else {
9808            panic!("Expected struct");
9809        }
9810    }
9811
9812    #[test]
9813    fn test_parse_no_std_attribute() {
9814        let source = r#"
9815            #![no_std]
9816            #![no_main]
9817
9818            rite kernel_main() -> ! {
9819                loop {}
9820            }
9821        "#;
9822        let mut parser = Parser::new(source);
9823        let file = parser.parse_file().unwrap();
9824
9825        assert!(file.config.no_std, "Should have no_std");
9826        assert!(file.config.no_main, "Should have no_main");
9827        assert_eq!(file.attrs.len(), 2);
9828    }
9829
9830    #[test]
9831    fn test_parse_feature_attribute() {
9832        let source = r#"
9833            #![feature(asm, naked_functions)]
9834
9835            rite main() -> i64 { 0 }
9836        "#;
9837        let mut parser = Parser::new(source);
9838        let file = parser.parse_file().unwrap();
9839
9840        assert_eq!(file.config.features.len(), 2);
9841        assert!(file.config.features.contains(&"asm".to_string()));
9842        assert!(file
9843            .config
9844            .features
9845            .contains(&"naked_functions".to_string()));
9846    }
9847
9848    #[test]
9849    fn test_parse_target_attribute() {
9850        let source = r#"
9851            #![no_std]
9852            #![target(arch = "x86_64", os = "none")]
9853
9854            rite kernel_main() { }
9855        "#;
9856        let mut parser = Parser::new(source);
9857        let file = parser.parse_file().unwrap();
9858
9859        assert!(file.config.no_std);
9860        let target = file
9861            .config
9862            .target
9863            .as_ref()
9864            .expect("Should have target config");
9865        assert_eq!(target.arch, Some("x86_64".to_string()));
9866        assert_eq!(target.os, Some("none".to_string()));
9867    }
9868
9869    #[test]
9870    fn test_parse_panic_handler() {
9871        let source = r#"
9872            #![no_std]
9873
9874            #[panic_handler]
9875            rite panic(info: *const PanicInfo) -> ! {
9876                loop {}
9877            }
9878        "#;
9879        let mut parser = Parser::new(source);
9880        let file = parser.parse_file().unwrap();
9881
9882        assert_eq!(file.items.len(), 1);
9883        if let Item::Function(func) = &file.items[0].node {
9884            assert!(
9885                func.attrs.panic_handler,
9886                "Should have panic_handler attribute"
9887            );
9888        } else {
9889            panic!("Expected function");
9890        }
9891    }
9892
9893    #[test]
9894    fn test_parse_entry_point() {
9895        let source = r#"
9896            #![no_std]
9897            #![no_main]
9898
9899            #[entry]
9900            #[no_mangle]
9901            rite _start() -> ! {
9902                loop {}
9903            }
9904        "#;
9905        let mut parser = Parser::new(source);
9906        let file = parser.parse_file().unwrap();
9907
9908        assert_eq!(file.items.len(), 1);
9909        if let Item::Function(func) = &file.items[0].node {
9910            assert!(func.attrs.entry, "Should have entry attribute");
9911            assert!(func.attrs.no_mangle, "Should have no_mangle attribute");
9912        } else {
9913            panic!("Expected function");
9914        }
9915    }
9916
9917    #[test]
9918    fn test_parse_link_section() {
9919        let source = r#"
9920            #[link_section = ".text.boot"]
9921            rite boot_code() { }
9922        "#;
9923        let mut parser = Parser::new(source);
9924        let file = parser.parse_file().unwrap();
9925
9926        assert_eq!(file.items.len(), 1);
9927        if let Item::Function(func) = &file.items[0].node {
9928            assert_eq!(func.attrs.link_section, Some(".text.boot".to_string()));
9929        } else {
9930            panic!("Expected function");
9931        }
9932    }
9933
9934    #[test]
9935    fn test_parse_linker_config() {
9936        let source = r#"
9937            #![no_std]
9938            #![linker_script = "kernel.ld"]
9939            #![entry_point = "_start"]
9940            #![base_address = 0x100000]
9941            #![stack_size = 0x4000]
9942
9943            rite kernel_main() { }
9944        "#;
9945        let mut parser = Parser::new(source);
9946        let file = parser.parse_file().unwrap();
9947
9948        let linker = file
9949            .config
9950            .linker
9951            .as_ref()
9952            .expect("Should have linker config");
9953        assert_eq!(linker.script, Some("kernel.ld".to_string()));
9954        assert_eq!(linker.entry_point, Some("_start".to_string()));
9955        assert_eq!(linker.base_address, Some(0x100000));
9956        assert_eq!(linker.stack_size, Some(0x4000));
9957    }
9958
9959    #[test]
9960    fn test_parse_interrupt_handler() {
9961        let source = r#"
9962            #[interrupt(32)]
9963            #[naked]
9964            rite timer_handler() {
9965                asm!("iretq", options(nostack));
9966            }
9967        "#;
9968        let mut parser = Parser::new(source);
9969        let file = parser.parse_file().unwrap();
9970
9971        if let Item::Function(func) = &file.items[0].node {
9972            assert_eq!(func.attrs.interrupt, Some(32));
9973            assert!(func.attrs.naked);
9974        } else {
9975            panic!("Expected function");
9976        }
9977    }
9978
9979    #[test]
9980    fn test_parse_inline_attributes() {
9981        let source = r#"
9982            #[inline]
9983            rite fast() -> i64 { 0 }
9984
9985            #[inline(always)]
9986            rite very_fast() -> i64 { 0 }
9987
9988            #[inline(never)]
9989            rite never_inline() -> i64 { 0 }
9990        "#;
9991        let mut parser = Parser::new(source);
9992        let file = parser.parse_file().unwrap();
9993
9994        assert_eq!(file.items.len(), 3);
9995
9996        if let Item::Function(func) = &file.items[0].node {
9997            assert_eq!(func.attrs.inline, Some(InlineHint::Hint));
9998        }
9999        if let Item::Function(func) = &file.items[1].node {
10000            assert_eq!(func.attrs.inline, Some(InlineHint::Always));
10001        }
10002        if let Item::Function(func) = &file.items[2].node {
10003            assert_eq!(func.attrs.inline, Some(InlineHint::Never));
10004        }
10005    }
10006
10007    #[test]
10008    fn test_parse_simd_type() {
10009        let source = r#"
10010            rite vec_add(a: simd<f32, 4>, b: simd<f32, 4>) -> simd<f32, 4> {
10011                ⤺ simd.add(a, b);
10012            }
10013        "#;
10014        let mut parser = Parser::new(source);
10015        let file = parser.parse_file().unwrap();
10016        assert_eq!(file.items.len(), 1);
10017
10018        if let Item::Function(func) = &file.items[0].node {
10019            assert_eq!(func.name.name, "vec_add");
10020            // Check first parameter type
10021            if let TypeExpr::Simd { element, lanes } = &func.params[0].ty {
10022                assert_eq!(*lanes, 4);
10023                if let TypeExpr::Path(path) = element.as_ref() {
10024                    assert_eq!(path.segments[0].ident.name, "f32");
10025                }
10026            } else {
10027                panic!("Expected SIMD type");
10028            }
10029        } else {
10030            panic!("Expected function");
10031        }
10032    }
10033
10034    #[test]
10035    fn test_parse_simd_literal() {
10036        let source = r#"
10037            rite make_vec() -> simd<f32, 4> {
10038                ⤺ simd[1.0, 2.0, 3.0, 4.0];
10039            }
10040        "#;
10041        let mut parser = Parser::new(source);
10042        let file = parser.parse_file().unwrap();
10043        assert_eq!(file.items.len(), 1);
10044    }
10045
10046    #[test]
10047    fn test_parse_simd_intrinsics() {
10048        let source = r#"
10049            rite dot_product(a: simd<f32, 4>, b: simd<f32, 4>) -> f32 {
10050                ≔ prod = simd.mul(a, b);
10051                ⤺ simd.hadd(prod);
10052            }
10053        "#;
10054        let mut parser = Parser::new(source);
10055        let file = parser.parse_file().unwrap();
10056        assert_eq!(file.items.len(), 1);
10057    }
10058
10059    #[test]
10060    fn test_parse_simd_shuffle() {
10061        let source = r#"
10062            rite interleave(a: simd<f32, 4>, b: simd<f32, 4>) -> simd<f32, 4> {
10063                ⤺ simd.shuffle(a, b, [0, 4, 1, 5]);
10064            }
10065        "#;
10066        let mut parser = Parser::new(source);
10067        let file = parser.parse_file().unwrap();
10068        assert_eq!(file.items.len(), 1);
10069    }
10070
10071    #[test]
10072    fn test_parse_atomic_type() {
10073        let source = r#"
10074            sigil Counter {
10075                value: atomic<i64>,
10076            }
10077        "#;
10078        let mut parser = Parser::new(source);
10079        let file = parser.parse_file().unwrap();
10080        assert_eq!(file.items.len(), 1);
10081
10082        if let Item::Struct(s) = &file.items[0].node {
10083            if let StructFields::Named(fields) = &s.fields {
10084                if let TypeExpr::Atomic(inner) = &fields[0].ty {
10085                    if let TypeExpr::Path(path) = inner.as_ref() {
10086                        assert_eq!(path.segments[0].ident.name, "i64");
10087                    }
10088                } else {
10089                    panic!("Expected atomic type");
10090                }
10091            }
10092        } else {
10093            panic!("Expected struct");
10094        }
10095    }
10096
10097    #[test]
10098    fn test_parse_atomic_operations() {
10099        let source = r#"
10100            rite increment(ptr: *Δ i64) -> i64 {
10101                ⤺ atomic.fetch_add(ptr, 1, SeqCst);
10102            }
10103        "#;
10104        let mut parser = Parser::new(source);
10105        let file = parser.parse_file().unwrap();
10106        assert_eq!(file.items.len(), 1);
10107    }
10108
10109    #[test]
10110    fn test_parse_atomic_compare_exchange() {
10111        let source = r#"
10112            rite cas(ptr: *Δ i64, expected: i64, new: i64) -> bool {
10113                ≔ result = atomic.compare_exchange(ptr, expected, new, AcqRel, Relaxed);
10114                ⤺ result;
10115            }
10116        "#;
10117        let mut parser = Parser::new(source);
10118        let file = parser.parse_file().unwrap();
10119        assert_eq!(file.items.len(), 1);
10120    }
10121
10122    #[test]
10123    fn test_parse_atomic_fence() {
10124        let source = r#"
10125            rite memory_barrier() {
10126                atomic.fence(SeqCst);
10127            }
10128        "#;
10129        let mut parser = Parser::new(source);
10130        let file = parser.parse_file().unwrap();
10131        assert_eq!(file.items.len(), 1);
10132    }
10133
10134    #[test]
10135    fn test_parse_derive_macro() {
10136        let source = r#"
10137            #[derive(Debug, Clone, Component)]
10138            sigil Position {
10139                x: f32,
10140                y: f32,
10141                z: f32,
10142            }
10143        "#;
10144        let mut parser = Parser::new(source);
10145        let file = parser.parse_file().unwrap();
10146        assert_eq!(file.items.len(), 1);
10147
10148        if let Item::Struct(s) = &file.items[0].node {
10149            assert_eq!(s.attrs.derives.len(), 3);
10150            assert!(matches!(s.attrs.derives[0], DeriveTrait::Debug));
10151            assert!(matches!(s.attrs.derives[1], DeriveTrait::Clone));
10152            assert!(matches!(s.attrs.derives[2], DeriveTrait::Component));
10153        } else {
10154            panic!("Expected struct");
10155        }
10156    }
10157
10158    #[test]
10159    fn test_parse_repr_c_struct() {
10160        let source = r#"
10161            #[repr(C)]
10162            sigil FFIStruct {
10163                field: i32,
10164            }
10165        "#;
10166        let mut parser = Parser::new(source);
10167        let file = parser.parse_file().unwrap();
10168        assert_eq!(file.items.len(), 1);
10169
10170        if let Item::Struct(s) = &file.items[0].node {
10171            assert_eq!(s.attrs.repr, Some(StructRepr::C));
10172        } else {
10173            panic!("Expected struct");
10174        }
10175    }
10176
10177    #[test]
10178    fn test_parse_allocator_trait() {
10179        let source = r#"
10180            Θ Allocator {
10181                type Error;
10182
10183                rite allocate(size: usize, align: usize) -> *Δ u8;
10184                rite deallocate(ptr: *Δ u8, size: usize, align: usize);
10185            }
10186        "#;
10187        let mut parser = Parser::new(source);
10188        let file = parser.parse_file().unwrap();
10189        assert_eq!(file.items.len(), 1);
10190
10191        if let Item::Trait(t) = &file.items[0].node {
10192            assert_eq!(t.name.name, "Allocator");
10193            assert_eq!(t.items.len(), 3); // associated type + 2 methods
10194            assert!(matches!(t.items[0], TraitItem::Type { .. }));
10195        } else {
10196            panic!("Expected trait");
10197        }
10198    }
10199
10200    #[test]
10201    fn test_parse_where_clause() {
10202        let source = r#"
10203            rite alloc_array<T, A>(allocator: &Δ A, count: usize) -> *Δ T
10204            where
10205                A: Allocator,
10206            {
10207                ⤺ allocator.allocate(count, 8);
10208            }
10209        "#;
10210        let mut parser = Parser::new(source);
10211        let file = parser.parse_file().unwrap();
10212        assert_eq!(file.items.len(), 1);
10213
10214        if let Item::Function(func) = &file.items[0].node {
10215            assert!(func.where_clause.is_some());
10216            let wc = func.where_clause.as_ref().unwrap();
10217            assert_eq!(wc.predicates.len(), 1);
10218        } else {
10219            panic!("Expected function");
10220        }
10221    }
10222}