| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The app model, the tree store and the HTTP host lived in
prototypes/connections among the earlier document runtime, the store was
known only by its format's name, and Vega compiled six Pure sources by path.
Now, as the README's principle has it:
core/ runtime, flow and the app model (module*.c), with what the core
asks of storage (state.h, store.h)
store/ the tree store (PURETRE3, PUREREC1)
serve/ pure-serve: HTTP host, outbound delivery, JSON in place
cli/ pure-run, pure-edit-module
A top-level make builds libpure.a (app model and store, for hosts to link)
and the hosts; make check runs the store's and the app model's tests. The
earlier runtime still builds from prototypes/connections against core/ and
store/ (check, check-tree and check-core pass). Design 009 records the rule:
parts by role behind libraries; git repositories split by coupling, so the
store stays here while its contract moves with the core, and Vega stays apart.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
A real app (a board, a stopwatch) already used a quarter of the 512
instructions, since a fn is inlined where it is called, and every text
it shows is one of 64 constants. The code and the constants now live in
one block sized to the module, which load takes and pure_module_release
gives back; the limits rise to 65,535 instructions and 4,096 constants
of up to 1 MiB, while PureModule shrinks from 28,664 to 11,936 bytes.
The verifier's branch marks are sized to the block instead of 64 KiB on
the stack. pure_module_read reads a module file whole, and every host
uses it instead of a 128 KiB buffer.
|
| |
|
|
|
|
|
|
|
|
| |
An input may be a timer (kind 4, its period of 1 ms to a day in place of
a key name): pure_app_tick delivers a tick, an event saved like a key's.
NOW gives handlers the time the host set in PureApp.now (milliseconds
since 1970, UTC), so a script replays any time and views stay functions
of state; FLOOR and MOD take times apart, MOD taking the divisor's sign as
floor division leaves it, a zero too. pure-run gains time MS and tick NAME.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A list state may name a key field of its record (the flags word of its
entry: field + 1). A keyed list keeps its items in key order, numbers by
value and texts by their bytes, each key once: LIST_APPEND places an item
by halving and fails with the new fault exists (PURE_CONFLICT) when the
key is there; LIST_FIND gives the index of a key's item and LIST_HAS
whether it is there. The verifier refuses inserting by position and
changing a key. Maps, sets and sorted maps are one list with an order
rule, so tables, filters, folds, indices, storage and replacement stay
as they are.
A module that opens over a list not in its key order (one that was not
keyed, keyed by another field, or stored so) puts it in order, moves its
indices with their items and stores it again; two items with one key
refuse the module rather than drop one.
TEXT_COMPARE compares two texts by their bytes under one of the six
relations.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A save now publishes everything since the last save in one commit: the
documents messages edited and the states that changed. If it fails, every
event since the last save is undone (values, text and list drafts, the
list undo log, event and tick counts), so an event reported as successful
is stored and a failed one leaves no trace.
By default each key, text and message event saves before it returns, as
before. With pure_app_defer events apply at once and a host saves a burst
with one commit; a key's document joins a burst once, so revisions move
one per save. On the Pi's SD card 600 events take 6.3 s saved one by one,
0.97 s in bursts of 8 and 0.34 s in bursts of 64. pure-run takes --batch N.
Tests compare a deferred stored app that saves at random and sometimes
stops unsaved with an app that replays only the saved events, undo a whole
burst on a failed save, and kill a process while it saves a burst.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
When the data host keeps states (PureData.state and .save, implemented by
pure_tree_data), every state of an app lives in the store: a text state's
draft is its stored value, a list mirrors each change into a stored draft
(record header, then items), and numbers, cursors and indices are stored
together by name. An app starts from what is stored, moves list fields by
name when a record changed, resets cursors and indices that no longer fit,
and refuses damaged stored values.
Each key, text and message event publishes the states it changed together
with the message's document in one store commit, or fails and leaves
memory and store as they were. Frame changes go with the next event or
pure_app_save. pure-run takes --store PATH.
Tests run the same random events on an app in memory and on a stored app
that restarts every few events and require equal states after every step;
kill a process at every commit stage of an event that changes a number, a
text and a list; and check frames, message atomicity and migration by
restart and by replacement. A stored event costs about 10.6 ms more on the
Pi's SD card, mostly two fsyncs.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Module format v5 lets a value cross a join: the verifier records the
stack each branch brings to its target and requires every path to agree
on height, types and owners, with at most 8 such joins ahead. Branches
are now allowed in views, so a view can be a conditional expression.
A table view has one row per item of a list. Its columns are number or
text views evaluated for one row at a time and may read that row (ROW).
Hosts compute only the cells they show through pure_app_rows,
pure_app_cell and pure_app_cell_text. Column names are scoped to their
table. The view limit rises to 64, columns included.
pure-run prints a table view as an array of row objects.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Module format v4 declares record types and adds list states (items of a
record) and index states (a position in one list). The verifier types
record operands field by field and rejects an index used on another list.
Indices follow their item across inserts and removes. List changes are
logged per event and undone when the event fails. Replacing a module keeps
a list by name and moves its fields by name when the record changed.
pure-run prints lists as arrays and a failed view as null.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Module format v3 adds text states, cursors, UTF-8 constants, text inputs
and text views. A text state is a runtime-owned draft without a store, so a
large text edits as an extent tree. Cursors are byte positions the runtime
keeps on character boundaries: insertion pushes cursors at or after the
point, removal gathers cursors inside the range, and a failed event returns
every text draft and cursor to where it was. The verifier types a cursor by
the text it belongs to and rejects editing one text with another's cursor.
Operations cover constants, concatenation, shortest round-trip number text,
character, line and byte counts, character and column-keeping line moves,
insert, remove, line views, whole-text replacement and UTF-8 checked
conversion from bytes. Replies of edited documents or texts are copied before
they are finished. pure-run gains text input and text output.
test-module covers typing Korean and emoji, moves that stop at the ends,
line moves, views, rollback, invalid UTF-8 and replacement, text-specific
verifier rules, and 20,000 damaged text modules whose cursors always stay
on character boundaries under ASan/UBSan.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Module format v2 adds byte values, message inputs with u32 and bytes-tail
fields, one keyed byte collection, replies and require. The verifier checks
every operand's type and the context each operation may run in, and allows
branches and joins only at an empty stack, so typed values never merge.
A message event opens its key's working version through a PureData host,
conflicts early on a stale base revision, runs its handlers, and commits
only if they succeed; a failed event leaves documents and states unchanged.
Replies lend payload or document extents, and a document reply is copied
before commit. pure_tree_data implements the host on tree store drafts, and
pure-edit-module offers the document CLI contract of pure-edit from a module.
test-module adds document semantics on an in-memory host (not found, create,
conflict before bounds, limits, short payloads, busy commits, stable replies,
require, state rollback), typed verifier rules, and 20,000 damaged message
modules run safely under ASan/UBSan.
|
|
|
Pure now owns the format its toolchains target, as the JVM owns class files.
A v1 module carries f64 states, key inputs, atomic event handlers and pure
views. pure_module_load checks sizes, names, keys, operands, forward-only
branches, reachability and stack heights at every join before anything runs,
so execution needs no stack checks and each event is bounded by its handler
length. PureApp runs events on a pending copy and replaces modules keeping
states by name, without allocation. Semantics match the workbench engine,
including IEEE minimum/maximum on signed zeros.
test-module covers behaviour, atomic faults, 26 rejection checks and 20,000
damaged modules under ASan/UBSan; pure-run is a JSON test host.
|