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
14 changes: 10 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,13 @@ __pycache__/

.mcp.json

# Written into the CWD by the file-I/O regression test
# (tests/regressions/basics/files/file_io_json_workflow.test.osp), which means
# it lands at the repo root whenever the corpus is run from there.
test_output.txt
# Written into the CWD by regression tests, which means they land at the repo
# root whenever the corpus is run from there. Both of the files below were
# COMMITTED once, in the same change that added the tests writing them — a
# corpus run then leaves the tree dirty, and a stale copy is a test input
# nobody wrote on purpose.
# file_io_json_workflow.test.osp -> test_output.txt, test_stale_reason.txt
# http_state_levels.test.osp -> osprey_http_state_levels.db
test_output.txt
test_stale_reason.txt
osprey_http_state_levels.db
97 changes: 97 additions & 0 deletions Book/EDITORIAL-BRIEF.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# Editorial brief

## Positioning

*The Osprey Book* is the bridge between “I can copy a code sample” and “I can design a small, honest program.” It teaches programming through Osprey's practical functional core: values, functions, inferred types, pattern matching, explicit failure, effects, and isolated concurrency.

The book is not a compressed language specification. It is a guided build in which every new idea solves a problem the reader has already met.

## Reader

The primary reader is a young or early-career developer, roughly beginner to intermediate. They may have tried a school course, a scripting language, a game engine, or a coding agent, but the book does not assume they know compiler theory or functional-programming vocabulary.

The reader can create a text file and use a browser. A local terminal is introduced as a useful tool, not an entrance exam. Installation appears beside the no-install Playground path so toolchain setup never blocks the first success.

More experienced readers should still find a direct account of Osprey's type inference, explicit failure, effects, fibers, memory modes, and flavor boundary.

## Promise and tone

- Pragmatic, friendly, and technically exact
- Short paragraphs with one clear move
- Concrete code before abstraction
- Never childish, even when explaining a first principle
- No hype, fake rivalry, or initiation rituals
- Compiler errors are guidance, not proof that the reader is “bad at programming”
- Define the everyday idea first, then offer the precise term
- Prefer one evolving program over unrelated toy fragments
- Keep limitations beside the feature they qualify

The prose can be energetic. It must never sound breathless. “You made the computer do something” is better than “unlock revolutionary performance.”

## Functional-programming signal

The book gives functional programmers quiet proof that Osprey contains the real ideas: immutable bindings, expressions, Hindley–Milner inference, algebraic data types, exhaustive pattern matching, persistent collections, higher-order functions, and first-class effects.

Those names appear after their behavior is useful. A beginner first learns that a value does not change under their feet; an experienced reader can recognise immutability. A beginner sees every possible state written down; an FP reader can recognise a sum type. No chapter turns that recognition into a lecture aimed past the primary reader.

## Flavor policy

Default flavor is the book's teaching surface. Every core lesson and complete running example appears in `.osp` first.

ML flavor is an optional alternate surface introduced after the reader already understands the shared idea. It is never called a separate language, an advanced mode, or a choice that must be made up front. The book may show a compact ML twin in a “Same flight, different feathers” aside when the comparison reduces confusion.

The language architecture is open to more flavors. Avoid claims that Osprey will always have exactly two. Say “the currently available Default and ML flavors” when the current count matters.

A coding agent can translate surface syntax quickly, which makes experimentation approachable. The book still requires the reader to run `--check` and the relevant tests after translation. Agent assistance lowers typing cost; it does not replace evidence.

## Teaching pattern

Every chapter follows the same learning loop:

1. **Make something happen.** Start from an outcome the reader can see.
2. **Read the code.** Name only the syntax needed for that outcome.
3. **Change one thing.** Invite a safe prediction before the reader runs it.
4. **Meet the idea.** Explain the general principle in plain language.
5. **Let the compiler help.** Make one useful mistake and read the location and expectation.
6. **Build the Flight Log.** Add one bounded capability to the running project.
7. **Take the agent handoff.** Provide a paste-ready prompt with a verification command.
8. **Check the result.** Run the program or tests and state what is now known.

No chapter introduces more than four conceptual families. Code blocks should fit a phone or small e-reader without horizontal scrolling.

## Running project: Flight Log

