mimium_lang/ast/
program.rs

1use std::path::PathBuf;
2
3use super::resolve_include::resolve_include;
4use super::statement::Statement;
5use crate::ast::Expr;
6use crate::ast::statement::into_then_expr;
7use crate::interner::{ExprNodeId, Symbol, TypeNodeId};
8use crate::pattern::TypedId;
9use crate::types::{RecordTypeField, Type};
10use crate::utils::error::ReportableError;
11use crate::utils::metadata::{Location, Span};
12
13use super::StageKind;
14
15#[derive(Clone, Debug, PartialEq)]
16pub enum ProgramStatement {
17    FnDefinition {
18        name: Symbol,
19        args: (Vec<TypedId>, Location),
20        return_type: Option<TypeNodeId>,
21        body: ExprNodeId,
22    },
23    StageDeclaration {
24        stage: StageKind,
25    },
26    GlobalStatement(Statement),
27    Import(Symbol),
28    Comment(Symbol),
29    DocComment(Symbol),
30    Error, //ModuleDefinition(Symbol),
31}
32
33#[derive(Clone, Debug, PartialEq, Default)]
34pub struct Program {
35    pub statements: Vec<(ProgramStatement, Span)>,
36}
37fn stmts_from_program(
38    program: Program,
39    file_path: PathBuf,
40    errs: &mut Vec<Box<dyn ReportableError>>,
41) -> Vec<(Statement, Location)> {
42    program
43        .statements
44        .into_iter()
45        .filter_map(|(stmt, span)| match stmt {
46            ProgramStatement::FnDefinition {
47                name,
48                args,
49                return_type,
50                body,
51            } => {
52                let loc = Location::new(span, file_path.clone());
53                let argloc = args.1.clone();
54                let argsty = args
55                    .clone()
56                    .0
57                    .into_iter()
58                    .map(RecordTypeField::from)
59                    .collect::<Vec<_>>();
60                let fnty = Type::Function {
61                    arg: Type::Record(argsty).into_id_with_location(argloc),
62                    ret: return_type.unwrap_or(Type::Unknown.into_id_with_location(loc.clone())),
63                }
64                .into_id_with_location(loc.clone());
65                Some(vec![(
66                    Statement::LetRec(
67                        TypedId::new(name, fnty),
68                        Expr::Lambda(args.0, return_type, body).into_id(loc.clone()),
69                    ),
70                    loc,
71                )])
72            }
73            ProgramStatement::GlobalStatement(statement) => {
74                Some(vec![(statement, Location::new(span, file_path.clone()))])
75            }
76            ProgramStatement::Comment(_) | ProgramStatement::DocComment(_) => None,
77            ProgramStatement::Import(filename) => {
78                let (imported_program, mut new_errs) =
79                    resolve_include(file_path.to_str().unwrap(), filename.as_str(), span.clone());
80                errs.append(&mut new_errs);
81                let res = stmts_from_program(imported_program, file_path.clone(), errs);
82                Some(res)
83            }
84            ProgramStatement::StageDeclaration { stage } => Some(vec![(
85                Statement::DeclareStage(stage),
86                Location::new(span, file_path.clone()),
87            )]),
88            ProgramStatement::Error => Some(vec![(
89                Statement::Error,
90                Location::new(span, file_path.clone()),
91            )]),
92        })
93        .flatten()
94        .collect()
95}
96pub(crate) fn expr_from_program(
97    program: Program,
98    file_path: PathBuf,
99) -> (ExprNodeId, Vec<Box<dyn ReportableError>>) {
100    let mut errs = vec![];
101    let stmts = stmts_from_program(program, file_path.clone(), &mut errs);
102
103    let res = into_then_expr(stmts.as_slice()).unwrap_or(Expr::Error.into_id_without_span());
104
105    (res, errs)
106}