Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
2c3c5fb
Add contextual spec paragraph ID resolution and draft string literal …
nikomatsakis Feb 11, 2026
f33d29c
Align RFC-0001 and spec for string literals
nikomatsakis Feb 11, 2026
85fc406
Support inline spec tags and extract shared badge rendering
nikomatsakis Feb 11, 2026
ce5dcc0
Add spec-aligned string literal tests and organize test directory
nikomatsakis Feb 12, 2026
f901e38
Move project guidance into contextual skills and slim down CLAUDE.md
nikomatsakis Feb 12, 2026
f773d58
Implement triple-quoted string literals
nikomatsakis Feb 12, 2026
acd36f2
Refactor string tokenizer: extract helpers and fix span offsets
nikomatsakis Feb 13, 2026
82f579d
Simplify string tokenizer: use peek-consume-peek instead of byte look…
nikomatsakis Feb 13, 2026
1d50458
Add inline Ast probe and implement multiline string dedenting
nikomatsakis Feb 13, 2026
4f73b78
Direct implementation tracking to RFC impl.md instead of GitHub issues
nikomatsakis Feb 14, 2026
3e7c748
Implement raw strings: "\ prefix disables multiline dedenting
nikomatsakis Feb 14, 2026
05be218
Add .claude/.gitignore to exclude local settings
nikomatsakis Feb 14, 2026
ecd8759
Draft spec chapters for grammar and program structure
nikomatsakis Feb 14, 2026
9929028
Add EBNF grammar to spec chapters, eliminate interfering rules
nikomatsakis Feb 14, 2026
4cdf7a0
Parse EBNF in spec directives: expand productions, link nonterminals
nikomatsakis Feb 17, 2026
cec85a1
Add EBNF grammars to statements and expressions spec chapters
nikomatsakis Feb 18, 2026
1c6ac25
chore: apply cargo fmt formatting
nikomatsakis Feb 20, 2026
4faaa02
feat: add FIXME_ICE test harness directive for type checker ICEs
nikomatsakis Feb 20, 2026
0809b6e
test: add spec-aligned expression grammar test suite
nikomatsakis Feb 20, 2026
fb2d790
chore: fix clippy collapsible_if warnings
nikomatsakis Feb 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
settings.local.json
44 changes: 0 additions & 44 deletions .claude/behavior.md

This file was deleted.

88 changes: 88 additions & 0 deletions .claude/skills/author-code/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
name: author-code
description: Conventions for authoring Rust code in the Dada compiler. Use when writing or modifying Rust code, adding functions, or making implementation changes.
---

# Authoring Code in Dada

## Code Style

- **Match local conventions** — mimic the style of the file you're editing
- **Use existing utilities** — check for helper functions before writing new ones
- **Check dependencies first** — never assume a library is available; verify in Cargo.toml
- **Follow existing patterns** — look at neighboring code and match its style

## Documentation

### When to document
- **Complex functions** encoding Dada's semantics need thorough documentation
- **Self-evident code** — simple utility functions don't need extensive comments

### Documentation pattern
- Use doc comments (`///`) with high-level explanation
- Include concrete Dada code examples showing the feature being implemented
- Use inline comments referencing back to the examples

```rust
/// Type checks a method call expression like `obj.method(args)`.
///
/// # Example
/// ```dada
/// let p = Point(x: 10, y: 20)
/// p.distance(other) # <-- we are type checking this
/// ```
///
/// The method resolution follows these steps:
/// 1. Determine the type of the receiver (`p`)
/// 2. Look up the method in the type's namespace
/// 3. Check argument compatibility
fn type_check_method_call(...) {
// Step 1: Get receiver type (Point in our example)
let receiver_ty = self.type_of(receiver);

// Step 2: Resolve method - this handles the lookup of `distance`
// in the Point type's method table
let method = self.resolve_method(receiver_ty, method_name)?;
}
```

## Insight Comments (`💡`)

Use `💡` comments to capture non-obvious constraints and reasoning for future sessions.

### Format
- **Preamble comment** on functions: explain the overall algorithmic or architectural choice
- **Inline comments** at the start of logical blocks: explain reasoning for that block
- **Before modifying code with `💡` comments**: pause and consider whether the reasoning affects your planned changes

### Decision boundaries

Annotate non-obvious decisions — skip self-explanatory code:
- ❌ `// 💡: Using a loop to iterate through items`
- ✅ `// 💡: Using manual iteration instead of map() to handle partial failures gracefully`

