1use crate::debug::DebugSymbol;
2use crate::parser::operator::{BinaryOp, UnaryOp};
3use crate::parser::primary::{Atom, Primary};
4use crate::parser::lvalue::Assignment;
5use crate::parser::fundefs::FunctionDef;
6use crate::parser::stmt::{StmtMeta, Stmt, Label, StmtList};
7
8#[derive(Debug, Clone)]
10pub enum Expr {
11
12 Atom(Atom),
13
14 Primary(Primary),
15
16 UnaryOp(UnaryOp, Box<Expr>),
17
18 BinaryOp(BinaryOp, Box<(Expr, Expr)>),
19
20 Assignment(Box<Assignment>),
21
22 Tuple(Box<[ExprMeta]>),
23
24 Unpack(Option<Box<Expr>>),
25
26 IfExpr {
29 branches: Box<[ConditionalBranch]>,
30 else_clause: Option<Box<ExprBlock>>,
31 },
32
33 Block {
34 label: Option<Label>,
35 suite: Box<ExprBlock>,
36 },
37
38 FunctionDef(FunctionDef),
39
40 }
43
44
45#[derive(Debug, Clone)]
47pub struct ExprBlock {
48 stmt_list: StmtList,
49 result: Option<ExprMeta>,
50}
51
52impl From<StmtList> for ExprBlock {
53 fn from(stmt_list: StmtList) -> Self {
54 let (mut suite, control) = stmt_list.take();
55
56 let mut result = None;
57 if control.is_none() && !suite.is_empty() {
58 match ExprMeta::try_from(suite.pop().unwrap()) {
59 Err(stmt) => suite.push(stmt), Ok(expr) => { result.replace(expr); },
61 }
62 }
63
64 let stmt_list = StmtList::new(suite, control);
65 Self { stmt_list, result }
66 }
67}
68
69impl ExprBlock {
70 pub fn stmt_list(&self) -> &StmtList { &self.stmt_list }
71 pub fn result(&self) -> Option<&ExprMeta> { self.result.as_ref() }
72}
73
74
75
76#[derive(Debug, Clone)]
77pub struct ConditionalBranch {
78 condition: Expr,
79 suite: ExprBlock,
80}
81
82impl ConditionalBranch {
83 pub fn new(condition: Expr, suite: ExprBlock) -> Self {
84 Self { condition, suite }
85 }
86
87 pub fn condition(&self) -> &Expr { &self.condition }
88 pub fn suite(&self) -> &ExprBlock { &self.suite }
89}
90
91
92#[derive(Debug, Clone)]
94pub struct ExprMeta {
95 variant: Expr,
96 symbol: DebugSymbol,
97}
98
99impl ExprMeta {
100 pub fn new(variant: Expr, symbol: DebugSymbol) -> Self {
101 ExprMeta { variant, symbol }
102 }
103
104 pub fn variant(&self) -> &Expr { &self.variant }
105 pub fn take_variant(self) -> Expr { self.variant }
106
107 pub fn debug_symbol(&self) -> &DebugSymbol { &self.symbol }
108 pub fn take_symbol(self) -> DebugSymbol { self.symbol }
109
110 pub fn take(self) -> (Expr, DebugSymbol) { (self.variant, self.symbol) }
111}
112
113impl From<ExprMeta> for (Expr, DebugSymbol) {
114 fn from(expr: ExprMeta) -> Self { (expr.variant, expr.symbol) }
115}
116
117
118
119impl From<Expr> for Stmt {
122 #[inline]
123 fn from(expr: Expr) -> Self { Stmt::Expression(expr) }
124}
125
126impl TryFrom<Stmt> for Expr {
127 type Error = Stmt;
128
129 #[inline]
130 fn try_from(stmt: Stmt) -> Result<Self, Stmt> {
131 if let Stmt::Expression(expr) = stmt { Ok(expr) }
132 else { Err(stmt) }
133 }
134}
135
136impl TryFrom<StmtMeta> for Expr {
137 type Error = StmtMeta;
138
139 #[inline]
140 fn try_from(stmt: StmtMeta) -> Result<Self, StmtMeta> {
141 let (stmt, symbol) = stmt.take();
142 if let Stmt::Expression(expr) = stmt { Ok(expr) }
143 else { Err(StmtMeta::new(stmt, symbol)) }
144 }
145}
146
147
148impl From<ExprMeta> for StmtMeta {
149 #[inline]
150 fn from(expr: ExprMeta) -> Self {
151 let (expr, symbol) = expr.take();
152 StmtMeta::new(expr.into(), symbol)
153 }
154}
155
156impl TryFrom<StmtMeta> for ExprMeta {
157 type Error = StmtMeta;
158
159 #[inline]
160 fn try_from(stmt: StmtMeta) -> Result<Self, StmtMeta> {
161 let (stmt, symbol) = stmt.take();
162 match Expr::try_from(stmt) {
163 Ok(expr) => Ok(ExprMeta::new(expr, symbol)),
164 Err(stmt) => Err(StmtMeta::new(stmt, symbol)),
165 }
166 }
167}