diff --git a/ulisp-arm.ino b/ulisp-arm.ino index a9f60df..8892924 100644 --- a/ulisp-arm.ino +++ b/ulisp-arm.ino @@ -1,5 +1,5 @@ -/* uLisp ARM 2.6a - www.ulisp.com - David Johnson-Davies - www.technoblogy.com - 19th April 2019 +/* uLisp ARM 2.7 - www.ulisp.com + David Johnson-Davies - www.technoblogy.com - 20th May 2019 Licensed under the MIT license: https://opensource.org/licenses/MIT */ @@ -392,8 +392,7 @@ int compactimage (object **arg) { char *MakeFilename (object *arg) { char *buffer = SymbolTop; int max = maxbuffer(buffer); - buffer[0]='/'; - int i = 1; + int i = 0; do { char c = nthchar(arg, i); if (c == '\0') break; @@ -649,21 +648,19 @@ void autorunimage () { File file = SD.open("ULISP.IMG"); if (!file) error(PSTR("Error: Problem autorunning from SD card")); object *autorun = (object *)SDReadInt(file); - object *nullenv = NULL; file.close(); if (autorun != NULL) { loadimage(NULL); - apply(autorun, NULL, &nullenv); + apply(autorun, NULL, NULL); } #elif defined(ARDUINO_METRO_M4) || defined(ARDUINO_ITSYBITSY_M4) || defined(ARDUINO_FEATHER_M4) if (!FlashSetup()) error(PSTR("No DataFlash found.")); - object *nullenv = NULL; FlashBeginRead(); object *autorun = (object *)FlashReadInt(); FlashEndRead(); if (autorun != NULL && (unsigned int)autorun != 0xFFFF) { loadimage(nil); - apply(autorun, NULL, &nullenv); + apply(autorun, NULL, NULL); } #else error(PSTR("autorun not available")); @@ -961,15 +958,6 @@ object *findvalue (object *var, object *env) { return pair; } -object *findtwin (object *var, object *env) { - while (env != NULL) { - object *pair = car(env); - if (pair != NULL && car(pair) == var) return pair; - env = cdr(env); - } - return NULL; -} - // Handling closures object *closure (int tc, object *fname, object *state, object *function, object *args, object **env) { @@ -982,10 +970,14 @@ object *closure (int tc, object *fname, object *state, object *function, object } object *params = first(function); function = cdr(function); - // Push state if not already in env + // Dropframe + if (tc) { + while (*env != NULL && car(*env) != NULL) pop(*env); + } else push(nil, *env); + // Push state while (state != NULL) { object *pair = first(state); - if (findtwin(car(pair), *env) == NULL) push(pair, *env); + push(pair, *env); state = cdr(state); } // Add arguments to environment @@ -1014,9 +1006,7 @@ object *closure (int tc, object *fname, object *state, object *function, object else error2(fname, PSTR("has too few arguments")); } else { value = first(args); args = cdr(args); } } - object *pair = findtwin(var, *env); - if (tc && (pair != NULL)) cdr(pair) = value; - else push(cons(var,value), *env); + push(cons(var,value), *env); if (trace) { pserial(' '); printobject(value, pserial); } } params = cdr(params); @@ -1027,24 +1017,24 @@ object *closure (int tc, object *fname, object *state, object *function, object return tf_progn(function, *env); } -object *apply (object *function, object *args, object **env) { +object *apply (object *function, object *args, object *env) { if (symbolp(function)) { symbol_t name = function->name; int nargs = listlength(args); if (name >= ENDFUNCTIONS) error2(function, PSTR("is not valid here")); if (nargslookupmax(name)) error2(function, PSTR("has too many arguments")); - return ((fn_ptr_type)lookupfn(name))(args, *env); + return ((fn_ptr_type)lookupfn(name))(args, env); } if (listp(function) && issymbol(car(function), LAMBDA)) { function = cdr(function); - object *result = closure(0, NULL, NULL, function, args, env); - return eval(result, *env); + object *result = closure(0, NULL, NULL, function, args, &env); + return eval(result, env); } if (listp(function) && issymbol(car(function), CLOSURE)) { function = cdr(function); - object *result = closure(0, NULL, car(function), cdr(function), args, env); - return eval(result, *env); + object *result = closure(0, NULL, car(function), cdr(function), args, &env); + return eval(result, env); } error2(function, PSTR("is an illegal function")); return NULL; @@ -1638,11 +1628,7 @@ object *sp_withspi (object *args, object *env) { SPI.begin(); params = cddr(params); if (params != NULL) { - int d = integer(eval(first(params), env)); - if (d<1 || d>7) error3(WITHSPI, PSTR("invalid divider")); - if (d == 7) divider = 3; - else if (d & 1) divider = (d>>1) + 4; - else divider = (d>>1) - 1; + divider = integer(eval(first(params), env)); params = cdr(params); if (params != NULL) { bitorder = (eval(first(params), env) == NULL); @@ -1653,7 +1639,7 @@ object *sp_withspi (object *args, object *env) { pinMode(pin, OUTPUT); digitalWrite(pin, LOW); SPI.setBitOrder((BitOrder)bitorder); - SPI.setClockDivider(divider); + if (divider != 0) SPI.setClockDivider(divider); SPI.setDataMode(mode); object *forms = cdr(args); object *result = eval(tf_progn(forms,env), env); @@ -1966,11 +1952,11 @@ object *fn_apply (object *args, object *env) { } if (!listp(car(last))) error3(APPLY, PSTR("last argument is not a list")); cdr(previous) = car(last); - return apply(first(args), cdr(args), &env); + return apply(first(args), cdr(args), env); } object *fn_funcall (object *args, object *env) { - return apply(first(args), cdr(args), &env); + return apply(first(args), cdr(args), env); } object *fn_append (object *args, object *env) { @@ -2003,13 +1989,13 @@ object *fn_mapc (object *args, object *env) { while (list1 != NULL && list2 != NULL) { if (improperp(list1)) error3(name, PSTR("second argument is not a proper list")); if (improperp(list2)) error3(name, PSTR("third argument is not a proper list")); - apply(function, cons(car(list1),cons(car(list2),NULL)), &env); + apply(function, cons(car(list1),cons(car(list2),NULL)), env); list1 = cdr(list1); list2 = cdr(list2); } } else { while (list1 != NULL) { if (improperp(list1)) error3(name, PSTR("second argument is not a proper list")); - apply(function, cons(car(list1),NULL), &env); + apply(function, cons(car(list1),NULL), env); list1 = cdr(list1); } } @@ -2029,7 +2015,7 @@ object *fn_mapcar (object *args, object *env) { while (list1 != NULL && list2 != NULL) { if (improperp(list1)) error3(name, PSTR("second argument is not a proper list")); if (improperp(list2)) error3(name, PSTR("third argument is not a proper list")); - object *result = apply(function, cons(car(list1), cons(car(list2),NULL)), &env); + object *result = apply(function, cons(car(list1), cons(car(list2),NULL)), env); object *obj = cons(result,NULL); cdr(tail) = obj; tail = obj; @@ -2038,7 +2024,7 @@ object *fn_mapcar (object *args, object *env) { } else if (list1 != NULL) { while (list1 != NULL) { if (improperp(list1)) error3(name, PSTR("second argument is not a proper list")); - object *result = apply(function, cons(car(list1),NULL), &env); + object *result = apply(function, cons(car(list1),NULL), env); object *obj = cons(result,NULL); cdr(tail) = obj; tail = obj; @@ -2062,7 +2048,7 @@ object *fn_mapcan (object *args, object *env) { while (list1 != NULL && list2 != NULL) { if (improperp(list1)) error3(name, PSTR("second argument is not a proper list")); if (improperp(list2)) error3(name, PSTR("third argument is not a proper list")); - object *result = apply(function, cons(car(list1), cons(car(list2),NULL)), &env); + object *result = apply(function, cons(car(list1), cons(car(list2),NULL)), env); while (result != NULL && (unsigned int)result >= PAIR) { cdr(tail) = result; tail = result; @@ -2074,7 +2060,7 @@ object *fn_mapcan (object *args, object *env) { } else if (list1 != NULL) { while (list1 != NULL) { if (improperp(list1)) error3(name, PSTR("second argument is not a proper list")); - object *result = apply(function, cons(car(list1),NULL), &env); + object *result = apply(function, cons(car(list1),NULL), env); while (result != NULL && (unsigned int)result >= PAIR) { cdr(tail) = result; tail = result; @@ -2677,7 +2663,7 @@ object *fn_sort (object *args, object *env) { while (go != ptr) { car(compare) = car(cdr(ptr)); car(cdr(compare)) = car(cdr(go)); - if (apply(predicate, compare, &env)) break; + if (apply(predicate, compare, env)) break; go = cdr(go); } if (go != ptr) { @@ -3790,11 +3776,7 @@ object *eval (object *form, object *env) { object *envcopy = NULL; while (env != NULL) { object *pair = first(env); - if (pair != NULL) { - object *val = cdr(pair); - if (integerp(val)) val = number(val->integer); - push(cons(car(pair), val), envcopy); - } + if (pair != NULL) push(pair, envcopy); env = cdr(env); } return cons(symbol(CLOSURE), cons(envcopy,args)); @@ -4224,7 +4206,7 @@ void setup () { initworkspace(); initenv(); initsleep(); - pfstring(PSTR("uLisp 2.6 "), pserial); pln(pserial); + pfstring(PSTR("uLisp 2.7 "), pserial); pln(pserial); } // Read/Evaluate/Print loop