Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make Interfaces/ Open Exhaustion #63

Open
mariari opened this issue Feb 13, 2023 · 2 comments
Open

Make Interfaces/ Open Exhaustion #63

mariari opened this issue Feb 13, 2023 · 2 comments
Assignees
Labels
static-analysis Static Analysis tools tooling

Comments

@mariari
Copy link
Member

mariari commented Feb 13, 2023

Problem

Currently we have a fairly good exhaustion system for geb

(defmethod dom ((x <substmorph>))
  (assure substobj
    (typecase-of substmorph x
      (init         so0)
      (terminal     (obj x))
      (alias        (dom (obj x)))
      (substobj     x)
      (inject-left  (mcar x))
      (inject-right (mcadr x))
      (comp         (dom (mcadr x)))
      (pair         (dom (mcar x)))
      (distribute   (prod (mcar x) (coprod (mcadr x) (mcaddr x))))
      (case         (coprod (dom (mcar x)) (dom (mcadr x))))
      ((or project-right
           project-left)
       (prod (mcar x) (mcadr x)))
      (otherwise
       (subclass-responsibility x)))))

where exhaustion is checked at macro expansion time..

However the subclass-responsiblity is not really enforced. We can have an open extension to <substmorph>. For which we don't care about implementing all the interfaces, but some core subset of features. Like we may care about visualizing a particular extension, but we don't support some feature like metadata

Thus I propose the following

Proposal

We should implement the following interface

(definterface <name> <method-name>*)

(implements <class-name> <interface-tuple>*)

interface-tuple ::= interface-name | (interface-name :subclasses) | (interface-name :self)

(subclasses <class-name> <class-name>)

(pledge <class-name> <pledge-tuple>*)

(subclasses-must-pledge <class-name> <interface>*)

pledge-tuple ::= interface-name | (interface-name :self) | (interface-name :superclass)

(pledge-ignore <class-name> <tuple-name>*)

(missing-interfaces <class-name>)
(missing-methods <class-name> <interface>)

With this, we can define out an interface, saying we implement some set of methods. A class implements the interface if it properly fulfills the interface either by implementing it itself or relying on the superclass to do the work.

The pledge function is not strictly needed, as these interfaces can be put in the inheritance list of the class at class creation time, and we can compute later based on the subclass who has pledge to implement what interfaces.

If a class subclasses another one, we can check if the interface is fulfilled, if the interface covers it's subclasses, or is pledged to have it filled by the superclass, then we can remove it from the checked list.

This culminates in the missing-inteface/missing-methods api which tells us how many we are missing.

If we are missing a pledged system, we will get an error instead of a warning for the methods we've pledged.

This should make it easy to see what methods are not exhaustive in the open extension case.

CL is a multiple dispatch system, so we will only check a single specifier works as intended. If more are needed, then an extension to this system should be had

Implementing

The implementation work of this should be somewhat easy. Thanks to the MOP, we can do things like

(c2mop:specializer-direct-methods (find-class 'alias))

(c2mop:generic-function-methods #'geb-gui.graphing::graphize)

These methods should allow us to determine the applicability of methods.

Further we may be able to remove subclasses or rather we should be able to build some of this implicitly.

Further we should make these mixins and likely stealth-mixins if we declare it later.

@mariari mariari self-assigned this Feb 13, 2023
@mariari mariari added static-analysis Static Analysis tools tooling labels Feb 13, 2023
@rokopt
Copy link
Member

rokopt commented May 9, 2023

Can this be closed as fixed by #64 with #87 open for follow-up enhancements?

@mariari
Copy link
Member Author

mariari commented May 9, 2023

no, I don't see how we have the API filled in here at all. This issue proposes a generic system for interfaces in CL and catching when methods are missing

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
static-analysis Static Analysis tools tooling
Projects
None yet
Development

No branches or pull requests

2 participants