mimium_lang/ast/
statement.rs

1use crate::{
2    ast::Expr,
3    interner::ExprNodeId,
4    pattern::{TypedId, TypedPattern},
5    utils::metadata::{Location, Span},
6};
7
8use super::StageKind;
9// an intermediate representation used in parser.
10// Note that this struct do not distinct between a global statement(allows `fn(){}`) and a local statement.
11// The distinction is done in the actual parser logic.
12#[derive(Clone, Debug, PartialEq)]
13pub enum Statement {
14    Let(TypedPattern, ExprNodeId),
15    LetRec(TypedId, ExprNodeId),
16    Assign(ExprNodeId, ExprNodeId),
17    Single(ExprNodeId),
18    DeclareStage(StageKind),
19    Error,
20}
21
22pub fn stmt_from_expr_top(expr: ExprNodeId) -> Vec<Statement> {
23    let mut res = vec![];
24    stmt_from_expr(expr, &mut res);
25    res
26}
27fn stmt_from_expr(expr: ExprNodeId, target: &mut Vec<Statement>) {
28    match expr.to_expr() {
29        Expr::Let(pat, e, then_opt) => {
30            target.push(Statement::Let(pat, e));
31            if let Some(then) = then_opt {
32                stmt_from_expr(then, target);
33            }
34        }
35        Expr::LetRec(id, e, then_opt) => {
36            target.push(Statement::LetRec(id, e));
37            if let Some(then) = then_opt {
38                stmt_from_expr(then, target);
39            }
40        }
41        _ => target.push(Statement::Single(expr)),
42    }
43}
44
45// A helper function to convert vector of statements to nested expression
46pub(crate) fn into_then_expr(stmts: &[(Statement, Location)]) -> Option<ExprNodeId> {
47    // Concat all statements into one nested expression.
48    // We need to check statements from first to last to resolve macro stage, but we need to build expression from last to first.
49    // So we build a closure to build expression from first to last, and then evaluate them in reverse order.
50    type ClsType = Box<dyn FnOnce(Option<ExprNodeId>) -> Option<ExprNodeId>>;
51    let mut last_stage = StageKind::Main;
52    let mut closures = Vec::<ClsType>::new();
53    for (stmt, loc) in stmts.iter() {
54        let stmt = stmt.clone();
55        let loc = loc.clone();
56        let cls = match stmt {
57            Statement::Let(typed_pattern, expr_node_id) => Box::new(move |then| {
58                Some(Expr::Let(typed_pattern.clone(), expr_node_id, then).into_id(loc.clone()))
59            }) as ClsType,
60            Statement::LetRec(typed_id, expr_node_id) => Box::new(move |then| {
61                Some(Expr::LetRec(typed_id.clone(), expr_node_id, then).into_id(loc.clone()))
62            }) as ClsType,
63            Statement::Assign(expr_node_id, expr_node_id1) => Box::new(move |then| {
64                Some(
65                    Expr::Then(
66                        Expr::Assign(expr_node_id, expr_node_id1).into_id(loc.clone()),
67                        then,
68                    )
69                    .into_id(loc.clone()),
70                )
71            }) as ClsType,
72            Statement::Single(expr_node_id) => {
73                Box::new(move |then: Option<ExprNodeId>| match then {
74                    None => Some(expr_node_id),
75                    Some(t) => Some(Expr::Then(expr_node_id, Some(t)).into_id(loc.clone())),
76                }) as ClsType
77            }
78            Statement::DeclareStage(stage_kind) => {
79                let res = match (&last_stage, stage_kind.clone()) {
80                    (StageKind::Macro, StageKind::Main) => {
81                        Box::new(|then: Option<_>| then.map(|e| Expr::Bracket(e).into_id(loc)))
82                            as ClsType
83                    }
84                    (StageKind::Main, StageKind::Macro) => {
85                        Box::new(|then: Option<_>| then.map(|e| Expr::Escape(e).into_id(loc)))
86                            as ClsType
87                    }
88                    (StageKind::Persistent, _) => {
89                        log::warn!("Persistent stage declaration is not supported yet,ignored");
90                        Box::new(move |then: Option<ExprNodeId>| then) as ClsType
91                    }
92                    (_, _) => Box::new(move |then: Option<ExprNodeId>| then) as ClsType,
93                };
94                last_stage = stage_kind.clone();
95                res
96            }
97            Statement::Error => Box::new(move |then| {
98                Some(Expr::Then(Expr::Error.into_id(loc.clone()), then).into_id(loc.clone()))
99            }) as ClsType,
100        };
101        closures.push(cls);
102    }
103    let e_pre = closures
104        .into_iter()
105        .rev()
106        .fold(None, move |then, cls: ClsType| cls(then));
107    // log::debug!("stmts {:?}, e_pre: {:?}", stmts, e_pre);
108    e_pre
109}