From b1f18384189e32fa29fadbb29d3043ade4aa67e5 Mon Sep 17 00:00:00 2001 From: Darren Bane Date: Fri, 9 Oct 2020 21:22:20 +0100 Subject: Trying to debug abstract classes, WIP --- cabs-syn.lisp | 5 ++++- cbasic.lisp | 19 +++++++++++++++++-- cutil.lisp | 9 ++++++--- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/cabs-syn.lisp b/cabs-syn.lisp index 12b9fd4..2b6d30a 100644 --- a/cabs-syn.lisp +++ b/cabs-syn.lisp @@ -24,7 +24,10 @@ ;; But classes seem better for the associated data, in discriminated unions. (defclass () () (:metaclass )) -(defclass () ((int :accessor int))) + +(defclass () ((my-int :accessor my-int))) +;; TODO: need another closer-mop:validate-superclass call here + (defclass () ((var :accessor var))) (defclass () ((str :accessor str))) (defclass () ((op :accessor op) (exp :accessor exp))) diff --git a/cbasic.lisp b/cbasic.lisp index 706c564..1085e16 100644 --- a/cbasic.lisp +++ b/cbasic.lisp @@ -1,11 +1,26 @@ ;;; I'm trying to write an interpreter for a BBC BASIC subset ;;; initially following the design of ;;; https://caml.inria.fr/pub/docs/oreilly-book/html/book-ora058.html -;;; and later I can Frankenstein it with -;;; https://github.com/Henry/BuddKaminInterpreters +;;; then later I can optimise following +;;; https://github.com/Henry/BuddKaminInterpreters and +;;; https://oleksandrmanzyuk.wordpress.com/2014/06/18/from-object-algebras-to-finally-tagless-interpreters-2/ +;;; +;;; A BASIC interpreter already exists at +;;; https://gitlab.com/com-informatimago/com-informatimago/-/tree/master/small-cl-pgms/basic +;;; but it is idiomatic CL, +;;; whereas I'm experimenting with a subset like ISLisp. +;; Because this is the main package, +;; 1) ql:quickload QuickLisp dependencies and +;; 2) load local dependencies here. (load "cutil.lisp") (load "cparse.lisp") +;; Use require & defpackage in each package from then on. +;; NB: must have no circular dependencies, and topologically sort the loads. +;; +;; TODO: it's easier to just get started with ASDF +;; ( https://lisp-lang.org/learn/writing-libraries ) + (require "cparse") (require "") (defpackage #:cbasic diff --git a/cutil.lisp b/cutil.lisp index 0b569e2..2f10099 100644 --- a/cutil.lisp +++ b/cutil.lisp @@ -1,11 +1,14 @@ (defpackage #:cutil - (:use #:common-lisp) + (:use #:common-lisp :closer-mop) (:export #:)) (in-package #:cutil) -(defclass () ()) +(defclass (standard-class) ()) (defmethod make-instance ((self ) &key) - (error "Cannot instantiate abstract class ~A" (class-name c))) + (error "Cannot instantiate abstract class ~A" (class-name self))) +(defmethod closer-mop:validate-superclass ((class ) + (superclass standard-class)) + t) (provide "cutil") -- cgit 1.4.1-2-gfad0 From 84d897e941a679529d4f00ea5952196c40656b5f Mon Sep 17 00:00:00 2001 From: Darren Bane Date: Mon, 12 Oct 2020 00:52:56 +0100 Subject: Trying to get cbasic.lisp to compile; WIP --- cabs-syn.lisp | 7 ++++--- cbasic.lisp | 15 ++++++++++----- clex.lisp | 16 ++++++++-------- cparse.lisp | 5 ++--- cutil.lisp | 11 +++++++++-- doc/breaking_rules.md | 2 +- 6 files changed, 34 insertions(+), 22 deletions(-) diff --git a/cabs-syn.lisp b/cabs-syn.lisp index 2b6d30a..60b1a65 100644 --- a/cabs-syn.lisp +++ b/cabs-syn.lisp @@ -30,11 +30,11 @@ (defclass () ((var :accessor var))) (defclass () ((str :accessor str))) -(defclass () ((op :accessor op) (exp :accessor exp))) +(defclass () ((op :accessor op) (expr :accessor expr))) (defclass () ((exp1 :accessor exp1) (op :accessor op) (exp2 :accessor exp2))) (defclass () () (:metaclass )) -(defclass () ((rem :accessor rem))) +(defclass () ((remark :accessor remark))) (defclass () ((goto :accessor goto))) (defclass () ((expr :accessor expr))) (defclass () ((var :accessor var))) @@ -54,7 +54,8 @@ ((not) 1) ((uminus) 7))) -(defun priority-binop (bin-op (cond ((member bin-op '(mult div)) 6) +(defun priority-binop (bin-op) + (cond ((member bin-op '(mult div)) 6) ((member bin-op '(plus minus)) 5) ((eql bin-op 'mod) 4) ((member bin-op '(equal less lesseq great greateq diff)) 3) diff --git a/cbasic.lisp b/cbasic.lisp index 5183859..0f2d63c 100644 --- a/cbasic.lisp +++ b/cbasic.lisp @@ -2,7 +2,7 @@ ;;; initially following the design of ;;; https://caml.inria.fr/pub/docs/oreilly-book/html/book-ora058.html ;;; then later I can optimise following -;;; https://github.com/Henry/BuddKaminInterpreters and +;;; https://github.com/Henry/BuddKaminInterpreters and *maybe* ;;; https://oleksandrmanzyuk.wordpress.com/2014/06/18/from-object-algebras-to-finally-tagless-interpreters-2/ ;;; ;;; A BASIC interpreter already exists at @@ -12,14 +12,19 @@ ;; Because this is the main package, ;; 1) ql:quickload QuickLisp dependencies and +(ql:quickload "closer-mop") ;; 2) load local dependencies here. (load "cutil.lisp") +(load "cabs-syn.lisp") +(load "clex.lisp") (load "cparse.lisp") +;; ;; Use require & defpackage in each package from then on. ;; NB: must have no circular dependencies, and topologically sort the loads. ;; -;; TODO: it's easier to just get started with ASDF +;; TODO: is it easier to just get started with ASDF? ;; ( https://lisp-lang.org/learn/writing-libraries ) +;; Although this is beyond OpenLisp. (require "cparse") (defpackage #:cbasic @@ -32,7 +37,7 @@ ;;; but try to keep the number of top-level functions the same as in OCaml. (defun one-command (st) - (format (standard-output) "> ") + (format *standard-output* "> ") (with-handler #'error-handler (let ((l (parse (read-line)))) (case (car l) @@ -47,8 +52,8 @@ (defun main () (catch 'end (lambda () - (format (standard-output) "BASIC version 0.1~%~%") + (format *standard-output* "BASIC version 0.1~%~%") (for ((st (create (class )))) (catch 'error (one-command st))))) - (format (standard-output) "See you later...~%")) + (format *standard-output* "See you later...~%")) (provide "cbasic") diff --git a/clex.lisp b/clex.lisp index 3ce6aaa..442f1cd 100644 --- a/clex.lisp +++ b/clex.lisp @@ -1,5 +1,5 @@ (defpackage #:clex - (:use #:common-lisp #:util) + (:use #:common-lisp #:cutil) (:export #: #: @@ -10,27 +10,27 @@ (defclass () () (:metaclass )) (defclass () ((int :reader int))) (defclass () ((ident :reader ident))) -(defclass () ((symbol :reader symbol))) -(defclass () ((string :reader string))) +(defclass () ((lsymbol :reader lsymbol))) +(defclass () ((lstring :reader lstring))) (defclass () ()) -(defclass () ((string :initarg :s :accessor string) +(defclass () ((lstring :initarg :s :accessor lstring) (current :initform 0 :accessor current) (size :accessor size))) (defmethod initialize-object :after ((self ) initargs) - (setf (size self) (length (str self)))) + (setf (size self) (length (lstring self)))) (defgeneric forward (cl &rest args)) (defmethod forward ((cl ) &rest args) (let ((incr (if (null args) 1 (car args)))) - (setf (curr cl) (+ (curr cl) incr)))) + (setf (current cl) (+ (current cl) incr)))) (defgeneric extract (pred cl)) (defmethod extract (pred (cl )) - (let* ((st (string cl)) + (let* ((st (lstring cl)) (pos (current cl)) (ext (lambda (n) (if (and (< n (size cl)) (pred (elt st n))) @@ -38,7 +38,7 @@ n))) (res (ext pos))) (setf (current cl) res) - (subseq (string cl) pos (- res pos)))) + (subseq (lstring cl) pos (- res pos)))) (defgeneric extract-int (cl)) (defmethod extract-int ((cl )) diff --git a/cparse.lisp b/cparse.lisp index 5c8c6bb..602dc76 100644 --- a/cparse.lisp +++ b/cparse.lisp @@ -5,7 +5,7 @@ (in-package #:cparse) (defclass () () (:metaclass )) -(defclass () ((exp :accessor exp))) +(defclass () ((expr :accessor expr))) (defclass () ((bin-op :accessor bin-op))) (defclass () ((unr-op :accessor unr-op))) (defclass ())) (t (error "Parse error")))) (t (error "Parse error"))))) - - +(provide "cparse") diff --git a/cutil.lisp b/cutil.lisp index 2f10099..e651b11 100644 --- a/cutil.lisp +++ b/cutil.lisp @@ -1,5 +1,5 @@ (defpackage #:cutil - (:use #:common-lisp :closer-mop) + (:use #:common-lisp) (:export #:)) (in-package #:cutil) @@ -7,8 +7,15 @@ (defclass (standard-class) ()) (defmethod make-instance ((self ) &key) (error "Cannot instantiate abstract class ~A" (class-name self))) + +;;; These are copied from cl-abstract-classes in Quicklisp. +;;; It turns out you do need both. +;;; Maybe someday I'll understand why :-) (defmethod closer-mop:validate-superclass ((class ) - (superclass standard-class)) + (superclass cl:standard-class)) + t) +(defmethod closer-mop:validate-superclass ((class cl:standard-class) + (superclass )) t) (provide "cutil") diff --git a/doc/breaking_rules.md b/doc/breaking_rules.md index b8887b3..93e6915 100644 --- a/doc/breaking_rules.md +++ b/doc/breaking_rules.md @@ -78,7 +78,7 @@ Reasons for choosing Common Lisp include: * Although the official ANSI standard is moribund, quasi-standard libaries are recommended on the [awesome list](https://github.com/CodyReichert/awesome-cl), - or [portability layers](https://github.com/CodyReichert/awesome-cl#portability-layers). + or [portability layers](http://portability.cl/). * Contrary to a lot of other languages, it is fairly paradigm-agnostic. At the same time, I want a clean subset of CL, -- cgit 1.4.1-2-gfad0 From 851f5d17ba7f22a54779b04e34bbde2917a2c10d Mon Sep 17 00:00:00 2001 From: Darren Bane Date: Wed, 14 Oct 2020 00:00:23 +0100 Subject: Should have used flet in the lexer --- clex.lisp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/clex.lisp b/clex.lisp index 442f1cd..cdd6025 100644 --- a/clex.lisp +++ b/clex.lisp @@ -32,27 +32,27 @@ (defmethod extract (pred (cl )) (let* ((st (lstring cl)) (pos (current cl)) - (ext (lambda (n) - (if (and (< n (size cl)) (pred (elt st n))) - (ext (+ n 1)) - n))) - (res (ext pos))) - (setf (current cl) res) - (subseq (lstring cl) pos (- res pos)))) + (res nil)) + (labels ((ext (n) + (if (and (< n (size cl)) (funcall pred (elt st n))) + (ext (+ n 1)) + n))) + (setq res (ext pos)) + (setf (current cl) res) + (subseq (lstring cl) pos (- res pos))))) (defgeneric extract-int (cl)) (defmethod extract-int ((cl )) - ;; TODO: flet? - (let ((is-int (lambda (x) - (and (char>= x #\0) (char<= x #\9))))) - (convert (extract is-int cl) ))) + (flet ((is-int (x) + (and (char>= x #\0) (char<= x #\9)))) + (parse-integer (extract #'is-int cl)))) (defgeneric extract-ident (cl)) (defmethod extract-ident ((cl )) - (let ((is-alpha-num (lambda (x) - (or (and (char>= x #\a) (char<= x #\z)) - (and (char>= x #\A) (char<= x #\Z)) - (and (char>= x #\0) (char<= x #\9)) - (char= x #\_))))) - (extract is-alpha-num))) + (flet ((is-alpha-num (x) + (or (and (char>= x #\a) (char<= x #\z)) + (and (char>= x #\A) (char<= x #\Z)) + (and (char>= x #\0) (char<= x #\9)) + (char= x #\_)))) + (extract #'is-alpha-num cl))) (provide "clex") -- cgit 1.4.1-2-gfad0