Brought the documentation to an acceptable level.
This commit is contained in:
parent
ec7ba974da
commit
0873a407f2
5 changed files with 81 additions and 13 deletions
|
@ -10,6 +10,7 @@ proc-macro = true
|
|||
|
||||
[dependencies]
|
||||
sing_util = { path = "../sing_util" }
|
||||
sing_parse = {path = "../sing_parse" }
|
||||
proc-macro2 = "1.0"
|
||||
ron = "0.7"
|
||||
rand = "0.7"
|
||||
|
|
|
@ -10,21 +10,49 @@ use std::{
|
|||
io::{Read, Write},
|
||||
};
|
||||
use syn::{
|
||||
bracketed, parenthesized,
|
||||
bracketed,
|
||||
parse::{Parse, ParseStream},
|
||||
parse2, parse_macro_input, Arm, AttributeArgs, FnArg, Ident, ImplItem, ItemImpl, LitStr, Meta,
|
||||
NestedMeta, Path, Signature, Stmt, Token,
|
||||
};
|
||||
|
||||
extern crate sing_parse;
|
||||
extern crate proc_macro;
|
||||
extern crate sing_util;
|
||||
|
||||
mod keyword;
|
||||
|
||||
/// Add the trait in this ipml block to sings trait store.
|
||||
/// Add the trait in this impl block to sings trait store.
|
||||
///
|
||||
/// The impl block needs to contain all functions as usual.
|
||||
/// After adding a trait, it can be used by the sing_loop macro.
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// trait FruitTree {
|
||||
/// fn shake(&self, shakes: u32) -> Vec<Fruit>;
|
||||
/// }
|
||||
///
|
||||
/// #[derive(Debug, Serialize, Deserialize)]
|
||||
/// struct Fruit {
|
||||
/// fruit_type: String,
|
||||
/// }
|
||||
///
|
||||
/// struct BananaTree;
|
||||
///
|
||||
/// #[sing_add_trait()]
|
||||
/// impl FruitTree for BananaTree {
|
||||
/// fn shake(&self, shakes: u32) -> Vec<Fruit>{
|
||||
/// let mut out = vec!();
|
||||
///
|
||||
/// for _ in 0..shakes {
|
||||
/// out.push(Fruit{fruit_type: String::from("Banana")});
|
||||
/// }
|
||||
///
|
||||
/// out
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
pub fn sing_add_trait(annotated_item: TokenStream, input: TokenStream) -> TokenStream {
|
||||
let input = parse_macro_input!(input as ItemImpl);
|
||||
|
@ -100,7 +128,38 @@ fn add_trait_inner(input: ItemImpl, annotated_item: Vec<NestedMeta>) -> TokenStr
|
|||
/// Creates a main loop that parses stdin (or the given input stream),
|
||||
/// evaluates the called function and returns the result.
|
||||
///
|
||||
/// TODO: document syntax
|
||||
/// ## Usage
|
||||
///
|
||||
/// A call of this macro looks like:
|
||||
/// ```sing_loop!(trait_object, ser_de <, msg: [msg_type, arg_type]> <, ioe: [input, output, error]>)```
|
||||
/// where all items in angle brackets are optional.
|
||||
///
|
||||
/// with the arguments:
|
||||
/// - trait_object: An instance of a struct that implements all desired traits.
|
||||
/// - argument_ser_de: Serialization and deserialization functions. It either looks like `[equal, ser_fun, de_fun]` in which case both messages and arguments are serialized an deserialized by the same functions or `[different, arg_ser_fun, arg_de_fun <, msg_ser_fun, msg_de_fun>` in which case different functions are used.
|
||||
/// - msg_type: A struct that implements [`sing_util::TraitCallMessage`] and should be used as the message type.
|
||||
/// - arg_type: The type to which the arguments of function calls should be serialized to.
|
||||
/// - input: The input Stream. Needs to implement [`std::io::BufRead`].
|
||||
/// - output: The output Stream. Needs to implement [`std::io::Write`].
|
||||
/// - error: The error output Stream. Needs to implement [`std::io::Write`].
|
||||
///
|
||||
/// `msg`, `ioe`, `equal` and `different` are keywords and need to be used literally in the call.
|
||||
///
|
||||
/// The optional parameters have the following defaults:
|
||||
/// - msg_ser_fun: [`sing_parse::callobj_to_string`]
|
||||
/// - msg_de_fun: [`sing_parse::callobj_to_string`]
|
||||
/// - msg_type: [`sing_parse::CallObj`]
|
||||
/// - arg_type: [`String`]
|
||||
/// - input: [`std::io::StdinLock`]
|
||||
/// - output: [`std::io::StdoutLock`]
|
||||
/// - error: [`std::io::StderrLock`]
|
||||
///
|
||||
/// ## Example
|
||||
/// ```
|
||||
/// let tree = BananaTree {};
|
||||
///
|
||||
/// sing_loop!(tree, [different, ron::to_string, ron::from_str],);
|
||||
/// ```
|
||||
#[proc_macro]
|
||||
pub fn sing_loop(input: TokenStream) -> TokenStream {
|
||||
let span = TokenStream2::from(input.clone()).__span();
|
||||
|
@ -443,9 +502,6 @@ struct LoopParams {
|
|||
}
|
||||
|
||||
impl Parse for LoopParams {
|
||||
/// Parses a given input into a Loopparams object
|
||||
/// according to the syntax outlined in the documentation
|
||||
/// of the sing_loop macro
|
||||
fn parse(input: ParseStream) -> syn::Result<Self> {
|
||||
let trait_obj = input.parse()?;
|
||||
input.parse::<Token![,]>()?;
|
||||
|
@ -500,10 +556,9 @@ impl Parse for LoopParams {
|
|||
input.parse::<keyword::msg>()?;
|
||||
input.parse::<Token![:]>()?;
|
||||
|
||||
|
||||
let content;
|
||||
parenthesized!(content in input);
|
||||
let m_a_type_err_generic = "The msg keyword expects two variables in the following order: (MessageType, ArgumentType),";
|
||||
bracketed!(content in input);
|
||||
let m_a_type_err_generic = "The msg keyword expects two variables in the following order: [MessageType, ArgumentType],";
|
||||
|
||||
message_type = match content.parse() {
|
||||
Ok(m) => Some(m),
|
||||
|
@ -542,9 +597,9 @@ impl Parse for LoopParams {
|
|||
input.parse::<Token![:]>()?;
|
||||
|
||||
let content;
|
||||
parenthesized!(content in input);
|
||||
bracketed!(content in input);
|
||||
let lh_inner = content.lookahead1();
|
||||
let ioe_err_generic = "The ioe keyword expects three variables in the following order: (Input, Output, Error),";
|
||||
let ioe_err_generic = "The ioe keyword expects three variables in the following order: [Input, Output, Error],";
|
||||
|
||||
if lh_inner.peek(Ident) {
|
||||
let r = content.parse()?;
|
||||
|
|
|
@ -10,6 +10,7 @@ pub struct CallObj {
|
|||
data: Vec<String>,
|
||||
}
|
||||
|
||||
/// Default message representation for the sing_loop! macro.
|
||||
impl CallObj {
|
||||
pub fn new((trait_string, fun_string, index): (Option<String>, String, usize), data: Vec<String>) -> Self {
|
||||
Self{
|
||||
|
|
|
@ -9,10 +9,12 @@ mod callobj;
|
|||
|
||||
lalrpop_mod!(fun_parser);
|
||||
|
||||
/// Default message serialization function for the sing_loop macro.
|
||||
pub fn callobj_to_string(o: CallObj) -> Result<String, Box<dyn Error>> {
|
||||
Ok(o.to_string())
|
||||
}
|
||||
|
||||
/// Default message deserialization function for the sing_loop macro.
|
||||
pub fn callobj_from_string(s: String) -> Result<CallObj, Box<dyn Error>> {
|
||||
// TODO: This should use a "?", but for some reason the error references s
|
||||
Ok(fun_parser::CallParser::new().parse(&s).unwrap())
|
||||
|
|
|
@ -46,14 +46,23 @@ pub enum DeduplicatedFunctionProfile {
|
|||
Multiple(Vec<String>),
|
||||
}
|
||||
|
||||
/// Needs to be implemented by all structs that are used as
|
||||
/// Needs to be implemented by all structs that are used to represent
|
||||
/// function calls that are sent through a sing I/O stream
|
||||
pub trait TraitCallMessage {
|
||||
/// The representation of rust data structures that is used internally to store the parameters.
|
||||
/// Usually also the type used by the I/O stream.
|
||||
type Representation;
|
||||
|
||||
/// Returns the called functions name.
|
||||
fn get_fun_name(&self) -> String;
|
||||
|
||||
/// Returns the name of the trait the function is called from.
|
||||
fn get_trait_name(&self) -> Option<String>;
|
||||
|
||||
/// Returns the parameters (or arguments) of the function call.
|
||||
fn get_params(&self) -> Vec<Self::Representation>;
|
||||
|
||||
/// Replaces the parameters currently stored in this TraitCallMessage object.
|
||||
fn new_params(&mut self, p: Vec<Self::Representation>);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue