Crates.io | stak-time |
lib.rs | stak-time |
version | |
source | src |
created_at | 2024-09-27 17:03:32.412157 |
updated_at | 2025-01-22 01:06:40.878455 |
description | Time library for Stak Scheme |
homepage | |
repository | https://github.com/raviqqe/stak |
max_upload_size | |
id | 1388810 |
Cargo.toml error: | TOML parse error at line 17, column 1 | 17 | autolib = false | ^^^^^^^ unknown field `autolib`, expected one of `name`, `version`, `edition`, `authors`, `description`, `readme`, `license`, `repository`, `homepage`, `documentation`, `build`, `resolver`, `links`, `default-run`, `default_dash_run`, `rust-version`, `rust_dash_version`, `rust_version`, `license-file`, `license_dash_file`, `license_file`, `licenseFile`, `license_capital_file`, `forced-target`, `forced_dash_target`, `autobins`, `autotests`, `autoexamples`, `autobenches`, `publish`, `metadata`, `keywords`, `categories`, `exclude`, `include` |
size | 0 |
The miniature, embeddable R7RS Scheme implementation in Rust
Stak Scheme aims to be:
std
and no-alloc
platformsFor more information and usage, visit the full documentation.
To install Stak Scheme as a library in your Rust project, run:
cargo add stak
cargo add --build stak-build
cargo install stak-compile
For full examples, see the examples
directory.
To install the Scheme interpreter as a command, run:
cargo install stak
First, prepare a Scheme script at src/hello.scm
.
(import (scheme base))
(write-string "Hello, world!\n")
Then, add a build script at build.rs
to build the Scheme source file into bytecodes.
use stak_build::{build_r7rs, BuildError};
fn main() -> Result<(), BuildError> {
build_r7rs()
}
Now, you can include the Scheme script into a program in Rust using the stak::include_module
macro.
use core::error::Error;
use stak::{
device::StdioDevice,
file::VoidFileSystem,
include_module,
process_context::VoidProcessContext,
module::{Module, UniversalModule},
r7rs::{SmallError, SmallPrimitiveSet},
time::VoidClock,
vm::Vm,
};
const HEAP_SIZE: usize = 1 << 16;
// Include a Scheme script in the bytecode format built by the build script above.
static MODULE: UniversalModule = include_module!("hello.scm");
fn main() -> Result<(), Box<dyn Error>> {
run(&MODULE.bytecode())?;
Ok(())
}
fn run(bytecodes: &[u8]) -> Result<(), SmallError> {
// Prepare a heap memory of a virtual machine.
let mut heap = [Default::default(); HEAP_SIZE];
// Create a virtual machine with its heap memory primitive procedures.
let mut vm = Vm::new(
&mut heap,
SmallPrimitiveSet::new(
// Attach standard input, output, and error of this process to a virtual machine.
StdioDevice::new(),
// Use void system interfaces for security because we don't need them for this example.
VoidFileSystem::new(),
VoidProcessContext::new(),
VoidClock::new(),
),
)?;
// Initialize a virtual machine with bytecodes.
vm.initialize(bytecodes.iter().copied())?;
// Run bytecodes on a virtual machine.
vm.run()
}
Currently, in-memory standard input (stdin
) and output (stdout
) to Scheme scripts are the only way to communicate information between Rust programs and Scheme scripts.
use core::{error::Error, str::{self, FromStr}};
use stak::{
device::ReadWriteDevice,
file::VoidFileSystem,
include_module,
process_context::VoidProcessContext,
module::{Module, UniversalModule},
r7rs::{SmallError, SmallPrimitiveSet},
time::VoidClock,
vm::Vm,
};
const BUFFER_SIZE: usize = 1 << 8;
const HEAP_SIZE: usize = 1 << 16;
static MODULE: UniversalModule = include_module!("fibonacci.scm");
fn main() -> Result<(), Box<dyn Error>> {
let input = 15;
let mut output = vec![];
let mut error = vec![];
run(&MODULE.bytecode(), input.to_string().as_bytes(), &mut output, &mut error)?;
// If stderr is not empty, we assume that some error has occurred.
if !error.is_empty() {
return Err(str::from_utf8(&error)?.into());
}
// Decode and test the output.
assert_eq!(isize::from_str(&str::from_utf8(&output)?)?, 610);
Ok(())
}
fn run(
bytecodes: &[u8],
input: &[u8],
output: &mut Vec<u8>,
error: &mut Vec<u8>,
) -> Result<(), SmallError> {
let mut heap = [Default::default(); HEAP_SIZE];
let mut vm = Vm::new(
&mut heap,
SmallPrimitiveSet::new(
// Create and attach an in-memory I/O device.
ReadWriteDevice::new(input, output, error),
VoidFileSystem::new(),
VoidProcessContext::new(),
VoidClock::new(),
),
)?;
vm.initialize(bytecodes.iter().copied())?;
vm.run()
}