Getting started
You will end this page with a C++ program that runs one line of script and prints hello.
Install
CMake, with this repo as a subdirectory:
add_subdirectory(ReScripted)
target_link_libraries(your_app PRIVATE ReScripted::ReScripted)
Without CMake: copy include/ReScripted.h onto your include path. Compile as C++17.
There is no .a or .so to link. The header is the library.
Four calls, every time
Every ReScripted program does the same four things:
Engine engine— the object that holds languages, C++ functions, and loaded scriptsengine.add_language(...)— “scripts in this language look like this”engine.bind("print", ...)— “when a script saysprint, run this C++”engine.eval(...)orload/run— run a script
A program that prints hello
This is Mini: let, fn, { }, ;. Copy the whole thing. It should print hello.
#include <ReScripted.h>
#include <iostream>
int main() {
rescripted::Engine engine;
// JSON: what Mini scripts look like. Compiled into this program.
engine.add_language(RESCRIPTED_LANGUAGE(R"({
"name": "Mini",
"extensions": [".mini"],
"variables": {
"enabled": true,
"declaration_keywords": ["let"],
"assignment_operators": ["="]
},
"functions": {
"enabled": true,
"declaration_keywords": ["fn"],
"return_keywords": ["return"]
},
"tokens": { "statement_terminators": [";"] },
"blocks": { "delimiter": { "enabled": true, "open": "{", "close": "}" } },
"entry_point": { "top_level_execution": true }
})"));
// Built-in print only returns a string. This one writes to the console.
engine.bind("print", [](const std::vector<rescripted::Value>& args) {
for (const auto& arg : args) {
std::cout << arg.to_string() << '\n';
}
return rescripted::Value();
});
engine.eval("print(\"hello\");", "Mini");
}
What each part is:
Engineholds languages, C++ functions, and loaded scripts.- The JSON is the language.
"name": "Mini"is the string you pass toeval."let","fn",";", and{ }are the words scripts may use. "extensions"letsload_file("ai.mini")pick Mini later.top_level_executionmeansrun()executes code at the top of a file, not only functions.bind("print", ...)is your C++. Skip it andprintstill exists but nothing appears on stdout.eval(..., "Mini")parses that text as Mini, runs it, and throws it away.
This short JSON is enough for hello world. A language you ship should be a full file — copy examples/mini/mini.json or see Language JSON.
A script as a file
eval is for one-liners. Real scripts live on disk.
Part of examples/mini/hello.mini:
let greeting = "hello from Mini";
print(greeting);
fn shout(name) {
return "hey " + name;
}
examples/mini/host.cpp (trimmed):
engine.add_language(rescripted::Language::compile(rescripted::embed::mini));
engine.bind("print", /* same lambda as above */);
auto id = engine.load_file("hello.mini"); // parse; shout now exists
engine.run(id); // greeting is set; print runs
engine.call("shout", {rescripted::Value("world")}); // "hey world"
engine.unload(id); // greeting and shout are gone
print is still there after unload. Host functions are not part of the script.
How rescripted::embed::mini gets into the program is the next page.
Next
- Putting the language in the binary — CMake copies
mini.jsoninto a header so you are not pasting JSON intomain - Calling C++ from a script — bind
spawnthe same way you boundprint - Loading scripts — load / run / unload in detail
The working copy of this setup is examples/mini/ in this repo.