Control Flow
Algorand Python Control Flow
Control flow in Algorand Python is similar to standard Python control flow, with support for if statements, while loops, for loops, and match statements.
If statements
If statements work the same as Python. The conditions must be an expression that evaluates to bool, which can include a String or Uint64 among others.
1if condition:2 # block of code to execute if condition is True3elif condition2:4 # block of code to execute if condition is False and condition2 is True5else:6 # block of code to execute if condition and condition2 are both False
Ternary conditions
Ternary conditions work the same as Python. The condition must be an expression that evaluates to bool, which can include a String or Uint64 among others.
1value1 = UInt64(5)2value2 = String(">6") if value1 > 6 else String("<=6")
While loops
While loops work the same as Python. The condition must be an expression that evaluates to bool, which can include a String or Uint64 among others.
You can use break
and continue
.
1while condition:2 # block of code to execute if condition is True
Note: we don’t currently have support for while-else statements.
For Loops
For loops are used to iterate over sequences, ranges and ARC-4 arrays. They work the same as Python.
Algorand Python provides functions like uenumerate
and urange
to facilitate creating sequences and ranges; in-built Python reversed
method works with these.
uenumerate
is similar to Python’s built-in enumerate function, but for UInt64 numbers; it allows you to loop over a sequence and have an automatic counter.urange
is a function that generates a sequence of Uint64 numbers, which you can iterate over.reversed
returns a reversed iterator of a sequence.
Here is an example of how you can use these functions in a contract:
1test_array = arc4.StaticArray(arc4.UInt8(), arc4.UInt8(), arc4.UInt8(), arc4.UInt8())2
3# urange: reversed items, forward index4
5for index, item in uenumerate(reversed(urange(4))):6 test_array[index] = arc4.UInt8(item)7
8assert test_array.bytes == Bytes.from_hex("03020100")
Note: we don’t currently have support for for-else statements.
Match Statements
Match statements work the same as Python and work for […]
1match value:2 case pattern1:3 # block of code to execute if pattern1 matches4 case pattern2:5 # block of code to execute if pattern2 matches6 case _:7 # Fallback
Note: Captures and patterns are not supported. Currently, there is only support for basic case/switch functionality; pattern matching and guard clauses are not currently supported.
TEAL Flow Control Opcode
Algorand Python and TypeScript are high-level smart contract languages that allow developers to express control flows in more accessible languages. However, the Algorand Virtual Machine (AVM) executes the Transaction Execution Approval Language (TEAL) flow control opcodes after compilation. TEAL is a low-level assembly language that the AVM understands directly. While developers will write smart contracts in higher-level languages, understanding the underlying TEAL opcodes can be beneficial to comprehend what’s happening line by line. The following chart contains all of the control flow opcodes available in TEAL.
Opcode | Description |
---|---|
err | Fail immediately. |
bnz target | branch to TARGET if value A is not zero |
bz target | branch to TARGET if value A is zero |
b target | branch unconditionally to TARGET |
return | use A as success value; end |
pop | discard A |
popn n | remove N values from the top of the stack |
dup | duplicate A |
dup2 | duplicate A and B |
dupn n | duplicate A, N times |
dig n | Nth value from the top of the stack. dig 0 is equivalent to dup |
bury n | replace the Nth value from the top of the stack with A. bury 0 fails. |
cover n | remove top of stack, and place it deeper in the stack such that N elements are above it. Fails if stack depth <= N. |
uncover n | remove the value at depth N in the stack and shift above items down so the Nth deep value is on top of the stack. Fails if stack depth <= N. |
frame_dig i | Nth (signed) value from the frame pointer. |
frame_bury i | replace the Nth (signed) value from the frame pointer in the stack with A |
swap | swaps A and B on stack |
select | selects one of two values based on top-of-stack: B if C != 0, else A |
assert | immediately fail unless A is a non-zero number |
callsub target | branch unconditionally to TARGET, saving the next instruction on the call stack |
proto a r | Prepare top call frame for a retsub that will assume A args and R return values. |
retsub | pop the top instruction from the call stack and branch to it |
switch target … | branch to the Ath label. Continue at following instruction if index A exceeds the number of labels. |
match target … | given match cases from A[1] to A[N], branch to the Ith label where A[I] = B. Continue to the following instruction if no matches are found. |