Imports & libraries¶
When a program needs code from somewhere else, such as the d/Works widget toolkit or a module of your own, it uses IMPORT. This page explains how module names work, the two ways an imported library can be delivered (copied into your program, or bound to an exact installed library file), which standard libraries exist, how to build a library of your own, and the limits the compiler enforces.
An import answers one simple question: which reviewed implementation does this name mean? d/BASIC gives two honest answers: bake the library's source into the program, or bind the program to an exact compiled library.
A dotted module name¶
An import takes a line of its own:
Module names are dotted identifiers, matched without regard to ASCII case. In the example, the public name dworks.widgets maps to the maintained library file dworks/widgets.bas. dworks is the prefix of the standard modules that come from d/Works, the office suite being written in d/BASIC (d/Write, d/Calc, d/Present).
dworks.* and gx (GX is d/BASIC's library for 2D games: scenes, sprites, tilemaps, cameras, collision) are protected standard module names. A project cannot replace either with a local file of the same name.
Baked imports¶
BAKED copies the library's source into your program before parsing begins, so the result is one self-contained compiled program file, .dbc. You can write the word explicitly for a protected d/Works module:
Use it when:
- one portable file is worth more than shared storage;
- the program and the library are being developed together;
- no installation step should be needed; or
- the machine that will run the program does not keep a store of shared libraries.
Expansion is deterministic and depth-first, and each file is expanded once, however many imports lead to it. A library may import another library; if the imports form a cycle, the compiler stops and says so instead of recursing forever.
Shared imports¶
SHARED compiles the program against a shared library file, .dbl, and records an exact dependency on it:
- the library's identity and version;
- each exported name and its ordinal, its position in the library's export table;
- the argument and result types of each exported procedure;
- the shape of each exported class the program uses; and
- the SHA-256 digest of the library file's bytes.
When the program is loaded, the d/OS runtime, the program that runs your compiled code, binds those exact bytes. (d/OS is the operating system that brings modern software to 8-bit home computers such as the Atari 800, the Commodore 64 and the Apple II.) If the library is absent, changed or incompatible, the runtime declines before the program starts and names the library it wanted. It never quietly bakes in a different copy and calls that close enough.
Use it when many programs share a large, stable library, or when a d/OS package installs the library alongside the programs that use it.
Every import is baked unless you say otherwise, including the protected modules. Write SHARED explicitly when a matching installed library is part of how the program is delivered:
The default is deliberately simple: the source travels with the program unless you name an exact shared library. One program may bake a helper that is still changing and share a stable installed d/Works or GX library, but wherever a dependency on an installed library matters, SHARED is written down.
Baked and shared are delivery choices¶
The BASIC you write is the same either way:
With a baked import, the code behind WorksButton lives inside your program's image. With a shared import, a call may cross into the installed library's image. The compiler's optimizer keeps only the dependencies your program actually reaches; merely offering a shared library does not force a dependency on it into a program that never uses it.
Project-local modules¶
For a name that is not under dworks.*, the compiler looks for the module below the project root, the directory that holds the entry source file:
Path separators, absolute paths, .. and any disguised way of escaping the project are not accepted; the compiler stops and says so. An import is a module name, not permission to read the filesystem.
A library cannot become a second application¶
Imported source may define:
- constants and declarations;
TYPErecords;- classes;
- procedures and the bodies of class members; and
- imports of its own.
It may not define a second program entry point, nor any of the handlers that make a program a window program: WINDOW SUB lifecycle routines, ON KEY, ON POINTER, WINDOW ACCEPTS or ON DROP. The application owns its one entry point and its event handlers.
That rule is what keeps dworks.widgets a toolkit rather than a hidden window manager.
Standard libraries¶
| Module | Purpose |
|---|---|
dworks.widgets |
themes, repaint tracking, controls, menus, and local UI events |
dworks.document_media |
bounded document tables, images, and staging for local transfers |
dworks.network |
HTTP helpers, capability and status records, and sessions that own their connection |
dworks.files |
typed helpers for mounts, directories, bounded file reads and writes, and file edits |
dworks.data |
typed fixed-array wrappers for database reads, browsing, writes, and saved documents |
dworks.sha256 |
wrapper around the system's COMPUTE.SHA256 request |
dworks.sha256_oracle |
a deliberately slow reference SHA-256 written entirely in BASIC, used by the tests |
dworks.drag |
typed helpers for the data a drag session carries |
dworks.interchange |
helpers for exchanging data between applications |
dworks.dwrite_dobj |
d/Write's DOBJ shapes and operations (DOBJ is the typed object a program hands to another program when you drag, drop, copy or paste) |
dworks.dwr1 |
helpers for DWR1 documents |
dworks.write_artifacts |
document save and publish workflows and their confirmations |
dworks.calc_model |
d/Calc model components |
dworks.calc_view |
d/Calc view helpers |
gx |
the GX game engine; the part supported today covers scenes, entities, tiles, cameras, collision and animation over arrays your program owns |
These are libraries of source. Importing one gives you declarations and implementations; it does not switch anything on in the host. IMPORT dworks.data does not mount any storage, and IMPORT gx does not give the program a graphics or sound route. The machine running the program must still provide every capability the library or the application asks it for.
Build a library artifact¶
The desktop toolchain can build a compiled d/BASIC library:
A .dbl describes itself: it is compiled code with a table of exports and no program entry point or window handlers. The publisher's identity and the version are inputs to the build; a library's source cannot claim them for itself.
Import safety limits¶
The part of the compiler that assembles source enforces limits so that a build is always finite:
- no more than 128 distinct modules;
- no more than 1 MiB of expanded source;
- each file expanded once;
- no cycles;
- no escape from the project's source root; and
- no program entry point or window handlers in imported code.
These limits produce useful diagnostics, not arbitrary inconvenience. A build should not depend on an unbounded chain of includes, or on whichever file happened to exist outside the project today.
What d/BASIC does not mean by import¶
IMPORT is not:
- C's
#includewith textual macros; - a request at runtime for an unchecked source path;
- a search for a DLL by a convenient filename;
- a plugin loader for one particular machine; or
- a way to sneak a second application entry point into the program.
The compiler knows either the source or the exact library file. The compiled program records what it depends on.
Library design advice¶
- Export concepts, not wrappers for one particular machine.
- Keep
WINDOWand input handlers in the application. - Put the packing of typed data for transfer behind small procedures.
- Keep changing session state in objects the application owns, not in module globals shared by everyone who imports the library.
- Give public operations stable names and explicit argument modes (
BYVALorBYREF). - Test both
BAKEDandSHAREDdelivery for a library meant to support both.
Next: Compiler & Optimizer →