Skip to content

Instantly share code, notes, and snippets.

@audinue
Created May 31, 2024 16:00
Show Gist options
  • Save audinue/b3b8920d436dfbeb7c4c3d5e14c54e8d to your computer and use it in GitHub Desktop.
Save audinue/b3b8920d436dfbeb7c4c3d5e14c54e8d to your computer and use it in GitHub Desktop.
local state for immediate stuff
<?php
function create_group($symbols, $prefix)
{
return (object) [
'tag' => 'group',
'symbols' => $symbols,
'prefix' => $prefix,
'key' => 0,
'used' => []
];
}
function current_group()
{
global $stack;
return $stack[count($stack) - 1];
}
function next_key()
{
$group = current_group();
return $group->prefix . $group->key++;
}
function clean_current_group()
{
$group = current_group();
foreach ($group->symbols as $key => $value) {
if (!in_array($key, $group->used)) {
unset($group->symbols->$key);
}
}
}
function &use_state($factory)
{
$group = current_group();
$key = next_key();
$group->used[] = $key;
if (!isset($group->symbols->$key)) {
$group->symbols->$key = $factory();
}
return $group->symbols->$key;
}
function begin_group($key = null)
{
global $stack;
$group = current_group();
if ($key === null) {
$key = next_key();
}
$group->used[] = $key;
if (!isset($group->symbols->$key)) {
$group->symbols->$key = create_group(
(object) [],
$key . '-'
);
}
$stack[] = &$group->symbols->$key;
}
function end_group()
{
global $stack;
clean_current_group();
array_pop($stack);
}
function is_group($value)
{
return is_object($value) && isset($value->tag) && $value->tag == 'group';
}
function sleep_group($group)
{
$symbols = (object) [];
foreach ($group->symbols as $key => $value) {
if (is_group($value)) {
$symbols->$key = sleep_group($value);
} else {
$symbols->$key = $value;
}
}
return (object) [
'tag' => 'group',
'symbols' => $symbols
];
}
function wake_group($group, $prefix = '')
{
$symbols = (object) [];
foreach ($group->symbols as $key => $value) {
if (is_group($value)) {
$symbols->$key = wake_group($value, $prefix . $key . '-');
} else {
$symbols->$key = (array) $value;
}
}
return create_group($symbols, $prefix);
}
<?php
require 'runtime.php';
function counter($action)
{
extract(use_state(fn () => ['id' => uniqid(), 'count' => 0]), EXTR_REFS);
if ($action == 'increment-' . $id) {
$count++;
}
?>
<button name="action" value="increment-<?= $id ?>"><?= $count ?></button>
<?php
}
function render($action)
{
extract(use_state(fn () => ['show' => false]), EXTR_REFS);
if ($action == 'toggle') {
$show = !$show;
}
?>
<button name="action" value="toggle">Toggle</button>
<?php counter($action) ?>
<?php begin_group() ?>
<?php if ($show) : ?>
<?php counter($action) ?>
<?php endif ?>
<?php end_group() ?>
<?php counter($action) ?>
<?php
}
function tick()
{
global $stack;
$root = wake_group(json_decode($_POST['state'] ?? '{"symbols":{}}'));
$stack = [$root];
?>
<form method="post">
<?php render($_POST['action'] ?? '') ?>
<?php clean_current_group() ?>
<input type="hidden" name="state" value="<?= htmlspecialchars(json_encode(sleep_group($root))) ?>">
</form>
<?php
}
tick();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment