6. Top-Level Data

All components are managed using a top-level struct called txtvm.

<<typedefs>>=
typedef struct txtvm txtvm;

This includes an instance of a stack and a dictionary.

Oh, and an I/O interface.

<<structs>>=
struct txtvm {
    txtvm_stack stack;
    txtvm_dict dict;
    txtvm_io io;
};

txtvm is initialized with txtvm_init.

<<funcdefs>>=
void txtvm_init(txtvm *vm);
<<funcs>>=
void txtvm_init(txtvm *vm)
{
    txtvm_stack_init(&vm->stack);
    txtvm_dict_init(&vm->dict);
}
<<funcdefs>>=
void txtvm_free(txtvm *vm);
<<funcs>>=
void txtvm_free(txtvm *vm)
{
    txtvm_dict_free(&vm->dict);
}

A getter for the stack is required for any functions to work.

<<funcdefs>>=
txtvm_stack *txtvm_stack_get(txtvm *vm);
<<funcs>>=
txtvm_stack *txtvm_stack_get(txtvm *vm)
{
    return &vm->stack;
}

The define operation is built on top of the append operation, and is designed to make it easier to add functions. in addition to the main callback and id, userdata and a cleanup callback can be provided. If they are NULLthey are ignored.

<<funcdefs>>=
void txtvm_define(txtvm *vm,
                  short id,
                  int (*fun)(txtvm*,void*),
                  void *ud,
                  void (*del)(void*));
<<funcs>>=
void txtvm_define(txtvm *vm,
                  short id,
                  int (*fun)(txtvm*,void*),
                  void *ud,
                  void (*del)(void*))
{
    txtvm_dict_entry *ent;
    txtvm_dict *dict;

    dict = &vm->dict;

    ent = txtvm_dict_new_entry(dict, id);

    ent->fun = fun;
    ent->ud = ud;
    ent->clean = del;
}

A function in txtvm is looked up and called with txtvm_call.

<<funcdefs>>=
int txtvm_call(txtvm *vm, short id);
<<funcs>>=
int txtvm_call(txtvm *vm, short id)
{
    int rc;
    txtvm_dict_entry *e;

    e = NULL;
    rc = txtvm_dict_lookup(&vm->dict, id, &e);

    if (rc != TXTVM_OK) return rc;

    if (e->fun != NULL) return e->fun(vm, e->ud);

    return TXTVM_OK;
}

Some pushing/popping abstractions are made for convenience.

<<funcdefs>>=
int txtvm_pop(txtvm *vm, txtvm_stacklet **s);
int txtvm_push(txtvm *vm, txtvm_stacklet **s);
<<funcs>>=
int txtvm_pop(txtvm *vm, txtvm_stacklet **s)
{
    return txtvm_stack_pop(&vm->stack, s);
}

int txtvm_push(txtvm *vm, txtvm_stacklet **s)
{
    return txtvm_stack_push(&vm->stack, s);
}
<<funcdefs>>=
int txtvm_pop_int(txtvm *vm, int *i);
int txtvm_push_int(txtvm *vm, int i);
<<funcs>>=
int txtvm_pop_int(txtvm *vm, int *i)
{
    return txtvm_stack_pop_int(&vm->stack, i);
}

int txtvm_push_int(txtvm *vm, int i)
{
    return txtvm_stack_push_int(&vm->stack, i);
}
<<funcdefs>>=
void txtvm_setup_writer(txtvm *vm,
                        txtvm_io_writebuf_data *data);
<<funcs>>=
void txtvm_setup_writer(txtvm *vm,
                        txtvm_io_writebuf_data *data)
{
    txtvm_io_writebuf(&vm->io, data);
}
<<funcdefs>>=
void txtvm_setup_parser(txtvm *vm,
                        txtvm_io_readbuf_data *data);
<<funcs>>=
void txtvm_setup_parser(txtvm *vm,
                        txtvm_io_readbuf_data *data)
{
    txtvm_io_readbuf(&vm->io, data);
}



prev | home | next