4 files changed, 407 insertions(+), 607 deletions(-)
D src/lispkit.c
D src/lispkit.h
M src/main.c
D src/secd.c
D src/lispkit.c => src/lispkit.c +0 -354
@@ 1,354 0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "lispkit.h"
-
-/*
-Copyright (c) 2011 A. Carl Douglas
-Copyright (c) 2023 Devine Lu Linvega
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE.
-*/
-
-/* - GC -------------------------------------- */
-
-#define NUM_CELLS 65535
-
-unsigned alloc_counter;
-unsigned collect_counter;
-unsigned num_cells;
-
-void *mem;
-Object **cells;
-Object *ff;
-
-void
-gc_mark(Object *object)
-{
- if(gc_header(object)->marked == 0) {
- gc_header(object)->marked = 1;
- if(isatom(object) == 0) {
- gc_mark(car(object));
- gc_mark(cdr(object));
- }
- }
-}
-
-void
-gc_init()
-{
- const unsigned cell_size = sizeof(struct GCHeader) + sizeof(Object);
- unsigned char *ptr;
- unsigned i;
-
- num_cells = getenv("LISPKIT_MEMORY") ? atoi(getenv("LISPKIT_MEMORY")) : NUM_CELLS;
-
- mem = calloc(num_cells, cell_size);
- cells = calloc(num_cells, sizeof(Object *));
-
- alloc_counter = 0;
- collect_counter = 0;
-
- ff = NULL;
-
- for(i = 0, ptr = mem; i < num_cells; i++, ptr += cell_size) {
- cells[i] = (Object *)((struct GCHeader *)ptr + 1);
- cells[i]->Cons.cdr = ff;
- ff = cells[i];
- }
-}
-
-void
-gc_exit()
-{
- free(mem);
- free(cells);
-}
-
-Object *
-gc_alloc()
-{
- Object *object;
-
- if(ff == NULL)
- gc_collect_garbage();
-
- object = ff;
- ff = ff->Cons.cdr;
- gc_header(object)->type = 0;
-
- alloc_counter++;
-
- return object;
-}
-
-void
-gc_collect()
-{
- int i;
- for(i = 0; i < NUM_CELLS; i++) {
- if(gc_header(cells[i])->marked == 0) {
- cells[i]->Cons.cdr = ff;
- ff = cells[i];
- collect_counter++;
- }
- }
-}
-
-void
-gc_collect_garbage()
-{
- int i;
- for(i = 0; i < NUM_CELLS; i++)
- gc_header(cells[i])->marked = 0;
- gc_mark(_rS);
- gc_mark(_rE);
- gc_mark(_rC);
- gc_mark(_rD);
- gc_mark(_t);
- gc_mark(_f);
- gc_mark(_nil);
- gc_collect();
- if(ff == NULL)
- crash("Error: Out of memory", "GC", "");
-}
-
-void
-gc_stats()
-{
- fprintf(stderr, "Cells: %u\n", num_cells);
- fprintf(stderr, "Allocates: %u\n", alloc_counter);
- fprintf(stderr, "Collects: %u\n", collect_counter);
-}
-
-/* - LISPKIT --------------------------------- */
-
-#define DICTLEN 0x8000
-
-static char dict_buf[DICTLEN], *dict_end;
-
-void
-crash(char *err, const char *value, const char *id)
-{
- fprintf(stderr, err, value, id);
- exit(-1);
-}
-
-void
-crashnum(char *err, int id)
-{
- fprintf(stderr, err, id);
- exit(-1);
-}
-
-/* print */
-
-static int needws;
-
-static void
-putreader(FILE *dest, const char *s)
-{
- if(s[0] == '\\') s++;
- if(!strcmp(s, "Newline"))
- putc('\n', dest);
- else if(!strcmp(s, "Space"))
- putc(' ', dest);
- else if(!strcmp(s, "Tab"))
- putc('\t', dest);
- else
- fprintf(dest, s);
-}
-
-static void
-putexp(Object *obj)
-{
- if(!obj || obj == _nil)
- return;
- if(needws) {
- putc(' ', stdout);
- needws = 0;
- }
- if(isnum(obj)) {
- printf("%ld", obj->num), needws = 1;
- return;
- } else if(issym(obj)) {
- printf("%s", obj->sym), needws = 1;
- return;
- }
- if(!iscons(car(obj)) && !iscons(cdr(obj)) && !isnull(cdr(obj)))
- putexp(car(obj)), putc('.', stdout), needws = 0;
- else if(iscons(car(obj)))
- putc('(', stdout), putexp(car(obj)), putc(')', stdout);
- else
- putexp(car(obj));
- putexp(cdr(obj));
-}
-
-static void
-putline(FILE *dest, Object *obj)
-{
- Object *atom;
- needws = 0;
- while(obj && obj != _nil) {
- if(obj->sym == _nil->sym || !isatom(car(obj)))
- return;
- atom = car(obj);
- if(needws) {
- putc(' ', dest);
- needws = 0;
- }
- if(isnum(atom))
- fprintf(dest, "%ld", atom->num), needws = 1;
- else if(issym(atom)) {
- if(atom->sym[0] == '#')
- putreader(dest, atom->sym + 1);
- else
- fprintf(dest, "%s", atom->sym), needws = 1;
- }
- obj = cdr(obj);
- }
-}
-
-/* dict */
-
-void
-dict_init(void)
-{
- int i;
- /* clear buffer */
- for(i = 0; dict_buf[i] && i < DICTLEN; i++)
- dict_buf[i] = 0;
- dict_end = &dict_buf[0];
-}
-
-const char *
-dict_alloc(const char *src)
-{
- char *ptr;
- int len = strlen(src);
- /* search */
- for(ptr = &dict_buf[0]; ptr < dict_end; ptr++)
- if(!strcmp(ptr, src))
- return ptr;
- /* create */
- if(len + dict_end - dict_buf >= DICTLEN)
- crash("Error: Out of memory", "DICT", "");
- dict_end += len + 1;
- return strcpy(ptr, src);
-}
-
-/* primitives */
-
-Object *
-cons(Object *_car, Object *_cdr)
-{
- Object *obj = gc_alloc();
- gettype(obj) = CONS;
- obj->Cons.car = _car;
- obj->Cons.cdr = _cdr;
- return obj;
-}
-
-const char *
-gettypestr(Object *obj)
-{
- switch(gettype(obj)) {
- case CONS: return "Cons";
- case NUMBER: return "Number";
- case SYMBOL: return "Symbol";
- }
- return "Unknown";
-}
-
-Object *
-car(Object *obj)
-{
- if(!iscons(obj))
- crash("Error: CAR not possible on <%s> %s.\n", obj->sym, gettypestr(obj));
- return obj->Cons.car;
-}
-
-Object *
-cdr(Object *obj)
-{
- if(!iscons(obj))
- crash("Error: CDR not possible on <%s> %s.\n", obj->sym, gettypestr(obj));
- return obj->Cons.cdr;
-}
-
-Object *
-newnum(int value)
-{
- Object *obj = gc_alloc();
- gettype(obj) = NUMBER;
- obj->num = value;
- return obj;
-}
-
-Object *
-newsym(const char *value)
-{
- Object *obj = gc_alloc();
- gettype(obj) = SYMBOL;
- obj->sym = dict_alloc(value);
- return obj;
-}
-
-int
-isequ(Object *a, Object *b)
-{
- int at = gettype(a), bt = gettype(b);
- if(at == bt) {
- if(at == NUMBER) return a->num == b->num;
- if(at == SYMBOL) return a->sym == b->sym;
- }
- return 0;
-}
-
-Object *
-implode(Object *obj)
-{
- char buf[0x80];
- char *ptr = &buf[0];
- while(obj && obj != _nil) {
- *ptr++ = (char)car(obj)->num;
- obj = cdr(obj);
- }
- *ptr = '\0';
- return newsym(buf);
-}
-
-Object *
-explode(Object *obj)
-{
- int l;
- const char *str;
- Object *list = _nil;
- if(issym(obj))
- for(str = obj->sym, l = strlen(str); l--;)
- list = cons(newnum(str[l]), list);
- return list;
-}
-
-void
-device_write(Object *obj)
-{
- Object *head = car(obj);
- needws = 0;
- if(iscons(head)) {
- Object *key = car(head);
- if(issym(key) && key->sym[0] == ':') {
- if(!strcmp(key->sym + 1, "cli")) {
- putline(stdout, cdr(head));
- return;
- }
- }
- }
- putexp(obj), putc('\n', stdout);
-}
D src/lispkit.h => src/lispkit.h +0 -85
@@ 1,85 0,0 @@
-/*
-Copyright (c) 2011 A. Carl Douglas
-Copyright (c) 2023 Devine Lu Linvega
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE.
-*/
-
-#ifndef SECD_H
-#define SECD_H 1
-
-union Object;
-typedef union Object Object;
-
-enum { EMPTY,
- NUMBER,
- SYMBOL,
- CONS };
-
-struct Cons {
- Object *car, *cdr;
-};
-
-union Object {
- long num;
- const char *sym;
- struct Cons Cons;
-};
-
-struct GCHeader {
- int size, type, marked, id;
-};
-
-/* gc */
-void gc_init();
-Object *gc_alloc();
-void gc_collect_garbage();
-void gc_collect();
-void gc_mark();
-void gc_exit();
-void gc_stats();
-
-#define gc_header(o) ((struct GCHeader *)o - 1)
-
-/* secd */
-extern Object *_rS, *_rE, *_rC, *_rD;
-extern Object *_t, *_f, *_nil;
-void secd_init();
-Object *secd_eval(Object *fn, Object *args);
-
-/* core */
-void crash(char *err, const char *value, const char *id);
-void crashnum(char *err, int id);
-
-/* dict */
-void dict_init(void);
-
-/* special opcodes */
-Object *implode(Object *obj);
-Object *explode(Object *obj);
-void device_write(Object *obj);
-
-/* misc */
-Object *cons(Object *, Object *);
-Object *car(Object *);
-Object *cdr(Object *);
-Object *newnum(int);
-Object *newsym(const char *);
-int isequ(Object *a, Object *b);
-int getnum(Object *);
-const char *getstr(int);
-
-#define gettype(o) gc_header(o)->type
-#define isnum(o) (gettype(o) == NUMBER)
-#define issym(o) (gettype(o) == SYMBOL)
-#define iscons(o) (gettype(o) == CONS)
-#define isatom(o) (issym(o) || isnum(o))
-#define istrue(o) (o->sym != _f->sym)
-#define isnull(o) (o == _nil)
-
-#endif
M src/main.c => src/main.c +407 -0
@@ 20,6 20,413 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
+union Object;
+typedef union Object Object;
+
+enum { EMPTY,
+ NUMBER,
+ SYMBOL,
+ CONS };
+
+struct Cons {
+ Object *car, *cdr;
+};
+
+union Object {
+ long num;
+ const char *sym;
+ struct Cons Cons;
+};
+
+struct GCHeader {
+ int size, type, marked, id;
+};
+
+/* gc */
+void gc_init();
+Object *gc_alloc();
+void gc_collect_garbage();
+void gc_collect();
+void gc_mark();
+void gc_exit();
+void gc_stats();
+
+#define gc_header(o) ((struct GCHeader *)o - 1)
+
+/* secd */
+extern Object *_rS, *_rE, *_rC, *_rD;
+extern Object *_t, *_f, *_nil;
+void secd_init();
+Object *secd_eval(Object *fn, Object *args);
+
+/* core */
+void crash(char *err, const char *value, const char *id);
+void crashnum(char *err, int id);
+
+/* dict */
+void dict_init(void);
+
+/* special opcodes */
+Object *implode(Object *obj);
+Object *explode(Object *obj);
+void device_write(Object *obj);
+
+/* misc */
+Object *cons(Object *, Object *);
+Object *car(Object *);
+Object *cdr(Object *);
+Object *newnum(int);
+Object *newsym(const char *);
+int isequ(Object *a, Object *b);
+int getnum(Object *);
+const char *getstr(int);
+
+#define gettype(o) gc_header(o)->type
+#define isnum(o) (gettype(o) == NUMBER)
+#define issym(o) (gettype(o) == SYMBOL)
+#define iscons(o) (gettype(o) == CONS)
+#define isatom(o) (issym(o) || isnum(o))
+#define istrue(o) (o->sym != _f->sym)
+#define isnull(o) (o == _nil)
+
+
+/* - GC -------------------------------------- */
+
+#define NUM_CELLS 65535
+
+unsigned alloc_counter;
+unsigned collect_counter;
+unsigned num_cells;
+
+void *mem;
+Object **cells;
+Object *ff;
+
+void
+gc_mark(Object *object)
+{
+ if(gc_header(object)->marked == 0) {
+ gc_header(object)->marked = 1;
+ if(isatom(object) == 0) {
+ gc_mark(car(object));
+ gc_mark(cdr(object));
+ }
+ }
+}
+
+void
+gc_init()
+{
+ const unsigned cell_size = sizeof(struct GCHeader) + sizeof(Object);
+ unsigned char *ptr;
+ unsigned i;
+
+ num_cells = getenv("LISPKIT_MEMORY") ? atoi(getenv("LISPKIT_MEMORY")) : NUM_CELLS;
+
+ mem = calloc(num_cells, cell_size);
+ cells = calloc(num_cells, sizeof(Object *));
+
+ alloc_counter = 0;
+ collect_counter = 0;
+
+ ff = NULL;
+
+ for(i = 0, ptr = mem; i < num_cells; i++, ptr += cell_size) {
+ cells[i] = (Object *)((struct GCHeader *)ptr + 1);
+ cells[i]->Cons.cdr = ff;
+ ff = cells[i];
+ }
+}
+
+void
+gc_exit()
+{
+ free(mem);
+ free(cells);
+}
+
+Object *
+gc_alloc()
+{
+ Object *object;
+
+ if(ff == NULL)
+ gc_collect_garbage();
+
+ object = ff;
+ ff = ff->Cons.cdr;
+ gc_header(object)->type = 0;
+
+ alloc_counter++;
+
+ return object;
+}
+
+void
+gc_collect()
+{
+ int i;
+ for(i = 0; i < NUM_CELLS; i++) {
+ if(gc_header(cells[i])->marked == 0) {
+ cells[i]->Cons.cdr = ff;
+ ff = cells[i];
+ collect_counter++;
+ }
+ }
+}
+
+void
+gc_collect_garbage()
+{
+ int i;
+ for(i = 0; i < NUM_CELLS; i++)
+ gc_header(cells[i])->marked = 0;
+ gc_mark(_rS);
+ gc_mark(_rE);
+ gc_mark(_rC);
+ gc_mark(_rD);
+ gc_mark(_t);
+ gc_mark(_f);
+ gc_mark(_nil);
+ gc_collect();
+ if(ff == NULL)
+ crash("Error: Out of memory", "GC", "");
+}
+
+void
+gc_stats()
+{
+ fprintf(stderr, "Cells: %u\n", num_cells);
+ fprintf(stderr, "Allocates: %u\n", alloc_counter);
+ fprintf(stderr, "Collects: %u\n", collect_counter);
+}
+
+/* - LISPKIT --------------------------------- */
+
+#define DICTLEN 0x8000
+
+static char dict_buf[DICTLEN], *dict_end;
+
+void
+crash(char *err, const char *value, const char *id)
+{
+ fprintf(stderr, err, value, id);
+ exit(-1);
+}
+
+void
+crashnum(char *err, int id)
+{
+ fprintf(stderr, err, id);
+ exit(-1);
+}
+
+/* print */
+
+static int needws;
+
+static void
+putreader(FILE *dest, const char *s)
+{
+ if(s[0] == '\\') s++;
+ if(!strcmp(s, "Newline"))
+ putc('\n', dest);
+ else if(!strcmp(s, "Space"))
+ putc(' ', dest);
+ else if(!strcmp(s, "Tab"))
+ putc('\t', dest);
+ else
+ fprintf(dest, s);
+}
+
+static void
+putexp(Object *obj)
+{
+ if(!obj || obj == _nil)
+ return;
+ if(needws) {
+ putc(' ', stdout);
+ needws = 0;
+ }
+ if(isnum(obj)) {
+ printf("%ld", obj->num), needws = 1;
+ return;
+ } else if(issym(obj)) {
+ printf("%s", obj->sym), needws = 1;
+ return;
+ }
+ if(!iscons(car(obj)) && !iscons(cdr(obj)) && !isnull(cdr(obj)))
+ putexp(car(obj)), putc('.', stdout), needws = 0;
+ else if(iscons(car(obj)))
+ putc('(', stdout), putexp(car(obj)), putc(')', stdout);
+ else
+ putexp(car(obj));
+ putexp(cdr(obj));
+}
+
+static void
+putline(FILE *dest, Object *obj)
+{
+ Object *atom;
+ needws = 0;
+ while(obj && obj != _nil) {
+ if(obj->sym == _nil->sym || !isatom(car(obj)))
+ return;
+ atom = car(obj);
+ if(needws) {
+ putc(' ', dest);
+ needws = 0;
+ }
+ if(isnum(atom))
+ fprintf(dest, "%ld", atom->num), needws = 1;
+ else if(issym(atom)) {
+ if(atom->sym[0] == '#')
+ putreader(dest, atom->sym + 1);
+ else
+ fprintf(dest, "%s", atom->sym), needws = 1;
+ }
+ obj = cdr(obj);
+ }
+}
+
+/* dict */
+
+void
+dict_init(void)
+{
+ int i;
+ /* clear buffer */
+ for(i = 0; dict_buf[i] && i < DICTLEN; i++)
+ dict_buf[i] = 0;
+ dict_end = &dict_buf[0];
+}
+
+const char *
+dict_alloc(const char *src)
+{
+ char *ptr;
+ int len = strlen(src);
+ /* search */
+ for(ptr = &dict_buf[0]; ptr < dict_end; ptr++)
+ if(!strcmp(ptr, src))
+ return ptr;
+ /* create */
+ if(len + dict_end - dict_buf >= DICTLEN)
+ crash("Error: Out of memory", "DICT", "");
+ dict_end += len + 1;
+ return strcpy(ptr, src);
+}
+
+/* primitives */
+
+Object *
+cons(Object *_car, Object *_cdr)
+{
+ Object *obj = gc_alloc();
+ gettype(obj) = CONS;
+ obj->Cons.car = _car;
+ obj->Cons.cdr = _cdr;
+ return obj;
+}
+
+const char *
+gettypestr(Object *obj)
+{
+ switch(gettype(obj)) {
+ case CONS: return "Cons";
+ case NUMBER: return "Number";
+ case SYMBOL: return "Symbol";
+ }
+ return "Unknown";
+}
+
+Object *
+car(Object *obj)
+{
+ if(!iscons(obj))
+ crash("Error: CAR not possible on <%s> %s.\n", obj->sym, gettypestr(obj));
+ return obj->Cons.car;
+}
+
+Object *
+cdr(Object *obj)
+{
+ if(!iscons(obj))
+ crash("Error: CDR not possible on <%s> %s.\n", obj->sym, gettypestr(obj));
+ return obj->Cons.cdr;
+}
+
+Object *
+newnum(int value)
+{
+ Object *obj = gc_alloc();
+ gettype(obj) = NUMBER;
+ obj->num = value;
+ return obj;
+}
+
+Object *
+newsym(const char *value)
+{
+ Object *obj = gc_alloc();
+ gettype(obj) = SYMBOL;
+ obj->sym = dict_alloc(value);
+ return obj;
+}
+
+int
+isequ(Object *a, Object *b)
+{
+ int at = gettype(a), bt = gettype(b);
+ if(at == bt) {
+ if(at == NUMBER) return a->num == b->num;
+ if(at == SYMBOL) return a->sym == b->sym;
+ }
+ return 0;
+}
+
+Object *
+implode(Object *obj)
+{
+ char buf[0x80];
+ char *ptr = &buf[0];
+ while(obj && obj != _nil) {
+ *ptr++ = (char)car(obj)->num;
+ obj = cdr(obj);
+ }
+ *ptr = '\0';
+ return newsym(buf);
+}
+
+Object *
+explode(Object *obj)
+{
+ int l;
+ const char *str;
+ Object *list = _nil;
+ if(issym(obj))
+ for(str = obj->sym, l = strlen(str); l--;)
+ list = cons(newnum(str[l]), list);
+ return list;
+}
+
+void
+device_write(Object *obj)
+{
+ Object *head = car(obj);
+ needws = 0;
+ if(iscons(head)) {
+ Object *key = car(head);
+ if(issym(key) && key->sym[0] == ':') {
+ if(!strcmp(key->sym + 1, "cli")) {
+ putline(stdout, cdr(head));
+ return;
+ }
+ }
+ }
+ putexp(obj), putc('\n', stdout);
+}
+
/* - SECD ------------------------------------ */
#define A car(_rS)
D src/secd.c => src/secd.c +0 -168
@@ 1,168 0,0 @@
-#include "lispkit.h"
-
-/*
-Copyright (c) 2011 A. Carl Douglas
-Copyright (c) 2023 Devine Lu Linvega
-
-Permission to use, copy, modify, and distribute this software for any
-purpose with or without fee is hereby granted, provided that the above
-copyright notice and this permission notice appear in all copies.
-
-THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
-WITH REGARD TO THIS SOFTWARE.
-*/
-
-#define A car(_rS)
-#define B car(cdr(_rS))
-
-Object *_rS, *_rE, *_rC, *_rD;
-Object *_t, *_f, *_nil;
-
-void
-secd_init(void)
-{
- _t = newsym("T");
- _f = newsym("F");
- _nil = newsym("NIL");
- _rS = _rC = _rE = _rD = _nil;
-}
-
-Object *
-secd_eval(Object *fn, Object *args)
-{
- Object *_work, *_a, *_b;
- int live = 1, i;
- _rS = cons(args, _nil);
- _rC = fn;
- while(live) {
- switch(car(_rC)->num) {
- case 0: /* NIL */
- break;
- case 1: /* LD */
- i = 0;
- _work = _rE;
- for(i = 1; i <= car(car(cdr(_rC)))->num; ++i)
- _work = cdr(_work);
- _work = car(_work);
- for(i = 1; i <= cdr(car(cdr(_rC)))->num; ++i)
- _work = cdr(_work);
- _work = car(_work);
- _rS = cons(_work, _rS);
- _rC = cdr(cdr(_rC));
- break;
- case 2: /* LDC */
- _rS = cons(car(cdr(_rC)), _rS);
- _rC = cdr(cdr(_rC));
- break;
- case 3: /* LDF */
- _rS = cons(cons(car(cdr(_rC)), _rE), _rS);
- _rC = cdr(cdr(_rC));
- break;
- case 4: /* AP */
- _rD = cons(cdr(_rC), _rD);
- _rD = cons(_rE, _rD);
- _rD = cons(cdr(cdr(_rS)), _rD);
- _rE = cons(B, cdr(car(_rS)));
- _rC = car(car(_rS));
- _rS = _nil;
- break;
- case 5: /* RTN */
- _rS = cons(car(_rS), car(_rD));
- _rE = car(cdr(_rD));
- _rC = car(cdr(cdr(_rD)));
- _rD = cdr(cdr(cdr(_rD)));
- break;
- case 6: /* DUM */
- _rE = cons(_nil, _rE);
- _rC = cdr(_rC);
- break;
- case 7: /* RAP */
- _rD = cons(cdr(_rC), _rD);
- _rD = cons(cdr(_rE), _rD);
- _rD = cons(cdr(cdr(_rS)), _rD);
- _rE = cdr(car(_rS));
- _rE->Cons.car = B;
- _rC = car(car(_rS));
- _rS = _nil;
- break;
- case 8: /* SEL */
- _rD = cons(cdr(cdr(cdr(_rC))), _rD);
- _rC = car(cdr(istrue(car(_rS)) ? _rC : cdr(_rC)));
- _rS = cdr(_rS);
- break;
- case 9: /* JOIN */
- _rC = car(_rD);
- _rD = cdr(_rD);
- break;
- case 10: /* CAR */
- _rS = cons(car(car(_rS)), cdr(_rS));
- _rC = cdr(_rC);
- break;
- case 11: /* CDR */
- _rS = cons(cdr(car(_rS)), cdr(_rS));
- _rC = cdr(_rC);
- break;
- case 12: /* ATOM */
- _rS = cons(isatom(A) ? _t : _f, cdr(_rS));
- _rC = cdr(_rC);
- break;
- case 13: /* CONS */
- _rS = cons(cons(A, B), cdr(cdr(_rS)));
- _rC = cdr(_rC);
- break;
- case 14: /* EQ */
- _rS = cons(isequ(A, B) ? _t : _f, cdr(cdr(_rS)));
- _rC = cdr(_rC);
- break;
- case 15: /* ADD */
- _a = A, _b = B;
- _rS = cons(isnum(_a) && isnum(_b) ? newnum(_b->num + _a->num) : _nil, cdr(cdr(_rS)));
- _rC = cdr(_rC);
- break;
- case 16: /* SUB */
- _a = A, _b = B;
- _rS = cons(isnum(_a) && isnum(_b) ? newnum(_b->num - _a->num) : _nil, cdr(cdr(_rS)));
- _rC = cdr(_rC);
- break;
- case 17: /* MUL */
- _a = A, _b = B;
- _rS = cons(isnum(_a) && isnum(_b) ? newnum(_b->num * _a->num) : _nil, cdr(cdr(_rS)));
- _rC = cdr(_rC);
- break;
- case 18: /* DIV */
- _a = A, _b = B;
- _rS = cons(isnum(_a) && isnum(_b) ? newnum(_b->num / _a->num) : _nil, cdr(cdr(_rS)));
- _rC = cdr(_rC);
- break;
- case 19: /* REM */
- _a = A, _b = B;
- _rS = cons(isnum(_a) && isnum(_b) ? newnum(_b->num % _a->num) : _nil, cdr(cdr(_rS)));
- _rC = cdr(_rC);
- break;
- case 20: /* LEQ */
- _a = A, _b = B;
- _rS = cons(isnum(_a) && isnum(_b) ? (_b->num <= _a->num ? _t : _f) : _nil, cdr(cdr(_rS)));
- _rC = cdr(_rC);
- break;
- case 21: /* BRK */
- live = 0;
- break;
- case 26: /* WRITE */
- device_write(_rS);
- _rC = cdr(_rC);
- break;
- case 27: /* IMP */
- _rS = cons(implode(A), cdr(_rS));
- _rC = cdr(_rC);
- break;
- case 28: /* EXP */
- _rS = cons(explode(A), cdr(_rS));
- _rC = cdr(_rC);
- break;
- default: /* ERR */
- crashnum("Error: Unknown opcode <%d>\n", car(_rC)->num);
- return _rS;
- }
- }
- return _rS;
-}