Christophe Weblog Wiki Code Publications Music
comments and figure from Jan
authorChristophe Rhodes <csr21@cantab.net>
Thu, 6 Feb 2014 08:11:59 +0000 (08:11 +0000)
committerChristophe Rhodes <csr21@cantab.net>
Thu, 6 Feb 2014 08:11:59 +0000 (08:11 +0000)
els-specializers.org
figures/dispatch-comparison.pdf [new file with mode: 0644]
figures/dispatch-comparison.svg [new file with mode: 0644]

index 6af13922e89061170f1e4e46ca20a85379664924..d9b66cf7c23e3d83e68274bf46a2a631e33fba54 100644 (file)
   Paepke; AMOP?].  XXX include typical examples of MOP: object
   persistence; maybe ref. Kizcales "MOPs: why we want them and what
   else they can do"? (Fig. 2 in that is good) ORMs; sparse slots.
   Paepke; AMOP?].  XXX include typical examples of MOP: object
   persistence; maybe ref. Kizcales "MOPs: why we want them and what
   else they can do"? (Fig. 2 in that is good) ORMs; sparse slots.
+  jmoringe:
+  + introspection, e.g. documentation generation
+  + programmatic construction of classes and generic functions
+    e.g. for IDL compilers, model transformations
 
   One area of functionality where there is scope for customization by
   the metaprogrammer is in the mechanics and semantics of method
 
   One area of functionality where there is scope for customization by
   the metaprogrammer is in the mechanics and semantics of method
@@ -59,6 +63,8 @@
   practice implementation support for this was weak until relatively
   recently (ref. closer, also check how ContextL and filtered dispatch
   are implemented).
   practice implementation support for this was weak until relatively
   recently (ref. closer, also check how ContextL and filtered dispatch
   are implemented).
+  jmoringe: filtered dispatch uses a custom method combination, i
+  think
 
   Another potential mechanism for customizing dispatch is implicit in
   the class structure defined by AMOP: standard specializer objects
 
   Another potential mechanism for customizing dispatch is implicit in
   the class structure defined by AMOP: standard specializer objects
   (ahem) the return value of =class-of=, and allows the metaprogrammer
   to hook into cacheing schemes to avoid needless recomputation of
   effective methods for sufficiently similar generic function
   (ahem) the return value of =class-of=, and allows the metaprogrammer
   to hook into cacheing schemes to avoid needless recomputation of
   effective methods for sufficiently similar generic function
-  arguments.
+  arguments (See Figure\nbsp\ref{fig:dispatch}).
+
+  #+CAPTION:    Dispatch Comparison
+  #+LABEL:      fig:dispatch
+  #+ATTR_LATEX: width=0.9\linewidth float
+  [[file:figures/dispatch-comparison.pdf]]
 
   The remaining sections in this paper can be read in any order.  We
   give some motivating examples in section XX, including
 
   The remaining sections in this paper can be read in any order.  We
   give some motivating examples in section XX, including
 (defmethod specializer-accepts-p ((s cons-specializer) o)
   (and (consp o) (eql (car o) (%car s))))
 
 (defmethod specializer-accepts-p ((s cons-specializer) o)
   (and (consp o) (eql (car o) (%car s))))
 
-#| less interesting methods elided |#
+#| less interesting methods elided: jmoringe: (un)parsing, specializer<?, more? |#
 
 #| XXX insert motivating example from Newton/Rhodes here |#
 #+end_src
 
 #| XXX insert motivating example from Newton/Rhodes here |#
 #+end_src
    specializer could be applicable to any given argument)
 
    Also of interest: note that we can have these
    specializer could be applicable to any given argument)
 
    Also of interest: note that we can have these
-   specializer/generalizers handle arbitrary objects: the string and
-   tbnl:request methods are independent of each other; this
+   specializer/generalizers handle arbitrary objects: the =string= and
+   =tbnl:request= methods are independent of each other; this
    generalizes to dealing with multiple web server libraries.
    generalizes to dealing with multiple web server libraries.