The reader grows a small personal project that records things they want to learn, marks progress, explains failures, and eventually performs outside work. It begins as a printed launch message, then gains typed states, lists, safe parsing, effects, tests, persistence, and concurrent tasks.

The project is intentionally ordinary. It provides enough domain to make types and effects meaningful without requiring a framework, database, or prior application architecture.

## Chapter limits

- 2,200–3,600 words
- Five to eight core sections
- Four to nine short code or command blocks
- Two to four purposeful visuals
- One Flight Log checkpoint
- One compiler-feedback exercise
- One paste-ready agent handoff
- Five to seven closing takeaways

## Accuracy gates

- Every example is checked with the pinned Osprey compiler.
- Behavior claims cite a governing specification and an executable test where practical.
- Installation commands come from the maintained installation guide.
- A generated illustration never contains product output, syntax, diagnostics, or labels.
- Future work is visibly labelled as future work.
- Native, WebAssembly, effect-resumption, module, package, GPU, and C-FFI limits remain beside the relevant claim.

## Explicitly out of scope

- A compiler implementation textbook
- Category theory as a prerequisite
- A complete standard-library reference
- A promise that alpha software will never change
- Treating ML syntax as mandatory for “real” functional programming
- Pretending a coding agent makes checking and testing optional
- Teaching roadmap-only modules, packages, hardware GPU execution, or strict static memory as shipped features

103 changes: 103 additions & 0 deletions Book/GLOSSARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
# Glossary

This glossary is the vocabulary authority for *The Osprey Book*. Definitions favour the meaning a learner needs in the chapter where a term first appears.

## Argument

A value supplied when calling a function. In `greet("Mika")`, the string `"Mika"` is an argument.

## Binding

A name connected to a value. Default flavor writes an immutable binding as `let name = "Mika"`. The name helps later expressions refer to that value; it does not imply a box that must change.

## Compiler

The program that reads Osprey source, checks it, and produces a native program or WebAssembly module. Running with `--check` stops after checking.

## Default flavor

The book's teaching surface and Osprey's default source syntax. It uses `.osp` files, braces, `fn`, `let`, and parenthesised calls.

## Effect

A typed request for work outside an ordinary calculation, such as logging or storage. The code performing an effect asks for an operation; a handler decides how to answer it.

## Expression

Code that produces a value. A string, a function call, a `match`, and many blocks are expressions in Osprey.

## Fiber

A lightweight unit of concurrent work. Osprey fibers communicate by sending values rather than sharing mutable state.

## Flavor

A source-level way to write Osprey. Default and ML are the currently available flavors. A flavor changes how code is written and read; shared checking and code generation operate after that source has been translated into the language's common program form. More flavors may be added in the future.

## Function

A named or anonymous transformation from input values to an output value. A function can be called more than once with different arguments.

## Handler

Code that gives meaning to one or more effect operations for a particular region of a program.

## Immutable

Unable to be reassigned after creation. Most Osprey bindings are immutable, so a name continues to mean the value it was given.

## Inference

The compiler's ability to work out types from how values are created and used. Inference keeps strong checking while removing obvious annotations.

## ML flavor

An optional Osprey source flavor using indentation-based layout, whitespace application, and currying by default. This book teaches it as an alternative after the shared language ideas are comfortable.

## Native program

A program compiled for a particular operating system and processor, without a virtual machine or JIT warm-up. Osprey produces native code through LLVM and clang.

## Parameter

A name in a function declaration that receives an argument. In `fn greet(name) = ...`, `name` is a parameter.

## Pattern

A shape used by `match` to recognise and, when needed, unpack a value.

## Pattern matching

A decision that compares a value with explicit patterns. For a known union or `Result`, the compiler requires every possible case to be covered.

## Persistent collection

An immutable list or map whose updates return a new collection while safely reusing unchanged internal structure.

## Pipeline

A left-to-right chain made with `|>`. The value on the left becomes the first argument of the function on the right.

## Record

A type or value with named fields that belong together, such as a project with a `name` and `status`.

## Result

A value that is either `Success` with a useful value or `Error` with failure information. `Result` keeps expected failure visible in the type.

## Type

A description of which values an expression may produce and which operations make sense for them.

## Union

