1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
#![warn(clippy::all)]
#![warn(rust_2018_idioms)]
#[macro_use]
mod id_type;
mod arret_root;
mod codegen;
mod context;
mod hir;
mod mir;
mod promise;
pub mod repl;
mod reporting;
mod rfi;
mod source;
mod ty;
mod typeck;
use std::collections::HashSet;
use std::sync::Arc;
use codespan_reporting::diagnostic::Diagnostic;
use arret_syntax::span::FileId;
pub use crate::arret_root::{find_arret_root, FindArretRootError};
pub use crate::codegen::initialise_llvm;
pub use crate::codegen::program::{gen_program, Options as GenProgramOptions, OutputType};
pub use crate::context::{CompileCtx, LinkedLibrary};
pub use crate::hir::PackagePaths;
pub use crate::id_type::ArcId;
pub use crate::mir::eval_hir::{BuiltProgram, EvalHirCtx};
pub use crate::mir::print_program as print_program_mir;
pub use crate::reporting::emit_diagnostics_to_stderr;
pub use crate::source::{SourceFile, SourceLoader, SourceText};
pub struct EvaluableProgram {
pub ehx: EvalHirCtx,
pub main_export_id: hir::ExportId,
pub linked_libraries: Vec<Arc<LinkedLibrary>>,
}
fn include_imports(
ehx: &mut EvalHirCtx,
visited_modules: &mut HashSet<context::ModuleId>,
linked_libraries: &mut Vec<Arc<LinkedLibrary>>,
root_module: &context::Module,
) -> Result<(), Vec<Diagnostic<FileId>>> {
if visited_modules.contains(&root_module.module_id) {
return Ok(());
}
visited_modules.insert(root_module.module_id);
if let Some(ref linked_library) = root_module.linked_library {
linked_libraries.push(linked_library.clone());
}
for import in root_module.imports.values() {
include_imports(ehx, visited_modules, linked_libraries, import)?;
}
ehx.visit_module_defs(root_module.module_id, &root_module.defs)?;
Ok(())
}
pub fn program_to_evaluable(
ccx: &CompileCtx,
source_file: &SourceFile,
) -> Result<EvaluableProgram, Vec<Diagnostic<FileId>>> {
use arret_syntax::span::Span;
use crate::typeck::infer;
let entry_module = ccx.source_file_to_module(source_file)?;
let main_local_id = if let Some(local_id) = entry_module.main_local_id {
local_id
} else {
use codespan_reporting::diagnostic::Label;
return Err(vec![Diagnostic::error()
.with_message("no main! function defined in entry module")
.with_labels(vec![Label::primary(source_file.file_id(), 0..1)
.with_message("main! function expected in this file")])]);
};
let inferred_main_type = &entry_module.inferred_locals[&main_local_id];
infer::ensure_main_type(
Span::new(Some(source_file.file_id()), 0, 0),
&entry_module.defs,
main_local_id,
inferred_main_type,
)
.map_err(|err| vec![err.into()])?;
let mut ehx = EvalHirCtx::new(ccx.enable_optimisations());
let mut linked_libraries = vec![];
let mut visited_modules = HashSet::new();
for import in entry_module.imports.values() {
include_imports(
&mut ehx,
&mut visited_modules,
&mut linked_libraries,
import,
)?;
}
ehx.consume_module_defs(entry_module.module_id, entry_module.defs)?;
if ehx.should_collect() {
ehx.collect_garbage();
}
Ok(EvaluableProgram {
ehx,
main_export_id: hir::ExportId::new(entry_module.module_id, main_local_id),
linked_libraries,
})
}