Skip to content

Compatibility, migration and what will not run

This page explains what an old BASIC program can expect from d/BASIC: which classic rules are kept exactly, what the language adds on top, how to modernize a listing one step at a time, and which machine-level tricks d/BASIC will never run. After reading it you will know whether a listing you own will run, and what to change if it does not.

d/BASIC does not treat compatibility as a costume. It keeps the rules that decide what a classic BASIC program means, then adds modern structure without asking you to switch the language into a second mode.

The compatibility center

Area d/BASIC rule
names ASCII, case does not matter; the suffix is part of the name's type
default numeric type SINGLE unless a suffix, AS, or a DEF* statement says otherwise
truth false is 0, true is -1
line numbers optional, and valid targets for branches and DATA
labels named labels sit alongside line numbers
statements separated by a newline or :
comments an apostrophe or REM to the end of the line
parameters BYREF by default; BYVAL when you say so; extra parentheses pass a copy
operators d/BASIC precedence, integer \, MOD, ^, and the logical operators in their classic order
strings $ names and the classic string functions
arrays bounds are inclusive; OPTION BASE, LBOUND, UBOUND, REDIM, ERASE
console PRINT, separators, TAB, SPC, INPUT, LINE INPUT
program data DATA, READ, RESTORE
flow IF, FOR, WHILE, DO, SELECT CASE, GOTO, GOSUB, ON ... GOTO/GOSUB
procedures DECLARE, SUB, FUNCTION, DEF FN, assigning the result to the function's name
records TYPE ... END TYPE value records

The acid tests are small details: -2 ^ 2 is -4; &HFFFF can be -1; CALL F((X)) passes a copy; an X with no declared type is SINGLE. These rules survive because programs written for other BASICs depend on them.

Line numbers are not deprecated

This is valid d/BASIC:

10 FOR I% = 1 TO 3
20 PRINT I%
30 NEXT I%
40 END

So is this:

FOR I% = 1 TO 3
  PRINT I%
NEXT I%

And so is a careful mixture. Modernizing should make a program clearer, not erase its history for sport.

What d/BASIC adds

Addition Why it exists
DECIMAL and @ exact base-10 values with four decimal places
ARRAYCOPY, ARRAYFILL, ARRAYSWAP say what you mean to a whole array, and let the optimizer act on it
CLASS, NEW, NOTHING, THIS objects with identity and behavior
access levels, inheritance, virtual/abstract/override structure that scales to a real application
properties and weak fields controlled state, and ownership without cycles
WINDOW SUB and ON KEY/ON POINTER window programs driven by events, portable across machines
INTENT and SERVICE ask the machine for a capability by name, never by memory address
IMPORT ... BAKED/SHARED reuse source in a controlled way, with each compiled dependency named exactly
d/Works widgets reusable, portable controls written in the language itself
DBC bytecode build once, check once, run on every system

All of this lives in one grammar. You do not choose a "classic mode" to keep line numbers or a "modern mode" to use a class.

Why direct machine access will not run

The following names are permanently outside portable d/BASIC:

Not allowed What it used to do What d/BASIC offers instead
PEEK, POKE read or write a memory address typed state, handles, registered intents
VARPTR get the address of a variable whole arrays and records passed as units, and managed references
DEF SEG choose a memory segment there is no memory map visible from source
USR, SYS, CALL with an address jump into machine code declared procedures, shared libraries, the native module and package route
WAIT poll a hardware port window events, services, intents that complete later
raw PTR, address-of, pointer arithmetic native memory identity object references and opaque handles

This is not a missing retro feature. It is the line that lets one compiled file mean the same thing on machines that share no memory map.

The compiler recognizes these spellings so it can explain the boundary by name. It does not misread the rest of the listing, and it never silently ignores the operation.

Graphics migrate to meaning

Vendor commands such as writing straight to screen memory, display lists, raster hooks, or chip registers cannot cross machines intact. Translate what they were trying to draw:

' Instead of writing a video-memory address:
INTENT GFX.FILL_RECT(X%, Y%, Width%, Height%, Color%)

