mimium_lang/ast/
program.rs1use 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, }
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}