Source, names & types¶
Source code is where D/BASIC makes its first promise: old listings should look familiar, but old accidents should not become new rules.
A source file at a glance¶
A console program may contain module directives, declarations, procedures, and executable statements:
OPTION BASE 1
DEFINT A-Z
CONST MaxGuests = 8
DECLARE FUNCTION Greeting$ (Name AS STRING)
DIM Guests(MaxGuests) AS STRING
Guests(1) = "Ada"
PRINT Greeting$(Guests(1))
FUNCTION Greeting$ (Name AS STRING)
Greeting$ = "WELCOME, " + UCASE$(Name)
END FUNCTION
A window program adds module-level WINDOW SUB and ON ... SUB faces. With handlers but no top-level executable statements it is window-only; with both, the same image offers console and window faces and the launch surface selects one. Classes, records, and procedure bodies remain module-level in either shape.
Lines and separators¶
- A newline ends a statement.
:separates multiple statements on one logical line.- A decimal
u32at the start of a logical line is a line number. Name:declares a named label.- An apostrophe or
REMcomments through the end of the logical line.
10 X% = 2: Y% = 3 ' Two statements, one numbered line
20 PRINT X% + Y%
Again:
REM A named label, not a procedure
PRINT "HELLO"
Inside a REM comment, a colon is just comment text. Prefer separate physical lines for new code; compact colon-separated style is most useful when preserving a classic listing.
Names¶
D/BASIC names are ASCII case-insensitive. score, Score, and SCORE name the same thing; diagnostics and bytecode use a canonical uppercase form.
An identifier:
- starts with an ASCII letter;
- continues with ASCII letters, digits,
_, or dotted components; - may end with a type suffix;
- has a maximum of 40 characters per dotted component; and
- cannot be a reserved word.
Whitespace separates words. FOR I is the keyword FOR followed by I; FORI is one perfectly ordinary name. D/BASIC does not imitate early token-crunching interpreters or silently truncate long names.
Dots also identify record fields, object members, and qualified procedure bodies, so use them intentionally.
The six everyday value types¶
| Type | Suffix | Storage | Best used for |
|---|---|---|---|
INTEGER |
% |
16-bit signed | counters, coordinates, compact whole numbers |
LONG |
& |
32-bit signed | larger counts, identifiers, milliseconds |
DECIMAL |
@ |
64-bit fixed, 4 decimal places | money and exact base-10 quantities |
SINGLE |
! |
IEEE binary32 | general real-number work; the default numeric type |
DOUBLE |
# |
IEEE binary64 | wider-range or higher-precision real work |
STRING |
$ |
counted reference | variable-length text |
DECIMAL is D/BASIC's exact base-10 numeric type. A value such as 12.3400@ is carried as a signed scale-10,000 integer, avoiding a binary floating-point round trip.
Named TYPE records and CLASS references add user-defined types. HANDLE, whole arrays, and internal references appear at specific API boundaries rather than acting like ordinary numeric values.
Three ways to say a type¶
Use a suffix for compact classic code:
Use AS for declarations that should read like prose:
Use a DEF range to choose defaults for otherwise-untyped names:
Available directives are DEFINT, DEFLNG, DEFSNG, DEFDBL, and DEFSTR. Without a suffix, an AS clause, or a matching DEF range, a numeric name is SINGLE.
The default surprises modern readers
DIM Count declares a SINGLE, not an INTEGER. Write Count%, DIM Count AS INTEGER, or a deliberate DEFINT range when you mean a whole number.
Literals¶
Numbers¶
D/BASIC accepts decimal integers and real numbers, E and D exponents, hexadecimal with &H, and octal with &O (or classic bare &). A suffix can force the intended type.
42 ' narrowest fitting INTEGER/LONG, then SINGLE
42000& ' LONG
3.5! ' SINGLE
3.5# ' DOUBLE
3.5@ ' DECIMAL
1.25E-3 ' SINGLE exponent
1.25D-30 ' DOUBLE exponent
&HFF ' hexadecimal
&O377 ' octal
Hexadecimal literals retain signed bit-pattern behavior. For example, an INTEGER-sized &HFFFF represents -1.
Strings¶
A string literal is text between double quotes and may contain up to 32,767 bytes.
String literals do not have a backslash escape language. Build special characters with CHR$ when needed.
Variables and declarations¶
DIM declares one or more names:
Use SHARED for module storage visible to procedures, and STATIC for procedure-local storage that survives calls:
DIM SHARED TotalRuns AS LONG
SUB CountVisit ()
STATIC Visits AS LONG
Visits = Visits + 1
TotalRuns = TotalRuns + 1
END SUB
Arrays add bounds after the name; Arrays covers their allocation and whole-array verbs.
Constants¶
CONST binds a name to a compile-time value:
Constants are substituted into the compiled image. Use them for meanings, not merely to avoid typing a number twice.
Array base¶
At module scope, one OPTION BASE chooses the omitted lower bound for array declarations:
Only OPTION BASE 0 and OPTION BASE 1 are valid. The compiler writes explicit bounds into bytecode, so a runtime never has to guess which option was in the source.
Truth¶
False is 0 and true is -1 (all bits set). Relational expressions produce those values, and logical operators work bitwise on integral values.
This makes classic bit masks natural, but it also means D/BASIC truth is not the modern 1 convention.
Conversion and promotion¶
Mixed numeric expressions widen through this order:
Assignment converts to the destination type. CINT and CLNG round to nearest-even, INT rounds toward negative infinity, and FIX truncates toward zero.
The same conversion rules matter in bulk operations: ARRAYFILL A%(), 2.6 stores 3 in every element.