# iRules expression lab

> Evaluate an expression the way expr and if do in an iRule and see every step: how each operand was read, numeric or text comparison, precedence, where && stopped, and == next to eq. Tcl 8.4 or iRules mode. Local, no network.

- Tool: https://ronutz.com/en/tools/f5-irules-expression-lab
- Family: Networking

---

## What it does

Evaluates an expression the way `expr`, `if` and `while` do in an iRule, and shows the whole evaluation: the value and how it is held, the expression with every operator's operands in parentheses so precedence is visible, a tree of every step, and, for a comparison, what `==`, `eq`, `<` and `>` each make of the same two operands. Variables get their values from ordinary `set` commands, so quoting behaves exactly as in an iRule.

Two modes: **Tcl 8.4** (plain Tcl 8.4.6, the base F5 names in K6091) and **iRules**, which adds the operators F5 documents (`contains`, `starts_with`, `ends_with`, `equals`, `matches_glob`, `matches_regex`, `and`, `or`, `not`) and request commands such as `[HTTP::uri]`, answered from an editable sample request.

## How to read the tree

Each box is one part of the expression: its source, an arrow, and what it produced. Operands sit under their operator. The notes under a box say what happened there, for example "Compared as integers: 10 and 10" for `$x == $y` with `x` set to `012`, or "Compared as text because the left side is not a number". A part marked "never evaluated" was skipped by `&&`, `||` or `?:`.

## Worth knowing

- `==` and the other comparison operators compare numbers when both sides read as numbers, and text otherwise. `eq` and `ne` always compare text.
- In a text comparison character codes decide, so every upper-case letter sorts before every lower-case one: `"bench" < "Chair"` is false.
- `true == 1` is false: `true` is a boolean word, not a number, so the comparison is between texts.
- Tcl 8.4 has no `**` operator; `2 ** 3` is a syntax error.
- Integer division rounds toward negative infinity (`7 / -2` is `-4`) and a remainder takes the divisor's sign.
- A literal such as `08` written in the expression is rejected when the expression is compiled, before any part of it runs.
- Brace your expressions. Without braces Tcl substitutes the text twice, which is slower and lets data run as code (F5 K57410758 and K15650046). The script stepper shows this happening.

## Limits

F5 documents its word operators but not their precedence relative to the Tcl operators; the tool places `contains`, `starts_with` and the others with `==`, and `and` and `or` with `&&` and `||`. `rand()` and `srand()` are refused because their results cannot be reproduced. Commands run inside an expression (in brackets) use the same small interpreter as the script stepper, bounded to 2,000 commands. This tool is not offered over the API, because it executes the Tcl you give it.

## Sources

- [F5 K6091: The version of Tcl used to develop iRules](https://my.f5.com/manage/s/article/K6091) (read 2026-10-03)
- [Tcl 8.4 manual: expr](https://www.tcl-lang.org/man/tcl8.4/TclCmd/expr.htm) (read 2026-10-03)
- [F5 iRules reference: Operators](https://clouddocs.f5.com/api/irules/Operators.html) (read 2026-10-02)
- [F5 K57410758: use curly braces to avoid double substitution](https://my.f5.com/manage/s/article/K57410758) (read 2026-10-03)
- [F5 K15650046: Tcl code injection security exposure](https://my.f5.com/manage/s/article/K15650046) (read 2026-10-03)

## Standards and references

- [F5 K6091: The version of Tcl used to develop iRules](https://my.f5.com/manage/s/article/K6091) - the iRules command set was developed from Tcl base version 8.4.6, which is used in all BIG-IP versions; the engine models that version
- [Tcl 8.4 manual: expr](https://www.tcl-lang.org/man/tcl8.4/TclCmd/expr.htm) - operand notation (decimal, octal with a leading 0, hexadecimal with 0x), operator precedence, string comparison, eq and ne, and the sign of a remainder
- [F5 iRules reference: Operators](https://clouddocs.f5.com/api/irules/Operators.html) - the Tcl operators by precedence and the operators F5 adds: contains, ends_with, equals, matches_glob, matches_regex, starts_with, and, not, or
- [F5 K57410758: warning [use curly braces to avoid double substitution]](https://my.f5.com/manage/s/article/K57410758) - expr, if and while substitute an unbraced argument a second time; the validator warning and the braced fix
- [F5 K15650046: Tcl code injection security exposure](https://my.f5.com/manage/s/article/K15650046) - always brace expressions; always put -- before the switch string; the bad option error a value starting with - produces
- [F5 iRules reference: HTTP::uri](https://clouddocs.f5.com/api/irules/HTTP__uri.html) - HTTP::uri returns the URI part of the request (path and query); the sample request answers it
- [F5 iRules reference: HTTP::host](https://clouddocs.f5.com/api/irules/HTTP__host.html) - HTTP::host returns the Host header value (with the port when it is not the standard one); the sample request answers it
- [Tcl 8.4.6 source code, tag core-8-4-6 on GitHub](https://github.com/tcltk/tcl/tree/core-8-4-6) - the reference interpreter: the engine was differential-tested against tclsh built from this tag (commit bf3eeadc)

## Related reading

- [iRules comparisons: == versus eq, precedence, and the quiet fallback to text](https://ronutz.com/en/learn/irules-expression-operators.md): In an iRule, == compares numbers when it can and text when it cannot, while eq always compares text. That one rule explains why 012 == 10 is true, why true == 1 is false, and why bench sorts after Chair. Here are the comparison rules of Tcl 8.4.6, the precedence that groups an expression, and F5's own operators.
- [iRules LX, explained: what runs where when Tcl calls Node.js](https://ronutz.com/en/learn/irules-lx-explained.md): iRules LX puts a Node.js process beside the Traffic Management Microkernel and lets a Tcl iRule call into it with ILX::call, wait at most three seconds by default, and get the answer back as a Tcl value. This is the whole mechanism, object by object and command by command, from F5's own reference: workspaces, extensions, plugins and the LX rule; ILX::init, ILX::call and ILX::notify; dedicated and single process modes; npm without an internet connection; the Node.js 6.9.1 runtime that BIG-IP 21.1 still ships after removing 0.12; the upgrade that used to break workspaces; and the questions to ask before a design depends on it.
- [Numbers in iRules: octal, hexadecimal, and why 08 is not a number](https://ronutz.com/en/learn/irules-tcl-number-notation.md): iRules read numbers by the rules of Tcl 8.4.6, and those rules hide a trap: a leading zero means octal, so 010 is eight and 08 is not a number at all. Here is how Tcl reads integers and doubles, the two places it reads them, and the zero-padded values that break real rules.
- [The DevCentral iRules Style Guide, rule by rule, with the reasons](https://ronutz.com/en/learn/irules-style-guide-explained.md): F5's DevCentral published an iRules Style Guide in 2022: editor settings and twenty numbered rules. Some are taste, but several prevent real failures: an iRule that will not load, a switch an attacker can steer, an expression that runs request data as code, a log storm. Here are the rules grouped by what they protect, with the reason behind each, what the comment thread under the guide corrected, and what has changed since it was written.
- [Zero or one: where BIG-IP starts counting](https://ronutz.com/en/learn/bigip-zero-or-one.md): Tcl counts from 0, several commands F5 adds count from 1, counters return 1 for the first item, many zeros in the configuration are values rather than positions, and the same path segment is element 1, field 2 or index 1 depending on who is asking. Here is where each one comes from, in F5's own words, with the traps and the places where F5's pages disagree with themselves.
