cpp-dsl-sdk tutorial

This walkthrough uses a small host with one object method. Save the schema, DSL and C++ source below in one directory. Copy include/dslvm.hpp from the SDK into a local include/ directory.

1. Declare the host schema

{
  "dsl.schema": 2,
  "name": "greeter",
  "types": {
    "Greeter": {
      "methods": {
        "say": [
          { "params": ["string"], "returns": "void" }
        ]
      }
    }
  },
  "functions": {},
  "context": { "g": "Greeter" }
}

2. Compile a DSL call

p = _dsl_ schema="schema.json";
g.say("Hello from the DSL");
end _dsl_
savedsl(p, "demo.dslb");

Run the compiler:

npx --yes --package=@lmctl-ai/lmctl -- lmscript demo.lms demo.dslb
exit status: 0

3. Implement and build the host

This host binds Greeter.say, loads bytecode against the exact schema bytes, supplies a live object through Context, and reports a standard JSON result line.

#include "dslvm.hpp"
#include <iostream>
struct Greeter { std::string last; };
int main(int argc, char** argv) {
  dslvm::Registry reg;
  reg.context("g", "Greeter");
  reg.method("Greeter", "say", {"string"}, "void", [](void* self, dslvm::Args& a) {
    static_cast<Greeter*>(self)->last = a[0].s; return dslvm::Value::none();
  });
  if (argc == 2 && std::string(argv[1]) == "--signatures") {
    for (const auto& s : reg.signatures()) std::cout << s << '\n'; return 0;
  }
  auto schema = dslvm::read_file(argv[2]);
  auto program = dslvm::Program::load(dslvm::read_file(argv[1]), schema, reg);
  Greeter greeter; dslvm::Context context; context.set("g", &greeter);
  program.run(context, reg);
  return dslvm::report_ok(dslvm::json_escape(greeter.last));
}
g++ -std=c++17 -Iinclude greeter.cpp -o greeter
host build: 0

4. Check signatures and run

Compare the compiler's canonical signature list with the registry, then run the compiled chunk:

./greeter --signatures
context g: Greeter
method Greeter.say(string) -> void
diff -u <(npx --yes --package=@lmctl-ai/lmctl -- lmscript --dsl-signatures schema.json) <(./greeter --signatures)
signature parity: 0
./greeter demo.dslb schema.json
{"ok": true, "result": "Hello from the DSL"}

What you learned

The compiler binds imports to the schema bytes; the host registers matching signatures, loads the program, provides owned objects through a context and executes the verified bytecode.