update readme, set add nix shell

This commit is contained in:
2026-03-08 13:42:07 +01:00
parent 22cde2b988
commit f40fa795eb
3 changed files with 114 additions and 0 deletions
+3
View File
@@ -1 +1,4 @@
target/
.direnv
.envrc
+89
View File
@@ -2,6 +2,95 @@
**Misses** is a DSL compiler that transforms `.mrs` macro definitions into ready-to-use Rust proc macro source files. Write your macro once in a concise, readable syntax; Misses generates the full `syn`/`quote` boilerplate for you.
---
## Why Misses?
Writing proc macros means wrestling with `syn` parsing, `quote!` boilerplate, error handling, and variadic patterns. You write the same patterns over and over.
**Misses lets you write the macro once, in readable syntax, and generates all the boilerplate for you.**
Here's a real example:
### `derive_getters.mrs`
```mrs
macro derive_getters! {
struct $name:ident { $($field:ident : $ty:ty),* } => {
T~{
impl $name {
for field in $fields =>
pub fn $field.name(&self) -> &$field.ty { &self.$field.name }
}
}
}
}
```
<details>
<summary>
<b>Generated output</b>
</summary>
```rust
extern crate proc_macro;
#[proc_macro]
pub fn derive_rpc(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
let input = proc_macro2::TokenStream::from(input);
use quote::format_ident;
let (name, params, ret) = {
use syn::parse::Parser as _;
let __parser = |
_input: syn::parse::ParseStream,
| -> syn::Result<(syn::Ident, Vec<(syn::Ident, syn::Type)>, syn::Type)> {
let name: syn::Ident = _input.parse()?;
let params = {
let mut __f = Vec::new();
while !__brace_content.is_empty() {
let __fn: syn::Ident = __brace_content.parse()?;
__brace_content.parse::<syn::Token![:]>()?;
let __ft: syn::Type = __brace_content.parse()?;
__f.push((__fn, __ft));
if __brace_content.peek(syn::Token![,]) {
__brace_content.parse::<syn::Token![,]>()?;
}
}
__f
};
let ret: syn::Type = _input.parse()?;
Ok((name, params, ret))
};
match __parser.parse2(input.clone()) {
Ok(v) => v,
Err(e) => return e.into_compile_error().into(),
}
};
let req_name = format_ident!("{}Request", name);
let res_name = format_ident!("{}Response", name);
let __spread_0: proc_macro2::TokenStream = params
.iter()
.map(|(__field_name, __field_ty)| {
quote::quote! {
pub # __field_name : # __field_ty,
}
})
.collect();
let __output = quote::quote! {
pub struct # req_name { # __spread_0 } pub struct # res_name { pub result : #
ret, }
};
__output.into()
}
```
</details>
---
## Quick start
+22
View File
@@ -0,0 +1,22 @@
{ pkgs ? import <nixpkgs> {}}:
pkgs.mkShell {
buildInputs = with pkgs; [
# Rust toolchain
cargo
rustc
rustfmt
clippy
rust-analyzer
# Additional tools
cargo-watch
cargo-edit
# Profiling tools
cargo-flamegraph
samply
perf
];
# Environment variables
RUST_BACKTRACE = 1;
}