Skip to main content

parser/
stmt.rs

1use crate::try_parse;
2use dynamic::Type;
3
4use super::{Expr, Parser, Pattern, Span, expr::ExprKind, pattern::PatternKind};
5use anyhow::{Result, anyhow};
6use smol_str::SmolStr;
7
8#[derive(Debug, Clone)]
9pub struct Stmt {
10    pub kind: StmtKind,
11    pub span: Span,
12}
13
14#[derive(Debug, Clone)]
15pub enum StmtKind {
16    Let { pat: Pattern, value: Box<Stmt> },
17    Expr(Expr, bool),
18    Block(Vec<Stmt>),
19    Break,
20    Continue,
21    Return(Option<Expr>),
22    While { cond: Expr, body: Box<Stmt> },
23    Loop(Box<Stmt>),
24    For { pat: Pattern, range: Expr, body: Box<Stmt> },
25    Fn { name: SmolStr, generic_params: Vec<Type>, args: Vec<(SmolStr, Type)>, body: Box<Stmt>, is_pub: bool },
26    Struct { name: SmolStr, def: Type, is_pub: bool },
27    Impl { target: Type, body: Box<Stmt> },
28    If { cond: Expr, then_body: Box<Stmt>, else_body: Option<Box<Stmt>> },
29    Static { name: SmolStr, ty: Type, value: Option<Expr>, is_pub: bool },
30    Const { name: SmolStr, ty: Type, value: Expr, is_pub: bool },
31}
32
33impl Stmt {
34    pub fn new(kind: StmtKind, span: Span) -> Self {
35        Self { kind, span }
36    }
37
38    pub fn expr(&self) -> Option<Expr> {
39        if let StmtKind::Expr(expr, _) = &self.kind { Some(expr.clone()) } else { None }
40    }
41
42    pub fn is_return(&self) -> bool {
43        matches!(self.kind, StmtKind::Return(_))
44    }
45
46    pub fn last_return(&mut self) -> bool {
47        match &mut self.kind {
48            StmtKind::Block(stmts) => stmts.last_mut().map(|stmt| stmt.last_return()).unwrap_or(false),
49            StmtKind::If { then_body, else_body, .. } => {
50                let then_returns = then_body.last_return();
51                let else_returns = else_body.as_mut().map(|body| body.last_return()).unwrap_or(false);
52                then_returns && else_returns
53            }
54            StmtKind::Expr(e, close) => {
55                if !*close {
56                    let span = e.span;
57                    *self = Self::new(StmtKind::Return(Some(std::mem::take(e))), span);
58                    true
59                } else {
60                    false
61                }
62            }
63            StmtKind::Return(_) => true,
64            _ => false,
65        }
66    }
67
68    pub fn get_type(&self) -> Option<Type> {
69        match &self.kind {
70            StmtKind::Expr(expr, _) => Some(expr.get_type()),
71            StmtKind::Block(stmts) => stmts.last().and_then(|stmt| stmt.get_type()),
72            StmtKind::If { then_body, .. } => then_body.get_type(),
73            _ => None,
74        }
75    }
76
77    fn get_assign(idx: u32, expr: Expr) -> Self {
78        let span = expr.span;
79        Self::new(StmtKind::Expr(Expr::new(ExprKind::Binary { left: Box::new(Expr::new(ExprKind::Var(idx), span)), op: crate::BinaryOp::Assign, right: Box::new(expr) }, span), true), span)
80    }
81
82    fn get_idx_assign(pat: Expr, idx: usize, expr: Expr) -> Self {
83        let span = pat.span.merge(expr.span);
84        let right = Expr::new(ExprKind::Binary { left: Box::new(expr), op: crate::BinaryOp::Idx, right: Box::new(Expr::new(ExprKind::Value((idx as u32).into()), span)) }, span);
85        Self::new(StmtKind::Expr(Expr::new(ExprKind::Binary { left: Box::new(pat), op: crate::BinaryOp::Assign, right: Box::new(right) }, span), true), span)
86    }
87
88    pub fn bind_pattern(&mut self, pat: Pattern) -> Result<()> {
89        if let Some(expr) = self.expr() {
90            let stmt = match pat.kind {
91                PatternKind::Var { idx, ty } => {
92                    if expr.get_type() != ty {
93                        Self::get_assign(idx, Expr::new(ExprKind::Typed { value: Box::new(expr), ty }, pat.span))
94                    } else {
95                        Self::get_assign(idx, expr)
96                    }
97                }
98                PatternKind::Tuple(list) | PatternKind::List { elems: list, has_rest: _ } => {
99                    let mut stmts = Vec::new();
100                    for (idx, p) in list.into_iter().enumerate() {
101                        match p.expr() {
102                            Ok(p) => stmts.push(Self::get_idx_assign(p, idx, expr.clone())),
103                            Err(e) => {
104                                println!("{:?}", e);
105                            }
106                        }
107                    }
108                    Self::new(StmtKind::Block(stmts), self.span)
109                }
110                p => panic!("{:?}", p),
111            };
112            let _ = std::mem::replace(self, stmt);
113        } else {
114            match &mut self.kind {
115                StmtKind::Block(stmts) => {
116                    stmts.last_mut().map(|stmt| stmt.bind_pattern(pat));
117                }
118                StmtKind::If { then_body, else_body, .. } => {
119                    let _ = then_body.bind_pattern(pat.clone());
120                    else_body.as_mut().map(|e| e.bind_pattern(pat));
121                }
122                _ => {}
123            }
124        }
125        Ok(())
126    }
127}
128
129use std::fmt;
130impl fmt::Display for Stmt {
131    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
132        match &self.kind {
133            StmtKind::Let { pat, value } => writeln!(f, "let {:?} = {}", pat, value)?,
134            StmtKind::Block(stmts) => stmts.iter().for_each(|s| {
135                let _ = write!(f, "{}", s);
136            }),
137            StmtKind::Expr(expr, close) => writeln!(f, "{:?}[{}]", expr, close)?,
138            StmtKind::Break => writeln!(f, "break")?,
139            StmtKind::Continue => writeln!(f, "continue")?,
140            StmtKind::Return(r) => writeln!(f, "return {:?}", r)?,
141            StmtKind::While { cond, body } => write!(f, "while {:?}\n{}", cond, body)?,
142            StmtKind::Loop(body) => write!(f, "loop\n{}", body)?,
143            StmtKind::For { pat, range, body } => writeln!(f, "for {:?} in {:?} \n{}", pat, range, body)?,
144            StmtKind::If { cond, then_body, else_body } => {
145                write!(f, "if {:?}\nthen-> {}\n", cond, then_body)?;
146                if let Some(e) = else_body {
147                    writeln!(f, "{}", e)?;
148                }
149            }
150            StmtKind::Fn { name, generic_params, args, body, is_pub } => {
151                let generic_suffix = if generic_params.is_empty() { String::new() } else { format!("<{:?}>", generic_params) };
152                if *is_pub {
153                    write!(f, "pub fn {:?}{} {:?}\n", name, generic_suffix, args)?
154                } else {
155                    write!(f, "fn {:?}{} {:?}\n", name, generic_suffix, args)?
156                }
157                write!(f, "{}", body)?;
158            }
159            _ => {
160                panic!("无效语句 {:?}", self)
161            }
162        }
163        fmt::Result::Ok(())
164    }
165}
166
167impl Parser {
168    pub fn ident_typed(&mut self) -> Result<(SmolStr, Type)> {
169        let name = self.ident()?;
170        self.whitespace()?;
171        if self.take(b':').is_ok() { Ok((name, self.get_type()?)) } else { Ok((name, Type::Any)) }
172    }
173
174    pub fn ident_generic(&mut self) -> Result<(SmolStr, Vec<Type>)> {
175        self.whitespace()?;
176        let name = self.ident()?;
177        self.whitespace()?;
178        let params = if self.get()? == b'<' {
179            self.pos += 1;
180            crate::parse_list!(self, Vec::new(), b'>', b',', self.get_type_param()?)
181        } else {
182            Vec::new()
183        };
184        Ok((name, params))
185    }
186
187    pub fn block(&mut self) -> Result<Stmt> {
188        self.whitespace()?;
189        let start = self.current_pos();
190        if self.get()? == b'{' {
191            self.pos += 1;
192            Ok(Stmt::new(StmtKind::Block(crate::parse_list!(self, Vec::new(), b'}', 0, self.stmt(false)?)), self.span_from(start)))
193        } else {
194            Err(anyhow!("not code block"))
195        }
196    }
197
198    pub fn if_block(&mut self) -> Result<Stmt> {
199        let start = self.spans.last().copied().unwrap_or_else(|| self.current_pos());
200        let cond = self.get_expr_without_struct_literal()?;
201        let then_body = Box::new(self.block()?);
202        self.whitespace()?;
203        let else_body = if self.keyword("else").is_ok() {
204            self.whitespace()?;
205            if self.keyword("if").is_ok() { self.if_block().map(Box::new).ok() } else { self.block().map(Box::new).ok() }
206        } else {
207            None
208        };
209        Ok(Stmt::new(StmtKind::If { cond, then_body, else_body }, Span::new(start, self.current_pos())))
210    }
211
212    pub fn stmt(&mut self, is_pub: bool) -> Result<Stmt> {
213        self.whitespace()?;
214        self.spans.push(self.pos);
215        let start = self.current_pos();
216        let stmt = if self.keyword("let").is_ok() {
217            let pat = self.pattern()?;
218            self.until(b'=')?;
219            self.whitespace()?;
220            let stmt = if self.get()? == b'{' {
221                if self.looks_like_dict() {
222                    let expr = self.get_expr()?;
223                    self.whitespace()?;
224                    if self.get()? == b';' {
225                        self.pos += 1;
226                    }
227                    Stmt::new(StmtKind::Expr(expr, true), Span::new(start, self.current_pos()))
228                } else {
229                    return Err(anyhow!("代码块不能直接作为表达式,请使用 || {{ ... }} 包装为匿名函数"));
230                }
231            } else {
232                let stmt = self.stmt(false)?;
233                if stmt.expr().is_none() {
234                    self.until(b';')?;
235                }
236                stmt
237            };
238            Stmt::new(StmtKind::Let { pat, value: Box::new(stmt) }, Span::new(start, self.current_pos()))
239        } else if self.keyword("break").is_ok() {
240            self.until(b';')?;
241            Stmt::new(StmtKind::Break, Span::new(start, self.current_pos()))
242        } else if self.keyword("continue").is_ok() {
243            self.until(b';')?;
244            Stmt::new(StmtKind::Continue, Span::new(start, self.current_pos()))
245        } else if self.keyword("return").is_ok() {
246            self.whitespace()?;
247            let expr = if matches!(self.get(), Ok(b';' | b'}')) { None } else { Some(self.get_expr()?) };
248            self.whitespace()?;
249            if self.take(b';').is_err() && !matches!(self.get(), Ok(b'}')) {
250                self.until(b';')?;
251            }
252            Stmt::new(StmtKind::Return(expr), Span::new(start, self.current_pos()))
253        } else if self.keyword("if").is_ok() {
254            self.if_block()?
255        } else if self.keyword("loop").is_ok() {
256            Stmt::new(StmtKind::Loop(Box::new(self.block()?)), Span::new(start, self.current_pos()))
257        } else if self.keyword("while").is_ok() {
258            self.whitespace()?;
259            let cond = self.get_expr()?;
260            let body = Box::new(self.block()?);
261            Stmt::new(StmtKind::While { cond, body }, Span::new(start, self.current_pos()))
262        } else if self.keyword("for").is_ok() {
263            self.whitespace()?;
264            let pat = self.pattern()?;
265            self.whitespace()?;
266            self.keyword("in")?;
267            self.whitespace()?;
268            let range = self.get_expr()?;
269            let body = Box::new(self.block()?);
270            Stmt::new(StmtKind::For { pat, range, body }, Span::new(start, self.current_pos()))
271        } else if self.keyword("fn").is_ok() {
272            self.whitespace()?;
273            let (name, generic_params) = self.ident_generic()?;
274            self.until(b'(')?;
275            let args = crate::parse_list!(self, Vec::new(), b')', b',', self.ident_typed()?);
276            let body = Box::new(self.block()?);
277            Stmt::new(StmtKind::Fn { name, generic_params, args, body, is_pub }, Span::new(start, self.current_pos()))
278        } else if self.keyword("struct").is_ok() {
279            let (name, params) = self.ident_generic()?;
280            if self.until(b'{').is_ok() {
281                let fields = crate::parse_list!(self, Vec::new(), b'}', b',', self.ident_typed()?);
282                if let Some(f) = fields.iter().find(|f| f.1.is_any()) {
283                    return Err(anyhow!("字段 {} 的类型未知", f.0));
284                }
285                Stmt::new(StmtKind::Struct { name, def: Type::Struct { params, fields }, is_pub }, Span::new(start, self.current_pos()))
286            } else {
287                self.until(b';')?;
288                Stmt::new(StmtKind::Struct { name, def: Type::Struct { params, fields: Vec::new() }, is_pub }, Span::new(start, self.current_pos()))
289            }
290        } else if self.keyword("const").is_ok() {
291            self.whitespace()?;
292            let (name, ty) = self.ident_typed()?;
293            self.until(b'=')?;
294            let value = self.get_expr()?;
295            self.until(b';')?;
296            Stmt::new(StmtKind::Const { name, ty, value, is_pub }, Span::new(start, self.current_pos()))
297        } else if self.keyword("static").is_ok() {
298            self.whitespace()?;
299            let (name, ty) = self.ident_typed()?;
300            self.whitespace()?;
301            if self.take(b'=').is_ok() {
302                let expr = self.get_expr()?;
303                self.until(b';')?;
304                Stmt::new(StmtKind::Static { name, ty, value: Some(expr), is_pub }, Span::new(start, self.current_pos()))
305            } else {
306                self.until(b';')?;
307                Stmt::new(StmtKind::Static { name, ty, value: None, is_pub }, Span::new(start, self.current_pos()))
308            }
309        } else if self.keyword("impl").is_ok() {
310            self.whitespace()?;
311            let target = self.get_type()?;
312            Stmt::new(StmtKind::Impl { target, body: Box::new(self.block()?) }, Span::new(start, self.current_pos()))
313        } else if self.keyword("pub").is_ok() {
314            self.stmt(true)?
315        } else {
316            let expr = if self.get()? == b'{' {
317                if self.looks_like_empty_dict() {
318                    self.dict()?
319                } else if let Ok(block) = try_parse!(self, self.block()) {
320                    let _ = self.spans.pop();
321                    return Ok(block);
322                } else if let Ok(dict) = try_parse!(self, self.dict()) {
323                    dict
324                } else {
325                    let block = self.block()?;
326                    let _ = self.spans.pop();
327                    return Ok(block);
328                }
329            } else {
330                self.get_expr()?
331            };
332            self.whitespace()?;
333            if self.is_eof() {
334                Stmt::new(StmtKind::Expr(expr, false), Span::new(start, self.current_pos()))
335            } else if self.get()? == b';' {
336                self.pos += 1;
337                Stmt::new(StmtKind::Expr(expr, true), Span::new(start, self.current_pos()))
338            } else if self.get()? == b'}' {
339                Stmt::new(StmtKind::Expr(expr, false), Span::new(start, self.current_pos()))
340            } else {
341                return Err(anyhow!("未结束的表达式"));
342            }
343        };
344        let _ = self.spans.pop();
345        Ok(stmt)
346    }
347}