From 24c849057b4d0ade443929bece5c69442f474fd2 Mon Sep 17 00:00:00 2001 From: David Johnson-Davies Date: Sat, 10 Feb 2018 17:15:42 +0000 Subject: [PATCH] Version 2.0 10th February 2018 Includes an SD card interface to allow you to read from and write to SD cards. --- ulisp.ino | 819 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 461 insertions(+), 358 deletions(-) diff --git a/ulisp.ino b/ulisp.ino index 3ec46b9..9ada1f7 100644 --- a/ulisp.ino +++ b/ulisp.ino @@ -1,15 +1,9 @@ -/* uLisp SAM/SAMD Version 1.9a - www.ulisp.com - David Johnson-Davies - www.technoblogy.com - 9th August 2017 +/* uLisp SAM/SAMD Version 2.0 - www.ulisp.com + David Johnson-Davies - www.technoblogy.com - 10th February 2018 Licensed under the MIT license: https://opensource.org/licenses/MIT */ -#include -#include -#include -#include -#include - // Compile options #define checkoverflow @@ -17,6 +11,18 @@ #define printfreespace #define serialmonitor // #define printgcs +#define sdcardsupport + +// Includes + +#include +#include +#include +#include + +#if defined(sdcardsupport) +#include +#endif // C Macros @@ -52,20 +58,20 @@ const int TRACEMAX = 3; // Number of traced functions enum type { ZERO=0, SYMBOL=2, NUMBER=4, STREAM=6, CHARACTER=8, STRING=10, PAIR=12 }; // STRING and PAIR must be last enum token { UNUSED, BRA, KET, QUO, DOT }; -enum stream { SERIALSTREAM, I2CSTREAM, SPISTREAM }; +enum stream { SERIALSTREAM, I2CSTREAM, SPISTREAM, SDSTREAM }; enum function { SYMBOLS, NIL, TEE, NOTHING, AMPREST, LAMBDA, LET, LETSTAR, CLOSURE, SPECIAL_FORMS, QUOTE, DEFUN, DEFVAR, SETQ, LOOP, PUSH, POP, INCF, DECF, SETF, DOLIST, DOTIMES, TRACE, UNTRACE, FORMILLIS, -WITHSERIAL, WITHI2C, WITHSPI, TAIL_FORMS, PROGN, RETURN, IF, COND, WHEN, UNLESS, AND, OR, FUNCTIONS, NOT, -NULLFN, CONS, ATOM, LISTP, CONSP, NUMBERP, SYMBOLP, STREAMP, EQ, CAR, FIRST, CDR, REST, CAAR, CADR, -SECOND, CDAR, CDDR, CAAAR, CAADR, CADAR, CADDR, THIRD, CDAAR, CDADR, CDDAR, CDDDR, LENGTH, LIST, REVERSE, -NTH, ASSOC, MEMBER, APPLY, FUNCALL, APPEND, MAPC, MAPCAR, ADD, SUBTRACT, MULTIPLY, DIVIDE, MOD, ONEPLUS, -ONEMINUS, ABS, RANDOM, MAX, MIN, NUMEQ, LESS, LESSEQ, GREATER, GREATEREQ, NOTEQ, PLUSP, MINUSP, ZEROP, -ODDP, EVENP, CHAR, CHARCODE, CODECHAR, CHARACTERP, STRINGP, STRINGEQ, STRINGLESS, STRINGGREATER, SORT, -STRINGFN, CONCATENATE, SUBSEQ, READFROMSTRING, PRINCTOSTRING, PRIN1TOSTRING, LOGAND, LOGIOR, LOGXOR, -LOGNOT, ASH, LOGBITP, EVAL, GLOBALS, LOCALS, MAKUNBOUND, BREAK, READ, PRIN1, PRINT, PRINC, TERPRI, -READBYTE, READLINE, WRITEBYTE, WRITESTRING, WRITELINE, RESTARTI2C, GC, ROOM, SAVEIMAGE, LOADIMAGE, CLS, -PINMODE, DIGITALREAD, DIGITALWRITE, ANALOGREAD, ANALOGWRITE, DELAY, MILLIS, NOTE, EDIT, PPRINT, ENDFUNCTIONS }; +WITHSERIAL, WITHI2C, WITHSPI, WITHSDCARD, TAIL_FORMS, PROGN, RETURN, IF, COND, WHEN, UNLESS, AND, OR, +FUNCTIONS, NOT, NULLFN, CONS, ATOM, LISTP, CONSP, NUMBERP, SYMBOLP, STREAMP, EQ, CAR, FIRST, CDR, REST, +CAAR, CADR, SECOND, CDAR, CDDR, CAAAR, CAADR, CADAR, CADDR, THIRD, CDAAR, CDADR, CDDAR, CDDDR, LENGTH, +LIST, REVERSE, NTH, ASSOC, MEMBER, APPLY, FUNCALL, APPEND, MAPC, MAPCAR, ADD, SUBTRACT, MULTIPLY, DIVIDE, +MOD, ONEPLUS, ONEMINUS, ABS, RANDOM, MAX, MIN, NUMEQ, LESS, LESSEQ, GREATER, GREATEREQ, NOTEQ, PLUSP, +MINUSP, ZEROP, ODDP, EVENP, CHAR, CHARCODE, CODECHAR, CHARACTERP, STRINGP, STRINGEQ, STRINGLESS, +STRINGGREATER, SORT, STRINGFN, CONCATENATE, SUBSEQ, READFROMSTRING, PRINCTOSTRING, PRIN1TOSTRING, LOGAND, +LOGIOR, LOGXOR, LOGNOT, ASH, LOGBITP, EVAL, GLOBALS, LOCALS, MAKUNBOUND, BREAK, READ, PRIN1, PRINT, PRINC, +TERPRI, READBYTE, READLINE, WRITEBYTE, WRITESTRING, WRITELINE, RESTARTI2C, GC, ROOM, SAVEIMAGE, LOADIMAGE, +CLS, PINMODE, DIGITALREAD, DIGITALWRITE, ANALOGREAD, ANALOGWRITE, DELAY, MILLIS, NOTE, EDIT, PPRINT, ENDFUNCTIONS }; // Typedefs @@ -92,11 +98,11 @@ typedef object *(*fn_ptr_type)(object *, object *); typedef struct { const char *string; fn_ptr_type fptr; - int min; - int max; + uint8_t min; + uint8_t max; } tbl_entry_t; -typedef char (*gfun_t)(); +typedef int (*gfun_t)(); typedef void (*pfun_t)(char); // Workspace @@ -328,6 +334,20 @@ int compactimage (object **arg) { return firstfree - Workspace; } +// Make SD card filename + +char *MakeFilename (object *arg) { + char *buffer = SymbolTop; + int i = 0; + do { + char c = nthchar(arg, i); + if (c == '\0') break; + buffer[i++] = c; + } while (i<12); // Truncate to 12 chars + buffer[i] = '\0'; + return buffer; +} + // Save-image and load-image void SDWriteInt(File file, int data) { @@ -339,27 +359,15 @@ void SDWritePtr(File file, uintptr_t data) { file.write(data>>16 & 0xFF); file.write(data>>24 & 0xFF); } -char *MakeFilename (object *arg) { - char *buffer = SymbolTop; - if (stringp(arg)) { - int i = 0; - do { - char c = nthchar(arg, i); - if (c == '\0') break; - buffer[i++] = c; - } while (i<8); - strcpy(&buffer[i], ".IMG"); - } else strcpy(buffer, "ULISP.IMG"); - return buffer; -} - int saveimage (object *arg) { SD.begin(SDCARD_SS_PIN); - File file = SD.open(MakeFilename(arg), FILE_WRITE); + File file; + if (stringp(arg)) { + file = SD.open(MakeFilename(arg), O_RDWR | O_CREAT | O_TRUNC); + arg = NULL; + } else file = SD.open("ULISP.IMG", O_RDWR | O_CREAT | O_TRUNC); if (!file) error(PSTR("Problem saving to SD card")); - if (stringp(arg)) arg = NULL; unsigned int imagesize = compactimage(&arg); - file.seek(0); // Overwrite previous saved image SDWritePtr(file, (uintptr_t)arg); SDWriteInt(file, imagesize); SDWritePtr(file, (uintptr_t)GlobalEnv); @@ -368,7 +376,7 @@ int saveimage (object *arg) { SDWritePtr(file, (uintptr_t)SymbolTop); for (int i=0; itype = STRING; - char ch = gfun(); + int ch = gfun(); + if (ch == EOF) return nil; object *head = NULL; int chars = 0; - while (ch != delim) { + while ((ch != delim) && (ch != EOF)) { if (ch == '\\') ch = gfun(); buildstring(ch, &chars, &head); ch = gfun(); @@ -708,7 +718,7 @@ void dropframe (int tc, object **env) { object *closure (object *fname, object *state, object *function, object *args, object **env) { int trace = tracing(fname->name); if (trace) { - indent(TraceDepth[trace-1]<<1); + indent(TraceDepth[trace-1]<<1, pserial); pint(TraceDepth[trace-1]++, pserial); pserial(':'); pserial(' '); pserial('('); printobject(fname, pserial); } @@ -846,8 +856,49 @@ void I2Cstop(uint8_t read) { if (read == 0) Wire.endTransmission(); // Check for error? } -inline char spiread () { return SPI.transfer(0); } -inline char serial1read () { while (!Serial1.available()) testescape(); return Serial1.read(); } +// Streams + +inline int spiread () { return SPI.transfer(0); } +#if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKRZERO) +inline int serial1read () { while (!Serial1.available()) testescape(); return Serial1.read(); } +#elif defined(ARDUINO_SAM_DUE) +inline int serial1read () { while (!Serial1.available()) testescape(); return Serial1.read(); } +inline int serial2read () { while (!Serial2.available()) testescape(); return Serial2.read(); } +inline int serial3read () { while (!Serial3.available()) testescape(); return Serial3.read(); } +#endif +#if defined(sdcardsupport) +File SDpfile, SDgfile; +inline int SDread () { + if (LastChar) { + char temp = LastChar; + LastChar = 0; + return temp; + } + return SDgfile.read(); +} +#endif + +void serialbegin (int address, int baud) { + #if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKRZERO) + if (address == 1) Serial1.begin((long)baud*100); + else error(PSTR("'with-serial' port not supported")); + #elif defined(ARDUINO_SAM_DUE) + if (address == 1) Serial1.begin((long)baud*100); + else if (address == 2) Serial2.begin((long)baud*100); + else if (address == 3) Serial3.begin((long)baud*100); + else error(PSTR("'with-serial' port not supported")); + #endif +} + +void serialend (int address) { + #if defined(ARDUINO_SAMD_ZERO) || defined(ARDUINO_SAMD_MKRZERO) + if (address == 1) Serial1.end(); + #elif defined(ARDUINO_SAM_DUE) + if (address == 1) Serial1.end(); + else if (address == 2) Serial2.end(); + else if (address == 3) Serial3.end(); + #endif +} gfun_t gstreamfun (object *args) { int streamtype = SERIALSTREAM; @@ -862,12 +913,19 @@ gfun_t gstreamfun (object *args) { else if (streamtype == SERIALSTREAM) { if (address == 0) gfun = gserial; else if (address == 1) gfun = serial1read; - } else error(PSTR("Unknown stream type")); + } + #if defined(sdcardsupport) + else if (streamtype == SDSTREAM) gfun = (gfun_t)SDread; + #endif + else error(PSTR("Unknown stream type")); return gfun; } inline void spiwrite (char c) { SPI.transfer(c); } inline void serial1write (char c) { Serial1.write(c); } +#if defined(sdcardsupport) +inline void SDwrite (char c) { SDpfile.write(c); } +#endif pfun_t pstreamfun (object *args) { int streamtype = SERIALSTREAM; @@ -882,7 +940,11 @@ pfun_t pstreamfun (object *args) { else if (streamtype == SERIALSTREAM) { if (address == 0) pfun = pserial; else if (address == 1) pfun = serial1write; - } else error(PSTR("'write-string' unknown stream type")); + } + #if defined(sdcardsupport) + else if (streamtype == SDSTREAM) pfun = (pfun_t)SDwrite; + #endif + else error(PSTR("unknown stream type")); return pfun; } @@ -1120,7 +1182,10 @@ object *sp_formillis (object *args, object *env) { unsigned long now, total = 0; if (param != NULL) total = integer(first(param)); eval(tf_progn(cdr(args),env), env); - do now = millis() - start; while (now < total); + do { + now = millis() - start; + testescape(); + } while (now < total); if (now <= INT_MAX) return number(now); return nil; } @@ -1130,28 +1195,14 @@ object *sp_withserial (object *args, object *env) { object *var = first(params); int address = integer(eval(second(params), env)); params = cddr(params); - #if defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega2560__) int baud = 96; if (params != NULL) baud = integer(eval(first(params), env)); - #endif object *pair = cons(var, stream(SERIALSTREAM, address)); push(pair,env); - #if defined(__AVR_ATmega1284P__) - if (address == 1) Serial1.begin(baud*100); - #elif defined(__AVR_ATmega2560__) - if (address == 1) Serial1.begin(baud*100); - else if (address == 2) Serial2.begin(baud*100); - else if (address == 3) Serial3.begin(baud*100); - #endif + serialbegin(address, baud); object *forms = cdr(args); object *result = eval(tf_progn(forms,env), env); - #if defined(__AVR_ATmega1284P__) - if (address == 1) Serial1.end(); - #elif defined(__AVR_ATmega2560__) - if (address == 1) Serial1.end(); - else if (address == 2) Serial2.end(); - else if (address == 3) Serial3.end(); - #endif + serialend(address); return result; } @@ -1210,6 +1261,37 @@ object *sp_withspi (object *args, object *env) { return result; } +object *sp_withsdcard (object *args, object *env) { +#if defined(sdcardsupport) + object *params = first(args); + object *var = first(params); + object *filename = eval(second(params), env); + params = cddr(params); + SD.begin(SDCARD_SS_PIN); + int mode = 0; + if (params != NULL && first(params) != NULL) mode = integer(first(params)); + int oflag = O_READ; + if (mode == 1) oflag = O_RDWR | O_CREAT; else if (mode == 2) oflag = O_RDWR | O_CREAT | O_TRUNC; + if (mode >= 1) { + SDpfile = SD.open(MakeFilename(filename), oflag); + if (!SDpfile) error(PSTR("Problem writing to SD card")); + } else { + SDgfile = SD.open(MakeFilename(filename), oflag); + if (!SDgfile) error(PSTR("Problem reading from SD card")); + } + object *pair = cons(var, stream(SDSTREAM, 1)); + push(pair,env); + object *forms = cdr(args); + object *result = eval(tf_progn(forms,env), env); + if (mode >= 1) SDpfile.close(); else SDgfile.close(); + return result; +#else + (void) args, (void) env; + error(PSTR("with-sd-card not supported")); + return nil; +#endif +} + // Tail-recursive forms object *tf_progn (object *args, object *env) { @@ -1987,7 +2069,7 @@ object *fn_subseq (object *args, object *env) { return result; } -char gstr () { +int gstr () { if (LastChar) { char temp = LastChar; LastChar = 0; @@ -2126,66 +2208,75 @@ object *fn_break (object *args, object *env) { } object *fn_read (object *args, object *env) { - (void) args; (void) env; - return read(gserial); + gfun_t gfun = gstreamfun(args); + return read(gfun); } object *fn_prin1 (object *args, object *env) { (void) env; object *obj = first(args); - printobject(obj, pserial); + pfun_t pfun = pstreamfun(cdr(args)); + printobject(obj, pfun); return obj; } object *fn_print (object *args, object *env) { (void) env; - pln(pserial); object *obj = first(args); - printobject(obj, pserial); - pserial(' '); + pfun_t pfun = pstreamfun(cdr(args)); + pln(pfun); + printobject(obj, pfun); + (pfun)(' '); return obj; } object *fn_princ (object *args, object *env) { (void) env; object *obj = first(args); + pfun_t pfun = pstreamfun(cdr(args)); char temp = PrintReadably; PrintReadably = 0; - printobject(obj, pserial); + printobject(obj, pfun); PrintReadably = temp; return obj; } object *fn_terpri (object *args, object *env) { - (void) args, (void) env; - pln(pserial); + (void) env; + pfun_t pfun = pstreamfun(args); + pln(pfun); return nil; } object *fn_readbyte (object *args, object *env) { (void) env; - return number((gstreamfun(args))()); + gfun_t gfun = gstreamfun(args); + int c = gfun(); + return (c == EOF) ? nil : number(c); } object *fn_readline (object *args, object *env) { (void) env; - return readstring('\n', gstreamfun(args)); + gfun_t gfun = gstreamfun(args); + return readstring('\n', gfun); } object *fn_writebyte (object *args, object *env) { (void) env; int value = integer(first(args)); - (pstreamfun(cdr(args)))(value); + pfun_t pfun = pstreamfun(cdr(args)); + (pfun)(value); return nil; } object *fn_writestring (object *args, object *env) { (void) env; object *obj = first(args); + pfun_t pfun = pstreamfun(cdr(args)); char temp = PrintReadably; PrintReadably = 0; - printstring(obj, pstreamfun(cdr(args))); + printstring(obj, pfun); PrintReadably = temp; return nil; } @@ -2193,10 +2284,11 @@ object *fn_writestring (object *args, object *env) { object *fn_writeline (object *args, object *env) { (void) env; object *obj = first(args); + pfun_t pfun = pstreamfun(cdr(args)); char temp = PrintReadably; PrintReadably = 0; - printstring(obj, pstreamfun(cdr(args))); - (pstreamfun(cdr(args)))('\n'); + printstring(obj, pfun); + (pfun)('\n'); PrintReadably = temp; return nil; } @@ -2336,7 +2428,7 @@ object *edit (object *fun) { if (c == 'q') setflag(EXITEDITOR); else if (c == 'b') return fun; else if (c == 'r') fun = read(gserial); - else if (c == '\n') { pfl(pserial); superprint(fun, 0); pln(pserial); } + else if (c == '\n') { pfl(pserial); superprint(fun, 0, pserial); pln(pserial); } else if (c == 'c') fun = cons(read(gserial), fun); else if (atom(fun)) pserial('!'); else if (c == 'd') fun = cons(car(fun), edit(cdr(fun))); @@ -2387,17 +2479,17 @@ int subwidthlist (object *form, int w) { return w; } -void superprint (object *form, int lm) { - if (atom(form)) printobject(form, pserial); - else if (quoted(form)) { pserial('\''); superprint(car(cdr(form)), lm + 1); } - else if (subwidth(form, PPWIDTH - lm) >= 0) supersub(form, lm + PPINDENT, 0); - else supersub(form, lm + PPINDENT, 1); +void superprint (object *form, int lm, pfun_t pfun) { + if (atom(form)) printobject(form, pfun); + else if (quoted(form)) { pfun('\''); superprint(car(cdr(form)), lm + 1, pfun); } + else if (subwidth(form, PPWIDTH - lm) >= 0) supersub(form, lm + PPINDENT, 0, pfun); + else supersub(form, lm + PPINDENT, 1, pfun); } -const int ppspecials = 8; -const char ppspecial[ppspecials] PROGMEM = { IF, SETQ, TEE, LET, LETSTAR, LAMBDA, WHEN, UNLESS }; +const int ppspecials = 12; +const char ppspecial[ppspecials] PROGMEM = { IF, SETQ, TEE, LET, LETSTAR, LAMBDA, WHEN, UNLESS, WITHI2C, WITHSERIAL, WITHSPI, WITHSDCARD }; -void supersub (object *form, int lm, int super) { +void supersub (object *form, int lm, int super, pfun_t pfun) { int special = 0, separate = 1; object *arg = car(form); if (symbolp(arg)) { @@ -2408,21 +2500,23 @@ void supersub (object *form, int lm, int super) { } } while (form != NULL) { - if (atom(form)) { pfstring(PSTR(" . "), pserial); printobject(form, pserial); pserial(')'); return; } - else if (separate) { pserial('('); separate = 0; } - else if (special) { pserial(' '); special--; } - else if (!super) pserial(' '); - else { pln(pserial); indent(lm); } - superprint(car(form), lm); + if (atom(form)) { pfstring(PSTR(" . "), pfun); printobject(form, pfun); pfun(')'); return; } + else if (separate) { pfun('('); separate = 0; } + else if (special) { pfun(' '); special--; } + else if (!super) pfun(' '); + else { pln(pfun); indent(lm, pfun); } + superprint(car(form), lm, pfun); form = cdr(form); } - pserial(')'); return; + pfun(')'); return; } object *fn_pprint (object *args, object *env) { (void) env; - pln(pserial); - superprint(first(args), 0); + object *obj = first(args); + pfun_t pfun = pstreamfun(cdr(args)); + pln(pfun); + superprint(obj, 0, pfun); return symbol(NOTHING); } @@ -2458,129 +2552,130 @@ const char string24[] PROGMEM = "for-millis"; const char string25[] PROGMEM = "with-serial"; const char string26[] PROGMEM = "with-i2c"; const char string27[] PROGMEM = "with-spi"; -const char string28[] PROGMEM = "tail_forms"; -const char string29[] PROGMEM = "progn"; -const char string30[] PROGMEM = "return"; -const char string31[] PROGMEM = "if"; -const char string32[] PROGMEM = "cond"; -const char string33[] PROGMEM = "when"; -const char string34[] PROGMEM = "unless"; -const char string35[] PROGMEM = "and"; -const char string36[] PROGMEM = "or"; -const char string37[] PROGMEM = "functions"; -const char string38[] PROGMEM = "not"; -const char string39[] PROGMEM = "null"; -const char string40[] PROGMEM = "cons"; -const char string41[] PROGMEM = "atom"; -const char string42[] PROGMEM = "listp"; -const char string43[] PROGMEM = "consp"; -const char string44[] PROGMEM = "numberp"; -const char string45[] PROGMEM = "symbolp"; -const char string46[] PROGMEM = "streamp"; -const char string47[] PROGMEM = "eq"; -const char string48[] PROGMEM = "car"; -const char string49[] PROGMEM = "first"; -const char string50[] PROGMEM = "cdr"; -const char string51[] PROGMEM = "rest"; -const char string52[] PROGMEM = "caar"; -const char string53[] PROGMEM = "cadr"; -const char string54[] PROGMEM = "second"; -const char string55[] PROGMEM = "cdar"; -const char string56[] PROGMEM = "cddr"; -const char string57[] PROGMEM = "caaar"; -const char string58[] PROGMEM = "caadr"; -const char string59[] PROGMEM = "cadar"; -const char string60[] PROGMEM = "caddr"; -const char string61[] PROGMEM = "third"; -const char string62[] PROGMEM = "cdaar"; -const char string63[] PROGMEM = "cdadr"; -const char string64[] PROGMEM = "cddar"; -const char string65[] PROGMEM = "cdddr"; -const char string66[] PROGMEM = "length"; -const char string67[] PROGMEM = "list"; -const char string68[] PROGMEM = "reverse"; -const char string69[] PROGMEM = "nth"; -const char string70[] PROGMEM = "assoc"; -const char string71[] PROGMEM = "member"; -const char string72[] PROGMEM = "apply"; -const char string73[] PROGMEM = "funcall"; -const char string74[] PROGMEM = "append"; -const char string75[] PROGMEM = "mapc"; -const char string76[] PROGMEM = "mapcar"; -const char string77[] PROGMEM = "+"; -const char string78[] PROGMEM = "-"; -const char string79[] PROGMEM = "*"; -const char string80[] PROGMEM = "/"; -const char string81[] PROGMEM = "mod"; -const char string82[] PROGMEM = "1+"; -const char string83[] PROGMEM = "1-"; -const char string84[] PROGMEM = "abs"; -const char string85[] PROGMEM = "random"; -const char string86[] PROGMEM = "max"; -const char string87[] PROGMEM = "min"; -const char string88[] PROGMEM = "="; -const char string89[] PROGMEM = "<"; -const char string90[] PROGMEM = "<="; -const char string91[] PROGMEM = ">"; -const char string92[] PROGMEM = ">="; -const char string93[] PROGMEM = "/="; -const char string94[] PROGMEM = "plusp"; -const char string95[] PROGMEM = "minusp"; -const char string96[] PROGMEM = "zerop"; -const char string97[] PROGMEM = "oddp"; -const char string98[] PROGMEM = "evenp"; -const char string99[] PROGMEM = "char"; -const char string100[] PROGMEM = "char-code"; -const char string101[] PROGMEM = "code-char"; -const char string102[] PROGMEM = "characterp"; -const char string103[] PROGMEM = "stringp"; -const char string104[] PROGMEM = "string="; -const char string105[] PROGMEM = "string<"; -const char string106[] PROGMEM = "string>"; -const char string107[] PROGMEM = "sort"; -const char string108[] PROGMEM = "string"; -const char string109[] PROGMEM = "concatenate"; -const char string110[] PROGMEM = "subseq"; -const char string111[] PROGMEM = "read-from-string"; -const char string112[] PROGMEM = "princ-to-string"; -const char string113[] PROGMEM = "prin1-to-string"; -const char string114[] PROGMEM = "logand"; -const char string115[] PROGMEM = "logior"; -const char string116[] PROGMEM = "logxor"; -const char string117[] PROGMEM = "lognot"; -const char string118[] PROGMEM = "ash"; -const char string119[] PROGMEM = "logbitp"; -const char string120[] PROGMEM = "eval"; -const char string121[] PROGMEM = "globals"; -const char string122[] PROGMEM = "locals"; -const char string123[] PROGMEM = "makunbound"; -const char string124[] PROGMEM = "break"; -const char string125[] PROGMEM = "read"; -const char string126[] PROGMEM = "prin1"; -const char string127[] PROGMEM = "print"; -const char string128[] PROGMEM = "princ"; -const char string129[] PROGMEM = "terpri"; -const char string130[] PROGMEM = "read-byte"; -const char string131[] PROGMEM = "read-line"; -const char string132[] PROGMEM = "write-byte"; -const char string133[] PROGMEM = "write-string"; -const char string134[] PROGMEM = "write-line"; -const char string135[] PROGMEM = "restart-i2c"; -const char string136[] PROGMEM = "gc"; -const char string137[] PROGMEM = "room"; -const char string138[] PROGMEM = "save-image"; -const char string139[] PROGMEM = "load-image"; -const char string140[] PROGMEM = "cls"; -const char string141[] PROGMEM = "pinmode"; -const char string142[] PROGMEM = "digitalread"; -const char string143[] PROGMEM = "digitalwrite"; -const char string144[] PROGMEM = "analogread"; -const char string145[] PROGMEM = "analogwrite"; -const char string146[] PROGMEM = "delay"; -const char string147[] PROGMEM = "millis"; -const char string148[] PROGMEM = "note"; -const char string149[] PROGMEM = "edit"; -const char string150[] PROGMEM = "pprint"; +const char string28[] PROGMEM = "with-sd-card"; +const char string29[] PROGMEM = "tail_forms"; +const char string30[] PROGMEM = "progn"; +const char string31[] PROGMEM = "return"; +const char string32[] PROGMEM = "if"; +const char string33[] PROGMEM = "cond"; +const char string34[] PROGMEM = "when"; +const char string35[] PROGMEM = "unless"; +const char string36[] PROGMEM = "and"; +const char string37[] PROGMEM = "or"; +const char string38[] PROGMEM = "functions"; +const char string39[] PROGMEM = "not"; +const char string40[] PROGMEM = "null"; +const char string41[] PROGMEM = "cons"; +const char string42[] PROGMEM = "atom"; +const char string43[] PROGMEM = "listp"; +const char string44[] PROGMEM = "consp"; +const char string45[] PROGMEM = "numberp"; +const char string46[] PROGMEM = "symbolp"; +const char string47[] PROGMEM = "streamp"; +const char string48[] PROGMEM = "eq"; +const char string49[] PROGMEM = "car"; +const char string50[] PROGMEM = "first"; +const char string51[] PROGMEM = "cdr"; +const char string52[] PROGMEM = "rest"; +const char string53[] PROGMEM = "caar"; +const char string54[] PROGMEM = "cadr"; +const char string55[] PROGMEM = "second"; +const char string56[] PROGMEM = "cdar"; +const char string57[] PROGMEM = "cddr"; +const char string58[] PROGMEM = "caaar"; +const char string59[] PROGMEM = "caadr"; +const char string60[] PROGMEM = "cadar"; +const char string61[] PROGMEM = "caddr"; +const char string62[] PROGMEM = "third"; +const char string63[] PROGMEM = "cdaar"; +const char string64[] PROGMEM = "cdadr"; +const char string65[] PROGMEM = "cddar"; +const char string66[] PROGMEM = "cdddr"; +const char string67[] PROGMEM = "length"; +const char string68[] PROGMEM = "list"; +const char string69[] PROGMEM = "reverse"; +const char string70[] PROGMEM = "nth"; +const char string71[] PROGMEM = "assoc"; +const char string72[] PROGMEM = "member"; +const char string73[] PROGMEM = "apply"; +const char string74[] PROGMEM = "funcall"; +const char string75[] PROGMEM = "append"; +const char string76[] PROGMEM = "mapc"; +const char string77[] PROGMEM = "mapcar"; +const char string78[] PROGMEM = "+"; +const char string79[] PROGMEM = "-"; +const char string80[] PROGMEM = "*"; +const char string81[] PROGMEM = "/"; +const char string82[] PROGMEM = "mod"; +const char string83[] PROGMEM = "1+"; +const char string84[] PROGMEM = "1-"; +const char string85[] PROGMEM = "abs"; +const char string86[] PROGMEM = "random"; +const char string87[] PROGMEM = "max"; +const char string88[] PROGMEM = "min"; +const char string89[] PROGMEM = "="; +const char string90[] PROGMEM = "<"; +const char string91[] PROGMEM = "<="; +const char string92[] PROGMEM = ">"; +const char string93[] PROGMEM = ">="; +const char string94[] PROGMEM = "/="; +const char string95[] PROGMEM = "plusp"; +const char string96[] PROGMEM = "minusp"; +const char string97[] PROGMEM = "zerop"; +const char string98[] PROGMEM = "oddp"; +const char string99[] PROGMEM = "evenp"; +const char string100[] PROGMEM = "char"; +const char string101[] PROGMEM = "char-code"; +const char string102[] PROGMEM = "code-char"; +const char string103[] PROGMEM = "characterp"; +const char string104[] PROGMEM = "stringp"; +const char string105[] PROGMEM = "string="; +const char string106[] PROGMEM = "string<"; +const char string107[] PROGMEM = "string>"; +const char string108[] PROGMEM = "sort"; +const char string109[] PROGMEM = "string"; +const char string110[] PROGMEM = "concatenate"; +const char string111[] PROGMEM = "subseq"; +const char string112[] PROGMEM = "read-from-string"; +const char string113[] PROGMEM = "princ-to-string"; +const char string114[] PROGMEM = "prin1-to-string"; +const char string115[] PROGMEM = "logand"; +const char string116[] PROGMEM = "logior"; +const char string117[] PROGMEM = "logxor"; +const char string118[] PROGMEM = "lognot"; +const char string119[] PROGMEM = "ash"; +const char string120[] PROGMEM = "logbitp"; +const char string121[] PROGMEM = "eval"; +const char string122[] PROGMEM = "globals"; +const char string123[] PROGMEM = "locals"; +const char string124[] PROGMEM = "makunbound"; +const char string125[] PROGMEM = "break"; +const char string126[] PROGMEM = "read"; +const char string127[] PROGMEM = "prin1"; +const char string128[] PROGMEM = "print"; +const char string129[] PROGMEM = "princ"; +const char string130[] PROGMEM = "terpri"; +const char string131[] PROGMEM = "read-byte"; +const char string132[] PROGMEM = "read-line"; +const char string133[] PROGMEM = "write-byte"; +const char string134[] PROGMEM = "write-string"; +const char string135[] PROGMEM = "write-line"; +const char string136[] PROGMEM = "restart-i2c"; +const char string137[] PROGMEM = "gc"; +const char string138[] PROGMEM = "room"; +const char string139[] PROGMEM = "save-image"; +const char string140[] PROGMEM = "load-image"; +const char string141[] PROGMEM = "cls"; +const char string142[] PROGMEM = "pinmode"; +const char string143[] PROGMEM = "digitalread"; +const char string144[] PROGMEM = "digitalwrite"; +const char string145[] PROGMEM = "analogread"; +const char string146[] PROGMEM = "analogwrite"; +const char string147[] PROGMEM = "delay"; +const char string148[] PROGMEM = "millis"; +const char string149[] PROGMEM = "note"; +const char string150[] PROGMEM = "edit"; +const char string151[] PROGMEM = "pprint"; const tbl_entry_t lookup_table[] PROGMEM = { { string0, NULL, NIL, NIL }, @@ -2611,129 +2706,130 @@ const tbl_entry_t lookup_table[] PROGMEM = { { string25, sp_withserial, 1, 127 }, { string26, sp_withi2c, 1, 127 }, { string27, sp_withspi, 1, 127 }, - { string28, NULL, NIL, NIL }, - { string29, tf_progn, 0, 127 }, - { string30, tf_return, 0, 127 }, - { string31, tf_if, 2, 3 }, - { string32, tf_cond, 0, 127 }, - { string33, tf_when, 1, 127 }, - { string34, tf_unless, 1, 127 }, - { string35, tf_and, 0, 127 }, - { string36, tf_or, 0, 127 }, - { string37, NULL, NIL, NIL }, - { string38, fn_not, 1, 1 }, + { string28, sp_withsdcard, 2, 127 }, + { string29, NULL, NIL, NIL }, + { string30, tf_progn, 0, 127 }, + { string31, tf_return, 0, 127 }, + { string32, tf_if, 2, 3 }, + { string33, tf_cond, 0, 127 }, + { string34, tf_when, 1, 127 }, + { string35, tf_unless, 1, 127 }, + { string36, tf_and, 0, 127 }, + { string37, tf_or, 0, 127 }, + { string38, NULL, NIL, NIL }, { string39, fn_not, 1, 1 }, - { string40, fn_cons, 2, 2 }, - { string41, fn_atom, 1, 1 }, - { string42, fn_listp, 1, 1 }, - { string43, fn_consp, 1, 1 }, - { string44, fn_numberp, 1, 1 }, - { string45, fn_symbolp, 1, 1 }, - { string46, fn_streamp, 1, 1 }, - { string47, fn_eq, 2, 2 }, - { string48, fn_car, 1, 1 }, + { string40, fn_not, 1, 1 }, + { string41, fn_cons, 2, 2 }, + { string42, fn_atom, 1, 1 }, + { string43, fn_listp, 1, 1 }, + { string44, fn_consp, 1, 1 }, + { string45, fn_numberp, 1, 1 }, + { string46, fn_symbolp, 1, 1 }, + { string47, fn_streamp, 1, 1 }, + { string48, fn_eq, 2, 2 }, { string49, fn_car, 1, 1 }, - { string50, fn_cdr, 1, 1 }, + { string50, fn_car, 1, 1 }, { string51, fn_cdr, 1, 1 }, - { string52, fn_caar, 1, 1 }, - { string53, fn_cadr, 1, 1 }, + { string52, fn_cdr, 1, 1 }, + { string53, fn_caar, 1, 1 }, { string54, fn_cadr, 1, 1 }, - { string55, fn_cdar, 1, 1 }, - { string56, fn_cddr, 1, 1 }, - { string57, fn_caaar, 1, 1 }, - { string58, fn_caadr, 1, 1 }, - { string59, fn_cadar, 1, 1 }, - { string60, fn_caddr, 1, 1 }, + { string55, fn_cadr, 1, 1 }, + { string56, fn_cdar, 1, 1 }, + { string57, fn_cddr, 1, 1 }, + { string58, fn_caaar, 1, 1 }, + { string59, fn_caadr, 1, 1 }, + { string60, fn_cadar, 1, 1 }, { string61, fn_caddr, 1, 1 }, - { string62, fn_cdaar, 1, 1 }, - { string63, fn_cdadr, 1, 1 }, - { string64, fn_cddar, 1, 1 }, - { string65, fn_cdddr, 1, 1 }, - { string66, fn_length, 1, 1 }, - { string67, fn_list, 0, 127 }, - { string68, fn_reverse, 1, 1 }, - { string69, fn_nth, 2, 2 }, - { string70, fn_assoc, 2, 2 }, - { string71, fn_member, 2, 2 }, - { string72, fn_apply, 2, 127 }, - { string73, fn_funcall, 1, 127 }, - { string74, fn_append, 0, 127 }, - { string75, fn_mapc, 2, 3 }, - { string76, fn_mapcar, 2, 3 }, - { string77, fn_add, 0, 127 }, - { string78, fn_subtract, 1, 127 }, - { string79, fn_multiply, 0, 127 }, - { string80, fn_divide, 2, 127 }, - { string81, fn_mod, 2, 2 }, - { string82, fn_oneplus, 1, 1 }, - { string83, fn_oneminus, 1, 1 }, - { string84, fn_abs, 1, 1 }, - { string85, fn_random, 1, 1 }, - { string86, fn_max, 1, 127 }, - { string87, fn_min, 1, 127 }, - { string88, fn_numeq, 1, 127 }, - { string89, fn_less, 1, 127 }, - { string90, fn_lesseq, 1, 127 }, - { string91, fn_greater, 1, 127 }, - { string92, fn_greatereq, 1, 127 }, - { string93, fn_noteq, 1, 127 }, - { string94, fn_plusp, 1, 1 }, - { string95, fn_minusp, 1, 1 }, - { string96, fn_zerop, 1, 1 }, - { string97, fn_oddp, 1, 1 }, - { string98, fn_evenp, 1, 1 }, - { string99, fn_char, 2, 2 }, - { string100, fn_charcode, 1, 1 }, - { string101, fn_codechar, 1, 1 }, - { string102, fn_characterp, 1, 1 }, - { string103, fn_stringp, 1, 1 }, - { string104, fn_stringeq, 2, 2 }, - { string105, fn_stringless, 2, 2 }, - { string106, fn_stringgreater, 2, 2 }, - { string107, fn_sort, 2, 2 }, - { string108, fn_stringfn, 1, 1 }, - { string109, fn_concatenate, 1, 127 }, - { string110, fn_subseq, 2, 3 }, - { string111, fn_readfromstring, 1, 1 }, - { string112, fn_princtostring, 1, 1 }, - { string113, fn_prin1tostring, 1, 1 }, - { string114, fn_logand, 0, 127 }, - { string115, fn_logior, 0, 127 }, - { string116, fn_logxor, 0, 127 }, - { string117, fn_lognot, 1, 1 }, - { string118, fn_ash, 2, 2 }, - { string119, fn_logbitp, 2, 2 }, - { string120, fn_eval, 1, 1 }, - { string121, fn_globals, 0, 0 }, - { string122, fn_locals, 0, 0 }, - { string123, fn_makunbound, 1, 1 }, - { string124, fn_break, 0, 0 }, - { string125, fn_read, 0, 0 }, - { string126, fn_prin1, 1, 1 }, - { string127, fn_print, 1, 1 }, - { string128, fn_princ, 1, 1 }, - { string129, fn_terpri, 0, 0 }, - { string130, fn_readbyte, 0, 2 }, - { string131, fn_readline, 0, 1 }, - { string132, fn_writebyte, 1, 2 }, - { string133, fn_writestring, 1, 2 }, - { string134, fn_writeline, 1, 2 }, - { string135, fn_restarti2c, 1, 2 }, - { string136, fn_gc, 0, 0 }, - { string137, fn_room, 0, 0 }, - { string138, fn_saveimage, 0, 1 }, - { string139, fn_loadimage, 0, 1 }, - { string140, fn_cls, 0, 0 }, - { string141, fn_pinmode, 2, 2 }, - { string142, fn_digitalread, 1, 1 }, - { string143, fn_digitalwrite, 2, 2 }, - { string144, fn_analogread, 1, 1 }, - { string145, fn_analogwrite, 2, 2 }, - { string146, fn_delay, 1, 1 }, - { string147, fn_millis, 0, 0 }, - { string148, fn_note, 0, 3 }, - { string149, fn_edit, 1, 1 }, - { string150, fn_pprint, 1, 1 }, + { string62, fn_caddr, 1, 1 }, + { string63, fn_cdaar, 1, 1 }, + { string64, fn_cdadr, 1, 1 }, + { string65, fn_cddar, 1, 1 }, + { string66, fn_cdddr, 1, 1 }, + { string67, fn_length, 1, 1 }, + { string68, fn_list, 0, 127 }, + { string69, fn_reverse, 1, 1 }, + { string70, fn_nth, 2, 2 }, + { string71, fn_assoc, 2, 2 }, + { string72, fn_member, 2, 2 }, + { string73, fn_apply, 2, 127 }, + { string74, fn_funcall, 1, 127 }, + { string75, fn_append, 0, 127 }, + { string76, fn_mapc, 2, 3 }, + { string77, fn_mapcar, 2, 3 }, + { string78, fn_add, 0, 127 }, + { string79, fn_subtract, 1, 127 }, + { string80, fn_multiply, 0, 127 }, + { string81, fn_divide, 2, 127 }, + { string82, fn_mod, 2, 2 }, + { string83, fn_oneplus, 1, 1 }, + { string84, fn_oneminus, 1, 1 }, + { string85, fn_abs, 1, 1 }, + { string86, fn_random, 1, 1 }, + { string87, fn_max, 1, 127 }, + { string88, fn_min, 1, 127 }, + { string89, fn_numeq, 1, 127 }, + { string90, fn_less, 1, 127 }, + { string91, fn_lesseq, 1, 127 }, + { string92, fn_greater, 1, 127 }, + { string93, fn_greatereq, 1, 127 }, + { string94, fn_noteq, 1, 127 }, + { string95, fn_plusp, 1, 1 }, + { string96, fn_minusp, 1, 1 }, + { string97, fn_zerop, 1, 1 }, + { string98, fn_oddp, 1, 1 }, + { string99, fn_evenp, 1, 1 }, + { string100, fn_char, 2, 2 }, + { string101, fn_charcode, 1, 1 }, + { string102, fn_codechar, 1, 1 }, + { string103, fn_characterp, 1, 1 }, + { string104, fn_stringp, 1, 1 }, + { string105, fn_stringeq, 2, 2 }, + { string106, fn_stringless, 2, 2 }, + { string107, fn_stringgreater, 2, 2 }, + { string108, fn_sort, 2, 2 }, + { string109, fn_stringfn, 1, 1 }, + { string110, fn_concatenate, 1, 127 }, + { string111, fn_subseq, 2, 3 }, + { string112, fn_readfromstring, 1, 1 }, + { string113, fn_princtostring, 1, 1 }, + { string114, fn_prin1tostring, 1, 1 }, + { string115, fn_logand, 0, 127 }, + { string116, fn_logior, 0, 127 }, + { string117, fn_logxor, 0, 127 }, + { string118, fn_lognot, 1, 1 }, + { string119, fn_ash, 2, 2 }, + { string120, fn_logbitp, 2, 2 }, + { string121, fn_eval, 1, 1 }, + { string122, fn_globals, 0, 0 }, + { string123, fn_locals, 0, 0 }, + { string124, fn_makunbound, 1, 1 }, + { string125, fn_break, 0, 0 }, + { string126, fn_read, 0, 1 }, + { string127, fn_prin1, 1, 2 }, + { string128, fn_print, 1, 2 }, + { string129, fn_princ, 1, 2 }, + { string130, fn_terpri, 0, 1 }, + { string131, fn_readbyte, 0, 2 }, + { string132, fn_readline, 0, 1 }, + { string133, fn_writebyte, 1, 2 }, + { string134, fn_writestring, 1, 2 }, + { string135, fn_writeline, 1, 2 }, + { string136, fn_restarti2c, 1, 2 }, + { string137, fn_gc, 0, 0 }, + { string138, fn_room, 0, 0 }, + { string139, fn_saveimage, 0, 1 }, + { string140, fn_loadimage, 0, 1 }, + { string141, fn_cls, 0, 0 }, + { string142, fn_pinmode, 2, 2 }, + { string143, fn_digitalread, 1, 1 }, + { string144, fn_digitalwrite, 2, 2 }, + { string145, fn_analogread, 1, 1 }, + { string146, fn_analogwrite, 2, 2 }, + { string147, fn_delay, 1, 1 }, + { string148, fn_millis, 0, 0 }, + { string149, fn_note, 0, 3 }, + { string150, fn_edit, 1, 1 }, + { string151, fn_pprint, 1, 2 }, }; // Table lookup functions @@ -2766,12 +2862,12 @@ int lookupfn (symbol_t name) { return pgm_read_word(&lookup_table[name].fptr); } -int lookupmin (symbol_t name) { - return pgm_read_word(&lookup_table[name].min); +uint8_t lookupmin (symbol_t name) { + return pgm_read_byte(&lookup_table[name].min); } -int lookupmax (symbol_t name) { - return pgm_read_word(&lookup_table[name].max); +uint8_t lookupmax (symbol_t name) { + return pgm_read_byte(&lookup_table[name].max); } char *lookupbuiltin (symbol_t name) { @@ -2802,12 +2898,14 @@ void testescape () { // Main evaluator +uint8_t End; + object *eval (object *form, object *env) { int TC=0; EVAL: // Enough space? if (Freespace < 20) gc(form, env); - if (_end != 0xA5) error(PSTR("Stack overflow")); + if (End != 0xA5) error(PSTR("Stack overflow")); // Escape if (tstflag(ESCAPE)) { clrflag(ESCAPE); error(PSTR("Escape!"));} #if defined (serialmonitor) @@ -2922,7 +3020,7 @@ object *eval (object *form, object *env) { int trace = tracing(fname->name); if (trace) { object *result = eval(form, env); - indent((--(TraceDepth[trace-1]))<<1); + indent((--(TraceDepth[trace-1]))<<1, pserial); pint(TraceDepth[trace-1], pserial); pserial(':'); pserial(' '); printobject(fname, pserial); pfstring(PSTR(" returned "), pserial); @@ -3050,6 +3148,7 @@ void printobject(object *form, pfun_t pfun){ pfstring(PSTR("<"), pfun); if ((form->integer)>>8 == SPISTREAM) pfstring(PSTR("spi"), pfun); else if ((form->integer)>>8 == I2CSTREAM) pfstring(PSTR("i2c"), pfun); + else if ((form->integer)>>8 == SDSTREAM) pfstring(PSTR("sd"), pfun); else pfstring(PSTR("serial"), pfun); pfstring(PSTR("-stream "), pfun); pint(form->integer & 0xFF, pfun); @@ -3060,7 +3159,7 @@ void printobject(object *form, pfun_t pfun){ // Read functions -char gserial () { +int gserial () { if (LastChar) { char temp = LastChar; LastChar = 0; @@ -3073,7 +3172,7 @@ char gserial () { } object *nextitem (gfun_t gfun) { - char ch = gfun(); + int ch = gfun(); while(isspace(ch)) ch = gfun(); if (ch == ';') { @@ -3081,8 +3180,7 @@ object *nextitem (gfun_t gfun) { ch = '('; } if (ch == '\n') ch = gfun(); - if (ch == EOF) exit(0); - + if (ch == EOF) return nil; if (ch == ')') return (object *)KET; if (ch == '(') return (object *)BRA; if (ch == '\'') return (object *)QUO; @@ -3175,7 +3273,7 @@ object *readrest (gfun_t gfun) { object *read (gfun_t gfun) { object *item = nextitem(gfun); - if (item == (object *)KET) error(PSTR("Unexpected end of list")); + if (item == (object *)KET) error(PSTR("Incomplete list")); if (item == (object *)BRA) return readrest(gfun); if (item == (object *)DOT) return read(gfun); if (item == (object *)QUO) return cons(symbol(QUOTE), cons(read(gfun), NULL)); @@ -3194,7 +3292,7 @@ void setup() { while (!Serial); // wait for Serial to initialize initworkspace(); initenv(); - pfstring(PSTR("uLisp 1.9a "), pserial); pln(pserial); + pfstring(PSTR("uLisp 2.0 "), pserial); pln(pserial); } // Read/Evaluate/Print loop @@ -3231,6 +3329,11 @@ void loop () { autorunimage(); #endif } - _end = 0xA5; // Canary to check stack + // Come here after error + End = 0xA5; // Canary to check stack + for (int i=0; i