Language specification#
One meaning for every program, on every machine.
This is the normative definition of .vis, version 0.1. Where a tutorial explains, this document decides:
when the two disagree, this one is right. The vocabulary is listed in Vocabulary, the grammar in
Language reference, the functions in Built-in functions and the errors in Errors; those pages are part of this
specification.
1. Conformance#
A program is a text that the rules below accept. Any other text is rejected at compile time with an error of Errors.
The result of a program is the final value of every channel and the series of every measure.
Determinism. The result of a program depends only on its text, the values of its params and the contents of the files it loads. It does not depend on the device, the vendor, the driver, the operating system, the number of devices or the time of the run.
Reference. The value of every operation is the one computed by the reference implementation of Vision (
--device numpy), bit by bit. An implementation, or a device, conforms when it gives the same bits on every case of the conformance kit (vision conformance, see Conformance kit).The words must, must not and is state requirements; for example introduces an illustration.
2. Lexical structure#
Encoding. A program is UTF-8 text. It is normalised to Unicode NFC before it is read, so the same visible text is the same program.
Lines. Line breaks have no meaning: a statement ends where the grammar says it ends.
;may separate statements and is never required.Comments start with
//and end at the end of the line.Names start with a letter (any Unicode letter) or
_, followed by letters, digits or_. Names are case sensitive. Keywords (Vocabulary) cannot be names.Numbers.
42is anintliteral;4.2,.5,2.and1e5arefloatliterals. A literal has no sign:-3is the negation of3. Anintliteral must not exceed 2147483647 (E0502); afloatliteral must fit in float32 (E0501).Strings appear only as file names:
"output/map.png". They have no escapes and end on the same line (E0101).Any other character is an error (
E0102).
3. Programs and names#
A program is a sequence of declarations:
param,canvas,kernel,measure, in any order, and at most onerunblock (E0202).Global names. Params, canvases, kernels and measures share one namespace (
E0302,E0303,E0304). Channels belong to their canvas.Reserved names. Keywords, the names of the functions,
x,y,width,heightandscenariocannot be declared (E0301). In a program with a 3-D canvas,zanddepthare reserved too; in a 2-D program they are ordinary names.Locals (
let,var, the variable of afor) live in their block and the blocks inside it. A local must not repeat a name of the same scope (E0313), a channel of the canvas (E0311) or a name of the program or of the language (E0312).
4. Values and types#
floatis a 32-bit binary floating-point number that is always finite.+,-and*are rounded to nearest, ties to even;/is within 1.15 ULP of the exact quotient, with1 / 0= MAX,-1 / 0= −MAX and0 / 0= 0. A result smaller in magnitude than 2⁻¹²⁶ is 0; a result beyond the largest float is ±3.4028235e38 (written ±MAX), with the sign of the exact result. There is no infinity and no NaN.intis a 32-bit two’s-complement integer.+,-and*wrap around.boolistrueorfalse, the result of comparisons and logical operators. Aboolis not a number: it cannot be stored in a channel (E0409) or used in arithmetic (E0421);select(cond, a, b)andfloat(cond)turn it into a number.Mixed arithmetic. An operation on an
intand afloatconverts theinttofloat./is always real division:7 / 2is3.5.int % intis the remainder with the sign of the dividend (-7 % 3is-1);x % 0is0.Powers.
x ^ n, with an integer literalnfrom 0 to 16, is the exact repeated product and keeps the type ofx. Any other power ispow(x, n), afloat.Conversions.
int(v)truncates towards zero and saturates at the limits ofint;float(v)is exact forbooland rounded forint.Functions are defined in Built-in functions, each with its type rule and the values at the edges of its domain. Outside its domain a function returns the value at the edge (for example,
sqrt(-1)is0).
5. Canvases#
canvas name[w, h] edge e { channels }declares a grid ofw × hcells;canvas name[w, h, d]a volume ofw × h × dcells (dat most 65535,E0508). Sizes are constant positive integers (E0503–E0507): numbers, params and arithmetic on them.A channel holds one value per cell:
f32(the default) ori32. Every channel starts at 0.The edge decides what a read outside the canvas gives:
clamp(the default) the nearest border cell,wrapthe cell on the opposite side,zerothe value 0. It applies to every axis.Cell
(0, 0)is the top-left cell;xgrows to the right,ydownwards,zfrom the first layer.
6. Kernels#
kernel name on canvas { statements }defines one step of every cell of the canvas.Execution model. When the run block calls a kernel, its statements run for every cell. Every cell starts from the same state, the state before the kernel. When every cell has finished, the channels the kernel assigned take their new values, all at once; the other channels keep theirs. The order in which the cells run has no effect on the result.
Reading. Inside the kernel:
a channel name (
t) denotes the value of this cell in this run of the kernel: it starts as the state before the kernel and follows the assignments of the kernel;an indexed read (
t[x - 1, y], and alsot[x, y]) always reads the state before the kernel;other.u[i, j]reads a channel of another canvas, in the state before the kernel;x,y,z,width,height,depthandscenarioare given by the canvas and the run (E0412).
Writing (the pixel rule). A kernel assigns only channels of its own canvas (
E0413), by name, and only for its own cell:t[x + 1, y] = …is not a statement (E0210). Hence there are no data races.Statements.
let(immutable,E0407) andvardeclare locals, which keep the type of their first value (E0408);name = exprandname op= exprassign;if/else if/elserun a block where a condition holds (E0404);for i in a to bruns a block fori = a … b, both ends included, with bounds that are the same in every cell (E0405), andicannot be assigned (E0406).An
i32channel takes onlyintvalues (E0410); afloatbecomesintonly withint(...).
7. Expressions#
Precedence and associativity are those of Vocabulary; parentheses group. Comparisons do not chain (
E0213).Operands are evaluated as values; there are no side effects inside an expression, so the order of evaluation cannot change a result.
rand(ix, iy, seed)is a pure function of its three integers: the same arguments give the same number in every cell, step and run. A new draw at every step needs an argument that changes, such as a step counter.
8. Measures#
measure name = f(value) on canvas [where condition]reduces the canvas to one number withsum,mean,min,max(of a number,E0402) orcount(of a condition,E0401).wherekeeps the cells where its condition holds (E0403).The value is evaluated for every cell like an expression of a kernel, on the current state.
sumandmeanare computed with about 44 bits of precision; every reduction has a fixed order, so its value is part of the deterministic result.Each call of the measure in the run block appends one value to its series. When no cell is selected the value is none (shown as
no pixels).
9. The run block#
The commands run in order: a kernel name runs one step; a measure name appends one value;
repeat n { … }runs its commandsntimes (n ≥ 0, constant,E0509).scenarios n { … }runs its commandsntimes (n ≥ 1,E0510), every time from the state at the start of the block, withscenario= 0, 1, …, n − 1 in kernels and measures; outside the blockscenariois 0. After the block the state is the one left by the last scenario. The block does not nest (E0511).load canvas.channel "file" [nodata v]replaces the state of a channel with the data of the file (section 10).printandsaveshow or write the current state; they do not change it. A measure must have been taken at least once before it is printed or saved (E0601).A kernel or measure named in the run block must exist (
E0316).
10. Data#
loadreads.npy,.csv/.txt,.asc(Esri ASCII grid) and.png. Row 0 of a file is rowy = 0of the canvas (the top, the north of a grid). A 3-D.npyis[depth, height, width].The size of the data must be the size of the canvas (
E0710).Values are made canonical as the device stores them: a magnitude below 2⁻¹²⁶ becomes 0, −0 becomes +0, ±infinity becomes ±MAX. NaN, and the
NODATA_valueof an.asc, are cells without data: they are an error unlessnodata vgives the value that replaces them (E0704).An
i32channel loads only integers that fit in 32 bits (E0711).The SHA-256 of every loaded file is part of a receipt of the run.
11. Errors#
Every error of a program is found before it runs, except those of data files (family E07). An error has a stable code (see Errors); a code keeps its meaning across versions, while its message may improve.
A program with an error does not run.
12. Versions and compatibility#
The language has a version
MAJOR.MINOR(this document: 0.1), separate from the version of the package.Before 1.0, a minor version may change the language; every change is listed in the release notes, with the way to update a program.
From 1.0 on:
a minor version only adds: every valid program keeps its meaning and its bits;
a change that alters the result of a valid program needs a new major version, and is announced one minor version before, with a warning.
Never, in any version:
an error code changes meaning;
the result of a program changes between devices.
Changes to the language are proposed as a Vision Enhancement Proposal (VEP). A VEP states:
the motivation;
the exact change to this specification;
the new error codes;
the conformance cases that check it;
its effect on existing programs.
It is accepted only with its specification text, its tests and its conformance cases.