A type that lists a closed set of possible cases. Functional programmers may know this as a sum type or algebraic data type.

## Value

A piece of data a program can use, such as a string, number, boolean, list, record, union case, or function.

## WebAssembly

A portable compilation target that can run in supported browser and server environments. Osprey's WebAssembly target supports a smaller runtime surface than native programs.
77 changes: 77 additions & 0 deletions Book/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
PANDOC ?= pandoc
EPUBCHECK ?= epubcheck
RSVG_CONVERT ?= rsvg-convert
MAGICK ?= magick
JQ ?= jq
OSPREY ?= ../target/release/osprey

BOOK_JSON := book.json
MANUSCRIPT := $(shell $(JQ) -r '.sections[].file' $(BOOK_JSON))
EPUB := dist/the-osprey-book-outline.epub
HTML := dist/index.html
DIAGRAM_PNGS := \
assets/diagrams/00-reading-journey.png \
assets/diagrams/01-program-anatomy.png \
assets/diagrams/01-source-to-output.png

.PHONY: check check-examples render-assets epub html release clean

check:
@$(JQ) -e '(.schemaVersion == 1) and ((.sections | length) == 17)' $(BOOK_JSON) >/dev/null
@$(JQ) -e '(.schemaVersion == 1) and ((.sources | length) >= 15)' sources.json >/dev/null
@$(JQ) -e '(.schemaVersion == 1) and ((.figures | length) >= 5)' figures.json >/dev/null
@for file in $(MANUSCRIPT); do test -f "$$file" || { echo "Missing manuscript file: $$file"; exit 1; }; done
@$(PANDOC) $(MANUSCRIPT) --from=gfm --to=native >/dev/null

check-examples:
@test -x "$(OSPREY)" || { echo "Missing compiler: $(OSPREY). Run make build at the repository root."; exit 1; }
@book_tmp=$$(mktemp -d); trap 'rm -r "$$book_tmp"' EXIT; \
$(OSPREY) examples/chapter-01/hello.osp --check >/dev/null; \
$(OSPREY) examples/chapter-01/first-flight.osp --check >/dev/null; \
$(OSPREY) examples/chapter-01/first-flight.ospml --check >/dev/null; \
$(OSPREY) examples/chapter-01/hello.osp --run > "$$book_tmp/hello.out"; \
$(OSPREY) examples/chapter-01/first-flight.osp --run > "$$book_tmp/first-flight.out"; \
$(OSPREY) examples/chapter-01/first-flight.ospml --run > "$$book_tmp/first-flight-ml.out"; \
diff -u examples/chapter-01/hello.expectedoutput "$$book_tmp/hello.out"; \
diff -u examples/chapter-01/first-flight.expectedoutput "$$book_tmp/first-flight.out"; \
diff -u examples/chapter-01/first-flight.expectedoutput "$$book_tmp/first-flight-ml.out"

render-assets: assets/cover/cover.png $(DIAGRAM_PNGS)

assets/cover/cover.png: assets/cover/cover.svg
@$(RSVG_CONVERT) --width 1600 --height 2560 --output $@.base.png $<
@$(MAGICK) $@.base.png \( ../website/src/assets/images/logo.png -resize 184x184 \) -geometry +112+104 -composite $@
@rm -f $@.base.png

assets/diagrams/%.png: assets/diagrams/%.svg
@$(RSVG_CONVERT) --width 1600 --height 1000 --output $@ $<

epub: check check-examples render-assets
@mkdir -p dist
@$(PANDOC) $(MANUSCRIPT) \
--from=gfm \
--to=epub3 \
--toc \
--metadata-file=metadata.yaml \
--css=styles/epub.css \
--epub-cover-image=assets/cover/cover.png \
--output=$(EPUB)
@$(EPUBCHECK) $(EPUB)

html: check render-assets
@mkdir -p dist
@$(PANDOC) $(MANUSCRIPT) \
--from=gfm \
--to=html5 \
--standalone \
--embed-resources \
--resource-path=. \
--toc \
--metadata-file=metadata.yaml \
--css=styles/epub.css \
--output=$(HTML)

release: check check-examples render-assets epub html

clean:
@rm -f $(EPUB) $(HTML) assets/cover/cover.png $(DIAGRAM_PNGS)
Loading
Loading