Skip to content

Commit 8bdf2b1

Browse files
authored
Merge pull request #254 from nikomatsakis/main
latest round of changes
2 parents c0db6e4 + 2519244 commit 8bdf2b1

Some content is hidden

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

67 files changed

+1675
-171
lines changed

CLAUDE.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
Dada is an experimental programming language that explores what a Rust-like language would look like if designed to feel more like Java/JavaScript rather than C++. It's async-first, uses a permission-based ownership system, and compiles to WebAssembly.
8+
9+
## Development Commands
10+
11+
### Basic Commands
12+
- `cargo run -- compile <file.dada>` - Compile a Dada source file
13+
- `cargo run -- run <file.dada>` - Compile and execute a Dada program
14+
- `cargo run -- test [files]` - Run test suite on specific Dada files
15+
- `cargo run -- debug <file.dada>` - Compile with debug server for introspection
16+
17+
### Testing
18+
- `just test` - Run all tests across the workspace (equivalent to `cargo test --all --workspace --all-targets`)
19+
- `cargo test` - Run Rust unit tests
20+
- Test files are in `tests/` directory with `.dada` extension
21+
22+
### Build Tools
23+
- `cargo xtask build` - Custom build tasks
24+
- `cargo xtask deploy` - Deployment automation
25+
26+
## Architecture
27+
28+
The compiler is built as a Cargo workspace with these key components:
29+
30+
### Core Pipeline (in compilation order)
31+
1. **`dada-parser`** - Lexing/parsing source to AST
32+
2. **`dada-ir-ast`** - AST representation and diagnostics
33+
3. **`dada-ir-sym`** - Symbolic IR (type-checked, high-level representation)
34+
4. **`dada-check`** - Type checking and semantic analysis
35+
5. **`dada-codegen`** - WebAssembly code generation (currently incomplete)
36+
37+
### Supporting Components
38+
- **`dada-lang`** - Main CLI entry point
39+
- **`dada-compiler`** - Compilation orchestration and VFS
40+
- **`dada-debug`** - Debug server for compiler introspection
41+
- **`dada-lsp-server`** - Language Server Protocol implementation
42+
- **`dada-util`** - Shared utilities (arena allocation, logging, etc.)
43+
44+
### Key Design Patterns
45+
- **Salsa-based**: Uses incremental, memoized computation framework
46+
- **Database pattern**: Central `Db` trait for accessing compiler state
47+
- **Async architecture**: Built around async/await throughout
48+
49+
## Current Status & Constraints
50+
51+
- **Early development**: Core language features implemented but not production-ready
52+
- **Codegen limitations**: Most test files have `#:skip_codegen` as WASM generation is incomplete
53+
- **Active experimentation**: Language design still evolving (see `tests/spikes/` for experimental features)
54+
55+
## Language Characteristics
56+
57+
- **Async-first**: Functions are async by default
58+
- **Permission system**: Uses ownership annotations (`my`, `our`, `mut`) for memory management
59+
- **Classes and structs**: Both reference types (classes) and value types (structs)
60+
- **Rust-inspired**: Similar memory safety guarantees with more accessible syntax
61+
- **Comments**: Use `#` not `//`
62+
63+
## Test File Structure
64+
65+
- `tests/parser/` - Parser tests
66+
- `tests/symbols/` - Symbol resolution tests
67+
- `tests/type_check/` - Type checking tests
68+
- `tests/spikes/` - Experimental language features
69+
- `tests/default_perms/` - Default permission inference tests
70+
71+
Test files use `.dada` extension and often include `#:skip_codegen` directives.
72+
73+
## Documentation
74+
75+
The compiler uses rustdoc for comprehensive documentation. Major documentation files:
76+
77+
### Generation Commands
78+
- `just doc` - Generate docs for all crates (recommended)
79+
- `just doc-open` - Generate and open docs in browser
80+
- `just doc-serve` - Generate docs and serve locally at http://localhost:8000
81+
- `cargo doc --workspace --no-deps --document-private-items` - Manual command equivalent to `just doc`
82+
83+
### Documentation Structure
84+
- **`dada-lang`** - Main landing page and compiler overview
85+
- **`dada-ir-sym`** - Core type system and symbolic IR documentation
86+
- **`dada-check`** - Type checking orchestration
87+
- **Individual modules** - Detailed documentation embedded in source
88+
89+
### Documentation Files
90+
- `components/*/docs/*.md` - Extended documentation included via `include_str!`
91+
- Inline module docs using `//!` comments
92+
- Cross-references using `[`item`]` syntax for automatic linking
93+
94+
Major documentation sections:
95+
- **Type Checking Pipeline** - Overview of the checking process
96+
- **Permission System** - Detailed guide to Dada's ownership model
97+
- **Type Inference** - How Hindley-Milner inference works in Dada
98+
- **Subtyping** - Type relationships and conversions
99+
100+
### Documentation Guidelines
101+
102+
#### Cross-Crate Links
103+
- Use `[text](../crate_name)` format for linking to sibling crates (regular markdown links)
104+
- Avoid bare `[crate_name]` links that rely on implicit resolution
105+
106+
#### Intra-Crate Links
107+
- Use `[item](`path::to::item`)` format with backticks around the path (rustdoc links)
108+
- For private items, use `pub(crate)` visibility when the item needs to be documented
109+
- Prefer concrete method names over non-existent placeholder methods
110+
- Examples: `[MyStruct](`crate::module::MyStruct`)`, `[method](`Self::method_name`)`
111+
112+
#### Code Blocks
113+
- Always specify language: ```rust, ```text, ```bash, etc.
114+
- Use ```text for error messages, command output, or mixed syntax
115+
- Use ```rust only for valid Rust code
116+
- Avoid bare ``` without language specification
117+
118+
#### Link Style
119+
- **Intra-crate**: `[item](`path::to::item`)` (with backticks for rustdoc resolution)
120+
- **Cross-crate**: `[crate](../crate_name)` (without backticks for markdown links)
121+
- Keep link text descriptive but concise
122+
123+
#### Writing Style
124+
- Use factual, objective tone
125+
- Avoid subjective adjectives like "powerful", "innovative", "elegant", "robust"
126+
- Focus on describing what the code does, not evaluating its quality
127+
- Let readers draw their own conclusions about the design
128+
- Prefer "implements X" over "provides powerful X functionality"
129+
130+
#### Error Prevention
131+
- Verify referenced types/methods actually exist before documenting them
132+
- Use `--document-private-items` compatible linking for internal docs
133+
- Test documentation builds regularly with `just doc`

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ url = "2.5.3"
1717
annotate-snippets = "0.11.4"
1818
wasm-encoder = "0.220.0"
1919

