click a cell: select it click it again, or ENTER, or EDIT: type a value or a formula arrow keys: move the selection X: clear the selected cell D or DEPS: dependency overlay — precedents blue, dependents magenta RECALC: force a full recalculation of the whole book CLEAR: empty the sheet DEMO: switch between the budget model and the circular-reference test drag a scrollbar: pan the 12 × 30 sheet under the 6 × 12 viewport Formulas start with =. Supported: - + - * / ^, unary minus, parentheses - comparisons = <> < > <= >=, which return 1 or 0 - references A1, ranges A1:C4 - SUM AVG MIN MAX COUNT over a range, IF(c,a,b), ABS SQRT INT, ROUND(x,n), MOD(a,b) - case-insensitive, whitespace ignored Errors are reported in the cell in red and named in the formula bar: #CIRC! #DIV/0! #NAME? #REF! #SYNTAX #VALUE!.
A working spreadsheet in Scratch: A1-style references, real formula evaluation, and a real dependency graph underneath — topological recalculation with circular references detected rather than hung. THE INTERESTING DECISION Evaluating =A1+B2*2 once is the easy half — it is the same tokeniser → shunting-yard → RPN stack machine that GRAPHER uses, extended with references, ranges and multi-argument functions. What makes it a spreadsheet is that when A1 changes, everything downstream must recompute **in an order where each cell's inputs are already final**. Compute the GROSS total before the NET it sums and you display last edit's number. So the engine keeps a real dependency graph. One pass over the compiled RPN emits an edge for every reference — ranges expanded cell by cell, so SUM(D2:D5) is four edges — bucketed by the precedent cell in a linked list (chead[cell] / e_next[edge]), which makes "who depends on this cell?" an O(out-degree) walk and works identically whether the precedent is a formula or a plain number. Kahn's algorithm over in-degrees then produces the evaluation order, and editing a cell evaluates only the forward closure of that cell, walked in that order. Clearing B2 in the demo model recalculates 13 of the 22 formulas, in the order D2 E2 D11 D10 D9 D8 D7 F2 E7 F8 F7 B13 B12 — which the status bar prints, because that is the claim and it should be inspectable. The part worth reading the code for is what happens to the cells Kahn cannot emit. Those are not all the same thing, and the engine says so. A node that is reachable from itself within the leftover set is a genuine circular reference and gets !; the rest are merely blocked by one, so they are removed from the graph, re-sorted, and evaluated normally — whereupon they inherit ! through ordinary error propagation, which is what Excel shows and is a different fact about the sheet. Press DEMO for the test case: B3/B4 are a 2-cycle, D3/D4/D5 a 3-cycle, H3 refers to itself, F3/F4 are clean formulas poisoned by B3, and column B rows 6–10 is a chain that must still compute (it does: 1, 2, 3, 4, 10). Six cycle members, two casualties, five healthy cells. That is not just tidiness. A func in goboscript runs *without screen refresh*, so a cyclic recalculation would not be slow — it would freeze the project with no way out short of reloading the page. Detection is the only thing standing between a spreadsheet and a hang. HONEST LIMITATIONS - 12 columns × 30 rows, six columns visible. Column letters are single (A–L). The grid scrolls but the sheet does not grow. Columns are 72px wide rather than a denser 55 on purpose: the stage is 480×360 and cannot be enlarged on scratch.mit.edu, so fitting more columns would have meant text too small to read at 1x. - Range arguments must be literal. SUM(A1:A10) is fine; SUM(A1:INDIRECT(...)) is not, and there is no INDIRECT. A range is folded into a single token at tokenise time, which is what lets the evaluator stay a plain number stack; the type flag on that stack is there so A1:A3 + 1 reports ! rather than quietly adding two encoded corner indices. - IF evaluates both arms. An RPN stack machine has no way to skip a subtree, so IF(A1<>0, 1/A1, 0) still divides by zero when A1 is 0. Excel short-circuits; this does not. All original - code, art and sound. See Inside is open.