+
+   jmoringe: the name =accept-specializer=, while sensible, may
+   confusing in this context because "accept" occurs as part of the
+   protocol with a different semantic.
+
 #+begin_src lisp
 (defclass accept-specializer (extended-specializer)
   ((media-type :initarg :media-type :reader media-type)))
 #+begin_src lisp
 (defclass accept-specializer (extended-specializer)
   ((media-type :initarg :media-type :reader media-type)))
    (next :initarg :next :reader next)))
 (defmethod generalizer-equal-hash-key
     ((gf accept-generic-function) (g accept-generalizer))
    (next :initarg :next :reader next)))
 (defmethod generalizer-equal-hash-key
     ((gf accept-generic-function) (g accept-generalizer))
-  `(accept-generalizer ,(header g)))
+   `(accept-generalizer ,(header g)))
 (defmethod specializer-accepts-generalizer-p ((gf accept-generic-function) (s acc
 ept-specializer) (generalizer accept-generalizer))
   (values (q (media-type s) (tree generalizer)) t))
 (defmethod specializer-accepts-generalizer-p ((gf accept-generic-function) (s acc
 ept-specializer) (generalizer accept-generalizer))
   (values (q (media-type s) (tree generalizer)) t))
@@ -235,12 +251,18 @@ est))
 (defmethod specializer-accepts-p ((s accept-specializer) (string string))
   (q (media-type s) (parse-accept-string string)))
 #+end_src
 (defmethod specializer-accepts-p ((s accept-specializer) (string string))
   (q (media-type s) (parse-accept-string string)))
 #+end_src
+
+   jmoringe: The role of =accept-generalizer.tree= and the =q=
+   function are hard to understand and may require some
+   explanation. However, the example with its distinct, asymmetric
+   specializers/generalizers, =accept-generalizer.next= and
+   =specializer<= is likely worth it.
+
 ** Pattern / xpattern / regex / optima
    Here's the /really/ interesting bit, but on the other hand we're
    probably going to run out of space, and the full description of
 ** Pattern / xpattern / regex / optima
    Here's the /really/ interesting bit, but on the other hand we're
    probably going to run out of space, and the full description of
-   these is going to take us into make-method-lambda territory.  A
-   second paper?  Future work?  It would be really nice to put a
-   marker in the sand.
+   these is going to take us into =make-method-lambda= territory.
+   A second paper?  Future work?
 * Protocol
 ** Generalizer
    - [ ] =generalizer-of-using-class= (NB class of gf not class of object)
 * Protocol
 ** Generalizer
    - [ ] =generalizer-of-using-class= (NB class of gf not class of object)
@@ -249,12 +271,41 @@ est))
    - [ ] =specializer-accepts-generalizer-p=
    - [ ] =specializer-accepts-p=
    - [ ] =specializer<=
    - [ ] =specializer-accepts-generalizer-p=
    - [ ] =specializer-accepts-p=
    - [ ] =specializer<=
