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
66 changes: 48 additions & 18 deletions .github/workflows/ci-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- uses: actions/checkout@v6
with:
repository: spore-lang/spore
ref: ef627c785e355a70551af5e4f4d85230996ce8d9
ref: d96212aa5a4cfe24759c21d8690642adfd357018
path: _spore

- uses: dtolnay/rust-toolchain@stable
Expand All @@ -58,38 +58,68 @@ jobs:

- name: Format Spore files
run: |
# `src/host.sp` is the package host entry; validate it via package/example flows,
# not standalone file-mode formatting.
paths=(examples src/basic_cli)
# `src/host.sp` is a legacy compatibility shim; validate package-backed behavior
# via the example and platform modules rather than standalone file-mode checks.
# Standalone file examples
find examples -maxdepth 1 -name '*.sp' -type f | sort | xargs _spore/target/release/spore format
# Project-mode examples (format their src files)
if [ -d examples/hello-app/src ]; then
find examples/hello-app/src -name '*.sp' -type f | sort | xargs _spore/target/release/spore format
fi
# Platform API modules
find src/basic_cli -name '*.sp' -type f | sort | xargs _spore/target/release/spore format
# Check tests if they exist
if [ -d tests ]; then
paths+=(tests)
find tests -name '*.sp' -type f | sort | xargs _spore/target/release/spore format
fi
find "${paths[@]}" -name '*.sp' -type f | sort | xargs _spore/target/release/spore format
git diff --exit-code -- "${paths[@]}"
git diff --exit-code

- name: Check Spore files
run: |
# `src/host.sp` is the package host entry; validate it via package/example flows,
# not standalone file-mode checks.
paths=(examples src/basic_cli)
# `src/host.sp` is a legacy compatibility shim; validate package-backed behavior
# via the example and platform modules rather than standalone file-mode checks.
# Standalone file examples
find examples -maxdepth 1 -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore check
# Platform API modules
find src/basic_cli -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore check
# Project-mode examples: validate with spore check
if [ -d examples/hello-app ]; then
echo "✓ Checking project-mode example examples/hello-app/src/main.sp"
_spore/target/release/spore check examples/hello-app/src/main.sp
fi
# Check tests if they exist
if [ -d tests ]; then
paths+=(tests)
find tests -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore check
fi
find "${paths[@]}" -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore check

- name: Build Spore files
run: |
# `src/host.sp` is the package host entry; validate it via package/example flows,
# not standalone file-mode builds.
paths=(examples src/basic_cli)
# `src/host.sp` is a legacy compatibility shim; validate package-backed behavior
# via the example and platform modules rather than standalone file-mode builds.
# Standalone file examples
find examples -maxdepth 1 -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore build
# Platform API modules
find src/basic_cli -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore build
# Project-mode examples: validate with spore build
if [ -d examples/hello-app ]; then
echo "✓ Building project-mode example examples/hello-app/src/main.sp"
_spore/target/release/spore build examples/hello-app/src/main.sp
fi
# Check tests if they exist
if [ -d tests ]; then
paths+=(tests)
find tests -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore build
fi
find "${paths[@]}" -name '*.sp' -type f | sort | xargs -n 1 _spore/target/release/spore build

- name: Run hello example
- name: Run standalone hello example
run: _spore/target/release/spore run examples/hello.sp

- name: Run project-mode hello-app example
run: |
if [ -d examples/hello-app ]; then
echo "✓ Running project-mode example examples/hello-app/src/main.sp"
_spore/target/release/spore run examples/hello-app/src/main.sp
fi

- name: Run Spore spec tests
run: |
if [ ! -d tests ]; then
Expand Down
55 changes: 44 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,58 @@ Operating System

## Quick Start

The canonical project-mode structure is demonstrated in `examples/hello-app/`:

**examples/hello-app/spore.toml:**
```toml
[package]
name = "hello-app"
version = "0.1.0"
type = "application"
spore-version = ">=0.1.0"

[project]
platform = "basic-cli"
default-entry = "app"

[entries.app]
path = "main.sp"

[capabilities]
allow = ["Compute"]

[dependencies]
basic-cli = { path = "../.." }
```

**examples/hello-app/src/main.sp:**
```spore
/// A simple "Hello World" using the basic-cli platform.
import basic_cli.stdout as stdout

fn main() -> () uses [Console] {
println("Hello from Spore basic-cli!")
println("Hello from a project-mode Spore application!")
return
}
```

**Run the project:**
```bash
spore check examples/hello.sp
spore build examples/hello.sp
spore run examples/hello.sp
cd examples/hello-app
spore check src/main.sp
spore run src/main.sp
```

