| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
state, record, message, output and argument fields, lets, views, keys
and slices can be i64 (Pure 016 stage 2). An integer literal becomes
an i64 where the other side of an operation, a comparison or an
assignment is one; a literal-only side follows the other, found by
compiling it on trial and rolling back. + - * and negation fail the
event with overflow, / and % floor, and i64(x) and number(n) are the
only way between the two, so a mix is a diagnostic that says so.
The check adds 18 i64 diagnostics, i64 accepted forms (with a 30-deep
chain that must stay linear), an event-by-event program past 2^53
and at the edges, and i64 values in the generated programs.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A condition was any number, non-zero being true: done was a number field,
a view showed 1 for true, and done + 1 was no type error. Now bool is its
own type (Pure 016, module format v6):
- true and false; comparisons, text comparisons, has and ! && || give a
bool. Bools are equal or not; they are no numbers and have no order.
- if, conditional expressions, require, where (folds, walks, filtered
tables) take a bool. Given a number, the diagnostic says how to make
one: "if takes a bool, not a number: compare it, as in n != 0".
- Bool states (state on = false), record fields (done = false), message,
output and argument fields (ok: bool), lets, views and columns.
Interpolation writes true or false. A list is not keyed by a bool.
- The examples' flags are bools (charge's holding, toggle's visible,
tasks' done).
Checks: 20 bool diagnostics, a form using bools everywhere, an app whose
every output shows true and false (states, items, views, columns, text)
and whose replacement turns a number into a bool and back. Models hold
bools and compare them strictly: Python's True == 1 no longer hides a 1
where a true belongs. Generated programs are typed, numbers and bools.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Adding one field to the board two nodes share (Pure's research 105)
still meant the record, the output, three sends and the code applying
what the other node sent: the sends and the apply named every field.
..source, last in a record value's or a send's braces, gives the fields
not written from the source's fields of the same names: an item (an
index, a let, the item a for walks, list[key]) or the handler's message
(grouped fields by their paths). A record value gives what the source
lacks its default; a send still needs every field. list[i] = Record {
... } sets every field of the item, all of them given; a keyed list's
key does not change, so a value with another key fails the event
(limit) and changes nothing.
Both are the fields written out: the checks compare the modules byte
for byte, and run the key rule in pure-run. Seven diagnostics: a spread
not last, a source that is no item nor this handler's message (also
another handler's message), a spread inside a send's group, a send
field left empty, a whole item missing a field, a value that is no
record. The board now sends { ..at } and applies cards[k] = Card {
..remote }: a new field is written in two places, the record and the
output.
|
| | |
|
| |
|
|
|
|
|
|
|
|
| |
list[low .. high], as a fold's or a for's list, is the items whose keys
are from low up to before high (a list keyed by a number), read by key:
distinct(l.item for l in lines[o * 16 .. o * 16 + 16] where
stock[l.item].quantity < t) reads one order's lines, whatever its test
does outside them. It compiles to Pure's sliced folds and walks; an empty
for over a slice still computes its keys. Two diagnostics and an app of
slices are checked.
|
| |
|
|
|
|
|
|
| |
distinct(value for item in list [where condition]) counts the different
values the included items give, compiled to Pure's fold of kind 5 (SQL's
count(distinct ...)). An accepted app walks and folds a keyed list in a
range of its key (where l.id >= start && l.id < start + 16), which Pure
reads by key.
|
| |
|
|
|
|
|
|
|
|
|
| |
let name = value, in a handler, names a number or an index for the rest
of its block; name = value gives it a new value of the same kind; the
walks and folds inside read it. It compiles to Pure's locals (a slot an
event, 0 when it begins, never saved), a slot a let in a handler, so an
order's loop sums into a let and takes stock through an index let without
finding the item again. A let may not be a declared name, another let in
scope or the walked item, and holds no text. Nine diagnostics and an app
of lets are checked.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
view name(argument: type, ...) = ... declares a view that takes u32,
number, bytes or text arguments, read by name in the view, in a table's
filter and columns and in the folds inside them (compiled to FIELD of an
arguments input named name.args that names its view, Pure's kind 6). A
host gives them as the request's query: GET /views/balance?aid=42, and a
table pages as before with from and count. A query compiled with aup
query may take arguments too.
An argument's name may not be a state or another declaration, nor the
table's row, nor from or count (which page a table). Eight diagnostics and
an app of views with arguments (a keyed lookup, a fold, a text, a table
filtered by two of them whose column folds with one, a handler's fold
reading its message) are checked.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
for item in list [where condition] { ... } runs its block in a handler
once for every item the list has, in order, the item an index of the list
(read, changed, removed: a removed item does not skip the next). It
compiles to Pure's EACH; a fold inside reads the walk's item as a fold in
a column reads its row. A for adds nothing to the list it walks, holds no
other for and does not reply, so it ends.
A message field may be a list of a record (lines: list of Line): its rows
arrive as a JSON array of objects and fill a list of their own, named
order.lines in the module, which the handler walks, folds and counts
(order.lines.count) and which is emptied when the event ends. So a
transaction over many rows (an order taking stock line by line, all or
nothing) and a bulk insert are one event. An output sends no rows.
Nine diagnostics and an accepted app (rows in a group, where, a fold over
the rows reading the walk's item, a walk that removes) are checked.
|
| |
|
|
|
|
|
|
|
|
| |
now is the time of the event a handler runs for (milliseconds since
1970, UTC), which a host gives and a script can replay; views cannot read
it. input tick = every 1 second declares a timer (ms, second, minute or
hour; 1 ms to a day). floor(x) and x % y, taking the divisor's sign as
Python does, take times apart. Checked against a Python model over 3,600
random steps; nine diagnostics.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
state xs: list of R by field keeps its items in that field's order, each
key once: xs.add(R { ... }) places an item (a taken key fails the event
with exists), xs[key] finds one by halving (its field, or its index),
xs.has(key) asks, xs.remove(key) removes. append and insert are refused
on a keyed list, add on another, and a key field is never assigned.
Texts compare with == != < <= > >= by their bytes.
Checked against a Python model over 3,600 random steps with a text-keyed
and a number-keyed list; 13 diagnostics; examples/tally.aup.
|
| |
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
Record v0b as complete: which text syntax exists, what is still missing
(multi-line strings, formats, graphemes, words), the insertion rule for
cursors, and how the text model and parity checks verify it.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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 declares connections and leaves storage, transactions and screen models
to Pure. Interface vocabulary lives in Vega, an aup library, not in the
language. text is one immutable UTF-8 type from a word to a 1 MiB document;
positions are cursors bound to a value that stay on character boundaries and
follow edits, lengths name their unit, and comparison is exact without silent
normalization. Stages v0b-v0d and their acceptance tests are listed.
|