cpp-dsl-sdk user guide
Overview
The SDK is a header-only C++17 loader, structural verifier, registry and VM. lmscript compiles source against a JSON schema; the host implements that schema in C++ and supplies its exact bytes to Program::load. The SDK does not parse or interpret schema JSON.
Install
Copy include/dslvm.hpp into your source tree and include it, or pin a repository revision and verify the header hash. Compile as C++17. No separate library is built and the header has no third-party dependencies. Use the matching published lmscript compiler.
Concepts
- Registry
- Declares context types, functions and methods with exact argument and return types, and stores the C++ callbacks.
- Program::load
- Loads a bytecode byte string and exact schema byte string, verifies format, schema binding and imports against a registry, then returns a runnable program.
- Context
- Maps schema context variable names to live host-owned object pointers.
- Value
- Carries INT (int64), FLOAT (binary64), STR, BOOL, VOID or OBJ (a host pointer and schema type name).
- Ownership
- The host owns objects referenced by context and object values. Keep them alive and stable throughout every call that can use them.
Reference
Typical embedding sequence:
dslvm::Registry registry;
registry.context("scene", "Scene");
registry.method("Scene", "render", {"string"}, "void", callback);
auto schema = dslvm::read_file("schema.json");
auto program = dslvm::Program::load(dslvm::read_file("scene.dslb"), schema, registry);
dslvm::Context context;
context.set("scene", &scene);
program.run(context, registry);
Callbacks receive dslvm::Args& and return a dslvm::Value. Void callbacks return Value::none(). Throw dslvm::Error for a host run failure. The standard command-line result helpers print one JSON line: report_ok exits 0, report_error exits 3 for load/run errors, and report_app_failure exits 4. Compiler failures normally exit 2.
Format compatibility is one-version-only. The current loader accepts bytecode v5 and refuses any other version; compiler, SDK and host must move together when the format changes.
String helpers are ordinary host functions, not VM built-ins. To add them, copy the functions object from stdlib/string.schema-fragment.json into the host schema, include stdlib/string.hpp, and call dslvm::stdlib::register_string(registry).
| Function | Signature | Behavior |
|---|---|---|
| str_starts_with | string, string → bool | Byte prefix test. |
| str_ends_with | string, string → bool | Byte suffix test. |
| str_contains | string, string → bool | Byte substring test. |
| str_lower | string → string | ASCII lowercase. |
| str_upper | string → string | ASCII uppercase. |
| str_substr | string, int, int → string | Clamped byte slice. |
| str_len | string → int | Byte length, including NUL. |
| str_match | string, string → bool | Whole-string byte glob. |
| str_find | string, string → int | Byte offset or −1. |
| str_replace | string, string, string → string | Non-overlapping replacement. |
| str_trim | string → string | Trim ASCII whitespace. |
| str_repeat | string, int → string | Repeat with a 64 MiB catalog bound. |
| str_to_int | string → int | Parse signed decimal; invalid input returns 0. |
| str_is_int | string → bool | Reports parse validity. |
| str_to_float | string → float | Parse finite decimal; invalid input returns 0. |
| str_is_float | string → bool | Reports parse validity. |
String lengths and indexes are bytes; UTF-8 is not decoded. Case conversion is ASCII-only. The catalog documents bounded replacement/repetition and glob work.
CLI hosts commonly embed one schema and implement --schema (compact summary), --schema --json (exact JSON bytes), and --dsl-signatures (registry list). A host can accept multiple --dsl bytecode files and run them in order against that same schema. The SDK itself does not define a CLI.
Tasks
- Register an object: call registry.context(name, type), then bind the type's methods with registry.method.
- Check parity: compare registry.signatures() with lmscript --dsl-signatures schema.json.
- Load safely: read binary files without text conversion and pass exact schema bytes to Program::load.
- Support collections: expose a host object with len() -> int and at(int) -> T; the compiler lowers foreach to those methods.
- Share optional strings: paste the catalog fragment and register the matching binder once per registry.
Limits
Bytecode is trusted input. The VM adds no execution budget, recursion limit, stack cap, local cap or string cap; max_stack is only a reservation hint. Hosts should decide whether and where to impose their own input and process limits. Defensive value-kind checks remain in the VM. String catalog helper bounds are library policy, not VM resource limits.
Troubleshooting
- Schema hash mismatch: use the same exact JSON bytes for compilation and loading; whitespace changes the binding.
- Unbound import: compare the compiler signature list with Registry::signatures(); check name, argument order, and result type.
- Object method failure: ensure context pointers and returned host objects remain alive while bytecode can use them.
- Unexpected version refusal: build with the compiler matching the SDK's single supported format version.
- String function not found: both copy its schema fragment and register its binder; neither is automatic.