cashscript icon indicating copy to clipboard operation
cashscript copied to clipboard

Bounded loops (2026 network upgrade)

Open mr-zwets opened this issue 1 year ago • 3 comments

There is a bounded loops proposal for BCH.

It would be good to consider the possible syntax this would translate to in CashScript. The bounded loops construction enables indefinite loops, which can easily emulate definite loops.

From the spec:

Naming and Semantics

This proposal is influenced by the BEGIN ... UNTIL indefinite loop construction in the Forth programming language (upon which the rest of the Bitcoin Cash VM is based). This particular construction offers maximal flexibility: definite loops can be easily emulated with indefinite loops, but indefinite loops cannot be emulated with definite loops.

So there would both be a for and a while loop syntax. I got the solidity syntax for both, I think they're the same as in Javascript:

while (i != 0) {
    // do something
}
for (uint i = 1; i <= 5; i++) {
    // do something
}

mr-zwets avatar Dec 13 '24 10:12 mr-zwets

Extra notes: CashScript currently does not have a shorthand increment operator ++ but besides that the solidity syntax of for loops should work as is.

We might want to investigate a simpler syntax for looping x times where x can be a number or a variable like tx.outputs.length

If we don't mind deviating from solidity we could add syntax like:

for i in range(tx.outputs.length) {
    // Access tx.outputs[i]
}

mr-zwets avatar Jan 22 '25 06:01 mr-zwets

Looping Control

If we add looping, we also need to think about looping control with break and continue

here is solidity's looping control:

https://www.tutorialspoint.com/solidity/solidity_loop_control.htm

Looping Syntax Comparison Table

Some brainstorming with AI on new for-loop syntax, for the solidity-draft proposal it referring to https://github.com/ethereum/solidity/issues/10162

Feature Python-style for i in range(n) Solidity-draft for (int value: array) Traditional for Loop for (int i = 0; i < n; i++) JS-style for...of for (int value of array) JS-style forEach array.forEach((value, i) => {...})
CashScript Syntax for int i in range(n) {} for (int value: array) {} for (int i = 0; i < n; i = i + 1) {} for (int value of array) {} array.forEach((int value, int i) => { ... })
Member Easily Accessible ❌ No ✅ Yes ✅ Yes ✅ Yes ✅ Yes (via callback argument)
Index Easily Accessible ✅ Yes ❌ No ✅ Yes ❌ No ✅ Yes (via callback argument)
Solidity-like Syntax ❌ No ❌ No (not yet in Solidity) ✅ Yes ❌ No ❌ No (callback-based)
JS-like Syntax ❌ No ❌ No ✅ Yes ✅ Yes ✅ Yes (callbacks are common in JS)
Ease of Use ✅ Very easy ✅ Very easy ❌ More verbose ✅ Very easy ❌ Requires callback
Avoids New Concepts ❌ No (range is new) ❌ No (: is new in CashScript) ❌ No (++, -- are new) ✅ Yes ❌ No (callback functions are new)
Can Iterate in Reverse ✅ Yes (range(n, 0, -1)) ❌ No (not built-in) ✅ Yes (for (int i = n; i >= 0; i--)) ❌ No (requires workaround) ❌ No (needs .reverse())
Can Iterate in Custom Jumps ✅ Yes (range(start, stop, step)) ❌ No (not built-in) ✅ Yes (i += step) ❌ No (requires workaround) ❌ No (requires custom logic in callback)

Chat GPT's conclusion:

Best combination: Implementing a standard for loop and JS-style for...of (instead of Solidity’s draft : syntax) keeps things intuitive. Adding range(n) is optional for simplicity in definite loops.

mr-zwets avatar Mar 05 '25 06:03 mr-zwets

Just leaving a note after chatting with @mr-zwets and @rkalis on this – CashScript is well positioned to be one of the most-well-adapted languages for CashVM.

Many other projects will ultimately find ways to adapt their existing language/compiler/tooling to target CashVM, producing compiled artifacts at various levels of sub-optimal (introducing workarounds and emulations to expose the kind of API they expect to programs within their artifacts – e.g. how emscripten or Rust produce some consistent overhead in their WASM-compiled artifacts).

Compared to these, CashScript is uniquely unburdened by existing features/patterns that were adapted to non-CashVM environments. Over time, CashScript will be a great place for companies to contribute optimizations and improvements that make it better even than hand-written CashVM bytecode, since compilers can usually attempt a vast number of potential optimizations that raw bytecode authors are less likely to use in perfectly-optimal combination(s). (This is why compilers have long outperformed hand-written assembly in sufficiently complex programs. Hand optimization is great for small components – and designing the actual compiler optimization techniques, but past some level of complexity, only a compiler can apply those optimizations optimally to very large programs.)

At a high level, that means for projects being ported from Rust, LLVM source languages, etc. "just rewrite it in CashScript" could ultimately be the best solution for many projects looking to get to the leanest, most auditable, production CashVM bytecode. And likewise for AlbaDsl or any other BCH-first smart contract systems.

So: counterintuitively, I'd encourage CashScript to start as low-level as possible on new features like this. For loops, that probably means a begin {} until (...) loop – a construction that can be directly translated with zero overhead or emulation tricks. I'd even encourage you to directly use the begin/until syntax – rather than designing your own e.g. loop {} until (...) – since the intention is to offer a lowest-level hook, and CashScript devs recognizing the begin as directly mapping to an OP_BEGIN eliminates some potential for magical thinking. (And note that the Forth world already uses the begin/until syntax – there's a multi-decade history of this syntax being maximally-useful to humans writing the actual source code. E.g. using loop as a keyword is likely to create real confusion vs. do/loop syntax.)

Of course, IMO CashScript should continue to focus on being user-friendly for new CashScript developers, and it would be perfectly reasonable for CashScript to also offer other loop constructions that average users expect (esp. for-style with initialization and a conditional check at the "top" of the loop and do/while, which is simply begin/until with the condition check inverted.)

However, those higher-level constructions should reasonably take more time to "get right" (maybe staying in a beta version for a little longer), whereas begin/until loops are very low risk at a language level – in the same way that TypeScript can very safely add Stage 4 Javascript features.

bitjson avatar Sep 17 '25 18:09 bitjson