diff --git a/.gitignore b/.gitignore
index 2f7896d..17bd830 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,4 @@
target/
+
+.direnv
+.envrc
\ No newline at end of file
diff --git a/README.md b/README.md
index d8d9413..4ba329b 100644
--- a/README.md
+++ b/README.md
@@ -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 }
+ }
+ }
+ }
+}
+```
+
+
+
+
+ Generated output
+
+
+```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::()?;
+ let __ft: syn::Type = __brace_content.parse()?;
+ __f.push((__fn, __ft));
+ if __brace_content.peek(syn::Token![,]) {
+ __brace_content.parse::()?;
+ }
+ }
+ __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()
+}
+
+```
+
+
+
+
---
## Quick start
diff --git a/shell.nix b/shell.nix
new file mode 100644
index 0000000..46c57b3
--- /dev/null
+++ b/shell.nix
@@ -0,0 +1,22 @@
+{ pkgs ? import {}}:
+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;
+}