Document constraint-driven choices:
- ❌ `// 💡: Using async/await for the API call`
- ✅ `// 💡: Using async/await because this API has 2-second response times that would block the UI`

Document tradeoffs and alternatives:
- ✅ `// 💡: Using Redis instead of in-memory cache because we need persistence across server restarts`

Capture consistency requirements:
- ✅ `// 💡: Using Result<T, E> pattern to match error handling in auth.rs and database.rs modules`

### Guidelines
1. **Focus on decisions with alternatives** — if there was only one way to do it, don't annotate
2. **Update annotations when modifying code** — ensure reasoning still matches implementation
3. **Be concise but specific** — future sessions should understand the decision quickly

## Error Handling

- Use diagnostics infrastructure from `dada-ir-ast`
- Provide helpful error messages with source spans
- Follow existing error formatting patterns

## References

- Crate-level rustdoc — each crate has `docs/overview.md` included via `#![doc = include_str!(...)]`
- Run `cargo doc --open` to browse implementation docs
128 changes: 128 additions & 0 deletions .claude/skills/rfc-workflow/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
---
name: rfc-workflow
description: RFC and specification workflow for Dada language features. Use when working with RFCs, writing spec paragraphs, or tracking implementation progress.
---

# RFC and Specification Workflow

This skill covers the practical RFC and spec integration workflow.

## RFC Directory Structure

```
rfcs/src/NNNN-feature-name/
├── README.md # The RFC document (design, motivation, examples)
├── impl.md # Implementation progress tracking
└── todo.md # Session-specific work tracking and context
```

Create new RFCs with: `cargo xtask rfc new feature-name`

## Spec Paragraph Authoring

Spec paragraphs live in `spec/src/` using MyST directive syntax.

### Block directives

```markdown
:::{spec} local-name tag1 tag2
Paragraph content describing one testable behavior.
:::
```

**Tags**:
- `rfcNNNN` — Links paragraph to an RFC (e.g., `rfc0001`)
- `unimpl` — Feature is specified but not yet implemented
- No tag for the local name means the ID comes from headings only

### Inline sub-paragraphs

Inside a block, mark sub-items with inline spec tags:

```markdown
:::{spec} rfc0001
String literals support these escape sequences:

* {spec}`backslash` `\\` produces a literal backslash.
* {spec}`newline` `\n` produces a newline.
:::
```

Each `` {spec}`name` `` creates a sub-paragraph with its own ID. Tags like `unimpl` can follow the name: `` {spec}`triple-quoted unimpl` ``.

### Paragraph ID format

```
file-prefix.heading-segment.local-name.inline-name
```

- File prefix: from path (e.g., `syntax.string-literals`)
- Heading segments: H2+ headings, lowercased, spaces → hyphens
- Local name: from `:::{spec} local-name`
- Inline name: from `` {spec}`name` ``

## Workflow: When to Put Spec Paragraphs Where

**Design is mature** → Author directly in `spec/src/` with `rfcNNNN unimpl` tags. This is the preferred approach — it validates the spec structure early.

**Design is still evolving** → Draft in the RFC's spec.md, then move to `spec/src/` during implementation.

The key insight: if you know enough to write a spec paragraph, put it in the spec. The `unimpl` tag makes it clear it's not yet implemented.

## Implementation Tracking

### impl.md

Track implementation progress in the RFC's impl.md:

```markdown
# Implementation Progress

## Status: In Progress

### Completed
- [x] Spec paragraphs drafted in spec/src/
- [x] Basic string literal parsing

### In Progress
- [ ] Triple-quoted string support

### Not Started
- [ ] String interpolation
```

### todo.md

Track session-specific context in todo.md:

