Skip to content
Draft
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
2 changes: 1 addition & 1 deletion docs/php/system-and-io.md
Original file line number Diff line number Diff line change
Expand Up @@ -346,7 +346,7 @@ wrappers are documented in [Streams](streams.md).

| Function | Signature | Description |
|---|---|---|
| `var_dump()` | `var_dump($value): void` | Output type and value. Homogeneous indexed arrays of `int`, `string`, `bool`, or `float` and associative arrays (hashes) print full per-element bodies (`[N]=>\n int(V)\n`, `["key"]=>\n string(…)\n`, etc.). Nested arrays/objects inside a Mixed-element array or hash print `NULL` (recursive nesting into those layouts is still pending). |
| `var_dump()` | `var_dump($value): void` | Output type and value. Homogeneous indexed arrays of `int`, `string`, `bool`, or `float` print full per-element bodies (`[N]=>\n int(V)\n`, `["key"]=>\n string(…)\n`, etc.). Associative arrays (hashes), `Mixed`-element arrays, and arbitrarily nested arrays recurse fully through the runtime value renderer, matching PHP's `array(N) {\n [key]=>\n TYPE(VAL)\n}\n` layout with 2-space indentation per level. Objects print `NULL` (full object dumps are not yet supported). |
| `print_r()` | `print_r($value): void` | Human-readable output. Indexed arrays, associative arrays, and arbitrarily nested arrays print PHP's recursive `Array\n(\n [key] => value\n)\n` layout (unquoted keys, 4 spaces of indentation per level, `1`/empty for bool `true`/`false`, empty for `null`). The 2-argument return form (`print_r($v, true)`) is not yet supported. |
| `var_export()` | `var_export($value, $return = false): ?string` | Parsable representation. Renders scalars (`'…'`-quoted strings with `\\`/`\'` escaping, `true`/`false`, `NULL`, integers, and floats — an integer-valued float gains a `.0`) and arbitrarily nested arrays in PHP's `array (\n key => value,\n)` layout (2 spaces of indentation per level, integer keys bare and string keys quoted, nested arrays on their own line). With `$return = true` the rendering is returned instead of printed. Objects are not yet rendered (PHP emits `\Class::__set_state(...)`). Floats use PHP's `serialize_precision = -1` semantics — the shortest decimal that round-trips back to the same `double` (so `1/3` renders as `0.3333333333333333`, not the 14-digit `(string)` form), with the same scientific layout as PHP (`1.0E+17`, `1.0E-6`), an integer-valued float gaining `.0` (`1.0`, `100.0`), and `-0.0`, `INF`, `-INF`, `NAN` preserved. This is independent of the default `precision` used by `echo`/`(string)`. |

Expand Down
4 changes: 4 additions & 0 deletions examples/nested-arrays/main.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,7 @@
echo "\nAfter adding a row:\n";
echo "Rows: " . count($matrix) . "\n";
echo "New row: " . $matrix[3][0] . " " . $matrix[3][1] . " " . $matrix[3][2] . "\n";

// var_dump recurses into nested arrays, matching PHP's layout
echo "\nvar_dump of the matrix:\n";
var_dump($matrix);
323 changes: 323 additions & 0 deletions src/codegen/runtime/arrays/array_strict_eq.rs

Large diffs are not rendered by default.

