Problem
#57 tracks try/catch/finally lowering, but throw and built-in Exception are not usable in app code today. Web apps need throwable errors for validation and HTTP error paths (complements #152 serve 500 mapping).
MiniWebApp contact validation and API error responses will eventually need throw new Exception(...) instead of ad-hoc echo + exit.
Goal
throw new Exception('Invalid input');
works in VM; catchable when #57 lands.
Implementation hints
| Layer |
Files |
Notes |
| Compiler |
lib/Compiler.php |
Lower PHPCfg\Op\Expr\Throw_ to opcode(s); unwind to nearest catch or top |
| VM |
lib/VM.php |
Stack unwind; minimal trace; pair with #152 bin/serve.php |
| Objects |
lib/ class table |
Builtin Exception (message, code, file, line) — needs #58 object model |
| JIT |
lib/JIT.php |
Defer: VM fallback via PHP_COMPILER_JIT_FALLBACK until stable |
| AOT |
lib/AOT/ |
Same as JIT or stub with link-time message |
| Serve |
lib/Web/ |
Uncaught → HTTP 500; PHP_COMPILER_DEBUG=1 body (#152 ✅) |
| Tests |
test/compliance/cases/exception_throw_*.phpt |
caught vs uncaught |
Suggested PHPT cases
throw inside function, caught in caller → continues with expected output
- Uncaught in CLI → non-zero exit / stderr
- Uncaught in
phpc serve → 500 generic body
Tasks
Acceptance criteria
./phpc run -r 'try { throw new Exception("x"); } catch (Exception $e) { echo $e->getMessage(); }'
# → x
./script/ci-fast.sh --filter exception_throw
Caught exception returns 200 with body in serve; uncaught returns 500 (with PHP_COMPILER_DEBUG).
Dependencies
Not blocking north-star MiniWebApp AOT execute (#764) — Phase 1 Language polish.
Verification
Local/Docker — ./script/ci-fast.sh for VM; @group llvm optional later.
Links
Problem
#57 tracks try/catch/finally lowering, but
throwand built-inExceptionare not usable in app code today. Web apps need throwable errors for validation and HTTP error paths (complements #152 serve 500 mapping).MiniWebApp contact validation and API error responses will eventually need
throw new Exception(...)instead of ad-hocecho+exit.Goal
works in VM; catchable when #57 lands.
Implementation hints
lib/Compiler.phpPHPCfg\Op\Expr\Throw_to opcode(s); unwind to nearest catch or toplib/VM.phpbin/serve.phplib/class tableException(message, code, file, line) — needs #58 object modellib/JIT.phpPHP_COMPILER_JIT_FALLBACKuntil stablelib/AOT/lib/Web/PHP_COMPILER_DEBUG=1body (#152 ✅)test/compliance/cases/exception_throw_*.phptSuggested PHPT cases
throwinside function, caught in caller → continues with expected outputphpc serve→ 500 generic bodyTasks
PHPCfg\Op\Expr\Throw_inlib/Compiler.phpExceptionclass (message, code, file, line)bin/serve.phpHTTP 500Acceptance criteria
Caught exception returns 200 with body in serve; uncaught returns 500 (with
PHP_COMPILER_DEBUG).Dependencies
Exception::getMessage)Not blocking north-star MiniWebApp AOT execute (#764) — Phase 1 Language polish.
Verification
Local/Docker —
./script/ci-fast.shfor VM;@group llvmoptional later.Links