```markdown
# Current Session

## Focus
What we're working on right now

## Next Steps
- Specific actionable items

## Open Questions
- Things still being figured out
```

## Cross-Referencing

- **Tests → Spec**: `#:spec syntax.string-literals.escape-sequences.backslash`
- **Spec → RFC**: `rfc0001` tag on `:::{spec}` directives
- **RFC → Spec**: Reference spec section in RFC README.md

Keep these synchronized. When adding a new spec paragraph, check if tests exist. When writing tests, add the `#:spec` annotation.

## Implementation Workflow

When implementing an RFC feature, follow this cycle for each piece of work:

1. Implement the feature in the compiler
2. Write tests with `#:spec` annotations
3. Remove `unimpl` from the spec paragraph tag
4. **Update the RFC's `impl.md`** — check off completed items, add new items discovered during implementation

Keep `impl.md` current as you go. It's the living record of what's done and what's next — don't wait until the end of a session to update it.
109 changes: 109 additions & 0 deletions .claude/skills/run-tests/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
name: run-tests
description: Run and interpret Dada test results. Use when running tests, debugging test failures, or understanding test output.
---

# Running Dada Tests

## Commands

```bash
# Run all tests
cargo dada test --porcelain

# Run tests in a directory
cargo dada test --porcelain tests/syntax/string_literals/

# Run a single test file
cargo dada test --porcelain tests/syntax/string_literals/type.dada
```

Always use `--porcelain` for machine-readable JSON output with structured failure information.

## Interpreting Output

The `--porcelain` flag produces JSON with this structure:

```json
{
"summary": { "total": 45, "passed": 45, "failed": 0, "duration_ms": 70 },
"tests": [
{
"path": "tests/syntax/string_literals/type.dada",
"status": "pass",
"annotations": ["#:skip_codegen", "#:spec syntax.string-literals.type"]
}
]
}
```

For failures, each test includes:
- `suggestion` — Actionable guidance on how to resolve the failure. **Read this first.**
- `details` — Usually points to a `.test-report.md` file alongside the test

## Reading Test Reports

When a test fails, a `.test-report.md` file is generated next to the test file. It contains:

1. **Compiler output** — The actual errors/warnings produced
2. **Unexpected diagnostics** — Errors the compiler produced that the test didn't expect
3. **Missing expected diagnostics** — `#!` annotations that didn't match any compiler output
4. **Probe failures** — `#?` probes that got unexpected results
5. **Next Steps** — Suggestions for resolution

## Test Annotation Reference

### Spec references
```dada
#:spec syntax.string-literals.escape-sequences.backslash
```
Links the test to a spec paragraph. Validated against actual spec files.

### Directives
```dada
#:skip_codegen # Skip WebAssembly generation (use for parser/type-check only tests)
#:fn_asts # Compare function AST output against .ref file
```

### Diagnostic expectations (`#!`)

**Without carets** — error can start anywhere on the previous interesting line:
```dada
print(unknown_var)
#! could not find anything named `unknown_var`
```

**With carets** — error span must match exactly (caret position = column on previous line):
```dada
fn test() { bad_name() }
#! ^^^^^^^^ could not find anything named `bad_name`
```

**With regex** — use `/` prefix (opening `/` only, NO closing `/`):
```dada
is_shared(x.mut)
#! /where clause.*not satisfied
```

> **Important**: The regex convention uses `/pattern` with NO closing `/`. Including a closing `/` causes the `/` to be part of the regex pattern, which will fail to match.

### Type probes (`#?`)

```dada
let x = 22 + 44
#? ^^ ExprType: u32 # Type of expression at that span
#? ^ VariableType: u32 # Type of the variable
```

Caret position must align with the target on the previous line. `VariableType` shows the declared type (e.g., `String` not `my String` — the permission is on the expression, not the variable).

Probes also support regex with `/`:
```dada
#? ^ VariableType: /my.*String
```

## Common Patterns

- Tests that only exercise parsing/type-checking should use `#:skip_codegen`
- Error tests use `#!` annotations; the test passes when all expected errors match and no unexpected errors appear
- Probe tests use `#?` annotations; the test passes when all probes return expected values
Loading