mirror of https://github.com/smlckz/lith
170 lines
4.7 KiB
C
170 lines
4.7 KiB
C
/* lith: library header */
|
|
#ifndef lith_h
|
|
#define lith_h
|
|
|
|
#include <stddef.h>
|
|
#include <stdio.h>
|
|
|
|
#define LITH_VERSION_STRING "0.1.0-alpha"
|
|
|
|
typedef struct lith_value lith_value;
|
|
typedef struct lith_value lith_env;
|
|
typedef struct lith_state lith_st;
|
|
typedef struct lith_string lith_string;
|
|
typedef struct lith_callable lith_callable;
|
|
typedef struct lith_lib_fn *lith_lib;
|
|
|
|
enum lith_error {
|
|
LITH_ERR_OK,
|
|
LITH_ERR_EOF,
|
|
LITH_ERR_SYNTAX,
|
|
LITH_ERR_NOMEM,
|
|
LITH_ERR_UNBOUND,
|
|
LITH_ERR_REDEFINE,
|
|
LITH_ERR_NARGS,
|
|
LITH_ERR_TYPE,
|
|
LITH_ERR_CUSTOM
|
|
};
|
|
|
|
enum lith_value_type {
|
|
LITH_TYPE_NIL,
|
|
LITH_TYPE_PAIR,
|
|
LITH_TYPE_BOOLEAN,
|
|
LITH_TYPE_INTEGER,
|
|
LITH_TYPE_NUMBER,
|
|
LITH_TYPE_STRING,
|
|
LITH_TYPE_SYMBOL,
|
|
LITH_TYPE_BUILTIN,
|
|
LITH_TYPE_CLOSURE,
|
|
LITH_TYPE_MACRO,
|
|
|
|
LITH_NTYPES /* number of types */
|
|
};
|
|
|
|
/* ISO C forbids forward references to 'enum' types */
|
|
typedef enum lith_value_type lith_valtype;
|
|
|
|
typedef lith_value *(*lith_builtin_function)(lith_st *, lith_value *);
|
|
|
|
struct lith_value {
|
|
lith_valtype type;
|
|
union {
|
|
int boolean;
|
|
long integer;
|
|
double number;
|
|
struct lith_string {
|
|
size_t len;
|
|
char *buf;
|
|
} string;
|
|
char *symbol;
|
|
struct {
|
|
struct lith_value *car, *cdr;
|
|
} pair;
|
|
struct lith_callable {
|
|
int exact;
|
|
size_t expect;
|
|
lith_value *name;
|
|
lith_builtin_function function;
|
|
lith_env *parent;
|
|
lith_value *args, *body;
|
|
} *callable;
|
|
} value;
|
|
};
|
|
|
|
|
|
#define LITH_IS(p, q) ((p)->type == (q))
|
|
#define LITH_IS_NIL(p) (LITH_IS(p, LITH_TYPE_NIL))
|
|
|
|
#define LITH_SYM_EQ(S, s) !strcmp((S)->value.symbol, (s))
|
|
|
|
#define LITH_CAR(p) ((p)->value.pair.car)
|
|
#define LITH_CDR(p) ((p)->value.pair.cdr)
|
|
#define LITH_CONS lith_make_pair
|
|
|
|
#define LITH_IS_CALLABLE(F) \
|
|
(LITH_IS(F, LITH_TYPE_MACRO) || LITH_IS(F, LITH_TYPE_CLOSURE) || \
|
|
LITH_IS(F, LITH_TYPE_BUILTIN))
|
|
|
|
struct lith_state {
|
|
enum lith_error error;
|
|
struct lith_error_state {
|
|
int success, manual;
|
|
char *msg, *sym, *name;
|
|
lith_value *expr;
|
|
struct lith_error_state__argsize {
|
|
size_t expected, got;
|
|
int exact;
|
|
} nargs;
|
|
struct lith_error_state__type {
|
|
lith_valtype expected, got;
|
|
size_t narg;
|
|
} type;
|
|
} error_state;
|
|
char *types[LITH_NTYPES];
|
|
lith_value *nil;
|
|
lith_value *True, *False;
|
|
lith_value *symbol_table;
|
|
lith_env *global;
|
|
char *filename;
|
|
};
|
|
|
|
struct lith_lib_fn {
|
|
char *name;
|
|
size_t expect; int exact;
|
|
lith_builtin_function fn;
|
|
};
|
|
|
|
extern struct lith_lib_fn lith_builtins[];
|
|
|
|
#define LITH_IS_ERR(L) ((L)->error != LITH_ERR_OK)
|
|
#define LITH_AT_END_NO_ERR(L) (((L)->error == LITH_ERR_EOF) && (L)->error_state.success)
|
|
|
|
#define LITH_TO_BOOL(B) ((!LITH_IS_NIL(B)) && !(LITH_IS(B, LITH_TYPE_BOOLEAN) && !((B)->value.boolean)))
|
|
#define LITH_IN_BOOL(B) ((B) ? L->True : L->False)
|
|
|
|
/* Public functions: the API of this library */
|
|
|
|
void lith_init(lith_st *);
|
|
void lith_free(lith_st *);
|
|
void lith_clear_error_state(lith_st *);
|
|
void lith_print_error(lith_st *, int);
|
|
void lith_simple_error(lith_st *, enum lith_error, char *);
|
|
|
|
lith_value *lith_new_value(lith_st *);
|
|
void lith_print_value(lith_st *, lith_value *, FILE *);
|
|
void lith_free_value(lith_value *);
|
|
lith_value *lith_copy_value(lith_st *, lith_value *);
|
|
|
|
lith_value *lith_make_integer(lith_st *, long);
|
|
lith_value *lith_make_number(lith_st *, double);
|
|
lith_value *lith_make_symbol(lith_st *, char *);
|
|
lith_value *lith_make_string(lith_st *, char *, size_t);
|
|
lith_value *lith_make_builtin(lith_st *, lith_value *, lith_builtin_function, size_t, int);
|
|
lith_value *lith_make_closure(lith_st *, lith_env *, lith_value *, lith_value *, lith_value *, size_t, int);
|
|
lith_value *lith_make_pair(lith_st *, lith_value *, lith_value *);
|
|
|
|
lith_value *lith_get_symbol(lith_st *, char *);
|
|
|
|
lith_value *lith_read_expr(lith_st *, char *, char **);
|
|
|
|
lith_value *lith_eval_expr(lith_st *, lith_env *, lith_value *);
|
|
|
|
lith_value *lith_apply(lith_st *, lith_value *f, lith_value *args);
|
|
|
|
lith_env *lith_new_env(lith_st *, lith_env *);
|
|
void lith_free_env(lith_env *);
|
|
|
|
lith_value *lith_env_get(lith_st *, lith_env *, lith_value *);
|
|
void lith_env_set(lith_st *, lith_env *, lith_value *, lith_value *);
|
|
void lith_env_put(lith_st *, lith_env *, lith_value *, lith_value *);
|
|
|
|
void lith_fill_env(lith_st *, lith_lib);
|
|
|
|
int lith_expect_type(lith_st *, char *, size_t, lith_valtype, lith_value *);
|
|
int lith_expect_nargs(lith_st *, char *, size_t, lith_value *, int);
|
|
|
|
void lith_run_string(lith_st *, lith_env *, char *, int);
|
|
void lith_run_file(lith_st *, lith_env *, char *);
|
|
|
|
#endif /* lith_h */
|