Skip to content

Commit

Permalink
docs for several builtins (#206)
Browse files Browse the repository at this point in the history
  • Loading branch information
jrvidal authored May 11, 2024
1 parent 95b4a05 commit a1ccce5
Show file tree
Hide file tree
Showing 24 changed files with 914 additions and 215 deletions.
55 changes: 41 additions & 14 deletions crates/steel-core/src/primitives/bytevectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,16 @@ pub fn bytevector_module() -> BuiltInModule {
module
}

/// Returns a new mutable vector vectors with each byte as the given arguments.
/// Returns a new mutable vector with each byte as the given arguments.
/// Each argument must satisfy the `byte?` predicate, meaning it is an exact
/// integer range from 0 - 255 (inclusive)
///
/// (bytevector b ...)
///
/// b : byte?
/// * b : byte?
///
///
/// # Example
/// # Examples
/// ```scheme
/// (bytevector 65 112 112 108 101)
/// ```
Expand All @@ -52,16 +52,16 @@ pub fn bytevector(args: &[SteelVal]) -> Result<SteelVal> {
.map(SteelVal::ByteVector)
}

/// Returns a new mutable vector vectors with each byte as the given arguments.
/// Returns a new mutable vector with each byte as the given arguments.
/// Each argument must satisfy the `byte?` predicate, meaning it is an exact
/// integer range from 0 - 255 (inclusive)
///
/// (bytes b ...)
///
/// b : byte?
/// * b : byte?
///
///
/// # Example
/// # Examples
/// ```scheme
/// (bytes 65 112 112 108 101)
/// ```
Expand All @@ -86,6 +86,22 @@ pub fn is_bytes(arg: &SteelVal) -> bool {
matches!(arg, SteelVal::ByteVector(_))
}

/// Creates a copy of a bytevector.
///
/// (bytevector-copy vector [start end]) -> bytes?
///
/// * vector : bytes?
/// * start: int? = 0
/// * end: int? = (bytes-length vector)
///
/// # Examples
///
/// ```scheme
/// (define vec (bytes 1 2 3 4 5))
///
/// (bytevector-copy vec) ;; => (bytes 1 2 3 4 5)
/// (bytevector-copy vec 1 3) ;; => (bytes 2 3)
/// ```
#[steel_derive::function(name = "bytevector-copy")]
pub fn bytevector_copy_new(
bytevector: &SteelByteVector,
Expand Down Expand Up @@ -124,6 +140,17 @@ pub fn bytevector_copy_new(
Ok(SteelVal::ByteVector(SteelByteVector::new(copy)))
}

/// Creates a bytevector given a length and a default value.
///
/// (make-bytes len default) -> bytes?
///
/// * len : int?
/// * default : byte?
///
/// # Examples
/// ```scheme
/// (make-bytes 6 42) ;; => (bytes 42 42 42 42 42)
/// ```
#[function(name = "make-bytes")]
pub fn make_bytes(k: usize, mut c: RestArgsIter<'_, isize>) -> Result<SteelVal> {
let default = c.next();
Expand All @@ -148,8 +175,8 @@ pub fn make_bytes(k: usize, mut c: RestArgsIter<'_, isize>) -> Result<SteelVal>
Ok(SteelVal::ByteVector(SteelByteVector::new(vec![default; k])))
}

/// Returns #t if the given value is a byte, meaning an exact
/// integer between 0 and 255 inclusive, #f otherwise.
/// Returns `#t` if the given value is a byte, meaning an exact
/// integer between 0 and 255 inclusive, `#f` otherwise.
///
/// # Examples
/// ```scheme
Expand Down Expand Up @@ -197,8 +224,8 @@ pub fn string_to_bytes(value: &SteelString) -> Result<SteelVal> {
///
/// (bytes-ref vector index)
///
/// vector : bytes?
/// index: (and exact? int?)
/// * vector : bytes?
/// * index: (and exact? int?)
///
/// # Examples
/// ```scheme
Expand All @@ -221,9 +248,9 @@ pub fn bytes_ref(value: &SteelByteVector, index: usize) -> Result<SteelVal> {
///
/// (bytes-set! vector index byte)
///
/// vector : bytes?
/// index: (and exact? int?)
/// byte: byte?
/// * vector : bytes?
/// * index: (and exact? int?)
/// * byte: byte?
///
/// # Examples
/// ```scheme
Expand Down Expand Up @@ -279,7 +306,7 @@ pub fn list_to_bytes(value: Vec<u8>) -> Result<SteelVal> {
///
/// # Examples
/// ```scheme
/// (bytes-append (bytes 0 1 2) (bytes 3 4 5)) ;; (bytes 0 1 2 3 4 5)
/// (bytes-append (bytes 0 1 2) (bytes 3 4 5)) ;; => (bytes 0 1 2 3 4 5)
/// ```
#[function(name = "bytes-append")]
pub fn bytes_append(value: &SteelByteVector, other: &SteelByteVector) -> Result<SteelVal> {
Expand Down
2 changes: 0 additions & 2 deletions crates/steel-core/src/primitives/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ impl Custom for PathBuf {
}
}

/// # steel/filesystem
///
/// Filesystem functions, mostly just thin wrappers around the `std::fs` functions in
/// the Rust std library.
#[steel_derive::define_module(name = "steel/filesystem")]
Expand Down
2 changes: 0 additions & 2 deletions crates/steel-core/src/primitives/lists.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ impl From<Result<SteelVal>> for UnRecoverableResult {
}
}

/// # steel/lists
///
/// Lists in Steel have an interface that matches those of classic schemes or lisps.
/// At face value, they appear to be implemented as cons cells - however, under the hood
/// they are actually implemented as unrolled linked lists.
Expand Down
87 changes: 82 additions & 5 deletions crates/steel-core/src/primitives/strings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ fn char_upcase(c: char) -> char {
c.to_ascii_uppercase()
}

/// # steel/strings
///
/// Strings in Steel are immutable, fixed length arrays of characters. They are heap allocated, and
/// are implemented under the hood as referenced counted Rust `Strings`. Rust `Strings` are stored
/// as UTF-8 encoded bytes.
Expand Down Expand Up @@ -169,56 +167,76 @@ pub fn string_constructor(rest: RestArgsIter<'_, char>) -> Result<SteelVal> {
rest.collect::<Result<String>>().map(|x| x.into())
}

/// Compares two strings lexicographically (as in "less-than-or-equal").
#[function(name = "string<=?", constant = true)]
pub fn string_less_than_equal_to(left: &SteelString, right: &SteelString) -> bool {
left <= right
}

/// Compares two strings lexicographically (as in "less-than-or-equal"),
// in a case insensitive fashion.
#[function(name = "string-ci<=?", constant = true)]
pub fn string_ci_less_than_equal_to(left: &SteelString, right: &SteelString) -> bool {
left.to_lowercase() <= right.to_lowercase()
}

/// Compares two strings lexicographically (as in "less-than").
#[function(name = "string<?", constant = true)]
pub fn string_less_than(left: &SteelString, right: &SteelString) -> bool {
left < right
}

/// Compares two strings lexicographically (as in "less-than"),
/// in a case insensitive fashion.
#[function(name = "string-ci<?", constant = true)]
pub fn string_ci_less_than(left: &SteelString, right: &SteelString) -> bool {
left.to_lowercase() < right.to_lowercase()
}

/// Compares two strings lexicographically (as in "greater-than-or-equal").
#[function(name = "string>=?", constant = true)]
pub fn string_greater_than_equal_to(left: &SteelString, right: &SteelString) -> bool {
left >= right
}

/// Compares two strings lexicographically (as in "greater-than-or-equal"),
/// in a case insensitive fashion.
#[function(name = "string-ci>=?", constant = true)]
pub fn string_ci_greater_than_equal_to(left: &SteelString, right: &SteelString) -> bool {
left.to_lowercase() >= right.to_lowercase()
}

/// Compares two strings lexicographically (as in "greater-than").
#[function(name = "string>?", constant = true)]
pub fn string_greater_than(left: &SteelString, right: &SteelString) -> bool {
left > right
}

/// Compares two strings lexicographically (as in "greater-than"),
/// in a case-insensitive fashion.
#[function(name = "string-ci>?", constant = true)]
pub fn string_ci_greater_than(left: &SteelString, right: &SteelString) -> bool {
left.to_lowercase() > right.to_lowercase()
}

/// Compares two strings for equality.
#[function(name = "string=?", constant = true)]
pub fn string_equals(left: &SteelString, right: &SteelString) -> bool {
left == right
}

/// Compares two strings for equality, in a case insensitive fashion.
#[function(name = "string-ci=?", constant = true)]
pub fn string_ci_equals(left: &SteelString, right: &SteelString) -> bool {
left.to_lowercase() == right.to_lowercase()
}

/// Extracts the nth character out of a given string.
///
/// (string-ref str n)
///
/// * str : string?
/// * n : int?
#[function(name = "string-ref", constant = true)]
pub fn string_ref(value: &SteelString, index: usize) -> Result<SteelVal> {
let res = if index < value.len() {
Expand All @@ -234,6 +252,19 @@ pub fn string_ref(value: &SteelString, index: usize) -> Result<SteelVal> {
}
}

/// Creates a substring slicing the characters between two indices.
///
/// (substring str start end) -> string?
///
/// * str: string?
/// * start : int?
/// * end : int?
///
/// # Examples
/// ```scheme
/// (substring "hello" 1 4) ;; => "ell"
/// (substring "hello" 10 15) ;; => error
/// ```
#[function(name = "substring", constant = true)]
pub fn substring(
value: &SteelString,
Expand Down Expand Up @@ -284,6 +315,13 @@ pub fn substring(
Ok(SteelVal::StringV(value[start..end].into()))
}

/// Creates a string of a given length, filled with an optional character
/// (which defaults to `#\0`).
///
/// (make-string len [char]) -> string?
///
/// * len : int?
/// * char : char? = #\0
#[function(name = "make-string")]
pub fn make_string(k: usize, mut c: RestArgsIter<'_, char>) -> Result<SteelVal> {
// If the char is there, we want to take it
Expand All @@ -298,14 +336,26 @@ pub fn make_string(k: usize, mut c: RestArgsIter<'_, char>) -> Result<SteelVal>
Ok((0..k).into_iter().map(|_| c).collect::<String>().into())
}

/// Replaces all occurrences of a pattern into the given string
///
/// (string-replace str from to) -> string?
///
/// * str : string?
/// * from : string?
/// * to : string?
///
/// # Examples
/// ```scheme
/// (string-replace "hello world" "o" "@") ;; => "hell@ w@rld"
/// ```
#[function(name = "string-replace")]
pub fn replace(value: &SteelString, from: &SteelString, to: &SteelString) -> Result<SteelVal> {
Ok(SteelVal::StringV(
value.replace(from.as_str(), to.as_str()).into(),
))
}

/// Concatenatives all of the inputs to their string representation, separated by spaces.
/// Concatenates all of the inputs to their string representation, separated by spaces.
///
/// (to-string xs ...)
///
Expand Down Expand Up @@ -521,6 +571,20 @@ pub fn split_whitespace(value: &SteelString) -> SteelVal {
split.into()
}

/// Splits a string given a separator at most once, yielding
/// a list with at most 2 elements.
///
/// (split-once str pat) -> string?
///
/// * str : string?
/// * pat : string?
///
/// # Examples
/// ```scheme
/// (split-once "foo,bar,baz" ",") ;; => '("foo" "bar,baz")
/// (split-once "foo|bar|" "|") ;; => '("foo" "bar|")
/// (split-once "" "&") ;; => '("")
/// ```
#[function(name = "split-once")]
pub fn split_once(value: &SteelString, pat: &SteelString) -> SteelVal {
let split: Option<List<SteelVal>> = value
Expand All @@ -529,6 +593,19 @@ pub fn split_once(value: &SteelString, pat: &SteelString) -> SteelVal {
split.into()
}

/// Splits a string given a separator pattern into a list of strings.
///
/// (split-many str pat) -> (listof string?)
///
/// * str : string?
/// * pat : string?
///
/// # Examples
/// ```scheme
/// (split-many "foo,bar,baz" ",") ;; => '("foo" "bar" "baz")
/// (split-many "foo|bar|" "|") ;; => '("foo" "bar" "")
/// (split-many "" "&") ;; => '("")
/// ```
#[function(name = "split-many")]
pub fn split_many(value: &SteelString, pat: &SteelString) -> SteelVal {
let split: List<SteelVal> = value
Expand All @@ -542,8 +619,8 @@ pub fn split_many(value: &SteelString, pat: &SteelString) -> SteelVal {
///
/// (starts-with? input pattern) -> bool?
///
/// input : string?
/// pattern: string?
/// * input : string?
/// * pattern: string?
///
/// # Examples
///
Expand Down
Loading

0 comments on commit a1ccce5

Please sign in to comment.