Skip to content

Latest commit

 

History

History
159 lines (116 loc) · 6.93 KB

File metadata and controls

159 lines (116 loc) · 6.93 KB

basic-cli

Basic CLI platform for Spore — provides file I/O, process execution, environment variables, and standard I/O effects.

Overview

In Spore, a platform bridges the pure, effect-tracked language with real-world side effects. basic-cli is the standard platform for command-line applications.

Your Spore App (pure, effect-checked)
     ↕  (effect dispatch)
basic-cli Platform API (.sp modules)
     ↕  (foreign fn)
Rust Host (actual I/O via std::fs, std::process, etc.)
     ↕
Operating System

Modules

Module Effects Description
basic_cli.stdout uses [Console] Standard output
basic_cli.stdin uses [Console] Standard input
basic_cli.file uses [FileRead] or uses [FileWrite] File system operations
basic_cli.dir uses [FileRead] or uses [FileWrite] Directory listing and creation
basic_cli.env uses [Env] Environment variables
basic_cli.cmd uses [Spawn] or uses [Exit] Process execution and explicit exit

Quick Start

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

examples/hello-app/spore.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"

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

examples/hello-app/src/main.sp:

import basic_cli.stdout as stdout

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

Run the project:

cd examples/hello-app
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 as an imported platform API call.

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

basic-cli/
├── spore.toml         # Platform manifest
├── src/
│   ├── host.sp        # Legacy compatibility shim
│   ├── platform_contract.sp
│   └── basic_cli/     # Spore API modules, checked and built in CI
│       ├── stdout.sp  # Standard output operations
│       ├── stdin.sp   # Standard input operations
│       ├── file.sp    # File read/write operations
│       ├── dir.sp     # Directory operations
│       ├── env.sp     # Environment variable access
│       └── cmd.sp     # Process execution
├── host/              # Rust host implementation
│   ├── Cargo.toml
│   └── src/
│       └── lib.rs     # Foreign function implementations
└── examples/          # Canonical examples that format/check/run in CI

Contract Surface (MVP)

The current Platform contract MVP is intentionally split across two artifacts:

  1. spore.toml [platform] metadata names the contract module, the startup contract symbol, the adapter function, and the handled effects.
  2. src/platform_contract.sp owns the startup contract itself:
    • 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. The current compiler already resolves the package's [platform] metadata and src/platform_contract.sp to validate that startup shape. Project-mode interpreter runtime support now goes through a generic package-backed host path: imported public foreign fn declarations bind by canonical operation name (print, file_exists, exit, etc.) instead of hard-coding the basic-cli package name. Startup spec stacking and native lowering for foreign fn platform projects are still follow-up work.

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/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 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:

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):

  • Effect-gated: Every I/O function declares its required effects via uses [Effect]
  • Cost-annotated: Platform functions can carry cost [c, a, i, p] budgets where meaningful
  • Error-typed: Functions declare error sets via ! ErrorType
  • Pure by default: The platform boundary is the only place side effects occur

Status

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

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 pure standalone file example (examples/hello.sp) stays around for quick experiments. The main remaining platform gaps are startup spec stacking and native lowering for foreign fn platform projects.

License

MIT — see LICENSE.