1#[cfg(test)]
2mod gc_test;
3#[cfg(test)]
4mod report_test;
5#[cfg(test)]
6mod runner_test;
7#[cfg(test)]
8mod value_test;
9#[cfg(test)]
10mod vm_test;
11
12pub mod frame;
13pub mod header;
14pub mod heap;
15pub mod list;
16pub mod malloc;
17pub mod report;
18pub mod runner;
19#[path = "gc_runtime.rs"]
22pub mod runtime;
23pub mod value;
24pub mod vm;
25
26pub use frame::Frame;
27pub use header::{GcId, GcObjectHeader, GcObjectType, GcPhase, RefCountHeader, RefCountId};
28pub use heap::{GcHeap, GcRef};
29pub use malloc::{MallocState, DEFAULT_GC_THRESHOLD, MALLOC_OVERHEAD};
30pub use report::{
31 EdgeRelation, FinalFate, FreeCycleStats, GcCollectionReport, GcObjectSummary, GcPhaseStats,
32 GcStatsBundle, GlobalRoot, HashKeyKind, HeapSnapshot, ObjectDecision, RestorationWitness,
33 ScanStats, TrialDecision, TrialDeletionStats, ValueKindCounts, VisitedEdge,
34};
35pub use runner::{compile_source, run_bytecode, run_bytecode_with_output};
36pub use runtime::{GcObject, GcRuntime, MarkFunc};
37pub use value::{
38 export_object, import_object, try_export_object, value_to_string, GcClosure, Value, ValueKind,
39};
40pub use vm::{
41 GcClassifiedRuntimeError, GcRuntimeError, GcRuntimeErrorKind, GcVM, DEFAULT_INSTRUCTION_BUDGET,
42};
43
44use compiler::compiler::{Bytecode, Compiler};
45use object::Object;
46use parser::ast::Node;
47use parser::lexer::token::Span;
48use serde::Serialize;
49
50#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize)]
51#[serde(rename_all = "lowercase")]
52pub enum GcRunStage {
53 Parse,
54 Compile,
55 Runtime,
56}
57
58#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
59#[serde(rename_all = "camelCase")]
60pub struct GcRunSuccess {
61 pub result: String,
62 pub report: GcCollectionReport,
63}
64
65#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
67#[serde(rename_all = "camelCase")]
68pub struct GcRunError {
69 pub stage: GcRunStage,
70 pub message: String,
71 pub span: Option<Span>,
72}
73
74#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
76#[serde(rename_all = "camelCase")]
77pub struct GcClassifiedRunError {
78 pub stage: GcRunStage,
79 pub kind: String,
80 pub message: String,
81 pub span: Option<Span>,
82}
83
84impl From<GcClassifiedRunError> for GcRunError {
85 fn from(error: GcClassifiedRunError) -> Self {
86 Self {
87 stage: error.stage,
88 message: error.message,
89 span: error.span,
90 }
91 }
92}
93
94pub fn compile(program: &Node) -> Result<Bytecode, String> {
96 let mut compiler = Compiler::new();
97 compiler.compile(program)
98}
99
100pub fn eval(program: &Node) -> Result<Object, String> {
102 let bytecode = compile(program)?;
103 let mut vm = GcVM::new(bytecode);
104 vm.run_with_budget(usize::MAX)
105 .map_err(|error| error.message)?;
106 vm.try_export_last_result()
107}
108
109pub fn eval_source(source: &str) -> Result<Object, String> {
111 let program = parser::parse(source).map_err(|errors| errors[0].clone())?;
112 eval(&program)
113}
114
115pub fn run_source_with_report(
117 source: &str,
118 instruction_budget: usize,
119) -> Result<GcRunSuccess, GcRunError> {
120 run_source_with_report_classified(source, instruction_budget).map_err(Into::into)
121}
122
123pub fn run_source_with_report_classified(
126 source: &str,
127 instruction_budget: usize,
128) -> Result<GcRunSuccess, GcClassifiedRunError> {
129 let program = parser::parse(source).map_err(|errors| GcClassifiedRunError {
130 stage: GcRunStage::Parse,
131 kind: "syntax".to_string(),
132 message: errors
133 .first()
134 .cloned()
135 .unwrap_or_else(|| "unknown parse error".to_string()),
136 span: None,
137 })?;
138 let mut compiler = Compiler::new();
139 let bytecode = compiler
140 .compile(&program)
141 .map_err(|message| GcClassifiedRunError {
142 stage: GcRunStage::Compile,
143 kind: "compile".to_string(),
144 message,
145 span: None,
146 })?;
147 let global_names = compiler.symbol_table.global_symbols();
148 let mut vm = GcVM::new(bytecode);
149 vm.set_global_names(global_names);
150 vm.heap_mut().set_gc_threshold(usize::MAX);
151 vm.run_with_budget_classified(instruction_budget)
152 .map_err(|error| GcClassifiedRunError {
153 stage: GcRunStage::Runtime,
154 kind: error.kind.as_str().to_string(),
155 message: error.message,
156 span: error.span,
157 })?;
158 let result = vm.last_result_string();
159 let report = vm.collect_garbage();
160 Ok(GcRunSuccess {
161 result,
162 report,
163 })
164}