#ifndef _MOTOOLS_H
#define _MOTOOLS_H

#include <stdlib.h>

#define MOTOOLS_VERSION 1

typedef enum {
  MO_NUM,
  MO_STRING,
  MO_BSTRING
} mo_kind_t;

typedef struct {
  const char *name;
  const char *signature;
  int is_op;
  unsigned int op_prec;
  unsigned int op_assoc;
  void (*callback)(void);
} mo_exported_t;

typedef int (*mo_getbstring_t)(unsigned int, unsigned char *buf, size_t z);
mo_getbstring_t mo_getbstring;
typedef void (*mo_putbstring_t)(unsigned char *, size_t);
mo_putbstring_t mo_putbstring;
typedef int (*mo_getstring_t)(unsigned int, char *, size_t);
mo_getstring_t mo_getstring;
typedef void (*mo_putstring_t)(char *);
mo_putstring_t mo_putstring;
typedef double (*mo_getnum_t)(unsigned int);
mo_getnum_t mo_getnum;
typedef double (*mo_putnum_t)(double);
mo_putnum_t mo_putnum;
typedef unsigned int (*mo_putlist_t)(mo_kind_t);
mo_putlist_t mo_putlist;
typedef void (*mo_addbstring_t)(unsigned int, unsigned char *, size_t);
mo_addbstring_t mo_addbstring;
typedef void (*mo_addstring_t)(unsigned int, char *);
mo_addstring_t mo_addstring;
typedef void (*mo_addnum_t)(unsigned int, double);
mo_addnum_t mo_addnum;

void mo_init_f(void);

unsigned int get_motools_version(void) {
  return MOTOOLS_VERSION;
}

void __MO_SYNC__(
  mo_getbstring_t getbstring_f,
  mo_putbstring_t putbstring_f,
  mo_getstring_t getstring_f,
  mo_putstring_t putstring_f,
  mo_getnum_t getnum_f,
  mo_putnum_t putnum_f,
  mo_putlist_t putlist_f,
  mo_addbstring_t addbstring_f,
  mo_addstring_t addstring_f,
  mo_addnum_t addnum_f
) {
  mo_getbstring = getbstring_f;
  mo_putbstring = putbstring_f;
  mo_getstring = getstring_f;
  mo_putstring = putstring_f;
  mo_getnum = getnum_f;
  mo_putnum = putnum_f;
  mo_putlist = putlist_f;
  mo_addbstring = addbstring_f;
  mo_addstring = addstring_f;
  mo_addnum = addnum_f;
}

/*
EXAMPLE:

void test_cb(void);
 
unsigned int mo_exports_count = 1;
mo_exported_t mo_exports[1] = {
  {
    .name = "test",
    .signature = "[num] -> [num]",
    .is_op = 0,
    .op_prec = 0,
    .op_assoc = 'l',

    .callback = test_cb
  }
};
*/

#endif
