Jason Daniels / AriaLisp
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers aria.h Source File

aria.h

00001 /**
00002  * Copyright (c) 2016 rxi
00003  *
00004  * This library is free software; you can redistribute it and/or modify it
00005  * under the terms of the MIT license. See LICENSE for details.
00006  */
00007 
00008 #ifndef ARIA_H
00009 #define ARIA_H
00010 
00011 #include <stdio.h>
00012 #include <stdlib.h>
00013 #include <stdarg.h>
00014 #include <string.h>
00015 #include <setjmp.h>
00016 #include <ctype.h>
00017 
00018 #define AR_VERSION "0.1.1"
00019 
00020 #ifdef __cplusplus
00021 extern "C" {
00022 #endif
00023 
00024 typedef struct ar_Value ar_Value;
00025 typedef struct ar_State ar_State;
00026 typedef struct ar_Chunk ar_Chunk;
00027 typedef struct ar_Frame ar_Frame;
00028 typedef struct ar_FuncMap ar_FuncMap;
00029 
00030 typedef void *(*ar_Alloc)(void *udata, void *ptr, size_t size);
00031 typedef ar_Value* (*ar_CFunc)(ar_State *S, ar_Value* args);
00032 typedef ar_Value* (*ar_Prim)(ar_State *S, ar_Value* args, ar_Value *env);
00033 
00034 
00035 struct ar_Value {
00036   unsigned char type, mark;
00037   union {
00038     struct { ar_Value *name; int line;            } dbg;
00039     struct { ar_Value *pair, *left, *right;       } map;
00040     struct { ar_Value *car, *cdr, *dbg;           } pair;
00041     struct { double n;                            } num;
00042     struct { ar_Value *params, *body, *env;       } func;
00043     struct { void *ptr; ar_CFunc gc, mark;        } udata;
00044     struct { ar_Value *parent, *map;              } env;
00045     struct { ar_CFunc fn;                         } cfunc;
00046     struct { ar_Prim fn;                          } prim;
00047     struct { char *s; size_t len; unsigned hash;  } str;
00048   } u;
00049 };
00050 
00051 
00052 struct ar_Frame {
00053   struct ar_Frame *parent;  /* Parent stack frame */
00054   ar_Value *caller;         /* Calling function pair */
00055   jmp_buf *err_env;         /* Jumped to on error, if it exists */
00056   int stack_idx;            /* Index on stack where frame's values start */
00057 };
00058 
00059 
00060 struct ar_State {
00061   ar_Alloc alloc;           /* Allocator function */
00062   void *udata;              /* Pointer passed as allocator's udata */
00063   ar_Value *global;         /* Global environment */
00064   ar_Frame base_frame;      /* Base stack frame */
00065   ar_Frame *frame;          /* Current stack frame */
00066   int frame_idx;            /* Current stack frame index */
00067   ar_Value *t;              /* Symbol `t` */
00068   ar_CFunc panic;           /* Called if an unprotected error occurs */
00069   ar_Value *err_args;       /* Error args passed to error handler */
00070   ar_Value *oom_error;      /* Value thrown on an out of memory error */
00071   ar_Value *oom_args;       /* Args passed to err handler on out of mem */
00072   ar_Value *parse_name;     /* Parser's current chunk name */
00073   int parse_line;           /* Parser's current line */
00074   ar_Value **gc_stack;      /* Stack of values (protected from GC) */
00075   int gc_stack_idx;         /* Current index for the top of the gc_stack */
00076   int gc_stack_cap;         /* Max capacity of protected values stack */
00077   ar_Chunk *gc_chunks;      /* List of all chunks */
00078   ar_Value *gc_pool;        /* Dead (usable) Values */
00079   int gc_count;             /* Counts down number of new values until GC */
00080 };
00081 
00082 struct ar_FuncMap { 
00083     const char *name; 
00084     ar_CFunc fn; 
00085 }; 
00086 
00087 enum {
00088   AR_TNIL,
00089   AR_TDBGINFO,
00090   AR_TMAPNODE,
00091   AR_TPAIR,
00092   AR_TNUMBER,
00093   AR_TSTRING,
00094   AR_TSYMBOL,
00095   AR_TFUNC,
00096   AR_TMACRO,
00097   AR_TPRIM,
00098   AR_TCFUNC,
00099   AR_TENV,
00100   AR_TUDATA
00101 };
00102 
00103 #define ar_get_global(S,x)    ar_eval(S, ar_new_symbol(S, x), (S)->global)
00104 #define ar_bind_global(S,x,v) ar_bind(S, ar_new_symbol(S, x), v, (S)->global)
00105 #define ar_call_global(S,f,a) ar_call(S, ar_get_global(S, f), a)
00106 #define ar_bind_global_list(S,l)                                    \
00107   for (int i = 0; l[i].name; i++)                                  \
00108     ar_bind_global(S, l[i].name, ar_new_cfunc(S, l[i].fn))         \
00109                                                                    
00110 
00111 
00112 
00113 #define ar_check_string(S,v)  ar_to_string(S, ar_check(S, v, AR_TSTRING))
00114 #define ar_check_udata(S,v)   ar_to_udata(S, ar_check(S, v, AR_TUDATA))
00115 #define ar_check_number(S,v)  ar_to_number(S, ar_check(S, v, AR_TNUMBER))
00116 
00117 #define ar_try(S, err_val, blk, err_blk)                  \
00118   do {                                                    \
00119     jmp_buf err_env__, *old_env__ = (S)->frame->err_env;  \
00120     S->frame->err_env = &err_env__;                       \
00121     if (setjmp(err_env__)) {                              \
00122       ar_Value *err_val = (S)->err_args;                  \
00123       (S)->frame->err_env = old_env__;                    \
00124       err_blk;                                            \
00125     } else {                                              \
00126       blk;                                                \
00127       (S)->frame->err_env = old_env__;                    \
00128     }                                                     \
00129   } while (0)
00130 
00131 ar_State *ar_new_state(ar_Alloc alloc, void *udata);
00132 void ar_close_state(ar_State *S);
00133 ar_CFunc ar_at_panic(ar_State *S, ar_CFunc fn);
00134 void ar_error(ar_State *S, ar_Value *err);
00135 void ar_error_str(ar_State *S, const char *fmt, ...);
00136 
00137 ar_Value *ar_new_env(ar_State *S, ar_Value *parent);
00138 ar_Value *ar_new_pair(ar_State *S, ar_Value *car, ar_Value *cdr);
00139 ar_Value *ar_new_list(ar_State *S, size_t n, ...);
00140 ar_Value *ar_new_number(ar_State *S, double n);
00141 ar_Value *ar_new_udata(ar_State *S, void *ptr, ar_CFunc gc, ar_CFunc mark);
00142 ar_Value *ar_new_stringl(ar_State *S, const char *str, size_t len);
00143 ar_Value *ar_new_string(ar_State *S, const char *str);
00144 ar_Value *ar_new_symbol(ar_State *S, const char *name);
00145 ar_Value *ar_new_cfunc(ar_State *S, ar_CFunc fn);
00146 ar_Value *ar_new_prim(ar_State *S, ar_Prim fn);
00147 
00148 int ar_type(ar_Value *v);
00149 const char *ar_type_str(int type);
00150 ar_Value *ar_check(ar_State *S, ar_Value *v, int type);
00151 ar_Value *ar_car(ar_Value *v);
00152 ar_Value *ar_cdr(ar_Value *v);
00153 ar_Value *ar_nth(ar_Value *v, int idx);
00154 ar_Value **ar_append_tail(ar_State *S, ar_Value **last, ar_Value *v);
00155 ar_Value *ar_to_string_value(ar_State *S, ar_Value *v, int quotestr);
00156 
00157 const char *ar_to_stringl(ar_State *S, ar_Value *v, size_t *len);
00158 const char *ar_to_string(ar_State *S, ar_Value *v);
00159 void *ar_to_udata(ar_State *S, ar_Value *v);
00160 double ar_to_number(ar_State *S, ar_Value *v);
00161 const char *ar_opt_string(ar_State *S, ar_Value *v, const char *def);
00162 void *ar_opt_udata(ar_State *S, ar_Value *v, void *def);
00163 double ar_opt_number(ar_State *S, ar_Value *v, double def);
00164 
00165 ar_Value *ar_bind(ar_State *S, ar_Value *sym, ar_Value *v, ar_Value *env);
00166 ar_Value *ar_set(ar_State *S, ar_Value *sym, ar_Value *v, ar_Value *env);
00167 
00168 void ar_mark(ar_State *S, ar_Value *v);
00169 void ar_gc(ar_State *S);
00170 
00171 ar_Value *ar_parse(ar_State *S, const char *str, const char *name);
00172 ar_Value *ar_eval(ar_State *S, ar_Value *v, ar_Value *env);
00173 ar_Value *ar_call(ar_State *S, ar_Value *fn, ar_Value *args);
00174 ar_Value *ar_do_list(ar_State *S, ar_Value *body, ar_Value *env);
00175 ar_Value *ar_do_string(ar_State *S, const char *str);
00176 ar_Value *ar_do_file(ar_State *S, const char *filename);
00177 
00178 
00179 #ifdef __cplusplus
00180 }
00181 #endif
00182 
00183 #endif
00184