Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 49 additions & 16 deletions docs/bootstrap-inventory.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,11 @@ Regenerate: `php script/bootstrap-inventory.php`

| Metric | Count |
|--------|------:|
| PHP files on vm.php path | 5098 |
| Phase A inventory files (M2 ratio SSOT) | 5098 |
| PHP files on vm.php path | 5102 |
| Phase A inventory files (M2 ratio SSOT) | 5102 |
| Phase A ratio-deferred paths | 0 |
| Source constructs flagged (blockers) | 0 |
| Source constructs flagged (warnings) | 13842 |
| Source constructs flagged (warnings) | 13855 |

## Compiler CFG gaps (`lib/Compiler.php`)

Expand Down Expand Up @@ -535,7 +535,7 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
| `ext/inotify/inotify_init.php` | 0 | 2 |
| `ext/inotify/inotify_read.php` | 0 | 2 |
| `ext/inotify/inotify_rm_watch.php` | 0 | 2 |
| `ext/intl/BuiltinClasses.php` | 0 | 10 |
| `ext/intl/BuiltinClasses.php` | 0 | 14 |
| `ext/intl/CollatorCreate.php` | 0 | 1 |
| `ext/intl/IdnFunction.php` | 0 | 3 |
| `ext/intl/IntlClassMethod.php` | 0 | 3 |
Expand All @@ -546,6 +546,10 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
| `ext/intl/JitGrapheme.php` | 0 | 2 |
| `ext/intl/JitLocaleParser.php` | 0 | 1 |
| `ext/intl/LocaleGetDefault.php` | 0 | 2 |
| `ext/intl/LocaleGetDisplayName.php` | 0 | 3 |
| `ext/intl/LocaleGetPrimaryLanguage.php` | 0 | 2 |
| `ext/intl/LocaleGetRegion.php` | 0 | 2 |
| `ext/intl/LocaleGetScript.php` | 0 | 2 |
| `ext/intl/LocaleParserJitHelper.php` | 0 | 1 |
| `ext/intl/LocaleSetDefault.php` | 0 | 2 |
| `ext/intl/Module.php` | 0 | 26 |
Expand Down Expand Up @@ -8534,14 +8538,18 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag

**Warnings** (review for bootstrap subset):
- new ClassEntry (line 41)
- new ClassEntry (line 55)
- new LocaleGetDefault (line 57)
- new LocaleSetDefault (line 60)
- new ClassEntry (line 68)
- new IntlDateFormatterCreate (line 70)
- new ClassEntry (line 78)
- new CollatorCreate (line 80)
- new ClassEntry (line 88)
- new ClassEntry (line 59)
- new LocaleGetDefault (line 62)
- new LocaleSetDefault (line 63)
- new LocaleGetPrimaryLanguage (line 64)
- new LocaleGetRegion (line 65)
- new LocaleGetScript (line 66)
- new LocaleGetDisplayName (line 67)
- new ClassEntry (line 79)
- new IntlDateFormatterCreate (line 81)
- new ClassEntry (line 89)
- new CollatorCreate (line 91)
- new ClassEntry (line 99)
- 7 class method(s)

### `ext/intl/CollatorCreate.php`
Expand Down Expand Up @@ -8581,9 +8589,9 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
### `ext/intl/IntlExtensionPolicy.php`

**Warnings** (review for bootstrap subset):
- new locale_get_primary_language (line 87)
- new locale_get_region (line 88)
- new locale_get_script (line 89)
- new locale_get_primary_language (line 92)
- new locale_get_region (line 93)
- new locale_get_script (line 94)
- 11 class method(s)

### `ext/intl/JitGrapheme.php`
Expand All @@ -8603,6 +8611,31 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
- new ArgumentCountError (line 21)
- 1 class method(s)

### `ext/intl/LocaleGetDisplayName.php`

**Warnings** (review for bootstrap subset):
- new ArgumentCountError (line 24)
- new ArgumentCountError (line 29)
- 1 class method(s)

### `ext/intl/LocaleGetPrimaryLanguage.php`

**Warnings** (review for bootstrap subset):
- new ArgumentCountError (line 22)
- 1 class method(s)

### `ext/intl/LocaleGetRegion.php`