20+
[workspace.lints.clippy]
21+
needless_lifetimes = "allow"
22+
2023
[package]
2124
name = "dada"
2225
version.workspace = true

components/dada-check/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ name = "dada-check"
33
version.workspace = true
44
edition.workspace = true
55

6+
[lib]
7+
doctest = false
8+
69
[dependencies]
710
dada-ir-ast = { version = "0.1.0", path = "../dada-ir-ast" }
811
dada-ir-sym = { version = "0.1.0", path = "../dada-ir-sym" }
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
# Type Checking Orchestration
2+
3+
This crate provides the high-level orchestration for Dada's type checking process. It implements the [`Check`] trait that defines what it means for a Dada program to successfully compile.
4+
5+
## Purpose
6+
7+
While the detailed type checking logic lives in [`dada_ir_sym::check`], this crate provides:
8+
- **Top-level entry points** for type checking entire programs
9+
- **Orchestration logic** that coordinates different phases of checking
10+
- **The [`Check`] trait** that unifies type checking across different AST nodes
11+
12+
## The Check Trait
13+
14+
The core abstraction is the [`Check`] trait:
15+
16+
```rust
17+
pub trait Check<'db> {
18+
fn check(&self, db: &'db dyn crate::Db);
19+
}
20+
```
21+
22+
This trait is implemented for all major AST and IR nodes:
23+
- **[`SourceFile`]** - Check an entire source file
24+
- **[`SymModule`]** - Check a module and all its items
25+
- **[`SymFunction`]** - Check a function signature and body
26+
- **[`SymAggregate`]** - Check class definitions and members
27+
28+
## Checking Pipeline
29+
30+
When you call `.check()` on a source file, it triggers a cascading validation:
31+
32+
1. **Module checking** - Validates module structure and use statements
33+
2. **Item checking** - Validates each top-level item (classes, functions)
34+
3. **Signature checking** - Validates function signatures and generic parameters
35+
4. **Body checking** - Validates function implementations
36+
5. **Field checking** - Validates class field types
37+
38+
## Error Accumulation
39+
40+
The checking process accumulates errors rather than failing fast. This allows the compiler to report multiple issues at once.
41+
42+
## Integration with Symbolic IR
43+
44+
This crate serves as a bridge between the parsed AST and the detailed type checking in [`dada_ir_sym`]. It:
45+
- Converts AST nodes to symbolic IR
46+
- Invokes the appropriate type checking logic
47+
- Ensures all necessary validations are performed
48+
49+
## Usage
50+
51+
Typically, you'll check an entire program like this:
52+
53+
```rust
54+
use dada_check::Check;
55+
56+
// Check a source file
57+
source_file.check(db);
58+
59+
// Or check a specific function
60+
sym_function.check(db);
61+
```
62+
63+
The actual type checking algorithms and detailed analysis are implemented in [`dada_ir_sym::check`].

