Skip to main content

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}