Syntax

This reference describes intended VKF syntax. Section 0 takes precedence over the later language direction. Examples are future compiler correction targets; this draft does not claim that every construct works in every compiler target.

Bindings and scopes

name: expression declares a binding. .name: expression updates the nearest existing binding; it does not create a missing name. Bindings may be shadowed in an inner scope, but not redeclared in the same scope. Updates describe new values; aliases retain their own previously observed values.

Editable example · Loading compiler…
Console
4
2

Indentation forms a scope. Its last expression supplies its result. Parentheses can group a scope or expression. A bare : returns the local scope as a record. Semicolons separate logical rows while preserving their indentation context. # begins a comment; :: expression writes an ordinary value.

Editable example · Loading compiler…
Console
3

Values and types

FormMeaning
42, 1.5Numeric literals
true, falseBoolean values
nullNo value
num(2,3)Complex value with real and imaginary components
"text"Immediate string
'text'Deferred template
(1,2)Tuple
(1,)One-element tuple; (1) is grouping
(x:1,y:2)Named tuple / record
[1,2,3]Vector
[[1,2],[3,4]]Rank-two vector
[value:n]Repeated value
{"a":2,"b":1}Multiset with counts
value.The value's actual type
value.x, value.0Named or positional member

Primitive type handles include bit, chr, int, num and str. Types are values. Type constructors describe vectors, tuples, records and multisets:

Editable example · Loading compiler…
Console
3
1
7

Unbound generic type names such as T bind from a call. Repeated occurrences require one consistent type. Shape parameters such as n bind independently. [T:n] describes a fixed vector type; [T] describes a vector without a fixed extent. Tuple structure never adds vector rank. Thus [(1,2),(3,4)]_a is rank one, while [[1,2],[3,4]]_ab is rank two.

Functions, calls and specialization

Editable example · Loading compiler…
Console
5
3
6

Parentheses call a function. Square brackets at a call site bind arguments into a callable. Binding every argument still creates a zero-argument callable; () evaluates it. A bare function name remains the unspecialized function.

Editable example · Loading compiler…
Console
11
11

Functions and operators are first-class values. Operator specialization uses named operands: +[b:2] maps a to a+2; -[a:2] maps b to 2-b. Functions may close over values, recurse and have forward declarations. Overloads use the same name with different compatible parameter types.

Runtime positional spilling uses :args, including f(:[1,2,3]) and f(:record). A declaration's ...args:T captures remaining positional arguments; :::named captures remaining named arguments. Call-site spilling uses :, not .... Process forwarding must use the final ordinary call rules; its exact variadic declaration remains undecided.

Bound arguments and structural selectors

Declare parameters in parentheses and bind ordinary named arguments with square brackets at the call site. Alphabetic suffixes select value dimensions; they do not declare or supply a separate sequence of compile-time parameters.

Editable example · Loading compiler…
Console
7
4

The former bracketed parameter declaration syntax is removed in this preview. Exact identifiers such as E_pot, x_min and particle_count take precedence where applicable. Underscores alone do not prove a structural suffix.

Named and anonymous dimensions

Named dimensions are single alphabetic characters. Digits are coordinates or values, never dimension names. Anonymous axes are positional and align only with anonymous axes. Equal extents do not make named and anonymous axes equal.

Editable example · Loading compiler…
Console
[[19, 22], [43, 50]]
[1, 4]

Names align by identity. A*B has axes i,j,k; multiplication never silently contracts j. sum_j explicitly removes it. Section 0 permits repeated names in a selection such as A_ii to select equal coordinates / a diagonal; repeated structural function selectors are invalid. Distinct stored dimension identities are unique. Aligned sizes must be compatible.

Without ..., a naming suffix covers the entire vector rank. A rank-two value requires two names. One structural ellipsis explicitly retains any remaining anonymous dimensions; it may expand to zero dimensions:

Suffix on a rank-five valueAxes
_i...k(i,_,_,_,k)
_...ij(_,_,_,i,j)
_ij...(i,j,_,_,_)
_i...jk(i,_,_,j,k)

Use ASCII ...; only one structural ellipsis may occur. Anonymous dimensions align positionally among anonymous dimensions; they are not silently remapped onto named axes.

Lifting and structural calls

Ordinary functions lift over compatible argument dimensions, independently of their declarations. Tuple and record structure remains separate from vector dimensions. Whole-container overloads take precedence when they match.

Editable example · Loading compiler…
Console
[0, 2, 3]

f_i(A_ij) passes _i intact into f and lifts over _j. The selected axis does not have to disappear: the function result determines its structure. f_ij(A_ijkt) selects both i and j and lifts over the remaining axes.

Operators

