Skip to main content

parser/
stmt.rs

1use crate::try_parse;
2use dynamic::{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    fn get_assign_expr(pat: Expr, expr: Expr) -> Self {
89        let span = pat.span.merge(expr.span);
90        Self::new(StmtKind::Expr(Expr::new(ExprKind::Binary { left: Box::new(pat), op: crate::BinaryOp::Assign, right: Box::new(expr) }, span), true), span)
91    }
92
93    pub fn bind_pattern(&mut self, pat: Pattern) -> Result<()> {
94        if let Some(expr) = self.expr() {
95            let stmt = match pat.kind {
96                PatternKind::Var { idx, ty } => {
97                    if expr.get_type() != ty {
98                        Self::get_assign(idx, Expr::new(ExprKind::Typed { value: Box::new(expr), ty }, pat.span))
99                    } else {
100                        Self::get_assign(idx, expr)
101                    }
102                }
103                PatternKind::Tuple(list) => {
104                    let mut stmts = Vec::new();
105                    for (idx, p) in list.into_iter().enumerate() {
106                        match p.expr() {
107                            Ok(p) => stmts.push(Self::get_idx_assign(p, idx, expr.clone())),
108                            Err(e) => return Err(e),
109                        }
110                    }
111                    Self::new(StmtKind::Block(stmts), self.span)
112                }
113                PatternKind::List { elems, has_rest } => {
114                    let mut stmts = Vec::new();
115                    let prefix_count = if has_rest { elems.len() - 1 } else { elems.len() };
116                    for (idx, p) in elems.iter().take(prefix_count).enumerate() {
117                        match p.expr() {
118                            Ok(p) => stmts.push(Self::get_idx_assign(p, idx, expr.clone())),
119                            Err(e) => return Err(e),
120                        }
121                    }
122                    if has_rest {
123                        // 最后一个元素是 `..rest`,把它绑定为 expr[prefix_count..] 的切片。
124                        let rest_pat = elems.last().unwrap();
125                        let rest_expr = match &rest_pat.kind {
126                            PatternKind::Ident { name, .. } => Expr::new(ExprKind::Ident(name.clone()), rest_pat.span),
127                            PatternKind::Var { idx, .. } => Expr::new(ExprKind::Var(*idx), rest_pat.span),
128                            _ => return Err(anyhow!("..rest 后的模式必须是标识符")),
129                        };
130                        let from = Expr::new(ExprKind::Value((prefix_count as u32).into()), rest_pat.span);
131                        let slice_idx = Expr::new(
132                            ExprKind::Binary {
133                                left: Box::new(expr.clone()),
134                                op: crate::BinaryOp::Idx,
135                                right: Box::new(Expr::new(
136                                    ExprKind::Binary { left: Box::new(from), op: crate::BinaryOp::RangeOpen, right: Box::new(Expr::new(ExprKind::Value(Dynamic::Null), rest_pat.span)) },
137                                    rest_pat.span,
138                                )),
139                            },
140                            rest_pat.span,
141                        );
142                        stmts.push(Self::get_assign_expr(rest_expr, slice_idx));
143                    }
144                    Self::new(StmtKind::Block(stmts), self.span)
145                }
146                p => return Err(anyhow!("不支持的模式绑定: {:?}", p)),
147            };
148            let _ = std::mem::replace(self, stmt);
149        } else {
150            match &mut self.kind {
151                StmtKind::Block(stmts) => {
152                    if let Some(stmt) = stmts.last_mut() {
153                        stmt.bind_pattern(pat)?;
154                    }
155                }
156                StmtKind::If { then_body, else_body, .. } => {
157                    then_body.bind_pattern(pat.clone())?;
158                    if let Some(e) = else_body {
159                        e.bind_pattern(pat)?;
160                    }
161                }
162                _ => {}
163            }
164        }
165        Ok(())
166    }
167}
168
169use std::fmt;
170impl fmt::Display for Stmt {
171    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
172        match &self.kind {
173            StmtKind::Let { pat, value } => writeln!(f, "let {:?} = {}", pat, value)?,
174            StmtKind::Block(stmts) => stmts.iter().for_each(|s| {
175                let _ = write!(f, "{}", s);
176            }),
177            StmtKind::Expr(expr, close) => writeln!(f, "{:?}[{}]", expr, close)?,
178            StmtKind::Break => writeln!(f, "break")?,
179            StmtKind::Continue => writeln!(f, "continue")?,
180            StmtKind::Return(r) => writeln!(f, "return {:?}", r)?,
181            StmtKind::While { cond, body } => write!(f, "while {:?}\n{}", cond, body)?,
182            StmtKind::Loop(body) => write!(f, "loop\n{}", body)?,
183            StmtKind::For { pat, range, body } => writeln!(f, "for {:?} in {:?} \n{}", pat, range, body)?,
184            StmtKind::If { cond, then_body, else_body } => {
185                write!(f, "if {:?}\nthen-> {}\n", cond, then_body)?;
186                if let Some(e) = else_body {
187                    writeln!(f, "{}", e)?;
188                }
189            }
190            StmtKind::Fn { name, generic_params, args, body, is_pub } => {
191                let generic_suffix = if generic_params.is_empty() { String::new() } else { format!("<{:?}>", generic_params) };
192                if *is_pub {
193                    write!(f, "pub fn {:?}{} {:?}\n", name, generic_suffix, args)?
194                } else {
195                    write!(f, "fn {:?}{} {:?}\n", name, generic_suffix, args)?
196                }
197                write!(f, "{}", body)?;
198            }
199            _ => write!(f, "(todo display: {:?})", self.kind)?,
200        }
201        fmt::Result::Ok(())
202    }
203}
204
205impl Parser {
206    pub fn ident_typed(&mut self) -> Result<(SmolStr, Type)> {
207        let name = self.ident()?;
208        self.whitespace()?;
209        if self.take(b':').is_ok() { Ok((name, self.get_type()?)) } else { Ok((name, Type::Any)) }
210    }
211
212    pub fn ident_generic(&mut self) -> Result<(SmolStr, Vec<Type>)> {
213        self.whitespace()?;
214        let name = self.ident()?;
215        self.whitespace()?;
216        let params = if self.get()? == b'<' {
217            self.pos += 1;
218            crate::parse_list!(self, Vec::new(), b'>', b',', self.get_type_param()?)
219        } else {
220            Vec::new()
221        };
222        Ok((name, params))
223    }
224
225    pub fn block(&mut self) -> Result<Stmt> {
226        self.check_fatal()?;
227        self.whitespace()?;
228        let start = self.current_pos();
229        if self.get()? == b'{' {
230            self.pos += 1;
231            self.enter_depth()?;
232            self.push_decl_scope();
233            let result = (|| -> Result<Stmt> {
234                let body = crate::parse_list!(self, Vec::new(), b'}', 0, self.stmt(false)?);
235                Ok(Stmt::new(StmtKind::Block(body), self.span_from(start)))
236            })();
237            self.pop_decl_scope();
238            self.exit_depth();
239            result
240        } else {
241            Err(anyhow!("not code block"))
242        }
243    }
244
245    pub fn if_block(&mut self) -> Result<Stmt> {
246        let start = self.spans.last().copied().unwrap_or_else(|| self.current_pos());
247        let cond = self.get_expr_without_struct_literal()?;
248        let then_body = Box::new(self.block()?);
249        self.whitespace()?;
250        let else_body = if self.keyword("else").is_ok() {
251            self.whitespace()?;
252            let body = if self.keyword("if").is_ok() { self.if_block()? } else { self.block()? };
253            Some(Box::new(body))
254        } else {
255            None
256        };
257        Ok(Stmt::new(StmtKind::If { cond, then_body, else_body }, Span::new(start, self.current_pos())))
258    }
259
260    pub fn stmt(&mut self, is_pub: bool) -> Result<Stmt> {
261        self.check_fatal()?;
262        self.whitespace()?;
263        self.spans.push(self.pos);
264        let start = self.current_pos();
265        // 函数体内不允许 fn / struct / impl / const / static 顶层声明。
266        // 编译器对这些位置直接 panic,这里前置到 parser,让错误落到用户可见的地方。
267        if self.fn_body_depth > 0 {
268            for kw in &["fn", "struct", "impl", "const", "static"] {
269                if self.keyword(kw).is_ok() {
270                    return Err(anyhow!("函数体内不能定义 {};请移到顶层或改用闭包", kw));
271                }
272            }
273        }
274        // impl body 允许 fn(方法)和 pub fn,但拒绝嵌套 struct / impl / const / static。
275        if self.impl_body_depth > 0 {
276            for kw in &["struct", "impl", "const", "static"] {
277                if self.keyword(kw).is_ok() {
278                    return Err(anyhow!("impl 体内不能定义 {};请移到顶层", kw));
279                }
280            }
281        }
282        let stmt = if self.keyword("let").is_ok() {
283            let pat = self.pattern()?;
284            self.declare_pattern_symbols(&pat)?;
285            self.until(b'=')?;
286            self.whitespace()?;
287            let value = if self.get()? == b'{' {
288                if self.looks_like_dict() {
289                    self.get_expr()?
290                } else {
291                    // 块作为表达式:{ stmts; expr } 的值是最后一条语句的值。
292                    let span = self.current_pos();
293                    let block_stmt = self.block()?;
294                    Expr::new(ExprKind::Stmt(Box::new(block_stmt)), Span::new(span, self.current_pos()))
295                }
296            } else {
297                self.get_expr()?
298            };
299            self.whitespace()?;
300            let close = self.take(b';').is_ok();
301            let stmt = Stmt::new(StmtKind::Expr(value, close), Span::new(start, self.current_pos()));
302            Stmt::new(StmtKind::Let { pat, value: Box::new(stmt) }, Span::new(start, self.current_pos()))
303        } else if self.keyword("break").is_ok() {
304            self.until(b';')?;
305            Stmt::new(StmtKind::Break, Span::new(start, self.current_pos()))
306        } else if self.keyword("continue").is_ok() {
307            self.until(b';')?;
308            Stmt::new(StmtKind::Continue, Span::new(start, self.current_pos()))
309        } else if self.keyword("return").is_ok() {
310            self.whitespace()?;
311            let expr = if matches!(self.get(), Ok(b';' | b'}')) { None } else { Some(self.get_expr()?) };
312            self.whitespace()?;
313            if self.take(b';').is_err() && !matches!(self.get(), Ok(b'}')) {
314                self.until(b';')?;
315            }
316            Stmt::new(StmtKind::Return(expr), Span::new(start, self.current_pos()))
317        } else if self.keyword("if").is_ok() {
318            self.if_block()?
319        } else if self.keyword("loop").is_ok() {
320            Stmt::new(StmtKind::Loop(Box::new(self.block()?)), Span::new(start, self.current_pos()))
321        } else if self.keyword("while").is_ok() {
322            self.whitespace()?;
323            let cond = self.get_expr()?;
324            let body = Box::new(self.block()?);
325            Stmt::new(StmtKind::While { cond, body }, Span::new(start, self.current_pos()))
326        } else if self.keyword("for").is_ok() {
327            self.whitespace()?;
328            let pat = self.pattern()?;
329            self.whitespace()?;
330            self.keyword("in")?;
331            self.whitespace()?;
332            let range = self.get_expr()?;
333            self.push_decl_scope();
334            let result: Result<Stmt> = (|| {
335                self.declare_pattern_symbols(&pat)?;
336                let body = Box::new(self.block()?);
337                Ok(Stmt::new(StmtKind::For { pat, range, body }, Span::new(start, self.current_pos())))
338            })();
339            self.pop_decl_scope();
340            result?
341        } else if self.keyword("fn").is_ok() {
342            self.whitespace()?;
343            let (name, generic_params) = self.ident_generic()?;
344            self.declare_function_name(&name)?;
345            self.until(b'(')?;
346            let args = crate::parse_list!(self, Vec::new(), b')', b',', self.ident_typed()?);
347            let body = Box::new(self.function_body(&args)?);
348            Stmt::new(StmtKind::Fn { name, generic_params, args, body, is_pub }, Span::new(start, self.current_pos()))
349        } else if self.keyword("struct").is_ok() {
350            let (name, params) = self.ident_generic()?;
351            self.declare_symbol(&name)?;
352            if self.until(b'{').is_ok() {
353                let fields = crate::parse_list!(self, Vec::new(), b'}', b',', self.ident_typed()?);
354                if let Some(f) = fields.iter().find(|f| f.1.is_any()) {
355                    return Err(anyhow!("字段 {} 的类型未知", f.0));
356                }
357                Stmt::new(StmtKind::Struct { name, def: Type::Struct { params, fields }, is_pub }, Span::new(start, self.current_pos()))
358            } else {
359                self.until(b';')?;
360                Stmt::new(StmtKind::Struct { name, def: Type::Struct { params, fields: Vec::new() }, is_pub }, Span::new(start, self.current_pos()))
361            }
362        } else if self.keyword("const").is_ok() {
363            self.whitespace()?;
364            let (name, ty) = self.ident_typed()?;
365            self.declare_symbol(&name)?;
366            self.until(b'=')?;
367            let value = self.get_expr()?;
368            self.until(b';')?;
369            Stmt::new(StmtKind::Const { name, ty, value, is_pub }, Span::new(start, self.current_pos()))
370        } else if self.keyword("static").is_ok() {
371            self.whitespace()?;
372            let (name, ty) = self.ident_typed()?;
373            self.declare_symbol(&name)?;
374            self.whitespace()?;
375            if self.take(b'=').is_ok() {
376                let expr = self.get_expr()?;
377                self.until(b';')?;
378                Stmt::new(StmtKind::Static { name, ty, value: Some(expr), is_pub }, Span::new(start, self.current_pos()))
379            } else {
380                self.until(b';')?;
381                Stmt::new(StmtKind::Static { name, ty, value: None, is_pub }, Span::new(start, self.current_pos()))
382            }
383        } else if self.keyword("impl").is_ok() {
384            self.whitespace()?;
385            let target = self.get_type()?;
386            Stmt::new(StmtKind::Impl { target, body: Box::new(self.impl_body()?) }, Span::new(start, self.current_pos()))
387        } else if self.keyword("pub").is_ok() {
388            self.stmt(true)?
389        } else {
390            let expr = if self.get()? == b'{' {
391                if self.looks_like_empty_dict() {
392                    self.dict()?
393                } else if let Ok(block) = try_parse!(self, self.block()) {
394                    let _ = self.spans.pop();
395                    return Ok(block);
396                } else if let Ok(dict) = try_parse!(self, self.dict()) {
397                    dict
398                } else {
399                    let block = self.block()?;
400                    let _ = self.spans.pop();
401                    return Ok(block);
402                }
403            } else {
404                self.get_expr()?
405            };
406            self.whitespace()?;
407            if self.is_eof() {
408                Stmt::new(StmtKind::Expr(expr, false), Span::new(start, self.current_pos()))
409            } else if self.get()? == b';' {
410                self.pos += 1;
411                Stmt::new(StmtKind::Expr(expr, true), Span::new(start, self.current_pos()))
412            } else if self.get()? == b'}' {
413                Stmt::new(StmtKind::Expr(expr, false), Span::new(start, self.current_pos()))
414            } else {
415                return Err(anyhow!("未结束的表达式"));
416            }
417        };
418        let _ = self.spans.pop();
419        Ok(stmt)
420    }
421}