Summary
exit program — the form given in the keyword reference — does not parse. Bare exit parses but is a no-op at top level: the program keeps running and exits 0. Neither spelling produces the documented "exit program" behaviour.
Reproduction
Documented form:
display "before"
exit program
display "after"
Bare form:
display "before"
exit
display "after"
Command:
wfl d2_exit_program.wfl
wfl d2_exit_bare_noop.wfl
Expected
Both should print before and stop. Docs/reference/reserved-keywords.md:610
lists exit under Control Flow with the usage column reading exit program,
and Docs/reference/keyword-reference.md:32 describes it as
| exit | Exit program/loop | ✗ |.
Actual
exit program:
error[ANALYZE-SEMANTIC]: Variable 'program' is not defined
Exit code: 3. (program is parsed as an operand, not part of the statement.)
Bare exit:
Exit code: 0 — the statement is accepted and does nothing.
Inside a loop, bare exit behaves like break (leaves the innermost loop and
continues afterwards); that part is coherent, but it is the loop half of the
documented "Exit program/loop" and the program half has no working spelling.
The statement exists in the AST and is executed as a control-flow signal:
// src/parser/ast.rs:232
ExitStatement { line: usize, column: usize },
// src/interpreter/mod.rs:7842-7846
Statement::ExitStatement { .. } => {
Ok((Value::Null, ControlFlow::Exit))
}
ControlFlow::Exit is honoured by the loop drivers but not at program top level,
so the documented program-termination behaviour is unreachable.
Environment
- wfl --version:
WebFirst Language (WFL) version 26.8.4
- binary: system install
C:\Program Files\wfl\bin\wfl.exe
- commit: c277d8f
- OS: Windows 11 Pro 10.0.26200
- build: release
Also reproduces on the repo build (26.8.2) — not a regression.
No .wflcfg in scope.
Context
Found while porting G:/repos/JShrink/src/JShrink/Minifier.php (a 738-line PHP
JavaScript minifier) to WFL. The port's CLI needs an early exit on a missing
argument, which is what sent us to exit.
This was encountered, not blocking — the port instead prints a usage line and
forces a nonzero status (see the companion issue on raising a fatal error with a
custom message). No stub was left.
Either half is a valid fix and they are independent: make exit program parse and
terminate with status 0, or make bare exit terminate at top level — but the two
reference pages should agree with whichever ships, since today they document a form
that errors and a form that silently does nothing.
Summary
exit program— the form given in the keyword reference — does not parse. Bareexitparses but is a no-op at top level: the program keeps running and exits 0. Neither spelling produces the documented "exit program" behaviour.Reproduction
Documented form:
Bare form:
Command:
Expected
Both should print
beforeand stop.Docs/reference/reserved-keywords.md:610lists
exitunder Control Flow with the usage column readingexit program,and
Docs/reference/keyword-reference.md:32describes it as|exit| Exit program/loop | ✗ |.Actual
exit program:Exit code: 3. (
programis parsed as an operand, not part of the statement.)Bare
exit:Exit code: 0 — the statement is accepted and does nothing.
Inside a loop, bare
exitbehaves likebreak(leaves the innermost loop andcontinues afterwards); that part is coherent, but it is the loop half of the
documented "Exit program/loop" and the program half has no working spelling.
The statement exists in the AST and is executed as a control-flow signal:
ControlFlow::Exitis honoured by the loop drivers but not at program top level,so the documented program-termination behaviour is unreachable.
Environment
WebFirst Language (WFL) version 26.8.4C:\Program Files\wfl\bin\wfl.exeAlso reproduces on the repo build (26.8.2) — not a regression.
No
.wflcfgin scope.Context
Found while porting
G:/repos/JShrink/src/JShrink/Minifier.php(a 738-line PHPJavaScript minifier) to WFL. The port's CLI needs an early exit on a missing
argument, which is what sent us to
exit.This was encountered, not blocking — the port instead prints a usage line and
forces a nonzero status (see the companion issue on raising a fatal error with a
custom message). No stub was left.
Either half is a valid fix and they are independent: make
exit programparse andterminate with status 0, or make bare
exitterminate at top level — but the tworeference pages should agree with whichever ships, since today they document a form
that errors and a form that silently does nothing.