bend/fun/check/
set_entrypoint.rs1use crate::{
2 diagnostics::WarningType,
3 fun::{Book, Ctx, Definition, Name},
4 ENTRY_POINT, HVM1_ENTRY_POINT,
5};
6
7#[derive(Debug, Clone)]
8pub enum EntryErr {
9 NotFound(Name),
10 Multiple(Vec<Name>),
11 MultipleRules,
12}
13
14impl Ctx<'_> {
15 pub fn set_entrypoint(&mut self) {
16 let mut entrypoint = None;
17
18 let (custom, main, hvm1_main) = self.book.get_possible_entry_points();
19 match (custom, main, hvm1_main) {
20 (Some(entry), None, None) | (None, Some(entry), None) | (None, None, Some(entry)) => {
21 match validate_entry_point(entry) {
22 Ok(name) => entrypoint = Some(name),
23 Err(err) => self.info.add_book_error(err),
24 }
25 }
26
27 (Some(a), Some(b), None) | (None, Some(a), Some(b)) | (Some(a), None, Some(b)) => {
28 self.info.add_book_error(EntryErr::Multiple(vec![a.name.clone(), b.name.clone()]));
29
30 match validate_entry_point(a) {
31 Ok(name) => entrypoint = Some(name),
32 Err(err) => self.info.add_book_error(err),
33 }
34 }
35
36 (Some(a), Some(b), Some(c)) => {
37 self.info.add_book_error(EntryErr::Multiple(vec![a.name.clone(), b.name.clone(), c.name.clone()]));
38
39 match validate_entry_point(a) {
40 Ok(name) => entrypoint = Some(name),
41 Err(err) => self.info.add_book_error(err),
42 }
43 }
44
45 (None, None, None) => {
46 let entrypoint = self.book.entrypoint.clone().unwrap_or(Name::new(ENTRY_POINT));
47 self.info.add_book_warning(EntryErr::NotFound(entrypoint), WarningType::MissingMain)
48 }
49 }
50
51 self.book.entrypoint = entrypoint;
52 }
53}
54
55fn validate_entry_point(entry: &Definition) -> Result<Name, EntryErr> {
56 if entry.rules.len() > 1 {
57 Err(EntryErr::MultipleRules)
58 } else {
59 Ok(entry.name.clone())
60 }
61}
62
63impl Book {
64 fn get_possible_entry_points(&self) -> (Option<&Definition>, Option<&Definition>, Option<&Definition>) {
65 let custom = self.entrypoint.as_ref().and_then(|e| self.defs.get(e));
66 let main = self.defs.get(&Name::new(ENTRY_POINT));
67 let hvm1_main = self.defs.get(&Name::new(HVM1_ENTRY_POINT));
68 (custom, main, hvm1_main)
69 }
70}
71
72impl std::fmt::Display for EntryErr {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 match self {
75 EntryErr::NotFound(name) => write!(f, "File has no '{name}' definition."),
76 EntryErr::Multiple(fnd) if fnd.len() == 2 => {
77 write!(f, "File has both '{}' and '{}' definitions.", fnd[0], fnd[1])
78 }
79 EntryErr::Multiple(fnd) => {
80 write!(f, "File has '{}', '{}' and '{}' definitions.", fnd[0], fnd[1], fnd[2])
81 }
82 EntryErr::MultipleRules => write!(f, "Main definition can't have more than one rule."),
83 }
84 }
85}