# Kamo-macros ![Build Status](https://img.shields.io/github/actions/workflow/status/typedduck/kamo/rust.yml) [![Crates.io](https://img.shields.io/crates/v/kamo-macros)](https://crates.io/crates/kamo-macros) [![Crates.io](https://img.shields.io/crates/d/kamo-macros)](https://crates.io/crates/kamo-macros) Kamo (カモ) is japanese for duck. This crate provides procedural macros for the [Kamo](https://crates.io/crates/kamo) crate. The macros provided are: - `sexpr!(, )` - A macro for parsing a single s-expression from a string. It returns a `kamo::value::Value`. - `sexpr_file!(, )` - A macro for parsing multiple s-expressions from a file. It returns an array of `kamo::value::Value`s. The array may be empty. - `sexpr_script!(, )` - A macro for parsing multiple s-expressions from a string. It returns an array of `kamo::value::Value`s. The array may be empty. The macros all take an optional `MutatorRef` identifier. This is used to allocate values on the heap. If the expression does not contain any values that need to be allocated on the heap, then the `Mutator` identifier can be omitted. The syntax for the macros is as defined by the Scheme standard R7RS for the `read` procedure. The syntactic definition is the `` in section ["7.1.2 External representations"](https://standards.scheme.org/official/r7rs.pdf) of the standard. The syntax deviations from the standard are: - The extactness (`#e` and `#i`) of numbers is not supported. Floating-point numbers are always inexact and integers are always exact. - Numbers may only be signed 64-bit integers or IEEE 754 double precision floating-point numbers. The standard allows for arbitrary precision integers, rationals and complex numbers. - Labels are not supported. - The `#;` comment syntax is only supported in the macros which parse multiple s-expressions. The `#;` comment syntax may not be nested. - Character literals defined by a hex escape sequence may have 1 to 6 digits. The standard excepts 1 or more digits. The code must be a valid Unicode code point. The parser is implemented with the `pest` crate. The grammar is defined in `src/sexpr/sexpr.pest`. This is necessary because the combination parser library defined in `kamo::parser` cannot be used here. It would be cyclic dependency. There will be an implementation of a parser for s-expressions in the `kamo::form` module in the future. It will be based on the `kamo::parser` crate and will be used by the scheme interpreter. ## Examples ```rust use kamo::{mem::Mutator, sexpr, value::{print, Value}}; let m = Mutator::new_ref(); let value = sexpr!(m, "(1 2 3)"); assert_eq!(print(value).to_string(), "(1 2 3)"); ``` ```rust use kamo::{sexpr_file, value::{print, Value}}; let m = Mutator::new_ref(); let values = sexpr_file!("tests/sexpr/values.scm"); assert_eq!(values.len(), 3); assert_eq!(print(values[0].clone()).to_string(), "()"); assert_eq!(print(values[1].clone()).to_string(), "100"); assert_eq!(print(values[2].clone()).to_string(), "#t"); let values: &[Value] = &sexpr_file!("tests/sexpr/empty.scm"); assert_eq!(values.len(), 0); ``` ```rust use kamo::{mem::Mutator, sexpr_script, value::{print, Value}}; let m = Mutator::new_ref(); let values = sexpr_script!(m, "(define a 1)\n(define b 2)\n(+ a b)"); assert_eq!(values.len(), 3); assert_eq!(print(values[0].clone()).to_string(), "(define a 1)"); assert_eq!(print(values[1].clone()).to_string(), "(define b 2)"); assert_eq!(print(values[2].clone()).to_string(), "(+ a b)"); let values: &[Value] = &sexpr_script!(""); assert_eq!(values.len(), 0); ```