From b32cd97f27cf714a5e0b5888b883f3ced4579811 Mon Sep 17 00:00:00 2001 From: Ralph Ronnquist Date: Tue, 16 May 2023 23:16:39 +1000 Subject: [PATCH] added --- Makefile | 20 ++++++ foop.lsp | 61 +++++++++++++++++ misc.lsp | 50 ++++++++++++++ newlisp-libmisc.a.8.adoc | 139 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 270 insertions(+) create mode 100644 Makefile create mode 100644 foop.lsp create mode 100644 misc.lsp create mode 100644 newlisp-libmisc.a.8.adoc diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..bc3fa26 --- /dev/null +++ b/Makefile @@ -0,0 +1,20 @@ +# Create the newlisp library foop.lsplib + +ARCHIVE = newlisp-libmisc.a +ARFILES = foop.lsp misc.lsp + +BUILD = ${ARCHIVE} ${ARCHIVE}.8 + +default: ${BUILD} + +${ARCHIVE}: ${ARFILES} + +%.a: + ar r $@ $^ + +%.8: %.8.adoc + asciidoctor -b manpage $< + +clean: + rm -f ${BUILD} + diff --git a/foop.lsp b/foop.lsp new file mode 100644 index 0000000..1724d3c --- /dev/null +++ b/foop.lsp @@ -0,0 +1,61 @@ +;; This newlisp module provides FOOP modelling support +;; +;; Functional Object-Oriented Programming (FOOP) is an abstraction +;; overlay using the newlisp context notion as similar to the class +;; notion in genuine object-oriented programming languages. This is +;; set out in newlisp by means of the representation principle that an +;; instance of a FOOP "class" (i.e. context) is a list headed by the +;; context itself, and followed by the "member values". +;; +;; FOOP further includes by the "method invocation" syntax where a +;; function is preceded by ':' and then followed by the instance +;; concerned before actual function arguments. That instance is then +;; stoved away as implicitly available via the (self) function, and +;; the member values accessible via index, e.g. the term (self 3) +;; refers to the third member of the instance. The self references are +;; destructively assignable with setf. +;; +;; This modelling support adds member name declaration together with +;; automatic getter and setter defintions. The (FOOP ...) term is used +;; for declaring member names in order. For example: +;; +;; (context 'MAIN:EX") +;; (FOOP a b c) +;; (define (EX:EX n) (list (context) (+ n 4) 3 2)) +;; +;; That would declare a FOOP context EX with instances having three +;; members named a, b and c. The declaratin results in a variable EX:. +;; whose value is (FOOP a b c), as well as three access functions for +;; each member: the member position index (.member), a getter +;; (%member) and a setter (!member V). +;; +;; As indicated in the example, (FOOP a b c) does not define the +;; "constructor". It only defines the access functions. + +(context 'FOOP) + +;; Helper function to make a new symbol for the context of S by +;; preceeding it with string P. +(define (name P S) (sym (string P (term S)) (prefix S))) + +;; (FOOP name ...) +; foop is a language extension to declare the field names of a FOOP +; object type, and thereby gain getter and setter functions with the +; naming formats (:%name obj) and (:!name obj value) respectively . +(define-macro (FOOP:FOOP) + (let ((K (sym "." (prefix (first (args))))) + (V (cons (context) (args))) + (I 0)) + (set K V) + (dolist (S (args)) + (letex ((GET (name "%" S)) + (SET (name "!" S)) + (IT (name "." S)) + (V (sym "V" (prefix S))) + (I (inc I))) + (define (IT) I) + (define (GET) (self I)) + (define (SET V) (setf (self I) V)))) + )) + +"foop.lsp" diff --git a/misc.lsp b/misc.lsp new file mode 100644 index 0000000..8a6309a --- /dev/null +++ b/misc.lsp @@ -0,0 +1,50 @@ +;; This module provides some utility functions. + +(define (prog1 X) X) +(global 'prog1) + +(define (die N) + (when (args) (write-line 2 (join (map string (args)) " "))) + (and (number? N) (exit N))) +(global 'die) + +;; Prepend with C onto S so as to fill width W, if it's a number. +(define (pre-fill C S W) + (while (and (number? W) (< (length S) W)) + (setf S (string C S))) + S) +(global 'pre-fill) + +;; Make a hex string from a data block pad with "0" to W if non-nil +(define (char2hex STR W) + (pre-fill "0" (join (map (curry format "%2x") (map char (explode STR)))) W)) +(global 'char2hex) + +;; Print binary byte as octal or as ASCII character [32-126] +(define (octal-byte x) + (if (and (> x 31) (< x 127)) (char x) (format "\\%o" x))) +(global 'octal-byte) + +;; Print string as binary octals +(define (octals-string S) + (join (map octal-byte (unpack (dup "b" (length S)) S)))) +(global 'octals-string) + +;; Return byte code as printable or as decimal number. +(define (human-byte B) + (if (and (> B 32) (< B 127)) (char B) B)) +(global 'human-byte) + +;; Return a packed encoding of a list of bytes, joining its string elements +(define (human-bytes BL) + (let ((OUT '()) (X nil)) + (dolist (B (map human-byte BL)) + (if (string? B) (if X (extend X B) (setf X B)) + (begin (when (string? X) (push X OUT -1)) + (push B OUT -1) + (setf X nil)))) + (when (string? X) (push X OUT -1)) + OUT)) +(global 'human-bytes) + +"misc.lsp" diff --git a/newlisp-libmisc.a.8.adoc b/newlisp-libmisc.a.8.adoc new file mode 100644 index 0000000..d5ce49c --- /dev/null +++ b/newlisp-libmisc.a.8.adoc @@ -0,0 +1,139 @@ += newlisp-libmisc.a(8) +:doctype: manpage +:revdate: {sys:date "+%Y-%m-%d %H:%M:%S"} + +== NAME + +newlisp-libmisc.a - Newlisp archive comprosing useful functions. + +== SYNOPSIS + +.With packnl (example) +packnl _main.lsp_ *-A newlisp-libmisc.a* + + +.With incore.lsp +(load "incore.lsp") + +(archive "newlisp-libmisc.a") + +(load "misc.lsp") + +== DESCRIPTION + +*newlisp-libmisc.a* is a newlisp archive file that provides loadable +modules with utility functions. + +=== misc.lsp API + +(prog1 [_term_]*):: + +The *prog1* function is like a *begin* function except that it returns +the value of the first term rather than the last. + +(die _N_ [_term_]*):: + +The *die* function printes to stderr the join of term values as +strings with space separation, and if _N_ is a number, then the +function exits the program with that return code. ++ +.Example of stderr logging +(die nil 'This "is" 'printed "to stderr") + +(octal-byte _B_):: +Print binary byte as octal or as ASCII character [32-126]. + +(octals-string _S_):: +Print string as a succesion of +octal-byte+. + +(human-byte _B_):: +Return byte code as printable (string) or as code (number). + +(human-bytes _BL_):: + +Return a list of human-byte elements from a list of byte codes but +also joining consecutive string elements to form packed strings. + +=== foop.lsp API + +This newlisp module provides Functional Object-Oriented Programming +(FOOP) modelling support. + +FOOP is an abstraction overlay using the newlisp context notion as a +simile to the _class_ notion in genuine object-oriented programming +languages. This is set out in newlisp by means of the representation +principle that an instance of a FOOP "class" (i.e. context) is a list +headed by the context itself, and followed by the "member values". + +FOOP further includes by the "method invocation" syntax where a +function is preceded by ':' and then followed by the instance +concerned before actual function arguments. That instance is then +stoved away as implicitly available via the (self) function, and the +member values accessible via index, e.g. the term (self 3) refers to +the third member of the instance. The self references are +destructively assignable with setf. + +This modelling support adds member name declaration together with +automatic getter and setter defintions. The (FOOP ...) term is used +for declaring member names in order. For example: + +(FOOP [_name_]):: + +*FOOP* is like a language extension to declare the field names of a +FOOP class, and thereby gain "get" and "set" functions generated with +the respective naming formats (:%name obj) and (:!name obj value). + +.illustration +---- +(context 'MAIN:EX) +(FOOP here there more) +(define (EX HERE THERE MORE) (list (context) HERE THERE MORE)) + +(context MAIN) +(setf A (EX 1 2 3)) +--> A = (EX 1 2 3) +(:!there A 4) +--> A = (EX 1 4 3) +---- + +=== mmap.lsp API + +This newlisp module implements a small FOOP model based memory mapping +API that links in the _libc6_ functions _mmap_, _munmap_, _msync_ and +_lseek_. + +(*MMap* _FD_ _LENGTH_ [_OFFSET_ [_PROT_]]):: + +This function creates a FOOP object that represents the memory mapping +of the given file descriptor. _FD_ may be the pathname string of a +file to memory map or an already opened file descriptor. The MMap +object represents the memory block starting at (:%base) and (%len) +bytes in length where the file is memory mapped. ++ +.Access example (from test.lsp) +[caption=""] +---- +(println (setf X (MMap "mmap.lsp"))) +(println (get-string (:%base X))) +---- ++ +Note that only a plain text file would be accessed with _get-string_. +A binary file would rather be accessed with _unpack_. The memory +mapping provides read-only "random access" to the file content. ++ +To set up read-write acces requires an _OFFSET_ and the _PROT_ +argument 0x3, and writing should be accompanied by _MMap:msync_ calls +so as to synchronize with the backing file. ++ +The FOOP object includes get and set methods for the fields (in +order): _base_, _len_, _prot_, _flags_, _fd_ and _offset_. + +=== test.lsp + +This file is a small test of the MMap memory mapping. + +== SEE ALSO + +*newlisp* + +== AUTHOR + +Ralph Ronnquist -- 2.39.2