From: Kim Nguyễn Date: Sun, 12 Apr 2015 15:33:04 +0000 (+0200) Subject: . X-Git-Url: http://git.nguyen.vg/gitweb/?p=hacks%2FsimpleWebSlides.git;a=commitdiff_plain;h=606df47f18f6e5e96e43f770d6d2727c736b69fc . --- diff --git a/pres-esop15/01.xhtml b/pres-esop15/01.xhtml new file mode 100644 index 0000000..845513e --- /dev/null +++ b/pres-esop15/01.xhtml @@ -0,0 +1,672 @@ + +∈"> + ∉"> + + + + + + + + + + + + + + + + + + ⟦" > + ⟧" > + + L" > + R"> + + + + + + +] + > + + + A Core Calculus for XQuery 3.0 + + + + + + + + + + + + + + + + + + + + +
+

A Core Calculus for XQuery 3.0

+

Combining Navigational and Pattern-Matching Approaches

+
+ + + + + + + + + +
Giuseppe Castagna1Hyeonseung Im2
Kim Nguyễn3Véronique Benzaken3
+
+

+ CNRS, PPS, Université Paris-Diderot, Paris, France
+ Kangwon National University, Chuncheon, Rep. of Korea
+ LRI, Université Paris-Sud, Orsay, France +

+
+
+

XQuery 3.0

+

W3C standard language for querying XML + databases/documents

+ + declare function get_links($page, $print) { + + for $i in $page/descendant::a[not(ancestor::b)] + return print($i) + } + + declare function pretty($link) { + typeswitch($link) + case $l as element(a) + return switch ($l/@class) + case "style1" + return <a href={$l/@href}><b>{$l/text()}</b></a> + default return $l + + default return $link + } + + +
+
+

XQuery 3.0

+ +

It's a pity since XML documents are very precisely + typed (DTD, XMLSchemas)

+

Document type information is validated at runtime rather than + checked statically

+
+
+

&cduce;

+

A polymorphic functional language (ML-style) equipped with + semantic subtyping

+ + + let pretty (<a>_ -> <a>_ & Any\<a>_ &rarrow; Any\<a>_) + + | <a class="style1" href=h ..> l &rarrow; <a href=h>[ <b>l ] + | x &rarrow; x + + + let get_links (page: <_>_) (print: <a>_ -> <a>_) : [ <a>_ * ] = + + match page with + <a>_ & x &rarrow; [ (print x) ] + | < (_\‘b) > l &rarrow; + (transform l with (i & <_>_) &rarrow; get_links i print) + | _ -> [ ] + + + + + + + +
+
+

&cduce;

+ +

Writing functions to traverse documents is painfull

+
+
+

This work

+
    +
  1. Add support for path navigation to + &cduce; + +
  2. +
  3. Perform a type-directed translation from XQuery to + &cduce;
  4. + +
+ +
+
+

&cduce;'s type algebra

+
+    t ::=  b  |  c  |  t × t  |  t &rarrow; t  |  t &lor; t  |  t  &land; t  |  t ∖ t  |  ⊤  |  ⊥  |  α
+
+

b : ranges over basic types (Int, String, …)
+ c : ranges over singleton types + (`A, 42, …)
+ α : type variables
+ types are interpreted co-inductively (recursive types) and regular + expression types
+

+
+    t1 ≡ (Int × t1) &lor; t2
+    t2 ≡ (Bool × t2) &lor; (Bool × `nil)
+
+    t1 ≡ [ Int* Bool+ ]
+
+
+
+
+

Semantic subtyping

+
+t ≤ s   &Lrarrow;   [t] ⊆  [s]
+
+

[ ] interpretation of types as sets of + values
+ Allows to reason modulo semantic equivalence of type connectives : +

+
+      [ Int* (Int | Bool*)? ] &land; [ Int+ (Bool+ | Int)* ] ≡ [Int+ Bool*]
+
+
+
+

&cduce; patterns

+
    p ::=  t  |  p | p  |  p & p  | (p, p) |  x   
+

t ranges over types
+ x ranges over capture variables
+ patterns are also co-inductively interpreted (recursive patterns) +

+

v / p : matching a value against a pattern yields a + substitution from variables to values
+ &lbag; p &rbag; : the set of values accepted by a + pattern is a type
+ t / p : matching a type against a pattern yields a + substitution from variables to types
+

+
+
+

