Constants and operators
Name fixed values with #CONSTANT and ENUMERATION, compute with every operator, avoid the precedence traps, and pick the right built-in maths and string functions.
In one line#
A constant is a name for a fixed value, written with # in front. Operators
combine values. Most of them read as in any BASIC, but a few follow JavaScript
rules, because BASIC compiles to JavaScript. This chapter lists every one, and
the traps that come with them.
#CONSTANT#
#CONSTANT <NAME> <value>
#CONSTANT <NAME> = <value>
Read it back with #<NAME>.
#CONSTANT TITLE "Space Rocks"
#CONSTANT GRAVITY 9.81
#CONSTANT DOUBLE_G = #GRAVITY * 2
Console(#TITLE + " " + Str(#DOUBLE_G)) ' Space Rocks 19.62
- The value is a number, a string, or an expression of other constants.
- The name is case-insensitive:
#titlereads#TITLE. - A constant is usable above its own line. Constants are set before the first line of the program runs.
Console(Str(#MAX_LIVES)) ' 3
#CONSTANT MAX_LIVES 3
What is refused#
A name declared twice, or the name of a built-in constant:
#CONSTANT LIVES 3
#CONSTANT LIVES 5
Duplicate BASIC constant: #LIVES
The name of a catalogue command. The message points at the command:
#CONSTANT LEFT 1
BASIC commands require parentheses: Left(...)
Pick a name no command uses, such as #DIR_LEFT.
⚠️ Traps#
-
A constant and a variable spelled exactly alike, case included, break the program. It compiles, but it does not start.
#SPEEDandspeedhappen to work, because their first spellings differ; do not rely on it, and give them different names.#CONSTANT SPEED 5 SPEED = 3 -
A constant name carries no sigil.
#CONSTANT NAME$ "x"compiles, but the program does not start. -
A misspelled constant is found only when the line runs.
#SPEDEcompiles, and stops the program withSPEDE is not defined. -
Writing to a constant is found only when the line runs.
#SPEED = 6stops the program withAssignment to constant variable. -
PureBasic's
#NAME = 5is not a declaration outside anENUMERATION. Write#CONSTANT NAME 5.
⚠️ With DO … LOOP, functions do not see constants#
In a program with a frame loop, constants are set up inside the loop's own function. A FUNCTION that reads one stops the program.
#CONSTANT MAX_LIVES 3
FUNCTION Lives()
ENDFUNCTION #MAX_LIVES
DO
Console(Str(Lives())) ' stops: MAX_LIVES is not defined
Sync()
LOOP
Copy the constant into a GLOBAL, and read the GLOBAL in the function:
#CONSTANT MAX_LIVES 3
GLOBAL maxLives = #MAX_LIVES
FUNCTION Lives()
ENDFUNCTION maxLives
DO
Console(Str(Lives())) ' 3
Sync()
LOOP
The same limit applies to plain variables: see Variables and types.
Built-in constants: #AK_*#
aukimi defines 61 constants, all named #AK_…. They name the options that
commands take, so your code does not depend on raw numbers. This is the complete
list.
| Family | Constants and values | Used for |
|---|---|---|
AUTO | #AK_AUTO_ID = -1 | let a creation command pick the id |
ERROR | #AK_ERROR_IGNORE = 0, #AK_ERROR_REPORT = 1, #AK_ERROR_STOP = 2 | the error policy of ErrorMode |
TEXT | #AK_TEXT_ASCII = 0, #AK_TEXT_UTF16 = 1, #AK_TEXT_UTF8 = 2 | text encodings |
MATCH | #AK_MATCH_EXACT = 0, #AK_MATCH_FOLD_CASE = 1 | case-sensitive or not |
ORDER | #AK_ORDER_LOW_TO_HIGH = 0, #AK_ORDER_HIGH_TO_LOW = 1, #AK_ORDER_FOLD_CASE = 2 | sorting |
ESCAPE | #AK_ESCAPE_NATIVE = 0, #AK_ESCAPE_MARKUP = 1, #AK_ESCAPE_DATA = 2 | escaping text |
LIST | #AK_LIST_LAST = 0, #AK_LIST_FIRST = 1, #AK_LIST_BEFORE = 2, #AK_LIST_AFTER = 3 | positions in a list |
DATA | #AK_DATA_NULL = 0, #AK_DATA_TEXT = 1, #AK_DATA_NUMBER = 2, #AK_DATA_FLAG = 3, #AK_DATA_LIST = 4, #AK_DATA_RECORD = 5, #AK_DATA_PRETTY = 1 | JSON and dictionary values |
PATTERN | #AK_PATTERN_DOT_NEWLINE = 1, #AK_PATTERN_IGNORE_SPACES = 2, #AK_PATTERN_LINE_ANCHORS = 4, #AK_PATTERN_ANY_NEWLINE = 8, #AK_PATTERN_FOLD_CASE = 16 | regular expression options |
TIME | #AK_TIME_PART_YEAR = 0, #AK_TIME_PART_MONTH = 1, #AK_TIME_PART_WEEK = 2, #AK_TIME_PART_DAY = 3, #AK_TIME_PART_HOUR = 4, #AK_TIME_PART_MINUTE = 5, #AK_TIME_PART_SECOND = 6, #AK_TIME_LOCAL = 0, #AK_TIME_UTC = 1 | dates |
CONFIG | #AK_CONFIG_COMPACT = 1, #AK_CONFIG_SECTION_GAPS = 2, #AK_CONFIG_NO_BOM = 4 | preference files |
HASH | #AK_HASH_CRC32 = 1, #AK_HASH_SHA1 = 2, #AK_HASH_SHA256 = 3, #AK_HASH_HMAC = 256 | StringFingerprint, FileFingerprint |
PACK | #AK_PACK_FAST = 1, #AK_PACK_BALANCED = 6, #AK_PACK_MAX = 9, #AK_PACK_SAFE_LIMIT = 32000000 | compression |
XML | #AK_XML_ROOT = 0, #AK_XML_ELEMENT = 1, #AK_XML_COMMENT = 2, #AK_XML_CDATA = 3, #AK_XML_DOCTYPE = 4, #AK_XML_INSTRUCTION = 5, #AK_XML_OK = 0, #AK_XML_INVALID = 1, #AK_XML_PRETTY = 1, #AK_XML_NO_DECLARATION = 2 | XML nodes and output |
ErrorMode(#AK_ERROR_REPORT)
Console(Str(#AK_ERROR_STOP)) ' 2
- They are read like your own constants, in any case:
#ak_error_stopworks. - You cannot redefine one:
#CONSTANT AK_ERROR_STOP 5is a duplicate. - Flags whose values are powers of two (
PATTERN,CONFIG,#AK_HASH_HMAC) combine with||, the bitwise or. - There are no
#PB_*or AGK constants. A program that uses them gets… is not definedwhen the line runs.
ENUMERATION and ENUMERATIONBINARY#
ENUMERATION [<Name>] [<start> [STEP <step>]]
#<NAME> [= <value>]
...
ENDENUMERATION
ENUMERATIONBINARY [<Name>] [<start>]
#<NAME> [= <value>]
...
ENDENUMERATION
An enumeration declares a run of constants, one per line.
ENUMERATION
#RED
#GREEN
#BLUE
ENDENUMERATION
Console(Str(#RED) + Str(#GREEN) + Str(#BLUE)) ' 012
ENUMERATION 10 STEP 5
#A
#B
#C = 100
#D
ENDENUMERATION
Console(Str(#A) + " " + Str(#B) + " " + Str(#C) + " " + Str(#D)) ' 10 15 100 105
ENUMERATIONBINARY
#FLAG_A
#FLAG_B
#FLAG_C
ENDENUMERATION
Console(Str(#FLAG_A) + " " + Str(#FLAG_B) + " " + Str(#FLAG_C)) ' 1 2 4
| Rule | Detail |
|---|---|
ENUMERATION | starts at 0 and adds 1, or starts at <start> and adds <step> |
ENUMERATIONBINARY | starts at 1 (or <start>) and doubles: 1, 2, 4, 8… |
#NAME = <value> | sets this value; the next entries continue from it |
| values | whole numbers: 0.5 is rounded to 1 |
<start>, <step>, <value> | numbers, or expressions of other constants; no command calls |
| a named enumeration | continues where it stopped when you open it again |
ENUMERATION Tiles
#FLOOR
#WALL
ENDENUMERATION
ENUMERATION Tiles
#DOOR
ENDENUMERATION
Console(Str(#DOOR)) ' 2
Refused:
| You write | Message |
|---|---|
a line without # inside the block | BASIC enumeration accepts only #Constant entries |
two names on one line (#A, #B) | same message |
ENUMERATIONBINARY 1 STEP 2 | ENUMERATIONBINARY does not accept STEP |
| an enumeration inside another | Nested BASIC enumerations are not supported |
| a named enumeration reopened in the other mode | BASIC enumeration Tiles cannot change between sequential and binary modes |
#A = Random(1, 2) | BASIC enumeration values must be constant numeric expressions |
A STEP needs a start value: write ENUMERATION 0 STEP 2.
Arithmetic#
| Operator | Meaning | Example | Result |
|---|---|---|---|
+ | add | 7 + 2 | 9 |
- | subtract, or negate | 7 - 2 | 5 |
* | multiply | 7 * 2 | 14 |
/ | divide, with decimals | 7 / 2 | 3.5 |
DIV | divide, whole part | 7 DIV 2 | 3 |
^ | power | 7 ^ 2 | 49 |
Mod(a, b) | remainder | Mod(7, 2) | 1 |
a = 7
b = 2
Console(Str(a / b)) ' 3.5
Console(Str(a DIV b)) ' 3
Console(Str(-7 DIV 2)) ' -3
Console(Str(Mod(a, b))) ' 1
Console(Str(Mod(-7, 3))) ' -1
Console(Str(a ^ b)) ' 49
/always keeps the decimals, even between two integers.DIVdrops them, toward zero:-7 DIV 2is-3.- Dividing by zero:
/givesInfinity;DIVstops the program withBASIC integer division by zero. - The remainder takes the sign of the first number:
Mod(-7, 3)is-1.
⚠️ MOD is written as a call#
The MOD operator of other BASICs is refused, because the catalogue has a
Mod command:
r = 7 MOD 2
BASIC commands require parentheses: Mod(...)
Write Mod(7, 2). For decimals, FMod(7.5, 2) gives 1.5.
⚠️ DIV takes its two neighbours#
DIV works between two plain values: numbers, variables, array cells, record
fields, or a group in parentheses on its left.
-
It is done before
*and/:2 * 7 DIV 2is2 * 3, so6. -
After a command call, it breaks the program, which does not start:
s$ = "hello" half = Len(s$) DIV 2 -
Before a group in parentheses, it is refused:
a = 9 b = 4 x = a DIV (b - 1)Unknown BASIC command: DIV()
Put the call or the group in a variable first:
a = 9
b = 4
d = b - 1
x = a DIV d
Console(Str(x)) ' 3
⚠️ ^ and the minus sign#
-
^groups from the right:2 ^ 3 ^ 2is2 ^ 9, so512. -
A minus sign (or
NOT) directly before a power is not allowed. The program does not start:x = 2 y = -x ^ 2Write
-(x ^ 2)for −4, or(-x) ^ 2for 4.2 ^ -2is fine:0.25.
Comparison#
| Operator | Meaning |
|---|---|
= | equal |
<> | different |
<, > | less, greater |
<=, >= | less or equal, greater or equal |
a = 5
same = (a = 5)
differ = (a <> 5)
Console(Str(same) + " " + Str(differ)) ' 1 0
loose = ("5" = 5)
Console(Str(loose)) ' 0: text is never equal to a number
IF a >= 5 THEN Console("five or more") ' five or more
- A comparison stored in a variable is 1 or 0. Inside
IF,WHILEandUNTIL, it is simply true or false. - On the right of an assignment,
=compares.same = (a = 5)does not changea. The parentheses are optional, but clearer. - Equality is strict: the text
"5"is not the number5. Convert first withValorStr. - Text compares in alphabetical order of character codes:
"B" < "a".
⚠️ Inside a call, = is not a comparison#
In a statement that is a command call, an = inside the parentheses
assigns. The variable changes, silently.
a = 5
Console(Str(a = 1)) ' 1, and a is now 1
Console(Str(a)) ' 1
Compare in a variable first, or in an IF.
⚠️ == and != compare loosely#
== and != are accepted, but they are JavaScript's loose comparisons:
text and numbers are converted before comparing.
c$ = "7"
n = 7
IF c$ = n THEN Console("never printed")
IF c$ == n THEN Console("== compares loosely") ' == compares loosely
Use = and <>.
Logical operators: AND, OR, NOT#
x = 5
y = 0
IF x > 0 AND y = 0 THEN Console("both") ' both
IF x < 0 OR y = 0 THEN Console("one of them") ' one of them
IF NOT y THEN Console("y is zero") ' y is zero
r = x > 0 AND y = 0
Console(Str(r)) ' 1
NOTis true for 0, an empty string andFALSE, and false for anything else.- The right side is evaluated only when needed: in
a AND b,bis skipped whenais false.
⚠️ On plain numbers, AND and OR return one of their operands, not 1 or 0.
Classic BASICs compute bits; aukimi does not.
v = 5 AND 3
Console(Str(v)) ' 3: the second operand
w = 0 OR 7
Console(Str(w)) ' 7
For bits, use the bitwise operators below.
Bitwise operators#
| aukimi | Meaning | Example | Result |
|---|---|---|---|
&& | and | %1100 && %1010 | 8 |
|| | or | %1100 || %0011 | 15 |
~~ | exclusive or | %1100 ~~ %1010 | 6 |
! | not (every bit flipped) | !0 | -1 |
<< | shift left | 1 << 4 | 16 |
>> | shift right, keeping the sign | -16 >> 2 | -4 |
flags = %1100
Console(Str(flags && %1010)) ' 8
Console(Str(flags || %0011)) ' 15
Console(Str(flags ~~ %1010)) ' 6
Console(Str(!0)) ' -1
Console(Str(1 << 4)) ' 16
Console(Str(-16 >> 2)) ' -4
The symbols are bitwise, the words are logical.
&&is notAND, and||is notOR. This is the reverse of C and JavaScript.
Bitwise operators work on signed 32-bit integers.
⚠️ XOR does not exist. It compiles, but the program does not start.
Write ~~.
x = 5 XOR 3
⚠️ A single & is not string concatenation. "a" & "b" gives 0.
Concatenate with +.
⚠️ A bit test needs parentheses#
&& comes after = in the order of operations. flags && 4 = 4 means
flags && (4 = 4).
flags = 4
IF flags && 4 = 4 THEN Console("never printed")
IF (flags && 4) = 4 THEN Console("bit set") ' bit set
IF flags && 4 THEN Console("also set") ' also setText#
+ joins strings. When one side is text and the other a number, the number
is turned into text.
score = 10
Console("Score: " + Str(score)) ' Score: 10
Console("n" + 5) ' n5
Console(Str(5 + "5")) ' 55
Console(Str(10 - "3")) ' 7
⚠️ -, * and / turn text into a number, but + turns a number into text.
Convert on purpose: Str to make text, Val or ValFloat to make a number.
Strings with {holes}, such as $"Score: {score}", are in
Shorthands.
TRUE, FALSE, NULL#
| Word | Value |
|---|---|
TRUE, FALSE | truth values (not the numbers 1 and 0) |
NULL | no value; the start value of a HANDLE |
They are written in any case.
ready = TRUE
Console(Str(ready)) ' true
IF ready THEN Console("ready") ' ready
IF ready = 1 THEN Console("never printed")
done = (3 > 2)
Console(Str(done)) ' 1
⚠️ TRUE is not 1. A variable set to TRUE prints true and is not
equal to 1. Test it with IF ready THEN. A comparison, on the other hand,
stores 1 or 0.
Order of operations#
From first to last. Operators on the same row go from left to right, except
^.
| Order | Operators |
|---|---|
| 1 | ( ), calls |
| 2 | DIV, with its two neighbours |
| 3 | ^ (from the right) |
| 4 | NOT, !, the minus sign |
| 5 | *, / |
| 6 | +, - |
| 7 | <<, >> |
| 8 | <, <=, >, >= |
| 9 | =, <> (and ==, !=) |
| 10 | && |
| 11 | ~~ |
| 12 | || |
| 13 | AND |
| 14 | OR |
⚠️ The traps#
| You write | It means | Write instead |
|---|---|---|
NOT a = b | (NOT a) = b | a <> b |
flags && 4 = 4 | flags && (4 = 4) | (flags && 4) = 4 |
2 * 7 DIV 2 | 2 * (7 DIV 2) = 6 | t = 2 * 7 then t DIV 2 |
2 ^ 3 ^ 2 | 2 ^ 9 = 512 | (2 ^ 3) ^ 2 for 64 |
-x ^ 2 | refused: the program does not start | -(x ^ 2) |
1 < x < 5 | (1 < x) < 5, always true | x > 1 AND x < 5 |
a = 1
b = 2
IF NOT a = b THEN Console("never printed")
IF a <> b THEN Console("a and b differ") ' a and b differ
same = (a = b)
IF NOT same THEN Console("not the same") ' not the sameBuilt-in functions#
Two kinds of functions look alike in your code.
Handled by the compiler#
| Name | What it does |
|---|---|
Float(x) | turns x into a number: Float("2.5") is 2.5 |
Max(a, b, …) | the largest of any number of values |
Min(a, b, …) | the smallest of any number of values |
PI | 3.141592653589793 (upper case only) |
TRUE, FALSE, NULL | see above |
Console(Str(Max(3, 9, 12)) + " " + Str(Min(4, -1, 2))) ' 12 -1
Console(Str(Float(7) / 2)) ' 3.5
From the catalogue#
Everything else is a catalogue command, even the classic maths and string names. Each has its page in the command reference.
The catalogue's trigonometry works in degrees.
Sin(90)is 1. The radian versions end inRad.
Console(Str(Sin(90))) ' 1
Console(Str(Cos(180))) ' -1
Console(Str(ATan2(1, 1))) ' 45
Console(Str(SinRad(PI / 2))) ' 1
Console(Str(Sin(PI / 2))) ' 0.027412133592044294: PI / 2 degrees
| Function | Result | Note |
|---|---|---|
Sin, Cos, Tan | from an angle in degrees | |
ASin, ACos, ATan, ATan2(y, x) | an angle in degrees | |
SinRad, CosRad, TanRad | from an angle in radians | |
Sqrt(x), Pow(a, b), Abs(x) | ||
Exp(x), Log(x), Log10(x) | Log is the natural logarithm | |
Int(x), Trunc(x) | the whole part, toward zero | Int(-3.7) is -3 |
Floor(x), Ceil(x) | down, up | Floor(-3.2) is -4 |
Round(x) | the nearest whole number; .5 goes up | Round(2.5) is 3, Round(-2.5) is -2 |
Mod(a, b), FMod(a, b) | remainder; whole, decimal | sign of a |
Sign(x) | -1, 0 or 1 | |
Random(from, to) | a whole number, both ends included | |
Str(n), Str(n, decimals) | text | Str(3.14159, 2) is 3.14 |
Val(s), Val(s, base) | a whole number | Val("1.5") is 1, Val("ff", 16) is 255 |
ValFloat(s) | a decimal number | ValFloat("1.5") is 1.5 |
Len(s) | the number of characters | |
Left(s, n), Right(s, n) | the first or last n characters | |
Mid(s, start, length) | part of s | start counts from 1 |
Upper(s), Lower(s) | ||
Chr(code), Asc(s) | a character from its code, and back | Chr(34) is " |
Hex(n), Bin(n) | text in base 16 or 2 | Hex(255) is FF |
FindString(s, find) | the position, from 1; 0 when absent |
Console(Str(Int(-3.7)) + " " + Str(Floor(-3.7))) ' -3 -4
Console(Mid("hello", 2, 3)) ' ell
Console(Str(FindString("hello", "l"))) ' 3
⚠️ QBasic's RND and INSTR do not exist. They are refused as unknown
commands. Write Random(from, to) and FindString(s, find).
x = RND(5)
p = INSTR("hello", "l")
⚠️ Int truncates; it does not round down. QBasic's INT(-3.7) is −4;
aukimi's Int(-3.7) is −3. Use Floor for −4.
⚠️ PureBasic's Sin takes radians; aukimi's takes degrees. Use SinRad
when your angles are in radians.
Coming from another BASIC#
| You write | In aukimi |
|---|---|
a MOD b | Mod(a, b) |
a XOR b | a ~~ b |
a AND b on bits | a && b |
a OR b on bits | a || b |
NOT a on bits | !a |
a & b to join text (Visual Basic) | a + b |
a \ b (whole division) | a DIV b |
#NAME = 5 (PureBasic) | #CONSTANT NAME 5 |
CONST NAME = 5 | #CONSTANT NAME 5 |
RND, INSTR, INT | Random, FindString, Floor |
Sin(x) with x in radians | SinRad(x) |