GavelScript: An easily embeddable scripting language for your C++ application!

39 views single-header-library c++

by CPunch

[Repository for this project is here]


Hey! I've been working on this passion project for a while now (longer than the repository says lol, trust me), and I think i'm finally prepared to talk about it, but first let's talk about why scripting languages are important.


If you've ever coded before, chances are you started on a scripting language. Scripting languages (more often than not) are simple and easy to understand, which is what makes them great languages for new coders! Personally I started out with Lua (couldn't have guessed that!) so I have a real softspot for the syntax. Lua's syntax just breathes simplicity and human readability! Why does this matter? In my mind, simplicity is everything. With scripting languages you empower people with the ability to create. This. Is. Huge. Not only are you giving people the ability to create and expand upon something they're already passionate about (be it a game or an application), you're giving them the logical skills to pursue other scripting languages and even other programming languages!


So, I've been quietly been working on GavelScript! Which is a passion project of mine which lets c++ developers easily embed a small scripting environment in their games/applications! It started out as a small project that was going to become a series, however the project quickly became wayy too big for that haha.


[GavelScript shell with a few examples :)]


So, lets look at just how easy it is to use GavelScript.


Here's a basic shell-like interface thing for GavelScript that I wrote to test things.


#include <fstream>
#include "gavel.h"

int main() {
    std::cout << Gavel::getVersionString() << " not-so-interactive shell" << std::endl;

    std::string script;
    GState* state = new GState();
    Gavel::lib_loadLibrary(state);

    while (true) {
        std::cout << ">> ";
        std::getline(std::cin, script);
        GavelCompiler compiler(script.c_str());
        GChunk* mainChunk = compiler.compile();

        if (mainChunk == NULL) {
            std::cout << compiler.getObjection().getFormatedString() << std::endl;
            continue;
        }

        if (!state->start(mainChunk)) {
            // objection occurred
            std::cout << state->getObjection().getFormatedString() << std::endl;
            state->stack.clearStack();
        }
    }

    delete state;
    return 0;
}


So now we have a basic GavelScript shell.. what if we wanted to add our own stuff to the GavelScript environment? It's incredibly easy to do.


GValueTable GTT;
GTT.newIndex("pi", 3.1415926535);
GTT.newIndex(1, "Hello");
GTT.newIndex(2, "World");

state->setGlobal("GTable", reinterpret_cast<GValue*>(&GTT));


Then in our shell we can use it!



We can even add our own C Functions to the environment like so:


GValue* lib_quit(GState* state, int args) {
    exit(0);

    // this shouldn't even be executed tbh (might not even be compiled in depending on the compiler :eyes:)
    return CREATECONST_NULL();
}


state->setGlobal("quit", lib_quit);


Then call it!



If you'd like to read more about the API, checkout the wiki!


Anyways sorry for the short post. I've literally been spending the past 2 months just working on this one project LOL. Don't worry though I have some plans for some much smaller projects soon :eyes:


See you soon!

Jan 23, 2020 by CPunch