aboutsummaryrefslogtreecommitdiffstats
path: root/cli
diff options
context:
space:
mode:
authoreunhhu <[email protected]>2026-10-18 17:23:37 +0100
committereunhhu <[email protected]>2026-10-18 17:23:37 +0100
commitd8e297452d8e0896d4733e09b70fdc3e6ce08a55 (patch)
treeb7502c598faf2fe54f49dc7e40ebfe54f94bb910 /cli
parent241016b0fc3139414089619f0ef8cb7237722c6c (diff)
downloadpure-d8e297452d8e0896d4733e09b70fdc3e6ce08a55.tar.gz
pure-d8e297452d8e0896d4733e09b70fdc3e6ce08a55.zip
Module format and executor: 027's stage 3, nested stored state: a stored or a transient list's records may hold lists (a message's rows not, nor as a key); such a list's cell holds the value in its items' stored form (PURE_CELL_LIST, held as bytes are: each item's fields in order, 8 bytes a number, bool or i64, a u32le length and bytes a text or a list, a list's in this form again), read into one of the event's lists by ITEM_GET (counted in the event's room) and written from one by LIST_APPEND, LIST_INSERT and ITEM_SET, APPEND_IN reading, appending and writing back (undone with the event): images, the log, undoing, readers' shares and commits hold it as a text's bytes, so nothing new is stored or recovered; a list image's header names its record graph (a list field's items' record by its number, the graph's other records after the fields: a record holds itself through a list), and starting or replacing moves the items of the lists in fields by field name down the graph (PureLayout, pure_list_migrate); an event's lists keep the event's lists' numbers; a view lets go the lists a view before it read in; no FIND joined to a list field's read; pure-run shows a kept list's lists; unit tests (an event changing a number and a stored item's list, the process dying at the tree's four stages and the log's two, failed commits changing nothing; a replacement moving a stored and a transient list's lists, their items' record gaining a field and the board's fields changing places; under ASan and UBSan too)
Diffstat (limited to 'cli')
-rw-r--r--cli/pure-run.c59
1 files changed, 47 insertions, 12 deletions
diff --git a/cli/pure-run.c b/cli/pure-run.c
index 97bd6d5..dceb841 100644
--- a/cli/pure-run.c
+++ b/cli/pure-run.c
@@ -49,22 +49,56 @@ static bool collect(void *context, PureSpan span) {
return true;
}
-static void show_list(const PureModule *m, const PureList *list, const PureRecord *record) {
+static uint32_t le32(const unsigned char *p) { return (uint32_t)p[0] | (uint32_t)p[1] << 8 | (uint32_t)p[2] << 16 | (uint32_t)p[3] << 24; }
+
+static void show_cell(const PureModule *m, uint32_t field, PureCell cell, bool kept);
+
+/* A list kept past an event holds a list field's value in its items' stored form (Pure 027's stage 3): its items. */
+static void show_value_items(const PureModule *m, uint32_t record, const unsigned char *bytes, size_t size) {
+ const PureRecord *r = &m->record[record];
+ putchar('[');
+ for (size_t at = 0, item = 0; at < size; ++item) {
+ printf("%s{", item ? "," : "");
+ for (unsigned f = 0; f < r->count && at <= size; ++f) {
+ uint8_t type = m->record_field_type[r->first + f];
+ PureCell cell = {0};
+ if (type == PURE_RECORD_TEXT || type == PURE_RECORD_LIST) {
+ cell.size = size - at >= 4 ? le32(bytes + at) : 0;
+ cell.text = (unsigned char *)bytes + at + 4;
+ at += 4 + cell.size;
+ } else {
+ memcpy(&cell.i64, bytes + at, 8);
+ at += 8;
+ }
+ printf("%s\"%s\":", f ? "," : "", m->record_field_names[r->first + f]);
+ show_cell(m, r->first + f, cell, true);
+ }
+ putchar('}');
+ }
+ putchar(']');
+}
+
+static void show_cell(const PureModule *m, uint32_t field, PureCell cell, bool kept) {
+ uint8_t type = m->record_field_type[field];
+ if (type == PURE_RECORD_BOOL) printf("%s", cell.num ? "true" : "false");
+ else if (type == PURE_RECORD_I64) printf("%" PRId64, cell.i64);
+ else if (type == PURE_RECORD_NUMBER) printf("%.17g", cell.num);
+ else if (type == PURE_RECORD_LIST && kept) show_value_items(m, (uint32_t)m->record_field_default[field].i64, cell.text, cell.size);
+ else if (type == PURE_RECORD_LIST) printf("%" PRId64, cell.i64); /* an event's list: its number among the event's */
+ else {
+ putchar('"');
+ json_span(NULL, (PureSpan){cell.text, cell.size});
+ putchar('"');
+ }
+}
+
+static void show_list(const PureModule *m, const PureList *list, const PureRecord *record, bool kept) {
putchar('[');
for (size_t at = 0; at < pure_list_count(list); ++at) {
printf("%s{", at ? "," : "");
for (unsigned f = 0; f < record->count; ++f) {
- PureCell cell = pure_list_get(list, at, f);
printf("%s\"%s\":", f ? "," : "", m->record_field_names[record->first + f]);
- uint8_t type = m->record_field_type[record->first + f];
- if (type == PURE_RECORD_BOOL) printf("%s", cell.num ? "true" : "false");
- else if (type == PURE_RECORD_I64) printf("%" PRId64, cell.i64);
- else if (type == PURE_RECORD_NUMBER) printf("%.17g", cell.num);
- else {
- putchar('"');
- json_span(NULL, (PureSpan){cell.text, cell.size});
- putchar('"');
- }
+ show_cell(m, record->first + f, pure_list_get(list, at, f), kept);
}
putchar('}');
}
@@ -106,7 +140,8 @@ static void show(PureApp *app, const char *failure) {
putchar('"');
pure_draft_read(app->texts[i], 0, pure_draft_size(app->texts[i]), json_span, NULL);
putchar('"');
- } else if (m->state_type[i] == PURE_STATE_LIST) show_list(m, app->lists[i], &m->record[m->state_ref[i]]);
+ } else if (m->state_type[i] == PURE_STATE_LIST)
+ show_list(m, app->lists[i], &m->record[m->state_ref[i]], !(m->state_flags[i] & PURE_LIST_ROWS >> 8));
else if (m->state_type[i] == PURE_STATE_BOOL) printf("%s", app->values[i].num ? "true" : "false");
else if (m->state_type[i] == PURE_STATE_I64) printf("%" PRId64, app->values[i].i64);
else printf("%.17g", app->values[i].num);