• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
No Tags

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Baremetal Lisp interpreter and compiler for low-resource devices


Commit MetaInfo

Revision0c8ad559cb691b8b6df62006cf5d429262639e8b (tree)
Time2020-09-08 07:58:00
AuthorAlaskanEmily <emily@alas...>
CommiterAlaskanEmily

Log Message

Add defrec

Change Summary

Incremental Difference

--- a/sl_i.c
+++ b/sl_i.c
@@ -21,6 +21,7 @@
2121 #include "sl_x.h"
2222
2323 #define SL_I_BIND_CAP_GROWTH 64
24+#define SL_I_REC_CAP_GROWTH 32
2425 #define SL_I_DEF_CAP_INIT 16
2526 #define SL_I_DEF_CAP_DOUBLE_MAX 256
2627
@@ -110,6 +111,20 @@ static sl_s_len_t sl_i_find_def(const struct SL_I_Runtime *rt,
110111
111112 /*****************************************************************************/
112113
114+static sl_s_len_t sl_i_find_rec(const struct SL_I_Runtime *rt,
115+ const struct SL_S_Atom *name){
116+
117+ register sl_s_len_t i, n;
118+ n = rt->num_recs;
119+ for(i = 0; i < n; i++){
120+ if(SL_S_COMPARE_ATOMS(rt->recs[i].name, name))
121+ return i;
122+ }
123+ return n;
124+}
125+
126+/*****************************************************************************/
127+
113128 static void sl_i_defun(struct SL_I_Runtime *rt,
114129 const struct SL_S_Atom *name,
115130 const struct SL_S_List *args,
@@ -265,6 +280,55 @@ static void sl_i_def(struct SL_I_Runtime *rt,
265280
266281 /*****************************************************************************/
267282
283+static void sl_i_defrec(struct SL_I_Runtime *rt,
284+ const struct SL_S_Atom *name,
285+ const struct SL_S_List *fields){
286+
287+ void *old;
288+ register sl_s_len_t i;
289+ struct SL_X_Record *rec;
290+
291+ /* Search for an existing function of this name. */
292+ i = sl_i_find_rec(rt, name);
293+
294+ /* Check if we found a matching bind or not. */
295+ if(i == rt->num_recs){
296+ /* Check if we need more room. */
297+ if(rt->cap_recs == i){
298+ /* Round up if the number of recs isn't a multiple of 32. */
299+ if(SL_I_UNLIKELY(rt->cap_recs & (SL_I_REC_CAP_GROWTH-1)))
300+ rt->cap_recs +=
301+ SL_I_REC_CAP_GROWTH + SL_I_REC_CAP_GROWTH -
302+ (rt->cap_recs & (SL_I_REC_CAP_GROWTH-1));
303+ else
304+ rt->cap_recs += SL_I_REC_CAP_GROWTH;
305+ /* Try to realloc */
306+ old = rt->recs;
307+ rt->recs = SL_S_Malloc(sizeof(struct SL_X_Record) * rt->cap_recs);
308+ if(SL_I_UNLIKELY(rt->recs == SL_S_NIL)){
309+ rt->pending_error = "Out of memory";
310+ rt->cap_recs = i;
311+ rt->recs = old;
312+ return;
313+ }
314+ SL_S_MemCopy(rt->recs, old, i * sizeof(struct SL_X_Record));
315+ SL_S_Free(old);
316+ }
317+ rt->num_recs++;
318+ rec = rt->recs + i;
319+ }
320+ else{
321+ rec = rt->recs + i;
322+ SL_S_DECREF(rec->name);
323+ SL_S_DECREF(rec->fields);
324+ }
325+
326+ rec->name = name;
327+ rec->fields = fields;
328+}
329+
330+/*****************************************************************************/
331+
268332 SL_S_FUNC(int) SL_I_Run(struct SL_I_Runtime *rt, const struct SL_S_List *code){
269333
270334 const struct SL_S_Atom *name, *hint;
@@ -296,6 +360,14 @@ SL_S_FUNC(int) SL_I_Run(struct SL_I_Runtime *rt, const struct SL_S_List *code){
296360 }
297361 sl_i_def(rt, hint, name, value);
298362 }
363+ else if(SL_X_IsDefrec(data) == 0){
364+ if(SL_X_ParseDefrec(data, &name, &body) != 0){
365+ rt->pending_error = "Error in defrec";
366+ return 1;
367+ }
368+ SL_S_INCREF(name);
369+ sl_i_defrec(rt, name, body);
370+ }
299371 else{
300372 SL_I_Execute(rt, code->head);
301373 }
--- a/sl_i.h
+++ b/sl_i.h
@@ -79,6 +79,9 @@ struct SL_I_Runtime{
7979 struct SL_I_Bind *binds;
8080 sl_s_len_t num_binds;
8181 sl_s_len_t cap_binds;
82+ struct SL_X_Record *recs;
83+ sl_s_len_t num_recs;
84+ sl_s_len_t cap_recs;
8285 struct SL_I_Frame global, *frames;
8386 const char *pending_error;
8487 void *error_free_ptr;
--- a/sl_x.c
+++ b/sl_x.c
@@ -49,6 +49,7 @@ SL_X_ATOM(sl_x_true, "true");
4949 SL_X_ATOM(sl_x_false, "false");
5050 SL_X_ATOM(sl_x_defun, "defun");
5151 SL_X_ATOM(sl_x_def, "def");
52+SL_X_ATOM(sl_x_defrec, "defrec");
5253 SL_X_ATOM(sl_x_if, "if");
5354 SL_X_ATOM(sl_x_let, "let");
5455 SL_X_ATOM(sl_x_plus, "+");
@@ -361,6 +362,42 @@ SL_S_PURE_FUNC(int) SL_X_IsDef(const struct SL_S_List *code){
361362 }
362363
363364 /*****************************************************************************/
365+#define SL_X_DEFREC_MIN_ARITY 2
366+static const unsigned char sl_x_defrec_flags[SL_X_DEFREC_MIN_ARITY] = {
367+ SL_S_IN_ATOM,
368+ SL_S_OUT_ATOM
369+};
370+
371+SL_S_PURE_FUNC(int) SL_X_IsDefrec(const struct SL_S_List *code){
372+ const void *args[SL_X_DEFREC_MIN_ARITY];
373+ int arity;
374+
375+ args[0] = SL_S_MK_ATOM(&sl_x_defrec);
376+
377+ arity = SL_S_Match(code,
378+ args,
379+ sl_x_defrec_flags,
380+ SL_X_DEFREC_MIN_ARITY,
381+ SL_X_DEFREC_MIN_ARITY);
382+
383+ if(arity == SL_X_DEFREC_MIN_ARITY){
384+ return 0;
385+ }
386+ else if(arity < 0 && (arity = -arity) > SL_X_DEFREC_MIN_ARITY){
387+ /* Test for the correct form in the fields. */
388+ code = code->tail->tail;
389+ do{
390+ if(!SL_S_IS_ATOM(code->head))
391+ return 1;
392+ }while((code = code->tail) != SL_S_NIL);
393+ return 0;
394+ }
395+ else{
396+ return 1;
397+ }
398+}
399+
400+/*****************************************************************************/
364401
365402 SL_S_FUNC(int) SL_X_ParseDefun(const struct SL_S_List *code,
366403 const struct SL_S_Atom **out_name,
@@ -375,6 +412,7 @@ SL_S_FUNC(int) SL_X_ParseDefun(const struct SL_S_List *code,
375412 *out_body = SL_S_PTR_FROM_TAG(code->tail->tail->tail);
376413 return 0;
377414 }
415+
378416 /*****************************************************************************/
379417
380418 SL_S_FUNC(int) SL_X_ParseDef(const struct SL_S_List *code,
@@ -421,6 +459,71 @@ SL_S_FUNC(int) SL_X_ParseDef(const struct SL_S_List *code,
421459
422460 /*****************************************************************************/
423461
462+static struct SL_S_List *sl_x_add_rec_field(
463+ const struct SL_S_Atom *name,
464+ const struct SL_S_Atom *hint){
465+
466+ struct SL_S_List *arg_pair, *to;
467+
468+ arg_pair = SL_S_Malloc(sizeof(struct SL_S_List));
469+ arg_pair->ref = 1;
470+ arg_pair->tail = SL_S_Malloc(sizeof(struct SL_S_List));
471+ arg_pair->tail->ref = 1;
472+ arg_pair->tail->tail = SL_S_NIL;
473+
474+ arg_pair->head = SL_S_MK_ATOM(hint);
475+ arg_pair->tail->head = SL_S_MK_ATOM(name);
476+
477+ to = SL_S_Malloc(sizeof(struct SL_S_List));
478+ to->ref = 1;
479+ to->head = SL_S_MK_LIST(arg_pair);
480+ return to;
481+}
482+
483+SL_S_FUNC(int) SL_X_ParseDefrec(const struct SL_S_List *code,
484+ const struct SL_S_Atom **out_name,
485+ const struct SL_S_List **out_fields){
486+
487+ const struct SL_S_Atom *name, *hint;
488+ struct SL_S_List *ret, **dest;
489+ register const struct SL_S_Atom *atom;
490+ register const struct SL_S_Atom **target;
491+
492+ *out_name = SL_S_PTR_FROM_TAG(code->tail->head);
493+ code = code->tail->tail;
494+ if(code == SL_S_NIL){
495+ *out_fields = SL_S_NIL;
496+ return 0;
497+ }
498+
499+ dest = &ret;
500+ do{
501+ atom = SL_S_PTR_FROM_TAG(code->head);
502+ SL_S_INCREF(atom);
503+ if(atom->len > 1 && atom->text[0] == '^')
504+ target = &hint;
505+ else
506+ target = &name;
507+ if(*target != SL_S_NIL){
508+ *dest = sl_x_add_rec_field(hint, name);
509+ dest = &((*dest)->tail);
510+ }
511+ *target = atom;
512+ }while((code = code->tail) != SL_S_NIL);
513+
514+ if(hint != SL_S_NIL || name != SL_S_NIL){
515+ *dest = sl_x_add_rec_field(hint, name);
516+ (*dest)->tail = SL_S_NIL;
517+ }
518+ else{
519+ *dest = SL_S_NIL;
520+ }
521+ *out_fields = ret;
522+ return 0;
523+}
524+
525+/*****************************************************************************/
526+
424527 static struct SL_S_List *sl_x_create_args(const struct SL_S_Atom *hint,
425528 const struct SL_S_Atom *name){
426529
--- a/sl_x.h
+++ b/sl_x.h
@@ -41,6 +41,7 @@ const extern struct SL_S_Atom
4141 sl_x_nil, sl_x_true, sl_x_false,
4242 sl_x_defun,
4343 sl_x_def,
44+ sl_x_defrec,
4445 sl_x_if,
4546 sl_x_let,
4647 sl_x_comment, sl_x_dot, sl_x_tick,
@@ -77,6 +78,14 @@ struct SL_X_Def{
7778
7879 /*****************************************************************************/
7980
81+struct SL_X_Record{
82+ const struct SL_S_Atom *name;
83+ /* Each field is structured as (hint name) where hint or name may be nil */
84+ const struct SL_S_List *fields;
85+};
86+
87+/*****************************************************************************/
88+
8089 SL_S_PURE_FUNC(int) SL_X_IsRuntimeConstant(const void *value);
8190
8291 /*****************************************************************************/
@@ -101,8 +110,13 @@ SL_S_PURE_FUNC(int) SL_X_IsDef(const struct SL_S_List *code);
101110
102111 /*****************************************************************************/
103112 /* Returns 0 on success. */
113+SL_S_PURE_FUNC(int) SL_X_IsDefrec(const struct SL_S_List *code);
114+
115+/*****************************************************************************/
116+/* Returns 0 on success. */
104117 SL_S_PURE_FUNC(int) SL_X_IsImport(const struct SL_S_List *code);
105118
119+/*****************************************************************************/
106120 /* Returns 0 on success.
107121 * Does not do increfs, so you've been warned.
108122 */
@@ -122,6 +136,15 @@ SL_S_FUNC(int) SL_X_ParseDef(const struct SL_S_List *code,
122136
123137 /*****************************************************************************/
124138 /* Returns 0 on success.
139+ * This DOES incref the fields, unlike the other parsers.
140+ * This does no incref the name.
141+ */
142+SL_S_FUNC(int) SL_X_ParseDefrec(const struct SL_S_List *code,
143+ const struct SL_S_Atom **out_name,
144+ const struct SL_S_List **out_fields);
145+
146+/*****************************************************************************/
147+/* Returns 0 on success.
125148 * The args is a list of lists, of the structure ((hint name) (hint name) ...)
126149 */
127150 SL_S_FUNC(struct SL_S_List) *SL_X_ParseArgs(const struct SL_S_List *args);
--- /dev/null
+++ b/tests/rec1.lsp
@@ -0,0 +1,6 @@
1+; Any copyright is dedicated to the Public Domain.
2+; https://creativecommons.org/publicdomain/zero/1.0/
3+
4+(defrec foo
5+ ^int i
6+ x)