SPREADSHEET
Paradigm(s) | concurrent,dataflow,grid |
---|---|
Designed by | cyanidesDuality |
Appeared in | 2021 |
Computational class | Turing complete |
Reference implementation | On Github |
Major implementations | None |
Influenced by | Psi |
File extension(s) | .sprd |
SPREADSHEET, devised by cyanidesDuality in 2021, is a grid-based concurrent event-driven language inspired by Psi.
Memory model
All data and instructions in a SPREADSHEET program are associated with cells in a full planar grid. Every integer lattice point in the plane is the coordinate of a cell. Each cell contains a command and an expression. Expressions are evaluated to values as needed.
Data types
Every cell can contain one of four data types: number, string, numeric 2-tuple (or complex number), or None. These are all equivalent to and represented in the same way as their corresponding Python types.
Number: 10 Number: -10 Number: 10.5 NOT a Number: .5 String: "beans are cool!" String: 'hello world' NOT a string: "oops' NOT a string: 'oops', i did it again' String: 'yay,\' fixed now' Tuple: (10,10) Tuple: (1.3,-4) Tuple: (1.963,100.37252) None: None
Syntax
Every line of a SPREADSHEET program is of a specific format:
V<coordinate>: <expression> S<coordinate>: <coordexpression> <= <expression> F<coordinate>: <coordexpression> <= <expression> I<coordinate>
Here, <coordinate> is an integer 2-tuple pointing to a cell in the program. <coordexpression> is an expression that evaluates to an integer 2-tuple. <expression> is any legal expression constructed of the available types and any of the operators listed in the Expressions and Operators section.
Comments begin with //
.
Semantics
In every update step, a new grid state is evaluated from the old grid state, and then the new grid replaces the old one. If cell (0,0) has been assigned by this update, its contents is printed to stdout before the cell is deleted.
The cell-type markers in cells determine how they are used during execution. These are the markers:
- The V marker defines an expression to be evaluated.
- The F marker takes two expressions, and sets the cell denoted by the first expression to a string containing a valid line of SPREADSHEET code.
- The S marker sets the cell denoted by the first expression to a V command containing the evaluated value of the second expression.
- The I marker takes input from the user.
Cells marked F and S are executable, and will all be executed in order of increasing distance from (0,0) and, in case of a tie, increasing value of atan(y,x) (e.g. counterclockwise from the positive x direction). If a cell tries to dereference a cell that has not yet been evaluated this update round, that cell is evaluated immediately. If a referenced cell has already been evaluated, the memoized value is returned without reevaluating. No cell is evaluated or executed more than once per update step. The execution order indicated determines in which order I cells are evaluated and therefore which inputs each one gets.
If, through this process, no grid cell is updated, execution halts. Thus, overwriting all executable cells is a straightforward way to halt a program. Note that since (0,0) is deleted at the end of each cycle (and therefore never changes), merely writing to output does not count as a grid update for the purposes of this determination.
Expressions and Operators
SPREADSHEET expressions are defined using the following post-fix operators along with literals of the types listed above. If some behaviour is not specified for this table, it returns None.
Operator | Arity | Function |
---|---|---|
+ |
2 | Performs addition between numbers/2-tuples, and concatenation between strings. |
- |
2 | Performs subtraction between numbers/2-tuples. |
* |
2 | Performs scalar/complex multiplication between numbers/2-tuples, and scalar vector multiplication between a number and a 2-tuple. Additionally, string number * returns string repeated number times, like in Python.
|
/ |
2 | Performs divison between numbers/2-tuples, and scalar vector division between a number and a 2-tuple. |
# |
1 | Absolute value of numbers, component-wise absolute value of 2-tuples, length of strings. |
£ |
1 | Sign of numbers, component-wise sign of 2-tuples. |
% |
2 | Modulus between numbers, component-wise modulus between 2-tuples. |
^ |
2 | Exponentiation between numbers |
? |
3 | A if C else B . For this statement, use Python truthiness rules. C is evaluated first, and then only the required argument is evaluated.
|
= |
2 | Python == . Returns 0 or 1.
|
< ,> ,≤ ,≥ |
2 | Performs magnitude comparison. Takes in numbers, returns 0 or 1. |
~ |
1 | Subtracts numbers from 1, reflects 2-tuples through the origin. |
$ |
1 | Returns the value of the cell at the input 2-tuple; evaluates it if needed. If the cell has no value, it returns None .
|
x ,y |
1 | Gets x-coordinate or y-coordinate of the input 2-tuple. |
C |
2 | Coerces the type of A to the type of B ; see table below.
|
T |
2 | Builds a 2-tuple from two numbers. |
X |
3 | Takes two numbers x and y and a string z and returns the slice z[x:y] from the string bounded by those indices.
|
@ |
0 | Return the coordinates of this cell. |
Here is a table of values for the C operator:
From | To | Method of conversion |
---|---|---|
Any | Same type | Identity |
Number | String | Format as decimal string |
Number | 2-Tuple | Create 2-Tuple containing the number twice |
String | Number | Attempt to parse string as base 10 number |
String | 2-Tuple | Attempt to parse string as 2-tuple containing base 10 numbers |
2-Tuple | Number | Compute magnitude as complex number (Pythagorean sum) |
2-Tuple | String | Format as string like "(decimal number,decimal number)" |
None | Number | Return 0 |
None | String | Return "None" |
None | 2-Tuple | Return (0,0) |
Any | None | Return None |
Examples
Cat
I(0,1) //no equation S(0,2): (0,0) <= (0,1) $
Explanation: First, the S
command evaluates. The first part of the S
command is the position expression, which here is a single value and thus evaluates immediately. The second part of the command is the value expression, which here is a $
operator called on a 2-tuple. This gets the value at (0,1)
, which has not been evaluated yet. Since this coordinate has an I
command attached to it, it gets input from the user. When the user gives input, the command at (0,1)
evaluates with a string. Then, since the value at (0,1)
has evaluated, the S
command at (0,2)
evaluates. This sets the value at (0,0)
to be whatever the user gave in. The program outputs what the user gave in, and then halts because no equations (apart from the one at (0,0)
, which is ignored) have changed.
Implementations
In Python 3: https://github.com/wompking/spreadsheetlang/blob/main/SPREADSHEET.py