**Warnings** (review for bootstrap subset):
- new ArgumentCountError (line 22)
- 1 class method(s)

### `ext/intl/LocaleGetScript.php`

**Warnings** (review for bootstrap subset):
- new ArgumentCountError (line 22)
- 1 class method(s)

### `ext/intl/LocaleParserJitHelper.php`

**Warnings** (review for bootstrap subset):
Expand Down Expand Up @@ -8666,7 +8699,7 @@ Rank live CFG gaps across inventory files: `php script/bootstrap-inventory-triag
### `ext/intl/VmLocale.php`

**Warnings** (review for bootstrap subset):
- 12 class method(s)
- 15 class method(s)

### `ext/intl/VmNormalizer.php`

Expand Down
2 changes: 1 addition & 1 deletion docs/capabilities-syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ Tracking issues: [#58](https://github.com/PurHur/php-compiler/issues/58), [#145]
| `new static()` and `: static` return type (late-bound class) | yes | yes | yes | [#3412](https://github.com/PurHur/php-compiler/issues/3412) | VM resolveClassScopeName on TYPE_NEW; returnTypeStatic verify (#3412) |
| Magic constants `__CLASS__`, `__METHOD__`, `__FUNCTION__` | yes | yes | yes | [#199](https://github.com/PurHur/php-compiler/issues/199) | Lowered at parse time via php-cfg MagicStringResolver; compliance PHPT |
| Magic constant `__NAMESPACE__` | yes | yes | yes | [#199](https://github.com/PurHur/php-compiler/issues/199) | Requires `namespace` declaration (#84); compliance PHPT |
| Magic constants `__DIR__`, `__FILE__` | yes | yes | yes | [#707](https://github.com/PurHur/php-compiler/issues/707) | VM script stack on include; JIT uses per-unit script path; compliance PHPT; bootstrap AOT; AOT PHPT |
| Magic constants `__DIR__`, `__FILE__` | yes | yes | yes | [#707](https://github.com/PurHur/php-compiler/issues/707) | VM script stack on include; JIT uses per-unit script path; compliance PHPT; bootstrap AOT |
| Magic constant `__LINE__` | yes | yes | yes | [#715](https://github.com/PurHur/php-compiler/issues/715) | Per-site line on TYPE_SCRIPT_MAGIC; include stack for multi-file units; compliance PHPT |
| Literal `include`/`require` with `__DIR__` | yes | yes | yes | [#475](https://github.com/PurHur/php-compiler/issues/475) | Compile-time inlining via IncludeHelper; two-file PHPT + MiniWebApp JIT gate (#587) |
| foreach by-reference (`&$v`) | yes | yes | yes | [#1222](https://github.com/PurHur/php-compiler/issues/1222) | Packed and string-keyed arrays; VM + JIT/AOT lowering (#1222, #4364); AOT: borrowed hashtable entry refs skip valueDelref (IteratorHelper); AOT PHPT: foreach_by_ref.phpt, foreach_by_ref_assoc.phpt |
Expand Down
5 changes: 5 additions & 0 deletions docs/capabilities.md
Original file line number Diff line number Diff line change
Expand Up @@ -484,6 +484,11 @@ Auto-generated by `script/capability-matrix.php`. Do not edit by hand.
| `levenshtein` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `link` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `linkinfo` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `locale_get_default` | yes | yes | yes | intl | |
| `locale_get_primary_language` | yes | yes | yes | intl | JIT PHPT; AOT PHPT |
| `locale_get_region` | yes | yes | yes | intl | JIT PHPT; AOT PHPT |
| `locale_get_script` | yes | yes | yes | intl | JIT PHPT; AOT PHPT |
| `locale_set_default` | yes | yes | yes | intl | |
| `localeconv` | yes | yes | yes | standard | |
| `localtime` | yes | yes | yes | standard | JIT PHPT; AOT PHPT |
| `log` | yes | yes | yes | standard | AOT PHPT |
Expand Down
7 changes: 6 additions & 1 deletion docs/pages/capability-comparison.html
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ <h1>PHP capability comparison</h1>
</article>
<article>
<div>Stdlib builtins</div>
<strong>986</strong> / 1079 full (VM+JIT+AOT)
<strong>991</strong> / 1084 full (VM+JIT+AOT)
<p style="margin:0.35rem 0 0;font-size:0.88rem;color:var(--text-muted)">68 partial · 25 gaps</p>
</article>
<article>
Expand Down Expand Up @@ -663,6 +663,11 @@ <h2>Stdlib builtins</h2>
<tr data-support="full"><td><code>`levenshtein`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
<tr data-support="full"><td><code>`link`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
<tr data-support="full"><td><code>`linkinfo`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
<tr data-support="full"><td><code>`locale_get_default`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
<tr data-support="full"><td><code>`locale_get_primary_language`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
<tr data-support="full"><td><code>`locale_get_region`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
<tr data-support="full"><td><code>`locale_get_script`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
<tr data-support="full"><td><code>`locale_set_default`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
<tr data-support="full"><td><code>`localeconv`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
<tr data-support="full"><td><code>`localtime`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
<tr data-support="full"><td><code>`log`</code></td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td class="status-yes">yes</td><td>—</td></tr>
Expand Down
29 changes: 20 additions & 9 deletions ext/intl/BuiltinClasses.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
use PHPCompiler\VM\Context;

/**
* Register intl builtin classes (php-src ext/intl/php_intl.c; issue #5774).
* Register intl builtin classes (php-src ext/intl/php_intl.c; issues #5774, #6696).
*
* ICU algorithms land in #3336, #5747, #5201; skeleton classes register only when
* {@see IntlExtensionPolicy::advertisesBuiltins()} (#12115).
* Locale registers when {@see IntlExtensionPolicy::advertisesLocale()}. ICU skeletons
* (Collator / IntlDateFormatter) register only when {@see IntlExtensionPolicy::advertisesBuiltins()} (#12115).
*/
final class BuiltinClasses
{
Expand Down Expand Up @@ -52,14 +52,25 @@ public static function registerNormalizer(Context $ctx): void

private static function registerLocaleClass(Context $ctx): void
{
if (isset($ctx->classes['locale'])) {
return;
}

$entry = new ClassEntry('Locale');
$pubStatic = CfgFunc::FLAG_PUBLIC | CfgFunc::FLAG_STATIC;
$entry->methods['getdefault'] = new LocaleGetDefault();
$entry->methodVisibility['getdefault'] = $pubStatic;
$entry->methodNames['getdefault'] = 'getDefault';
$entry->methods['setdefault'] = new LocaleSetDefault();
$entry->methodVisibility['setdefault'] = $pubStatic;
$entry->methodNames['setdefault'] = 'setDefault';
$methods = [
'getdefault' => [new LocaleGetDefault(), 'getDefault'],
'setdefault' => [new LocaleSetDefault(), 'setDefault'],
'getprimarylanguage' => [new LocaleGetPrimaryLanguage(), 'getPrimaryLanguage'],
'getregion' => [new LocaleGetRegion(), 'getRegion'],
'getscript' => [new LocaleGetScript(), 'getScript'],
'getdisplayname' => [new LocaleGetDisplayName(), 'getDisplayName'],
];
foreach ($methods as $lc => [$handler, $name]) {
$entry->methods[$lc] = $handler;
$entry->methodVisibility[$lc] = $pubStatic;
$entry->methodNames[$lc] = $name;
}
$ctx->classes['locale'] = $entry;
}

Expand Down
17 changes: 11 additions & 6 deletions ext/intl/IntlExtensionPolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,22 @@
/**
* ext/intl builtin advertisement — php-src ext/intl/php_intl.c module registration (#11768, #11825).
*
* Grapheme helpers and intl_* functions require a loaded intl extension on Zend; partial
* PHP implementations stay compiled in-tree but are withheld from function_exists() and
* intl OOP class_exists() until {@see ModuleRegistry::extensionLoaded}('intl') is true
* (full ext/intl parity, #11472).
* Grapheme helpers and intl_* error functions require a loaded intl extension on Zend; they stay
* withheld from function_exists()/class_exists() until {@see ModuleRegistry::extensionLoaded}('intl')
* (#11472, #17694). Locale + Normalizer are partial surfaces that advertise without loading intl
* (#6696, #5153).
*/
final class IntlExtensionPolicy
{
/** locale_get_default()/Locale — php-src registers only with loaded ext/intl (#9576, #16214). */
/**
* locale_get_default()/Locale — partial PHP surface without extension_loaded('intl') (#6696, #9576).
*
* Mirrors {@see advertisesNormalizer()}: BCP-47 default/parser OOP is available while grapheme_*
* and full ICU classes stay gated on loaded ext/intl (#16214/#11472/#17694).
*/
public static function advertisesLocale(): bool
{
return ModuleRegistry::extensionLoaded('intl');
return true;
}

/**
Expand Down
62 changes: 62 additions & 0 deletions ext/intl/LocaleGetDisplayName.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\ext\intl;

use PHPCompiler\ext\standard\VmString;
use PHPCompiler\Frame;
use PHPCompiler\VM\Builtin\VmClassMethod;
use PHPCompiler\VM\Variable;

/** Locale::getDisplayName() — OOP wrapper for {@see VmLocale::getDisplayName()} (#6696). */
final class LocaleGetDisplayName extends VmClassMethod
{
public function __construct()
{
parent::__construct('getDisplayName');
}

public function execute(Frame $frame): void
{
$argc = \count($frame->calledArgs);
if ($argc < 1) {
throw new \ArgumentCountError(
'Locale::getDisplayName() expects at least 1 argument, '.$argc.' given'
);
}
if ($argc > 2) {
throw new \ArgumentCountError(
'Locale::getDisplayName() expects at most 2 arguments, '.$argc.' given'
);
}
$locale = VmString::coerceStringBuiltinArg(
$frame->calledArgs[0],
'Locale::getDisplayName',
0,
'locale'
);
$displayLocale = null;
if (isset($frame->calledArgs[1])) {
$displayArg = $frame->calledArgs[1]->resolveIndirect();
if (Variable::TYPE_NULL !== $displayArg->type) {
$displayLocale = VmString::coerceStringBuiltinArg(
$frame->calledArgs[1],
'Locale::getDisplayName',
1,
'displayLocale'
);
}
}
if (null === $frame->returnVar) {
return;
}
$name = VmLocale::getDisplayName($locale, $displayLocale);
if (false === $name) {
$frame->returnVar->bool(false);

return;
}
$frame->returnVar->string($name);
}
}
36 changes: 36 additions & 0 deletions ext/intl/LocaleGetPrimaryLanguage.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\ext\intl;

use PHPCompiler\ext\standard\VmString;
use PHPCompiler\Frame;
use PHPCompiler\VM\Builtin\VmClassMethod;

/** Locale::getPrimaryLanguage() — OOP wrapper for {@see VmLocale::getPrimaryLanguage()} (#6696). */
final class LocaleGetPrimaryLanguage extends VmClassMethod
{
public function __construct()
{
parent::__construct('getPrimaryLanguage');
}

public function execute(Frame $frame): void
{
if (1 !== \count($frame->calledArgs)) {
throw new \ArgumentCountError(
'Locale::getPrimaryLanguage() expects exactly 1 argument, '.\count($frame->calledArgs).' given'
);
}
$locale = VmString::coerceStringBuiltinArg(
$frame->calledArgs[0],
'Locale::getPrimaryLanguage',
0,
'locale'
);
if (null !== $frame->returnVar) {
$frame->returnVar->string(VmLocale::getPrimaryLanguage($locale));
}
}
}
36 changes: 36 additions & 0 deletions ext/intl/LocaleGetRegion.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace PHPCompiler\ext\intl;

use PHPCompiler\ext\standard\VmString;
use PHPCompiler\Frame;
use PHPCompiler\VM\Builtin\VmClassMethod;

/** Locale::getRegion() — OOP wrapper for {@see VmLocale::getRegion()} (#6696). */
final class LocaleGetRegion extends VmClassMethod
{
public function __construct()
{
parent::__construct('getRegion');
}

public function execute(Frame $frame): void
{
if (1 !== \count($frame->calledArgs)) {
throw new \ArgumentCountError(
'Locale::getRegion() expects exactly 1 argument, '.\count($frame->calledArgs).' given'
);
}
$locale = VmString::coerceStringBuiltinArg(
$frame->calledArgs[0],
'Locale::getRegion',
0,
'locale'
);
if (null !== $frame->returnVar) {
$frame->returnVar->string(VmLocale::getRegion($locale));
}
}
}
Loading
Loading