Inspiration: Ruby · Layer: front-end only (lexer + parser) · Commit:
e2dfce0
unless is sugar for a negated if. It runs its body when the condition is
false. Three forms are supported:
unless ($user->isBanned()) { // block form
echo "welcome";
}
unless ($cache->has($key)) { // with else
$value = compute();
} else {
$value = $cache->get($key);
}
print "saved\n" unless $dryRun; // statement modifierunless (C) { S } is exactly equivalent to if (!C) { S }.
It's the simplest possible language change — no new types, no runtime, no engine
work — which made it the ideal warm-up for wiring up the whole build/patch/test
loop. It also reads well for guard-style early conditions where if (!…) is noisy.
Entirely in the front-end; the compiler and runtime never learn about it.
- Lexer (
Zend/zend_language_scanner.l): a new keyword tokenT_UNLESS. - Parser (
Zend/zend_language_parser.y): theunlessrules desugar to the same AST thatifproduces —ZEND_AST_IF/ZEND_AST_IF_ELEM— with the condition wrapped in a boolean-NOT node (!C). Because it lowers to the existingifAST, there is zero new compiler or opcode surface.
unless is semi-reserved: it's added to reserved_non_modifiers, so it
remains usable as a method or constant name ($obj->unless()), preserving
backward compatibility.
- None of note — it desugars to
if, so semantics, scoping, and short-circuiting are identical.
smoke.sh— smoke tests (block, else, modifier, semi-reserved usage)tests/unless.phpt,tests/unless_comprehensive.phpt— in-tree regression tests