Auto-generated from Truth Vectors. This document serves as the absolute specification for MS-DOS QBasic behavior.
/ (Floating-Point Division) • \ (Integer Division) • ABS Function • ASC Function • ATN Function • CALL Statement • CHR$ Function • CINT Function • COS Function • Default Implicit Typing (SINGLE) • DEFINT Statement • DEFSNG Statement • DO...LOOP Statement (Post-test) • DO...LOOP Statement (Pre-test) • ERASE Statement • EXIT FOR Statement • EXP Function • Explicit Type Suffix Override • FIX Function • Fixed-Length String Padding • Fixed-Length String Truncation • FOR...NEXT Statement • GOSUB...RETURN Statement • HEX$ Function • INSTR Function • INT Function • LCASE$ Function • LEFT$ Function • LEN Function • LOG Function • LTRIM$ Function • Memory Aliasing (DIM AS STRING) • MID$ Function • MOD Operator • RIGHT$ Function • RTRIM$ Function • SELECT CASE Statement • SIN Function • SPACE$ Function • SQR Function • STR$ Function • STRING$ Function • SWAP Statement • TAN Function • UCASE$ Function • VAL Function • WHILE...WEND Statement
- STDLIB: Math & Floating-Point Unit
- STDLIB: Strings & Type Casting
- CORE: Control Flow & Jumps
- CORE: Memory, Types & Structures
- CORE: Procedures & Functions
Syntax: INT(numeric_expression)
Returns the largest integer less than or equal to a numeric expression.
Example:
PRINT INT(2.8)Output:
2
For negative numbers, it mathematically floors downwards (e.g., -2.2 becomes -3).
IntPos = INT(2.8)
IntNeg = INT(-2.2)Memory State (End of Execution):
IntPos = 2 (number)
IntNeg = -3 (number)
Syntax: FIX(numeric_expression)
Returns the truncated integer part of a numeric expression.
Example:
PRINT FIX(-2.8)Output:
-2
Unlike INT, it strictly removes the fractional part towards zero without flooring downwards.
FixPos = FIX(2.8)
FixNeg = FIX(-2.8)Memory State (End of Execution):
FixPos = 2 (number)
FixNeg = -2 (number)
Syntax: CINT(numeric_expression)
Rounds a numeric expression to the nearest integer.
Example:
PRINT CINT(2.6)Output:
3
CRITICAL QUIRK: QBasic employs 'Banker's Rounding'. If the fractional part is exactly .5, it rounds to the nearest EVEN integer.
CintUp = CINT(2.6)
CintHalfEven = CINT(2.5)
CintHalfOdd = CINT(3.5)Memory State (End of Execution):
CintUp = 3 (number)
CintHalfEven = 2 (number)
CintHalfOdd = 4 (number)
Syntax: expression1 / expression2
Divides two numbers and returns a floating-point result.
Example:
PRINT 5 / 2Output:
2.5
Operands are not rounded before the operation, and the result retains fractional precision.
FloatDiv! = 5 / 2Memory State (End of Execution):
FloatDiv! = 2.5 (number)
Syntax: expression1 \ expression2
Divides two numbers and returns an integer result.
Example:
PRINT 5 \ 2Output:
2
CRITICAL QUIRK: Both operands are rounded to integers (Banker's Rounding) BEFORE the division occurs. Using float suffix (!) prevents DEFINT masking during tests. Evaluates rounding of .5 to the nearest even integer.
IntDiv! = 5 \ 2
IntDivRound! = 5.6 \ 1.9
IntDivBankerEven! = 2.5 \ 1
IntDivBankerOdd! = 3.5 \ 1Memory State (End of Execution):
IntDiv! = 2 (number)
IntDivRound! = 3 (number)
IntDivBankerEven! = 2 (number)
IntDivBankerOdd! = 4 (number)
Syntax: expression1 MOD expression2
Divides two numbers and returns the integer remainder.
Example:
PRINT 10 MOD 3Output:
1
Like the backslash operator, MOD rounds its operands to integers BEFORE performing the operation. The result inherits the sign of the first operand. Using float suffix (!) prevents DEFINT masking during tests.
ModNorm! = 10 MOD 3
ModNeg! = -10 MOD 3
ModRound! = 10.6 MOD 3Memory State (End of Execution):
ModNorm! = 1 (number)
ModNeg! = -1 (number)
ModRound! = 2 (number)
Syntax: ABS(numeric_expression)
Returns the absolute value of a numeric expression.
Example:
PRINT ABS(-42)Output:
42
Standard arithmetic absolute conversion.
AbsVal = ABS(-42)Memory State (End of Execution):
AbsVal = 42 (number)
Syntax: SQR(numeric_expression)
Returns the square root of a numeric expression.
Example:
PRINT SQR(16)Output:
4
Passing a negative number natively throws an 'Illegal function call' exception.
SqrVal = SQR(16)Memory State (End of Execution):
SqrVal = 4 (number)
Syntax: SIN(angle)
Returns the trigonometric sine of an angle (in radians).
Example:
PRINT SIN(0)Output:
0
To avoid floating-point precision mismatch assertions between MS-DOS x87 architecture and modern V8 IEEE-754, the test result is multiplied by 1000 and clamped to an integer.
SinZero = CINT(SIN(0) * 1000)Memory State (End of Execution):
SinZero = 0 (number)
Syntax: COS(angle)
Returns the trigonometric cosine of an angle (in radians).
Example:
PRINT COS(0)Output:
1
To avoid floating-point precision mismatch assertions between MS-DOS x87 architecture and modern V8 IEEE-754, the test result is multiplied by 1000 and clamped to an integer.
CosZero = CINT(COS(0) * 1000)Memory State (End of Execution):
CosZero = 1000 (number)
Syntax: TAN(angle)
Returns the trigonometric tangent of an angle (in radians).
Example:
PRINT TAN(0)Output:
0
To avoid floating-point precision mismatch assertions between MS-DOS x87 architecture and modern V8 IEEE-754, the test result is multiplied by 1000 and clamped to an integer.
TanZero = CINT(TAN(0) * 1000)Memory State (End of Execution):
TanZero = 0 (number)
Syntax: ATN(numeric_expression)
Returns the arctangent of a numeric expression (in radians).
Example:
PRINT ATN(0)Output:
0
To avoid floating-point precision mismatch assertions between MS-DOS x87 architecture and modern V8 IEEE-754, the test result is multiplied by 1000 and clamped to an integer.
AtnZero = CINT(ATN(0) * 1000)Memory State (End of Execution):
AtnZero = 0 (number)
Syntax: EXP(numeric_expression)
Returns 'e' (the base of natural logarithms) raised to the power of the specified expression.
Example:
PRINT EXP(0)Output:
1
To avoid floating-point precision mismatch assertions between MS-DOS x87 architecture and modern V8 IEEE-754, the test result is multiplied by 1000 and clamped to an integer.
ExpZero = CINT(EXP(0) * 1000)Memory State (End of Execution):
ExpZero = 1000 (number)
Syntax: LOG(numeric_expression)
Returns the natural logarithm of a numeric expression.
Example:
PRINT LOG(1)Output:
0
To avoid floating-point precision mismatch assertions between MS-DOS x87 architecture and modern V8 IEEE-754, the test result is multiplied by 1000 and clamped to an integer.
LogOne = CINT(LOG(1) * 1000)Memory State (End of Execution):
LogOne = 0 (number)
Syntax: STR$(numeric_expression)
Returns a string representation of the value of a numeric expression.
Example:
PRINT STR$(42)Output:
42
CRITICAL QUIRK: Positive numbers and zero are strictly prefixed with a leading space (acting as an implicit '+' sign). Negative numbers are prefixed by '-' without a leading space.
PosStr$ = STR$(42)
ZeroStr$ = STR$(0)
NegStr$ = STR$(-15)Memory State (End of Execution):
PosStr$ = " 42" (string)
ZeroStr$ = " 0" (string)
NegStr$ = "-15" (string)
Syntax: HEX$(numeric_expression)
Returns a string that represents the hexadecimal value of the decimal argument.
Example:
PRINT HEX$(255)Output:
FF
QBasic rounds floats to the nearest integer before conversion (Banker's rounding). Standard numbers are treated as 16-bit integers (FFFF for -1), while Long integers (&) or values exceeding -32768 fallback to 32-bit two's complement. Output is always uppercase.
NormHex$ = HEX$(255)
RoundDownHex$ = HEX$(12.4)
RoundUpHex$ = HEX$(12.6)
NegTwosComp$ = HEX$(-1)
LargeNegTwosComp$ = HEX$(-100000)
ZeroHex$ = HEX$(0)Memory State (End of Execution):
NormHex$ = "FF" (string)
RoundDownHex$ = "C" (string)
RoundUpHex$ = "D" (string)
NegTwosComp$ = "FFFF" (string)
LargeNegTwosComp$ = "FFFE7960" (string)
ZeroHex$ = "0" (string)
Syntax: VAL(stringexpression$)
Returns the numeric value of a string of characters.
Example:
PRINT VAL("123.45")Output:
123.45
Accurately parses MS-DOS legacy radix prefixes: Hexadecimal (&H) and Octal (&O). Invalid input gracefully falls back to 0 without throwing an exception.
NormVal! = VAL("123.45")
HexVal = VAL("&H10")
HexLowVal = VAL("&hc")
OctVal = VAL("&O10")
GarbageVal = VAL("NOTANUMBER")Memory State (End of Execution):
NormVal! = 123.45 (number)
HexVal = 16 (number)
HexLowVal = 12 (number)
OctVal = 8 (number)
GarbageVal = 0 (number)
Syntax: LEFT$(stringexpression$, n%)
Returns a string consisting of the leftmost n% characters of a string.
Example:
PRINT LEFT$("SYSCLONE", 3)Output:
SYS
If N exceeds the string length, the entire string is safely returned without throwing an out-of-bounds error.
BaseStr$ = "SYSCLONE"
NormLeft$ = LEFT$(BaseStr$, 3)
OverLeft$ = LEFT$(BaseStr$, 50)Memory State (End of Execution):
NormLeft$ = "SYS" (string)
OverLeft$ = "SYSCLONE" (string)
Syntax: RIGHT$(stringexpression$, n%)
Returns a string consisting of the rightmost n% characters of a string.
Example:
PRINT RIGHT$("SYSCLONE", 5)Output:
CLONE
Similar to LEFT$, an oversized N returns the whole string safely.
BaseStr$ = "SYSCLONE"
NormRight$ = RIGHT$(BaseStr$, 5)
OverRight$ = RIGHT$(BaseStr$, 50)Memory State (End of Execution):
NormRight$ = "CLONE" (string)
OverRight$ = "SYSCLONE" (string)
Syntax: MID$(stringexpr$, start%[, length%])
Returns a substring of a specified length starting at a 1-based index.
Example:
PRINT MID$("SYSCLONE", 4, 2)Output:
CL
If the length parameter is omitted, it returns the remainder of the string. Out-of-bounds start indices yield an empty string without throwing an error.
BaseStr$ = "SYSCLONE"
NormMid$ = MID$(BaseStr$, 4, 2)
NoLenMid$ = MID$(BaseStr$, 4)
OutBoundsMid$ = MID$(BaseStr$, 99, 2)Memory State (End of Execution):
NormMid$ = "CL" (string)
NoLenMid$ = "CLONE" (string)
OutBoundsMid$ = "" (string)
Syntax: SPACE$(n%)
Returns a string of n% spaces.
Example:
PRINT "A" + SPACE$(3) + "B"Output:
A B
Negative or zero lengths safely return an empty string.
SpcStr$ = SPACE$(3)Memory State (End of Execution):
SpcStr$ = " " (string)
Syntax: STRING$(n%, {stringexpression$ | ascii_code%})
Returns a string of characters, n% long, consisting of a single character.
Example:
PRINT STRING$(4, "A")Output:
AAAA
The character can be specified either as a numeric ASCII/CP437 code, or as a string (in which case only the first character is used).
StrChar$ = STRING$(4, "A")
StrLong$ = STRING$(3, "XYZ")
StrCode$ = STRING$(3, 65)Memory State (End of Execution):
StrChar$ = "AAAA" (string)
StrLong$ = "XXX" (string)
StrCode$ = "AAA" (string)
Syntax: LEN(stringexpression$)
Returns the number of characters in a string.
Example:
PRINT LEN("HELLO")Output:
5
Standard length calculation.
StrLen = LEN("HELLO")Memory State (End of Execution):
StrLen = 5 (number)
Syntax: UCASE$(stringexpression$)
Returns a string expression with all letters converted to uppercase.
Example:
PRINT UCASE$("hello")Output:
HELLO
Transforms lowercase ASCII characters to uppercase without affecting symbols or numbers.
UpStr$ = UCASE$("hello")Memory State (End of Execution):
UpStr$ = "HELLO" (string)
Syntax: LCASE$(stringexpression$)
Returns a string expression with all letters converted to lowercase.
Example:
PRINT LCASE$("HELLO")Output:
hello
Transforms uppercase ASCII characters to lowercase without affecting symbols or numbers.
LowStr$ = LCASE$("HELLO")Memory State (End of Execution):
LowStr$ = "hello" (string)
Syntax: LTRIM$(stringexpression$)
Returns a copy of a string with leading (leftmost) spaces removed.
Example:
PRINT LTRIM$(" TEXT")Output:
TEXT
Crucial for cleaning up STR$ outputs which naturally contain leading spaces for positive numbers.
LTrimStr$ = LTRIM$(" TEXT")Memory State (End of Execution):
LTrimStr$ = "TEXT" (string)
Syntax: RTRIM$(stringexpression$)
Returns a copy of a string with trailing (rightmost) spaces removed.
Example:
PRINT RTRIM$("TEXT ")Output:
TEXT
Often used to trim fixed-length strings (STRING * N) that are padded with spaces on the right.
RTrimStr$ = RTRIM$("TEXT ")Memory State (End of Execution):
RTrimStr$ = "TEXT" (string)
Syntax: CHR$(ascii_code%)
Returns a one-character string whose ASCII/CP437 code is the argument.
Example:
PRINT CHR$(65)Output:
A
Sysclone maps these directly to the MS-DOS Code Page 437 (CP437) for graphical block character fidelity.
Char$ = CHR$(65)Memory State (End of Execution):
Char$ = "A" (string)
Syntax: ASC(stringexpression$)
Returns the ASCII/CP437 character code corresponding to the first letter in a string.
Example:
PRINT ASC("A")Output:
65
If the string is empty, true QBasic throws an 'Illegal function call' error.
AscVal = ASC("A")Memory State (End of Execution):
AscVal = 65 (number)
Syntax: INSTR([start%,] string1$, string2$)
Returns the character position of the first occurrence of a string in another.
Example:
PRINT INSTR("HELLO WORLD", "WORLD")Output:
7
Uses 1-based indexing. If an optional start index is provided, the search begins there. Returns 0 if the substring is not found or if the start index is out of bounds.
FoundIdx = INSTR("HELLO WORLD", "WORLD")
OffsetIdx = INSTR(3, "HELLO WORLD, HELLO", "HELLO")
NotFoundIdx = INSTR("HELLO", "Z")
OutBoundsIdx = INSTR(100, "HELLO", "L")Memory State (End of Execution):
FoundIdx = 7 (number)
OffsetIdx = 14 (number)
NotFoundIdx = 0 (number)
OutBoundsIdx = 0 (number)
Syntax: FOR counter = start TO end [STEP increment] ... NEXT [counter]
Iterates a block of code based on a counter variable. The loop continues until the counter passes the terminal value.
Example:
FOR I = 1 TO 3
PRINT I;
NEXTOutput:
1 2 3
CRITICAL QUIRKS:
- Terminal Overshoot: The loop iterator always increments past the limit, leaving the leaked value in memory.
- Bound Immutability: The TO and STEP expressions are evaluated exactly ONCE upon entering the loop. Mutating their source variables inside the loop has no effect.
- Iterator Mutation: Modifying the counter explicitly inside the loop directly affects the remaining cycles.
' 1. Terminal Overshoot (Positive & Negative)
CountA = 0: FOR I = 1 TO 5: CountA = CountA + 1: NEXT
CountB = 0: FOR J = 5 TO 1 STEP -1: CountB = CountB + 1: NEXT
' 2. Bound Immutability
Limit = 3: Inc = 1: Runs = 0
FOR K = 1 TO Limit STEP Inc
Runs = Runs + 1
Limit = 10
Inc = 5
NEXT
' 3. Iterator Mutation
MutRuns = 0
FOR M = 1 TO 5
MutRuns = MutRuns + 1
M = M + 1
NEXTMemory State (End of Execution):
CountA = 5 (number)
I = 6 (number)
CountB = 5 (number)
J = 0 (number)
Runs = 3 (number)
K = 4 (number)
Limit = 10 (number)
Inc = 5 (number)
MutRuns = 3 (number)
M = 7 (number)
Syntax: EXIT FOR
Immediately terminates the execution of the innermost FOR...NEXT loop, transferring control to the statement following the NEXT keyword.
Example:
FOR I = 1 TO 5
IF I = 3 THEN EXIT FOR
PRINT I;
NEXTOutput:
1 2
CRITICAL QUIRKS:
- Iterator Retention: Unlike a naturally completed loop which overshoots, exiting prematurely leaves the iterator at its exact current value.
- Scope Isolation: In nested loops,
EXIT FORstrictly breaks only the deepest active loop without affecting outer iterators. - Short-Circuit: Any statements remaining in the loop body after the
EXIT FORcommand are immediately bypassed.
' 1. Basic Exit and Iterator Retention
TargetVal = 0: FinalI = 0
FOR I = 5 TO 1 STEP -1
IF I = 3 THEN
TargetVal = I
EXIT FOR
END IF
NEXT
FinalI = I
' 2. Scope Isolation (Nested Loops)
OuterCount = 0: InnerCount = 0
FOR Outer = 1 TO 3
OuterCount = OuterCount + 1
FOR Inner = 1 TO 5
IF Inner = 2 THEN EXIT FOR
InnerCount = InnerCount + 1
NEXT
NEXT
FinalOuter = Outer
FinalInner = Inner
' 3. Short-Circuit Execution
Flag = 0: FinalK = 0
FOR K = 1 TO 5
EXIT FOR
Flag = 99
NEXT
FinalK = KMemory State (End of Execution):
TargetVal = 3 (number)
FinalI = 3 (number)
OuterCount = 3 (number)
FinalOuter = 4 (number)
InnerCount = 3 (number)
FinalInner = 2 (number)
Flag = 0 (number)
FinalK = 1 (number)
Syntax: DO [{WHILE | UNTIL} condition] ... LOOP
Evaluates the condition BEFORE executing the block. If the initial condition is unmet, the loop executes 0 times. Truthiness is strict: exactly 0 is FALSE, any other number is TRUE.
Example:
Cond = 0
DO WHILE Cond
PRINT "Never prints"
LOOPOutput:
Proves that a pre-test loop bypasses the block entirely if the condition is false (WHILE 0) or already true (UNTIL -1). Also validates arbitrary float truthiness.
' 1. WHILE False -> 0 runs
RunsPreWhile = 0
DO WHILE 0
RunsPreWhile = RunsPreWhile + 1
LOOP
' 2. UNTIL True -> 0 runs
RunsPreUntil = 0
DO UNTIL -1
RunsPreUntil = RunsPreUntil + 1
LOOP
' 3. WHILE Arbitrary Float (True) -> 1 run
RunsFloat = 0
CondF = 42.5
DO WHILE CondF
RunsFloat = RunsFloat + 1
CondF = 0
LOOPMemory State (End of Execution):
RunsPreWhile = 0 (number)
RunsPreUntil = 0 (number)
RunsFloat = 1 (number)
Syntax: DO ... LOOP [{WHILE | UNTIL} condition]
Evaluates the condition AFTER executing the block. The loop is guaranteed to execute AT LEAST ONCE, regardless of the initial condition.
Example:
Cond = 0
DO
PRINT "Prints exactly once"
LOOP WHILE CondOutput:
Prints exactly once
Proves the post-test execution flow. A WHILE condition initialized to 0 (FALSE) will still allow exactly one iteration before exiting.
RunsPostA = 0
DO
RunsPostA = RunsPostA + 1
LOOP WHILE 0
RunsPostB = 0
DO
RunsPostB = RunsPostB + 1
LOOP UNTIL -1Memory State (End of Execution):
RunsPostA = 1 (number)
RunsPostB = 1 (number)
Syntax: GOSUB label ... label: ... RETURN
Branches to, and returns from, a subroutine within the same module. Variables are fully shared with the caller.
Example:
GOSUB PrintMsg
END
PrintMsg:
PRINT "Hello"
RETURNOutput:
Hello
CRITICAL QUIRKS:
- Scope Sharing: GOSUB does not create a new variable scope. It shares the exact same memory space as the caller.
- Internal Jumps: A GOTO inside a GOSUB block strictly shifts the internal pointer without breaking the GOSUB loop.
- Spatial Return: The RETURN statement is strictly required to escape the GOSUB isolation loop and resume main execution.
GlobalVar = 10: StepId = 0
GOSUB RoutineStart
StepId = 99
GOTO EndTest
RoutineStart:
GlobalVar = GlobalVar * 2
GOTO RoutineSkip
GlobalVar = 0 ' MUST NEVER EXECUTE
RoutineSkip:
StepId = 1
RETURN
EndTest:Memory State (End of Execution):
GlobalVar = 20 (number)
StepId = 99 (number)
Syntax: SELECT CASE testexpression ... CASE {expressionlist | IS relation | start TO end} ... [CASE ELSE] ... END SELECT
Executes one of several blocks of statements depending on the value of an expression. Supports exact matches, inclusive ranges (TO), and relational comparisons (IS).
Example:
Score = 85
SELECT CASE Score
CASE IS >= 90
PRINT "Grade: A"
CASE 80 TO 89
PRINT "Grade: B"
CASE 0, 1, 2
PRINT "Grade: Z"
CASE ELSE
PRINT "Unknown"
END SELECTOutput:
Grade: B
CRITICAL QUIRKS:
- Single Evaluation: The base test expression is evaluated exactly once.
- No Fallthrough: Unlike C or JavaScript, QBasic executes ONLY the first matching CASE block and then exits the SELECT entirely.
- Range Matching: The 'TO' keyword denotes an inclusive mathematical range.
- Relational Matching: The 'IS' keyword allows direct relational comparisons (>, <, >=, <=, <>).
' 1. Exact Match, Range (TO), and No Fallthrough
TestVal = 5: Result = 0: ExecCount = 0
SELECT CASE TestVal
CASE 1, 2, 3
Result = 1: ExecCount = ExecCount + 1
CASE 4 TO 6
Result = 2: ExecCount = ExecCount + 1
CASE 5
Result = 3: ExecCount = ExecCount + 1 ' MUST NEVER EXECUTE (No fallthrough)
CASE ELSE
Result = 4: ExecCount = ExecCount + 1
END SELECT
' 2. Relational Matching (CASE IS)
Score = 85: Grade = 0
SELECT CASE Score
CASE IS >= 90
Grade = 1
CASE IS >= 80
Grade = 2
CASE IS < 50
Grade = 3
END SELECTMemory State (End of Execution):
Result = 2 (number)
ExecCount = 1 (number)
Grade = 2 (number)
Syntax: WHILE condition ... WEND
Executes a series of statements as long as a specified condition is true. It is the legacy predecessor to DO WHILE...LOOP.
Example:
I = 1
WHILE I < 4
PRINT I;
I = I + 1
WENDOutput:
1 2 3
CRITICAL QUIRKS:
- No Native Exit: Unlike DO or FOR, QBasic does not support 'EXIT WHILE'. Early termination must be achieved via GOTO or RETURN.
- Pre-test Only: The condition is evaluated before the loop begins. If initially false (0), the body executes 0 times.
Runs = 0: ValA = 1
WHILE ValA
Runs = Runs + 1
IF Runs = 2 THEN GOTO EscapeWhile
WEND
EscapeWhile:
FalseRuns = 0
WHILE 0
FalseRuns = 99
WENDMemory State (End of Execution):
Runs = 2 (number)
FalseRuns = 0 (number)
Syntax: Variable = value
By default, QBasic treats all undeclared variables without a type suffix as Single-precision floats (!). They retain fractional values without rounding.
Example:
DefaultFloat = 3.14
PRINT DefaultFloatOutput:
3.14
Ensures the engine natively defaults to Single precision when no DEF type or suffix is active.
DefaultFloat = 3.14Memory State (End of Execution):
DefaultFloat = 3.14 (number)
Syntax: DEFINT letter[-letter]
Sets the default data type for variables to Integer.
Example:
DEFINT A-Z
Score = 10.8
PRINT ScoreOutput:
11
Forces all untyped variables starting with specified letters to automatically become integers. Floating-point assignments to these variables are mathematically rounded (Banker's rounding).
DEFINT A-Z
ImplicitIntA = 2.5
ImplicitIntB = 2.6Memory State (End of Execution):
ImplicitIntA = 2 (number)
ImplicitIntB = 3 (number)
Syntax: DEFSNG letter[-letter]
Sets the default data type for variables to Single-precision float.
Example:
DEFSNG A-Z
Score = 10.8
PRINT ScoreOutput:
10.8
Forces untyped variables to default to Single-precision. This preserves fractional values without mathematical rounding. While QBasic defaults to Single precision natively, DEFSNG is used to explicitly override a previous DEFINT.
DEFINT A-Z
DEFSNG A-Z
ImplicitSng = 5.8Memory State (End of Execution):
ImplicitSng = 5.8 (number)
Syntax: Variable[%, &, !, #, $]
Explicit type declaration suffixes.
Example:
DEFINT A-Z
PRINT 5.5!Output:
5.5
Even if DEFINT is active, appending a specific type suffix (like ! for Single Precision Float) overrides the implicit rule and preserves the fractional value.
DEFINT A-Z
OverrideFloat! = 3.14Memory State (End of Execution):
OverrideFloat! = 3.14 (number)
Syntax: DIM variable AS type
Declares a variable and allocates memory space.
Example:
DIM Name AS STRING
Name = "NIBBLES"
PRINT Name$Output:
NIBBLES
Declaring a variable with an explicit type (e.g., AS STRING) internally links it to its MS-DOS suffixed counterpart. Writing to the base name updates the suffixed name, as they share the exact same memory pointer.
DIM AliasTest AS STRING
AliasTest = "NIBBLES"
Extracted$ = AliasTest$Memory State (End of Execution):
Extracted$ = "NIBBLES" (string)
Syntax: DIM variable AS STRING * length
Declares a string with a fixed memory length.
Example:
DIM S AS STRING * 5
S = "HI"
PRINT S; "THERE"Output:
HI THERE
Allocating a Fixed-Length String locks a specific memory block. If a shorter string is assigned, it is automatically padded with spaces on the right to fill the block.
DIM PadStr AS STRING * 5
PadStr = "HI"
PadLen = LEN(PadStr)Memory State (End of Execution):
PadStr = "HI " (string)
PadLen = 5 (number)
Syntax: DIM variable AS STRING * length
Prevents memory overflow during assignment.
Example:
DIM S AS STRING * 3
S = "123456"
PRINT SOutput:
123
If a string longer than the locked memory block is assigned, MS-DOS silently truncates the overflow without throwing an error.
DIM TruncStr AS STRING * 3
TruncStr = "123456"Memory State (End of Execution):
TruncStr = "123" (string)
Syntax: SWAP variable1, variable2
Exchanges the values of two variables of the same type. Works with scalars, array elements, and UDT properties.
Example:
A = 1: B = 2
SWAP A, B
PRINT A; BOutput:
2 1
CRITICAL QUIRKS:
- Memory Type Integrity: SWAP must work seamlessly across direct environment variables and complex array indices.
- Reference Decoupling: In memory-managed languages (like JS), swapping object references directly can entangle them. A purist VM must deep-clone the values to safely exchange them.
- Fixed-Length Preservation: Swapping UDTs or Fixed-Length Strings must mutate the memory IN PLACE, otherwise the fixed-length constraint is permanently destroyed.
' 1. Scalar Swap
ValA = 10: ValB = 99
SWAP ValA, ValB
' 2. Array Indices Swap
DIM SwapArr(2)
SwapArr(1) = 42: SwapArr(2) = 77
SWAP SwapArr(1), SwapArr(2)
ArrRes1 = SwapArr(1)
ArrRes2 = SwapArr(2)
' 3. Fixed-Length String Swap Integrity
TYPE SwapType
F AS STRING * 4
END TYPE
DIM ST1 AS SwapType, ST2 AS SwapType
ST1.F = "A"
ST2.F = "B"
SWAP ST1, ST2
ST1.F = "Z"
FixedLenAfterSwap = LEN(ST1.F)Memory State (End of Execution):
ValA = 99 (number)
ValB = 10 (number)
ArrRes1 = 77 (number)
ArrRes2 = 42 (number)
FixedLenAfterSwap = 4 (number)
Syntax: ERASE arrayname [, arrayname] ...
Reinitializes elements of static arrays and completely deallocates dynamic arrays from memory.
Example:
DIM Arr(5)
Arr(1) = 42
ERASE Arr
PRINT Arr(1)Output:
0
CRITICAL QUIRKS:
- Static Array Reset: For statically dimensioned arrays, ERASE does not destroy the array footprint. It iterates and resets numeric arrays to 0, and string arrays to empty strings ("").
- Type Protection: Erasing an array of UDTs containing Fixed-Length strings must softly reset the string's content without destroying its prototype length.
' 1. Numeric Array Erase
DIM NumArr(2)
NumArr(1) = 42: NumArr(2) = 99
ERASE NumArr
CheckNum1 = NumArr(1)
CheckNum2 = NumArr(2)
' 2. String Array Erase
DIM StrArr$(1)
StrArr$(1) = "Hello World"
ERASE StrArr$
CheckStr$ = StrArr$(1)
' 3. UDT with Fixed-Length String Erase
TYPE EraseType
F AS STRING * 4
END TYPE
DIM EArr(1) AS EraseType
EArr(1).F = "TEST"
ERASE EArr
EArr(1).F = "X"
FixedLenAfterErase = LEN(EArr(1).F)Memory State (End of Execution):
CheckNum1 = 0 (number)
CheckNum2 = 0 (number)
CheckStr$ = "" (string)
FixedLenAfterErase = 4 (number)
Syntax: CALL subname([argumentlist])
Transfers control to a subroutine. Arguments are passed by reference by default, allowing the subroutine to directly modify the caller's variables.
Example:
A = 10
CALL Multiply(A)
PRINT A
END
SUB Multiply(X)
X = X * 2
END SUBOutput:
20
CRITICAL QUIRKS:
- Pass by Reference (Default): Passing a raw variable directly links the subroutine's parameter to the caller's memory address.
- Pass by Value (Forced): Enclosing a variable in extra parentheses explicitly evaluates it as an expression (an R-Value), forcing a disconnected copy to be passed.
- Multiple Parentheses: Nesting parentheses, such as (((X))), must strictly resolve as a single R-Value without corrupting the AST or evaluation.
RefVar = 10
ValVar = 10
DeepVar = 10
CALL ScopeTest(RefVar, (ValVar), (((DeepVar))))
GOTO EndCallTest
SUB ScopeTest (ArgRef, ArgVal, ArgDeep)
ArgRef = 99
ArgVal = 99
ArgDeep = 99
END SUB
EndCallTest:Memory State (End of Execution):
RefVar = 99 (number)
ValVar = 10 (number)
DeepVar = 10 (number)