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/// 把 pattern 引入的所有变量绑定生成出来,追加到 `out`。
9/// `access` 是该 pattern 整体对应的访问表达式(如 `__m_scrut` 或 `__m_scrut.field`)。
10fn collect_bindings(pat: &Pattern, access: &Expr, out: &mut Vec<Stmt>, span: Span) {
11    use crate::expr::BinaryOp;
12    let mk_let_ident = |name: SmolStr, value: Expr, span: Span| {
13        let p = Pattern::new(PatternKind::Ident { name, ty: Type::Any }, span);
14        let value_stmt = Stmt::new(StmtKind::Expr(value, true), span);
15        Stmt::new(StmtKind::Let { pat: p, value: Box::new(value_stmt) }, span)
16    };
17    let mk_bin = |left: Expr, op: BinaryOp, right: Expr, span: Span| Expr::new(ExprKind::Binary { left: Box::new(left), op, right: Box::new(right) }, span);
18    let mk_idx_int = |obj: Expr, i: i32, span: Span| mk_bin(obj, BinaryOp::Idx, Expr::new(ExprKind::Value(Dynamic::I32(i)), span), span);
19    let mk_field = |obj: Expr, name: SmolStr, span: Span| mk_bin(obj, BinaryOp::Idx, Expr::new(ExprKind::Value(Dynamic::String(name)), span), span);
20
21    match &pat.kind {
22        PatternKind::Ident { name, .. } => {
23            out.push(mk_let_ident(name.clone(), access.clone(), span));
24        }
25        PatternKind::Tuple(items) => {
26            for (i, p) in items.iter().enumerate() {
27                let elem = mk_idx_int(access.clone(), i as i32, span);
28                collect_bindings(p, &elem, out, span);
29            }
30        }
31        PatternKind::List { elems, has_rest } => {
32            let prefix = if *has_rest { elems.len() - 1 } else { elems.len() };
33            for (i, p) in elems.iter().take(prefix).enumerate() {
34                let elem = mk_idx_int(access.clone(), i as i32, span);
35                collect_bindings(p, &elem, out, span);
36            }
37            if *has_rest {
38                if let PatternKind::Ident { name, .. } = &elems.last().unwrap().kind {
39                    // 切片: access[prefix..];用 `ExprKind::Range` 而不是 `Binary{RangeOpen}`,
40                    // 与 parser 产物一致,这样下游 type infer / 优化都走同一条路径。
41                    let from = Expr::new(ExprKind::Value((prefix as u32).into()), span);
42                    let range = Expr::new(ExprKind::Range { start: Box::new(from), stop: Box::new(Expr::new(ExprKind::Value(Dynamic::Null), span)), inclusive: false }, span);
43                    let slice = Expr::new(ExprKind::Binary { left: Box::new(access.clone()), op: BinaryOp::Idx, right: Box::new(range) }, span);
44                    out.push(mk_let_ident(name.clone(), slice, span));
45                }
46            }
47        }
48        PatternKind::Struct { fields, .. } => {
49            for (fname, sub) in fields {
50                let field_access = mk_field(access.clone(), fname.clone(), span);
51                match sub {
52                    None => {
53                        // 简写 `field` —— 绑定同名变量
54                        out.push(mk_let_ident(fname.clone(), field_access, span));
55                    }
56                    Some(sub_pat) => {
57                        collect_bindings(sub_pat, &field_access, out, span);
58                    }
59                }
60            }
61        }
62        // 其它(Wildcard / Literal / Var / Member / Idx)在 match 上下文中不产生绑定
63        _ => {}
64    }
65}
66
67#[derive(Debug, Clone)]
68pub struct Stmt {
69    pub kind: StmtKind,
70    pub span: Span,
71}
72
73#[derive(Debug, Clone)]
74pub enum StmtKind {
75    Let { pat: Pattern, value: Box<Stmt> },
76    Expr(Expr, bool),
77    Block(Vec<Stmt>),
78    Break,
79    Continue,
80    Return(Option<Expr>),
81    While { cond: Expr, body: Box<Stmt> },
82    Loop(Box<Stmt>),
83    For { pat: Pattern, range: Expr, body: Box<Stmt> },
84    Fn { name: SmolStr, generic_params: Vec<Type>, args: Vec<(SmolStr, Type)>, body: Box<Stmt>, is_pub: bool },
85    Struct { name: SmolStr, def: Type, is_pub: bool },
86    Impl { target: Type, body: Box<Stmt> },
87    If { cond: Expr, then_body: Box<Stmt>, else_body: Option<Box<Stmt>> },
88    Static { name: SmolStr, ty: Type, value: Option<Expr>, is_pub: bool },
89    Import { module: SmolStr, path: SmolStr, is_pub: bool },
90    Const { name: SmolStr, ty: Type, value: Expr, is_pub: bool },
91}
92
93impl Stmt {
94    pub fn new(kind: StmtKind, span: Span) -> Self {
95        Self { kind, span }
96    }
97
98    pub fn expr(&self) -> Option<Expr> {
99        if let StmtKind::Expr(expr, _) = &self.kind { Some(expr.clone()) } else { None }
100    }
101
102    pub fn is_return(&self) -> bool {
103        matches!(self.kind, StmtKind::Return(_))
104    }
105
106    pub fn last_return(&mut self) -> bool {
107        match &mut self.kind {
108            StmtKind::Block(stmts) => stmts.last_mut().map(|stmt| stmt.last_return()).unwrap_or(false),
109            StmtKind::If { then_body, else_body, .. } => {
110                let then_returns = then_body.last_return();
111                let else_returns = else_body.as_mut().map(|body| body.last_return()).unwrap_or(false);
112                then_returns && else_returns
113            }
114            StmtKind::Expr(e, close) => {
115                if !*close {
116                    let span = e.span;
117                    *self = Self::new(StmtKind::Return(Some(std::mem::take(e))), span);
118                    true
119                } else {
120                    false
121                }
122            }
123            StmtKind::Return(_) => true,
124            _ => false,
125        }
126    }
127
128    pub fn get_type(&self) -> Option<Type> {
129        match &self.kind {
130            StmtKind::Expr(expr, _) => Some(expr.get_type()),
131            StmtKind::Block(stmts) => stmts.last().and_then(|stmt| stmt.get_type()),
132            StmtKind::If { then_body, .. } => then_body.get_type(),
133            _ => None,
134        }
135    }
136
137    fn get_assign(idx: u32, expr: Expr) -> Self {
138        let span = expr.span;
139        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)
140    }
141
142    fn get_idx_assign(pat: Expr, idx: usize, expr: Expr) -> Self {
143        let span = pat.span.merge(expr.span);
144        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);
145        Self::new(StmtKind::Expr(Expr::new(ExprKind::Binary { left: Box::new(pat), op: crate::BinaryOp::Assign, right: Box::new(right) }, span), true), span)
146    }
147
148    /// 与 `get_idx_assign` 类似,但把右侧索引读取包成 `Typed { value, ty }`。
149    /// 解构生成的 `arr[i]` 默认返回 `Any`(指向 Dynamic 的指针),
150    /// 不加类型标注的话元素槽会被声明成 Any,后续读取拿到的是裸指针而不是值。
151    /// 这里按模式里推导出的元素类型 `ty` 包一层 `Typed`,让 JIT 走 Any→ty 的转换。
152    fn get_idx_assign_typed(pat: Expr, idx: usize, expr: Expr, ty: Type) -> Self {
153        let span = pat.span.merge(expr.span);
154        let idx_expr = 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);
155        let right = Expr::new(ExprKind::Typed { value: Box::new(idx_expr), ty }, span);
156        Self::new(StmtKind::Expr(Expr::new(ExprKind::Binary { left: Box::new(pat), op: crate::BinaryOp::Assign, right: Box::new(right) }, span), true), span)
157    }
158
159    fn get_assign_expr(pat: Expr, expr: Expr) -> Self {
160        let span = pat.span.merge(expr.span);
161        Self::new(StmtKind::Expr(Expr::new(ExprKind::Binary { left: Box::new(pat), op: crate::BinaryOp::Assign, right: Box::new(expr) }, span), true), span)
162    }
163
164    fn var_expr_with_ty(pat: &Pattern) -> Option<(Expr, Type)> {
165        if let PatternKind::Var { idx, ty } = &pat.kind
166            && !ty.is_any()
167        {
168            Some((Expr::new(ExprKind::Var(*idx), pat.span), ty.clone()))
169        } else {
170            None
171        }
172    }
173
174    pub fn bind_pattern(&mut self, pat: Pattern) -> Result<()> {
175        if let Some(expr) = self.expr() {
176            let stmt = match pat.kind {
177                PatternKind::Var { idx, ty } => {
178                    if expr.get_type() != ty {
179                        Self::get_assign(idx, Expr::new(ExprKind::Typed { value: Box::new(expr), ty }, pat.span))
180                    } else {
181                        Self::get_assign(idx, expr)
182                    }
183                }
184                PatternKind::Tuple(list) => {
185                    let mut stmts = Vec::new();
186                    for (idx, p) in list.into_iter().enumerate() {
187                        match Self::var_expr_with_ty(&p) {
188                            Some((p, ty)) => stmts.push(Self::get_idx_assign_typed(p, idx, expr.clone(), ty)),
189                            None => match p.expr() {
190                                Ok(p) => stmts.push(Self::get_idx_assign(p, idx, expr.clone())),
191                                Err(e) => return Err(e),
192                            },
193                        }
194                    }
195                    Self::new(StmtKind::Block(stmts), self.span)
196                }
197                PatternKind::List { elems, has_rest } => {
198                    let mut stmts = Vec::new();
199                    let prefix_count = if has_rest { elems.len() - 1 } else { elems.len() };
200                    if has_rest {
201                        for (idx, p) in elems.iter().take(prefix_count).enumerate() {
202                            match Self::var_expr_with_ty(p) {
203                                Some((p, ty)) => stmts.push(Self::get_idx_assign_typed(p, idx, expr.clone(), ty)),
204                                None => match p.expr() {
205                                    Ok(p) => stmts.push(Self::get_idx_assign(p, idx, expr.clone())),
206                                    Err(e) => return Err(e),
207                                },
208                            }
209                        }
210                    } else {
211                        for (idx, p) in elems.iter().enumerate() {
212                            match Self::var_expr_with_ty(p) {
213                                Some((p, ty)) => stmts.push(Self::get_idx_assign_typed(p, idx, expr.clone(), ty)),
214                                None => match p.expr() {
215                                    Ok(p) => stmts.push(Self::get_idx_assign(p, idx, expr.clone())),
216                                    Err(e) => return Err(e),
217                                },
218                            }
219                        }
220                    }
221                    if has_rest {
222                        // 最后一个元素是 `..rest`,把它绑定为 expr[prefix_count..] 的切片。
223                        let rest_pat = elems.last().unwrap();
224                        let rest_expr = match &rest_pat.kind {
225                            PatternKind::Ident { name, .. } => Expr::new(ExprKind::Ident(name.clone()), rest_pat.span),
226                            PatternKind::Var { idx, .. } => Expr::new(ExprKind::Var(*idx), rest_pat.span),
227                            _ => return Err(anyhow!("..rest 后的模式必须是标识符")),
228                        };
229                        let from = Expr::new(ExprKind::Value((prefix_count as u32).into()), rest_pat.span);
230                        // 用 `ExprKind::Range` 与 parser 产物对齐,确保下游 type infer 走切片分支。
231                        let range = Expr::new(ExprKind::Range { start: Box::new(from), stop: Box::new(Expr::new(ExprKind::Value(Dynamic::Null), rest_pat.span)), inclusive: false }, rest_pat.span);
232                        let slice_idx = Expr::new(ExprKind::Binary { left: Box::new(expr.clone()), op: crate::BinaryOp::Idx, right: Box::new(range) }, rest_pat.span);
233                        stmts.push(Self::get_assign_expr(rest_expr, slice_idx));
234                    }
235                    Self::new(StmtKind::Block(stmts), self.span)
236                }
237                p => return Err(anyhow!("不支持的模式绑定: {:?}", p)),
238            };
239            let _ = std::mem::replace(self, stmt);
240        } else {
241            match &mut self.kind {
242                StmtKind::Block(stmts) => {
243                    if let Some(stmt) = stmts.last_mut() {
244                        stmt.bind_pattern(pat)?;
245                    }
246                }
247                StmtKind::If { then_body, else_body, .. } => {
248                    then_body.bind_pattern(pat.clone())?;
249                    if let Some(e) = else_body {
250                        e.bind_pattern(pat)?;
251                    }
252                }
253                _ => {}
254            }
255        }
256        Ok(())
257    }
258}
259
260use std::fmt;
261impl fmt::Display for Stmt {
262    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
263        match &self.kind {
264            StmtKind::Let { pat, value } => writeln!(f, "let {:?} = {}", pat, value)?,
265            StmtKind::Block(stmts) => stmts.iter().for_each(|s| {
266                let _ = write!(f, "{}", s);
267            }),
268            StmtKind::Expr(expr, close) => writeln!(f, "{:?}[{}]", expr, close)?,
269            StmtKind::Break => writeln!(f, "break")?,
270            StmtKind::Continue => writeln!(f, "continue")?,
271            StmtKind::Return(r) => writeln!(f, "return {:?}", r)?,
272            StmtKind::While { cond, body } => write!(f, "while {:?}\n{}", cond, body)?,
273            StmtKind::Loop(body) => write!(f, "loop\n{}", body)?,
274            StmtKind::For { pat, range, body } => writeln!(f, "for {:?} in {:?} \n{}", pat, range, body)?,
275            StmtKind::If { cond, then_body, else_body } => {
276                write!(f, "if {:?}\nthen-> {}\n", cond, then_body)?;
277                if let Some(e) = else_body {
278                    writeln!(f, "{}", e)?;
279                }
280            }
281            StmtKind::Fn { name, generic_params, args, body, is_pub } => {
282                let generic_suffix = if generic_params.is_empty() { String::new() } else { format!("<{:?}>", generic_params) };
283                if *is_pub {
284                    write!(f, "pub fn {:?}{} {:?}\n", name, generic_suffix, args)?
285                } else {
286                    write!(f, "fn {:?}{} {:?}\n", name, generic_suffix, args)?
287                }
288                write!(f, "{}", body)?;
289            }
290            StmtKind::Import { module, path, is_pub } => {
291                if *is_pub {
292                    writeln!(f, "pub import {:?}, {:?};", module, path)?
293                } else {
294                    writeln!(f, "import {:?}, {:?};", module, path)?
295                }
296            }
297            _ => write!(f, "(todo display: {:?})", self.kind)?,
298        }
299        fmt::Result::Ok(())
300    }
301}
302
303impl Parser {
304    pub fn ident_typed(&mut self) -> Result<(SmolStr, Type)> {
305        let name = self.ident()?;
306        self.whitespace()?;
307        if self.take(b':').is_ok() { Ok((name, self.get_type()?)) } else { Ok((name, Type::Any)) }
308    }
309
310    pub fn ident_generic(&mut self) -> Result<(SmolStr, Vec<Type>)> {
311        self.whitespace()?;
312        let name = self.ident()?;
313        self.whitespace()?;
314        let params = if self.get()? == b'<' {
315            self.pos += 1;
316            crate::parse_list!(self, Vec::new(), b'>', b',', self.get_type_param()?)
317        } else {
318            Vec::new()
319        };
320        Ok((name, params))
321    }
322
323    pub fn block(&mut self) -> Result<Stmt> {
324        self.check_fatal()?;
325        self.whitespace()?;
326        let start = self.current_pos();
327        if self.get()? == b'{' {
328            self.pos += 1;
329            self.enter_depth()?;
330            self.push_decl_scope();
331            let result = (|| -> Result<Stmt> {
332                let body = crate::parse_list!(self, Vec::new(), b'}', 0, self.stmt(false)?);
333                Ok(Stmt::new(StmtKind::Block(body), self.span_from(start)))
334            })();
335            self.pop_decl_scope();
336            self.exit_depth();
337            result
338        } else {
339            Err(anyhow!("not code block"))
340        }
341    }
342
343    pub fn if_block(&mut self) -> Result<Stmt> {
344        let start = self.spans.last().copied().unwrap_or_else(|| self.current_pos());
345        let cond = self.get_expr_without_struct_literal()?;
346        let then_body = Box::new(self.block()?);
347        self.whitespace()?;
348        let else_body = if self.keyword("else").is_ok() {
349            self.whitespace()?;
350            let body = if self.keyword("if").is_ok() { self.if_block()? } else { self.block()? };
351            Some(Box::new(body))
352        } else {
353            None
354        };
355        Ok(Stmt::new(StmtKind::If { cond, then_body, else_body }, Span::new(start, self.current_pos())))
356    }
357
358    /// 解析 `match scrut { pat ("|" pat)* ("if" guard)? => body ","? ... }`,
359    /// desugar 成 `Block + Let + If 链 + 临时变量`,返回顶层 `Block`(再由
360    /// 调用方用 `ExprKind::Stmt` 包成表达式)。
361    pub fn match_block(&mut self, start: usize) -> Result<Stmt> {
362        use crate::expr::{BinaryOp, ExprKind, UnaryOp};
363        use crate::pattern::{Pattern, PatternKind};
364
365        // ---- 一、解析阶段 ----
366        let scrut = self.get_expr_without_struct_literal()?;
367        self.whitespace()?;
368        self.take(b'{').map_err(|_| anyhow!("match 缺少 `{{`"))?;
369
370        // 每个 arm 是 (pats: Vec<Pattern>, guard: Option<Expr>, body: Expr)
371        let mut arms: Vec<(Vec<Pattern>, Option<Expr>, Expr)> = Vec::new();
372        loop {
373            self.whitespace()?;
374            if self.take(b'}').is_ok() {
375                break;
376            }
377            self.push_decl_scope();
378            let arm_res: Result<(Vec<Pattern>, Option<Expr>, Expr)> = (|| {
379                // 一组 pattern(用 `|` 分隔,or-pattern)
380                let mut pats = vec![self.pattern()?];
381                self.whitespace()?;
382                while matches!(self.get(), Ok(b'|')) && !matches!(self.ahead(), Ok(b'|')) {
383                    self.pos += 1;
384                    self.whitespace()?;
385                    pats.push(self.pattern()?);
386                    self.whitespace()?;
387                }
388                // 声明 pattern 引入的变量(对每个 alt 都声明,允许重名 → 由
389                // declare_symbol_in_current_scope 容错;这里我们只用第一个 alt 的 binding)
390                for pat in &pats[..1] {
391                    self.declare_pattern_symbols(pat)?;
392                }
393                // or-pattern:第二及之后的 alt 现在支持任意 pattern(不再限制为 Literal/Wildcard)。
394                // 注意:绑定只取第一个 alt(collect_bindings(&pats[0])),
395                // 若其它 alt 匹配且 body 引用了第一个 alt 的变量,该变量未绑定(读默认/Null)。
396                // 动态语言语义下这是用户责任;Rust 要求 or-pattern 绑定一致,zust 更宽松。
397                // 可选 guard
398                self.whitespace()?;
399                let guard = if self.keyword("if").is_ok() {
400                    self.whitespace()?;
401                    Some(self.get_expr_no_assign()?)
402                } else {
403                    None
404                };
405                // `=>`
406                self.whitespace()?;
407                self.just("=>").map_err(|_| anyhow!("match arm 缺少 `=>`"))?;
408                self.whitespace()?;
409                // 体
410                let body_start = self.current_pos();
411                let body = if self.get()? == b'{' {
412                    let block_stmt = self.block()?;
413                    Expr::new(ExprKind::Stmt(Box::new(block_stmt)), Span::new(body_start, self.current_pos()))
414                } else {
415                    // body 也用 no_assign 防止 `=> body, ...` 中 `,` 后或下一 arm
416                    // 的 `=>` 被错误吞入(同时仍允许 +-*/ 等正常二元)。
417                    self.get_expr_no_assign()?
418                };
419                // 容忍尾随逗号
420                self.whitespace()?;
421                let _ = self.take(b',');
422                Ok((pats, guard, body))
423            })();
424            self.pop_decl_scope();
425            arms.push(arm_res?);
426        }
427        let span = Span::new(start, self.current_pos());
428
429        // ---- 二、声明 match 顶层临时变量 ----
430        // 为避免嵌套 match 重名,加 counter 后缀(简单递增,parser 本地状态)
431        let suffix = self.match_counter;
432        self.match_counter += 1;
433        let scrut_name: SmolStr = format!("__m_scrut_{}", suffix).into();
434        let done_name: SmolStr = format!("__m_done_{}", suffix).into();
435        let out_name: SmolStr = format!("__m_out_{}", suffix).into();
436        self.declare_symbol_in_current_scope(&scrut_name)?;
437        self.declare_symbol_in_current_scope(&done_name)?;
438        self.declare_symbol_in_current_scope(&out_name)?;
439
440        // ---- 三、构建顶层 Block ----
441        let mk_ident = |name: &SmolStr, span: Span| Expr::new(ExprKind::Ident(name.clone()), span);
442        let mk_value = |v: Dynamic, span: Span| Expr::new(ExprKind::Value(v), span);
443        let mk_binary = |left: Expr, op: BinaryOp, right: Expr, span: Span| Expr::new(ExprKind::Binary { left: Box::new(left), op, right: Box::new(right) }, span);
444        let mk_let = |name: SmolStr, value: Expr, span: Span| {
445            let pat = Pattern::new(PatternKind::Ident { name, ty: Type::Any }, span);
446            let value_stmt = Stmt::new(StmtKind::Expr(value, true), span);
447            Stmt::new(StmtKind::Let { pat, value: Box::new(value_stmt) }, span)
448        };
449        let mk_assign_stmt = |name: &SmolStr, value: Expr, span: Span| {
450            let assign = mk_binary(mk_ident(name, span), BinaryOp::Assign, value, span);
451            Stmt::new(StmtKind::Expr(assign, true), span)
452        };
453        let mk_any = |value: Expr, span: Span| Expr::new(ExprKind::Typed { value: Box::new(value), ty: Type::Any }, span);
454
455        let mut stmts = Vec::new();
456        // let __m_scrut = SCRUT;
457        stmts.push(mk_let(scrut_name.clone(), scrut, span));
458        // let __m_done = false;
459        stmts.push(mk_let(done_name.clone(), mk_value(Dynamic::Bool(false), span), span));
460        // let __m_out = null;
461        stmts.push(mk_let(out_name.clone(), mk_value(Dynamic::Null, span), span));
462
463        // 每个 arm 一个 if(顺序构造)
464        for (pats, guard, body) in arms {
465            let arm_span = body.span;
466            let scrut_ident = mk_ident(&scrut_name, arm_span);
467            // test = pat[0].test || pat[1].test || ...
468            let mut test_chain = pats[0].match_test(&scrut_ident);
469            for p in &pats[1..] {
470                let t = p.match_test(&scrut_ident);
471                test_chain = mk_binary(test_chain, BinaryOp::Or, t, arm_span);
472            }
473            // !__m_done && (test_chain)
474            let not_done = Expr::new(ExprKind::Unary { op: UnaryOp::Not, value: Box::new(mk_ident(&done_name, arm_span)) }, arm_span);
475            let outer_cond = mk_binary(not_done, BinaryOp::And, test_chain, arm_span);
476
477            // arm body block:bind + guard + assign + done
478            let mut body_stmts = Vec::new();
479            collect_bindings(&pats[0], &mk_ident(&scrut_name, arm_span), &mut body_stmts, arm_span);
480            // 内层 body:__m_out = BODY; __m_done = true;
481            let inner_stmts = vec![mk_assign_stmt(&out_name, mk_any(body, arm_span), arm_span), mk_assign_stmt(&done_name, mk_value(Dynamic::Bool(true), arm_span), arm_span)];
482            let inner_block = Stmt::new(StmtKind::Block(inner_stmts), arm_span);
483            // 如果有 guard,再裹一层 if;否则直接展开
484            if let Some(g) = guard {
485                body_stmts.push(Stmt::new(StmtKind::If { cond: g, then_body: Box::new(inner_block), else_body: None }, arm_span));
486            } else {
487                body_stmts.push(inner_block);
488            }
489            let then_body = Stmt::new(StmtKind::Block(body_stmts), arm_span);
490            stmts.push(Stmt::new(StmtKind::If { cond: outer_cond, then_body: Box::new(then_body), else_body: None }, arm_span));
491        }
492        // 末尾求值:__m_out
493        stmts.push(Stmt::new(StmtKind::Expr(mk_any(mk_ident(&out_name, span), span), false), span));
494
495        Ok(Stmt::new(StmtKind::Block(stmts), span))
496    }
497
498    /// 在 stmt 顶层 peek 一下,判断接下来的 token 是不是 `import` 顶层
499    /// 声明(`import "name";` 或 `import "name", "path";`)。区分点:
500    /// 声明形式是 `import` 后跟空白+字符串字面量(`"`)或 ident;
501    /// 函数调用形式是 `import(...)`,`import` 后紧跟 `(` —— 这种仍走
502    /// 普通表达式路径(`import` ident + 调用)。`import` 关键字不进
503    /// KEYWORDS 列表就是为了让函数调用形式继续 work。
504    fn peek_import_top_level(&self) -> bool {
505        let rest = &self.buf[self.pos..];
506        let Some(after_kw) = rest.strip_prefix(b"import") else {
507            return false;
508        };
509        // import 后必须是空白
510        let Some(&first) = after_kw.first() else {
511            return false;
512        };
513        if !first.is_ascii_whitespace() {
514            return false;
515        }
516        // 跳过空白, peek 第一个非空白字符
517        let mut after_ws = after_kw.iter().skip_while(|b| b.is_ascii_whitespace());
518        matches!(after_ws.next(), Some(b'"'))
519    }
520
521    pub fn stmt(&mut self, is_pub: bool) -> Result<Stmt> {
522        self.check_fatal()?;
523        self.whitespace()?;
524        // RAII 守卫:无论 stmt 内部走哪个分支(包括 import / let / fn
525        // 等 `?` 提前返回),`spans` 都会被清理,错误消息 [`error_stmt`] 不会读到
526        // 残留的旧 span。
527        let _span_guard = self.with_stmt_span();
528        let start = self.current_pos();
529        // 函数体内不允许 fn / struct / impl / const / static 顶层声明。
530        // 编译器对这些位置直接 panic,这里前置到 parser,让错误落到用户可见的地方。
531        if self.scope_depths.fn_body_depth > 0 {
532            for kw in &["fn", "struct", "impl", "const", "static"] {
533                if self.keyword(kw).is_ok() {
534                    return Err(anyhow!("函数体内不能定义 {};请移到顶层或改用闭包", kw));
535                }
536            }
537        }
538        // impl body 允许 fn(方法)和 pub fn,但拒绝嵌套 struct / impl / const / static。
539        if self.scope_depths.impl_body_depth > 0 {
540            for kw in &["struct", "impl", "const", "static"] {
541                if self.keyword(kw).is_ok() {
542                    return Err(anyhow!("impl 体内不能定义 {};请移到顶层", kw));
543                }
544            }
545        }
546        let stmt = if self.peek_import_top_level() {
547            // 顶层 import 声明:`import "module";` 或 `import "module", "path";`。
548            // 必须用 `peek` 而不是 `keyword`,因为 `import` 在 HEAD 下不
549            // 在 KEYWORDS 列表里 —— `import(...)` 函数调用形式仍要把
550            // `import` 当 ident 通过表达式解析路径走通。
551            // 区分要点:声明形式 `import` 后面是空白+字符串/ident;
552            // 函数调用形式 `import` 后面是 `(`。只在 stmt 顶层做这个判断。
553            if self.scope_depths.fn_body_depth > 0 || self.scope_depths.impl_body_depth > 0 {
554                return Err(anyhow!("import 只能作为顶层声明;请写在模块顶层"));
555            }
556            self.just("import").map_err(|_| anyhow!("expected import"))?;
557            self.whitespace()?;
558            let module = match self.get_expr()?.kind {
559                ExprKind::Value(Dynamic::String(value)) => value,
560                ExprKind::Ident(value) => value,
561                other => return Err(anyhow!("import 模块名必须是字符串或标识符,实际是 {:?}", other)),
562            };
563            self.whitespace()?;
564            let path = if self.take(b',').is_ok() {
565                self.whitespace()?;
566                match self.get_expr()?.kind {
567                    ExprKind::Value(Dynamic::String(value)) => value,
568                    ExprKind::Ident(value) => value,
569                    other => return Err(anyhow!("import 路径必须是字符串或标识符,实际是 {:?}", other)),
570                }
571            } else {
572                format!("{module}.zs").into()
573            };
574            self.until(b';')?;
575            Stmt::new(StmtKind::Import { module, path, is_pub }, Span::new(start, self.current_pos()))
576        } else if self.keyword("let").is_ok() {
577            let pat = self.pattern()?;
578            self.declare_pattern_symbols(&pat)?;
579            self.until(b'=')?;
580            self.whitespace()?;
581            let value = if self.get()? == b'{' {
582                if self.looks_like_dict() {
583                    self.get_expr()?
584                } else {
585                    // 块作为表达式:{ stmts; expr } 的值是最后一条语句的值。
586                    let span = self.current_pos();
587                    let block_stmt = self.block()?;
588                    Expr::new(ExprKind::Stmt(Box::new(block_stmt)), Span::new(span, self.current_pos()))
589                }
590            } else {
591                self.get_expr()?
592            };
593            self.whitespace()?;
594            let close = self.take(b';').is_ok();
595            let stmt = Stmt::new(StmtKind::Expr(value, close), Span::new(start, self.current_pos()));
596            Stmt::new(StmtKind::Let { pat, value: Box::new(stmt) }, Span::new(start, self.current_pos()))
597        } else if self.keyword("break").is_ok() {
598            self.until(b';')?;
599            Stmt::new(StmtKind::Break, Span::new(start, self.current_pos()))
600        } else if self.keyword("continue").is_ok() {
601            self.until(b';')?;
602            Stmt::new(StmtKind::Continue, Span::new(start, self.current_pos()))
603        } else if self.keyword("return").is_ok() {
604            self.whitespace()?;
605            let expr = if matches!(self.get(), Ok(b';' | b'}')) { None } else { Some(self.get_expr()?) };
606            self.whitespace()?;
607            if self.take(b';').is_err() && !matches!(self.get(), Ok(b'}')) {
608                // return 表达式后必须是 ; 或 }(语句/块结束)。
609                // 原先用 until(';') 会贪婪消费到下一个分号,可能吞掉合法代码
610                // (如 return (a, b), c 里的 , c)。改为报错,让用户明确语法问题。
611                return Err(anyhow!("return 后期望 ; 或 }}"));
612            }
613            Stmt::new(StmtKind::Return(expr), Span::new(start, self.current_pos()))
614        } else if self.keyword("if").is_ok() {
615            self.if_block()?
616        } else if self.keyword("loop").is_ok() {
617            Stmt::new(StmtKind::Loop(Box::new(self.block()?)), Span::new(start, self.current_pos()))
618        } else if self.keyword("while").is_ok() {
619            self.whitespace()?;
620            let cond = self.get_expr()?;
621            let body = Box::new(self.block()?);
622            Stmt::new(StmtKind::While { cond, body }, Span::new(start, self.current_pos()))
623        } else if self.keyword("for").is_ok() {
624            self.whitespace()?;
625            let pat = self.pattern()?;
626            self.whitespace()?;
627            self.keyword("in")?;
628            self.whitespace()?;
629            let range = self.get_expr()?;
630            self.push_decl_scope();
631            let result: Result<Stmt> = (|| {
632                self.declare_pattern_symbols(&pat)?;
633                let body = Box::new(self.block()?);
634                Ok(Stmt::new(StmtKind::For { pat, range, body }, Span::new(start, self.current_pos())))
635            })();
636            self.pop_decl_scope();
637            result?
638        } else if self.keyword("fn").is_ok() {
639            self.whitespace()?;
640            let (name, generic_params) = self.ident_generic()?;
641            self.declare_function_name(&name)?;
642            self.until(b'(')?;
643            let args = crate::parse_list!(self, Vec::new(), b')', b',', self.ident_typed()?);
644            let body = Box::new(self.function_body(&args)?);
645            Stmt::new(StmtKind::Fn { name, generic_params, args, body, is_pub }, Span::new(start, self.current_pos()))
646        } else if self.keyword("struct").is_ok() {
647            let (name, params) = self.ident_generic()?;
648            self.declare_symbol(&name)?;
649            if self.until(b'{').is_ok() {
650                let fields = crate::parse_list!(self, Vec::new(), b'}', b',', self.ident_typed()?);
651                if let Some(f) = fields.iter().find(|f| f.1.is_any()) {
652                    return Err(anyhow!("字段 {} 的类型未知", f.0));
653                }
654                Stmt::new(StmtKind::Struct { name, def: Type::Struct { params, fields }, is_pub }, Span::new(start, self.current_pos()))
655            } else {
656                self.until(b';')?;
657                Stmt::new(StmtKind::Struct { name, def: Type::Struct { params, fields: Vec::new() }, is_pub }, Span::new(start, self.current_pos()))
658            }
659        } else if self.keyword("const").is_ok() {
660            self.whitespace()?;
661            let (name, ty) = self.ident_typed()?;
662            self.declare_symbol(&name)?;
663            self.until(b'=')?;
664            let value = self.get_expr()?;
665            self.until(b';')?;
666            Stmt::new(StmtKind::Const { name, ty, value, is_pub }, Span::new(start, self.current_pos()))
667        } else if self.keyword("static").is_ok() {
668            self.whitespace()?;
669            let (name, ty) = self.ident_typed()?;
670            self.declare_symbol(&name)?;
671            self.whitespace()?;
672            if self.take(b'=').is_ok() {
673                let expr = self.get_expr()?;
674                self.until(b';')?;
675                Stmt::new(StmtKind::Static { name, ty, value: Some(expr), is_pub }, Span::new(start, self.current_pos()))
676            } else {
677                self.until(b';')?;
678                Stmt::new(StmtKind::Static { name, ty, value: None, is_pub }, Span::new(start, self.current_pos()))
679            }
680        } else if self.keyword("impl").is_ok() {
681            self.whitespace()?;
682            let target = self.get_type()?;
683            Stmt::new(StmtKind::Impl { target, body: Box::new(self.impl_body()?) }, Span::new(start, self.current_pos()))
684        } else if self.keyword("pub").is_ok() {
685            // pub pub fn ... 应报错而非递归到深度限制。
686            // is_pub 为 true 说明已经处在一次 pub 递归中,再遇 pub 是重复修饰符。
687            if is_pub {
688                return Err(anyhow!("重复的 pub 修饰符"));
689            }
690            self.stmt(true)?
691        } else {
692            let expr = if self.get()? == b'{' {
693                if self.looks_like_empty_dict() {
694                    self.dict()?
695                } else if let Ok(block) = try_parse!(self, self.block()) {
696                    // 块是顶层 stmt(无分号结尾),原 spans 守卫仍在,函数末尾 drop 时清理。
697                    return Ok(block);
698                } else if let Ok(dict) = try_parse!(self, self.dict()) {
699                    dict
700                } else {
701                    let block = self.block()?;
702                    return Ok(block);
703                }
704            } else {
705                self.get_expr()?
706            };
707            self.whitespace()?;
708            if self.is_eof() {
709                Stmt::new(StmtKind::Expr(expr, false), Span::new(start, self.current_pos()))
710            } else if self.get()? == b';' {
711                self.pos += 1;
712                Stmt::new(StmtKind::Expr(expr, true), Span::new(start, self.current_pos()))
713            } else if self.get()? == b'}' {
714                Stmt::new(StmtKind::Expr(expr, false), Span::new(start, self.current_pos()))
715            } else {
716                return Err(anyhow!("未结束的表达式"));
717            }
718        };
719        // _span_guard 在函数末尾 drop,自动弹出 spans 栈帧。
720        Ok(stmt)
721    }
722}