stak_sac/
lib.rs

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
128
129
130
131
132
133
134
135
136
137
138
//! Utilities to build executable binaries from bytecode files.

#![no_std]

#[cfg(feature = "std")]
pub extern crate std;

#[doc(hidden)]
pub mod __private {
    #[cfg(feature = "std")]
    pub use clap;
    #[cfg(feature = "libc")]
    pub use libc;
    #[cfg(feature = "std")]
    pub use main_error;
    pub use stak_configuration;
    pub use stak_device;
    pub use stak_file;
    pub use stak_macro;
    pub use stak_process_context;
    pub use stak_r7rs;
    pub use stak_time;
    #[cfg(feature = "libc")]
    pub use stak_util;
    pub use stak_vm;
    #[cfg(feature = "std")]
    pub use std;
}

/// Defines a `main` function that executes a source file at a given path.
///
/// The given source file is compiled into bytecodes and bundled into a
/// resulting binary.
#[cfg(feature = "std")]
#[macro_export]
macro_rules! main {
    ($path:expr) => {
        $crate::main!(
            $path,
            $crate::__private::stak_configuration::DEFAULT_HEAP_SIZE
        );
    };
    ($path:expr, $heap_size:expr) => {
        use $crate::__private::{
            clap::{self, Parser},
            main_error::MainError,
            stak_device::StdioDevice,
            stak_file::OsFileSystem,
            stak_macro::include_r7rs,
            stak_process_context::OsProcessContext,
            stak_r7rs::SmallPrimitiveSet,
            stak_time::OsClock,
            stak_vm::Vm,
        };

        #[derive(clap::Parser)]
        #[command(about, version)]
        struct Arguments {
            #[arg()]
            arguments: Vec<String>,
            #[arg(short = 's', long, default_value_t = $heap_size)]
            heap_size: usize,
        }

        fn main() -> Result<(), MainError> {
            let arguments = Arguments::parse();

            let mut heap = vec![Default::default(); arguments.heap_size];
            let mut vm = Vm::new(
                &mut heap,
                SmallPrimitiveSet::new(
                    StdioDevice::new(),
                    OsFileSystem::new(),
                    OsProcessContext::new(),
                    OsClock::new(),
                ),
            )?;

            vm.initialize(include_r7rs!($path).iter().copied())?;

            Ok(vm.run()?)
        }
    };
}

/// Defines a `main` function that executes a source file at a given path.
///
/// The given source file is compiled into bytecodes and bundled into a
/// resulting binary.
#[cfg(feature = "libc")]
#[macro_export]
macro_rules! libc_main {
    ($path:expr) => {
        $crate::libc_main!(
            $path,
            $crate::__private::stak_configuration::DEFAULT_HEAP_SIZE
        );
    };
    ($path:expr, $heap_size:expr) => {
        use $crate::__private::{
            libc::exit,
            stak_device::libc::{ReadWriteDevice, Stderr, Stdin, Stdout},
            stak_file::LibcFileSystem,
            stak_macro::include_r7rs,
            stak_process_context::LibcProcessContext,
            stak_r7rs::SmallPrimitiveSet,
            stak_time::LibcClock,
            stak_util::Heap,
            stak_vm::Vm,
        };

        #[cfg(not(test))]
        #[panic_handler]
        fn panic(_info: &core::panic::PanicInfo) -> ! {
            unsafe { exit(1) }
        }

        #[cfg_attr(not(test), no_mangle)]
        unsafe extern "C" fn main(argc: isize, argv: *const *const i8) -> isize {
            let mut heap = Heap::new($heap_size, Default::default);
            let mut vm = Vm::new(
                heap.as_slice_mut(),
                SmallPrimitiveSet::new(
                    ReadWriteDevice::new(Stdin::new(), Stdout::new(), Stderr::new()),
                    LibcFileSystem::new(),
                    LibcProcessContext::new(argc, argv),
                    LibcClock::new(),
                ),
            )
            .unwrap();

            vm.initialize(include_r7rs!($path).iter().copied()).unwrap();
            vm.run().unwrap();

            0
        }
    };
}