From 398232195fe2dd9788c8c0b4437c7ac72a39007c Mon Sep 17 00:00:00 2001 From: colin Date: Thu, 18 Apr 2024 22:47:06 -0700 Subject: initial commit --- obwyn.lisp | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 obwyn.lisp (limited to 'obwyn.lisp') diff --git a/obwyn.lisp b/obwyn.lisp new file mode 100644 index 0000000..db2f778 --- /dev/null +++ b/obwyn.lisp @@ -0,0 +1,109 @@ +(defpackage #:obwyn + (:use #:cl) + (:local-nicknames + (#:a #:alexandria-2))) + +(in-package :obwyn) + +(defun values-binding-p (form) + #+testiere + (:tests + (:is (values-binding-p 'a)) + (:is (values-binding-p '(a b))) + (:is (values-binding-p '())) + (:is (not (values-binding-p :x))) + (:is (not (values-binding-p '(a b 4)))) + (:is (not (values-binding-p '(a :b 4))))) + (or (and (symbolp form) + (not (keywordp form))) + (and (listp form) + (every (a:conjoin #'symbolp (complement #'keywordp)) form)))) + +(defun destructuring-bind-list-p (form) + #+testiere + (:tests + (:is (destructuring-bind-list-p '())) + (:is (destructuring-bind-list-p '(a b))) + (:is (destructuring-bind-list-p '(a &rest b))) + (:is (destructuring-bind-list-p '(a &rest b &key (x 10) y))) + (:is (destructuring-bind-list-p '(&optional a b))) + (:is (not (destructuring-bind-list-p 'x))) + (:is (not (destructuring-bind-list-p '(&rest x &optional y)))) + (:is (not (destructuring-bind-list-p '(&rest 10 &optional y))))) + (and (listp form) + (ignore-errors + (multiple-value-bind (required optional rest kwargs allow-other aux keyp) + (alexandria:parse-ordinary-lambda-list form) + (declare (ignorable required optional rest kwargs keyp)) + (not (or allow-other aux)))))) + +(defun expand-clauses (clauses) + (loop :with expanded := nil + :for (tag bindings form) :in (nreverse clauses) + :do + (setf expanded + (ecase tag + (:simple + (cond ((null expanded) form) + ((eq 'cl:progn (first expanded)) + `(progn ,form ,@(rest expanded))) + (t + `(progn ,form ,expanded)))) + (:multiple-value-bind + `(multiple-value-bind + ,(if (listp bindings) bindings (list bindings)) + ,form + ,@(if (and (listp expanded) (eq 'cl:progn (first expanded))) + (rest expanded) + (list expanded)))) + (:destructuring-bind + `(destructuring-bind ,bindings ,form + ,@(if (and (listp expanded) (eq 'cl:progn (first expanded))) + (rest expanded) + (list expanded)))))) + :finally (return + (if (and (listp expanded) (eq 'cl:progn (first expanded))) + `(block nil ,@(rest expanded)) + `(block nil ,expanded))))) + + +(defun literals-equal (a b) + (and (symbolp a) (symbolp b) (string-equal a b))) + +(argot:deflanguage >>> (:literals= #'literals-equal) + ( + :match (:seq (:* ) (:eof)) + :then (expand-clauses (first ))) + + ( + :match (:or + + )) + + ( + :match (:seq (:= :<-) (:item)) + :then (destructuring-bind (bindings _ form) + (declare (ignore _)) + (list :multiple-value-bind bindings form))) + + ( + :match (:item) + :if values-binding-p + :note "Either a symbol or a list suitable for passing to MULTIPLE-VALUE-BIND") + + ( + :match (:seq (:= :<~) (:item)) + :then (destructuring-bind (bindings _ form) + (declare (ignore _)) + (list :destructuring-bind bindings form))) + + ( + :match (:item) + :if destructuring-bind-list-p + :note "An list that might be passed as the first argument to DESTRUCTURING-BIND.") + + ( + :match (:@ simple (:item)) + :if (not (member simple '(:<~ :<-))) + :then (list :simple nil simple))) + -- cgit v1.2.3