FormMeaning
+ - * / // % ^Elementwise arithmetic with dimensional alignment
= ~= ~ < <= > >=Elementwise comparisons and logical operations
== !=Whole-value comparison
A &_i BConcatenate along dimension i
A & BConcatenate when one dimension can be inferred
f & gComposition: apply f, then g
f+g, f^2Pointwise operations on compatible functions
+(a,b), *(a,b)Call an operator as a function
=>Implication outside a matching arm
->Function / return type

Implicit multiplication is permitted where unambiguous, such as 2x, 3(x+1) and 2sin(x). Adjacent variable names form an identifier: xy is one name, so write x*y for variable multiplication. R[L] in a domain context is a domain qualification, not implicit multiplication.

Index access and ranges

Index access uses .(). A numeric index selects a coordinate; a range selects a span. Bounds violations are errors, including an element access on an empty vector. Evaluate the base and index expressions in their defined source order.

Index tokenMeaning
:Preserve one existing dimension
...Preserve all remaining dimensions
::Insert one size-one dimension

For shape (3,4), a.(::,:,:) has shape (1,3,4), a.(:,::,:) has shape (3,1,4) and a.(...,::) has shape (3,4,1).

Ranges are inclusive. ..0 contains zero, ..10 contains zero through ten, a..b includes both endpoints, and .. is unbounded. Vectors are lazy by default; finite demand can consume an infinite value. Empty structural work performs no element operations; it is not an ordinary descending range.

Folds, recurrence and composition

Editable example · Loading compiler…
Console
6

reduce_i(f,A_i,initial) is an ordered fold with exactly one binary reducer, one input collection and one initial accumulator. It calls f(f(f(initial,A_0),A_1),A_2).... There is no variadic collection-fold interface. Parallel reassociation requires permission from the reducer's numerical contract.

sum_i(A)=reduce_i(+,A,0), prod_i(A)=reduce_i(*,A,1) and chain_i(F)=reduce_i(&,F,id). Empty calls yield sum()=0, prod()=1 and chain()=id. Multiple reduction selectors remove only those dimensions.

For a recurrence with several varying inputs, specialize first:

Editable example · Loading compiler…
Console
0.052808601763274413 + 0.22361225622108541i

Pipes and loop coordinates

>> passes values into a scope; $ is the current value. Flat pipes progress; indentation or parentheses nests them. Outer pipe values use $$, $$$. Selected named coordinates use $i, with outer coordinates such as $$i.

Editable example · Loading compiler…
Console
0
0
10
1
1
20

$0 is the outermost loop's iteration index; $n selects the loop at literal nonnegative integer depth n. Named and anonymous loops both count. Multiple selected axes introduce loops in selector order. Scalar scopes do not add a loop. Indices count positions from zero, even for offset or descending ranges; they are read-only and scoped. Sibling loops reuse the same depth.

Conditions, matching and errors

FormMeaning
condition? expressionConditional expression / indented suite
condition?!Assertion, optionally followed by a message
value ?? with pattern => resultMatching expression
Bare final matching rowFallback arm
condition?>Conditional loop
value??>Repeatedly evaluate and match
@:Return a value immediately
@Return null
@>Continue the nearest loop / pipe
@|Break the nearest loop / pipe
error!Raise a typed error value
expression!?Catch errors with matching arms
Editable example · Loading compiler…
Console
many

Error construction alone does not raise. Only error types and error values may be raised; unmatched errors continue outward. In a pipe block, @: returns from that element rather than the enclosing function.

Editable example · Loading compiler…
Console
message

Nominal types, reflection and modules

Uppercase constructors create nominal types. A spilled backing value can carry local overrides and extensions. Compatible operations reconstruct through the constructor; impossible reconstruction is an error. Distinct nominal types do not implicitly unify because their backing values happen to match.

Editable example · Loading compiler…
Console
2

Postfix . returns the actual type. For a closed record, [:record] and [:record.] return accessible field names in declaration order; (:record.) retains record field types. record.(name) selects a named field. Operators and dotted access may be overloaded with ordinary typed functions.

.name names a module handle. Bind an alias with m:.math, or spill its exports with :.math. Local modules use the same import model. Lexical shadowing does not replace an already captured qualified module handle.

Symbolic domains and calculus

x:R declares a real symbolic domain; z:C declares a complex domain. Domain information is authoritative and distinct from a variable's spelling. Ordinary evaluation, symbolic reasoning, transforms and compile-time evaluation share semantic values. simplify(f) preserves domain assumptions and singularities; executing a simplified expression requires a justified numerical policy.

f'x and f''xy are exact function-variable differentiation transforms; finite differences use separate operations such as diff_i(A). integ_x(f) and integ_xy(f) select formal variables, not structural axes. An absent differentiation dependency yields zero; integration may introduce an absent variable.

Editable example · Loading compiler…
Console
6
9

Integration parameters are ordinary callable parameters. General from and to bounds can be overridden by variable-specific bounds such as x_from and y_to. Specialization does not evaluate the integral by itself.

