Skip to content

Pepper v0.2.0

Choose a tag to compare

@justinboswell justinboswell released this 19 Oct 04:45
· 556 commits to main since this release

Pepper v0.2.0: everything merged since the v0.1.0 extension release (2026-09-21). One line per pull request.

The VS Code extension is published as release vsix-v0.2.0. It was built from main at 543c43c0, which is v0.2.0 plus #275, a test-only fix to the LSP smoke test.

Language

  • Attribute syntax [Name(args)] on functions, blocks, externs, structs and members (#39)
  • Per-platform code with OS(...)/Arch(...), consolidated into [Target(<bool expr>)] (#40, #46), also on type aliases and module-scope variables (#57)
  • [LinkName("sym")] for externs (#56)
  • Type aliases (#52)
  • Modules: private by default with export (#53), import/export forms (#54), export * from / export [...] from re-exports (#138)
  • Reject C T* pointer syntax outside extern declarations (#59)
  • i16/u16 (short/ushort) (#61)
  • for loops and the iterator protocol (#66)
  • Function types and named function references (#67), closure literals (#93), methods, constructors and generic functions as values (#96), plain vs shared function types (#111), named functions and captureless closures as C callbacks (#113)
  • construct replaces new constructors, with deprecation warnings and fixes (#76)
  • with blocks and the Scoped<T> protocol (#80)
  • Weak references: __weak<T> and Weak<T> (#84)
  • Traits as types, with dynamic dispatch (#88)
  • An extension method needs an import of its file (#91)
  • Module-scope variables must be const and thread-safe (#95)
  • [Deprecated("message")] (#104)
  • Type argument inference, generic methods, iterator map/filter (#105)
  • [Implicit] constructors (#106)
  • Overloading: free functions (#119), methods, static methods and operators (#129), extension methods and trait members (#147), constructors (#150)
  • Each file outside a module is namespaced by its path (#120)
  • A struct may hold a field of its own type (#130)
  • Pepper-style operator methods, indexers and constructor parameters (#131)
  • Character literals 'a' (#132)
  • Semicolons are required; line breaks never end a statement (#136), and a missing ; is an error (#158)
  • Tuples and multiple return values (#140), collections, ==, hashing, labels and nested destructuring (#159), optional and labeled tuples (#160), tuple patterns in match and is (#176)
  • T? for Optional<T> (#141)
  • Unary operator overloads and the truth test !! (#142)
  • Enums: value enums and match (#144), methods, name() and from_value() (#154), cases that carry values (#168), match expressions, is tests and literal patterns (#173)
  • Float arguments convert to integer parameters (#166)
  • main(args: String[]) (#171)
  • Array and map literals (#174)
  • String interpolation $"text {name}" with ToString (#175), expressions in holes (#192), no assignments in holes (#197)
  • Generic constraints: T: Shape & Named checked at every use (#202), constrained bodies checked against their constraints (#203), constrained extensions and conditional conformance (#204), the built-in Shared constraint (#205)
  • Static methods may call sibling statics by bare name (#235)

Runtime and library

  • The runtime is written in Pepper; the C support library is gone (#44)
  • Runtime types renamed to PascalCase: String, Array, HashMap, HashSet (#50); fields and constants follow the naming conventions (#127, #134, #143, #148, #156, #161, #190)
  • Result<TValue, TError=Error> and default generic parameters (#51), later an enum (#177); None (#58); Optional<T> (#133)
  • Atomic<T> and [Link("library")] (#49); Atomic moved into the async module (#200)
  • The io module: File, Directory, Path (#62); TCP and UDP sockets (#165); Unix domain sockets (#198); tasks park on file reads and writes (#191)
  • The async module: Thread, ThreadId, ThreadLocal and CPU counts (#92); Mutex, Condition, Once, Lazy, Channel (#121); copy and Copyable (#135); confinement and Mutex<T> for any struct (#157); move(x), [Move] and the PEP_CHECK_SYNC census (#169); Select<E> and Condition.wait_while (#194); TaskLocal<T> (#208)
  • Tasks: fibers and a scheduler (#178); parking on sockets and async.timeout (#183); I/O backends chosen at run time, IOCP and poll (#184); several workers and async.spawn (#185); run_blocking, stream transfer and per-worker accept (#186); tasks park on Mutex, Condition, Channel and Thread.sleep (#187); an opt-in io_uring backend (#188)
  • Runtime API cleanups: String messages, !==, Result.value, Result<void> (#101)
  • The runtime uses overloads (#162), character literals (#139) and is formatted with pep-fmt (#179)
  • arguments() and exit(code) (#163); text helpers, Array.sort and ordered print output (#164)
  • Format specifications and String.format (#196)
  • A tls module: TLS 1.2/1.3 over TCP (OpenSSL 3, SChannel) (#209)
  • An http module: HTTP/1.1 client and server (#210)
  • Uri: RFC 3986 URI references (#240)

Tooling and LSP

  • Clang-style compiler errors with exact line and column (#64), documented as the standard (#74)
  • The VS Code extension installs from any branch and hot-restarts pepper-lsp (#55)
  • Hover and go-to-definition follow imports (#69); implicit conversions shown in hover and inlay hints (#112); pepper-lsp stays alive (nesting limit, CRLF, closure panics, restarts) (#201); go-to-definition hang fixed (#213) and nested members (#253); hover types inferred locals (#259) and shows parameters in scope and an assignment's left side (#266)
  • pep-fmt, a formatter written in Pepper, and the tools/syntax library (#124); enums, match, optionals and format: off regions (#172); runtime helpers (#181)
  • The Pepper book and INTERNALS.md (#78); docs kept current per PR (#81); naming conventions (#125); agent rules (#47, #170, #189)
  • -T time and deterministic output (#114); speed-ups in sema and parsing (#109, #180, #182, #193)
  • Build cache: one object per unit with unchanged units reused (#137), units keyed by their sources (#153), cached units' bodies skip sema (#167), keys by their inputs' interfaces with early cutoff (#212)

CI and build

  • The VSIX is packaged when GitHub-hosted legs fail (#79)
  • Self-hosted runners for Windows and Linux (#65), macOS (#83), and every workflow, with the VSIX built only on release or dispatch (#146); build output and LLVM reused across runs (#77)
  • Driver integration tests link into one binary (#115) and compile through the real load path (#71); unique temp directories (#90, #123, #126)
  • No CI on pushes to main (#118); incremental compilation off in persistent target dirs (#151); prose-only PRs skip build and test jobs (#155); the LLVM version matrix runs before a release (#206, #211); test threads capped at 16 and cache verification on Linux only (#215); async.run test programs run one at a time (#224); no CI on draft PRs (#258)
  • The vestigial C++ implementation is removed (#48)
  • The version is 0.2.0 (#267)

Fixes

  • return inside nested blocks (#41); ten bugs from edge-case tests (#42); refcount leaks at break/continue and ternary (#45); compiler fixes from the io work (#63)
  • assert(x, __null) segfault (#68); chained indexing through pointer elements (#70); struct returns from specialized extensions (#72); an uncalled override of another file's private generic (#73)
  • Bugs found by the docs audit (#82); Array.Api refcounts and the corpus run (#86); compiler warnings (#89)
  • One scope walker for linking and visibility (#85); each file its own namespace for private names (#87)
  • Pointee type inference for var v = p[i] (#94); struct overrides of generic functions across files (#97); raw pointers as struct references and Strings as pointers rejected (#102)
  • A trait default's bare calls bind only to the trait's methods (#108); calls in a generic struct's methods (#116); string literal bytes to char/void pointer slots (#122)
  • Type-parameter fields zero-initialized with __default<T> (#145); a store of the wrong LLVM type is an internal error (#149)
  • Generic calls in generic extensions and trait-value call results (#199); the JIT's sections stay in one region on Windows (#207)
  • TLS and socket write bugs (#221); string literals in trait default bodies and operators on implicit-this calls (#251); functions with cached bodies usable as values (#256); __default<T>() is typed, so a tuple literal can hold it (#268)