1#![cfg_attr(all(doc, not(doctest)), feature(doc_cfg))]
4#![no_std]
5
6#[cfg(feature = "libc")]
7#[doc(hidden)]
8pub extern crate alloc;
9#[cfg(feature = "std")]
10#[doc(hidden)]
11pub extern crate std;
12
13#[doc(hidden)]
14pub mod __private {
15 #[cfg(feature = "libc")]
16 pub use alloc;
17 #[cfg(feature = "std")]
18 pub use clap;
19 #[cfg(feature = "libc")]
20 pub use dlmalloc;
21 #[cfg(feature = "std")]
22 pub use main_error;
23 #[cfg(feature = "libc")]
24 pub use origin;
25 pub use stak_configuration;
26 pub use stak_device;
27 pub use stak_file;
28 pub use stak_macro;
29 pub use stak_process_context;
30 pub use stak_r7rs;
31 pub use stak_time;
32 pub use stak_vm;
33 #[cfg(feature = "std")]
34 pub use std;
35}
36
37#[cfg(feature = "std")]
52#[macro_export]
53macro_rules! main {
54 ($path:expr) => {
55 $crate::main!(
56 $path,
57 $crate::__private::stak_configuration::DEFAULT_HEAP_SIZE
58 );
59 };
60 ($path:expr, $heap_size:expr) => {
61 use $crate::__private::{
62 clap::{self, Parser},
63 main_error::MainError,
64 stak_device::StdioDevice,
65 stak_file::OsFileSystem,
66 stak_macro::include_r7rs,
67 stak_process_context::OsProcessContext,
68 stak_r7rs::SmallPrimitiveSet,
69 stak_time::OsClock,
70 stak_vm::Vm,
71 };
72
73 #[derive(clap::Parser)]
74 #[command(disable_help_flag = true, ignore_errors = true, version)]
75 struct Arguments {
76 #[arg()]
77 arguments: Vec<String>,
78 #[arg(short = 's', long, default_value_t = $heap_size)]
79 heap_size: usize,
80 }
81
82 fn main() -> Result<(), MainError> {
83 let arguments = Arguments::parse();
84
85 Vm::new(
86 vec![Default::default(); arguments.heap_size],
87 SmallPrimitiveSet::new(
88 StdioDevice::new(),
89 OsFileSystem::new(),
90 OsProcessContext::new(),
91 OsClock::new(),
92 ),
93 )?
94 .run(include_r7rs!($path).iter().copied())?;
95
96 Ok(())
97 }
98 };
99}
100
101#[cfg(feature = "libc")]
108#[macro_export]
109macro_rules! libc_main {
110 ($path:expr) => {
111 $crate::libc_main!(
112 $path,
113 $crate::__private::stak_configuration::DEFAULT_HEAP_SIZE
114 );
115 };
116 ($path:expr, $heap_size:expr) => {
117 use $crate::__private::{
118 alloc::vec,
119 dlmalloc::GlobalDlmalloc,
120 origin::program::exit,
121 stak_device::libc::{ReadWriteDevice, Stderr, Stdin, Stdout},
122 stak_file::LibcFileSystem,
123 stak_macro::include_r7rs,
124 stak_process_context::LibcProcessContext,
125 stak_r7rs::SmallPrimitiveSet,
126 stak_time::LibcClock,
127 stak_vm::Vm,
128 };
129
130 #[global_allocator]
131 static GLOBAL_ALLOCATOR: GlobalDlmalloc = GlobalDlmalloc;
132
133 #[cfg(not(test))]
134 #[panic_handler]
135 fn panic(_info: &core::panic::PanicInfo) -> ! {
136 exit(1)
137 }
138
139 #[cfg_attr(not(test), unsafe(no_mangle))]
140 extern "C" fn main(argc: isize, argv: *const *const i8) {
141 Vm::new(
142 vec![Default::default(); $heap_size],
143 SmallPrimitiveSet::new(
144 ReadWriteDevice::new(Stdin::new(), Stdout::new(), Stderr::new()),
145 LibcFileSystem::new(),
146 unsafe { LibcProcessContext::new(argc, argv) },
147 LibcClock::new(),
148 ),
149 )
150 .unwrap()
151 .run(include_r7rs!($path).iter().copied())
152 .unwrap();
153
154 exit(0);
155 }
156 };
157}