Physical domains and units

Domain[Dimension] qualifies a numerical domain with a physical dimension: R[L], R[L/T], R^3[M*L/T^2] and complex domains use the same mechanism. R and C alone are physically dimensionless.

The seven SI base dimensions are L M T I Θ N J. Rational compile-time exponents, such as L^(1/2), are permitted. Units contain a physical dimension, scale to canonical SI, display symbol, LaTeX symbol and optional quantity kind. Named units such as newtons do not introduce new base dimensions.

Editable example · Loading compiler…
Console
230 cm
[100, 200, 300] cm

Addition, subtraction and comparison require compatible dimensions. Addition and subtraction inherit the left operand's preferred unit. Multiplication and division combine dimensions algebraically. Exponents must be dimensionless; dimensional bases normally require compile-time-known exponents.

A vector has one unit for the whole value. Conversions preserve the physical quantity and change its preferred representation; canonical SI backing remains available to computation. Unit display is automatic. Its priority is explicit .to(...), configured preference, inherited arithmetic preference, automatic SI prefix, then canonical SI. The complete configuration surface is documented when finalized; this reference does not invent additional configuration syntax.

rad and deg are physically dimensionless angle units; radians are canonical. sin, cos, exp, ln and log require dimensionless inputs. For example, exp(num(0,1)*180deg) represents Euler's relation and returns ordinary dimensionless output. Angles are not an eighth base physical dimension.

sum, mean, min and max preserve physical dimensions; variance squares them and standard deviation restores them. Differentiation divides by the variable's dimension; integration multiplies by it. Ordinary printing, LaTeX and plot labels consume the same unit information.

Strings and templates

Double quotes interpolate immediately; single quotes defer substitution. $x selects a value, $x.1f formats it, $x.0.1f accesses a member before formatting and $x.$format selects a dynamic format. .format(...) follows ordinary vectorization and accepts spilled named tuples.

Editable example · Loading compiler…
Console
[1.2, 4.6]

Geometry, views and physics

The later integration direction gives u,v,w connected-topology meanings, t time, c components and m reference-member slots. It does not override Section 0's ordinary dimension alignment and structural-call rules. Other letters are generic grouping dimensions.

p_uc, p_uvc and p_uvwc describe connected curves, surfaces and volumes. Explicit topology uses reference values: edge_bm can reference vertices grouped by i without aligning b with i. Subsets likewise carry references into a parent group; sparse properties need no dense null entries.

Properties keep their names; supplied values carry their dimensions: frame.add(p:p_ic) and world.add(p:p_ic,v:v_ic).

OperationMeaning
set(...)Change persistent configuration
add(...)Create one layer
push()Freeze / push the composed state
append(...)Add and push
show()Display
plot(...)Append and show

Frame layers render data; world layers may evolve physical state. Laws are ordinary functions; Embeddings map state into perception. Without _t, p, v and a provide initial state. With _t, they prescribe motion. Precedence is prescribed position, velocity, acceleration, then Laws. Prescribed degrees of freedom act as kinematic constraints during physical interaction.

Camera/view configuration can vary over a grouping dimension while geometry is invariant. Styles, colormaps and interpolation are ordinary properties and functions, including structural suffixes such as jet_i and cubic_t. Side-specific limits override the corresponding side of combined limits. Symbolic plotting uses the same API; relations denote boundaries or regions and rendering adapts to geometry, zoom and discontinuities.

Event and I/O concurrency

The .concurrent library supplies process, queue, broadcast and shared. Numeric concurrency is compiler-managed; these constructs coordinate events and I/O using ordinary function call semantics.

FormMeaning
process(worker,10,events:events)Start an isolated concurrent function with ordinary positional/named arguments
p.join()Wait and return the worker result
p.kill()Forced termination
queue()Destructive FIFO queue
q.put(value)Send one item
q.get()Suspend until an item is available
broadcast()Publish to active subscribers
b.subscribe()Create a subscriber stream
shared(value)Share exactly one ordinary value

Each queue item goes to one receiver. Every active broadcast subscriber receives every subsequently published value. Per-producer ordering is preserved.

This finite example uses numeric event tags. The producer runs in a separate process; the matching loop receives ordinary values until the stop tag arrives.

Editable example · Loading compiler…
Console
1
2

The receive expression is evaluated each iteration. The event remains bound in its selected arm. Shared values retain ordinary vector/tuple/record structure; published generations are immutable. Bulk-data descriptors may reference shared backing rather than copying vectors through queues.

Grammar decisions still open

Do not infer new syntax for deterministic external-resource cleanup, publishing shared generations, complete UI bindings/controls, every unit-literal and dimension-suffix precedence combination, or a final process variadic declaration. These remain explicit design decisions. Editor highlighting should use semantic resolution for suffixes and dimension identity, rather than treating every underscore name as structural.