This repository currently keeps `examples/` limited to files that PR CI validates today.
This is a real package-backed application. The in-repo example points `basic-cli` at `../..`; projects generated by `spore new` vendor the package and use `vendor/basic-cli` instead. The formatter currently normalizes the import to `import basic_cli.stdout as stdout`, while `println` still resolves directly in scope.

For quick experiments, you can also run standalone `.sp` files (see `examples/hello.sp`), but production applications should use the project-mode structure above.

## Project Structure

```
basic-cli/
├── spore.toml # Platform manifest
├── src/
│ ├── host.sp # Compatibility runtime entry point
│ ├── host.sp # Legacy compatibility shim
│ ├── platform_contract.sp
│ └── basic_cli/ # Spore API modules, checked and built in CI
│ ├── stdout.sp # Standard output operations
Expand All @@ -75,13 +105,14 @@ The current Platform contract MVP is intentionally split across two artifacts:
- a hole-backed `main` function carries the authoritative startup signature
- `main_for_host` is the Platform-owned adapter that receives the application startup function

Applications targeting `basic-cli` must implement the same startup function name/signature in their entry module. When the compiler starts reading Platform contracts from packages, `spec` items attached to the Platform contract and the application implementation will both have to hold.
Applications targeting `basic-cli` must implement the same startup function name/signature in their entry module. The current compiler already resolves the package's `[platform]` metadata and `src/platform_contract.sp` to validate that startup shape. Runtime support is currently specialized to package-backed `basic-cli`: imported `basic_cli.*` foreign functions route through the built-in basic-cli host profile, while generic `handles` enforcement and startup `spec` stacking are still follow-up work.

`src/host.sp` remains as a compatibility copy of the adapter while the compiler still hardcodes platform startup behavior.
`src/host.sp` remains as a compatibility copy of the adapter for older references; current manifest-backed projects use `src/platform_contract.sp`.

## Tutorial Contract

- `examples/` is for truthful, CI-validated examples only.
- `examples/hello-app/` is the **canonical project-mode example** — it is formatted, checked, built, and run in CI.
- `examples/hello.sp` is a minimal standalone file for quick experiments (also validated in CI).
- `src/basic_cli/` is the API surface for the platform modules themselves.
- `src/platform_contract.sp` is the package-owned startup contract surface.
- Only add `tests/` when the repo has real Spore-side regression coverage worth running with `spore test`.
Expand All @@ -105,7 +136,9 @@ Following Spore's [SEP-0003 (Effect Capability System)](https://github.com/spore

🚧 **Early development** — API is unstable and subject to change.

At the moment, the validated example is `examples/hello.sp`. More ambitious host-backed demos such as environment/file workflows should stay out of `examples/` until the current platform import/runtime architecture supports them honestly.
The canonical example is the **package-backed project-mode** `examples/hello-app/` application. It already validates and runs with `[project].platform = "basic-cli"`, an in-repo path dependency, and `import basic_cli.stdout`.

The standalone file example (`examples/hello.sp`) stays around for quick experiments. The main remaining platform gaps are generic `handles` enforcement, startup `spec` stacking, and lifting the runtime from its current explicit `basic-cli` host profile to a more general package-backed mechanism.

## License

Expand Down
18 changes: 18 additions & 0 deletions examples/hello-app/spore.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "hello-app"
version = "0.1.0"
type = "application"
spore-version = ">=0.1.0"

[project]
platform = "basic-cli"
default-entry = "app"

[entries.app]
path = "main.sp"

[capabilities]
allow = ["Compute"]

[dependencies]
basic-cli = { path = "../.." }
12 changes: 12 additions & 0 deletions examples/hello-app/src/main.sp
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/// Canonical package-backed application example for basic-cli.
///
/// This mirrors the formatted `spore new` scaffold: import the
/// platform module explicitly and call `println` directly from the
/// imported basic-cli surface.
/// Application entry point matching the platform contract.
import basic_cli.stdout as stdout

fn main() -> () uses [Console] {
println("Hello from a project-mode Spore application!")
return
}
6 changes: 3 additions & 3 deletions src/host.sp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/// Compatibility startup adapter.
/// Keep this entry in sync with `platform_contract.sp` until the compiler reads
/// `[platform].contract-module` directly.
/// Legacy compatibility adapter.
/// Manifest-backed projects resolve `main_for_host` from `platform_contract.sp`;
/// keep this shim in sync for older references.
pub fn main_for_host(app_main: () -> ()) -> () {
app_main()
return
Expand Down
Loading