+     jmoringe: If I remember correctly, closette has
+     =method-more-specific-p= should we aim for parity with that and
+     use =specializer-more-specific-p=? The downside would be that
+     =-p= indicates a Boolean return value which is not the case here.
 ** Full protocol
    Description and specification left for reasons of space (we'll see?)
    - [ ] =same-specializer-p=
    - [ ] =parse/unparse-specializer-using-class=
    - [ ] =make-method-specializers-form=
 ** Full protocol
    Description and specification left for reasons of space (we'll see?)
    - [ ] =same-specializer-p=
    - [ ] =parse/unparse-specializer-using-class=
    - [ ] =make-method-specializers-form=
+   - [ ] jmoringe: In an email, I suggested
+     =make-specializer-form-using-class=:
+
+     #+begin_quote
+     Could we change =make-method-specializers-form='s default
+     behaviour to call a new generic function
+     #+begin_src
+       make-specializer-form-using-class gf method name env
+     #+end_src
+     with builtin methods on =sb-mop:specializer=, =symbol=, =cons= (for
+     eql-specializers)? This would make it unnecessary to repeat
+     boilerplate along the lines of
+     #+begin_src lisp
+     (flet ((make-parse-form (name)
+              (if <name-is-interesting>
+                <handle-interesting-specializer>
+                <repeat-handling-of-standard-specializers>)))
+       `(list ,@(mapcar #'make-parse-form specializer-names)))
+     #+end_src
+     for each generic function class.
+     #+end_quote
    - [ ] =make-method-lambda= revision (use environment arg?)
    - [ ] =make-method-lambda= revision (use environment arg?)
+
+     jmoringe: would only be relevant for pattern dispatch, right? I
+     think, we didn't finish the discussion regarding special
+     variables vs. environment vs. new protocol function
 * Related Work
   - [ ] Newton/Rhodes
   - [ ] filtered dispatch
 * Related Work
   - [ ] Newton/Rhodes
   - [ ] filtered dispatch
diff --git a/figures/dispatch-comparison.pdf b/figures/dispatch-comparison.pdf
new file mode 100644 (file)
index 0000000..9a29d1d
Binary files /dev/null and b/figures/dispatch-comparison.pdf differ
diff --git a/figures/dispatch-comparison.svg b/figures/dispatch-comparison.svg
new file mode 100644 (file)
index 0000000..292c5de
--- /dev/null
@@ -0,0 +1,515 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="856.98193"
+   height="234.33665"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.3.1 r9886"
+   sodipodi:docname="dispatch-comparision.svg">
+  <defs
+     id="defs4">
+    <marker
+       inkscape:stockid="EmptyTriangleInL"
+       orient="auto"
+       refY="0"
+       refX="0"
+       id="EmptyTriangleInL"
+       style="overflow:visible">
+      <path
+         id="path4073"
+         d="m 5.77,0 -8.65,5 0,-10 8.65,5 z"
+         style="fill:#ffffff;fill-rule:evenodd;stroke:#000000;stroke-width:1pt"
+         transform="matrix(-0.8,0,0,-0.8,4.8,0)"
+         inkscape:connector-curvature="0" />
+    </marker>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="0.0"
+     inkscape:pageshadow="2"
+     inkscape:zoom="1"
+     inkscape:cx="647.09412"
+     inkscape:cy="38.998487"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="false"
+     inkscape:snap-global="true"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:window-width="1920"
+     inkscape:window-height="1151"
+     inkscape:window-x="1440"
+     inkscape:window-y="24"
+     inkscape:window-maximized="1" />
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Layer 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(27.665546,-26.452583)">
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+       x="95.253151"
+       y="41.647896"
+       id="text2985"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan2987"
+         x="95.253151"
+         y="41.647896">AMOP Dispatch</tspan></text>
+    <text
+       xml:space="preserve"
+       style="font-size:20px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+       x="514.53345"
+       y="41.647896"
+       id="text2989"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan2991"
+         x="514.53345"
+         y="41.647896">Generalized Dispatch</tspan></text>
+    <g
+       id="g4464">
+      <g
+         transform="translate(385.42857,49.857143)"
+         id="g3801">
+        <rect
+           y="130.79225"
+           x="319.40588"
+           height="28.139849"
+           width="105.2827"
+           id="rect3803"
+           style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+        <text
+           sodipodi:linespacing="125%"
+           id="text3805"
+           y="149.03015"
+           x="332.4613"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           xml:space="preserve"><tspan
+             y="149.03015"
+             x="332.4613"
+             id="tspan3807"
+             sodipodi:role="line">Argument</tspan></text>
+      </g>
+      <g
+         transform="translate(166.92857,-66.642857)"
+         id="g3809">
+        <rect
+           y="130.79225"
+           x="319.40588"
+           height="28.139849"
+           width="105.2827"
+           id="rect3811"
+           style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+        <text
+           sodipodi:linespacing="125%"
+           id="text3813"
+           y="149.03015"
+           x="328.05896"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           xml:space="preserve"><tspan
+             y="149.03015"
+             x="328.05896"
+             id="tspan3815"
+             sodipodi:role="line">Specializer</tspan></text>
+      </g>
+      <g
+         id="g3822"
+         transform="translate(385.92857,-1.642857)">
+        <rect
+           style="fill:none;stroke:#ff0000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect3824"
+           width="105.2827"
+           height="28.139849"
+           x="319.40588"
+           y="130.79225" />
+        <text
+           xml:space="preserve"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           x="325.41833"
+           y="149.03015"
+           id="text3826"
+           sodipodi:linespacing="125%"><tspan
+             sodipodi:role="line"
+             id="tspan3828"
+             x="325.41833"
+             y="149.03015">Generalizer</tspan></text>
+      </g>
+      <g
+         id="g3859"
+         transform="translate(234.42857,-1.642857)">
+        <rect
+           style="fill:none;stroke:#ff0000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect3861"
+           width="105.2827"
+           height="28.139849"
+           x="319.40588"
+           y="130.79225" />
+        <text
+           xml:space="preserve"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           x="329.13708"
+           y="149.03015"
+           id="text3863"
+           sodipodi:linespacing="125%"><tspan
+             sodipodi:role="line"
+             id="tspan3865"
+             x="329.13708"
+             y="149.03015">Gen. Spec.</tspan></text>
+      </g>
+      <g
+         inkscape:connector-avoid="true"
+         id="g3867"
+         transform="translate(170.60223,49.857143)">
+        <rect
+           style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect3869"
+           width="105.2827"
+           height="28.139849"
+           x="319.40588"
+           y="130.79225" />
+        <text
+           xml:space="preserve"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           x="350.93005"
+           y="149.03015"
+           id="text3871"
+           sodipodi:linespacing="125%"><tspan
+             sodipodi:role="line"
+             id="tspan3873"
+             x="350.93005"
+             y="149.03015">Class</tspan></text>
+      </g>
+      <g
+         id="g3875"
+         transform="translate(94.42857,101.35714)">
+        <g
+           id="g3897">
+          <rect
+             y="130.79225"
+             x="319.40588"
+             height="28.139849"
+             width="105.2827"
+             id="rect3877"
+             style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+          <text
+             sodipodi:linespacing="125%"
+             id="text3879"
+             y="149.03015"
+             x="334.84802"
+             style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+             xml:space="preserve"><tspan
+               y="149.03015"
+               x="334.84802"
+               id="tspan3881"
+               sodipodi:role="line">Eql-Spec.</tspan></text>
+        </g>
+      </g>
+      <path
+         inkscape:connection-end-point="d4"
+         inkscape:connection-end="#g3859"
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3822"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="polyline"
+         id="path3883"
+         d="m 705.33445,143.21932 -46.2173,0"
+         style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
+      <path
+         inkscape:connection-end-point="d4"
+         inkscape:connection-end="#g3801"
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3822"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="orthogonal"
+         id="path3885"
+         d="m 757.9758,157.28924 0,23.36015"
+         style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+      <path
+         inkscape:connection-end-point="d4"
+         inkscape:connection-end="#g3801"
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3875"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="orthogonal"
+         id="path3887"
+         d="m 519.11715,246.21932 235.35865,0 c 1.5,0 3,-1.5 3,-3 l 0,-34.43008"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+      <path
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3867"
+         inkscape:connection-end-point="d4"
+         inkscape:connection-end="#g3801"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="orthogonal"
+         id="path3889"
+         d="m 595.29081,194.71932 109.54364,0"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline" />
+      <path
+         inkscape:connection-end-point="d4"
+         inkscape:connection-end="#g3867"
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3809"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="orthogonal"
+         id="path3891"
+         d="m 542.64946,92.289243 0,88.360147"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#EmptyTriangleInL)" />
+      <path
+         inkscape:connection-end="#g3875"
+         inkscape:connection-end-point="d4"
+         sodipodi:nodetypes="cssc"
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3809"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="orthogonal"
+         id="path3893"
+         d="m 486.33445,78.219319 -16.85865,0 c -1.5,0 -3,1.5 -3,3 l 0,150.930071"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#EmptyTriangleInL)" />
+      <path
+         inkscape:connection-end-point="d4"
+         inkscape:connection-end="#g3859"
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g3809"
+         inkscape:connector-curvature="3"
+         inkscape:connector-type="orthogonal"
+         id="path3895"
+         d="m 591.61715,78.219319 11.85865,0 c 1.5,0 3,1.5 3,3 l 0,47.930071"
+         style="fill:none;stroke:#ff0000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#EmptyTriangleInL)" />
+      <text
+         sodipodi:linespacing="125%"
+         id="text3902"
+         y="191.86218"
+         x="610.5"
+         style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+         xml:space="preserve"><tspan
+           y="191.86218"
+           x="610.5"
+           id="tspan3904"
+           sodipodi:role="line">match class-of</tspan></text>
+      <text
+         sodipodi:linespacing="125%"
+         id="text3906"
+         y="243.36218"
+         x="615.5"
+         style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+         xml:space="preserve"><tspan
+           y="243.36218"
+           x="615.5"
+           id="tspan3908"
+           sodipodi:role="line">match</tspan></text>
+      <text
+         sodipodi:linespacing="125%"
+         id="text3910"
+         y="139.36218"
+         x="664.5"
+         style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+         xml:space="preserve"><tspan
+           y="139.36218"
+           x="664.5"
+           id="tspan3912"
+           sodipodi:role="line">s-a-g-p</tspan></text>
+      <text
+         sodipodi:linespacing="125%"
+         id="text3914"
+         y="172.36218"
+         x="760"
+         style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#ff0000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+         xml:space="preserve"><tspan
+           y="172.36218"
+           x="760"
+           id="tspan3916"
+           sodipodi:role="line">generalizer-of</tspan></text>
+    </g>
+    <g
+       id="g4506">
+      <g
+         id="g4364"
+         transform="translate(-55.57143,49.857143)">
+        <rect
+           style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect4366"
+           width="105.2827"
+           height="28.139849"
+           x="319.40588"
+           y="130.79225" />
+        <text
+           xml:space="preserve"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           x="332.4613"
+           y="149.03015"
+           id="text4368"
+           sodipodi:linespacing="125%"><tspan
+             sodipodi:role="line"
+             id="tspan4370"
+             x="332.4613"
+             y="149.03015">Argument</tspan></text>
+      </g>
+      <g
+         id="g4372"
+         transform="translate(-308.4846,-66.642857)">
+        <rect
+           style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+           id="rect4374"
+           width="105.2827"
+           height="28.139849"
+           x="319.40588"
+           y="130.79225" />
+        <text
+           xml:space="preserve"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           x="328.05896"
+           y="149.03015"
+           id="text4376"
+           sodipodi:linespacing="125%"><tspan
+             sodipodi:role="line"
+             id="tspan4378"
+             x="328.05896"
+             y="149.03015">Specializer</tspan></text>
+      </g>
+      <g
+         transform="translate(-270.39777,49.857143)"
+         id="g4396"
+         inkscape:connector-avoid="true">
+        <rect
+           y="130.79225"
+           x="319.40588"
+           height="28.139849"
+           width="105.2827"
+           id="rect4398"
+           style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+        <text
+           sodipodi:linespacing="125%"
+           id="text4400"
+           y="149.03015"
+           x="350.93005"
+           style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+           xml:space="preserve"><tspan
+             y="149.03015"
+             x="350.93005"
+             id="tspan4402"
+             sodipodi:role="line">Class</tspan></text>
+      </g>
+      <g
+         transform="translate(-346.57143,101.35714)"
+         id="g4404">
+        <g
+           id="g4406">
+          <rect
+             style="fill:none;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+             id="rect4408"
+             width="105.2827"
+             height="28.139849"
+             x="319.40588"
+             y="130.79225" />
+          <text
+             xml:space="preserve"
+             style="font-size:16px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+             x="334.84802"
+             y="149.03015"
+             id="text4410"
+             sodipodi:linespacing="125%"><tspan
+               sodipodi:role="line"
+               id="tspan4412"
+               x="334.84802"
+               y="149.03015">Eql-Spec.</tspan></text>
+        </g>
+      </g>
+      <path
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+         d="m 78.117153,246.21932 235.358647,0 c 1.5,0 3,-1.5 3,-3 l 0,-34.43008"
+         id="path4418"
+         inkscape:connector-type="orthogonal"
+         inkscape:connector-curvature="3" />
+      <path
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;display:inline"
+         d="m 154.29081,194.71932 109.54364,0"
+         id="path4420"
+         inkscape:connector-type="orthogonal"
+         inkscape:connector-curvature="3" />
+      <path
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g4372"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#EmptyTriangleInL);display:inline"
+         d="m 101.64946,92.289243 0,88.360147"
+         id="path4422"
+         inkscape:connector-type="orthogonal"
+         inkscape:connector-curvature="3" />
+      <path
+         inkscape:connection-start-point="d4"
+         inkscape:connection-start="#g4372"
+         style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;marker-start:url(#EmptyTriangleInL);display:inline"
+         d="m 25.4758,92.289243 0,139.860147"
+         id="path4424"
+         inkscape:connector-type="orthogonal"
+         inkscape:connector-curvature="3"
+         sodipodi:nodetypes="cssc" />
+      <text
+         xml:space="preserve"
+         style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+         x="169.5"
+         y="191.86218"
+         id="text4428"
+         sodipodi:linespacing="125%"><tspan
+           sodipodi:role="line"
+           id="tspan4430"
+           x="169.5"
+           y="191.86218">match class-of</tspan></text>
+      <text
+         xml:space="preserve"
+         style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+         x="174.5"
+         y="243.36218"
+         id="text4432"
+         sodipodi:linespacing="125%"><tspan
+           sodipodi:role="line"
+           id="tspan4434"
+           x="174.5"
+           y="243.36218">match</tspan></text>
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-size:10px;font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;text-align:start;line-height:125%;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans;-inkscape-font-specification:Sans"
+       x="659.33447"
+       y="68.789238"
+       id="text4533"
+       sodipodi:linespacing="125%"><tspan
+         sodipodi:role="line"
+         id="tspan4535"
+         x="659.33447"
+         y="68.789238">specializer-accepts-generalizer-p</tspan></text>
+    <path
+       style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+       d="M 714,46.336655 704,106.33665"
+       id="path4537"
+       inkscape:connector-curvature="0"
+       transform="translate(-27.665546,26.452583)" />
+  </g>
+</svg>