.Dd April 5, 2026 .Dt THALATTA 5 .Os . .Sh NAME .Nm thalatta .Nd procedural graph description language . .Sh DESCRIPTION .Nm is a language used to generate attributed digraphs. It is intended to be minimalist, yet provides enough syntax for convenient graph construction. .Nm has C-like syntax, but introduces some new features as well, while removing unnecessary ones for graph context. This manual shows only where .Nm differs from C. . .Ss Values There are only 3 types in .Nm : arrays, integers, and nil. . .Pp Arrays are constant: a new one is allocated on operations such as assignment, concatenation etc. . .Pp Integers store not only user-defined numbers, but also node and module identifiers used by an implementation. These identifiers are used by the implementation and should not be edited by the programmer. . .Pp Nil type is the one that does not hold anything. It can be used as a placeholder. .Nm has a predefined variable .Dv nil of the type of the same name. . .Ss Operations .Nm has operations very like in C, excluding function calls, structures, and some others. Instead introduces some new ones: .Bl -tag -width Ds .It Connecting .Nm is a graph description language. The .Ic <- operator is used to connect a graph. Its precedencence is like of an addition. It creates a connection from right to left, returning the left operand, so .Bd -literal -offset indent -compact a <- b <- c; .Ed connects both b and c to a, not b to a and c to b. . .Pp Connecting a node to an array means connecting it all the cells from the array. Connecting array to array is possible only if they are isomorphic, i.e., they are of the same length, and all subarrays are of the same length recursively, if applicable. . .It Generation .Nm lacks array initializers like in C. Instead, there is a prefix operator .Ic Bq Va expr , where .Va expr must be an integer. This will allocate an array of size .Va expr . For each array cell of depth n there is a variable starting with @ followed by an nth letter of the alphabet storing current depth's index. . .Pp For example, this code: .Bd -literal -offset indent -compact [2][3]node(@a, @b); .Ed . .Pp generates 4 nodes with properties as in binary count: .Bd -literal -offset indent -compact 0 0 | 0 1 | 0 2 | 1 0 | 1 1 | 1 2 | .Ed . .It Slicing Besides simple indexing, .Nm has a postfix operator .Ic Bq Va l Ic : Va r that returns a slice of given array from .Va l inclusive to .Va r non inclusive. Both bounds are clamped to the array limits. . .It Concatenation The .Ic >< operator is used to concatenate 2 arrays. Its precedence is like of a multiplication. . .It Exponentiation Uses .Ic ** operator, is done before multiplication and right-associative. .El . .Pp .Nm has also the prefix operator .Ic len to get an array length, and the prefix operator .Ic assert aborting the execution if its argument evaluates to zero, and returning it otherwise. . .Ss Nodes Nodes are created using the following syntax: .Bd -literal -offset indent -compact node(prop1, prop2); .Ed where properties are numbers. This will return a number \(em a unique node identifier. . .Ss Foreach The .Ic foreach construct is used to iterate over elements of an array. It recursively walks through its argument, for each cell executing its body with variables .Va @0 .Va @1 \&... set just like the generation operator does. In addition, it sets the .Va @ variable to the current element. . .Pp This code ensures that every number in array .Va arr is greater than zero: .Bd -literal -offset indent foreach (arr) { assert(@ > 0); } .Ed . .Ss Modules Instead of functions, .Nm has modules. A module with parameters .Ar a , .Ar b can be defined like that: .Bd -literal -offset indent mod (a, b) { } .Ed It is possible to assign this to a variable. . .Pp Then, to use this module later, there is .Ic with statement, that first evaluates the module and then executes its body, with parent scope set to the scope of the module. . .Pp This code tests whether the variable x is positive, though in somewhat weird way to show the module usage: .Bd -literal -offset indent foo = mod(a) { b = a; } with foo(x) { assert(b > 0); } .Ed . .Sh SYNTAX This is the syntax of .Nm expressed in ABNF: .Bd -literal -indent offset code = *(stmt) stmt = comp / for / foreach / if / with / expr ";" / break / continue continue = "continue" ";" break = "break" ";" with = "with" expr "(" [*(expr ",") expr] ")" stmt if = "if" "(" expr ")" stmt ["else" stmt] foreach = "foreach" "(" expr ")" stmt for = "for" "(" [expr] ";" [expr] ";" [expr] ")" stmt expr-assign-oper =/ "|=" / "^=" / "=" / ">>=" / "<<=" / "%=" expr-assign-oper = "+=" / "-=" / "*=" / "/=" / "%=" / "&=" expr-assign = expr-cond [expr-assign-oper expr-assign] expr-cond = expr-or ? expr : expr-cond expr-pref = expr-post / ("assert" / "len" / "~" / "!" / "--" / "++") expr-pref expr-post = expr-primary *("--" / "++" / "[" expr [":" expr] "]") expr-mod = "mod" "(" [*(id ",") id] ")" comp expr-node = "node" "(" [*(expr ",") expr] ")" expr-primary = NUMBER / id / "nil" / expr-node / expr-mod / "(" expr ")" comp = "{" *(stmt) "}" expr = expr-assign .Ed . .Sh EXAMPLES This snippet creates a graph of a CLA adder: .Bd -literal -offset indent and = 0; xor = 1; add = mod(a, b, c) { assert(len(a) == len(b)); l = len(a); out = [l]node(xor); { p = [l]node(xor) <- a <- b; g = [l]node(and) <- a <- b; out <- p; foreach (out) { @ <- (node(and) <- p[0:@0] <- c); for (i = 0; i < @0; ++i) @ <- (node(and) <- p[i+1:@0] <- g[i]); } } }; first = [8]node(xor, 0); second = [8]node(xor, 1); carry = node(xor, 2); with add(first, second, carry) { } .Ed . .Sh SEE ALSO .Xr thac 1 . .Rs .%A B. W. Kernighan .%A D. M. Ritchie .%D 1978 .%B The C Programming Language .Re . .Rs .%A D. Crocker .%A P. Overell .%D January 2008 .%R RFC 5234 .%T Augmented BNF for Syntax Specifications: ABNF .Re . .Sh AUTHORS .An Nakidai Perumenei Aq Mt nakidai@disroot.org