Claude-skill-registry cljr-feature-dev
Develop features for the Cljr Clojure-to-.NET compiler. Use when adding emitter features, expression types, analyzer support, or testing features. Guides the complete workflow from Expr.cs to C# tests to NRepl verification. Critical for REPL-oriented development.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/cljr-feature-dev" ~/.claude/skills/majiayu000-claude-skill-registry-cljr-feature-dev && rm -rf "$T"
skills/data/cljr-feature-dev/SKILL.mdCljr Feature Development
This skill guides you through the complete workflow for adding features to the Cljr compiler, with proper testing in both C# unit tests and NRepl evaluation.
When to use this skill
- Adding new language features to the emitter
- Creating new expression types in the analyzer
- Modifying existing expression handling
- Testing features via C# unit tests
- Testing features via NRepl evaluation (CRITICAL for REPL-oriented workflow)
Feature Development Workflow
Step 1: Define Expression Type (if new)
Location:
src/Cljr.Compiler/Analyzer/Expr.cs
Add a new record type extending
Expr:
/// <summary> /// Description of what this expression represents /// </summary> public record MyFeatureExpr( string Property1, Expr Property2 ) : Expr;
See expressions.md for all existing expression types.
Step 2: Add Analyzer Support
Location:
src/Cljr.Compiler/Analyzer/Analyzer.cs
- Add case in
orAnalyzeForm()
to recognize the new formAnalyzeSeq() - Build the expression AST
- Handle type hints and symbol resolution
Step 3: Add Emitter Support
Location:
src/Cljr.Compiler/Emitter/CSharpEmitter.cs
- Add case to
switch statementEmitExpr() - Generate valid C# code for the expression
case MyFeatureExpr e: EmitMyFeature(e); break;
Step 4: Write C# Unit Test for Compilation (REQUIRED)
Location:
tests/Cljr.Compiler.Tests/
Test that the emitter generates correct C# code:
[Fact] public void MyFeature_EmitsCorrectCSharp() { var source = "(my-feature args)"; var result = Compile(source); Assert.Contains("expected C# output", result); }
Step 5: Write C# Unit Test for NRepl Eval (REQUIRED)
Location:
tests/Cljr.Compiler.Tests/ReplNamespaceTests.cs
This is CRITICAL for the REPL-oriented workflow. Test via
NreplSession.EvalAsync():
[Fact] public async Task MyFeature_WorksInRepl() { var session = new NreplSession(); var result = await session.EvalAsync("(my-feature args)"); Assert.Null(result.Error); Assert.Equal(expectedValue, result.Values[0]); }
See testing-patterns.md for comprehensive test patterns including:
- State persistence across evaluations
- Namespace isolation
- Error handling
Step 6: Manual NRepl Verification (Optional)
Start the REPL and test interactively:
./nrepl.sh # or dotnet run --project src/Cljr.Cli -- nrepl
Then test your feature in the REPL to verify developer experience.
Key Files
| File | Purpose |
|---|---|
| Expression type definitions |
| Parsing and AST construction |
| C# code generation |
| NRepl evaluation tests |
| REPL session API |
Testing Requirements
Every feature MUST have:
- C# compilation test - Verify the emitter generates correct C#
- C# NRepl eval test - Verify the feature works in REPL evaluation via
NreplSession.EvalAsync()
The NRepl eval test is especially important because it ensures the feature works in the interactive REPL-oriented development workflow that Clojure developers expect.
Run Tests
# Run all compiler tests dotnet test tests/Cljr.Compiler.Tests/ # Run specific test dotnet test tests/Cljr.Compiler.Tests/ --filter "MyFeature"
References
- Expression Types - All 30+ expression types in Expr.cs
- Testing Patterns - C# and NRepl test examples