Auto-generated from Truth Vectors. This document serves as the absolute specification for MS-DOS Turbo Pascal behavior.
Addition Operator (+) • Address Operator (@) • ARRAY (Arbitrary Integer Bounds) • ARRAY (Character Bounds) • ARRAY (Multi-Dimensional) • Bit Shift Left (SHL) • Bit Shift Right (SHR) • Bitwise AND Operator • Bitwise NOT Operator • Bitwise OR Operator • Bitwise XOR Operator • Boolean Type Fundamentals • CASE..OF (Multiple Branching) • Chr Function • Copy (Function) • Dec Procedure • Delete (Procedure) • Dereference Operator (^) • Equality Operator (=) • FOR..DOWNTO (Decrementing Loop) • FOR..TO (Incrementing Loop) • Function (Declaration and Return) • Greater Than Operator (>) • Greater Than or Equal Operator (>=) • IF..THEN..ELSE (Conditional Branching) • Inc Procedure • Inequality Operator (<>) • Insert (Procedure) • Int Function • Integer Division (DIV) • Length (Function) • Less Than Operator (<) • Less Than or Equal Operator (<=) • Logical AND Operator • Logical NOT Operator • Logical OR Operator • Logical XOR Operator • Modulo Operator (MOD) • Multiplication Operator (*) • Operator Precedence Matrix • Ord Function • Parameters (Pass by Value) • Pos (Function) • Procedure (Declaration and Call) • Real Division Operator (/) • RECORD (Basic Field Access) • REPEAT..UNTIL (Post-Condition Loop) • Round Function • Scope (Global Visibility) • Scope (Local and Variable Shadowing) • Set Membership Operator (IN) • SizeOf Function • Str (Integer Basic Conversion) • Str (Integer Width Overflow) • Str (Integer Width Padding) • Str (Real Fixed-Point Conversion) • Str (Real Fixed-Point Padding) • Str (Real Fixed-Point Rounding) • String (1-Based Access & Length Byte) • String Concatenation Operator (+) • Subtraction Operator (-) • Succ and Pred Functions • Trunc Function • Unary Minus Operator (-) • Val (Procedure: String to Number) • VAR Parameters (Pass by Reference) • WHILE..DO (Pre-Condition Loop) • WITH (Record Scope Resolution)
- STDLIB: Formatting Engine (Str)
- CORE: Logic, Boolean & Bitwise
- STDLIB: Math Built-ins
- CORE: Operators & Precedence
- Unary Minus Operator (-)
- Address Operator (@)
- Dereference Operator (^)
- Multiplication Operator (*)
- Real Division Operator (/)
- Addition Operator (+)
- Subtraction Operator (-)
- String Concatenation Operator (+)
- Equality Operator (=)
- Inequality Operator (<>)
- Less Than Operator (<)
- Greater Than Operator (>)
- Less Than or Equal Operator (<=)
- Greater Than or Equal Operator (>=)
- Set Membership Operator (IN)
- Operator Precedence Matrix
- STDLIB: String Manipulation & Casting
- STDLIB: System & Ordinal Routines
- CORE: Control Flow & Loops
- CORE: Data Structures (Arrays & Records)
- CORE: Procedures, Functions & Scope
Syntax: procedure Str(X: Integer; var S: String);
Converts an integer to its string representation. Unlike some other dialects, Turbo Pascal does not prepend a leading space for positive numbers. Negative numbers are strictly prefixed with a minus sign.
Example:
Str(42, S);
WriteLn(S);Output:
42
Validates that basic conversion handles sign characters correctly without implicit padding.
Str(42, StrIntPos);
Str(-42, StrIntNeg);Memory State (End of Execution):
StrIntPos = "42" (string)
StrIntNeg = "-42" (string)
Syntax: procedure Str(X: Integer : Width; var S: String);
When a Width parameter is provided (X:Width), the resulting string is right-aligned and padded with leading spaces if the number's length is less than the specified Width. The minus sign of a negative number is included in this width calculation.
Example:
Str(42:5, S);
WriteLn(S);Output:
42
Validates right-alignment and space padding for both positive and negative integers.
Str(42:5, StrPadPos);
Str(-42:5, StrPadNeg);Memory State (End of Execution):
StrPadPos = " 42" (string)
StrPadNeg = " -42" (string)
Syntax: procedure Str(X: Integer : Width; var S: String);
If the specified Width is smaller than the actual number of characters required to represent the integer, Turbo Pascal ignores the Width constraint and outputs the full number without truncation.
Example:
Str(12345:2, S);
WriteLn(S);Output:
12345
Validates that data integrity takes precedence over the formatting width constraint.
Str(12345:2, StrIntOverflow);Memory State (End of Execution):
StrIntOverflow = "12345" (string)
Syntax: procedure Str(X: Real : Width : Decimals; var S: String);
By default, Real numbers are converted using scientific notation. Adding a second colon and a Decimals parameter forces fixed-point notation. A Width of 0 instructs the engine to use exactly as much space as needed, without leading padding.
Example:
Str(3.14159:0:2, S);
WriteLn(S);Output:
3.14
Validates the override of scientific notation to standard fixed-point decimal string representation.
Str(3.14159:0:2, StrRealFix);Memory State (End of Execution):
StrRealFix = "3.14" (string)
Syntax: procedure Str(X: Real : Width : Decimals; var S: String);
When both Width and Decimals are provided, the total length of the resulting string (including the integer part, the decimal point, and the decimal digits) is padded with leading spaces to meet the Width requirement.
Example:
Str(3.14:6:2, S);
WriteLn(S);Output:
3.14
Validates the global width calculation for real numbers (3 chars for '3.1', plus 1 for '4' = 4 chars. Padded to 6 results in 2 leading spaces).
Str(3.14:6:2, StrRealPad);Memory State (End of Execution):
StrRealPad = " 3.14" (string)
Syntax: procedure Str(X: Real : Width : Decimals; var S: String);
When formatting constraints reduce the number of visible decimals, the Str procedure mathematically rounds the last visible digit (rounding half away from zero) rather than simply truncating the string.
Example:
Str(3.8:0:0, S);
WriteLn(S);Output:
4
Validates that formatting is not just string manipulation, but involves arithmetic rounding.
Str(3.15:0:1, StrRealRoundUp);
Str(3.14:0:1, StrRealRoundDown);
Str(3.8:0:0, StrRealNoDecimals);Memory State (End of Execution):
StrRealRoundUp = "3.2" (string)
StrRealRoundDown = "3.1" (string)
StrRealNoDecimals = "4" (string)
Syntax: Type Boolean = (False, True);
Turbo Pascal implements a strict Boolean type natively. In memory, it is an ordinal type where False evaluates to 0 and True evaluates to 1.
Example:
WriteLn(Ord(True));Output:
1
Validates the native ordinal memory mapping of Boolean values.
BoolTrue := True;
BoolFalse := False;
OrdTrue := Ord(True);
OrdFalse := Ord(False);Memory State (End of Execution):
BoolTrue = true (boolean)
BoolFalse = false (boolean)
OrdTrue = 1 (integer)
OrdFalse = 0 (integer)
Syntax: NOT Operand: Boolean; { Returns Boolean }
Inverts the truth value of a Boolean expression.
Example:
WriteLn(NOT True);Output:
FALSE
When applied to a Boolean type, NOT performs a pure logical negation.
NotTrue := NOT True;
NotFalse := NOT False;Memory State (End of Execution):
NotTrue = false (boolean)
NotFalse = true (boolean)
Syntax: Operand1: Boolean AND Operand2: Boolean; { Returns Boolean }
Performs a logical conjunction on two Boolean expressions. By default, Turbo Pascal employs short-circuit evaluation ({$B-}).
Example:
WriteLn(True AND False);Output:
FALSE
CRITICAL ARCHITECTURE: If the first operand of an AND is False, the second operand is skipped entirely. This test validates short-circuiting by attempting a division by zero using a variable (to bypass compile-time constant folding). If evaluated at runtime, it would trigger Runtime Error 200.
LogAndBase := True AND False;
ZeroVarAnd := 0;
SurvivedAndShort := False;
IF (False) AND (10 DIV ZeroVarAnd = 1) THEN SurvivedAndShort := False ELSE SurvivedAndShort := True;Memory State (End of Execution):
LogAndBase = false (boolean)
ZeroVarAnd = 0 (integer)
SurvivedAndShort = true (boolean)
Syntax: Operand1: Boolean OR Operand2: Boolean; { Returns Boolean }
Performs a logical disjunction on two Boolean expressions. Also subject to short-circuit evaluation ({$B-}).
Example:
WriteLn(True OR False);Output:
TRUE
CRITICAL ARCHITECTURE: If the first operand of an OR is True, the compiler knows the overall expression is True and skips the second operand.
LogOrBase := True OR False;
ZeroVarOr := 0;
SurvivedOrShort := False;
IF (True) OR (10 DIV ZeroVarOr = 1) THEN SurvivedOrShort := True ELSE SurvivedOrShort := False;Memory State (End of Execution):
LogOrBase = true (boolean)
ZeroVarOr = 0 (integer)
SurvivedOrShort = true (boolean)
Syntax: Operand1: Boolean XOR Operand2: Boolean; { Returns Boolean }
Performs a logical exclusive disjunction. Returns True if operands are strictly different.
Example:
WriteLn(True XOR True);Output:
FALSE
Unlike AND/OR, XOR cannot be short-circuited because both operands are always mathematically required to determine the final state.
LogXorDiff := True XOR False;
LogXorSame := True XOR True;Memory State (End of Execution):
LogXorDiff = true (boolean)
LogXorSame = false (boolean)
Syntax: NOT Operand: Integer; { Returns Integer }
Performs a bitwise one's complement operation on the binary representation of an ordinal integer type.
Example:
WriteLn(NOT 0);Output:
-1
Turbo Pascal overloads the NOT operator based on the operand type. When given an integer, it flips all bits (e.g., NOT 0 yields -1 in two's complement arithmetic).
BitNotZero := NOT 0;
BitNotPos := NOT 1;Memory State (End of Execution):
BitNotZero = -1 (integer)
BitNotPos = -2 (integer)
Syntax: Operand1: Integer AND Operand2: Integer; { Returns Integer }
Performs a bitwise logical AND between the bits of two integers.
Example:
WriteLn(170 AND 85);Output:
0
Overloaded for integers. Evaluates strictly at the bit level without any short-circuiting mechanics. (170 is $AA, 85 is $55).
BitAndEx := 170 AND 85;Memory State (End of Execution):
BitAndEx = 0 (integer)
Syntax: Operand1: Integer OR Operand2: Integer; { Returns Integer }
Performs a bitwise logical OR between the bits of two integers.
Example:
WriteLn(170 OR 85);Output:
255
Combines the bits of two integer values.
BitOrEx := 170 OR 85;Memory State (End of Execution):
BitOrEx = 255 (integer)
Syntax: Operand1: Integer XOR Operand2: Integer; { Returns Integer }
Performs a bitwise logical Exclusive OR between two integers.
Example:
WriteLn(170 XOR 255);Output:
85
Toggles bits where the mask has a 1.
BitXorEx := 170 XOR 255;Memory State (End of Execution):
BitXorEx = 85 (integer)
Syntax: Value: Integer SHL Count: Byte; { Returns Integer }
Shifts the bits of an integer value to the left by the specified count, filling vacated bits with zeros.
Example:
WriteLn(1 SHL 3);Output:
8
A low-level arithmetic shift, highly optimized by the compiler. Functionally equivalent to multiplying by 2^Count.
ShlEx := 1 SHL 3;Memory State (End of Execution):
ShlEx = 8 (integer)
Syntax: Value: Integer SHR Count: Byte; { Returns Integer }
Shifts the bits of an integer value to the right by the specified count, filling vacated bits with zeros.
Example:
WriteLn(8 SHR 1);Output:
4
Logical right shift. Equivalent to an integer division by 2^Count.
ShrEx := 8 SHR 1;Memory State (End of Execution):
ShrEx = 4 (integer)
Syntax: function Int(X: Real): Real;
Returns the integer part of a real number.
Example:
WriteLn(Int(2.8):0:2);Output:
2.00
The Int() function returns a REAL type, not an integer. It simply truncates the decimal part without rounding.
IntPos := Int(2.8);
IntNeg := Int(-2.8);Memory State (End of Execution):
IntPos = 2 (float)
IntNeg = -2 (float)
Syntax: function Trunc(X: Real): Longint;
Truncates a real-type value to an integer-type value.
Example:
WriteLn(Trunc(2.8));Output:
2
It removes the fractional part, rounding toward zero.
TruncPos := Trunc(2.8);
TruncNeg := Trunc(-2.8);Memory State (End of Execution):
TruncPos = 2 (number)
TruncNeg = -2 (number)
Syntax: function Round(X: Real): Longint;
Rounds a real-type value to the nearest integer. If the value is exactly halfway between two integers, it rounds to the number with the greatest absolute magnitude (away from zero).
Example:
WriteLn(Round(2.5));Output:
3
Turbo Pascal employs standard arithmetic rounding (rounding away from zero). A fractional part of exactly .5 will always be rounded to the number with the greatest absolute magnitude, meaning positive numbers round up and negative numbers round down.
RoundUp := Round(2.6);
RoundHalf := Round(2.5);
RoundHalfOdd := Round(3.5);
RoundNegHalf := Round(-2.5);Memory State (End of Execution):
RoundUp = 3 (number)
RoundHalf = 3 (number)
RoundHalfOdd = 4 (number)
RoundNegHalf = -3 (number)
Syntax: Operand1: Longint DIV Operand2: Longint; { Returns Longint }
Performs integer division. Truncates the result towards zero.
Example:
WriteLn(10 DIV 3);Output:
3
Unlike standard real division (/), DIV strictly returns an integer.
IntDiv := 10 DIV 3;Memory State (End of Execution):
IntDiv = 3 (number)
Syntax: Operand1: Longint MOD Operand2: Longint; { Returns Longint }
Returns the remainder of integer division.
Example:
WriteLn(10 MOD 3);Output:
1
Standard modulo arithmetic. The sign of the result depends on the dividend.
ModNorm := 10 MOD 3;
ModNeg := -10 MOD 3;Memory State (End of Execution):
ModNorm = 1 (number)
ModNeg = -1 (number)
Syntax: -Operand: Numeric; { Returns Numeric }
Negates the value of a numeric operand.
Example:
WriteLn(-5);Output:
-5
Evaluates at Level 1 (highest precedence) along with NOT and @. It is a unary sign operator, distinct from binary subtraction.
UnaryBase := 5;
UnaryNeg := -UnaryBase;Memory State (End of Execution):
UnaryBase = 5 (integer)
UnaryNeg = -5 (integer)
Syntax: @Operand: Any; { Returns Pointer }
Returns the memory address of a variable, procedure, or function.
Example:
P := @MyVar;Output:
Evaluates at Level 1 precedence. Generates a pointer to the memory location of the operand.
AddrTarget := 42;
TestPtr := @AddrTarget;Memory State (End of Execution):
AddrTarget = 42 (integer)
TestPtr = @AddrTarget (^Integer)
Syntax: PointerOperand^: BaseType;
Accesses the value stored at the memory address pointed to by a typed pointer.
Example:
P^ := 99;
WriteLn(P^);Output:
99
A postfix operator. Modifying the dereferenced pointer directly mutates the original variable residing at that memory address.
DerefTarget := 10;
TestPtrDeref := @DerefTarget;
TestPtrDeref^ := 99;Memory State (End of Execution):
DerefTarget = 99 (integer)
TestPtrDeref = @DerefTarget (^Integer)
Syntax: Operand1: Numeric * Operand2: Numeric; { Returns Numeric }
Performs arithmetic multiplication.
Example:
WriteLn(6 * 7);Output:
42
Level 2 precedence. If both operands are integers, returns an integer. If one is real, returns a real. (Note: Also used for Set intersection, not covered here).
MulRes := 6 * 7;Memory State (End of Execution):
MulRes = 42 (integer)
Syntax: Operand1: Numeric / Operand2: Numeric; { Returns Real }
Performs real division.
Example:
WriteLn(10 / 2:0:1);Output:
5.0
Level 2 precedence. The division operator (/) ALWAYS returns a Real type, even if both operands are integers and the division is mathematically exact.
DivRes := 10 / 4;Memory State (End of Execution):
DivRes = 2.5 (float)
Syntax: Operand1: Numeric + Operand2: Numeric; { Returns Numeric }
Performs arithmetic addition.
Example:
WriteLn(10 + 5);Output:
15
Level 3 precedence. (Note: Also used for Set union, not covered here).
AddRes := 10 + 5;Memory State (End of Execution):
AddRes = 15 (integer)
Syntax: Operand1: Numeric - Operand2: Numeric; { Returns Numeric }
Performs arithmetic subtraction.
Example:
WriteLn(10 - 5);Output:
5
Level 3 precedence. Evaluates left-to-right when chained with addition. (Note: Also used for Set difference, not covered here).
SubRes := 10 - 5;Memory State (End of Execution):
SubRes = 5 (integer)
Syntax: Operand1: String + Operand2: String; { Returns String }
The addition operator is overloaded to perform string concatenation when applied to String or Char types.
Example:
WriteLn('Turbo' + ' Pascal');Output:
Turbo Pascal
Concatenates dynamically. If the resulting string exceeds 255 characters, it is silently truncated at runtime.
ConcatRes := 'Sys' + 'clone';Memory State (End of Execution):
ConcatRes = "Sysclone" (string)
Syntax: Expr1 = Expr2; { Returns Boolean }
Evaluates to True if both expressions are equal.
Example:
WriteLn(5 = 5);Output:
TRUE
Level 4 precedence (lowest). String comparisons are strictly case-sensitive.
EqRes := (5 = 5);Memory State (End of Execution):
EqRes = true (boolean)
Syntax: Expr1 <> Expr2; { Returns Boolean }
Evaluates to True if expressions are not equal.
Example:
WriteLn(5 <> 4);Output:
TRUE
Level 4 precedence.
NeqRes := (5 <> 4);Memory State (End of Execution):
NeqRes = true (boolean)
Syntax: Expr1 < Expr2; { Returns Boolean }
Evaluates to True if the left expression is strictly less than the right.
Example:
WriteLn(4 < 5);Output:
TRUE
Level 4 precedence.
LtRes := (4 < 5);Memory State (End of Execution):
LtRes = true (boolean)
Syntax: Expr1 > Expr2; { Returns Boolean }
Evaluates to True if the left expression is strictly greater than the right.
Example:
WriteLn(5 > 4);Output:
TRUE
Level 4 precedence.
GtRes := (5 > 4);Memory State (End of Execution):
GtRes = true (boolean)
Syntax: Expr1 <= Expr2; { Returns Boolean }
Evaluates to True if the left expression is less than or equal to the right.
Example:
WriteLn(5 <= 5);Output:
TRUE
Level 4 precedence. (Note: Also used to test if Set1 is a subset of Set2).
LteRes := (5 <= 5);Memory State (End of Execution):
LteRes = true (boolean)
Syntax: Expr1 >= Expr2; { Returns Boolean }
Evaluates to True if the left expression is greater than or equal to the right.
Example:
WriteLn(5 >= 5);Output:
TRUE
Level 4 precedence. (Note: Also used to test if Set1 is a superset of Set2).
GteRes := (5 >= 5);Memory State (End of Execution):
GteRes = true (boolean)
Syntax: Element IN Set: Boolean;
Evaluates to True if the element is a member of the specified set.
Example:
WriteLn(3 IN [1..5]);Output:
TRUE
Level 4 precedence. Operates on ordinal types and sets.
InResTrue := 3 IN [1, 2, 3, 4, 5];
InResFalse := 9 IN [1, 2, 3];Memory State (End of Execution):
InResTrue = true (boolean)
InResFalse = false (boolean)
Syntax: L1(@, NOT) > L2(*, /, DIV, MOD, AND, SHL, SHR) > L3(+, -, OR, XOR) > L4(=, <>, <, >, <=, >=, IN)
Defines the strict hierarchy of expression evaluation. Operators with higher precedence are evaluated first.
Example:
WriteLn(2 + 3 * 4);Output:
14
CRITICAL COMPILE-TIME QUIRK: Logical operators (AND/OR, Level 2/3) have higher precedence than relational operators (=/<, Level 4). Expressions like 'A = 1 AND B = 2' will throw a Type Mismatch. They MUST be parenthesized: '(A = 1) AND (B = 2)'. This test validates the full chain.
PrecChain1 := (5 + 2 * 3 = 11);
PrecChain2 := (10 - 6 / 2 = 7.0);
PrecChain3 := NOT False AND True;
PrecChainFull := PrecChain1 AND PrecChain2 AND PrecChain3 AND (3 IN [1..5]);Memory State (End of Execution):
PrecChain1 = true (boolean)
PrecChain2 = true (boolean)
PrecChain3 = true (boolean)
PrecChainFull = true (boolean)
Syntax: function Copy(S: String; Index: Integer; Count: Integer): String;
Returns a substring containing Count characters, starting from Index.
Example:
WriteLn(Copy('Turbo Pascal', 1, 5));Output:
Turbo
If the Index is greater than the string length, Copy returns an empty string. If Count exceeds the remaining characters, it gracefully returns only what is available without throwing out-of-bounds errors.
CopyNorm := Copy('Pascal', 1, 4);
CopyOOB := Copy('Pascal', 10, 2);
CopyTrunc := Copy('Pascal', 4, 10);Memory State (End of Execution):
CopyNorm = "Pasc" (string)
CopyOOB = "" (string)
CopyTrunc = "cal" (string)
Syntax: procedure Delete(var S: String; Index: Integer; Count: Integer);
Removes Count characters from string S, starting at Index.
Example:
S := 'Hello World';
Delete(S, 6, 6);
WriteLn(S);Output:
Hello
CRITICAL QUIRK: This is a Procedure, not a Function. It mutates the string variable IN PLACE. If Index is out of bounds, it simply does nothing.
DelStr := 'Hello World';
Delete(DelStr, 6, 6);
DelOOB := 'Test';
Delete(DelOOB, 10, 2);Memory State (End of Execution):
DelStr = "Hello" (string)
DelOOB = "Test" (string)
Syntax: procedure Insert(Source: String; var S: String; Index: Integer);
Inserts a Source string into target string S at the specified Index.
Example:
S := 'World';
Insert('Hello ', S, 1);
WriteLn(S);Output:
Hello World
Like Delete, it mutates the target string IN PLACE. If Index is greater than the current length of S, the Source string is simply concatenated at the end.
InsStr := 'World';
Insert('Hello ', InsStr, 1);
InsOOB := 'Hi';
Insert('!', InsOOB, 10);Memory State (End of Execution):
InsStr = "Hello World" (string)
InsOOB = "Hi!" (string)
Syntax: function Length(S: String): Integer;
Returns the dynamic length of a string.
Example:
WriteLn(Length('Turbo'));Output:
5
Standard length evaluation. Note that in memory, this dynamically reads the byte value at index 0 of the string array.
LenNorm := Length('Hello');
LenEmpty := Length('');Memory State (End of Execution):
LenNorm = 5 (integer)
LenEmpty = 0 (integer)
Syntax: function Pos(Substr: String; S: String): Byte;
Searches for a substring and returns the 1-based index of its first occurrence.
Example:
WriteLn(Pos('cal', 'Pascal'));Output:
4
The arguments are ordered as Substring first, Target second. It is strictly case-sensitive. Returns 0 if not found.
PosFound := Pos('cal', 'Pascal');
PosNotFound := Pos('Basic', 'Pascal');
PosCase := Pos('pascal', 'Pascal');Memory State (End of Execution):
PosFound = 4 (integer)
PosNotFound = 0 (integer)
PosCase = 0 (integer)
Syntax: S[Index: Byte]: Char;
Characters in a string can be accessed directly as an array. Index 0 holds the length.
Example:
S := 'ABC';
WriteLn(Ord(S[0]));Output:
3
CRITICAL QUIRK: In Turbo Pascal, a String is an array of characters from 0 to 255. Index 0 stores the dynamic length of the string as a character byte. Reading the Ord() of index 0 is functionally equivalent to calling Length().
LenByteStr := 'ABC';
FirstChar := LenByteStr[1];
LenByteVal := Ord(LenByteStr[0]);Memory State (End of Execution):
LenByteStr = "ABC" (string)
FirstChar = A (char)
LenByteVal = 3 (integer)
Syntax: procedure Val(S: String; var V; var Code: Integer);
Converts a string to its numeric value. The target variable V is untyped (can be Integer, Longint, or Real), but the error Code variable MUST be strictly a 16-bit Integer.
Example:
Val('42', Num, ErrCode);
WriteLn(Num);Output:
42
CRITICAL COMPILE-TIME QUIRK: Turbo Pascal enforces strict var-parameter typing. Passing a Longint for the 'Code' parameter will throw 'Error 89: Type mismatch' at compile time. RUNTIME QUIRK: If parsing fails, the target numeric variable remains unchanged, and Code is set to the 1-based index of the invalid character.
ValInt := 0;
Val('42', ValInt, ValCode1);
ValFloat := 0.0;
Val('42.5', ValFloat, ValCode2);
ValErr := 0;
Val('42X', ValErr, ValCode3);Memory State (End of Execution):
ValInt = 42 (integer)
ValCode1 = 0 (integer)
ValFloat = 42.5 (float)
ValCode2 = 0 (integer)
ValErr = 0 (integer)
ValCode3 = 3 (integer)
Syntax: procedure Inc(var X: Ordinal [; N: Longint]);
Increments an ordinal variable. If N is specified, increments by N.
Example:
X := 10;
Inc(X, 5);
WriteLn(X);Output:
15
Like Delete and Insert, Inc is a mutating procedure, not a function. It operates directly on the memory address of the variable. It works on any ordinal type (Integer, Char, Boolean).
IncBase := 10;
Inc(IncBase);
IncStep := 10;
Inc(IncStep, 5);
IncChar := 'A';
Inc(IncChar);Memory State (End of Execution):
IncBase = 11 (number)
IncStep = 15 (number)
IncChar = B (char)
Syntax: procedure Dec(var X: Ordinal [; N: Longint]);
Decrements an ordinal variable. If N is specified, decrements by N.
Example:
X := 10;
Dec(X);
WriteLn(X);Output:
9
The inverse of Inc. Mutates the variable in place. Highly optimized by the compiler into native DEC or SUB assembly instructions.
DecBase := 10;
Dec(DecBase);
DecStep := 10;
Dec(DecStep, 5);
DecChar := 'B';
Dec(DecChar);Memory State (End of Execution):
DecBase = 9 (number)
DecStep = 5 (number)
DecChar = A (char)
Syntax: function Succ(X: Ordinal): Ordinal; function Pred(X: Ordinal): Ordinal;
Returns the successor or predecessor of an ordinal value.
Example:
WriteLn(Succ('A'));Output:
B
Unlike Inc and Dec, these are purely functional and do not mutate the argument. They evaluate to the next or previous value in the ordinal sequence.
SuccNum := Succ(42);
PredNum := Pred(42);
SuccChar := Succ('A');Memory State (End of Execution):
SuccNum = 43 (number)
PredNum = 41 (number)
SuccChar = B (char)
Syntax: function Ord(X: Ordinal): Longint;
Returns the ordinal value (memory integer representation) of an ordinal-type expression.
Example:
WriteLn(Ord('A'));Output:
65
Standard ASCII mapping for characters. Structurally tied to Pascal's strict ordinal type system.
OrdChar := Ord('A');
OrdSpace := Ord(' ');Memory State (End of Execution):
OrdChar = 65 (integer)
OrdSpace = 32 (integer)
Syntax: function Chr(X: Byte): Char;
Returns the character corresponding to a specific ASCII value.
Example:
WriteLn(Chr(65));Output:
A
Specifically expects a Byte (0-255). It maps directly to the character in the extended ASCII memory table.
ChrVal := Chr(65);Memory State (End of Execution):
ChrVal = A (char)
Syntax: function SizeOf(X: Any): Word;
Returns the number of bytes occupied by a variable or a type.
Example:
WriteLn(SizeOf(Integer));Output:
2
CRITICAL QUIRK: Memory footprint verification. In 16-bit MS-DOS, an Integer is 2 bytes, a Longint is 4 bytes, a standard String is 256 bytes (Length byte + 255 chars). Crucially, the default Real type is Borland's proprietary 'Real48' format, which occupies exactly 6 bytes (unlike IEEE 754 8-byte Doubles).
SizeInt := SizeOf(Integer);
SizeLong := SizeOf(Longint);
SizeReal := SizeOf(Real);
SizeStr := SizeOf(String);
SizeChar := SizeOf(Char);Memory State (End of Execution):
SizeInt = 2 (integer)
SizeLong = 4 (integer)
SizeReal = 6 (integer)
SizeStr = 256 (integer)
SizeChar = 1 (integer)
Syntax: CASE Selector OF Label1: Statement1; Label2, Label3: Statement2; Label4..Label5: Statement3; [ELSE Statement4;] END;
Executes one of several statements based on the value of an ordinal selector expression. Turbo Pascal extends standard Pascal by allowing comma-separated lists, ranges (..), and an explicit ELSE fallback clause.
Example:
CASE X OF
1: WriteLn('One');
2..9: WriteLn('Multiple');
ELSE WriteLn('Other');
END;Output:
Validates the evaluation of exact matches, ranges, and the ELSE fallback.
CaseRange := 0;
CaseTarget1 := 4;
CASE CaseTarget1 OF
1, 2: CaseRange := 10;
3..5: CaseRange := 20;
ELSE CaseRange := 30;
END;
CaseElse := 0;
CaseTarget2 := 99;
CASE CaseTarget2 OF
1: CaseElse := 10;
ELSE CaseElse := 30;
END;Memory State (End of Execution):
CaseRange = 20 (integer)
CaseTarget1 = 4 (integer)
CaseElse = 30 (integer)
CaseTarget2 = 99 (integer)
Syntax: FOR Counter := Start DOWNTO End DO Statement;
Executes a statement a fixed number of times, strictly decrementing an ordinal control variable by 1 on each iteration. If the Start value is less than the End value, the loop body is bypassed entirely.
Example:
FOR I := 3 DOWNTO 1 DO WriteLn(I);Output:
3
2
1
Uses the DOWNTO keyword instead of a dynamic step. Validates decrementing and bypass logic.
DownSum := 0;
FOR J := 5 DOWNTO 1 DO Inc(DownSum, J);
DownSkip := 0;
FOR J := 1 DOWNTO 5 DO Inc(DownSkip, J);Memory State (End of Execution):
DownSum = 15 (integer)
DownSkip = 0 (integer)
J = 1 (integer)
Syntax: FOR Counter := Start TO End DO Statement;
Executes a statement a fixed number of times, strictly incrementing an ordinal control variable by 1 on each iteration. The Start and End limits are evaluated exactly once before the loop begins.
Example:
FOR I := 1 TO 3 DO WriteLn(I);Output:
1
2
3
Validates incrementing logic and ensures the loop is skipped if Start > End.
ForSum := 0;
FOR I := 1 TO 5 DO Inc(ForSum, I);
ForSkip := 0;
FOR I := 5 TO 1 DO Inc(ForSkip, I);Memory State (End of Execution):
ForSum = 15 (integer)
ForSkip = 0 (integer)
I = 5 (integer)
Syntax: IF Condition THEN Statement1 [ ELSE Statement2 ];
Branches execution based on a boolean condition. Turbo Pascal strictly forbids placing a semicolon immediately before the ELSE keyword.
Example:
IF True THEN
WriteLn('Yes')
ELSE
WriteLn('No');Output:
Yes
CRITICAL PARSING QUIRK: Turbo Pascal resolves the 'dangling ELSE' ambiguity by strictly binding the ELSE clause to the closest preceding IF statement.
IfRes := 0;
IF True THEN
IF False THEN IfRes := 1
ELSE IfRes := 2;Memory State (End of Execution):
IfRes = 2 (integer)
Syntax: REPEAT Statement1; [Statement2;] UNTIL Condition;
Repeats a sequence of statements until a boolean condition evaluates to True. Because the condition is evaluated after the loop body, the statements are guaranteed to execute AT LEAST ONCE.
Example:
REPEAT
Inc(X);
UNTIL X = 5;Output:
CRITICAL SYNTAX QUIRK: Unlike WHILE or FOR, REPEAT..UNTIL acts as a natural block envelope and does not require BEGIN..END to wrap multiple statements.
RepCount := 0;
REPEAT
Inc(RepCount);
UNTIL RepCount >= 5;Memory State (End of Execution):
RepCount = 5 (integer)
Syntax: WHILE Condition DO Statement;
Repeats a statement as long as a boolean condition evaluates to True. The condition is evaluated before entering the loop body. If it is initially False, the body is completely bypassed.
Example:
WHILE X < 5 DO
begin
Inc(X);
end;Output:
Validates the pre-condition check and loop execution.
WhileCount := 0;
WHILE WhileCount < 5 DO Inc(WhileCount);
WhileSkip := 0;
WHILE False DO Inc(WhileSkip);Memory State (End of Execution):
WhileCount = 5 (integer)
WhileSkip = 0 (integer)
Syntax: array[Start..End] of Type;
Unlike C or JavaScript where arrays always start at index 0, Turbo Pascal arrays can have arbitrary ordinal bounds, including negative numbers.
Example:
var Temp: array[-5..5] of Integer;
begin
Temp[-2] := 42;
end;Output:
Validates that negative bounds are correctly allocated and accessed in memory without shifting offsets incorrectly.
ArrNegative[-2] := 42;
ArrNegRes := ArrNegative[-2];Memory State (End of Execution):
ArrNegRes = 42 (integer)
Syntax: array['A'..'Z'] of Type;
The index type of an array is not limited to integers. Any ordinal type can be used as an index, including characters or enumerations.
Example:
var Letters: array['a'..'z'] of Integer;
begin
Letters['x'] := 99;
end;Output:
CRITICAL PARSER QUIRK: The AST must resolve the character literal to its ASCII ordinal value to correctly compute the memory offset.
ArrChar['B'] := 77;
ArrCharRes := ArrChar['B'];Memory State (End of Execution):
ArrCharRes = 77 (integer)
Syntax: array[Dim1Start..Dim1End, Dim2Start..Dim2End] of Type;
Multi-dimensional arrays can be defined either as arrays of arrays or using a comma-separated syntax for dimensions.
Example:
var Matrix: array[1..3, 1..3] of Integer;
begin
Matrix[2, 3] := 88;
end;Output:
Validates 2D array parsing and contiguous memory access.
ArrMulti[2, 3] := 88;
ArrMultiRes := ArrMulti[2, 3];Memory State (End of Execution):
ArrMultiRes = 88 (integer)
Syntax: Type Name = RECORD Field1: Type; Field2: Type; END;
A Record groups heterogeneous data fields under a single identifier. Fields are accessed using dot notation.
Example:
Type TPoint = RECORD X, Y: Integer; END;
var P: TPoint;
begin
P.X := 10;
end;Output:
Validates custom TYPE declaration, record instantiation, and member access.
MyPoint.X := 10;
MyPoint.Y := 20;
RecResX := MyPoint.X;
RecResY := MyPoint.Y;Memory State (End of Execution):
RecResX = 10 (integer)
RecResY = 20 (integer)
Syntax: WITH RecordVariable DO Statement;
The WITH statement temporarily opens a record's namespace. Within its block, the record's fields can be accessed directly without prefixing them with the record variable name.
Example:
WITH P DO
begin
X := 10;
Y := 20;
end;Output:
CRITICAL SCOPE QUIRK: The environment evaluator must temporarily push the record's fields to the top of the symbol resolution stack.
WITH Player1 DO
BEGIN
Score := 100;
Alive := True;
END;
WithResScore := Player1.Score;
WithResAlive := Player1.Alive;Memory State (End of Execution):
WithResScore = 100 (integer)
WithResAlive = true (boolean)
Syntax: procedure Name[(ParameterList)]; [Local Declarations] begin Statements; end;
A procedure is a subprogram that performs a specific task but does not return a value. It is invoked as a standalone statement.
Example:
procedure Greet;
begin
WriteLn('Hello World');
end;
Greet; { Call the procedure }Output:
Hello World
Validates basic procedure declaration, invocation, and execution flow.
ProcCalled := False;
Ref_BasicProc;Memory State (End of Execution):
ProcCalled = true (boolean)
Syntax: function Name[(ParameterList)]: ReturnType; [Local Declarations] begin Name := ReturnValue; end;
A function is a subprogram that computes and returns a single value. In Turbo Pascal, there is no 'return' keyword. The return value is specified by assigning a value to the function's own identifier before it exits.
Example:
function GetTen: Integer;
begin
GetTen := 10;
end;
WriteLn(GetTen);Output:
10
Validates function execution and the assignment to the function identifier for returning a value.
FuncRes := Ref_BasicFunc;Memory State (End of Execution):
FuncRes = 42 (integer)
Syntax: procedure RoutineName(Param: Type);
In Turbo Pascal, parameters are passed by value by default. The procedure or function receives a copy of the argument. Any modifications made to the parameter within the routine are strictly local and do not affect the original variable passed by the caller.
Example:
procedure AddTen(X: Integer);
begin
X := X + 10;
end;Output:
Validation of memory isolation for value parameters.
OriginalVal := 5;
Ref_PassByValue(OriginalVal);Memory State (End of Execution):
OriginalVal = 5 (integer)
Syntax: procedure RoutineName(VAR Param: Type);
To pass a parameter by reference, the VAR keyword must precede the parameter declaration. The routine accesses the actual memory address of the argument. Any changes made to the parameter inside the routine will directly modify the original variable.
Example:
procedure AddTen(VAR X: Integer);
begin
X := X + 10;
end;Output:
Validation of memory mutation for reference parameters.
OriginalRef := 5;
Ref_PassByRef(OriginalRef);Memory State (End of Execution):
OriginalRef = 15 (integer)
Syntax: var GlobalVar: Type;
Variables declared in the main VAR block of a program are global. They are visible and can be directly accessed or modified by any procedure or function, provided they are declared before the routine in the source code.
Example:
procedure MutateGlobal;
begin
GlobalVar := 99;
end;Output:
Validation of outer scope traversal and mutation.
GlobalTarget := 21;
Ref_GlobalAccess;Memory State (End of Execution):
GlobalTarget = 42 (integer)
Syntax: procedure RoutineName; var LocalVar: Type; begin ... end;
Variables declared within a procedure or function are local to that routine. If a local variable has the exact same name as a global variable, the local declaration 'shadows' (hides) the global one. Any operations on that identifier within the routine will only affect the local instance.
Example:
procedure ShadowGlobal;
var X: Integer;
begin
X := 99; { Modifies local X, not global X }
end;Output:
Validation of scope priority (Local over Global) during identifier resolution.
ShadowTarget := 10;
Ref_Shadowing;Memory State (End of Execution):
ShadowTarget = 10 (integer)