Conversation
b1fed8b to
0262885
Compare
Member
Author
|
This is almost ready for a first merge. It's still experimental, but it's a good candidate for the next release |
A literal eval storing a different scalar type into an existing local
(e.g. $x = 1; eval('$x = "changed";')) previously fell back to the
scope path, whose write-back cast the value through the stale slot type.
Widen the slot to boxed Mixed storage and keep the native direct-store
path; codegen re-lowers every load/store with the final slot type.
…rrides PHP resolves $obj->m() from class scope S to S's own private instance method when S declares one and the receiver is an instance of S, even if a subclass overrides m publicly. The interpreter resolved metadata from the receiver's runtime class, found the override, and sent its class as the bridge scope — masking the ambient scope the AOT caller had pushed. Check the calling scope first and dispatch with it directly; the native bridge's hidden private shadow slots already select the right symbol from the scope string. Applies to direct calls and callable arrays.
Extend eval result casting (False lowers as Bool) and native type-spec
formatting ("false") for the literal-false type introduced by main's
narrowing work.
class_exists() accepts a dynamic autoload flag (never an AOT autoload demand; class_parents keeps the literal-flag coverage) and stacked parameter attributes now persist in the AST as ordered groups.
Capture the declaring home file on every eval_builtin! spec via file!(), name EvalArea spellings, and surface a documentation projection (builtin_docs_metadata: area, params with defaults/by-ref, variadic, hook kinds, home file) plus the procedural date-alias name list through the public builtin_metadata API.
Move gen_builtins from a bin to an example target so it can link the elephc-magician dev-dependency without embedding the interpreter in the elephc binary. Every record gains an eval block (kind: registry | date-alias | none, hooks, params, home file); eval-registry names with no static counterpart are appended as aot_resident (compiler-resident constructs) or eval_only records. CI, skill, and docs references updated.
extract.py consumes the exporter's eval blocks (merging resident ones into the language-construct entries and building pages for eval-only builtins), the JSON registry carries eval/eval_only per record, and the renderer adds an Availability section to user pages, an eval-interpreter section to internals pages, and AOT/eval() columns to the indexes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This PR adds full
eval()support to elephc through Magician (crates/elephc-magician), a PHP interpreter that ships as an optional static library. Programs that never calleval()are completely unaffected: the interpreter is linked only when eval is actually used, and native-only binaries keep their current size and dependencies.1,207 commits · 2,128 files · +268k/−11.5k lines
How eval is executed
Eval sites are compiled with a three-tier strategy, picked per call site by coordinated classifiers in the plan, lowering, and codegen layers:
__elephc_eval_*FFI bridge, with bidirectional scope synchronization between native locals and the eval scope.Native ↔ eval interop
__call/__callStaticfallbacks, and late static binding.function_exists,defined, reflection, …).The Magician interpreter
eval_builtin!registry (inventory-collected, one home file per builtin), covering strings, arrays, math, regex (PCRE + mb_ereg), JSON, filesystem, date/time, SPL, and reflection.tests/builtin_parity_tests.rs).Documentation
docs/php/eval.mdcovering supported semantics and the AOT tiers.eval(), with links to both implementations. The exporter reads both registries, so the matrix cannot drift from the parity tests.Compiler improvements landed along the way
array_key_exists()over boxed Mixed containers with runtime tag dispatch; float key normalization.is_array/is_integerdispatchable as runtime string callbacks.newInstanceArgs()with indexed argument lists, attribute array-literal arguments.Testing
declaresupport) with the generated docs byte-identical to CI regeneration.