- Implemented parseNestedArrayUnset method to handle chained array dimension unsets
- Added logic to process nested ArrayDimFetch expressions in unset statements
- Created proper dimension parsing and code generation for nested array operations
- Maintained PHP evaluation order for key materialization in nested unsets
- Added comprehensive test coverage for nested unset chain behavior
- Extended compiler tests to verify correct handling of complex unset scenarios
- Introduce StdVector, StdMap, and StdOrderedMap parameter attributes
- Add explicit std-container contract to ArgInfo entity
- Implement parameter validation and type checking logic
- Add error handling for invalid container parameter usage
- Support container parameter contracts in function signatures
- Generate automatic type conversion at function entry points
- Add compilation tests for std container parameter contracts
- Update documentation with container parameter rules and examples
- Implement compatibility checks between child and parent classes
- Add support for container parameters in trait methods and inheritance
- Removed redundant zval macro handling for property access
- Replaced Z_LVAL_P and Z_DVAL_P calls with direct attribute accessors
- Updated property getter logic to use attrInt and attrFloat methods
- Modified tests to match new property access pattern
- Added comprehensive test case for inherited property reference handling
- Update swoole/phpx from ~2.7.0 to ~2.8.0 in composer.json
- Add proper button styling for macOS 11+ with automatic button styles
- Fix control nil check in macos_bridge.mm to prevent crashes
- Use title property for NSButton updates on macOS to handle system-style buttons
- Refactor unset handling in PropertyAccessTrait to use type-specific defaults
- Replace hardcoded default values with Type::getDefaultValueExpression calls
- Add
- Replace ArgList with VarList for fixed argument arrays to avoid dynamic Args allocation
- Add call argument limit assertion to prevent unbounded call generation
- Implement direct static method calls using callStaticMethod when possible
- Add alternating dynamic static call benchmarks for class and method variations
- Update documentation on request-local call slot destruction requirements
- Fix dynamic static call target evaluation order to precede argument evaluation
- Add tests for call argument limits and dynamic class evaluation ordering
- 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
* fix(gen_stub): register enum-case class constants as persistent AST constants
A class constant valued by an enum case was registered with the folded
scalar (the backing value, or the case name for pure cases), so
constant('K::CB'), $cls::CB and reflection observed an int/string where
PHP has the case object, and K::CB === E::B was false on every dynamic
path. Enum case objects have request lifetime and can never sit in the
persistent class-entry tables, in any request-init rebinding scheme
least of all: writing a request-owned object into the shared table is
unsafe under concurrent ZTS requests.
Reuse the engine's own mechanism for internal enums instead: the
constant is declared as a persistent IS_CONSTANT_AST holding the
Enum::Case fetch, so Zend separates the class constants table into
request-local mutable storage on first access, evaluates the fetch
there, and cleans it up at request shutdown. Identity is preserved for
static access, constant(), dynamic class access and reflection, with no
module-lifecycle hooks and no registration-order sensitivity.
Case identity flows through compile-time constant evaluation as an
EnumCaseRef value instead of a scalar, so it also survives constant
expressions (true ? E::A : E::B), constant chains, typed class
constants (declared type and AST value are registered together), and
internal enum cases such as RoundingMode::HalfEven, which previously
aborted stub generation. The runtime expression path (php::getEnumCase)
is unchanged.
The preprocessor also no longer reads the raw ->value property off
arbitrary case expressions (`case A = 1 + 1;` warned and was recorded
as a pure case): only literal backing values are recorded eagerly, and
no compile-time consumer needs the evaluated scalar - gen_stub
evaluates the registration value from the AST itself.
* fix(gen_stub): constrain enum-case AST registration to class constants
The persistent IS_CONSTANT_AST representation leaked into property and
parameter defaults, whose persistent tables reject refcounted zvals:
startup died with "Internal zvals cannot be refcounted". EvaluatedValue
now carries the case identity in a dedicated field while its value
degrades to what those consumers read before case identity existed
(the host case object for internal enums, the literal backing value or
case name for compiled ones), and only class-constant registration opts
into the AST. Property/parameter defaults keep flowing through their
existing runtime-restore machinery unchanged.
Also parenthesize a folded constant operand before appending a member
access: the C++ ternary of `const VALUE = cond ? E::A : E::B;` bound
`.attr("value")` to its else branch only, so `K::VALUE->value`
evaluated to the case object instead of its backing value.
* fix(gen_stub): give persistent AST constants a complete teardown lifecycle
destroy_zend_class() asserts (in debug builds) that every persistent
AST constant remaining on an internal class is CONST_ENUM_INIT, and its
teardown frees only the allocation referenced by Z_AST — the previous
representation left a CLASS_CONST root behind (assertion failure at
shutdown on 8.4/8.5 debug builds) and leaked the two separately
allocated children.
The AST is now built in one contiguous persistent allocation (ast_ref,
root, both zval children — mirroring Zend's own persistent enum AST
builder), and every generated file with AST constants emits a release
function that runs from the module's MSHUTDOWN, before Zend's class
teardown: it frees the single block and restores the constant slot to
null, so destroy_zend_class() never sees a foreign AST. Request-local
mutable copies are unaffected (no request is live at MSHUTDOWN).
CONST_ENUM_INIT itself is not usable here: that node constructs a new
case object rather than fetching the canonical registered one, which
would break case identity again.
* fix(codegen): reject lifecycles that cannot release AST constants
The typephp_release_ast_constants_*() teardown ran only from MSHUTDOWN,
which is not a general pre-class-destruction hook: for a
MODULE_TEMPORARY module loaded through dl(), module_destructor() runs
clean_module_classes() before the shutdown callback, so the foreign
ZEND_AST_CLASS_CONST reached destroy_zend_class() first and still
tripped the debug assertion; and a MINIT that fails after registering
such a constant never sets module_started, so MSHUTDOWN is not
guaranteed to run at all.
The generated module now enforces the lifecycle contract instead of
assuming it. When the module declares any enum-case AST constant, MINIT
opens with a guard that rejects MODULE_TEMPORARY (zend_error E_WARNING,
return FAILURE) before a single class is registered — with nothing in
the class table, teardown is trivially safe. MINIT is also restructured
so that every step that can return FAILURE precedes the first
register_class_*() call: the AST constants are installed by the
infallible tail (class registration, then symbol registration), so a
FAILURE return can never leave a foreign AST in the persistent tables.
The generator itself throws if a future change introduces a FAILURE
return after registration begins. The MSHUTDOWN release is unchanged
and remains the supported, persistent-module path.
EnumCaseAstConstantLifecycleTest asserts the guard exists exactly when
AST constants exist, that it precedes every registration step, that no
FAILURE return follows the first class registration, and that MSHUTDOWN
releases the constants before any other teardown. The enum-case phpt
gains a never-accessed constant so the full process shutdown it already
performs also covers a pristine persistent AST; a dl()-path phpt is not
feasible because the harness only builds standalone binaries whose
module is registered persistently (documented in the test file).
- 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
- Remove initialization window semantics for readonly properties
- Restrict readonly property writes to direct assignment only
- Add explicit error messages for unsupported readonly operations
- Update tests to reflect new readonly property behavior
- Remove constructor and clone method invocation restrictions
- Add support for closure rebinding rejection at compile time
- Modify property write target preparation with readonly checks
- Update documentation to remove outdated readonly initialization rules
- Add new test cases for readonly property direct assignment enforcement
- Check for readonly property when calling unset on object properties
- Throw fatal error when attempting to unset readonly properties
- Add proper error message with property display name
- Include tests for unset operations on readonly properties
- Support both regular readonly properties and readonly class properties
- Ensure consistent error handling for readonly property access violations
- Add runtime check mechanism for objects that require value validation
- Prevent null assignment to typed objects after unset with proper error message
- Disable native call optimizations when object values become unpredictable
- Maintain class constraints even after unset and reassignment
- Generate appropriate error handling for invalid object operations
- Update SSA analysis to recognize unset operations as dangerous for property hoisting
- Add comprehensive tests for typed object unset behavior scenarios
- Add initialization of standard containers with default values when not boxed
- Implement iteration guards for safe foreach structural mutations in std containers
- Add support for compound operations on bigint, bigfloat, and decimal types
- Introduce lazy offset retrieval for map containers with default values
- Enhance unset operations to use proper type conversions and default values
- Add parallel testing support with worker isolation and temporary directories
- Implement proper container size reporting using runtime values instead of compile-time
- Add comprehensive test coverage for container operations and edge cases
- Add fake_scope_guard keyword to reserved words list
- Implement trait property scope handling in PropertyAccessTrait
- Generate proper scope guards for trait methods in Translator
- Add WASM implementation documentation outlining technical approach
- Include trait-fake-scope-guard-param test case
- Link WASM plan in main documentation index
- Add test case for namespaced class name escaping in C++ string generation
- Verify proper error message display for type mismatch in namespaced properties
- Test native scalar property assignments with configuration arrays
- Validate TypeError handling for invalid type assignments in namespaced context
fix(compiler): ensure namespaced class names are properly escaped in property type checks
- Update genCharPtr call with escape parameter set to true
- Fix object property type check display name generation for namespaced classes
- Maintain backward compatibility with existing property access patterns
- Add support for array references using byRef flag in ArrayExpressionTrait
- Modify hasReference check in array parsing logic to handle mixed references
- Implement reference value parsing with proper error handling for unpacking
- Enhance foreach reference binding with improved type checking and error messages
- Add proper scope handling for foreach iterators with class context
- Update foreach value assignment to use correct reference expression syntax
- Implement structural mutation protection for std containers during iteration
- Add comprehensive test coverage for foreach edge cases and reference mutations
- Document std container modification restrictions during foreach loops
- Update yield from and foreach documentation for iterator handling differences
- Replace php::throwException with php::throwExceptionEx for better error handling
- Add return php::null statements after exception throws in closure generators
- Update argument count error messages to use format strings with proper escaping
- Modify type error messages to use format strings instead of concatenation
- Add completed callback parameter to dispatchParallel method in NativeBuilder
- Track and report completed task count during parallel compilation
- Add progress bar functionality using AnsiKit components
- Include failure reason reporting when compilation fails
- Add test case for parallel dispatcher completion tracking
- Add test for foreach indentation restoration in object iteration
- Increment version from 0.3.0 to 0.4.0
- Replace appendCapturedStmtLines helper with direct formatCapturedStmtLines calls
- Change createPropertyAccessResolver from private to protected for extensibility
- Change resolveNativeInstanceProperty from private to protected for extensibility
- Change resolveNativeStaticProperty from private to protected for extensibility
- Change applyNativePropertyAccessResult from private to protected for extensibility
- Change containsNullsafeChain from private to protected for extensibility
- Replace parseTypeDecl output parameter with resolveTypeDecl returning array
- Change sortFiles to getSortedFiles returning sorted array instead of modifying input
- Update name resolution to handle imported namespace prefixes correctly
- Enhance property hook backing access detection with additional conditions
- Add redis extension availability check to test skip conditions
- Document compiler self-hosting constraints regarding reference parameters across traits
- Add readonly flag to PropertyDef entity
- Implement readonly check in property hoisting logic
- Prevent hoisting of readonly properties in SsaPropOptimizer
- Update canHoist methods to accept PropertyDef parameter
- Add test case for readonly cross-class property access
- Document readonly property restriction in hoisting rules
- Replaced all occurrences of self::TYPE_* with Type::* in AnonClassGenerator.php
- Updated ArrayExpressionTrait.php to use Type::ARRAY and Type::VAR instead of self::TYPE_*
- Modified AssignOpTrait.php to reference Type constants instead of self::TYPE_*
- Changed BinaryOpTrait.php to use Type::BIGINT, Type::DECIMAL, Type::BIGFLOAT constants
- Updated CallArgumentGenerator.php to use Type::ARRAY and Type::REF constants
- Added Type import statements to all modified files
- Maintained same functionality while improving code consistency with Type namespace
- Move Reflection class from TypePhp to TypePhp\Resolver namespace
- Rename ArgInfo.php to TypePhp\Entity\ArgInfo and update all references
- Move AstNodeType.php to TypePhp\Parser\AstNodeType with namespace update
- Update Symbol.php import paths to use TypePhp\Generator\Symbol
- Move Constants.php to TypePhp\Metadata\Constants with namespace change
- Rename FileScanner.php to TypePhp\Build\FileScanner with namespace update
- Move MagicMethodDetector.php to TypePhp\Resolver\MagicMethodDetector
- Rename PropertyHookLowering.php to TypePhp\Transform\PropertyHookLowering
- Move Visitor.php to TypePhp\Transform\Visitor with namespace update
- Update all test files to reflect new class
- Extract composite type checking logic to new CompositeTypeCheckerTrait
- Move dynamic property access methods from CompilerBase to PropertyAccessTrait
- Add use statement for CompositeTypeCheckerTrait in CompilerBase
- Remove duplicate method implementations from CompilerBase
- Maintain all existing functionality through trait-based code organization