yog_script_analyze/ast/stmt.rs
1//! Blocks and statements (`ys-grammar.md` §3.1).
2
3use super::{Expr, Name, Type};
4use crate::source::token::Span;
5
6/// Where a `goto` goes.
7#[derive(Debug, Clone, PartialEq)]
8pub enum Goto {
9 /// A label of its block or one around it.
10 Label(Name),
11 /// The `switch` section around it whose label takes this value.
12 Case(Expr),
13 /// The `switch` section around it that's `default`.
14 Default,
15}
16
17#[derive(Debug, Clone, PartialEq)]
18pub struct Block {
19 pub stmts: Vec<Stmt>,
20 pub span: Span,
21}
22
23/// What a local declaration or a `foreach` binds: one name or a
24/// deconstruction (`let (a, b)`).
25#[derive(Debug, Clone, PartialEq)]
26pub enum Binding {
27 One(Name),
28 Tuple(Vec<Name>),
29}
30
31impl Binding {
32 /// The names it binds.
33 pub fn names(&self) -> impl Iterator<Item = &str> {
34 let names: Vec<&str> = match self {
35 Binding::One(n) => vec![n.text.as_str()],
36 Binding::Tuple(ns) => ns.iter().map(|n| n.text.as_str()).collect(),
37 };
38 names.into_iter()
39 }
40}
41
42#[derive(Debug, Clone, PartialEq)]
43pub enum Stmt {
44 /// `let x = …;`, `let mut x = …;`, `i32 x;`,
45 /// `let (a, b) = …;`; `ty` None: its value's.
46 Local {
47 ty: Option<Type>,
48 binding: Binding,
49 value: Option<Expr>,
50 /// May be assigned again (`let mut`, a typed local).
51 mutable: bool,
52 },
53 /// `place op= value;`; `op` None for `=`.
54 Assign {
55 place: Expr,
56 op: Option<super::BinOp>,
57 value: Expr,
58 },
59 If {
60 cond: Expr,
61 then: Box<Stmt>,
62 otherwise: Option<Box<Stmt>>,
63 },
64 Foreach {
65 ty: Option<Type>,
66 binding: Binding,
67 iter: Expr,
68 body: Box<Stmt>,
69 /// `foreach (let mut x in items)`: each item lent to be changed
70 /// (Rust's `iter_mut`); else read only.
71 mutable: bool,
72 /// `await foreach`: the items of an `IAsyncEnumerable<T>`, each
73 /// awaited (in an `async` method).
74 awaits: bool,
75 },
76 For {
77 init: Option<Box<Stmt>>,
78 cond: Option<Expr>,
79 step: Option<Box<Stmt>>,
80 body: Box<Stmt>,
81 },
82 While {
83 cond: Expr,
84 body: Box<Stmt>,
85 },
86 DoWhile {
87 body: Box<Stmt>,
88 cond: Expr,
89 },
90 Block(Block),
91 /// `name:` (C#'s label): where a `goto name;` in its block (or one
92 /// inside it) goes on from.
93 Label(Name),
94 /// `goto name;`, `goto case value;`, `goto default;`.
95 Goto(Goto, Span),
96 Break(Span),
97 Continue(Span),
98 Return(Option<Expr>, Span),
99 /// `skip value;` in a patch's `before`: the method ends with it.
100 Skip(Option<Expr>, Span),
101 /// `yield return value;` (`Some`) or `yield break;` (`None`), in an
102 /// iterator.
103 Yield(Option<Expr>, Span),
104 /// `unsafe { … }`: the threads checks skipped inside (a warning).
105 Unsafe(Block, Span),
106 /// `checked { … }` (`checked`) or `unchecked { … }`: the block's
107 /// whole-number arithmetic panicking on overflow, or wrapping.
108 Checked(Block, bool),
109 /// `switch (expr) { case p when g: … break; default: … }` (C#'s
110 /// statement): the first section a label of takes the value runs; its
111 /// `break` leaves the switch.
112 Switch {
113 expr: Expr,
114 sections: Vec<Section>,
115 },
116 /// A local function (C#'s): a method declared in a block, reaching the
117 /// block's locals, called anywhere in it (before it too).
118 Function(Box<super::Decl>),
119 /// `lock (target) body` or `lock (target, ref let value) body`: a
120 /// `Lock<T>` held for `body`, its value lent as `value`.
121 Lock {
122 target: Expr,
123 value: Option<super::Name>,
124 body: Box<Stmt>,
125 at: Span,
126 },
127 Expr(Expr),
128 /// A block lambda's last expression, without `;`: its value.
129 Value(Expr),
130}
131
132/// The local functions `stmts` declare.
133pub fn local_functions(stmts: &[Stmt]) -> impl Iterator<Item = &super::Method> {
134 stmts.iter().filter_map(|s| match s {
135 Stmt::Function(d) => match &d.kind {
136 super::DeclKind::Method(m) => Some(m),
137 _ => None,
138 },
139 _ => None,
140 })
141}
142
143/// A `switch` statement's section: its labels (`case p when g:`; `None`:
144/// `default:`) and its statements.
145#[derive(Debug, Clone, PartialEq)]
146pub struct Section {
147 pub labels: Vec<Option<(super::Pattern, Option<Expr>)>>,
148 pub body: Vec<Stmt>,
149}