- Implement Android platform class with API level detection and compiler configuration
- Add Android-specific library linking with proper archive grouping and system libraries
- Integrate Android target detection and SDK directory resolution in build configuration
- Add Android-specific compile flags including static libstdc++ and security hardening
- Include Android platform support in translator and compiler base classes
- Add PHPX_ANDROID=1 define flag for Android builds
- Support
- Add five new reference types (INT_REF, STR_REF, FLOAT_REF, BOOL_REF, ARRAY_REF)
- Create typed reference ABI using C++ references for strict type safety
- Implement RefWrap<T> bridge for dynamic PHP reference compatibility
- Add getRawVarType() and update getVarType() to handle reference unwrapping
- Enforce strict typing rules preventing fixed storage corruption via references
- Support typed property and array element reference handling
- Implement exception-safe reference binding with proper
- Replace any() with std::any() in test files and compiler logic
- Replace refval() with std::ref() for reference wrapping operations
- Replace expected() with std::expected() for branch prediction hints
- Replace unexpected() with std::unexpected() for branch prediction hints
- Remove deprecated objval() function and use toObject() keyword method
- Update parser to recognize std:: class expressions with case insensitivity
- Add comprehensive changelog documenting breaking API changes
- Update documentation to reflect new std:: namespace conventions
- Add tests for case-insensitive std class and method names
- Verify global function names remain available for user-defined functions
- Add function call cache infrastructure with typephp_call_cached wrapper
- Implement method call caching using typephp_call_method_cached for named methods
- Add scoped method call caching via typephp_call_method_scoped_cached for dynamic scopes
- Create late-static-bound class entry tracking with getCalledCeExpr and getCalledClassExpr
- Implement lazy static property slot resolution with typephp_get_static_property_cached
- Add benchmark cases for dynamic static method calls and scoped method invocations
- Update call cache test expectations to reflect new cached call implementations
- Integrate call caching into function and method call compilation paths
- Add nullsafe method call caching support in nullsafe access trait
- Implement static property slot registration and resolution mechanisms
- Update native property handling to use cached static property access
- Add comprehensive test coverage for various dynamic call scenarios
- Implement exact-class fast path for zero-argument late-static calls with fallback mechanism
- Add static property fetch resolution using typephp_get_static_property symbol
- Enhance isset operations on static array properties with direct typephp_array_isset calls
- Update class reference detection to return Type::STR for class constant fetch expressions
- Add benchmark suite for static cache performance measurement including late static dispatch
- Modify compiler symbols to use typephp variants for called class and static property access
- Create comprehensive tests for static array single offset presence and late static call exact guards
- Update unit tests to reflect new symbol names and variable
- Add fullStatic property to CompilerBase for --full-static flag
- Register --full-static option in Constants with description
- Implement getFullStaticSdkDir method to resolve SDK path
- Modify getIncludePaths to use SDK headers when full static enabled
- Update getLibraryPaths to use
The >=16-significant-digit float-literal-to-php::Decimal promotion
(docs/en/HIGH_PRECISION_TYPES.md) counted every digit in the raw
literal with preg_replace('/[^0-9]/'), so exponent digits and trailing
zeros counted as significant: 1.23456789012345e300 (15 significant
digits) and 999999999999999.0 became Decimal, making
is_float(2.220446049250313E-16) compile to false. Hex literals whose
digits contain E (0x123456789E1234567) matched the [.eE] test and
became Decimal("0x..."), where Zend folds an overflowing hex literal
to its exact double.
Three fixes, keeping the documented feature:
- Count true mantissa significant digits (strip sign, exponent,
leading and trailing zeros) and additionally require that the double
cannot reproduce the literal exactly - a literal that round-trips
(every var_export/serialize output, PHP_FLOAT_EPSILON) has lost
nothing and stays float, while 3.14159265358979323846 still promotes.
- Exclude hex/octal/binary notation from the reclassification.
- When a Decimal-classified literal meets a float-typed expression in
a binary op or comparison, demote the literal to its exact double
instead of the "Cannot convert float expression to Decimal" fatal:
PHP evaluates every float literal as a double, so
0.1 + 0.2 == 0.30000000000000004 is valid PHP and must be true.
The classMethodOverride registration in prepareClassMethod() depends on
file preprocessing order. With a "sandwich" order (ancestor first, leaf
second, intermediate class last), the ancestor method's override flag is
missed: the upward marking cannot cross the not-yet-registered
intermediate class, and the downward subclass lookup ran before the leaf
was prepared. findNativeMethod() then devirtualizes the late-bound call
into a direct native call, silently ignoring the override. In Hyperf this
turns SoftDeletes::delete() into a physical DELETE.
Finalize the flags once the complete class graph is known:
finalizeMethodOverrideFlags() walks every declared method's complete
parent chain and marks each existing ancestor method of the same name as
overridden (method count x inheritance depth). It runs from
Translator::convertFile() next to finalizeDeclarationExpressions(), so
both the project pipeline and the public prepareFile()/convertFile() API
share the same pre-conversion finalization, guarded by a dirty/finalized
flag reset in prepareFile().
Tests:
- tests/compiler/devirtualize/override-order-sandwich.phpt (fails on
master with "base", passes with "leaf")
- tests/compiler/devirtualize/override-order-normal.phpt (control)
- phpunit/src/DevirtualizeOrderTest.php driving the public
prepareFile()/convertFile() API in both orders, asserting the
generated Base::delete() body dispatches dynamically
Consolidate float-to-C++ literal generation into Utils::genFloatLiteral().
Previously:
- genCValue() stringified floats directly via (string), emitting 'INF', '-INF', 'NAN', or losing the floating-point decimal point for whole numbers like 1.0 -> '1'.
- BinaryOpTrait::genFloatLiteral() used sprintf('%.17g') without handling INF or NAN.
Now all float code generation paths delegate to Utils::genFloatLiteral(), mapping INF/-INF/NAN to std::numeric_limits<double> and ensuring whole numbers retain .0.
The flag checks that translate `break N` / `continue N` were emitted only
at the end of each enclosing loop body. After the inner construct exited
with the countdown flag set, every trailing statement of the enclosing
body still executed before the check ran:
foreach ([1] as $x) {
foreach ([1] as $y) { break 2; }
echo "leaked"; // ran in compiled output, not in PHP
}
The native (int-typed) switch path was worse: its check sat inside the
do-while(0) wrapper, decrementing the flag a second time for the switch
level the C++ `break` had already exited. A `break 2` from a native
switch inside a loop therefore never exited the loop at all.
Emit the propagation check immediately after every nested loop / switch
statement instead, from the statement dispatcher, and drop the dead
end-of-body emissions. The check now also distinguishes the enclosing
construct: when it sits inside a switch, a continue that lands on the
switch level lowers to `break`, matching PHP's continue-targets-switch
semantics.
parseBreak/parseContinue now reject levels exceeding the number of
enclosing breakable constructs - the same compile-time validation PHP
performs (`Cannot 'break' 2 levels`) - which the countdown scheme
relies on to terminate at an enclosing construct.
The continue-2-while scenario in break-continue-level.phpt encoded the
old leaked behavior: its `$i++` after the inner loop only ran because of
the misplaced check; standard PHP loops forever on it. The counter now
advances before the inner loop.
The flag checks that translate `break N` / `continue N` were emitted only
at the end of each enclosing loop body. After the inner construct exited
with the countdown flag set, every trailing statement of the enclosing
body still executed before the check ran:
foreach ([1] as $x) {
foreach ([1] as $y) { break 2; }
echo "leaked"; // ran in compiled output, not in PHP
}
The native (int-typed) switch path was worse: its check sat inside the
do-while(0) wrapper, decrementing the flag a second time for the switch
level the C++ `break` had already exited. A `break 2` from a native
switch inside a loop therefore never exited the loop at all.
Emit the propagation check immediately after every nested loop / switch
statement instead, from the statement dispatcher, and drop the dead
end-of-body emissions. The check now also distinguishes the enclosing
construct: when it sits inside a switch, a continue that lands on the
switch level lowers to `break`, matching PHP's continue-targets-switch
semantics.
parseBreak/parseContinue now reject levels exceeding the number of
enclosing breakable constructs - the same compile-time validation PHP
performs (`Cannot 'break' 2 levels`) - which the countdown scheme
relies on to terminate at an enclosing construct.
The continue-2-while scenario in break-continue-level.phpt encoded the
old leaked behavior: its `$i++` after the inner loop only ran because of
the misplaced check; standard PHP loops forever on it. The counter now
advances before the inner loop.
- Add useImportAliases property to track import aliases by type domain
- Implement registerUseImportAlias method with duplicate detection logic
- Update use declaration processing to utilize import alias registration
- Make class and function aliases case-insensitive while constants remain case-sensitive
- Add comprehensive test coverage for import alias domain isolation
- Include negative test cases for duplicate alias detection across domains
- Move AST name resolution earlier in preprocessing steps
- Add proper error handling for PHP parser errors during traversal
- Implement clone-with functionality with one/two argument support
- Add preservation of evaluation order for clone-with operations
- Support dynamic, numeric and object-valued properties in clone-with
- Handle error cases and stop property updates at first error
- Reject active references and unwrap sole remaining references
- Respect property scope and unlock readonly properties during cloning
- Add first-class callable and string callable support for clone
- Preserve lexical class scope in Zend call frames for method calls
- Update documentation with clone-with compatibility requirements
- Add comprehensive test coverage for clone-with features
- Implement scope argument handling in runtime function calls
- Add support for __NAMESPACE__ magic constant resolution in namespace, class, and global scopes
- Add support for __PROPERTY__ magic constant that resolves to property name within property context
- Implement namespace\name relative name resolution for functions, constants, classes, and members
- Update AnonClassGenerator to properly parse identifiers instead of using toString()
- Extend CompilerBase to handle Scalar_MagicConst_Namespace and Scalar_MagicConst_Property
- Modify class inheritance and interface implementation to use parseIdentifier for proper name resolution
- Add comprehensive tests for namespace magic constant behavior across different scopes
- Add tests for property magic constant resolving correctly in property contexts only
- Implement runtime attribute factory lowering with proper namespace context handling
- Update visitor pattern to track property magic boundaries and namespace context correctly
- Document incompatibility with PHP 8.5 #[NoDiscard]
- Removed isConstFetch and isAssignOp methods from AstNodeType
- Removed corresponding test cases for isConstFetch and isAssignOp
- Updated CallArgumentGenerator to use setValue and appendValue instead of set and append
- Removed parseNamedCallArgs method from CallArgumentGenerator
- Removed unused getPlatformFullLinkFlags method from Clang backend
- Updated ClosureGenerator to use appendValue instead of append
- Removed abstract compileFile and linkObjects methods from CompilerBackend
- Removed unused getObjectPropVarInfo and getDecimalLiteralString methods
- Removed resetReturnType and mustNoCall methods from CompilerBase
- Removed testParseIncludesUsesNewArchitecture, testParseLdflagsUsesNewArchitecture,
testParseLibsUsesNewArchitecture and testBackwardCompatibility methods
- Removed isUniversalCtags property and related logic from Extractor
- Removed extractWithMetadata, generateStatistics and exportToMarkdown methods from Extractor
- Removed extractMetadata, extractComments, isPHPFunction and parseDocTags methods from Extractor
- Removed FINAL_TEST_SUCCESS.md file containing old test results
- Replace reinterpret_cast<void **> with direct reference operator &
- Remove unnecessary casting for local variable slot registration
- Maintain same functionality while improving code clarity
docs(runtime): add comprehensive runtime lifecycle documentation
- Create detailed RUNTIME_LIFECYCLE.html explaining four-layer architecture
- Document different modes: ext, bin, lib, and WASM with their lifecycle flows
- Add visual flowcharts showing initialization and shutdown sequences
- Include troubleshooting section with shutdown order constraints
- Add naming conventions and maintenance rules for lifecycle management
test(array): add null key append behavior test case
- Create test for null array key appending behavior
- Verify boolean keys convert to integer indexes properly
- Document expected output for null and boolean key handling
- Replace php_get_class with get_class throughout the codebase
- Replace php_get_persistent_class with get_persistent_class
- Replace php_get_func with get_func and update related helpers
- Replace php_get_persistent_method with get_persistent_method
- Replace php_get_persistent_prop with get_persistent_prop
- Replace php_globals_array with php::globalsArray
- Replace php_deindirect with php::deindirect
- Replace php_get_called_ce with php::getCalledCe
- Replace php_get_callable_scope with php::getCallableScope
- Replace php_get_str with get_str for literal string access
- Update build script to handle TypePHP project module accessor
- Add test case for helper symbol collision prevention
- Modify module initialization from app_init/app_clean to module_init/module_clean
- Introduce $allowLocalClassEntryHoisting flag to control class entry hoisting behavior
- Add withoutLocalClassEntryHoisting method to temporarily disable hoisting during callback execution
- Modify getLocalClassEntryPtr to respect hoisting allowance when checking process stable class
- Wrap parameter default parsing in withoutLocalClassEntryHoisting to prevent unwanted hoisting
- Update array initialization in Preprocessor to use hoisting control for literal arrays
- Add support for new expressions in array parameter defaults with proper class resolution
- Include tests for array parameter defaults containing new expressions
- Add tests for runtime array property defaults with copy-on-write behavior
- Rename generated request array default symbols with 'typephp_' prefix for consistency
- Update documentation to reflect implemented optimizations and remaining costs
- Add optimized array write operations that preserve references and avoid temporaries
- Implement direct array append and item assignment for known array types
- Optimize compound assignment operations like += for known array slots
- Add compile-time expansion for $this::CONST class constant fetches
- Cache process-stable class entry pointers at function level to avoid repeated lookups
- Optimize string concatenation with two scalar operands using efficient overload
- Skip unnecessary type conversions for arguments that already have exact types
- Add comprehensive test coverage for optimized array operations and object creation
- Implement lazy initialization of request-scoped array default templates
- Generate efficient
- Change temporary variable type to Variant for PHP arrays to prevent undefined C++ behavior
- Add methodNameToStr helper that treats 'self' and 'static' as ordinary member names
- Replace identifierToStr with methodNameToStr for method calls to respect lexical rules
- Update nullsafe access trait to use proper method name parsing
- Add test case for array element compound arithmetic overflow handling
- Add test case for nullsafe chain preserving typed method returns