Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pharmsol-dsl = { path = "pharmsol-dsl", version = "0.28.2" }
pharmsol-macros = { path = "pharmsol-macros", version = "0.28.2" }
serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
thiserror = "2.0.18"

[package]
name = "pharmsol"
Expand Down Expand Up @@ -52,7 +53,7 @@ cranelift-module = { version = "0.131.0", optional = true }
cranelift-native = { version = "0.131.0", optional = true }
serde = { workspace = true }
serde_json = { workspace = true }
thiserror = "2.0.18"
thiserror = { workspace = true }
tracing = "0.1.44"
wasm-encoder = { version = "0.247.0", optional = true }

Expand Down
1 change: 1 addition & 0 deletions pharmsol-dsl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ bench = false
[dependencies]
serde = { workspace = true }
serde_json = { workspace = true }
thiserror = { workspace = true }
67 changes: 42 additions & 25 deletions pharmsol-dsl/README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,23 @@
# pharmsol-dsl

`pharmsol-dsl` is the backend-neutral frontend crate for the pharmsol DSL.
`pharmsol-dsl` compiles pharmsol DSL model source into a ready-to-run form.

Use this crate when you need to work with model source as data:

- parse DSL text into syntax nodes
- inspect spans and diagnostics
- analyze names and types into typed IR
- lower validated models into the execution model used by runtime backends
- analyze names and types into a checked model
- compile validated models into the ready-to-run form used by runtime backends

Do not use this crate for JIT compilation, native AoT export or load, WASM runtime loading, or `Subject`-based prediction helpers. Those workflows stay in `pharmsol::dsl` in the main `pharmsol` crate.

## Main Pipeline

The public pipeline is:

1. `parse_model` or `parse_module`
2. `analyze_model` or `analyze_module`
3. `lower_typed_model` or `lower_typed_module`

The main public modules are:

- `ast` for syntax-level nodes
- `diagnostic` for spans, codes, and rendered reports
- `ir` for the typed intermediate representation
- `execution` for the lowered execution model shared by JIT, AoT, and WASM backends

The parser accepts both canonical `model { ... }` source and the authoring shorthand used by the `pharmsol` examples.

## Small Example
The one-shot pipeline is `compile_model` or `compile_module`, which fails with
the unified `DslError`:

```rust
use pharmsol_dsl::{analyze_model, lower_typed_model, parse_model};
use pharmsol_dsl::compile_model;

let source = r#"
name = bimodal_ke
Expand All @@ -47,19 +33,50 @@ dx(central) = -ke * central
out(cp) = central / v
"#;

let syntax = parse_model(source).expect("model parses");
let typed = analyze_model(&syntax).expect("model analyzes");
let execution = lower_typed_model(&typed).expect("model lowers");
let execution = compile_model(source).expect("model compiles");

assert_eq!(execution.name, "bimodal_ke");
assert_eq!(execution.metadata.routes.len(), 1);
assert_eq!(execution.metadata.outputs.len(), 1);
```

The staged pipeline is available when you need the intermediate representations:

1. `parse_model` or `parse_module`
2. `analyze_model` or `analyze_module`
3. `compile_analyzed_model` or `compile_analyzed_module`

The main public modules are:

- `syntax` for the syntax tree
- `diagnostic` for spans, codes, and rendered reports
- `analysis` for the analyzed, fully checked model
- `execution` for the ready-to-run model shared by JIT, AoT, and WASM backends

The parser accepts both canonical `model { ... }` source and the authoring
shorthand used by the `pharmsol` examples.

## Errors

Every stage reports errors with source spans and renders an annotated report
when printed:

```text
error[DSL2000]: unknown identifier `missing_state`
--> line 3, column 11
|
3 | out(cp) = missing_state
| ^^^^^^^^^^^^^ unknown identifier `missing_state`
```

`DslError::phase` identifies the failing stage, `DslError::diagnostics`
exposes the structured diagnostics, and `DslError::diagnostic_report` produces
a JSON-serializable report for editors and tooling.

## Boundary With `pharmsol`

`pharmsol-dsl` owns the frontend pipeline and its data structures.
`pharmsol-dsl` owns the source-to-execution compiler and its data structures.

`pharmsol::dsl` re-exports that frontend surface and adds the runtime-facing APIs for backend selection, artifact loading, and prediction execution.
`pharmsol::dsl` re-exports that compiler surface and adds the runtime-facing APIs for backend selection, artifact loading, and prediction execution.

Use `pharmsol-dsl` when you are building tooling, validation, migration, or your own backend. Use `pharmsol::dsl` when you want a complete source-to-runtime workflow.
2 changes: 1 addition & 1 deletion pharmsol-dsl/browser-compile-bridge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ pub unsafe extern "C" fn compile_model(
"metadata": {
"abiVersion": compiled.metadata.abi_version,
"model": compiled.metadata.model,
"kernels": compiled.metadata.kernels,
"functions": compiled.metadata.functions,
}
}));
0
Expand Down
Loading