&cduce; patterns (example)

+

Assume l has type [ Int+ Bool* ], consider:

+ + match l with + [ _* (x & Int) Bool* (y & Bool) ] &rarrow; (x, y) + | [ _* (x & Int) ] &rarrow; (x, `false) + | [ ] &rarrow; (0, `false) + +
    +
  1. &lbag;[ _* (x & Int) Bool* (y & Bool) ]&rbag; ≡ [ ⊤* Int Bool+ ]
    + yield : { x ↦ Int, y ↦ Bool } +
  2. +
  3. &lbag;[ _* (x & Int) ]&rbag; ≡ [ ⊤* Int ]
    + yield : { x ↦ Int } +
  4. +
  5. Since [Int+ Bool* ] ∖ ( [ ⊤* Int Bool+ ] &lor; [ ⊤* Int]) ≡ ⊥ + the third case is unreachable. +
  6. + + +
+ +
+
+

&cduce; data-model

+

Sequences are nested pairs: [ v1 … vn ] ≡ (v1, (…, (vn, `nil))) +

+

XML documents are tagged sequences:

<foo>[ v1  … vn ] ≡ (`foo, [ v1  … vn ])
+

+

Ususal lisp-like encoding of trees, how to perform navigation + (including upward ?)

+
+
+

Zippers (1/2)

+ +
 v ::=  …  |  vδ
+ δ ::=  &bcirc;  | &left;v · δ | &right;v · δ
+
+ +
+
+

Zippers (2/2)

+

fst (resp. snd) takes the first (resp. second) + projection of a pair and update its zipper accordingly:

+
    v1 ≡ (1, (2, (3, (4, `nil))))&bcirc;
+    v11 ≡ fst v1 ≡ 1&left;(1, (2, (3, (4, `nil))))&bcirc; · &bcirc; 
+    v2 ≡ snd v1 ≡ (2, (3, (4, `nil)))&right;(1, (2, (3, (4, `nil))))&bcirc; · &bcirc; 
+    v3 ≡ snd v2 ≡ (3, (4, `nil))&right;v2 · &right;v1 · &bcirc; 
+
+

up pops returns the head of the zipper:

+
    up v3 ≡ v2 ≡ (2, (3, (4, `nil)))&right;(1, (2, (3, (4, `nil))))&bcirc; · &bcirc; 
+
+
+
+

Zipper types

+

We extend the type-algebra with zipper types:

+
 t ::=  …  |  tτ
+ τ ::=  &bcirc;  |  &left;t · τ  | &right;t · τ  |  τ &lor; τ  |  τ ∖ τ  |  &ztop;
+
+

&bcirc;: singleton type denoting the empty zipper
+ &ztop;: the top zipper types
+ Zipper types are interpreted co-inductively (regular expressions on + zippers)

+ Int(&left;⊤)* &bcirc;: type of + integers that are the leftmost descendant of a tree.
+ [ […] […] ]]]>&bcirc;: type of + HTML documents
+ [ … ]]]>&ztop;: types of links in any context + +

+
+
+

Tree navigation

+

Since patterns contain types, we can check complex + conditions:

+
+    p ≡ <a>_   &lor;   <_>[ _* p _* ]
+ 
+    τ ≡ &bcirc;   &lor;   &right;⊤ · τ   &lor;   &left;(⊤∖ <b>_) · τ 
+
+
+ + match v with + pτ & x &rarrow; … + | _ &rarrow; … + +

+We want more, namely return all descendants (ancestor, + children, siblings, …) of a node matching a particular condition +

+Remark: (recursive) patterns already perform a recursive traversal + of the value +

+Idea: Piggy back on the traversal and accumulate +nodes in special variables +

+ +
+
+

Operators and Accumulators

+

An operator is a 4-tupple (o, no, + &rleadsto;o, &rarrow;o), where:

+

o: is the accumulator name
+no: is the arity of o
+&rleadsto;o: +&mathV;no &rsarrow; &mathV;, the reduction relation
+&rarrow;o: +&mathT;no &rsarrow; &mathT;, the typing relation
+

+

An accumulator is a variable (ranged over + by ẋ, ẏ, …) with:

+ Op(ẋ): an operator
+ Init(ẋ) ∈ &mathV; : an initial value
+

+
+
+

Some operators

+
+    v, v' &rleadsto;cons, (v, v') 
+ v, `nil &rleadsto;snoc (v, `nil)
+ v, (v',v'') &rleadsto;snoc (v', snoc(v,v''))
+
+

Now we can use accumulators equipped with cons/snoc in + patterns. Instead of matching a single node against a variable, it + accumulates that node in sequence (in reverse or in-order).

+
+
+

Pattern matching semantics (v/p)

+
+  σ; δ ⊢ v / p &rleadsto; γ, σ'
+
+

σ, σ': mapping from accumulators to + values
+ v: input value
+ p: pattern
+ γ: mapping from capture variables to + values
+ δ: current context +

+
+
+ v ∈ [ t ] + σ; δ ⊢ v / t &rleadsto; ∅, + σ +
(type) + +
+ + σ; δ ⊢ v / ẋ &rleadsto; ∅, + σ[ ẋ := Op(ẋ) (vδ, σ(ẋ)) ] +
(acc) + +
+ + σ; δ ⊢ v / x &rleadsto; { x ↦ v }, + σ +
(var) + +
+ σ; &left;v · δ ⊢ (fst v)/p1 + &rleadsto; γ1, σ' + σ'; &right;v · δ ⊢ (snd v)/p2 + &rleadsto; γ2, σ'' + + σ; δ ⊢ v / + (p1, p2) &rleadsto; + γ1∪ γ2, + σ'' +
(pair) +… and some other rules for alternation, failure, recursion, etc. +
+
+
+

Typing of patterns (with accumulators) 1/2

+

Well known that typing path expressions escapes regular tree languages + (i.e. &cduce;'s types). Consider: +

+
+      t ≡ <c>[ <a>[] t <b>[] ]    &lor;   <c>[]   anbn
+
+

The set of all a or b labeled + descendants + is { [<a>[]n <b>[]n ] | n ≥ 0 } +which is not a type.

+

Intuitively it means that when applying a + recursive pattern against a recursive type, we may generate an + infinite number of distinct types for an accumulator. +

+
+
+

Typing of patterns (with accumulators) 2/2

+

We use the typing relation of operators to introduce + approximations:

+
+    t0, [ (t1 &lor; … &lor; tn)* ] &rarrow;cons [ (t0 &lor; t1 &lor; … &lor; tn)* ] 
+ t0, [ (t1 &lor; … &lor; tn)* ] &rarrow;snoc [ (t0 &lor; t1 &lor; … &lor; tn)* ] +
+

Ensures termination of typechecking of patterns.

+
+
+

Results

+

Zippers (in values, types, patterns) are orthogonal to the rest of the language

+ +
+
+

From zippers to XPath

+

We use regular expressions over basic &left;/&right; zippers to encode XPath

+ [ [ + [] + [] + [ [] ] + ] + ]]]> +ex_ntree
+

rb_tree

+
+
+

Downward axes

+ [ [ [] [] [ [] ] ] ]]]>&bcirc; + +
+     self :: t ≡    (ẋ & t | _ )&ztop;
+     child :: t ≡  <_>[ (ẋ & t | _ )* ]&ztop;
+     descendant-or-self:: t ≡   X ≡ ((ẋ & t | _ )  & <_>[ X * ])&ztop;
+     descendant :: t ≡ <_>[ (descendant-or-self::t)* ]&ztop;
+
+ + +
+

Upward axes

+ [ [ [] [] [ [] ] ] ]]]>&bcirc; + +
+     parent :: t ≡   ⊤ (&left;_) · (&right;_)* · (&right; ẋ & t) · (( (&left; _) · &ztop;)  &lor;  &bcirc; )
+     ancestor :: t ≡   ⊤ ((&left;_) · (&right;_)* · (&right; ẋ & t))* · &bcirc; 
+
+ +
+

Other results

+
    +
  • Encoding of paths is compositional
  • +
  • Once we have path, translation from XQuery to &cduce; is straightforward
  • +
  • We also give a direct typing algorithm for XQuery 3.0 rather than typing the translation to &cduce;
  • +
+
+
+

Conclusion, thoughts and future work

+
    +
  • Adding path expressions to a functional language such as &cduce; is possible
  • +
  • Semantic subtyping and regular expression types play nicely with zippers
  • +
  • In terms of language design, exposing directly zippers patterns to the programmer is a big no-no
  • +
  • Can also be applied to XSLT
  • +
  • Implementation on-going (including a &cduce; to javascript backend)
  • +
  • Extend the approach to Json (google ``path language for json''), i.e. generalise from products to extensible records
  • +
+ +
+ + + diff --git a/pres-esop15/LICENSE.txt b/pres-esop15/LICENSE.txt new file mode 100644 index 0000000..75b5248 --- /dev/null +++ b/pres-esop15/LICENSE.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/pres-esop15/OpenSans-Bold.ttf b/pres-esop15/OpenSans-Bold.ttf new file mode 100644 index 0000000..fd79d43 Binary files /dev/null and b/pres-esop15/OpenSans-Bold.ttf differ diff --git a/pres-esop15/OpenSans-BoldItalic.ttf b/pres-esop15/OpenSans-BoldItalic.ttf new file mode 100644 index 0000000..9bc8009 Binary files /dev/null and b/pres-esop15/OpenSans-BoldItalic.ttf differ diff --git a/pres-esop15/OpenSans-ExtraBold.ttf b/pres-esop15/OpenSans-ExtraBold.ttf new file mode 100644 index 0000000..21f6f84 Binary files /dev/null and b/pres-esop15/OpenSans-ExtraBold.ttf differ diff --git a/pres-esop15/OpenSans-ExtraBoldItalic.ttf b/pres-esop15/OpenSans-ExtraBoldItalic.ttf new file mode 100644 index 0000000..31cb688 Binary files /dev/null and b/pres-esop15/OpenSans-ExtraBoldItalic.ttf differ diff --git a/pres-esop15/OpenSans-Italic.ttf b/pres-esop15/OpenSans-Italic.ttf new file mode 100644 index 0000000..c90da48 Binary files /dev/null and b/pres-esop15/OpenSans-Italic.ttf differ diff --git a/pres-esop15/OpenSans-Light.ttf b/pres-esop15/OpenSans-Light.ttf new file mode 100644 index 0000000..0d38189 Binary files /dev/null and b/pres-esop15/OpenSans-Light.ttf differ diff --git a/pres-esop15/OpenSans-LightItalic.ttf b/pres-esop15/OpenSans-LightItalic.ttf new file mode 100644 index 0000000..68299c4 Binary files /dev/null and b/pres-esop15/OpenSans-LightItalic.ttf differ diff --git a/pres-esop15/OpenSans-Regular.ttf b/pres-esop15/OpenSans-Regular.ttf new file mode 100644 index 0000000..db43334 Binary files /dev/null and b/pres-esop15/OpenSans-Regular.ttf differ diff --git a/pres-esop15/OpenSans-Semibold.ttf b/pres-esop15/OpenSans-Semibold.ttf new file mode 100644 index 0000000..1a7679e Binary files /dev/null and b/pres-esop15/OpenSans-Semibold.ttf differ diff --git a/pres-esop15/OpenSans-SemiboldItalic.ttf b/pres-esop15/OpenSans-SemiboldItalic.ttf new file mode 100644 index 0000000..59b6d16 Binary files /dev/null and b/pres-esop15/OpenSans-SemiboldItalic.ttf differ diff --git a/pres-esop15/anbn_tree.svg b/pres-esop15/anbn_tree.svg new file mode 100644 index 0000000..5e15f2d --- /dev/null +++ b/pres-esop15/anbn_tree.svg @@ -0,0 +1,261 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + c + + + a + b + + + c + + + a + b + + + + + c + + + a + b + + + c + + + diff --git a/pres-esop15/ex_ntree.svg b/pres-esop15/ex_ntree.svg new file mode 100644 index 0000000..5c50d87 --- /dev/null +++ b/pres-esop15/ex_ntree.svg @@ -0,0 +1,187 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + + a + b + c + d + e + + + + + + + + f + + + diff --git a/pres-esop15/rb_tree.svg b/pres-esop15/rb_tree.svg new file mode 100644 index 0000000..e5edacb --- /dev/null +++ b/pres-esop15/rb_tree.svg @@ -0,0 +1,723 @@ + + + + + + + + + + + + image/svg+xml + + + + + + + + <> + + (,) + + + <> + + (,) + + + (,) + + + (,) + + <> + + <> + + <> + + + (,) + + <> + + + `nil + + `nil + + `nil + + `nil + + `nil + + `nil + + `a + `b + `c + `d + `e + `f + ⏺ + L + L + L + L + L + L + L + L + L + L + L + R + R + R + R + R + R + R + R + R + R + R + +