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:
So is this:
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:
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¶
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 →