An intent is a named request such as "fill this rectangle" that the machine carries out however it can. One runtime can carry it out on a GPU at high resolution; another can draw it into a small composed screen. Read Intents & Services.

One kind of error message, three places it can appear

d/BASIC uses one set of error messages, with the same codes, whether a problem is found while compiling, while loading, or while running. But only a program that has started can catch a problem at run time. A compile error produces no compiled file at all. A problem found while loading, or by the checks a program passes before it runs, means no program code runs. ON REFUSAL handles failures that happen after those checks, when a call is made: an optional provider (the part of the host that supplies files, sound or the network) that disappears, a session that has gone stale, bounds that are no longer valid, a capacity limit, or an operation the provider declines.

ON REFUSAL GOTO OptionalRouteMissing
CALL UseAdmittedOptionalRoute
PRINT "OPTIONAL RESULT READY"
GOTO Done

OptionalRouteMissing:
  PRINT "UNAVAILABLE:"; ERR; " AT "; ERL
  RESUME Done

Done:
END

A truly optional feature is discovered by asking the machine whether it has the capability, and used only when the answer is yes. A required capability that is missing stops the program before it starts, so you never get a half-launched application. See Errors, Refusals & Diagnostics for handler and cleanup patterns.

A migration recipe

1. Run the listing before beautifying it

Keep line numbers, suffixes, GOSUB, and odd-looking parentheses until you have tests that capture what the program does.

2. Make types visible

Keep the original suffixes or add explicit AS clauses. Remember that a numeric name without a type is still SINGLE.

3. Isolate machine operations

Mark every PEEK, POKE, SYS, hardware graphics or sound command, and machine-specific file path. Translate the purpose of each into an intent, a widget, a data wrapper, or a declared capability.

4. Name repeated work

Move substantial GOSUB routines into SUB and FUNCTION procedures. Keep GOSUB where it is still the clearest way to express a small classic algorithm.

5. Replace parallel arrays with records

TYPE Player
  Name AS STRING * 24
  Score AS LONG
END TYPE

Reach for a class only when identity, ownership, behavior, or virtual methods actually matter.

6. State whole-array meaning

Replace obvious clear-the-array and copy-the-buffer loops with ARRAYFILL, ARRAYCOPY, or ARRAYSWAP. The code becomes clearer and the optimizer gets a stronger promise to work with.

7. Move display code into a window program

Console output can stay as PRINT. A graphical application should create its state in OPEN, respond to layout in RESIZE, handle interaction in ON KEY/ON POINTER, and paint in DRAW.

8. Build and test the compiled file

Compare the same compiled file and its output log across every machine you intend to run it on. Portability is a property of the file you deliver, not just of how the source looks.

The dialect optimizer's role

The dialect optimizer can recognize historical forms and produce standard d/BASIC, but what it writes is still source you can read and review. It is allowed to smooth out differences in spelling; it is not allowed to guess what a machine-specific command was for.

That is why d/BASIC can welcome many BASIC traditions without becoming a bag of runtime switches.

Common transfer surprises

Untyped means SINGLE

DIM Count is not an integer declaration. Use %, AS INTEGER, or DEFINT.

Calls default to BYREF

A plain variable passed to a procedure can be changed by that procedure. Use BYVAL in the declaration, or extra parentheses at the call, when you deliberately want to pass a copy.

True is -1

Code that compares a true result to 1 misunderstands d/BASIC truth. Test for nonzero, or compare to -1 when the exact bit pattern matters.

A class variable starts out as NOTHING

DIM Button AS WorksButton declares a reference. Build the object with NEW; the declaration alone does not call a constructor.

Compatibility without stagnation

d/BASIC is not trying to recreate one old machine. It keeps the language rules that people and programs relied on, then gives operating-system and hardware work a portable home in the language.

That is a more ambitious form of compatibility: yesterday's first line can still run, and tomorrow's full application does not need to leave BASIC behind.


Next: Quick Reference →