Expressions
The syntax gives names for branches and local variables.
An expression combines those forms into a program written as data.
The first item in a list is
the operator. The other items are its arguments. You write 2 + 3 * 4 in this
form:
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | 1C 2A | txt "*" |
| 06 | 02 03000000000000 00 | i64 3 |
| 0F | 02 04000000000000 00 | i64 4 |
| 18 | 0E 15 00 0700 030000 00 04000000 060000 00 0F000000 | array leaf, size 21, shift 0, bitmap 0007, count 3 (root): @4 → @6 → @F |
| 2D | 1C 2B | txt "+" |
| 2F | 02 02000000000000 00 | i64 2 |
| 38 | 0E 15 00 0700 030000 00 2D000000 2F0000 00 18000000 | array leaf, size 21, shift 0, bitmap 0007, count 3 (root): @2D → @2F → @18 |
| 4D | 38000000 00000000 | root → @38; previous: none |
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | 02 0E000000000000 00 | i64 14 |
| 0D | 04000000 00000000 | root → @4; previous: none |
An expression is an ordinary document. Stardust keeps it, examines it, and records each change to it. A native document keeps the expression without a text conversion. DUST gives a readable form of that document.
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 000 | 54 52 4F 4E | magic TRON |
| 004 | 3C 616765 | txt "age" |
| 008 | 02 24000000000000 00 | i64 36 |
| 011 | 0F 0A 04000000 0800 0000 | map leaf, size 10: @4 → @8 |
| 01B | 4C 726F6C65 | txt "role" |
| 020 | 8C 656E67696E6565 72 | txt "engineer" |
| 029 | 0F 0A 1B000000 2000 0000 | map leaf, size 10: @1B → @20 |
| 033 | 4C 6E616D65 | txt "name" |
| 038 | 3C 416461 | txt "Ada" |
| 03C | 0F 0A 33000000 3800 0000 | map leaf, size 10: @33 → @38 |
| 046 | 07 12 00910000 1100 0000 29000000 3C00 0000 | map branch, size 18, depth 0 (root), slots 8, 12, 15: @11 → @29 → @3C |
| 058 | 5C 236C696E6B | txt "#link" |
| 05E | 5C 235F616461 | txt "#_ada" |
| 064 | 0F 0A 58000000 5E00 0000 | map leaf, size 10: @58 → @5E |
| 06E | 3C 616765 | txt "age" |
| 072 | 02 29000000000000 00 | i64 41 |
| 07B | 0F 0A 6E000000 7200 0000 | map leaf, size 10: @6E → @72 |
| 085 | 6C 6D656E746F72 | txt "mentor" |
| 08C | 0F 0A 85000000 6400 0000 | map leaf, size 10: @85 → @64 |
| 096 | 4C 726F6C65 | txt "role" |
| 09B | 8C 656E67696E6565 72 | txt "engineer" |
| 0A4 | 0F 0A 96000000 9B00 0000 | map leaf, size 10: @96 → @9B |
| 0AE | 4C 6E616D65 | txt "name" |
| 0B3 | 3C 426F62 | txt "Bob" |
| 0B7 | 0F 0A AE000000 B300 0000 | map leaf, size 10: @AE → @B3 |
| 0C1 | 07 16 00990000 7B00 0000 8C000000 A400 0000 B7000000 | map branch, size 22, depth 0 (root), slots 8, 11, 12, 15: @7B → @8C → @A4 → @B7 |
| 0D7 | 3C 616765 | txt "age" |
| 0DB | 02 1D000000000000 00 | i64 29 |
| 0E4 | 0F 0A D7000000 DB00 0000 | map leaf, size 10: @D7 → @DB |
| 0EE | 4C 726F6C65 | txt "role" |
| 0F3 | 8C 64657369676E65 72 | txt "designer" |
| 0FC | 0F 0A EE000000 F300 0000 | map leaf, size 10: @EE → @F3 |
| 106 | 4C 6E616D65 | txt "name" |
| 10B | 2C 4379 | txt "Cy" |
| 10E | 0F 0A 06010000 0B01 0000 | map leaf, size 10: @106 → @10B |
| 118 | 07 12 00910000 E400 0000 FC000000 0E01 0000 | map branch, size 18, depth 0 (root), slots 8, 12, 15: @E4 → @FC → @10E |
| 12A | 4C 235F6379 | txt "#_cy" |
| 12F | 0F 0A 2A010000 1801 0000 | map leaf, size 10: @12A → @118 |
| 139 | 5C 235F626F62 | txt "#_bob" |
| 13F | 0F 0A 39010000 C100 0000 | map leaf, size 10: @139 → @C1 |
| 149 | 5C 235F616461 | txt "#_ada" |
| 14F | 0F 0A 49010000 4600 0000 | map leaf, size 10: @149 → @46 |
| 159 | 07 12 80210000 2F01 0000 3F010000 4F01 0000 | map branch, size 18, depth 0 (root), slots 7, 8, 13: @12F → @13F → @14F |
| 16B | 59010000 00000000 | root → @159; previous: none |
Variables
Every variable binding and reference uses ?name, including let names and
fn parameters. A reference uses the inner declaration first. A reference
without a declaration reads caller input. A plain word in value position is
always text.
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | 1C 2B | txt "+" |
| 06 | 2C 3F78 | txt "?x" |
| 09 | 02 01000000000000 00 | i64 1 |
| 12 | 0E 15 00 0700 030000 00 04000000 060000 00 09000000 | array leaf, size 21, shift 0, bitmap 0007, count 3 (root): @4 → @6 → @9 |
| 27 | 12000000 00000000 | root → @12; previous: none |
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | 02 2A000000000000 00 | i64 42 |
| 0D | 04000000 00000000 | root → @4; previous: none |
With the caller variable x set to 41, this expression gives 42. An
expression contains no inputs and no results. Each evaluation gives one value
and the cost of the calculation.
An expression calculates its result from its variables. A standalone expression needs no database or external service.
True and false values
Only null and false are false. All other values are true. The number 0,
the empty text, and the empty list are also true. The branch
operators use this rule.
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | 2C 6966 | txt "if" |
| 07 | 02 00000000000000 00 | i64 0 |
| 10 | CC 7A65726F2D6973 2D74727565 | txt "zero-is-true" |
| 1D | 5C 6E65766572 | txt "never" |
| 23 | 0E 19 00 0F00 040000 00 04000000 070000 00 10000000 1D0000 00 | array leaf, size 25, shift 0, bitmap 000F, count 4 (root): @4 → @7 → @10 → @1D |
| 3C | 23000000 00000000 | root → @23; previous: none |
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | CC 7A65726F2D6973 2D74727565 | txt "zero-is-true" |
| 11 | 04000000 00000000 | root → @4; previous: none |
Exact numbers
An integer has 64 bits and keeps its exact value. A float has 64 bits in binary form. Stardust does not change the type of a value automatically. Each operator sets the type of its arguments. One argument with a known type therefore sets the type of the others.
[+ 9007199254740993 1]gives the exact value9007199254740994.[/ 6 3]gives2.[/ 6.0 3.0]gives2.0.
An integer result outside the 64-bit range is an error. The value does not change to a negative number.
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | 1C 2B | txt "+" |
| 06 | 02 FFFFFFFFFFFFFF 7F | i64 9223372036854775807 |
| 0F | 02 01000000000000 00 | i64 1 |
| 18 | 0E 15 00 0700 030000 00 04000000 060000 00 0F000000 | array leaf, size 21, shift 0, bitmap 0007, count 3 (root): @4 → @6 → @F |
| 2D | 18000000 00000000 | root → @18; previous: none |
Error
Runtime_Failure: Integer addition exceeds the signed 64-bit range.
Arithmetic operators do not change text into a number.
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | 1C 2B | txt "+" |
| 06 | 1C 35 | txt "5" |
| 08 | 02 01000000000000 00 | i64 1 |
| 11 | 0E 15 00 0700 030000 00 04000000 060000 00 08000000 | array leaf, size 21, shift 0, bitmap 0007, count 3 (root): @4 → @6 → @8 |
| 26 | 11000000 00000000 | root → @11; previous: none |
Error
Runtime_Failure: A number is required, but the value has type string.
Stardust compares an integer with a float exactly. The expression
[> 9007199254740993 9007199254740992.0] is true.
Changing a value type
Use toInt, toFloat, toText, or toBool when an operator needs a
different value type. Each operator accepts one argument.
toInt keeps an integer and changes a boolean to 1 or 0. It also reads
signed decimal integer text.
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | 5C 746F496E74 | txt "toInt" |
| 0A | 3C 2D3432 | txt "-42" |
| 0E | 0E 11 00 0300 020000 00 04000000 0A0000 00 | array leaf, size 17, shift 0, bitmap 0003, count 2 (root): @4 → @A |
| 1F | 0E000000 00000000 | root → @E; previous: none |
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | 02 D6FFFFFFFFFFFF FF | i64 -42 |
| 0D | 04000000 00000000 | root → @4; previous: none |
A float loses its fraction toward zero. NaN, infinity, and values outside the signed 64-bit integer range give an error.
toFloat keeps a float, changes an integer to a float, and reads decimal or
exponent text. The result can lose integer precision. A boolean gives an error.
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | 7C 746F466C6F6174 | txt "toFloat" |
| 0C | 3C 316533 | txt "1e3" |
| 10 | 0E 11 00 0300 020000 00 04000000 0C0000 00 | array leaf, size 17, shift 0, bitmap 0003, count 2 (root): @4 → @C |
| 21 | 10000000 00000000 | root → @10; previous: none |
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | 03 0000000000408F 40 | f64 1000 |
| 0D | 04000000 00000000 | root → @4; previous: none |
toText gives plain text for numbers and booleans. A float without a fraction
gives no decimal point, so [toText 2.0] gives 2. It gives null as the text
null, and gives lists and maps as JSON.
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | 4C 6C697374 | txt "list" |
| 09 | 02 01000000000000 00 | i64 1 |
| 12 | 09 | bit true |
| 13 | 0E 15 00 0700 030000 00 04000000 090000 00 12000000 | array leaf, size 21, shift 0, bitmap 0007, count 3 (root): @4 → @9 → @12 |
| 28 | 6C 746F54657874 | txt "toText" |
| 2F | 0E 11 00 0300 020000 00 28000000 130000 00 | array leaf, size 17, shift 0, bitmap 0003, count 2 (root): @28 → @13 |
| 40 | 2F000000 00000000 | root → @2F; previous: none |
| Offset (hex) | Bytes (hex) | Meaning |
|---|---|---|
| 00 | 54 52 4F 4E | magic TRON |
| 04 | 8C 5B312C74727565 5D | txt "[1,true]" |
| 0D | 04000000 00000000 | root → @4; previous: none |
toBool accepts a boolean, the exact text true or false, and the integer
1 or 0. Other values give an error.
These operators reject spaces around numeric text and values outside the
applicable range. toInt rejects decimal text such as 4.0.
Use floor, ceil, or round when you must control how a float becomes an
integer. Use format when you must control the text digits.
Cost
The native evaluation reports measured CPU time in 100-nanosecond ticks. The evaluation options use the same unit for the cost limit. Evaluating gives the details.
Types
Stardust calculates the type of the result and the type of each variable from
their use. Each operator sets the types of its arguments and its result.
Stardust changes no type automatically. One argument with a known type
therefore sets the other types. A type that stays unknown becomes any.
Syntax gives the branch operators, the names that you set, the functions, and the literal values.