components/dada-check/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
//! Type checking orchestration for Dada programs.
2+
#![doc = include_str!("../docs/overview.md")]
3+
14
use dada_ir_ast::{
25
ast::Identifier,
36
diagnostic::{Diagnostic, Level},
@@ -119,7 +122,7 @@ fn check_for_duplicates<'db, S: Spanned<'db>>(
119122
Diagnostic::error(
120123
db,
121124
value.span(db),
122-
format!("duplicate parameter name `{}`", id),
125+
format!("duplicate parameter name `{id}`"),
123126
)
124127
.label(
125128
db,

components/dada-codegen/src/cx/generate_expr.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,10 @@ impl<'cx, 'db> ExprCodegen<'cx, 'db> {
139139
PermissionOp::Give => {
140140
self.push_from(&wasm_place_repr);
141141
}
142+
143+
PermissionOp::Share => {
144+
todo!()
145+
}
142146
}
143147
}
144148
SymExprKind::Call {
@@ -232,10 +236,9 @@ impl<'cx, 'db> ExprCodegen<'cx, 'db> {
232236
}
233237
Err(e) => match e {
234238
NotPrimitive::DeadCode => (),
235-
NotPrimitive::OtherType => panic!(
236-
"don't know how to execute a binary op on ({:?}, {:?})",
237-
lhs_ty, rhs_ty
238-
),
239+
NotPrimitive::OtherType => {
240+
panic!("don't know how to execute a binary op on ({lhs_ty:?}, {rhs_ty:?})")
241+
}
239242
},
240243
}
241244
}

components/dada-codegen/src/cx/generate_expr/wasm_place_repr.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,8 @@ use crate::cx::wasm_repr::WasmRepr;
1313
use super::ExprCodegen;
1414

1515
/// The WASM representation for a Dada place. Dada places can be
16-
/// spread across the WASM local variables and
17-
/// The [`EmplacedWasmRepr`][] type tells you which values are stored
18-
/// where.
16+
/// spread across the WASM local variables and WASM memory.
17+
/// This type tells you which values are stored where.
1918
#[derive(Debug)]
2019
pub enum WasmPlaceRepr {
2120
/// A primitive value stored in a WASM local variable.
@@ -27,8 +26,8 @@ pub enum WasmPlaceRepr {
2726
}
2827

2928
impl<'db> ExprCodegen<'_, 'db> {
30-
/// Returns a [`WasmPointer`][] to the current start of a callee's stack frame.
31-
/// This value is only valid until [`Self::insert_variable`][] is next called.
29+
/// Returns a [`WasmPointer`] to the current start of a callee's stack frame.
30+
/// This value is only valid until [`Self::insert_variable`] is next called.
3231
pub(super) fn next_stack_frame(&self) -> WasmPointer {
3332
WasmPointer {
3433
base_variable: self.wasm_stack_pointer,
@@ -38,7 +37,7 @@ impl<'db> ExprCodegen<'_, 'db> {
3837

3938
/// Introduce the variable `lv` into scope and create a place for it.
4039
/// This can allocate more stack space in WASM memory.
41-
/// You can find this place by invoking [`Self::local`][] later on.
40+
/// You can find this place by invoking [`Self::place_for_local`] later on.
4241
pub(super) fn insert_variable(&mut self, lv: SymVariable<'db>, ty: SymTy<'db>) {
4342
let ty_repr = self.wasm_repr_of_type(ty);
4443
let emplaced_repr = self.emplace_local(&ty_repr);

components/dada-debug/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ version.workspace = true
44
repository.workspace = true
55
edition.workspace = true
66

7+
[lints.clippy]
8+
result_large_err = "allow"
9+
710
[dependencies]
811
anyhow.workspace = true
912
axum = "0.8.1"

components/dada-debug/src/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
pub fn error(e: anyhow::Error) -> String {
2-
format!("<html><body><h1>Oh geez</h1><p>{}</p></body></html>", e)
2+
format!("<html><body><h1>Oh geez</h1><p>{e}</p></body></html>")
33
}

components/dada-debug/src/events.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub async fn events(
2020
state: &State,
2121
) -> anyhow::Result<Vec<crate::root::RootEvent>> {
2222
check_accept_header(headers)?;
23-
crate::root::root_data(&state).await
23+
crate::root::root_data(state).await
2424
}
2525

2626
pub async fn try_event_data(

0 commit comments

Comments
 (0)