Giter Site home page Giter Site logo

pcostanza / closer-mop Goto Github PK

View Code? Open in Web Editor NEW
147.0 147.0 20.0 240 KB

Closer to MOP is a compatibility layer that rectifies many of the absent or incorrect CLOS MOP features across a broad range of Common Lisp implementations.

License: MIT License

Common Lisp 100.00%

closer-mop's People

Contributors

attila-lendvai avatar dspearson avatar fittestbits avatar froggey avatar marcoheisig avatar pcostanza avatar robert-strandh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

closer-mop's Issues

closer-mop breaks defclass in LispWorks

In LW, if you are in the C2CL-USER package, then standard-class is closer-mop:standard-class, not cl:standard-class. But defclass is cl:defclass. This means that a form like

(defclass my-class () ())

will create a class whose metaclass is cl:standard-class, not closer-mop:standard-class. Doom pretty rapidly follows: if you define methods on validate-superclass to allow a class whose metaclass is not standard-class to be a subclass or superclass of one which is then this completely fails to do what you expect unless you add suitable metaclass options to all your defclass forms.

This will, I think, be true for any platform where cl:standard-class is not closer-mop:standard-class unless defclass is modified.

A fix for this might be to add a version of defclass something like:

(defmacro defclass (class supers slots &rest options)
  `(cl:defclass ,class ,supers
     ,slots
     ,@(if (assoc ':metaclass options)
           options
         (cons '(:metaclass standard-class) options))))

Default make-method-lambda doesn't add implicit blocks around the method body.

The following code signals "Error: return for unknown block: foo".

(in-package #:closer-common-lisp)

(defclass gf (standard-generic-function)
  ()
  (:metaclass funcallable-standard-class))

(defgeneric foo (x)
  (:generic-function-class gf))

;; This method on MAKE-METHOD-LAMBDA is necessary to suppress the default
;; expansion DEFMETHOD and use the expander from CLOSER-MOP instead.
(defmethod make-method-lambda :before ((gf gf) method lambda env)
  (declare (ignore gf method lambda env)))

(defmethod foo ((x integer))
  (return-from foo x))

It seems closer-mop's expansion of make-method-lambda doesn't add the necessary implicit blocks around the method function body.

irregurality on ABCL

on ABCL, class-slots to a structure-class returns objects of system::defstruct-slot-description , not slot-definition.

LispWorks 8: c2mop:compute-applicable-methods-using-classes's default method specializes wrong class

On lispworks8, c2mop:compute-applicable-methods-using-classes specializes on c2mop:standard-generic-function.
On other platform like SBCL, it specializes on cl:generic-function.

(mapcar (lambda (m)
          (mapcar #'class-name (c2mop:method-specializers m)))
        (c2mop:generic-function-methods #'c2mop:compute-applicable-methods-using-classes))

on lispworks8
โ†’ ((c2mop:standard-generic-function t))

on sbcl
โ†’ ((cl:generic-function t))

IMHO (c2mop:compute-applicable-methods-using-classes cl:generic-function) is more natural and portable like other platforms.

compute-effective-method-function does not expand implementation-specific macros

I think that it is a problem with SBCL (I've contacted devs on IRC about that), but it won't hurt to mention the issue here, especially that it directly affects CLOSER-MOP.

SBCL except from call-method and make-method introduces another local macro check-applicable-keywords. The effective method combination, when the generic function has keyword arguments, constructs the effective method (when there is only one primary method) as:

           ;; By returning a single call-method `form' here we enable
           ;; an important implementation-specific optimization; that
           ;; is, we can use the fast method function directly as the
           ;; effective method function.
           ;;
           ;; However, the requirement by ANSI (CLHS 7.6.5) on generic
           ;; function argument checking inhibits this, as we don't
           ;; perform this checking in fast-method-functions given
           ;; that they are not solely used for effective method
           ;; functions, but also in combination, when they should not
           ;; perform argument checks.
           (let ((call-method
                  `(call-method ,(first (primary)) ,(rest (primary)))))
             (if (gf-requires-emf-keyword-checks generic-function)
                 (multiple-value-bind (valid-keys keyargs-start)
                     (compute-applicable-keywords generic-function applicable-methods)
                   `(let ((.valid-keys. ',valid-keys)
                          (.keyargs-start. ',keyargs-start))
                      (check-applicable-keywords)
                      ,call-method))
                 call-method))

... see the function sb-pcl::standard-compute-effective-method for details.

The issue is that CLOSER-MOP calls (call-next-method) in make-method-lambda to get the effective method body, and then expands it in a different environment than SBCL (providing its own versions of call-method and make-method), which defines check-applicable-keywords to expand to (check-applicable-keywords .valid-keys. .keyargs-start. darg1 darg2), so when the effective method is called, there is a runtime error that the function is called with 0 arguments instead of 4.

Here's a test case:

(in-package #:cl-user)

(eval-when (:compile-toplevel :load-toplevel :execute)
  (ql:quickload "closer-mop"))

(defclass pfft (c2mop:standard-generic-function)
  ()
  (:metaclass c2mop:funcallable-standard-class))

(defmethod c2mop:make-method-lambda
    ((gf pfft) method lambda-expression environment)
  (declare (ignorable method lambda-expression environment))
  (call-next-method))

(defgeneric foobar (a &key b)
  (:generic-function-class pfft)
  (:method (a &key b)
    (print (cons a b))))

(defun runtime-error ()
  (foobar 3))

No applicable method for "compute-applicable-methods-using-classes" for ccl on OSX.

(defclass a () ())
(defclass b () ())

(defparameter *a* (make-instance 'a))
(defparameter *b* (make-instance 'b))

(defgeneric foo (x y))

(defmethod foo (x y)
  'yay!)

This works. Using the built in function in ccl.

(compute-applicable-methods-using-classes (symbol-function 'foo) (list (class-of *a*) (class-of *b*)))

This does not work.

(closer-mop:compute-applicable-methods-using-classes (symbol-function 'foo) (list (class-of *a*) (class-of *b*)))

Going to have a dig into the library later but if someone knows from looking at this a solution is appreciated!

Redefined standard-generic-function.

Hello.
I use Clozure Common Lisp 1.11 and I have found that
method COMPUTE-APPLICABLE-METHODS-USING-CLASSES is defined for (CLOSER-MOP:STANDARD-GENERIC-FUNCTION T), so, for example, calling it with #'PRINT-OBJECT (which is COMMON-LISP:STANDARD-GENERIC-FUNCTION) results in 'Error: There is no applicable method...'

writing a test code

I can work on it, but if you already have a set of testing code, I appreciate it very much

Problem with closer-mop::only-standard-methods.

In my library fast-generic-functions, I create some custom generic functions and methods. These methods use an :around method on make-method-lambda to compute some metadata. However, on CCL, make-method-lambda is never executed for my custom methods.

I tracked the bug down to closer-mop:defmethod. Therein, the function only-standard-methods returns T, which causes closer-mop:defmethod to expand directly into cl:defmethod, which on CCL doesn't call make-method-lambda. If I remove the clause

  ...
  (when (only-standard-methods generic-function)
              (return-from defmethod `(cl:defmethod ,@(cdr form))))
  ...

everything works as expected. Unfortunately, I failed to grasp what only-standard-methods should do, so I cannot submit a proper fix. Any help would be much appreciated.

Documentation and internal symbol exports

Multiple exports from this system are undocumented. Some of them need to be fixed elsewhere, for example CLASSP on SBCL, but some are internal to Closer to MOP, for example, FIX-INITARGS.

Another issue with it is that Closer to MOP reexports an internal SBCL symbol, which is against SBCL guidelines - that symbol may disappear at any moment, breaking Closer to MOP.

Reader functions for method-combination class

I found that I had to define some portability reader methods for method-combination objects. Is this something that closer-mop wants to integrate?

(defgeneric method-combination-type-name (method-combination))
(defgeneric method-combination-options (method-combination))

(defmethod method-combination-type-name ((object method-combination))
  #+sbcl (sb-pcl::method-combination-type-name object)
  #+ccl (ccl::method-combination-name object)
  #+allegro (excl::method-combination-type object)
  #+ecl (mop::method-combination-name object))

(defmethod method-combination-options ((object method-combination))
  #+sbcl (sb-pcl::method-combination-options object)
  #+ccl (ccl::method-combination-options object)
  #+allegro (excl::method-combination-options object)
  #+ecl (mop::method-combination-options object))

slot-boundp-using-class broken in LispWorks 8?

I'm having an issue with SLOT-BOUNDP-USING-CLASS in LispWorks 8.

Here is my code:

(use-package :c2cl)

(defclass ping-response () 
   ((message :initarg :message)))

(setf *inst* (make-instance 'ping-response :message "test"))
(setf *class* (class-of *inst*))

(mapcar (lambda (s) 
                  (slot-boundp-using-class *class* *inst* s)) 
               (class-slots *class*))

Error: The slot #<STANDARD-EFFECTIVE-SLOT-DEFINITION MESSAGE 8010142433> 
is missing from #<PING-RESPONSE 801014487B> 
of class #<COMMON-LISP:STANDARD-CLASS PING-RESPONSE 82C03C074B>), 
when reading the value.

In CLOSER-MOP, there is this definition:

(cl:defmethod slot-boundp-using-class
           ((class standard-class) object (slotd standard-effective-slot-definition))
  (declare (optimize (speed 3) (debug 0) (safety 0)
                     (compilation-speed 0)))
  (slot-boundp-using-class
   (load-time-value (class-prototype (find-class 'cl:standard-class)))
   object
   (slot-definition-name slotd)))

in closer-lispworks.lisp.

When I change the lambda list to

(cl:defmethod slot-boundp-using-class
           ((class cl:standard-class) object (slotd standard-effective-slot-definition))

(adding the cl: package to the class specializer) the error is gone.

I found this issue, which might be related:
#18

Which is why I tried to add the USE-PACKAGE :C2CL but that didn't change anything.

For reference, this issue affects the JZON library, which is how I came to it:
Zulu-Inuoe/jzon#49

I'm sure that I'm doing something wrong here and hope that perhaps someone can give me hint.

Build failure with ECL 21.2.1


;;; Loading "/nix/store/y3fmiqvsmpd2zqnznsgkm1yafak94jvh-disable-debugger.lisp"

;;; Loading #P"/nix/store/n0cyh2wvsjwd012s68dv0w9j14h1bd8m-ecl-21.2.1/lib/ecl-21.2.1/cmp.fasc"

;;; Compiling /nix/store/ingdl8krq7p3mdcvzjf4n07kfw39bf35-lisp-closer-mop-20211209-git/closer-mop-packages.lisp.

;;; Compiling #<input stream /nix/store/ingdl8krq7p3mdcvzjf4n07kfw39bf35-lisp-closer-mop-20211209-git/closer-mop-packages.lisp 0x7ffff783ce60>.

;;; Loading "//build/_nix_store_ingdl8krq7p3mdcvzjf4n07kfw39bf35-lisp-closer-mop-20211209-git_closer-mop-packages.lisp.fasc"

;;; Compiling /nix/store/ingdl8krq7p3mdcvzjf4n07kfw39bf35-lisp-closer-mop-20211209-git/closer-mop-shared.lisp.

;;; Compiling #<input stream /nix/store/ingdl8krq7p3mdcvzjf4n07kfw39bf35-lisp-closer-mop-20211209-git/closer-mop-shared.lisp 0x7ffff6fd0d20>.

;;; Loading "//build/_nix_store_ingdl8krq7p3mdcvzjf4n07kfw39bf35-lisp-closer-mop-20211209-git_closer-mop-shared.lisp.fasc"

;;; Compiling /nix/store/ingdl8krq7p3mdcvzjf4n07kfw39bf35-lisp-closer-mop-20211209-git/closer-ecl.lisp.

;;; Compiling #<input stream /nix/store/ingdl8krq7p3mdcvzjf4n07kfw39bf35-lisp-closer-mop-20211209-git/closer-ecl.lisp 0x7ffff6f0a8c0>.

;;; Loading "//build/_nix_store_ingdl8krq7p3mdcvzjf4n07kfw39bf35-lisp-closer-mop-20211209-git_closer-ecl.lisp.fasc"

;;;

;;; Compiling /nix/store/ingdl8krq7p3mdcvzjf4n07kfw39bf35-lisp-closer-mop-20211209-git/closer-mop-packages.lisp.

;;; OPTIMIZE levels: Safety=2, Space=0, Speed=3, Debug=0

;;;

;;; End of Pass 1.

;;; Finished compiling /nix/store/ingdl8krq7p3mdcvzjf4n07kfw39bf35-lisp-closer-mop-20211209-git/closer-mop-packages.lisp.

;;;

;;;

;;; Compiling /nix/store/ingdl8krq7p3mdcvzjf4n07kfw39bf35-lisp-closer-mop-20211209-git/closer-mop-shared.lisp.

;;; OPTIMIZE levels: Safety=2, Space=0, Speed=3, Debug=0

;;;

;;; Compiling (DEFUN REQUIRED-ARGS ...).

;;; Compiling (DEFUN ENSURE-FINALIZED ...).

;;; Compiling (DEFUN SUBCLASSP ...).

;;; Compiling (DEFCLASS STANDARD-GENERIC-FUNCTION ...).

;;; Compiling (DEFUN COMPUTE-ARGUMENT-ORDER ...).

;;; Compiling (DEFUN PARSE-METHOD-BODY ...).

;;; Compiling (DEFUN BLOCK-NAME ...).

;;; Internal error:

;;;   in file closer-mop-shared.lisp, position 2299

;;;   at (DEFUN BLOCK-NAME ...)

;;;   ** In function CAR, the value of the only argument is

;;;   0

;;; which is not of the expected type CONS

Darcs repository - dates

I see that Closer to MOP was converted from a darcs repository, 4692dc1

Do you perhaps have that repository anywhere? I am looking for its commit history and the date of the first commit.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.