// s7Engine.c -- bridges the s7 Scheme adapter to the actor layer's CalogEngineT vtable.
//
// Every hook runs on the owning context's thread (createInterpreter, runSource,
// destroyInterpreter), confining the s7 interpreter to one thread. createInterpreter
// builds the interpreter and exposes the registered natives; runSource evaluates a
// script and reports failure through the single error channel (result).

#include "calogInternal.h"
#include "s7Adapter.h"

static int32_t s7EngineCreate(CalogContextT *context, void **interpOut);
static void    s7EngineDestroy(void *interp);
static int32_t s7EngineRun(void *interp, const char *source, CalogValueT *result);
static void    s7ExposeVisitor(const CalogEntryT *entry, void *ud);

static const char *const s7Extensions[] = { "scm", NULL };

const CalogEngineT calogS7Engine = {
    "scheme",
    s7Extensions,
    s7EngineCreate,
    s7EngineDestroy,
    s7EngineRun
};


static int32_t s7EngineCreate(CalogContextT *context, void **interpOut) {
    CalogS7T *s7;
    int32_t   status;

    *interpOut = NULL;
    status = calogS7Create(&s7, calogContextBroker(context), calogContextId(context));
    if (status != calogOkE) {
        return status;
    }
    calogForEach(calogContextBroker(context), s7ExposeVisitor, s7);
    *interpOut = s7;
    return calogOkE;
}


static void s7EngineDestroy(void *interp) {
    calogS7Destroy((CalogS7T *)interp);
}


static int32_t s7EngineRun(void *interp, const char *source, CalogValueT *result) {
    int32_t status;

    calogValueNil(result);
    status = calogS7Run((CalogS7T *)interp, source);
    if (status != calogOkE) {
        return calogFail(result, status, "scheme script failed");
    }
    return calogOkE;
}


static void s7ExposeVisitor(const CalogEntryT *entry, void *ud) {
    calogS7Expose((CalogS7T *)ud, entry->name);
}
