diff --git a/doc/DRAWL.md b/doc/DRAWL.md index 01831e3..c8dee36 100644 --- a/doc/DRAWL.md +++ b/doc/DRAWL.md @@ -21,6 +21,132 @@ However, the code is partitioned to allow for easy extension so some of these mi - Bit-wise logic operations on 32 bit integers - Hexadecimal input/output +Thes DRAWL implementation comes with the follwoing built-in: + +### Constants +- T = True +- F = False +- NIL = NULL +- SPACE = SPACE character on output +- CR = Carriage Return character on output +- CSET() +- CSETQ() +- DEFINE() + +### Function types + +- LAMBDA +- FUNARG +- FUNCTION + + +### Predicates + +- ATOM() +- EQ() +- NOT() +- AND(...) +- OR(...) +- NULL() + +### Misc + +- SET +- QUOTE() +- ARRAY +- TRACE() = Turn tracing on/off +- GC() = Run garbage collector and return free memory amount +- QUIT() = Exit REPL + +### List manipulation + +- CAR() +- CDR() +- CONS() +- LIST(...) + +### Conditionals + +- COND(...) +- IF() + +### Output + +- PRHEX() = Turn hexadecimal output on/off +- PRI(...) = Print without newline +- PRINT(...) = Print with newline +- FMTFPI() = Floating point format integer digits +- FMTFPF() = Floating point format fractional digits +- PRINTER() = Turn printer echo on/off on slot# + +### Looping + +- FOR() +- WHILE() +- UNTIL() + +### Associations + +- LABEL() +- SET() +- SETQ() + +### Program feature + +- PROG +- GO() +- RETURN() + +### Numbers + +- +() +- -() +- '\*'() +- /() +- REM() +- NEG() +- ABS() +- >() +- <() +- MIN() +- MAX() + +### Integers + +- BITNOT() = Bit-wise NOT +- BITAND() = Bit-wise AND +- BITOR() = Bit-wise OR +- BITXOR= Bit-wise XOR +- SHIFT() = Bit-wise SHIFT (positive = left, negative = right) +- ROTATE() = Bit-wise ROTATE (positive = left, negative = right) + +### Floating Point (from the SANE library) + +- PI() +- MATH_E() +- LOGB() +- SCALEB_I() +- TRUNCATE() +- ROUND() +- SQRT() +- COS() +- SIN() +- TAN() +- ATAN() +- LOG2() +- LOG2_1() +- LN() +- LN_1() +- POW2() +- POW2_1() +- POWE() +- POWE_1() +- POWE2_1() +- POW_I() +- POWY() +- COMP() +- ANNUITY() + LISP is one of the earliest computer languages. As such, it holds a special place in the anals of computer science. I've always wanted to learn why LISP is held in such high regard by so many, so I went about learning LISP by actually implementing a LISP interpreter in PLASMA. PLASMA is well suited to implement other languages due to its rich syntax, performance and libraries. ## Links @@ -29,6 +155,10 @@ Here are some links to get you started. LISP 1.5 Manual: https://archive.org/details/bitsavers_mitrlelisprammersManual2ed1985_9279667 +LISP 1.5 Primer: https://www.softwarepreservation.org/projects/LISP/book/Weismann_LISP1.5_Primer_1967.pdf + +Apple Numerics Manual (SANE): https://vintageapple.org/inside_o/pdf/Apple_Numerics_Manual_Second_Edition_1988.pdf + Video showing DRAWL in action: https://youtu.be/wBMivg6xfSg Preconfigured PLASMA ProDOS boot floppy for DRAWL: https://github.com/dschmenk/PLASMA/blob/master/images/apple/DRAWL.po diff --git a/images/apple/DRAWL.po b/images/apple/DRAWL.po index 9fd6252..175c388 100644 Binary files a/images/apple/DRAWL.po and b/images/apple/DRAWL.po differ diff --git a/src/lisp/drawl.pla b/src/lisp/drawl.pla index cf49541..775e58d 100644 --- a/src/lisp/drawl.pla +++ b/src/lisp/drawl.pla @@ -59,10 +59,14 @@ import smath predef eval_int(expr)#1 end + var prog, prog_expr, prog_return // Current PROG expressions var sym_cond, sym_if, sym_fpint, sym_fpfrac var pred_true +const csw = $0036 // Output switch vector +var scrncsw = 0 // Output screen value + const FILEBUF_SIZE = 128 var readfn // Read input routine var fileref, filebuf // File read vars @@ -174,6 +178,24 @@ def natv_gc(symptr, expr) return new_int(heapavail, 0) end +def natv_printer(symptr, expr) + byte slot + + slot = eval_int(expr)=>intval & 7 + if slot + if !scrncsw + scrncsw = *csw + fin + *csw = $C000 | (slot << 8) + else + if scrncsw + *csw = scrncsw + fin + scrncsw = 0 + fin + return new_int(slot, 0) +end + def natv_bye(symptr, expr) quit = TRUE return new_sym("GOODBYE!") @@ -267,22 +289,23 @@ end // puts("DRAWL (LISP 1.5) symbolic processor\n") -pred_true = bool_pred(TRUE) // Capture value of TRUE -sym_fpint = new_sym("FMTFPI") -sym_fpfrac = new_sym("FMTFPF") -sym_fpint=>natv = @natv_fpint -sym_fpfrac=>natv = @natv_fpfrac -sym_fpint=>apval = new_int(fmt_fpint, 0) ^ NULL_HACK -sym_fpfrac=>apval = new_int(fmt_fpfrac, 0) ^ NULL_HACK -sym_cond = new_sym("COND") // This should actually match COND -sym_if = new_sym("IF") // This should actually match IF -new_sym("PROG")=>natv = @natv_prog -new_sym("GO")=>natv = @natv_go -new_sym("RETURN")=>natv = @natv_return -new_sym("SET")=>natv = @natv_set -new_sym("SETQ")=>natv = @natv_setq -new_sym("GC")=>natv = @natv_gc -new_sym("QUIT")=>natv = @natv_bye +pred_true = bool_pred(TRUE) // Capture value of TRUE +sym_fpint = new_sym("FMTFPI") +sym_fpfrac = new_sym("FMTFPF") +sym_fpint=>natv = @natv_fpint +sym_fpfrac=>natv = @natv_fpfrac +sym_fpint=>apval = new_int(fmt_fpint, 0) ^ NULL_HACK +sym_fpfrac=>apval = new_int(fmt_fpfrac, 0) ^ NULL_HACK +sym_cond = new_sym("COND") // This should actually match COND +sym_if = new_sym("IF") // This should actually match IF +new_sym("PROG")=>natv = @natv_prog +new_sym("GO")=>natv = @natv_go +new_sym("RETURN")=>natv = @natv_return +new_sym("SET")=>natv = @natv_set +new_sym("SETQ")=>natv = @natv_setq +new_sym("GC")=>natv = @natv_gc +new_sym("PRINTER")=>natv = @natv_printer +new_sym("QUIT")=>natv = @natv_bye parse_cmdline while not quit