Release: 0.37 - Type Inference
0.37.0 - Type Inference
Released 2026-05-12 · GitHub release
Type tags + tag inference + 3.66x recursion speedup + agent-install workflow + .phel/ consolidation.
🎉 Added
Core
defnmetadata:^:memoize,^{:memoize-lru N}wrap body inmemoize/memoize-lru(#1915);^:asyncwraps inasyncreturningAmp\Future(#1924)
Compiler
:tagmetadata emits PHP type declarations; reader shorthands^int,^"?int",^"\\Foo\\Bar",^{:tag "..."}(#1916)- Tag inference: return types from tail primitive ops and tail calls to tagged globals / pure PHP built-ins (#1932, #1941); param types from primitive body uses (#1944); inferred tags persist in def meta and graft onto compiled PHP signatures for single-arity
defn(#1941, #1949) - Static checker reports
:tagmismatches at compile time (#1933) php/Foo.Bar/bazandphp/Foo.Bar.bazaccepted as backslash-free aliases forphp/Foo\Bar\baz(#1952)composer bench-jit-baseline/bench-jit-tracingfor typed-vs-untyped JIT kernels (#1931)
Profile
phel profile <path>: per-fn timings and compile-phase costs (--format,--output)
Test
- Unified diff on
(is (= a b))collection failures phel test --repeat=N,--seed=<int>,--random-order
REPL
- Eval-error rendering: headline, optional hint, trace with internal frames hidden
⚖️ Changed
Compiler
- Recursive self-calls emit
$this(...): ~3.66x faster (#1914)
DX
phel agent-installstamps installed skill files with<!-- phel-agents vX.Y.Z -->fromVERSION; idempotent on re-install- Slimmer Claude skill (89 → 36 lines); shared syntax cheatsheet moved to
resources/agents/quick-syntax.md; aider/codex/gemini/copilot/cursor pointers unified phel agent-install --checkreports installed vs current skill version per platform; exits 1 on driftphel agent-install --listenumerates platforms, source templates, install targets, and current statephel agent-install --uninstallremoves skill file(s) and restores.pre-phel.bakif present;--with-docsalso drops.agents/phel agent-install --autoinstalls skills only for agents already used in the project (detects.claude/,.cursor/,AGENTS.md,GEMINI.md, etc.)phel doctornow reports installed agent skills and surfaces stale versions in one place- New agent task recipes:
tasks/async.md,tasks/memoize.md,tasks/write-macros.md; common-gotchas trimmed to non-duplicative items; module table cross-links to tasks - Runtime state (cache, REPL history, error log) consolidated under
.phel/; relocate viawithPhelDir()orPHEL_DIRenv (#1954) - Module boundary tightening:
Munge,CompileOptions,PhelProjectDirectory,VersionFindermoved toPhel\Shared;GlobalEnvironment,DebugLineTapexposed viaCompilerFacade(#1963, #1964) PhelConfigimmutable viawithX()chain; build/export fields flat on root; oldsetX()shims deprecated- Breaking:
PhelConfig::forProject(ProjectLayout $layout = Flat, string $mainNamespace = ''): layout first, Flat default - Breaking: Cross-module exceptions +
CodeSnippetmoved fromPhel\Compiler\Domain\Exceptions/Phel\Compiler\Domain\Evaluator\Exceptions/Phel\Compiler\Domain\Parser\ReadModeltoPhel\Shared\Exceptions/Phel\Shared\Parser\ReadModel(#1975) - Breaking:
Phel\Printermoved toPhel\Shared\Printer. Phel sources should now(:use Phel.Shared.Printer.Printer); old path no longer resolves - Upgrade note: clear compiled caches after upgrading (
./vendor/bin/phel cache:clear, or delete.phel/cache/). Cached PHP from earlier installs references the old FQNs and will fail to load otherwise. Both Phel sources and compiled fixtures in this repo are regenerated; downstream projects must rebuild theirs.
🐛 Fixed
Compiler
- Return-type inference skips loops whose
recurrebinds to a different/unknown type
Core
memoize/memoize-lruretain entries from recursive calls within a single invocation (#1915)
Test
- Default reporter wraps dot output at 80 columns under
with-output-buffer
Api
phel analyzepreloads namespaces required by the analyzed file (#1919)
Nrepl
lookup/info/eldocresolve session-defineddefns, honoring requestnsparam or session namespace (#1963)
Build
- Entry-point
main.phprequire_onceresolves dotted main namespaces to nested paths (#1956) PhpNamespaceCacheevicts always-excluded segments at load time; policy changes take effect without manual cache wipe (#1962)
Run
phel run <file>resolves(:require ...)from configuredsrcDirs/vendor first; sibling files resolve only as name-matched fallback (#1962)- REPL
startup.phellives atresources/repl/startup.phel, outside defaultsrcDirs(#1962)
👥 Contributors
Full Changelog: v0.36.0...v0.37.0
Downloads
v0.37.0
- phel.phar (1.44 MB)