Skip to content

Commit 87390e2

Browse files
authored
Add AI-maintained knowledge base documentation (#244)
* Scaffold reference docs * Reorganize reference files * Add review instructions * Revise docs * Revise docs * Revise docs * Add example docs * Add Hypershell example * Add profile picture example * Add money transfer example * Add extensible data types examples * Add web app example * Add syntax grammar sections to macro pages * Revise examples used in references * Add extensible shape example * Add modular serialization and coherence dos * Clarify use of open * Move concepts to top-level * Scaffold new CGP skill * Revise skills * Minor revise skills * Add error handling and modularity hierarchy concepts
1 parent f4460fb commit 87390e2

131 files changed

Lines changed: 17646 additions & 1 deletion

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CLAUDE.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Understanding CGP first
6+
7+
This repository **is** the implementation of Context-Generic Programming (CGP). Before reading or
8+
writing any CGP code here, **always invoke the `/cgp` skill** to load the fundamentals (consumer vs.
9+
provider traits, `#[cgp_component]`/`#[cgp_impl]`/`#[cgp_fn]`, `delegate_components!`, `HasField`,
10+
`UseDelegate`, check traits, etc.). Re-invoke it whenever you navigate into unfamiliar parts of the
11+
codebase — the macros and core traits here are the ground truth that the skill describes, so the two
12+
should always be read together.
13+
14+
The canonical export surface for users is `cgp::prelude` — see
15+
[crates/main/cgp/src/prelude.rs](crates/main/cgp/src/prelude.rs), which re-exports
16+
`cgp_core::prelude` + `cgp_extra::prelude`. When unsure what a name resolves to, start from the
17+
prelude re-exports in [crates/main/cgp-core/src/prelude.rs](crates/main/cgp-core/src/prelude.rs).
18+
19+
## Commands
20+
21+
This is a Cargo workspace (edition 2024, resolver 3). Toolchain is pinned to **1.93** via
22+
[rust-toolchain.toml](rust-toolchain.toml). Nearly every crate is `#![no_std]` — keep new code
23+
`no_std`-compatible (use `core`/`alloc`, gate `std`/`alloc` usage behind features as existing crates
24+
do).
25+
26+
- **Format** (requires nightly — `.rustfmt.toml` uses unstable `group_imports`/`imports_granularity`):
27+
`cargo +nightly fmt --all` (check: `cargo +nightly fmt --all -- --check`)
28+
- **Lint:** `cargo clippy --all-features --all-targets -- -D warnings`
29+
and `cargo clippy --no-default-features --all-targets -- -D warnings`
30+
- **Test** (uses `cargo-nextest`): `cargo nextest run --all-features --no-fail-fast --workspace`
31+
- **Single test crate / test:** `cargo nextest run -p cgp-tests` or target one file with the
32+
standard test harness, e.g. `cargo test -p cgp-tests --test component`
33+
- Many "tests" are **compile-time wiring checks** (`check_components!` /
34+
`delegate_and_check_components!`) and **macro-expansion snapshots** — for these, a successful
35+
`cargo build`/`cargo test` compilation *is* the passing test. A wiring mistake surfaces as a
36+
compile error, not a runtime failure.
37+
38+
## Architecture: layered micro-crates
39+
40+
Crates are organized so that low-level primitives have no knowledge of the high-level facade. Work
41+
inward (core/macros) when changing fundamentals, outward (main) only to adjust the public surface.
42+
43+
- **`crates/macros/`** — the proc-macro pipeline. `cgp-macro` is a thin `#[proc_macro]` entrypoint
44+
that forwards to `cgp-macro-lib` (one module per macro), which in turn builds on
45+
**`cgp-macro-core`** — this is where the real parsing, AST types, and codegen live (see
46+
`cgp-macro-core/src/{types,functions,visitors,macros}/`). When a macro misbehaves, the logic to
47+
fix is almost always in `cgp-macro-core`, not the entrypoint crate. `cgp-async-macro` provides
48+
`#[async_trait]`; `cgp-extra-macro{,-lib}` host the extra-feature macros.
49+
50+
- **`crates/core/`** — the foundational runtime traits the macros expand into:
51+
- `cgp-component` — the wiring machinery: `DelegateComponent`, `IsProviderFor`,
52+
`CanUseComponent`, `UseContext`, `UseDelegate`, `UseField`, `WithProvider`, etc.
53+
- `cgp-type` — abstract types: `HasType`, `TypeProvider`, `UseType`.
54+
- `cgp-field``HasField` and extensible data: `Cons`/`Nil`, `Symbol`, `Index`, `Field`,
55+
builders/extractors for records and variants.
56+
- `cgp-error``HasErrorType`, `CanRaiseError`, `CanWrapError`.
57+
- `cgp-base-types` — the lowest-level type-level primitives (`Symbol`/`Chars`/`Cons`/`Nil`/path).
58+
59+
- **`crates/extra/`** — higher-level building blocks layered on core: `cgp-handler`,
60+
`cgp-dispatch`, `cgp-monad`, `cgp-run`, `cgp-runtime`, `cgp-field-extra`, `cgp-error-extra`.
61+
62+
- **`crates/main/`** — facade crates that only re-export. `cgp` is the crate users depend on
63+
(`cgp = core + extra`, exposing `cgp::prelude`). `cgp-core`/`cgp-extra`/`cgp-base`/
64+
`cgp-base-extra` are intermediate bundles. Changes here are almost always just re-export plumbing.
65+
66+
- **`crates/standalone/error/`** — pluggable error backends implementing the `cgp-error` traits:
67+
`cgp-error-anyhow`, `cgp-error-eyre`, `cgp-error-std`. These are opt-in and not part of the
68+
default `cgp` facade.
69+
70+
- **`crates/tests/`**`cgp-tests` exercises real wiring and the user-facing macros end-to-end;
71+
`cgp-macro-tests` covers parser corner cases plus **expansion snapshots** via the `snapshot_*`
72+
proc macros in `cgp-macro-test-util{,-lib}` (which pretty-print generated code with
73+
`prettyplease`). When you change macro codegen, expect snapshot output to change — update and
74+
review the expanded code, since it is the contract users see.
75+
76+
## Conventions specific to this repo
77+
78+
- All versions are kept in lockstep at the workspace level (currently **0.7.0**); inter-crate
79+
dependencies are declared once in the root [Cargo.toml](Cargo.toml) `[workspace.dependencies]`
80+
and referenced with `{ workspace = true }`. Add new crates to the `members` list and the
81+
workspace dependency table together.
82+
- The crate split is deliberate (coherence-friendly micro-crates). When adding functionality,
83+
place it in the lowest layer that makes sense and re-export upward through the facade crates,
84+
rather than adding cross-layer dependencies that skip the hierarchy.
85+
- See [CHANGELOG.md](CHANGELOG.md) for the evolution of macro syntax — it is the most reliable
86+
record of which macro forms are current vs. removed (e.g. `#[cgp_context]` was removed,
87+
`ProvideType``TypeProvider`).
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
`cgp-macro-core` is the pure-logic core of the CGP proc-macro suite. **Always invoke the `/cgp`
6+
skill before working here** — every type in this crate exists to generate one of the CGP constructs
7+
the skill describes (`#[cgp_component]`, `#[cgp_impl]`, `#[cgp_fn]`, `delegate_components!`,
8+
`check_components!`, `#[derive(HasField)]`, …). You cannot correctly change the *output* of a macro
9+
without knowing the *expansion* it is supposed to produce, and that expansion is documented by
10+
`/cgp`. The workspace-level [../../../CLAUDE.md](../../../CLAUDE.md) covers build/test/lint commands
11+
and the crate hierarchy.
12+
13+
## What this crate is (and isn't)
14+
15+
- It contains **no `#[proc_macro]` entrypoints** and does **not depend on `proc-macro`** — only
16+
`syn` (with `full`, `extra-traits`, `visit`, `visit-mut`), `quote`, `proc-macro2`, `itertools`.
17+
Everything operates on `proc_macro2::TokenStream` and `syn` AST.
18+
- The proc-macro pipeline is **`cgp-macro` (entrypoints) → `cgp-macro-lib` (per-macro glue) →
19+
`cgp-macro-core` (this crate, all the logic)**. A `cgp-macro-lib` function is thin: `syn::parse2`
20+
the attr/item, build a `cgp_macro_core::types::<macro>::Item*`, run its transform pipeline, and
21+
wrap the result in `quote!`. See `cgp-macro-lib/src/cgp_component.rs` for the canonical shape.
22+
- Because it is `proc-macro`-free, its parsers and codegen are **unit-testable as plain functions**.
23+
Tests live in the sibling `crates/tests/cgp-macro-tests` crate (parser corner cases like
24+
`IdentWithTypeArgs`, plus expansion **snapshots** via the `snapshot_*` macros). Prefer adding
25+
coverage there over ad-hoc verification.
26+
27+
## Module map
28+
29+
- **[src/types/](src/types/)** — the bulk of the crate. One submodule per user-facing macro
30+
(`cgp_component`, `cgp_impl`, `cgp_provider`, `cgp_fn`, `cgp_getter`, `cgp_auto_getter`,
31+
`cgp_type`, `cgp_data`, `delegate_component`, `check_components`,
32+
`delegate_and_check_components`, `namespace`, `product`, `sum`), plus shared building-block types:
33+
`attributes/` (parsing of `#[uses]`, `#[use_type]`, `#[use_provider]`, `#[derive_delegate]`,
34+
`#[default_impl]`), `generics/`, `field/`, `getter/`, `implicits/`, `ident/`, `path/`, `keyword`.
35+
- **[src/functions/](src/functions/)** — free helper functions: identifier case conversion
36+
(`camel_case`/`snake_case`), `parse_internal`, generics merging, delegated-impl synthesis,
37+
field/getter/implicit-argument parsing, `strip`.
38+
- **[src/visitors/](src/visitors/)**`syn` `VisitMut` passes that rewrite ASTs. `replace_self`
39+
(receiver/type/value) is the heart of `#[cgp_impl]`: it rewrites `self`/`Self` into the explicit
40+
`context`/`Context`. Also `replace_provider`, `remove_self_path`, `self_assoc_type`, and
41+
`substitute_abstract_type` (the `#[use_type]` machinery). **Do AST rewriting with these visitors,
42+
never with string manipulation.**
43+
- **[src/exports.rs](src/exports.rs)** — see "hygiene" below.
44+
- **[src/traits/](src/traits/)** — small internal traits (`ToType`, `IsKeyword`, bound helpers).
45+
- **[src/macros/](src/macros/)** — internal `macro_rules!`: `parse_internal!`, `export_construct(s)!`,
46+
`define_keyword!`.
47+
- **[src/vendor.rs](src/vendor.rs)** — re-exports `quote::quote` so exported `macro_rules!` can use
48+
it from downstream crates.
49+
50+
## Conventions you must follow
51+
52+
**1. Construct = a type implementing `Parse` and/or `ToTokens`.** Input is parsed by implementing
53+
`syn::parse::Parse`; code is emitted by implementing `quote::ToTokens`. Add new syntax by writing a
54+
type with these impls rather than hand-rolling token munging.
55+
56+
**2. Build AST nodes with `parse_internal!`, not by hand.** `parse_internal!(#some_tokens ...)`
57+
(in [src/functions/parse_internal.rs](src/functions/parse_internal.rs)) quasi-quotes tokens and
58+
parses them into the target `syn` type, attaching a descriptive error (including the offending
59+
tokens with the `::cgp::macro_prelude::` prefix stripped) on failure. It expands to a `?`
60+
expression, so call it inside a `syn::Result`-returning function.
61+
62+
**3. Reference CGP items through `exports.rs`, never by hardcoded path.** Each name in
63+
[src/exports.rs](src/exports.rs) (`IsProviderFor`, `DelegateComponent`, `UseField`, `HasField`, …)
64+
is a zero-sized marker struct whose `ToTokens` emits the fully-qualified path
65+
`::cgp::macro_prelude::<Name>`. Generated code interpolates these markers (e.g.
66+
`use crate::exports::IsProviderFor;` then `#is_provider_for`) so the expansion is hygienic and the
67+
user only needs `cgp` in scope. **To emit a new CGP item, add it to `export_constructs!` in
68+
`exports.rs` and interpolate the marker** — don't write `::cgp::...` path literals inline.
69+
70+
**4. Codegen is a staged transform pipeline.** Each macro type moves through explicit stages rather
71+
than emitting in one pass. The reference shape is `cgp_component`:
72+
`ItemCgpComponent { args, item_trait }``.preprocess()``PreprocessedCgpComponent`
73+
`.eval()``Evaluated…``.to_items()``Vec<syn::Item>` (driven by
74+
`cgp-macro-lib/src/cgp_component.rs` as `item.preprocess()?.eval()?.to_items()?`). Other macros use
75+
their own stage names — look for `item.rs`, `preprocessed.rs`/`lowered.rs`, `evaluated/`, and
76+
`to_*` methods within each `types/<macro>/` directory. When extending a macro, slot your change
77+
into the existing stage rather than collapsing the pipeline.
78+
79+
**5. Custom keywords go through `define_keyword!` + `IsKeyword`** (see
80+
[src/macros/keyword.rs](src/macros/keyword.rs) and `types/keyword*.rs`).

crates/main/cgp-core/src/prelude.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub use cgp_field::traits::{
1717
pub use cgp_field::types::{Chars, Cons, Either, Field, Index, Life, Nil, Symbol, Void};
1818
pub use cgp_macro::{
1919
BuildField, CgpData, CgpRecord, CgpVariant, ExtractField, FromVariant, HasField, HasFields,
20-
Product, Sum, Symbol, cgp_auto_getter, cgp_component, cgp_fn, cgp_getter, cgp_impl,
20+
Path, Product, Sum, Symbol, cgp_auto_getter, cgp_component, cgp_fn, cgp_getter, cgp_impl,
2121
cgp_namespace, cgp_new_provider, cgp_provider, cgp_type, check_components,
2222
delegate_and_check_components, delegate_components, product,
2323
};

0 commit comments

Comments
 (0)