Skip to content

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 u32 at the start of a logical line is a line number.
  • Name: declares a named label.
  • An apostrophe or REM comments 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.

DIM Customer.Name AS STRING
DIM Customer_Order_7 AS LONG

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:

Lives% = 3
Population& = 120000
Price@ = 19.9500@
Ratio! = .625
Distance# = 1.2D30
Name$ = "MIRA"

Use AS for declarations that should read like prose:

DIM Lives AS INTEGER
DIM Price AS DECIMAL
DIM Name AS STRING

Use a DEF range to choose defaults for otherwise-untyped names:

DEFINT A-C, I-N
DEFDBL D-H
DEFSTR S-Z

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.

Message$ = "A SMALL LANGUAGE CAN HOLD A LARGE IDEA."

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:

DIM X AS INTEGER, Y AS INTEGER
DIM Caption$
DIM Balance AS DECIMAL

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:

CONST ScreenMargin = 12
CONST ProductName$ = "D/BASIC"
CONST Debt@ = -4.2500@

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:

OPTION BASE 1
DIM Deck%(52)       ' 1 TO 52
DIM Pixels%(0 TO 7) ' Explicit bounds always win

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.

PRINT 7 > 3       ' -1
PRINT 7 = 3       '  0
PRINT NOT 0       ' -1

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:

INTEGER → LONG → DECIMAL → SINGLE → DOUBLE

Assignment converts to the destination type. CINT and CLNG round to nearest-even, INT rounds toward negative infinity, and FIX truncates toward zero.

PRINT CINT(2.5)    ' 2
PRINT CINT(3.5)    ' 4
PRINT INT(-2.2)    ' -3
PRINT FIX(-2.2)    ' -2

The same conversion rules matter in bulk operations: ARRAYFILL A%(), 2.6 stores 3 in every element.


Next: Variables, DIM & Memory →