1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
pub mod annotations;
pub mod argument;
pub mod call_apply;
pub mod call_dot;
pub mod call_subscript;
pub mod ctor;
mod dispatch;
pub mod lambda;
pub mod number;
pub mod operators;
pub mod parameter;
pub mod range;
pub mod string_template;
pub mod symbol;
pub mod tuple;

pub mod call_generic;

mod display;
use crate::{helper::ValkyrieNode, *};
use alloc::{
    boxed::Box,
    format,
    string::{String, ToString},
    vec,
    vec::Vec,
};
use core::{
    fmt::{Debug, Display, Formatter, Write},
    num::{NonZeroU64, NonZeroUsize},
    ops::Range,
};
use deriver::From;
#[cfg(feature = "lispify")]
use lispify::{Lisp, Lispify};
use nyar_error::{
    third_party::{Associativity, Precedence},
    FileID, FileSpan, NyarError, ReportKind, SyntaxError,
};
#[cfg(feature = "pretty-print")]
use pretty_print::{
    helpers::{KAndRBracket, PrettySequence},
    PrettyPrint, PrettyProvider, PrettyTree,
};
/// The ast node for an expression
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ExpressionNode {
    /// Weather to omit to results
    pub omit: bool,
    /// The expression body
    pub body: ExpressionKind,
    /// The range of the node
    pub span: Range<u32>,
}

/// Temporary node for use in the parser
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct TypingExpression {
    /// The type level expression body
    pub body: ExpressionKind,
    /// The range of the node
    pub span: Range<u32>,
}

/// Environment for expression parsing
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct ExpressionContext {
    /// Weather the expression is on type level
    pub type_level: bool,
    /// Weather the expression allow new line in postfix calls
    pub allow_newline: bool,
    /// Weather the expression allow curly braces in postfix calls
    pub allow_curly: bool,
}

/// The base expression type
#[derive(Clone, PartialEq, Eq, Hash, From)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ExpressionKind {
    /// - Placeholder expression
    Placeholder,
    /// - Atomic expression
    Null(Box<NullNode>),
    /// - Atomic expression
    Boolean(Box<BooleanNode>),
    /// - Atomic expression
    Lambda(Box<LambdaNode>),
    /// - Atomic expression
    Slot(Box<LambdaSlotNode>),
    /// - Atomic expression
    Symbol(Box<NamePathNode>),
    /// - Atomic expression
    Number(Box<NumberLiteralNode>),
    /// - Atomic expression
    Text(Box<StringTextNode>),
    /// - Atomic expression
    String(Box<StringLiteralNode>),
    /// - Atomic expression
    Formatted(Box<FormatterNode>),
    /// - Atomic expression
    New(Box<ConstructNewNode>),
    /// - Atomic expression
    Object(Box<ConstructObjectNode>),
    /// - Compound expression
    Unary(Box<UnaryNode>),
    /// - Compound expression
    Infix(Box<BinaryNode>),
    /// - Compound expression
    Tuple(Box<TupleNode>),
    /// - Compound expression
    Array(Box<RangeNode>),
    /// - Standalone expression
    If(Box<IfStatement>),
    /// - Standalone expression
    IfLet(Box<GuardStatement>),
    /// - Standalone expression
    Switch(Box<SwitchStatement>),
    /// - Standalone expression
    Match(Box<MatchStatement>),
    /// - Standalone expression
    Try(Box<TryStatement>),
    /// `@procedural() { }`
    Procedural(Box<ProceduralNode>),
    /// - Postfix expression
    ApplyCall(Box<ApplyCallNode>),
    /// - Postfix expression
    ClosureCall(Box<ClosureCallNode>),
    /// - Postfix expression
    SubscriptCall(Box<SubscriptCallNode>),
    /// - Postfix expression
    GenericCall(Box<GenericCallNode>),
    /// - Postfix expression
    DotCall(Box<DotCallNode>),
    /// - Postfix expression
    DotMatchCall(Box<MatchCallNode>),
    /// - REPL Reference
    OutputReference(Box<OutputNode>),
}

impl Default for ExpressionContext {
    fn default() -> Self {
        ExpressionContext { type_level: false, allow_newline: true, allow_curly: false }
    }
}

impl ExpressionContext {
    /// A type level expression
    pub fn in_type() -> Self {
        ExpressionContext { type_level: true, allow_newline: true, allow_curly: false }
    }
    /// A term level expression
    pub fn in_free() -> Self {
        ExpressionContext { type_level: false, allow_newline: true, allow_curly: true }
    }
    /// In a repl statement
    pub fn in_repl() -> Self {
        ExpressionContext { type_level: false, allow_newline: false, allow_curly: true }
    }
}

impl TypingExpression {
    /// Convert this node into a full expression node
    #[allow(clippy::wrong_self_convention)]
    pub fn as_normal(self) -> ExpressionNode {
        ExpressionNode { omit: true, body: self.body, span: self.span }
    }
}

impl ExpressionKind {
    /// Build a new binary expression
    pub fn binary(o: OperatorNode, lhs: Self, rhs: Self) -> Self {
        Self::Infix(Box::new(BinaryNode { infix: o, lhs, rhs }))
    }
    /// Build a new prefix expression
    pub fn prefix(o: OperatorNode, rhs: Self) -> Self {
        Self::Unary(Box::new(UnaryNode { operator: o, base: rhs }))
    }
    /// Build a new suffix expression
    pub fn suffix(o: OperatorNode, lhs: Self) -> Self {
        Self::Unary(Box::new(UnaryNode { operator: o, base: lhs }))
    }
}