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 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 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 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 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}