396 changes: 396 additions & 0 deletions src/codegen/runtime/arrays/hash_strict_eq.rs

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions src/codegen/runtime/arrays/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ mod array_set_mixed;
mod array_set_mixed_key;
mod array_set_refcounted;
mod array_set_str;
mod array_strict_eq;
mod array_rand;
mod random_u32;
mod random_uniform;
Expand Down Expand Up @@ -114,6 +115,7 @@ mod hash_insert_owned;
mod hash_iter;
mod hash_new;
mod hash_set;
mod hash_strict_eq;
mod hash_to_mixed;
mod hash_union;
mod hash_unset;
Expand Down Expand Up @@ -259,6 +261,8 @@ pub use array_set_refcounted::emit_array_set_refcounted;
/// Emit refcounted indexed-array set helper.
pub use array_set_str::emit_array_set_str;
/// Emit string indexed-array set helper.
pub use array_strict_eq::emit_array_strict_eq;
/// Emit indexed-array strict-equality comparison helper.
pub use array_rand::emit_array_rand;
/// Emit random array element helper.
pub use random_u32::emit_random_u32;
Expand Down Expand Up @@ -355,6 +359,8 @@ pub use hash_new::emit_hash_new;
/// Emit new hash helper.
pub use hash_set::emit_hash_set;
/// Emit hash set helper.
pub use hash_strict_eq::emit_hash_strict_eq;
/// Emit hash strict-equality comparison helper.
pub use hash_to_mixed::emit_hash_to_mixed;
/// Emit hash-to-Mixed conversion helper.
pub use hash_union::emit_hash_union;
Expand Down
37 changes: 23 additions & 14 deletions src/codegen/runtime/data/fixed.rs
Original file line number Diff line number Diff line change
Expand Up @@ -694,25 +694,34 @@ pub(crate) fn emit_runtime_data_fixed(heap_size: usize, target: Target) -> Strin
// __rt_hash_get. v1 limitation: only one active context at a time —
// a fresh stream_context_create overwrites the slot.
out.push_str(".comm _stream_context_options, 8, 3\n");
// var_dump body literals (rodata): per-element prefix/suffix bytes
// used by the array walkers __rt_var_dump_array_int / _str.
out.push_str(".globl _vd_indent_open\n_vd_indent_open:\n .ascii \" [\"\n");
// var_dump body literals (rodata): per-element prefix/suffix bytes used by
// the array walkers and the recursive `__rt_var_dump_value` renderer. The
// prefixes carry no leading indent; indentation is written separately by
// `__rt_var_dump_spaces` so nested arrays indent correctly.
out.push_str(".globl _vd_indent_open\n_vd_indent_open:\n .ascii \"[\"\n");
out.push_str(".globl _vd_close_arrow\n_vd_close_arrow:\n .ascii \"]=>\\n\"\n");
out.push_str(".globl _vd_int_prefix\n_vd_int_prefix:\n .ascii \" int(\"\n");
out.push_str(".globl _vd_int_prefix\n_vd_int_prefix:\n .ascii \"int(\"\n");
out.push_str(".globl _vd_close_paren\n_vd_close_paren:\n .ascii \")\\n\"\n");
out.push_str(".globl _vd_str_prefix\n_vd_str_prefix:\n .ascii \" string(\"\n");
out.push_str(".globl _vd_str_prefix\n_vd_str_prefix:\n .ascii \"string(\"\n");
out.push_str(".globl _vd_close_paren_space\n_vd_close_paren_space:\n .ascii \") \\\"\"\n");
out.push_str(".globl _vd_close_quote\n_vd_close_quote:\n .ascii \"\\\"\\n\"\n");
// var_dump bool-array literals — preformatted lines (12 / 13 bytes) so
// the bool walker is a single dispatch + write.
out.push_str(".globl _vd_bool_true_line\n_vd_bool_true_line:\n .ascii \" bool(true)\\n\"\n");
out.push_str(".globl _vd_bool_false_line\n_vd_bool_false_line:\n .ascii \" bool(false)\\n\"\n");
out.push_str(".globl _vd_float_prefix\n_vd_float_prefix:\n .ascii \" float(\"\n");
out.push_str(".globl _vd_null_line\n_vd_null_line:\n .ascii \" NULL\\n\"\n");
// var_dump hash (associative array) string-key delimiters: ` ["` before the
// key bytes and `"]=>\n` after, matching PHP's ` ["key"]=>` line format.
out.push_str(".globl _vd_str_key_open\n_vd_str_key_open:\n .ascii \" [\\\"\"\n");
// var_dump bool-array literals — preformatted lines so the bool walker is a
// single dispatch + write (no leading indent; spaces are written separately).
out.push_str(".globl _vd_bool_true_line\n_vd_bool_true_line:\n .ascii \"bool(true)\\n\"\n");
out.push_str(".globl _vd_bool_false_line\n_vd_bool_false_line:\n .ascii \"bool(false)\\n\"\n");
out.push_str(".globl _vd_float_prefix\n_vd_float_prefix:\n .ascii \"float(\"\n");
out.push_str(".globl _vd_null_line\n_vd_null_line:\n .ascii \"NULL\\n\"\n");
// var_dump hash (associative array) string-key delimiters: `["` before the
// key bytes and `"]=>\n` after, matching PHP's `["key"]=>` line format.
out.push_str(".globl _vd_str_key_open\n_vd_str_key_open:\n .ascii \"[\\\"\"\n");
out.push_str(".globl _vd_str_key_close\n_vd_str_key_close:\n .ascii \"\\\"]=>\\n\"\n");
// 64-space pad used by `__rt_var_dump_spaces` (written in <=64-byte chunks).
out.push_str(".globl _vd_spaces\n_vd_spaces:\n .ascii \" \"\n");
// var_dump recursive array-header/footer literals: `array(` before the
// count, `) {\n` after it, and `}\n` for the closing brace.
out.push_str(".globl _vd_array_open\n_vd_array_open:\n .ascii \"array(\"\n");
out.push_str(".globl _vd_array_close_brace\n_vd_array_close_brace:\n .ascii \") {\\n\"\n");
out.push_str(".globl _vd_close_brace_nl\n_vd_close_brace_nl:\n .ascii \"}\\n\"\n");
// print_r body literals (rodata): PHP's `Array\n(\n` header, `)\n` footer,
// `[`/`] => ` key delimiters (unquoted keys, unlike var_dump), a lone
// newline, the `1` rendered for boolean true, and a 64-space pad used by
Expand Down
5 changes: 5 additions & 0 deletions src/codegen/runtime/emitters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,8 @@ pub(crate) fn emit_runtime(emitter: &mut Emitter, features: RuntimeFeatures) {
arrays::emit_mixed_is_empty(emitter);
arrays::emit_mixed_numeric_binops(emitter);
arrays::emit_mixed_strict_eq(emitter);
arrays::emit_array_strict_eq(emitter);
arrays::emit_hash_strict_eq(emitter);
arrays::emit_mixed_unbox(emitter);
arrays::emit_mixed_write_stdout(emitter);
arrays::emit_object_free_deep(emitter);
Expand Down Expand Up @@ -463,6 +465,9 @@ pub(crate) fn emit_runtime(emitter: &mut Emitter, features: RuntimeFeatures) {
io::emit_var_dump_emit_bool_line(emitter);
io::emit_var_dump_emit_float_line(emitter);
io::emit_var_dump_emit_null_line(emitter);
io::emit_var_dump_spaces(emitter);
io::emit_var_dump_value(emitter);
io::emit_var_dump_indexed(emitter);
io::emit_print_r_spaces(emitter);
io::emit_print_r_open(emitter);
io::emit_print_r_close(emitter);
Expand Down
2 changes: 1 addition & 1 deletion src/codegen/runtime/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -257,5 +257,5 @@ pub(crate) use var_dump_walk::{
emit_var_dump_array_mixed, emit_var_dump_array_str, emit_var_dump_emit_bool_line,
emit_var_dump_emit_float_line, emit_var_dump_emit_indexed_key, emit_var_dump_emit_int_line,
emit_var_dump_emit_null_line, emit_var_dump_emit_string_key, emit_var_dump_emit_string_line,
emit_var_dump_hash,
emit_var_dump_hash, emit_var_dump_indexed, emit_var_dump_spaces, emit_var_dump_value,
};
Loading
Loading