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
7 changes: 4 additions & 3 deletions .github/workflows/ci-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,16 @@ jobs:
- name: Check Spore files
run: |
find src/basic_cli -name '*.sp' -type f | sort | xargs -n 1 spore check
spore check examples/hello.sp
spore check examples/hello-app/src/main.sp

- name: Build Spore files
- name: Build Spore platform API files
run: |
find src/basic_cli -name '*.sp' -type f | sort | xargs -n 1 spore build
spore build examples/hello-app/src/main.sp

- name: Run project-mode hello-app example
- name: Run Spore examples
run: |
spore run examples/hello.sp
(
cd examples/hello-app
echo "✓ Running project-mode example (default entry)"
Expand Down
33 changes: 25 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ basic-cli = { path = "../.." }
import basic_cli.stdout as stdout

fn main() -> () uses [Console] {
println("Hello from a project-mode Spore application!")
println("Hello from a project-mode Spore application!");
return
}
```
Expand All @@ -67,9 +67,9 @@ spore check src/main.sp
spore run src/main.sp
```

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.
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 as an imported platform API call.

For quick experiments, you can also run standalone `.sp` files (see `examples/hello.sp`), but production applications should use the project-mode structure above.
For quick experiments, you can also run pure standalone `.sp` files (see `examples/hello.sp`), but production applications that call platform APIs such as `println` should use the project-mode structure above.

## Project Structure

Expand All @@ -90,7 +90,7 @@ basic-cli/
│ ├── Cargo.toml
│ └── src/
│ └── lib.rs # Foreign function implementations
└── examples/ # Canonical examples that format/check/build in CI
└── examples/ # Canonical examples that format/check/run in CI
```

## Contract Surface (MVP)
Expand All @@ -108,18 +108,35 @@ Applications targeting `basic-cli` must implement the same startup function name

## Tutorial Contract

- `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.
- `examples/hello-app/` is the **canonical project-mode example** — it is formatted, checked, and run in CI.
- `examples/hello.sp` is a minimal pure standalone file for quick experiments — it is formatted, checked, and run 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`.

If you want to add a new tutorial/example, treat this as the bar:

1. keep it self-contained;
2. make sure it passes `spore format --check`, `spore check`, and `spore build`;
2. make sure it passes `spore format --check`, `spore check`, and `spore run`;
3. only then promote it into `examples/` and mention it in this README.

Native `spore build` is still useful for platform API modules and pure standalone files, but it is not required for package-backed platform projects that rely on `foreign fn` declarations until the backend supports foreign/platform lowering.

## Platform API Calls and Effect Syntax

Project-mode applications call imported `basic-cli` platform functions directly:

```spore
import basic_cli.stdout as stdout

fn main() -> () uses [Console] {
println("Hello from basic-cli!");
return
}
```

In this style, the `uses [Console]` clause records the capability required by the direct `println` platform API call. The lower-level `perform Effect.op(...)` form belongs to effect-handler syntax; use it only when documenting or implementing explicit handlers, not for the normal `basic-cli` project-mode tutorial path.

## Design Philosophy

Following Spore's [SEP-0003 (Effect System)](https://github.com/spore-lang/spore-evolution/blob/main/seps/SEP-0003-effect-system.md):
Expand All @@ -135,7 +152,7 @@ Following Spore's [SEP-0003 (Effect System)](https://github.com/spore-lang/spore

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 handled-effects enforcement, startup `spec` stacking, and lifting the runtime from its current explicit `basic-cli` host profile to a more general package-backed mechanism.
The pure standalone file example (`examples/hello.sp`) stays around for quick experiments. The main remaining platform gaps are generic handled-effects enforcement, startup `spec` stacking, native lowering for `foreign fn` platform projects, and lifting the runtime from its current explicit `basic-cli` host profile to a more general package-backed mechanism.

## License

Expand Down
14 changes: 12 additions & 2 deletions examples/hello.sp
Original file line number Diff line number Diff line change
@@ -1,4 +1,14 @@
/// A simple "Hello World" using the basic-cli platform.
/// A minimal pure standalone Spore file.
///
/// Run with: spore run examples/hello.sp
fn main() -> () uses [Console] { println("Hello from Spore basic-cli!") }
///
/// This intentionally does not import or call the basic-cli platform. Platform
/// APIs such as `println` are available from package-backed applications like
/// `examples/hello-app/`, not from standalone files.
fn greeting(name: Str) -> Str { "Hello, " + name + "!" }

fn main() -> () {
let message = greeting("standalone Spore");
message;
return
}
Loading