| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
| |
A build records every path it opened or looked for and a digest of the
bytes there, so a rebuild happens exactly when one of them reads
differently: the source, a library (the one with the error too), or a
library appearing where one was searched. A change is built once it reads
the same twice in a row, so a file caught halfway through being written
is never built; the module is replaced whole through a rename.
|
| |
|
|
|
|
|
|
|
|
| |
first(item in list [where condition]) is the index of the first item the
condition keeps, typed as an index of that list: at = first(...), a field
through first(...).title, or its .position. With no such item a view has
no value and a handler fails not_found. A fold's result now takes member
access like a call's. The random model check jumps to the first open
task and shows its position; one diagnostic joins.
|
| |
|
|
|
|
|
|
|
|
|
| |
view open_list = each t in tasks where !t.done { ... } has a row for each
item the condition keeps, in the list's order; the condition compiles to
the table's filter block, generated like a column so it reads the row's
item, and the view entry names the list in the byte after its type. A
count, sum, max or min inside the condition is a compile error, as Pure
refuses a fold in a filter. The random model check now compares a
filtered table too; two diagnostics join.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
count(t in tasks where !t.done), sum(t.points for t in tasks), and max
and min in the same form compile to Pure's FOLD: the value and the where
condition become a block run once per item, as a column of the list, so
views count and add without a copy of the list or a state kept in step.
max(a, b), min(a, b) and fns of the same names stay calls, told apart by
the `for` after the first expression or the `name in` after count(.
Inside the block only its item and states can be read; a parameter of
the fn outside, the enclosing column's row, dt and a fold inside a fold
are compile errors that say why. The checks run 3,600 random steps
against a Python model and add seven diagnostics.
|
| |
|
|
|
|
|
|
| |
`state from: mark in note` is a cursor that stays before text inserted
at its position; `cursor in` goes after it, as a caret does. Everything
a cursor takes, a mark takes too. The notes example's mark is now one,
and its reference model agrees: typing at the mark leaves it in place.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
fn name(params) = value declares one expression, inlined where it is
called: arguments are computed once onto the stack and the body reads them
with PICK, so a fn costs no runtime call and keeps Pure's bound on work.
Parameters take any kind of value; recursion is a compile error.
use name reads name.aup beside the source or from AUP_PATH. A library
declares only fns and uses, sees only its parameters, and is called as
name.fn(...). Diagnostics now carry the file they are in, and the
compiler takes a loader so that sources come from the host.
examples/words.aup is such a library; examples/tasks.aup uses it and still
matches its reference model.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
if c { a } else { b }, with else-if chains, is an expression anywhere a
value goes. Only the chosen branch runs, every branch gives the same type,
and nesting that would pass Pure's limit of 8 value-carrying joins is a
compile error.
view name = each row in list { column = value ... } declares a table with
a row per item; columns read their row as an index of the list. An index
now reads and writes its item's fields directly (at.title, at.done = 1),
so 'position' cannot name a record field.
examples/tasks.aup gains conditional views and a board table and still
matches its reference model; a new check confirms the unchosen branch is
never computed.
|
| |
|
|
|
|
|
| |
Pure now loads only v5 modules, where a view entry's type is one byte
followed by the table it belongs to. Plain views encode as before, so the
output changes only in its magic. The view limit follows Pure's to 64.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
A record declares named number and text fields with defaults. A list of a
record is runtime-owned state, and an index of a list always names one of
its items: it follows its item across inserts and removes and stops at the
ends. Items are read and changed by field (tasks[at].title), appended or
inserted as record values whose missing fields take defaults, and removed
by index. Using an index of another list is a compile error.
examples/tasks.aup matches a Python reference model over 4,800 random steps,
including events that fail on an empty list. Replacing it with a module
whose record gained and reordered fields keeps every item.
|
| |
|
|
|
|
| |
Pure now loads only v4 modules. The new header counts records, which aup
does not declare yet, so the output changes only in its magic.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
aup now emits Pure module v3 and adds text states with string initializers,
cursors bound to a text, text inputs, string literals with escapes and
{interpolation} of numbers and text, cursor distances in chars and lines,
.start/.end, insert/remove, name.line(cursor), .chars/.lines/.bytes on text,
.chars/.line on cursors, and text(bytes)/bytes(text). Replies and replace
accept text as its UTF-8 bytes. Views are numbers or text. Up to 32 inputs.
examples/notes.aup is a small editor. make check replays random typing
(ASCII, Korean, emoji, combining marks, NUL, newlines), moves and deletions
against a Python reference model: 4,800 snapshots of text, cursor, mark and
views match. It also checks escapes and number text, 16 new diagnostics, a
document loaded into text and saved back, and all earlier parity; the
compiler and the Pure executor each pass under ASan/UBSan.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
aup now emits Pure module v2 and adds keyed byte collections
(state documents: bytes by key), message inputs by key with u32 and a
trailing bytes field, on-message handlers, field access, name[key] reads
and .bytes sizes, replace(a .. b, value), reply and require, all checked
for number/bytes types with file:line:column diagnostics.
The document editor and its size-bounded variant are rewritten in aup.
make check runs them through pure-edit-module against pure-edit running the
original editor.pure programs: 1,280 random show/edit/apply operations,
including conflicts, limits, missing documents, budgets and invalid keys,
produce byte-identical stdout, stderr and exit codes, and each CLI reads the
other's store identically. v0a parity with the workbench engine, 33
diagnostics and generated/damaged programs still pass, also with a
sanitizer-built compiler.
|
|
|
aup check/build parse states, key inputs, views and handlers (with if/else
and else-if), resolve names, generate forward-only stack code and encode a
Pure module v1 deterministically. Diagnostics carry file:line:column.
make check loads every module with Pure's verifier, checks determinism, 20
diagnostics and accepted forms, replacement by name, 600 generated programs
and damaged sources (every emitted module verifies), and replays random event
scripts against the workbench Zig engine: 16,667 snapshots across counter,
toggle, charge, else-if and fault programs matched, including 921 failed
events. The sanitizer-built compiler passes the same checks.
|