[Mlir-commits] [mlir] [coc.nvim] add extension (PR #83682)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Sat Mar 2 08:26:23 PST 2024


https://github.com/Freed-Wu created https://github.com/llvm/llvm-project/pull/83682

None

>From ab35a8064a35098126e7588523d1355c024036ec Mon Sep 17 00:00:00 2001
From: Wu Zhenyu <wuzhenyu at ustc.edu>
Date: Sun, 3 Mar 2024 00:23:51 +0800
Subject: [PATCH] [coc.nvim] add extension

---
 .../.github/workflows/auto_publish.yml        |  31 +
 mlir/utils/coc.nvim/.gitignore                |   7 +
 mlir/utils/coc.nvim/.npmignore                |  26 +
 mlir/utils/coc.nvim/.vscode/launch.json       |  24 +
 mlir/utils/coc.nvim/.vscode/tasks.json        |  33 +
 mlir/utils/coc.nvim/.vscodeignore             |   4 +
 mlir/utils/coc.nvim/LICENSE                   | 234 ++++++
 mlir/utils/coc.nvim/README.md                 | 343 +++++++++
 mlir/utils/coc.nvim/cpp-grammar.json          |  44 ++
 mlir/utils/coc.nvim/grammar.json              | 398 ++++++++++
 mlir/utils/coc.nvim/icon.png                  | Bin 0 -> 51803 bytes
 .../coc.nvim/language-configuration.json      |  22 +
 mlir/utils/coc.nvim/markdown-grammar.json     | 117 +++
 mlir/utils/coc.nvim/package-lock.json         | 710 ++++++++++++++++++
 mlir/utils/coc.nvim/package.json              | 213 ++++++
 mlir/utils/coc.nvim/pdll-grammar.json         | 524 +++++++++++++
 .../coc.nvim/pdll-language-configuration.json |  67 ++
 mlir/utils/coc.nvim/src/config.ts             |  19 +
 mlir/utils/coc.nvim/src/configWatcher.ts      |  86 +++
 mlir/utils/coc.nvim/src/extension.ts          |  30 +
 mlir/utils/coc.nvim/src/mlirContext.ts        | 392 ++++++++++
 mlir/utils/coc.nvim/tablegen-grammar.json     | 452 +++++++++++
 .../tablegen-language-configuration.json      |  89 +++
 mlir/utils/coc.nvim/tsconfig.json             |  17 +
 24 files changed, 3882 insertions(+)
 create mode 100644 mlir/utils/coc.nvim/.github/workflows/auto_publish.yml
 create mode 100644 mlir/utils/coc.nvim/.gitignore
 create mode 100644 mlir/utils/coc.nvim/.npmignore
 create mode 100644 mlir/utils/coc.nvim/.vscode/launch.json
 create mode 100644 mlir/utils/coc.nvim/.vscode/tasks.json
 create mode 100644 mlir/utils/coc.nvim/.vscodeignore
 create mode 100644 mlir/utils/coc.nvim/LICENSE
 create mode 100644 mlir/utils/coc.nvim/README.md
 create mode 100644 mlir/utils/coc.nvim/cpp-grammar.json
 create mode 100644 mlir/utils/coc.nvim/grammar.json
 create mode 100644 mlir/utils/coc.nvim/icon.png
 create mode 100644 mlir/utils/coc.nvim/language-configuration.json
 create mode 100644 mlir/utils/coc.nvim/markdown-grammar.json
 create mode 100644 mlir/utils/coc.nvim/package-lock.json
 create mode 100644 mlir/utils/coc.nvim/package.json
 create mode 100644 mlir/utils/coc.nvim/pdll-grammar.json
 create mode 100644 mlir/utils/coc.nvim/pdll-language-configuration.json
 create mode 100644 mlir/utils/coc.nvim/src/config.ts
 create mode 100644 mlir/utils/coc.nvim/src/configWatcher.ts
 create mode 100644 mlir/utils/coc.nvim/src/extension.ts
 create mode 100644 mlir/utils/coc.nvim/src/mlirContext.ts
 create mode 100644 mlir/utils/coc.nvim/tablegen-grammar.json
 create mode 100644 mlir/utils/coc.nvim/tablegen-language-configuration.json
 create mode 100644 mlir/utils/coc.nvim/tsconfig.json

diff --git a/mlir/utils/coc.nvim/.github/workflows/auto_publish.yml b/mlir/utils/coc.nvim/.github/workflows/auto_publish.yml
new file mode 100644
index 00000000000000..3b053cb14c6295
--- /dev/null
+++ b/mlir/utils/coc.nvim/.github/workflows/auto_publish.yml
@@ -0,0 +1,31 @@
+# This workflow publishes the extension to the Coc marketplace when the version changes.
+name: Publish to Coc Marketplace
+on:
+  # Run whenever a new commit is pushed to the main branch.
+  push:
+    branches: [ main ]
+    paths: [ 'package.json' ]
+  workflow_dispatch:
+
+jobs:
+  publish:
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout at v2
+
+    - name: detect version
+      uses: EndBug/version-check at v2.0.1
+      id: check
+      if: github.event_name != 'workflow_dispatch'
+      with:
+        # Search the diff content for version changes.
+        diff-search: true
+
+    - name: publish
+      # if: steps.check.outputs.changed == 'true'
+      # The token will be expired in on 08/03/2022.
+      run: |
+        npm install
+        npm publish
+      env:
+        NODE_AUTH_TOKEN: ${{secrets.NODE_AUTH_TOKEN}}
diff --git a/mlir/utils/coc.nvim/.gitignore b/mlir/utils/coc.nvim/.gitignore
new file mode 100644
index 00000000000000..ec25628b950a13
--- /dev/null
+++ b/mlir/utils/coc.nvim/.gitignore
@@ -0,0 +1,7 @@
+out
+node_modules
+.vscode-test
+*.vsix
+*.tgz
+
+!.vscode
diff --git a/mlir/utils/coc.nvim/.npmignore b/mlir/utils/coc.nvim/.npmignore
new file mode 100644
index 00000000000000..2f8b41a7adc23c
--- /dev/null
+++ b/mlir/utils/coc.nvim/.npmignore
@@ -0,0 +1,26 @@
+src/
+*.map
+*.tgz
+
+# tool
+.github
+.eslintrc.js
+.prettierrc
+
+# package manager
+yarn.lock
+yarn-error.log
+
+# bundler
+tsconfig.json
+webpack.config.js
+esbuild.mjs
+esbuild.js
+
+# vscode
+.vscodeignore
+.vscode/
+grammar.json
+*-grammar.json
+language-configuration.json
+*-language-configuration.json
diff --git a/mlir/utils/coc.nvim/.vscode/launch.json b/mlir/utils/coc.nvim/.vscode/launch.json
new file mode 100644
index 00000000000000..dfe1753e6a663d
--- /dev/null
+++ b/mlir/utils/coc.nvim/.vscode/launch.json
@@ -0,0 +1,24 @@
+{
+	// Use IntelliSense to learn about possible attributes.
+	// Hover to view descriptions of existing attributes.
+	// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
+	"version": "0.2.0",
+	"configurations": [
+		{
+			"type": "extensionHost",
+			"request": "launch",
+			"name": "Run Extension",
+			"runtimeExecutable": "${execPath}",
+			"args": [
+				"--extensionDevelopmentPath=${workspaceRoot}"
+			],
+			"outFiles": [
+				"${workspaceRoot}/out/**/*.js"
+			],
+			"preLaunchTask": {
+				"type": "npm",
+				"script": "watch"
+			}
+		}
+	]
+}
\ No newline at end of file
diff --git a/mlir/utils/coc.nvim/.vscode/tasks.json b/mlir/utils/coc.nvim/.vscode/tasks.json
new file mode 100644
index 00000000000000..5efd8048880a18
--- /dev/null
+++ b/mlir/utils/coc.nvim/.vscode/tasks.json
@@ -0,0 +1,33 @@
+{
+	"version": "2.0.0",
+	"tasks": [
+		{
+			"type": "npm",
+			"script": "compile",
+			"group": "build",
+			"presentation": {
+				"panel": "dedicated",
+				"reveal": "never"
+			},
+			"problemMatcher": [
+				"$tsc"
+			]
+		},
+		{
+			"type": "npm",
+			"script": "watch",
+			"isBackground": true,
+			"group": {
+				"kind": "build",
+				"isDefault": true
+			},
+			"presentation": {
+				"panel": "dedicated",
+				"reveal": "never"
+			},
+			"problemMatcher": [
+				"$tsc-watch"
+			]
+		}
+	]
+}
\ No newline at end of file
diff --git a/mlir/utils/coc.nvim/.vscodeignore b/mlir/utils/coc.nvim/.vscodeignore
new file mode 100644
index 00000000000000..f369b5e55b684e
--- /dev/null
+++ b/mlir/utils/coc.nvim/.vscodeignore
@@ -0,0 +1,4 @@
+.vscode/**
+.vscode-test/**
+.gitignore
+vsc-extension-quickstart.md
diff --git a/mlir/utils/coc.nvim/LICENSE b/mlir/utils/coc.nvim/LICENSE
new file mode 100644
index 00000000000000..53bb2e7fbc7643
--- /dev/null
+++ b/mlir/utils/coc.nvim/LICENSE
@@ -0,0 +1,234 @@
+==============================================================================
+The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
+==============================================================================
+
+                                 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.
+
+
+---- LLVM Exceptions to the Apache 2.0 License ----
+
+As an exception, if, as a result of your compiling your source code, portions
+of this Software are embedded into an Object form of such source code, you
+may redistribute such embedded portions in such Object form without complying
+with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
+
+In addition, if you combine or link compiled forms of this Software with
+software that is licensed under the GPLv2 ("Combined Software") and if a
+court of competent jurisdiction determines that the patent provision (Section
+3), the indemnity provision (Section 9) or other Section of the License
+conflicts with the conditions of the GPLv2, you may retroactively and
+prospectively choose to deem waived or otherwise exclude such Section(s) of
+the License, but only in their entirety and only with respect to the Combined
+Software.
+
+==============================================================================
+Software from third parties included in the LLVM Project:
+==============================================================================
+The LLVM Project contains third party software which is under different license
+terms. All such code will be identified clearly using at least one of two
+mechanisms:
+1) It will be in a separate directory tree with its own `LICENSE.txt` or
+   `LICENSE` file at the top containing the specific license and restrictions
+   which apply to that software, or
+2) It will contain specific license and restriction terms at the top of every
+   file.
diff --git a/mlir/utils/coc.nvim/README.md b/mlir/utils/coc.nvim/README.md
new file mode 100644
index 00000000000000..70773cf3877db6
--- /dev/null
+++ b/mlir/utils/coc.nvim/README.md
@@ -0,0 +1,343 @@
+# MLIR
+
+Ported from [vscode-mlir](https://github.com/llvm/vscode-mlir).
+
+Because some APIs of [vscode](github.com/microsoft/vscode) are missing in
+[coc.nvim](https://github.com/neoclide/coc.nvim), disable some features
+temporarily:
+
+- command `mlir.viewPDLLOutput`: miss
+  `vscode.workspace.openTextDocument({language, content})`
+- custom editor `mlir.bytecode`: miss
+  `vscode.window.registerCustomEditorProvider()`
+- filesystem `mlir.bytecode-mlir`: miss `vscode.workspace.registerFileSystemProvider()`
+- use `chokidar.watch()` to detect the changes of the paths of language
+  servers: miss `vscode.Disposable.constructor()`
+
+## Install
+
+- [coc-marketplace](https://github.com/fannheyward/coc-marketplace)
+- [npm](https://www.npmjs.com/package/coc-mlir)
+- vim:
+
+```vim
+" command line
+CocInstall coc-mlir
+" or add the following code to your vimrc
+let g:coc_global_extensions = ['coc-mlir', 'other coc-plugins']
+```
+
+---
+
+Provides language IDE features for [MLIR](https://mlir.llvm.org/) related
+languages: [MLIR](#mlir---mlir-textual-assembly-format),
+[PDLL](#pdll---mlir-pdll-pattern-files), and [TableGen](#td---tablegen-files)
+
+## `.mlir` - MLIR textual assembly format:
+
+The MLIR extension adds language support for the
+[MLIR textual assembly format](https://mlir.llvm.org/docs/LangRef/):
+
+### Features
+
+- Syntax highlighting for `.mlir` files and `mlir` markdown blocks
+- go-to-definition and cross references
+- Detailed information when hovering over IR entities
+- Outline and navigation of symbols and symbol tables
+- Code completion
+- Live parser and verifier diagnostics
+
+#### Diagnostics
+
+The language server actively runs verification on the IR as you type, showing
+any generated diagnostics in-place.
+
+![IMG](https://mlir.llvm.org/mlir-lsp-server/diagnostics.png)
+
+##### Automatically insert `expected-` diagnostic checks
+
+MLIR provides
+[infrastructure](https://mlir.llvm.org/docs/Diagnostics/#sourcemgr-diagnostic-verifier-handler)
+for checking expected diagnostics, which is heavily utilized when defining IR
+parsing and verification. The language server provides code actions for
+automatically inserting the checks for diagnostics it knows about.
+
+![IMG](https://mlir.llvm.org/mlir-lsp-server/diagnostics_action.gif)
+
+#### Code completion
+
+The language server provides suggestions as you type, offering completions for
+dialect constructs (such as attributes, operations, and types), block names, SSA
+value names, keywords, and more.
+
+![IMG](https://mlir.llvm.org/mlir-lsp-server/code_complete.gif)
+
+#### Cross-references
+
+Cross references allow for navigating the use/def chains of SSA values (i.e.
+operation results and block arguments), [Symbols](../SymbolsAndSymbolTables.md),
+and Blocks.
+
+##### Find definition
+
+Jump to the definition of the IR entity under the cursor. A few examples are
+shown below:
+
+- SSA Values
+
+![SSA](https://mlir.llvm.org/mlir-lsp-server/goto_def_ssa.gif)
+
+- Symbol References
+
+![Symbols](https://mlir.llvm.org/mlir-lsp-server/goto_def_symbol.gif)
+
+The definition of an operation will also take into account the source location
+attached, allowing for navigating into the source file that generated the
+operation.
+
+![External Locations](https://mlir.llvm.org/mlir-lsp-server/goto_def_external.gif)
+
+##### Find references
+
+Show all references of the IR entity under the cursor.
+
+![IMG](https://mlir.llvm.org/mlir-lsp-server/find_references.gif)
+
+#### Hover
+
+Hover over an IR entity to see more information about it. The exact information
+displayed is dependent on the type of IR entity under the cursor. For example,
+hovering over an `Operation` may show its generic format.
+
+![IMG](https://mlir.llvm.org/mlir-lsp-server/hover.png)
+
+#### Navigation
+
+The language server will also inform the editor about the structure of symbol
+tables within the IR. This allows for jumping directly to the definition of a
+symbol, such as a `func.func`, within the file.
+
+![IMG](https://mlir.llvm.org/mlir-lsp-server/navigation.gif)
+
+#### Bytecode Editing and Inspection
+
+The language server provides support for interacting with MLIR bytecode files,
+enabling IDEs to transparently view and edit bytecode files in the same way
+as textual `.mlir` files.
+
+![IMG](https://mlir.llvm.org/mlir-lsp-server/bytecode_edit.gif)
+
+### Setup
+
+#### `mlir-lsp-server`
+
+The various `.mlir` language features require the
+[`mlir-lsp-server` language server](https://mlir.llvm.org/docs/Tools/MLIRLSP/#mlir-lsp-language-server--mlir-lsp-server).
+If `mlir-lsp-server` is not found within your workspace path, you must specify
+the path of the server via the `mlir.server_path` setting. The path of the
+server may be absolute or relative within your workspace.
+
+## `.pdll` - MLIR PDLL pattern files:
+
+The MLIR extension adds language support for the
+[PDLL pattern language](https://mlir.llvm.org/docs/PDLL/).
+
+### Features
+
+- Syntax highlighting for `.pdll` files and `pdll` markdown blocks
+- go-to-definition and cross references
+- Types and documentation on hover
+- Code completion and signature help
+- View intermediate AST, MLIR, or C++ output
+
+#### Diagnostics
+
+The language server actively runs verification as you type, showing any
+generated diagnostics in-place.
+
+![IMG](https://mlir.llvm.org/mlir-pdll-lsp-server/diagnostics.png)
+
+#### Code completion and signature help
+
+The language server provides suggestions as you type based on what constraints,
+rewrites, dialects, operations, etc are available in this context. The server
+also provides information about the structure of constraint and rewrite calls,
+operations, and more as you fill them in.
+
+![IMG](https://mlir.llvm.org/mlir-pdll-lsp-server/code_complete.gif)
+
+#### Cross-references
+
+Cross references allow for navigating the code base.
+
+##### Find definition
+
+Jump to the definition of a symbol under the cursor:
+
+![IMG](https://mlir.llvm.org/mlir-pdll-lsp-server/goto_def.gif)
+
+If ODS information is available, we can also jump to the definition of operation
+names and more:
+
+![IMG](https://mlir.llvm.org/mlir-pdll-lsp-server/goto_def_ods.gif)
+
+##### Find references
+
+Show all references of the symbol under the cursor.
+
+![IMG](https://mlir.llvm.org/mlir-pdll-lsp-server/find_references.gif)
+
+#### Hover
+
+Hover over a symbol to see more information about it, such as its type,
+documentation, and more.
+
+![IMG](https://mlir.llvm.org/mlir-pdll-lsp-server/hover.png)
+
+If ODS information is available, we can also show information directly from the
+operation definitions:
+
+![IMG](https://mlir.llvm.org/mlir-pdll-lsp-server/hover_ods.png)
+
+#### Navigation
+
+The language server will also inform the editor about the structure of symbols
+within the IR.
+
+![IMG](https://mlir.llvm.org/mlir-pdll-lsp-server/navigation.gif)
+
+#### View intermediate output
+
+The language server provides support for introspecting various intermediate
+stages of compilation, such as the AST, the `.mlir` containing the generated
+PDL, and the generated C++ glue. This is a custom LSP extension, and is not
+necessarily provided by all IDE clients.
+
+![IMG](https://mlir.llvm.org/mlir-pdll-lsp-server/view_output.gif)
+
+#### Inlay hints
+
+The language server provides additional information inline with the source code.
+Editors usually render this using read-only virtual text snippets interspersed
+with code. Hints may be shown for:
+
+- types of local variables
+- names of operand and result groups
+- constraint and rewrite arguments
+
+![IMG](https://mlir.llvm.org/mlir-pdll-lsp-server/inlay_hints.png)
+
+### Setup
+
+#### `mlir-pdll-lsp-server`
+
+The various `.pdll` language features require the
+[`mlir-pdll-lsp-server` language server](https://mlir.llvm.org/docs/Tools/MLIRLSP/#pdll-lsp-language-server--mlir-pdll-lsp-server).
+If `mlir-pdll-lsp-server` is not found within your workspace path, you must
+specify the path of the server via the `mlir.pdll_server_path` setting. The path
+of the server may be absolute or relative within your workspace.
+
+#### Project setup
+
+To properly understand and interact with `.pdll` files, the language server must
+understand how the project is built (compile flags).
+[`pdll_compile_commands.yml` files](https://mlir.llvm.org/docs/Tools/MLIRLSP/#compilation-database)
+related to your project should be provided to ensure files are properly
+processed. These files can usually be generated by the build system, and the
+server will attempt to find them within your `build/` directory. If not
+available in or a unique location, additional `pdll_compile_commands.yml` files
+may be specified via the `mlir.pdll_compilation_databases` setting. The paths of
+these databases may be absolute or relative within your workspace.
+
+## `.td` - TableGen files:
+
+The MLIR extension adds language support for the
+[TableGen language](https://llvm.org/docs/TableGen/ProgRef.html).
+
+### Features
+
+- Syntax highlighting for `.td` files and `tablegen` markdown blocks
+- go-to-definition and cross references
+- Types and documentation on hover
+
+#### Diagnostics
+
+The language server actively runs verification as you type, showing any
+generated diagnostics in-place.
+
+![IMG](https://mlir.llvm.org/tblgen-lsp-server/diagnostics.png)
+
+#### Cross-references
+
+Cross references allow for navigating the code base.
+
+##### Find definition
+
+Jump to the definition of a symbol under the cursor:
+
+![IMG](https://mlir.llvm.org/tblgen-lsp-server/goto_def.gif)
+
+##### Find references
+
+Show all references of the symbol under the cursor.
+
+![IMG](https://mlir.llvm.org/tblgen-lsp-server/find_references.gif)
+
+#### Hover
+
+Hover over a symbol to see more information about it, such as its type,
+documentation, and more.
+
+![IMG](https://mlir.llvm.org/tblgen-lsp-server/hover_def.png)
+
+Hovering over an overridden field will also show you information such as
+documentation from the base value:
+
+![IMG](https://mlir.llvm.org/tblgen-lsp-server/hover_field.png)
+
+### Setup
+
+#### `tblgen-lsp-server`
+
+The various `.td` language features require the
+[`tblgen-lsp-server` language server](https://mlir.llvm.org/docs/Tools/MLIRLSP/#tablegen-lsp-language-server--tblgen-lsp-server).
+If `tblgen-lsp-server` is not found within your workspace path, you must specify
+the path of the server via the `mlir.tablegen_server_path` setting. The path of
+the server may be absolute or relative within your workspace.
+
+#### Project setup
+
+To properly understand and interact with `.td` files, the language server must
+understand how the project is built (compile flags).
+[`tablegen_compile_commands.yml` files](https://mlir.llvm.org/docs/Tools/MLIRLSP/#compilation-database-1)
+related to your project should be provided to ensure files are properly
+processed. These files can usually be generated by the build system, and the
+server will attempt to find them within your `build/` directory. If not
+available in or a unique location, additional `tablegen_compile_commands.yml`
+files may be specified via the `mlir.tablegen_compilation_databases` setting.
+The paths of these databases may be absolute or relative within your workspace.
+
+## Contributing
+
+This extension is actively developed within the
+[LLVM monorepo](https://github.com/llvm/llvm-project), at
+[`mlir/utils/vscode`](https://github.com/llvm/llvm-project/tree/main/mlir/utils/vscode).
+As such, contributions should follow the
+[normal LLVM guidelines](https://llvm.org/docs/Contributing.html), with code
+reviews sent to
+[phabricator](https://llvm.org/docs/Contributing.html#how-to-submit-a-patch).
+
+When developing or deploying this extension within the LLVM monorepo, a few
+extra setup steps are required:
+
+- Copy `mlir/utils/textmate/mlir.json` to the extension directory and rename to
+  `grammar.json`.
+- Copy `llvm/utils/textmate/tablegen.json` to the extension directory and rename
+  to `tablegen-grammar.json`.
+- Copy
+  `https://mlir.llvm.org//LogoAssets/logo/PNG/full_color/mlir-identity-03.png`
+  to the extension directory and rename to `icon.png`.
+
+Please follow the existing code style when contributing to the extension, we
+recommend to run `npm run format` before sending a patch.
+
diff --git a/mlir/utils/coc.nvim/cpp-grammar.json b/mlir/utils/coc.nvim/cpp-grammar.json
new file mode 100644
index 00000000000000..36063c6a5210bd
--- /dev/null
+++ b/mlir/utils/coc.nvim/cpp-grammar.json
@@ -0,0 +1,44 @@
+{
+  "scopeName": "source.cpp.mlir",
+  "injectionSelector": "L:source.cpp -string.quoted.double.cpp -string.quoted.double.raw",
+  "patterns": [
+    {
+      "include": "#mlir-raw-string"
+    }
+  ],
+  "repository": {
+    "mlir-raw-string": {
+      "begin": "R\"(?i:mlir)(\\()",
+      "beginCaptures": {
+        "0": {
+          "name": "punctuation.definition.string.begin.cpp"
+        },
+        "1": {
+          "name": "mlir.delimeter.raw.string.cpp"
+        }
+      },
+      "end": "\\)(?i:mlir)\"",
+      "endCaptures": {
+        "0": {
+          "name": "punctuation.definition.string.end.cpp"
+        },
+        "1": {
+          "name": "mlir.delimeter.raw.string.cpp"
+        }
+      },
+      "name": "mlir.raw.string.cpp",
+      "patterns": [
+        {
+          "contentName": "source.mlir",
+          "begin": "(?!\\G)",
+          "end": "(?i)(?=\\)mlir\")",
+          "patterns": [
+            {
+              "include": "source.mlir"
+            }
+          ]
+        }
+      ]
+    }
+  }
+}
diff --git a/mlir/utils/coc.nvim/grammar.json b/mlir/utils/coc.nvim/grammar.json
new file mode 100644
index 00000000000000..820f8921cf237e
--- /dev/null
+++ b/mlir/utils/coc.nvim/grammar.json
@@ -0,0 +1,398 @@
+{
+  "name": "MLIR",
+  "fileTypes": [
+    "mlir"
+  ],
+  "patterns": [
+    {
+      "include": "#comment"
+    },
+    {
+      "include": "#string"
+    },
+    {
+      "include": "#top_level_entity"
+    }
+  ],
+  "repository": {
+    "comment": {
+      "match": "\/\/.*$",
+      "name": "comment.line.double-slash.mlir"
+    },
+    "number": {
+      "patterns": [
+        {
+          "match": "(\\W)?([0-9]+\\.[0-9]*)([eE][+-]?[0-9]+)?",
+          "name": "constant.numeric.mlir"
+        },
+        {
+          "match": "([\\W])?(0x[0-9a-zA-Z]+)",
+          "captures": {
+            "2": {
+              "name": "constant.numeric.mlir"
+            }
+          }
+        },
+        {
+          "match": "([\\Wx])?([0-9]+)",
+          "captures": {
+            "2": {
+              "name": "constant.numeric.mlir"
+            }
+          }
+        }
+      ]
+    },
+    "string": {
+      "begin": "\"",
+      "beginCaptures": {
+        "0": {
+          "name": "punctuation.definition.string.begin.mlir"
+        }
+      },
+      "patterns": [
+        {
+          "match": "\\\\[nt\"]",
+          "name": "constant.character.escape.mlir"
+        }
+      ],
+      "end": "\"",
+      "endCaptures": {
+        "0": {
+          "name": "punctuation.definition.string.end.mlir"
+        }
+      },
+      "name": "string.quoted.double.mlir"
+    },
+    "top_level_entity": {
+      "patterns": [
+        {
+          "include": "#attribute_alias_def"
+        },
+        {
+          "include": "#type_alias_def"
+        },
+        {
+          "include": "#operation_body"
+        }
+      ]
+    },
+    "attribute_alias_def": {
+      "match": "^\\s*(\\#\\w+)\\b\\s+\\=",
+      "captures": {
+        "1": {
+          "name": "constant.language.mlir"
+        }
+      }
+    },
+    "type_alias_def": {
+      "match": "^\\s*(\\!\\w+)\\b\\s+\\=",
+      "captures": {
+        "1": {
+          "name": "entity.name.type.mlir"
+        }
+      }
+    },
+    "operation": {
+      "patterns": [
+        {
+          "match": "^\\s*(\\%[\\%\\w\\:\\,\\s]+)\\s+\\=\\s+([\\w\\.\\$\\-]+)\\b",
+          "captures": {
+            "1": {
+              "patterns": [
+                {
+                  "include": "#ssa_value"
+                }
+              ]
+            },
+            "2": {
+              "name": "variable.other.enummember.mlir"
+            }
+          }
+        },
+        {
+          "match": "^\\s*([\\w\\.\\$\\-]+)\\b(?=[^\\<\\:])",
+          "name": "variable.other.enummember.mlir"
+        }
+      ]
+    },
+    "operation_body": {
+      "patterns": [
+        {
+          "include": "#operation"
+        },
+        {
+          "include": "#region_body_or_attr_dict"
+        },
+        {
+          "include": "#comment"
+        },
+        {
+          "include": "#ssa_value"
+        },
+        {
+          "include": "#block"
+        },
+        {
+          "include": "#attribute_value"
+        },
+        {
+          "include": "#bare_identifier"
+        }
+      ]
+    },
+    "region_body_or_attr_dict": {
+      "patterns": [
+        {
+          "begin": "\\{\\s*(?=\\%|\\/|\\^)",
+          "patterns": [
+            {
+              "include": "#operation_body"
+            }
+          ],
+          "end": "\\}"
+        },
+        {
+          "begin": "\\{\\s*(?=[^\\}]*$)",
+          "patterns": [
+            {
+              "include": "#operation_body"
+            }
+          ],
+          "end": "\\}"
+        },
+        {
+          "begin": "\\{\\s*(?=\\%)",
+          "patterns": [
+            {
+              "include": "#operation_body"
+            }
+          ],
+          "end": "\\}"
+        },
+        {
+          "begin": "\\{\\s*(?=.*$)",
+          "patterns": [
+            {
+              "include": "#attribute_dictionary_body"
+            }
+          ],
+          "end": "\\}"
+        }
+      ]
+    },
+    "attribute_value": {
+      "patterns": [
+        {
+          "include": "#string"
+        },
+        {
+          "include": "#comment"
+        },
+        {
+          "include": "#number"
+        },
+        {
+          "match": "\\b(false|true|unit)\\b",
+          "name": "constant.language.mlir"
+        },
+        {
+          "begin": "\\b(affine_map|affine_set)\\s*\\<",
+          "beginCaptures": {
+            "1": {
+              "name": "constant.language.mlir"
+            }
+          },
+          "patterns": [
+            {
+              "match": "\\b(ceildiv|floordiv|mod|symbol)\\b",
+              "name": "entity.name.function.mlir"
+            },
+            {
+              "match": "\\b([\\w\\.\\$\\-]+)\\b",
+              "name": "variable.mlir"
+            },
+            {
+              "include": "#number"
+            }
+          ],
+          "end": "\\)\\>"
+        },
+        {
+          "begin": "\\b(dense|opaque|sparse)\\s*\\<",
+          "beginCaptures": {
+            "1": {
+              "name": "constant.language.mlir"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#attribute_value"
+            }
+          ],
+          "end": "\\>"
+        },
+        {
+          "begin": "\\[",
+          "patterns": [
+            {
+              "include": "#attribute_value"
+            },
+            {
+              "include": "#operation_body"
+            }
+          ],
+          "end": "\\]"
+        },
+        {
+          "begin": "\\{",
+          "patterns": [
+            {
+              "include": "#attribute_dictionary_body"
+            }
+          ],
+          "end": "\\}"
+        },
+        {
+          "match": "(\\@[\\w+\\$\\-\\.]*)",
+          "name": "entity.name.function.mlir"
+        },
+        {
+          "begin": "(\\#[\\w\\$\\-\\.]+)\\<",
+          "beginCaptures": {
+            "1": {
+              "name": "constant.language.mlir"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#attribute_value"
+            },
+            {
+              "match": "\\-\\>|\\>\\="
+            },
+            {
+              "include": "#bare_identifier"
+            }
+          ],
+          "end": "\\>"
+        },
+        {
+          "match": "\\#[\\w\\$\\-\\.]+\\b",
+          "name": "constant.language.mlir"
+        },
+        {
+          "include": "#type_value"
+        },
+        {
+          "begin": "\\<",
+          "patterns": [
+            {
+              "include": "#attribute_value"
+            },
+            {
+              "include": "#bare_identifier"
+            }
+          ],
+          "end": "\\>"
+        }
+      ]
+    },
+    "attribute_dictionary_body": {
+      "patterns": [
+        {
+          "include": "#comment"
+        },
+        {
+          "include": "#string"
+        },
+        {
+          "include": "#attribute_value"
+        },
+        {
+          "match": "(\\%)?\\b([\\w\\.\\-\\$\\:0-9]+)\\b\\s*(?=\\=|\\,|\\})",
+          "name": "variable.other.mlir"
+        }
+      ]
+    },
+    "type_value": {
+      "patterns": [
+        {
+          "begin": "(\\![\\w\\$\\-\\.]+)\\<",
+          "beginCaptures": {
+            "1": {
+              "name": "entity.name.type.mlir"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#attribute_value"
+            },
+            {
+              "match": "\\-\\>|\\>\\=",
+              "name": "punctuation.other.mlir"
+            },
+            {
+              "include": "#bare_identifier"
+            }
+          ],
+          "end": "\\>"
+        },
+        {
+          "match": "\\![\\w\\$\\-\\.]+\\b",
+          "name": "entity.name.type.mlir"
+        },
+        {
+          "begin": "(complex|memref|tensor|tuple|vector)\\<",
+          "beginCaptures": {
+            "1": {
+              "name": "entity.name.type.mlir"
+            }
+          },
+          "patterns": [
+            {
+              "match": "[\\?x0-9\\[\\]]+",
+              "captures": {
+                "0": {
+                  "patterns": [
+                    {
+                      "include": "#number"
+                    }
+                  ]
+                }
+              }
+            },
+            {
+              "include": "#attribute_value"
+            },
+            {
+              "match": "\\-\\>|\\>\\=",
+              "name": "punctuation.other.mlir"
+            },
+            {
+              "include": "#bare_identifier"
+            }
+          ],
+          "end": "\\>"
+        },
+        {
+          "match": "bf16|f16|f32|f64|f80|f128|index|none|(u|s)?i[0-9]+",
+          "name": "entity.name.type.mlir"
+        }
+      ]
+    },
+    "bare_identifier": {
+      "match": "\\b([\\w\\.\\$\\-]+)\\b",
+      "name": "keyword.other.mlir"
+    },
+    "ssa_value": {
+      "match": "\\%[\\w\\.\\$\\:\\#]+",
+      "name": "variable.other.mlir"
+    },
+    "block": {
+      "match": "\\^[\\w\\d_$\\.-]+",
+      "name": "keyword.control.mlir"
+    }
+  },
+  "scopeName": "source.mlir"
+}
\ No newline at end of file
diff --git a/mlir/utils/coc.nvim/icon.png b/mlir/utils/coc.nvim/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..2daa335d02995767baefcbbcbc0f0f72c253f298
GIT binary patch
literal 51803
zcmeFZ`9IX_|37{)!pWWr$r7DPDufh<DTPzE_9#&*ON(U9I$EfRIxR|JQlcb8$k;m8
zN{n5yMP;2C`@Vc0*Nm2PUhhBP`@{E#Zn at 1om+Ses?vMN9{<vS)Jg=IW7zoT?G9Mu%
z at R#A%T?ox<#Q%7?;ggN(M#td4Kh7GOJ0rAC9{=O;h|zUJNEZFIb at LvNhrLbZj(a;I
znd2QR{6CvCZpc`+xps at Jdgd<0o1`Q9+ at uwX5^sCUmY8~GT$&}6`k|xy<h>54ivMYZ
zg#HQUT^_AiW4t4c;{6w8sbiREylhw11jEx?@GrxoiPO&XY0tk5Zf<vVX*DPH6_@)a
z&JLvKPOs&FAt4lT{=+!yFH#3TgY^k*9=AK|k50~uTC6`@{NGBk{>aR06=eNkX?>Ol
z|3O}-oI${Uki^6rS(l;k{r{Kw|9EV&+J!lgwa234uG%rF_x#Atrj9KK`ZEx+-Z&kW
zJ56_#7C?yqe)J2$C$|^x+8*XNC{LB19gR(QJmql$A>~8MkHfJg3y-Tu?XozZUmrOz
zd-~7WSwMkafdD{9e8D#Jh!5lUY^YNr#O(?nb+diiBW-yRx at ZfLA#;3)7&)mB!>8`I
zJbj?=B at +-uIL7+oUBrlC{-LhQ&{hZj(Fs7KvN(pKI63;o_ko0wu647C=>w-nx0NqK
zXyOBgqR(wDI-f#J3US8DGGtcD2afKP!KfYD%t$S!`93S}$i5xu&iY)1^*QZi#K^ex
zR~xtZJA>- at 9yC3CkItLXFV=m3G+BS+VZQ@|+OqV53?D+lOYu1_<~#Sr4$zu=OuQ^V
zocHkS{6s*cQH*!Wj&nNS8;~a5b?vt=mM0+BGh5dN!jncQzF&R#N at gV`nfOhnXZuVt
zB#G3ye8?hAv)eUqZdbMmyEgP(%b9Gf`mDiF9}E=w5uGL1UTH=KjvS$<*1dihIC|&A
zOdm|vS)5c!Ja4L`|G4`>-uFyhd&e^zI4UcmmaE at 8=!DX%Y|foXnA%lSxNIyLp*)%@
zq-LH~2`k#SY&`dc&PChr9~?SAS@#ATyWG~`hBGks78qJHE4y=VYSC|ozG*wv-09#g
zzXgBc`w^dzsPNuloqI#*rZC;t;a1O|<NM#o#4uA~ANpwe#bEudZ`xTsR02{S!NU!H
z-H1Q0%!t|+c$a<ay!!PpCgrqiuPjOuM(lIvXGY)o%;1ynbLK!~A|9`@+qGAj;`vD?
zUgcX`d}g}nk{Sj>9l$k?7$VlE79Mw9EkxI(PbWig0^9p;&4a+f9LXoHiYJ`6tFxC0
zj?vC?3~o1-M&$nfyS4%-Zxu|&61rm1i2t<|t9Rv`2<hLI!~=X1{h}=9_F~tDK$D at S
zj>zU5C&xx1PDHM-!S{Ls_tM7q%0InHh^g4_D-5RyvTnA_y+PjmT%qXc+wm23b?$KR
zLJSAHEDY2gJ7b9-^&P&2Jzp0xxfuX<3IlA3A`Z81mqN%TgYzEv9Lh}`B{dTkP~TQb
z{xz2kq{pml1=nfP2M1K-6Yu0ci-uT}Y*-&(YP7d9RFE1hD0=Up%>s5fp0+$Q$SU!M
za?f2hc(fSU{A=-8^%Od6<P^@m6Kzx9 at rJoh6(B)7|3MxwRlo4~B8`Uq!St-nQ{e~R
z<?2IH$7OthYtdG{?>?GS^RlY!%!}`z85$9b5z1%XB at al075{2h{7r-qc{6KDl>wUe
zH$FsiTAn559 at q=0A^X#C6lJfy3NMdvv(aigw`sJgBVrZIS8D(a%x5nv5u#1Bh>Lwj
z-vGNbI at 2I=g8)+G92kKIBh~6`+fYS9qq~(;Cwvo*zlnSgB;kF?sgj>oGZqk<16Rt%
z(4g4DjXtC|#73;wqug<%DtU^-DHrf5FIk~6)wB$tJ!S)xwii!H<_h-)G2pj{s|Au4
z<{lny;y|5?am=K=5~_5RWc2b=2Vzx*@W=P?bwa+Hcr`lceqU~%RO9^_rwq9PPhs`0
z+cnR;RmWb49=o)rBWF at iXb~c3<FF*H+$7^{92+5$4kUD60wFj0T7!8g at 64j(i at NSD
zveB}U^}U|>)oKuuTk#B>&=&^qzvuY6Csj2hnyE87G;-Z5QU{W?2+y(1YKY2q`<<~;
z4R;6oa at sZ`<ROX&oO=s$wlbsFrPcjqF;fWBo$n4{8?qJTtd4ubb$Z{4Fy|JZ=5d7j
zG&L|(72kIsVx&g7$R(W&-L-uX17<nC6wIUE<mF^t{y647>1G_0BK+{yM&C at lmaDuR
zQ%9E0>N)-~fJo&?{PZ?)tK#2y$NMx42EIJ`?K2}NWHGYN!dNXbWTYxRxn1VTpgDi&
zpEQPmS$ng-Ah9t2ZZII{;QM?k%wgUYoczH_Y|Ja0B|LPhgcK1!0`o)`0i+aa_el)~
zAF+G!J!jH5lnYr8;S1>-v6%T~m0<o!K)n!A9+LM6pg~-O6?my7#}$N_>s5gtTGtAR
zAj<f)SJ(6>uO&+ at S?OE;@@q>zB;Z5L1p at nipfUJTC$*f2OIGn8h-QQbz>VWB-Qe1A
zWN1yt7oWnEdB_d}g>><&$>f&pU9UR0<(ZySzBsGxFhh{^pg4wEUDKrBe_L;dnZWZa
zq)<6bqVm^svBZFpTak-`6Xu9O{3yQ3vO8LIl~k*~U~=zV-~(>pz?Z;1ytj8<vn5RV
z$M*|tg2^R+If|cA4(3W}8}a)a<ab0pcMncFYeO8C0Cs$92hoV#92pQ!;4>&JM*h14
zx!6Hm at SGD^SGp1XV(~ecLRFOc1QW90LPVLxlj{RvDHJboY4DeZVl at TD>Wt<wM4nNB
z*&6!mNAQO}oRe;r(R4!OW;~5U2X^k`ITt(qDutW-t0#l%=mF9od+;uVturF}MRY~Z
z(NjF!Yi9T at -ubQIKs0%b{2|iLeI2{D2Wistgn!h<^8oOs<1p~f=;#+A9gi$yrNrH!
z0$cSzf$YtPXwv3E44wrjmWkTki|^lJi-S`p0U^-bbGznH at Lq)&d)q(M_9*7qk3lMJ
z6B0%g9XvnAESUdg%Nu-UZW7|&!sU_-Sf9_c<q3{E$Y$w!0vw;WF1yw~DlC+vh@|M}
zyb}jH42Oq$gC##~%J{@p<NG_JFp{ls2&S&GBK^Xdv#9Z0S*iBY(TfO;$>Vv}C>g(J
zsBq|<4$6JSW(9JK#|M9erYv^ub9(GkSTES8-*4N#eI{iABG+L;z5%SO(&A8O&r=@(
z%rpITkP~6uT|n~%1s7K(Xm*fYzmnT{Imk|Us*Cn9QVkY-d1W;ZSvnDC4%GlOi|zpL
zD&PG<$fVIjWj>?lZRew4d7uPxGSJwYhoKerJe>(O5AVO}cnH_R$yBrj(v@$gl1Cfz
zaaClqyZCu{7V9TK3Qq)HdQ>8Ut9nj9mL$RJAzsR_=E#_MocxIPKD|kdC<rwYCWd?y
zs7fU at YRH8npmL6l<qIM7!NIJ;W;w8jW62SPnZ{Zeu>NI80J|(UDWL0B at 1wS3R#<}b
zNX-HUl`vuxxt#Pk;d^PRai|EgTMhT78G`zJuOV0Nc>&2EXR*RQM6rkIB0c`<U8)}8
zM!q>m#}t+3fjC5dy6XMvN)^Q-H*&JDUv1)7-AN9#<Si&!>rM##I#z_0(|*vg?;nuK
zr7!~igdd<J-=1WsWF>ACK-S{;86ROf7S8DHLVetI?Jc5^Xn9E$5Xpe;JNFH~sXB9t
zr!|xn{FPjYUla%b5g at 5<*Y=e}5j4`ebG!Xvz?e8UjxmMB7krUiNGjtFOUhbX!^7l}
zpc*|vFFiPsOGV9?{!74~GB2D!Vg4wDI*7=Mz0^8HGsWLHo{RNa7UNR;j6mc0(9gtj
znPP<lQx5aUPY-*z0TGhea+wl~KQ~=;{Pm54^Z^ybze^EjQF|Vu>}P!e+DHX!!6PW3
z1ncD?Gekavk#7lP{Y*QxCzYUF3Poy$wwn`W;t6)y2COhZ1Fk0BTJ!CTPyTKK(j2}k
z%7rxd-rlQ*g$PnJo1&ilbC$}FC at fNV{WJb~SFX&7<?|FolEQ&0XDMa32sfl(0sOOH
z+Y(tT;mExF#%AT+1Z)07p?=IRkfc;hBW^KJs-|{T+ppx#6Srs4awjA#CNsa)Y<czs
ziQCNS<f&zVrapZ(Bfv!Yxht|bGmi-zOSXb$W&C#KqLl>XSpB}`cFt1(e^wbh=#(WO
zbH~omO^eXjj`;DI=P>=G2Y}@IF5HsT+M~S4wH++UUGxw>E;>+FTwu_qH0}z@<KTNA
zEEL3dJD%@@0t at 9z5|pbO>I@%q at 7_M+z6L1=G at j)ltLz41_KpWeM4q<lEpEA8!5pmO
zYHjpGA|skEt6M4MupR<bS{J}1d#6sn0!d78o)c;M_ka?DlR&mQ$2QdqqKmFrq!FQ1
zSOO{M at j~G{#1b4RVAq^PE^p@`S3uPuivVBrvt~N4?_gQ}<TcxQ=rLwddFU+K<-7N5
zn<Bf1@%=}g0cUoYcGV8;+~?fC&2zhbLkbtU$e~c9JgPY-xl at Fb<P0OEJen(w%YY5o
zv`pp(8AZwmsPogsw6&19`3{AcdH8y`{;Cx~Gk1Pm9EtNKOc}f3k9qOOQ2s!7gq%MN
z?Zm#p(^w^op99E<A7xR)=Q2+d=uz%Ew at iP@kbw+Tgp>FmJq*42X!`FCAn&4G(#^+D
zK<Ul;=8y8uD$LOXY85JI5!pA;A_3L94Fbo16*r9sp+x{mm%viW;)p*I=9K%zs`z$=
zm~8+~3ZcS1%FA=I=$alE`7K~Aj|`9Fy>RN4Ewq;JhQ}r^L+bJe;OjvRWYYu6>^jGw
zmTT=row`5|lu*EW*q{pBh?I!gj<`|)O#?TRb)dcTSk^tSLjVnZN|-vj7oN2fce+Dn
zfI@@J#ErJdI`3uCJcPfH!e1D|B#iHyOjYGZ0b3PY+^mL3h%yO at Lp%PaD(A*7&7M;n
z<Yljy`dL-D^N<;M0>W4m5cW_3(S&!f>LSbdAq5`pNiF|S4DzY^y at WQt1C}hf#Vwqg
z*R9gQi_{uf>>$fQk%oI$!#8YlK#xzbsM#FVOTrhuo6Cw1RoO$W$(xIPSo1kEl%%!I
zypV4vriQ$GS8 at kme9a|rAS&)3rY`?z-Z;oAKN^U^Am~Q1T%CbP77t>wL48pyt*nh&
zN8uU!Bq5(=B6509LBHGSIpy;g5UsB<XywC at QQnMH$<G{Urv6)_dz8CA>J!3QpsUHE
z<_I20Ty5|(pv5J>l_INzu>_m=XbRW|v;<aXp_~Ty2#$f`A4;<7S44;s|FY;ZH$<lB
zCY+KC_c-LM(5+%BgD5Na4er=0CZ&Yh3t9#9>R}>r|JDtn3wkSz*&^s($T!({8A#<o
z+(+4>Em#dACZDh>{&J&3)W{R~;yD&=(ggJQJzU8UlJ=<g=2&=kWf!Pgv!Hw)fTi;o
zdWbwjh4<Ziu#^Rr_!+A<NQL0}_<E1#8fcKPcX12taR#Y19gLJk#`}NJGrGReFYw?y
zzgPlU-#K53T=a_`tdBvv&VY7(RC^Z+FKHDdwf|_J5qfM7bFCPugp7eVC at SnK^a=Q1
zoNs?SkqG>#29=(yzX}Y7+=Z?UqVSC(b~3hwN|BF%#bF)CDo`tl3W%IMvWi8+toBw<
zfo)>^!GZe1*^14&6X;od^_wc4s9AX#Xm=l^4t(Q>a0Xn1dprVnqkmVmO(ZzA)TAYT
ze%0<g)(7wz8EnNC%YjG&z?-1uttl{>{6?6a{guwc2`+DUF{mF(k+QJkCO5<l5zAm{
zSwsnHW8PI9XNDu1J0OO(f19~wX*w&)oiQxMwws$(X@{T)f|Z1ENz#QPF#TvZ52X%n
zGqeY%tEZBdJ=t at _IICrbncXnc{0C>XJDaJ=k-!`@)otb<JCc1G6bQXd2OVeY)Lg&b
zQaj(-KH}%zQ&?v|_-TLF?BqAyhbu_L1no>KXJ1waOn!-*Jr<2qa^B^~R#o%ZHawo}
zIeMyPis9SfIg{7LSuOUX2M<6lw;)h20Vu2v{5cw)s(bg?{(EOf7kzrS-$cvow{Isb
z{06p7geI&sSwhJ<_=cI&#?R5o4KR{|Uc03DkW)As&Pwsql+vCs_d44WB;M%fF>rih
z{P>4=glc#7bs?Qp0!;xQk4+_(w2fQ#w~E&IJ(J#JC!pnaV7HRO<V*-o_1`Sb=yCxr
zsxi1TJd!v|1usq|ExnfURHjbGOAZYa*^Q(Zh+k_{Hp1S$<ER$>bdQh{_0&f+(CgfV
z#I&f`>#wx{ZxQC#a!0$Vgd{O23vS<Dn at nbT^OJ~RWJ%IRt5!~&yP%ukS7q`MhFM+v
zKB^m|1Ph-joZ1KJ#Sa(fHPc-hRtiNhEObt!%c-UexB2I2k!<J6&CG2Gp)T|w&%7UZ
zyx7edw^Ebdzoj~T)Kp-I%kTV~PdRijK4~|BXZ$+FIapnM?yW(UI+q5H?#~+izM9Hj
zIZY>JR#dpQ9H2fpd>T{?XZ4(H^#wVVm$>lwYYHfTtK~Lrm*bda-W#i9#eGISlAo9I
zlTIfzx>=pQgnFS%py3vdr4%SnpUK;DSK23 at jAiDG_vRP~nzcCO(0!{UIKj>rciv_$
zWvZ~YJC#taq2d$m6YoQd7|D!gN~braA8gq$P%Napd`<)}65_J<hKgN;QCn=KG^viv
z%C#nAtKL4260nTTe%VQ#?fd#+Xz;^6RX<LY|HX5Pc(6svS{t8Z21V}tDQIT!jPEwk
z`Ri7oj`X|s&z}9R4c;SnAc{UL at CKlEcu-}1T>7-=D~ax8&lN&ZCc9-G+8e<w#6N4~
zQlru$b?v^Jf^)6?-e=S+k|)mt9y!>bmCF}81k6m2*_;URZLSBnRJdCKXtgv5q|<Dt
zO}PzbRDKP3c{0w0&fIv8s!}>WE9pzw_HU`FZLsulCzl<%9;6I_c?@>5ax`0619>`J
zIaX?-6W~|>u9OWC5XVx>@;V_&gYUu3#iApJPjPggcl`c%Bw=JHGqrA!jaQ at Ftkbj;
zD<DTUvDzr>OTaw(TOo)v-*>9>@Cck96KCF81-<lY#1zz70_6})7=0)>lrMADwptXI
zik66R+8?!jRTCO?tR*RF`^q*0qSZiBQr==0Y4)gZsWVqSHNs at _>!Ydx6{%~brL{pk
zEcAc$8GTSDLb(qC5Wpy9$+&7Y6(2dNd(&#!*?#Xu+$xlmG^&akB2t?s+>ZI0Kx=?4
zS3wzyIX>&}e}naKY<6*UPfoI%2Jn{e6Te7AOk;Jo<N%luwXHk%@qu_5-nM?l8R!j0
z_YXC-7g1SA1)4t at B5XYd&<Fs1$o2rxu(8yp$5lEcEuYbkwxh)({3ug)f`L~mGCGtw
z0>a)(SsOxg!18C2`nC-xfSxqzdU6wt9 at 8AVjuR-3W!mBkLx=;6pc~ft{>ql{6Q*6M
zLeGA((#gh9PKs!qvx7c>^a?(KC6Z#|V9e at U*PrMvS!q8&D-KEINIUEuu_4L_>@PDb
z#oRrv6%w5MJQua{gjwa=)KeM_8%gU#Jk{CwxT;xMCC$;-UH3H6PnluBLA%P<wBpKe
zJYp3zF>M~Qr<|m-^+;8!V_TBwsigg%%OU2_nUTvHS&WuPhT(97qVCweeg8vU%u!L1
z#HbZdO*g(3dDS$r;dLzorrqVc!=YZ#Yn{3mwMbEL at vMcz_fmN3sfI<pUv0!KweCy6
zH5;(x060xRfu^lwbvEX<f at bAjsxq$wM}VC+y;bS^@ZsY~-%R^NyOZvGvI!Vo7+pdz
z=ft}#!E>$_4R6IB*4WDSm6_1^f*x`?#+D{TuwpwO&ACaN2)&jrV0!zxf7gpOn6RII
zFoKtR%nssKa_KUXBRrWWWmSAoznD36<r7as9s(Dbq(7i1$%iuzDoH<qsgL-B<O2fQ
z4+ONaEicWI+nu})WCvTrIE3HRxhYuc`@E_w3QQw5SZg<PRHtL8mI+g|VAz%*I{n!I
zhagY8SdV0xXn8HL9KHUU+Ep_$Dkw<F>46gVg`YzcjQ>u|PvbwPo(0#ctDV&1>!XHc
z$ZUsVD5Gwv49N$^5ssN at mqj%&nd3lT*T{~Yt_ at uQ;-A}No*yii*=S0h_~99p30pH^
zBwmne?2f5=;ir4|A4m11R*C*bOW4|Sy2M)4smF!JyL6E)_iu=;5>v^T<JG$ao;apM
zR^oO5tUFwq3J(d&^0|o?N#JJiea(Tt!nKEz+aEK32dsC;IlQ70R3_Y74(T?-CZ5Vo
z9Myx(r3Ut%I4}ets+06H6He2~JRD{%Y>Q@!10XBO?!q1lk%%|1Z&IGLZ_se6|6{${
z;nTXNk|*7vXlpvNJLFvGOguiado!|Ubd|J5!%D#G=73tap3fuKLEDlWEXM!-J4Y+;
zB#hmh-L7pCC1(d6EB*SV3UbYUTztv0^{N;I2^~Uk?e2ru6CcC>GaydHy;#uw<fO|-
z&Wx_o8Gd_zXk<pg*06nQ;GF7dUw11&tSVc?6~U^3_`yvwqB8zjU-xscYWySO%pb;L
zmZRdBS~XvRd$V3O?*KG9HqTbY&%;oZlMq$f>Vt7xQZkN#8?+Z1LJ%cslNaQ<imt;o
z6 at O|xhj7hv`mqr=)2rNDyxm&zx#JvJ9XY>0w$F;TKr6Bv8=F9CMp1TH?ASis+Cn at -
zbxhA0Zsh0=%4wIk$@sAsfVCvJ at 8L4#Zhl6dA;_sQ@%H1UODK^(qRd!AN{4HM#L1tk
zK$pcUJ>!L7GUS!O6UfJ}iXYcb1N)^~_}#r{@=;IT>B(s6l>80 at 3}LwbHMo8WsJugE
z#hq}t+W9e;@QK!76RoVx!Sn|$O{N&c(&UMK&L_S{s&eUHg@=}az^5-?=K-Q{>m27M
z@%@J2^noDY7yp}}CzdF&3u_fuTt~!oRaa|8xl6;NfS;WEp`QaQK{Ie?j6vcrfqn*-
z5x~%(1h6=ZT=s7zh|N8kA#39QG8Lvoj-Jrj4&~al;Ze}hQ;rEu#=0+c-Cq0<g0zj?
z?v$N#I`9 at DZsjW#o)fyplPd(ZHh13qjb+yq*7;2^NVmir{q;Rq%RU4%Q<nyLsX<0*
zpo#Fr*VtjlhG#7Dv>31Y2#3nUp^re3IK at xji=CI`t`#xzPA~SGjWznO4784ufJ3n%
z=6&nSi&!pv;r4x#pC at A<%JSDkdHtN;#6sZ1NrsS=ymBzi2<_eYy^|O#^amcgQul~0
zjMs$xKQkGSVO8;TCQ*Vs0gI`yj>o^~qL%U=SV^S;|0w;f(!XU-gqyf;g?p%2{QFV_
zvi0=nJOf^SJ~(XQZ%ox)A`#(ccP}Dm at _Wjpv=ob7u{}Yw<>kk at 68FQ^q&&UaB}&Kc
z2JH}B^)ushf+KMo+#WAI@%wKEtwX at wRC4ZzNJJtsd!tNvLVcfB3Cb^@VCZU(ub-ZJ
z^(`59FgeYjpSi&r8nXO9w4a-|a`gYg6FZjJuq4jBa;|(vs8;<6&tU(b(yuRrqucBD
zu5eIF6QC7`U_}d*)LVN3*8QES%m*8LxsH@(HTX6&s0L at a$#YBHozQvEQ~^rk_Y_Se
zD3P71rsa{2x#Ek&9e)>od`Dom6JfR^abx;hlOj&8qyMW*>D&Mp+zS^}+Dhy>_Cxo9
zHQ5?kP!Iaq?~q?_FzP;7rnC=?_)KWTUAD1B-&Ibm<}xazXSwRHcV-r|$T0-`Q7F22
z)v>eWHyYKOq^injZl>Igs?D`$HNmf6pZo0dR)jMGL>4wnS)S}Ra`xx0R8wiqwK4>k
zH7pVZk?L|neYD9@(|`gCR7tkj2-BlNwJ?Tur_%qEX%(Py=`z~h+^j|;z*?nS&p{qO
zvleU-XzF2K6>L?udp-gEX_R1TBq(^#bw7bAwSnXV)=<mYfV?vhGE2Phn7eQ<JDm%z
zLo6sQ&`W4wV-0vT?D=8mODyZv at A;~DXO>mQQUI|0!0o{9PoVx-{V*LRIQ_sS$=dnD
z)-l`7686wY^Iz|zChCqyM?B!5q`?M+#En~8(_y%YP_CZXtkaSpdp3X4jS!TcHiG3N
zi(eHqkjt!P_+dDRrWvqprvRGHKg<44#V2HUDM8FC_M@#8 at Kkl(d!@aWE&(JU+AbL^
z!c8 at W;qnj0R~eV%cr002G*a8pG}Jy}BP2x0Vd=d<72C6cDs1W0*MlgLB}Gd?W79D<
z{q?<GPivok(S(&-Da%62zqdXkUmO;>vAJ9>gTYyReFQSmL|9w_GVrqot7x55UzgEE
z%^y?A$iD|pv<G-f<<iznIf);6Qbo{j`0hShRXd0k|8T<hu;<;>d~tmIoYVAuPR3!`
zx7m6Pl+F|)Tg$Q543)Y08Om+vbXI86!?aJb%DA4_l&JO6ZFR%|T*3jRIUwPKLC#_a
znYDoE%w11~0n=tMc?!wK4E@%goS`ah+#+tw?JmCgU!`+}v9xB>nKVM5P=!m2XTR)e
z9V&AVB+JKifUBPPS~y|Z|G*V`u$e7GO&Ya~C-mC%kolAxn0j580OchxYEGaHoe;NA
zgIsa8Ed`TZdA;YMs1vWf1clf%<S^-FzynjyGE40?Uev<2^skQ8=`pTBs=#=X%$pB6
zD0lZsHzjV;v0DcR?)j}hk=AKq>n(RkaizUYV52}X|FThN+T8AT_kNLSNm1$2=|ga7
zgJ@>X%-0|{%ttIP<$bh?pFtC5^HHS4?^H@#`3tY|Sn+M|3eV9}yZBaW2?*ymV`1 at -
z!o-`wpWYQCn%|trZ_^4J#9O*tE-5!cGz#Wiby2wRNAKHDZOcI&@E-`KCxHGf9xj%i
zNAh7WdFX+CsJDvksEwoFypssoJmK^IgVY-UCgJnHYG%9sWWmrMD|wX*(hjzyIbtk9
z6$%?3YB~Zv)e%GXV);E=&R;bXEs^_;pGLTR+{Fc9z5z}q-<XC`!)s9YRp at 1ehrxL=
z5vKV2f_37X{2V+2gS#M09@$(1M?IhX)!PV`ue1q2QA+*}9W*~);g&LoHma1L9~x+G
z2-$zs9k22QUyIqN(?|E-mjF%rhMv>P`zRM?!{A>K)sL03=I;f#MKz5=$(e&@r_e>M
zq0RrR?s&wNe%8zLKbwF>w!GQL&jw0EYLAW89`E2cE6=$)TIK&~5URb+FCs0TUWGKB
zh;H+J+_7Je?fPHfoU=>ZywOxsZBSy>_mo7ejZc27m=0IH#8A!93&Trh9X8-2IfQF_
zYa08Ug~5|Gt|j{nQYY<u#tA$?dk$r#jm`lyBDZ_z-_U0;1+C6L{iWzo at Ajdlx+w38
zvX98 at GkZ}1?*(-MXke?voU?kcY^F<%=#?{lbPuYJ_ju%hTLy6VKCv|2f^MpwEd<e@
zwQmoopS(m)BIQ;n2ifG`b+cO~Lr;J$={k7WZ7AORLZBI|q!phY1#3 at hKNcKVR2~WC
zXW$)hutJgfwGrcD5|^!<tNA9v<jCLA$+Aq2gu&r_iLMPD-)vYQdScUz9TQHP#=oq+
zfjaj<OXZAwE4=4vM(l%%?QfC}iC-xxJ(cZ20k7_UO{05m*U~Sc5{+Mk*lTRI5hAR9
z;vn6T8FlUg;&1$2(?JIsBH{~c)wwtS?UjJB$3s3M`m+Iz6kwIku>1aX;*DR_x0$cS
zdR*+?J&$G3&mm*s|JZtcQT&X)D7{J8MhLs7NIts_%HRarMz&W%)cy%Mud*9Xwr6c$
z{I5|0%je+0q)kGV7h1sL&cuy+MR(ptB*TWvey7+EzVi at kl3n^bZ2_Obw|_c%cd;xO
zuD2X&k}%+QFEaVR;TinmUuE<0q`Ga%MwJZJ4Or3L(Czw{qC+;zibg&%8L`mnX`dxe
zNXOj%KHMY$-mLy%wxX*7ckVX at kBZ9T=^gYOudiVA&{^AMB<$g6yy-#b`?Xkpth8fo
z%VSw}lbkH3wC8j}6G*Sl(wYqMXUwv=^%<&v|HsYaMq{rdN`rx0PRD~C(8(*I4wu{x
z1K`_P?)i%CJx}ff(S)Xwq03L34DAVxSU~b&HJY}^#2Y34U}5=B(}i<odu$~vVO6+7
zCHcWbIa=3k&&Kw%HbA<Ki<6f?cg&V`Iw-CS_ZoOV)DHt!?f%;cyvTBtkt#E|kYnUb
zY?aRW&Qx!H<g)qLiL}GoG<YN<&`7Y1>QuF<ax1s{lGs)8yYWUyo;drX6I(T*Pxthi
zy)Dm0UN;H8eZv9jEnsI&3zm+bp-EIOhjSkPSo?{y|5-0l=f%!U#}`e;iD|j+jc6El
zxccNvRC2-Lu<$WHwF}w}oY$fnc%6eX`(JU#uXRyN51P6k+72F6X<Lmw5Bcq<E~+Ec
zcm?!ZwZv<%deD8hvxlzmN=4N`7aoGVY=O_{@Jg#xXH`_42CmK`gOVh`(H_82rAipI
zL%*pz6mWq5XXl{;R78x0wFHSJ-0lJT|F^nBOODPhoM4gkdH@#WB9_5c$FjV+1t)>u
z<sF&(T5|SlH;w6xnfi7 at 9CIi3W+hf#)FQApwOI8n1g1Gv`jeK>5=PC)U~00P0rn$U
zrgIrdys?YgXdhKRdoz?HZW%UweU46CYA29IQko{xeA?MwZqC>9#w`)Psu at -Laa#eq
zyuNabtovK#R-kF at GoiALL?rGs*P~+tI-Rv4*Q5n59>ns#Ux at NxH(4b$7rfj*IP>m}
z!Q^|fEoIR3!%bbAE@~0)465{tMDBn^94s?w(1f6(-7ZZwbJjCn?4qf1yL&#JE1W;U
zx(!k2{{<^-wv50lO&;63BIjrc%!k;|AKhRZ)3z#~p2CZ%u<GE<5$8AzE>v-ZOw&k+
zXbevXEV*{y|6%08{)tCp0p8y88QB+QVqmq#o;sY6&sneac at YsWcrQ!(>EWTIll=k{
zv+ZMrZgoC3^fR8Xr?c}3WDeMdl80V9#z~DYH<q5Lw?W9^s$;!hA1tb+4!8BdAmZK5
zaU*elSbyR#0l$eJdJ&2aY7%bA^BZjqq=!8}L-cDk;;=^GPSI?g_)fFjWkjkg)EJQ8
zJ(??{8Bxowk7yb!L$c0!+gTS)k0DjO-rvzCIT<)xKHDt)bJ6P&fg}TFC#AUU=_eB%
zZbXS{lbkk~Nu2FqVqX?@;;p(vG_YY~x>$N3k5s5J1FK6WKQtOQ8oC1O+Mcp!ZefQW
zcMl%0Ye-lO$vKMUgRaG!c{;(SLoPePWMC<=;`xX_CPNs?2S{W(i-T~<N1YcUU?ZzI
z)MFGbyN<UYc7V+!<aN-}lLBFqE%8d#rtOHbvn`r5Mf?s^@!IMI-tirQ4>5L<Uz0<+
z4l6rq=7*NT#vCe-?kQG3Y8DEE99ebd0<7BO1&Rs|B>(5S1xq8Rm at INr+IQzZ2RR!q
zk|%A19e&vOm6dUzFV{HAZj>dj@;I#Lmj3&Xs at TAurgaTUmvvn-r`=_dwL9MWV%c!U
z=fR9kPt;e~iI^;_NI+iTACZYyls1BBx#>IgC0Xn#Cz4k<e6PFk8Db5|;ffL|%5mD+
z6EDd0&45{040{tAaJkmQG)^=`aqnR3iqsV)!}No*s>aef3GlRPySy(b9S+GHp7O_>
z3$8hmx~60VGSJc81nP at dvN)oN_lJbzrf=}W-9T=He;GqwcU5W6?CEbOs6En3`<lQe
zt>8p@;5849 at PS9nL7`$?9q+%~<39VUngQN2-t%L9pkU=-n?9~DLjicMkHs=|*bBTi
z#r%lBdQR|xw4(&#3+VOFqZj2i+vi^D1#_+8jRZLxXL$oG>Q3gW%$cGcJiUK;PcQ;k
zTEW5|8-+q`e2pEmOx<*zQShK8OUag39}#noq&rKh>!{=Y(aVEpOtD{p3cL%#f+Pc8
zF(tH(uX%P at cczPZ@qUh0-wND{UjNq8tbhHB&)}zNR-@;>)yOF7tZyDOb at oL`OA>+o
zBMpME6`D<**~nU1(i(hZfKsy?d?Pp1GN!(rt`={@ftuW{+TT$ET24^dF37Q at FiIXo
z2kX}#;y1>&Y}ENa%>*YH+)vPf!G%#guu66~ElW(L)NfR2M_2a!&<2fW9|!KD{Zr?Y
z*lSSDiJVAW7H9YY?;}fnMh*1}jA3((xY9wT9Fqs-Io+Kb9QcP}Wns=Lx7w_%56IVO
zkl!|sy at w}YtM{X&=~dw2L&<&cT)C}nbW+GPX9}-xiuY>F44Y_~yMjE at Q76c+^DTGG
z_UMZj12p1axsaC)Oz?@oLcjz=*|Tkf!`CM>&#Mma=O62Tc3-^FHpG{)TUGf&8}kp?
zi*Uv#Ul4WT?J at k1#yB;(-^loRG)gx&?YaE at q@Nz0I!XT=H!XZ|W_Chm_BO1M^gojj
z7wMnWoLSmcqtVOW?`nOeP^`K<edZIN$fGZCKef9&H+`;{ek>@FVP5HbCSmt9Q)wSJ
zn!r0J1(F806yOC7cZx*YgA-u(d{#1$ej?t}wp(>}MlN7<5S~cj)!;jEU^6?ssIOMg
z<1?B;*HQ8L=kdj5i&%b at lAiPml_`T3;>^?)OfAY;ZRMdE at S6ca^bzk43%IJ3#hTdw
z2mTXayLw$xUfw2Y1BO2TG|c)y+lY at hUTzE6k!baT9}V3F#4lN$BRtEnx;qnjU*+Cg
z>%v%5xoO(%&vA)<4l8E(E8GL$c8><#;UG7I+eOMR6#K55pldSM5{+zpRNnT$O670$
z;SCPn7iG^>&5Y%@vlg7D)7h-A2+t$Vf%k!N^v|2XnG?zc$MS^oMV%`x?iKq(!j^<y
z7z=ninBZpuopQCW=_S*TBxWI#Dii7b3?57#EGQ(uJjZ%;%ht~9h~E5F0Dni>Q|U7u
zEzWyMqXIp6ba?-<HCLfnUw;&=w`U29WUlhHDuh+w-0Ksb*!C~h=qEF#ny-l|7BiKQ
zwHiMDQlZ$86Q9Nzs at F2P>QRTu^OGAKc5BgH3pEzcKz?ZLUgQ_j`(R^ZX%sKN{}}ha
zsZG%^pvU-!Ir8grl0wDgW+sEgo6CEs`O>M5o*mw$8-pCxydgXM%1g(p`Fjsf&3u~M
zNl=Zf`JozF8x at F6K%*)qS7Z&F7yZu6DWNlub5`W^!@_d=kL at Lo#+}|OUxQ6+`DgYV
zhRNy;fypW=?NQoV?H<??^f?aP-g94Bqm|tNdEw=)3$-vR+`k33Jcf4Tpy=YHQ2BcK
zN}rdLr254B{-b+lEWGvPbks%te7CkV#h$SChD*=tdbtZp*12|EpUv|aKo+^j!b;w6
z-m3np+Av7LjqmS<08f;i{8%DcuE~%qZXx&9h9v6!t_6nCH~fyw7qQ%WOjMLVJ=$pg
zfoJBo*0=?2zKs+W4v@}mc$IAwy=v#p at 1ZTPyYAS$Yx}@&`@OlG$GU%Exy2^<(>Zsv
zbQJZS;&ex=lzHU-nPuo-4>LP;m at Bw{^u4>#WDWo2z10`tITA%-v#6Ey74d0Ca=WFq
z{?39#ZMo&UCzE{o|B+j**7mKb#bv3(=<KGXWlr=fQgqJ-4zep;wRMN-2(|d_^Bep7
z|Lz*ieRET4h0*lZu?#n+#YDTUNR~_m)8u8Le;htOcLnTK&1rk*>&_$hw?;*k^s at U+
zan~0qt&eUY`l^d6F^8zPRtiEo=UmN`LLSeD2_o`mne|?~to08bWZI`oy4n)Q<0YmU
zsZ at _6V!5p}K#I4hKWt{bE_YyzX*K=zL%4*$1bu~Xf(W&Nu75gYrJuTJoiLp6pjUNj
zn-4$A8{~yOt^!vnU&>GBo|Tn5-L4d>`%!S~YsuH at 1$?3PQd6-lKE6`pwJ&p(CT`HU
zmjWtI-G$NAL-Z;I+ngr?TN-Iq&CzZ1N-oY$+1D~>=uD~pcnOQYaTF64KolRO`O3Dv
zbYzyhJ at 0mp-TR_Wr~Z1wL}agf=yM6XdGOd;4KlM|Lf|JWX<Gs2r_8w)uqH!G_~z4V
z<wtrQ>Z+O#<HMU6{R at P`k4#&C8`I`QrvmXXHo!2}BulD0gbbyor+e%i(48GtGB at 5^
z+<ePdJwN1J(t2cO3iCo)7pX0*a>0F?p|&ecbs}g&d_ey2!>Q3k-+|*FgRMT&4ExUq
z^;{8igB6ZHAS9XBTHC4&be(181O_`(W(|e>CLKK+oYx$FGIgFV)^&$D<Lud`HG5#_
z3#AMPMeT1GjU6wK+%Cud^&PB<Z`d)jZPmnN=&U;R?i77AWUPkY^^5g!M5*9{jl%gG
zg>QOZi5zK}{ce?Vai>D0$J>Ffrl{j}p}Et|vsKKpyBiNkpn3&7_AhwsoGFg<39pM~
z&V_sr45FsJMk=}Gl&|OR&+*!rJrv=$Yky(D)VKcFPkdTL*hOg~0+H8R!5PXkJHDGo
zZs1UV{1x7J)jEB3ZS#!wTqyWJ&F$KF%-dr%4^*;`a(L79LxRZpyB-Rn7=_-qcz4$^
zEO+=#G%39bbDwBB&zjE at cs`AjePxecV)~_zUdnsX8XZf#FtSlrbi?YyrQQ>rwq1oG
zekC~0g^QyCTbd@#Oku139{d!~<iwq1k2)ocrWOZ at QFnfN?y+-lOej4ib2S{?jstTC
zgYj-Fsi5uZ_)NaznfmM7EssSs<xa2anVlUO4LPRNU!s8roL~q*NnOYz_r1kR+Ao~0
zUsGiwU%>Zpc0AGVox}4s&4C0<KgWm8C2!v&Qam2?TH9$-fv)f3x052%j7=hgOSBq>
zQ&U9SE|;-kE3MT$?XW`T=wZLv2a;Wo1PT*o2(8_Y at AHCpPjpL@{}sBD;8wVis`e+Q
zbe%}UEsSutWe_ at xNP@`c{k{6rP1!=jsa1P`0%n_<MSaz)^f5M4B_Stii<e%hKYUcf
zp_;SHKK4#QP}EqB5f?+s%XFf~D99ObN(;fbI0!L1`QdP|_f8o?!s^3Z(?21ax)?t?
z-3SlqPae6n$g$zgmyS8e*opNY?S%9#Iov#LT)b?s_88`j0TMn=okwniRo2wlwBwm$
zfsI?JS8r%^ht7<B%8dn-K_raZAnvkC_{N`|Wsf><HTCMX3ynN(=idL%s)?p{?<@8F
zFI#+UF&0bkW89Dw+}bG7f1$m?b~ZBmD>>_`m?0}$W5aR=O}n2jDZn8=j8mu)o}|4X
zkvDqc?U_9TXQub7Itf%T59_i<X9A=9dY2&5v-0rKt%fHwR&QINboZ#(NR;nr&>D~Z
z`(G17btXfH`qF2g!q)c^b$siSaO=o8pDPriVC?1SYhuPxIuque$?Y<)S}iSWzT+{j
zS^x){@xp;w!wo#tonM^$+q(K?&iI+{FVw(6HrtA!Xtwmqn74|K-`Gb1BE4^+InTJ*
zG^1sv`DX8*(pKLv6iaYOmTeO5 at 0l4Gt2(9eJkrf0$79*>9KB3Ad_PE?X^z_j_r!r-
z7)B7$1yI`<P$S*yvphBrx9a*$9RFyv(@z~kn_P|~@{i(x|CJxlb^mX%w?Fm*z%!;P
zlxd9(HYimpwoG>nRl3h4E9ZCNGZQg<y&oC!$QA7fzzIbsRPW5nn3yh}4Zn=Da4Tc(
z9;}+By^IM*o~e$j*g1)=iz>a+$(~GEgUiNx_uOzN2ti&7j0Hu?Il^&4msnJ?o}*r(
z|7cIH-|(#=D1)rIJl(=%;QM#rO6Yx2d+8N%>aaYNK=e^WDKpyhPZr!Br9HUZ8>VYj
z4V%OJK0?rtBrOCk{NVx+oBqUyc2kR1D?;JoN3PYIru$QPn?qBLbE%LyXoCU7Eon3T
zob1t|)Z&nlPIGRH9a$*IcXXqSoLg491N*QveSFwo37)cTo~E!ukR-Xt;$W6=keOEZ
zbBkv!O#nCaSss$GK6;;~u!?8HW1CNB_SngoYfL!mzR$^Z(%-5&*(3#NXeI+wPd at GN
z-T#WngaPf0#_H5WkDZID?`MaoR>$5>n$+#Z(@F8gPvM$W1yA9}6oL{ylRCmz#j{C7
zsZ7UbC}rqqvF;N`Kc->+T-YaYfT}Ad;Ij7$O=|RqsKp^}MEVV at emOco&vu&OB=s!4
z(>|0{UeNI91(kW%>`rAUNqHtzH4+3wH`ihgTI^7xC?2Y}*l#jk(fsoDB&mVZ*)7DJ
z!TzSiz~0&K7eim2yp<$n_r#<2n(aEW+^c-4RZsF`2==Esk9qpdoXFgmazk3jv-cvZ
zw#*jXIt7tW at jXtYn`u`tXMPpMgEKY37w`B-^u6CftsFD6(rjvZu+PE0^3qP8`9P`*
zE!J at Hgu2EARn=8iPhF1|;-Sf!f(qh^_dQwH;@GL1nj@*+Z9_g9Bz9(YIzGzVTs5V_
z*IlWX9C7aHtl<(Fo%@G<ox)Uj<{QJs4zJ-=e4H4onmGE at xx=>d9Nn!Vkjw4{Z&vjC
zBl0|QIupIRmH90*54y!$72D=DM%DS=JUq_O#qbL)U%C|NPAewXMb^^OYn3a5q5Pfn
z<xhXDyxD8>+Iq(|QlfMssmc)y;sI4nlAd=Jg#Z04qdCw)hHQIHd3sc4_T=ImOvC0)
zrMG~FdoN`tx;@$9C=ko2^lcaD<AO_BU7goHPy at Tm#<Nc7=W5Y-fw>K=NBm}(=_w6?
zo>C#aU#+t4O%5^2E3ts-e%>}qzbr+w1JN?9;<REhvRVl{paKq%LWV}44t#qv^tST(
z5zZw?iOPg}C~qCdrIJM3rsBIh$&qek$G!`1IXu!17 at 7nN#l*aGPdT#%UaS#))%KCc
zifgv=N3`-ZQu3v&34)Bzw}z=o>*{tLKWCB)Kh?eARZ*q0p)t%vioX66l3ae4r~Xnq
zF~%hWLUTX&8T_yTmBb83j>OfcK9;g}2KYW$$XC|s9y;^S)vkHdfM(K}0%wz62WDf_
zkzE{VKv+rJlF at a+{I`#rKD~XO&S=)S4F?_69I~)=lXY;n&;5g|o*Uw`q40uBf3|yN
z?{E!}vMK?g)S$S~s}xI9SdM^V-MxHq+)BZ)SH7ch;qX=vyW=~h9>dCK&SB+9G at R1R
z%vo>w at gMk+GI^h9`Re}C1?B7hflXHcT?$8Zi_dfIzcKXQ at Ktp+UsTWMhu`SdH1F4{
zj7bj|P9><_kb>=}3;8~Mi?4Yhs*))JH*jkJ4$ywU`<Y|O4tNNH$>`|Qn)n)*r?XeS
zz)Kn2jI=Knq!?=7LNpIfce2!irYm<U>Z&TgQlG`T<bh9t1Vqc1_V<dE%Yy!P3lW54
z+|IT{s(H<POwBm7<IcNHtY|es8T{5u(rn(nJ`Nenp5?Lo`v59#DJXrdrtT+C^d73;
z1HW`VxPVCCDWkf<r4n(f-P|rgUJ*3U$z`>mbkBNtZ$;kI!j!GryJ4u|<#3<H!V%X*
z+x6`G?A$XqX5YAbGTj*7JJEMNI at ZTKL&-I4L~<2*F=z?9WyxkCzN4Rd;_Z)mZpO3U
zr~YI1hZW7q`+(}~HYcCeamu*;vb3f20*<cm=1D_8#}P$yWD$z*wTQ2?)B4c;mnXi!
z`DTaujfBg&`-5dq at z`0qWe`#`%9^C?*}>m6K5!`0bu>qTfXEj%!t_565$v?*u at i;x
zZ4lw>EgWrrH_;^T;WyTq{0xqH==m+i(wz1ZCOJFqHiw;Ra_ix23uD`f(0iJI!bb;s
zio>ny1!<T=Pp{IHg!H$S3L(Z2p2ABN&dJt}Bo~Fg&VghYd9sU}a(!FwB+g{tQD?EI
zRoOfzpNb;XQ2Gl4U&(-hO~QPGfB`kg09PWs)FDBsmXRC~`Z_B~N>&E$vuXVXm-RiK
zOSPZ&h#+KP{^FAjUHYU48qjMMyrEh#yirBx_T3dNHQ at 81wJT~nllO(HLzN~^ReTY=
zv72X<4o at f+cJkT!O|dwY!dH1VDBAK=_DBA0k4jYhwMb=!7iP|Okuul&sTzN5F%*&^
zZuka2<kyRioi>`isaDx?(m;#E0qHPbcJWAsfCTZTXcb at A#hAU&k0F7 at J<N>@Upu=8
zKH^@*3s>_m*rJ;$#}n!n3xwg)!|<tscY?UOb-pg!BPC_n6f+&Lm|_i&HE$u`EQJ5B
zl)C*Xt(G4lJ5E8B-AeQAwhOD^TD1yas_<go)%=(jEyU+100s$HyTw8KXPJ$Opj8>e
zzN2@#92VyQ>LtZab{^PK9BxrBhy!};e{zoi2bCv{)`YlpB^-fEcwdIYytip9udzxv
z(R8a~GyE2IDiJ8=fGXc-j<J(aNF%#l{2VRVb1yE7kfFjs$>JrOYTu(iHT<=L<|@qn
zz;nAzyU6~Wh;rlT+NCGk4oLRc^RzzbJj>Ji1~c7>^4$B2e at 36Y1zMu_pZs02Vvqg9
zQ7;T?PI9r(l70;p=e0j#55F at 1YBH2+;8R*p`|B28-ctagbyeG2`AkJ9T at u;=v_ESz
zl4}>G5t0 at G-jn{Uu-pU~;D(R~Rq@%sar;c-M6|S at srO(jN&{7$msUXdYlvEY*b4Sa
z at lC)R5$qIyre2RRN;8FDJ6RSG-b2V;j?X;xh16@<!bO*#&i<6B0Y7|m$sm|%^ivjC
zhV8h;WaVCJ^nv)7Mt;pz>rU}dB75OSQ4CFY_b1N=3 at x5D{q^mGb60KCBscub at Tu0%
z+ at l<U$yYPdE?JW^YEsLTeoGC97fOVGxfAAgd^6w{EisPaM*?C(8{+rJcNxu!T!dGj
zgj`d%d$H{@9l>5BEu<xvse&`l@;+o9H at qGq;F`Ma3!;s{bJ!vf5xt9>EVXEwk<!sp
zI?+^adCz22`o(=9wC)qkc&V<+gZV&?cJs9wIqa@^Ad4J}kC|$ZcSB~T*<{BOYw!Kz
zhQhZ&D0W9Mm>)IOc|yCY;XMr}kFJ$C`ToE`PLe9fOS{a@>WAVo+aVC$@Jnv%{G)X7
zlO+dsbldY#7Qx(8jxTLYU)kesb?9Zx`>zjiC?i+@%sUQFN(`iv-KPH5xgvM}>37E`
zfuYh5mLv2kazu67pwiGUQHqXIm&5a}Rgk6>1(=-hc{rDNqVtfMb at IBUl8hY@R4uUd
z?aTp_78crO+g5h8Rxn(gJeRGlJM%ypkvXqMj`V-YskUrzgr`0ahc#@`w#LLXT(c)f
zI~HE{Bij+J^Hfvw2Cly~C{+ONc=}K243nknj!!dos>4fyX12Np!^|{P at SPAKyZu)9
z2A0*jB^L#~j!cpwyB!OJ6BQ?#V&BW#$GEMGm{Tth`qOs5McxZAOB-o>durT4y=N@=
zr76HHAL`zVZ<pxktACypxp5;_ZHfD;?$5}tScE8rh2d*!&m;#B$XUV}gd2(#!{!n`
z#GaX61u5k>EYh<}-WR0)0ERfA4}*BKkTv^8K_6c4x&N>Vh>>=zqU!J_ts5bu8;7LH
zQ_ynUIN47U^AlBN>A<1B3L8<7;TNIX at 3w(ZFL6WXOaX?Mg at rsSL^M5Ke7HnFy*Cbc
z6)rKV7bNYh{~|~_velroV9acZc0<HE6Qw8L8cyF5LNo*^rPCOexnoj530(%`fpWI(
zt<pr3ZDJzqLuIKIS17DD`959MJ9AfaQSL!HEZnEf8 at ch&_Wj=-F`ViHfQoL;H23bm
zjLi0EHgc>=^^grVslcMD58(dss`{Q6F-ML6gskg?tRvsv)xii++bjK-;%lvE-sjgf
zWqP$FA?RxK5?!CN)EV-)kSB#Ag at uBHnAsq|4EkQe%(uoz>#Vo{VjlImu0D=h71}t?
z4a2O+%|oru$s4Yz|D6OU;a;{}Sn3JZ8t+}yhi?mtuRxTfqiYwQj6NXQ1&iCZyP?3A
zL%;p6oRe6OD8eH-4L8?itG|FQcSDJwJF2I6&<;V)Y3_JTU5I28YrPt5=<=s{$k(CG
z$XkJPE^`Ou+`4&aU}f#b<l3w1LMUky;I{rk=emerId^VZty*&0RrL^<_4*~i=Sc$p
zt#x)<KW6>5ku*AW3nI`hD{UqeCip~gP@@VO06g*e^HFMQr at d~K-}382qYV{;$Q7oI
zta+8ECi&4Vb7oh;(3S~n`x+W2Bx0>1%-l1mc7Je^H33GXh{B5}U7`e~=_X>aV$cGl
zE#pQOTZU3Yg+^mQh>LO}0T5VZ?yEeXI^CnPbHd+;bySxkWGp(YQd8mY0 at dy>cry#W
z)WyP!^k3!9ZP%V+kSgSe{tHgr<f4O2cPqByAw4b(m#>vh<`zjK<dr4CPk!CZhNz}@
z3 at W$NP4=leL&?n-Le({o>NHa(aKTI(1c=eN`cc+cvsTyi_=B#t(hERI)}L{Sh*N@?
ztKUPk<$wUn)i!?*KtM#7?$ITPyf*0d))xwpmb61K0d}uC_ap at 8M7q8hxh;4PUW5Ux
zCw%hCfgO05-!TN%$^p=S7Q8UryQrhQ-E^PV at _Wk!pR^MNZFtE0aC8 at o3YGn+dNfE-
zZw2UVbxxe>e6pE?ycon2ve=_-Xdu?pn!Ii|7dm$G!U0LpniN+cU&`feVm**~7UACe
zK|wCu^Md2(TH%wN at TjzgJz&pBZp?5rt!3(X`KTKkDRsiHzd51oCV$Cs>5j9aa*(LN
zA|%PHJPgsm9bNCIjHems#_k>>u5 at m&PWWIaJj&@6(pitG>b at 4zU%;A?adHgx@^0*b
z3Pkh88MmS44OQNl9rM*zkvnjYaR<?!3TD^dfBu;8jGEfAkdq_{m?k|4;u-v*GjWeW
zm+!Wbv#SH~G>(z+(BoALQE=ZpWN~om6)0e6U>i`_*Ama%Np`Z`vp{y6okByrUIWrg
zWT0-z27<yFnR;NJJ2}@}RPiI at v|sw>h7E8mDWs4v4c%X at fTUD1$}0m)J=E(JB=i9E
zu4vxb%v_Cx!wFB{+6W#akRuk3HfQh at XN#i}UEu$PTU`p~+PGmVMrQT~#v3PQ4Gg;Q
z5g=~<_tqRD+`jGH+Py0}hTssXZ9jX87s!kRa9I_{%h~35^t(lPc<xQyx<7`VVj+<Z
zV)_XrR)8>?kG;NmVsA-9A54sto(SFD7o at WkCD}X4NU<v$zcgC-5VE#}^Frr6sb55U
zkrUX4NN<N!gg~2dAPE?AUkoolj?07tOvr8sw5iC?6#K$~a<;(Dyp6edp`ok1GycH5
zh9C94i3^eFVj3&uW_-AUkk#OYW#AmGxNxcSN3tz6Z{%x_6d%<;0ykI#QAI7_8_rd@
z`1^05x8NX9l<~CJ;B-YB at NG^RatUCbZH~&lzpiWzAW*jMSFTl{yntu7!6EwdLf~9?
z=TDFgYm*im)r8w5;aYB86-`ZBKjB$>{PS*2Ys67<IU}|(do9BWFRUb(0YFcggO-c*
zQ(enyq}MfhC7n>_u+#Fgq8r{xA#{0!>ixq(remA@^J0!|Q^uu-cI+P1fT^M_{!!(^
zm0{fg5(c at 7`fqb-#+_XpaAC&&LgEg1iAFUh%((c at tY554`Bspvz}V at OSP4j|ey|<v
zq-E at W{+Fz at d){d;1M?RfGO=heqHTnyp*)hS-^lLhs+od$Apk|0F6QgUu%xi@&U#oZ
z*p??E^`>8RhPQ>odSwA|C4=ZBv>*)}{<lyvtczV348z^uZl>;{-U9lpOrVYm=pa}3
zUp)o47^>fi!&bZvy#kgq&-LPBI>4s7z`1rF(bnK`*yDAUi+ee&<J(AkfG<cXU0|(+
zJ7l-`9M25*+|FafjUFr*4ao?^b7|oZWreik3iPXkjwhxW9qWu at y@YCw_)&T4uVf?b
zNQR8CQxJKGy9ueRib6hQYJrpOG9;UwI==6pz_G at 2dRCN+w1V-6lj9XHE<{qq?&n&?
zOpm!{0<vx4fkr~xVc}6OJU+!LcyCf_*2T$@W7CYEdd5unS7F-();sV!>GPGmKWA2)
zcp39-T(axS<Kh)UKofIvCj2m>B;dt|G*OPy*5sFJD%m%54p^xBqfHCyMu8Zs-%#^Y
zIninCS*FJD9$irsSoxcdG$e0W{4?Fu;5cw6Q0i;m6YP9TYq!kRB6)$*tgpcB+kFCR
zh{S1onb!eSWDFGBlvXKntr)A1_Z%;@Ji!NFiW$kH8)72$TUkuU*TP|E>~uZkr0by+
zpjlERXe`_a{itj|SoR%S+X^qge5R>M!Or<w$ov}zMLKae at taS0>J>+LE3_0b{f}~7
zGIQ(t2<XjIs46AdydFQ4rKELW;cJbTZ$a==cyS1qZ8bQ1d}#QEY6jRTPY7xU4xMZd
zm#jOCCt at dbVQBuJ?D{rLjbe-2K at Jr6c+Pi&z7NfR2Y992kmH56!Wfi-dAc(CELvBY
z at wDjmUP!5hcOWdQQn9W`?}Lem7MhoLw at _W}WsH;YJhW;(JdBw~#aiv3Eq&4-P9K9$
z+8)va#|S}VfyOG|`gnmM_0vJgQw2Aty7-}Hcim=$OfjCO?(p82i~A3eqsP^^&2$p<
zwEdIZx)9jO77H~HX>a5Dt76;I?1JRa)6mc7b1k$uBxJMS3)Ccx4CUcg2jy($+EHPw
z?UAZ=N2xsKpgU7?9mVXoI#&SK!E2S)1UWkkZ)OCv>lfVBRY}d;e2lp8!ZF%_6=c#M
z*nF(vCrNK(H525IUT^Plpi^Z(3!OMoR--L^aa~$Q(I4>kk`3T1fdsk6%D$&}8X{a6
z|F~q1T7NX-JZ=B0pFn9i=H%1Y$PT!n&<rWFA-g3vS4r0?1DWQH;792G`dc%<i}J1T
z_3D at APIPG6bzt6+>%xfQIU{YN$^Y)cx~CcXg|D~6${xuF^Mf7vKl!I-Ih4AeC20P<
z1uuS+g%pQ9mDY;C=U;$i{Z5vTYNNMOKpWn%hX>+D;<CJ0oLM<1DQ^(8<X&pcDM}6y
z{v7y9QVaa+{@qyU38`)UDJcp3(5T>HYpvl-VrxpeM;%kJdIxKrVYdM_SOJklA>C2<
za?WJ7#`(C$gQq@(x4~e-tLlRiV|@rH(18p7 at NAL1MUch7ewUf(!J at j5jDUjITLG%H
zL%7<dlHm at kL!UtSp<4_))0FLKL3VUuGcR6{r)|MQS-bo~3N~|?<t;{Hwu>wC4ML5D
z`W7W-r7B(*8jh)&&gO>Qf`vGT>^6%$!MX!_TqB{rn2Z$#uQ%h{g|n`+I`bax?3+rl
zr}oGEH7_}w)?PVz0hAB9HU{#SQixmEe|c*B^N;?9hK5VP+32(!XZjCMZ6jfPQA_{W
z%VPJ#_&%%|KMhLrSnU^WXzZ#t3l_R-<+S%(!pk?aanu^jTsE4rJ?vqso=JiGrktw&
zrds^4k>G)#)a3ub;q)&{t&4!{obe<sy+UF9$5cz8wf%0XA(9Ec+c`N-YNvO|Ovlx(
z%h+Fkc6srlmMXTTrof3xM1T`WWn0N&QnZT()ZIS}&49&DzslcJE+iX><F{#%e{-7`
z^9itnIqvYnS7NQH>zevu4Y*48AWLOC<XW|$6hjMG!=IEAt*MV;u99UP$$<tO*>&(T
zlhj`5zBb3XzeyB|@WP8Yr1KU`Gv;b=*_@~18<+AM_pOozX^Q5rx{!w*?cJK0G5&O{
zIhl8%46 at o>G|z2Lbi(9&^IJ={X)SDt88hJk6BozqLeQD6_nkfV_5)4TyEV;*zL1Tt
zGL5|5+q9kl)gwHLWB=o+<!t_ui-OR4wff;S8 at t9U-2R*NJVkEh`<aX2^;tazD3N2Y
zkyJFF{Xe#@1e~g_`yWGSKpH4A#2cv$WeVXIsmvvkAxarDX3BWgn<1gzB15<(LuMH=
zWGXb6hY&6znWr*k{I7kl)cd{v at A;nZ`5v8n&OUpu{ae5FTWha_G&Qc%{ELF+&L_Y=
zO0$sPDHS=%H}mg3c>ClR1@*;wTf<?&F^QiLT=T%fV0Al>8~>rH@&CQfeL`qKm_&&?
zqqp2H$JXWS_sOJ9m}PhqG;~FTE=HQ%_<IZ^Br#Jyy4+Mswqt5H3(R}QMYIDm_JPFH
zc>d;Jsm<fh*CbV{GaV?GK^C(yBR#bA*OjRs{fg~ZAgrZQ>TvlbW at C6)L>X}g3P$;^
zIT5wfoQDb7cji+nO|{{baU`oxj2wKOhN3&8ISBA|bkDhq_ldB^Xo2$sCJ0Oq8y5T@
z?<ewJl=xfB#_EO9c<Y6kt_vEb#sjNJImi~VSJrK6_r1DjU;}tX<echl0T8p&M$3!~
zUVgqf6&_G`$(;sTP@}35Y}9Y?WAv{WKjBNS2y;x%d^Jc6m{9`qenzL*|E;SH|5nw!
zHvs)Zt8aFfPT_xI{Ox6-|8jp=1WLQ&niPatiR}$pGHZNj_jO%&&t8pYNFdNaOW=6Y
zcpaD?DYni68~O!+=Umdrx(W`Nf(|5&kSK`>@Z4(pQ_xn22%jlCMymaqJEV?Kp$n#~
zM*ZSfKFQmWluUx$(af!Ic>kTLbA{<D7qTX!t_0NK+?jht_Fe}>()tYMh*O5N at tUgo
zi-hWUk3v{&;A*J at 8yK@fL>bAoX;l}JFFHFrxIDChi1zRRkQ=Q14s3jUuKn-Lr=qV`
z(OJ3Yojw?aG>Q at Gou0idgm?pDY6%c{!b+d`<=>MG%tsL)PP!3|p+gFy>Ij)t6WujY
zb54Ax%osV=cxwmKZi8O2{StM~ufU#^N_b(#<tkNQ+Wo5*fE?yuZSaK#)lW!PX{}((
zM(hT+sA3TiAbB?*5&!#q$d*9rTbB8^v`zi$K5Q}0ab?IPoaBUNR`#e?1}Auuzy|VD
z>xHKB>06$2yaDU+J|`p?4bjN#1t`1LouR2I)ae9I&zY1!S7Q7z#IkYYC+pb^z8q}&
zbjaP*v|L9>wKy`c2-z(+5?SzX20Mul;>p_P8WW0KqWPUv!U(p=gm<V>m;Jd9Id4h%
zEriiQISv(wd7!ai`%~zAE~IN`1=;2DRSH+0LtF3xGTi;ygUso$1!oFj3-0hZDlSlY
zs8X;Jl^9_s69BTXV(`YW0xc7sYg{P9{q`RajORn(g{k{tHxU=&4py at -wg6GP@-#dH
zGu#I|2%mt&RmXoAIhxKC3s!Ph{#6P0otHuud`#ZqpEbv~nK;3*+F`uq%Asi(cPS}M
z!Vi#jm10sVG5^hU;i+FSzlFCK^xDssMR&QbL0#voOp9V{bBh&4*ZDy^L0>`F_PS}#
zGh~GYE9FI=&uBY0o`X#)d?s9-9R1%AbDt`)gvtTPhMSS^$U?f~aq7kfb6H at Z22U=X
zuFC1KlDW4ov+6<p1%{2C0V}{dwo*8f(HL?MRu at FpHMR?zmn at -)T at jjP0t0sjN-rW0
zs3Pr0$|+$QazeY5F)T6oS6b;+()_E6lEW*hXagl8)deHe0#W)`Qa2}bSMQ(GPlF;s
zjP<WuW5@;a$P_e2UW4gh5kNOF+k at Ukv~6gmE1L|$pQoM%t(q*o>VwUJiK4PYAczie
z7ZeTa3Yy%MXjxY{@2x5>z3MG_f&8D758C5x#~VP|`jyblFPK|jg{A`ETuO3r5=Pj_
zy*0SRKiqO{38r#an0|RcRX%u{KSFe~XLRpljXfrHT0>WvrdB0ZY(Qhf2>GCJVUX?(
zn(?1{D*Aic*%oL4Mb}*59q0&8i44A;oBL?+uYlxB`11I#q!Mu<4RTq871BjlxKGQG
zo#2vE$)c+|%IM}E<bW{<pv?)aF!2<h+jQ0i-hr21Mv$EzhGc#L{QM+o&F-8mmDS=n
zd=ef<b4mCN%ok)RJ<u=VKZ#T at v(2A{yp}Wff{qp~wi#=Vf!Q2RIVSm7t!R1mrXT$I
zT*}!ispnRDaVF#%n0gE>X{hZpXZ*+hm;^WxkO}-DLa^npOmTlPr4%g;k1AhqR46ZJ
zVDqSH at rMMx2v#qe$?Pw7CPfv)R|0V2ZbQ2KD1w7%iI0%=cxQ{s5|KLVpL03|l-<e&
zxk?tysS>ikLyI=6M*&=+NP{sBT#O<IX6CmTlM)BTBj?{?r3_FWfjQ|Mn|ES-+*DpI
zwmc3VyP}=DWmjg)R;2Z!;XG7P5xQ!S1W2b!fn``_#{1=*OgW6<zadR?`^m?{`I|+C
z<{3SoL$0^&A07E}UGA105QGu(fx6;0=Q+-K0($h?@`E4?x)c_D(6!xIVv$zaQ-Bsr
zMdFpf*SEnIL$U2+P<C*dbxj?c2KWHQ4H6Xbpf4bmGyuJQfIsa(TdH_r_CJ+Ai;XX0
z4dUsr_YjY!Y)9HJ7gm1 at 7Qg;k?{TRDoj%jvPasTza2US{+cf;RWaVfG-vE-#g8 at 2(
zVF|PITry;xW_`^kbuIw6NrWRdl>Q50-}@zjgw*q*Tk-ZDmzL^^?e+kr*qjRgBr+@?
z70|U;Z|2>CwZC&MajRqNhgt`b8`yn$yWn6qkIo-Rw7o<UZ6Pm|aPY!8bx3wk&uSnG
zW2GR}5Ld4XL`lm*We3(C1|+k-ve)~yTi%lckG-NDUsGaZeB)p2go51)z!$Vff?e5j
zEf^Gb?N68+u!&H^%y{f3g4|p>t0?fZP%eXi;uqA4c-j)JoD$??;&)=YI-SXV(d={9
z at EZ3yA)mu#3V~Ei@#<`F6A1q2C8Y_lTDqr!$np*}`f^Gx?ZLhyw<fuh@%xkn6b2}+
zg>9cerf+ESytZNz5q3#<19smS917P!Z<%btWyml^SYT$ikc_JXc>mKBbmSd4hqq8h
z^bph@)it>k*6ucJ<BFj>+4_Z6i4+7bm{<+2sZ!46ad5&flc3 at n)9?bcDE!=aQUcRJ
z%GrJb9rmo7R1W|JA*X;0UR_gmmkYLF`#E6RG&Go~%f}1RKCsLGW{l8yt}$B3wH at YP
z0|k?~G7u?4)h?txk8bonFC%>)xV+}{UZ~Gr>`#|d>;Hh38Hb43Rqp*q!45#hb9CS;
zTIv;q1b*G*J2 at FOz;&d6rX%9uev+E@*T&oeT1F>N-z9$FOe+zvM)MJa(SZhT4JQlF
z6&m9)uDDT9aVzsqL53EKR)o~vqzV*{Ex+=5GE-={R)D30?WkQ=Z)wc`A%Y$<0EIl5
zOB&s-0^cfgc-xkXo3WEy=U(T{Rmf<-1YiFfp3{~Aaa&53(`-SlF7{nu+|jNsz>O2A
zJ-`-(FSYGASWFtHIG0XCrXqj)TyEaGiXt^|=ouHm4)6jXApdJW5>i1&zh*D!F at Ls3
zffCb0CG@%bZutjWyh7PfP;Vqi^RWr^zUWzU7K>gQ25SZ2KvH at gI%@?}pOcauW{;0=
zAoRlxJ4?`Zya;dteivWhU&<|IBL^0-wjXI&@S#7d485Lwe0T$u4?vH9N5mC|1u5?t
zn|g)OK*bzn5g|{nd!qT>BcZx$LO#%1{5Y(Xs0uY}!xYEzI8r%8F;$VnH&o&6>TQK~
zU4buyv at 8<cV53y at M`Y3%ovJ9}8$WI*g!o;c2^ePv515ogztS*2`{~DB97+)AY&nL}
z-&lQ^<1oI2GR{V)5d9rZq?3g;cwzr@;NoLJtXZ>Dua{%{9P4GcMH3h=PE#S+x|OYe
zdSyv<JG^AM%)W5}J2)0-21Q<g*bQ-dpj`y5_MAcptpFjF9izY7nNCf_ZEBvwDw`F6
zu9YxRvfSse4vj`o08?~C^0DmF`=^~4&Jqb`0z8xt=h;Bq1|l=m&*B`u2P@`vZBMW6
zR)N$!4ah0{up#lG+bNVBCTlMlib;Z%cCz(yATF=_0CovZ`7T2jvI$z{WOH(9ROEg<
zCGgd?+KqSM3{eJv5O*>ILhkh)Spiw&%t)C_rIc7UVr%ux+-Clsa}Y^`roW>UJSyZf
zM=wA&eGCV4TQAOS>u(VBu69KjG6X7naB3A|vS~ARH7K$iD+eY)80-Acb~N5bVc)Zc
z%xH4RLT at VF)ho1DrwcEfqJ`9D_KU<|e#7V{hzzo2kb2({fR7&uv<LMy{sXm{h}~F_
zWgbA~d*qexZ*G`kE95~&5Yo>6a8rG6uP%G*Xr2>NOTV9heFz-?fA?V-_ at EU&%c0Jn
zyAdJ?A{+R6j#`rVw*P$o(vK9jUHETzE$#Fl_O%~^dHs&6*uS>J>!+}}%obQ1;Z6K4
zZS at 2CBH-?(FqK?$&)DWW?}Q^rZk%AqxZMk?ZdV=+8pB;QSsJ?_e^<9aR0py8<7W!M
zKYEz$kPrFOUrve1Z^3rlg`K|t2_0TGiKvG1SCE{a{vJ^1P6r8P((+d)8IPL5-4JT;
zI7fXPtijyLd|x2_TpS2;?pv|ky{_$j1+Eii5tpg4O-MiAp-U~_Ah1-{Xu<j`oY at A5
zv2F;Z6xbc`C)jEJ&3A!#uKPrnAkzF-UDBb%CM98xOSf|$y&E()=*-C`Wp0K=U%B!v
z0tsdbE at cGJDL(ynic*-NpXC*Owmw#blk-xD)kg1y_a<Yq!_e4MlnKzFxa07958?+<
z_|qfFZ8Xdwm;hYKG^zqS$<+EfZ?-}V;ozh@%rTz+ZgFp##7C50_Sy2jD6geLOeoC*
z!hw4*cShTvW#vI(!ieyt7sSI3xbgBFfiye2RAfXMl7NI*F4qFF<X;Za49Y?;g+Ec|
z^!%D(2Gw6E7{4x0t@$s9_yng1Glp;w;y!;Wtc at 2e5_8;oT+4wSQc_}104FWA^$Q_~
zjm=z!rN%`mv`!(8bUW^o=vtwMK>a@;%=J#6&`l$XgNW`3C8$_p7F`B;+O@@EyV=cl
zk{x0N7u*Of3)J~$lRP4nJ>WDUnpCgpe(xCw0kttwD$EFUxmP5HGPC5M3`I<yel#y{
zwp?s~+DQln at Ri837}5Se`>)O0XW_Rq#H5iuW!&bTzZ(?~XA9WbHAJYI4M-S_L=iJe
z^tP&7kL#?V-&@9JRejCgc5YZ+GX}5?+(U)O_M<1pZpJ==T2vLPjB9rE{+4I-Nzf-6
z3_$?!e9t+Ad at 0?_jUDo+wt=5Q{Ez*I3A{l9J2R8_#W`C^Ey2}eBSthXp?QksIoxTx
z(d)FJLn3B}A-(vL;oIjCsW9*K084p&o?cyOLT!oUg>1s0k*xD&UiQ_pV1TReJmzw-
zy=n9)IiUNHba$tb at nsl6`ImD^PuQU%U;|`|*ES#&5Z3ns%wtwuw{ri-5jN3CvXE&h
z6xV3dlUX9jzX$%}c8N65Jp<bMP;-NzCaolB6;mE1kUrP}!y$>Pk^Y#V)Dz?f*O<|c
z6KWvwtq~(75Q6W6=@L{=a>3~dz~OU_4!D{v*_mtG4;q%&7n6o1NLeuG0wEBjb>g?T
zSFhF4CI>=(p{U4c1w at hV-+M5&o~E~uwfpn at _$G+8z9ZcRzXyQ4DdZqj at p5U^F+2x(
zIqZ_z;gY49cQ1}fCIBy8Q+Ib9?*fCWwlJymRUdZtW!@??#*!eH4xWxH2IX<T>QK9_
zF(OqF(X;NfeTDnM65dN7OQ=05;Q;D!%g!QTL<N^=E1U(3-KN-^VGG{(Lb}8zsNVQv
z3*LuPzA#s_`zS*B_*H*llE-%!h{5Qr9>ItkyH^4n1ByeFyV-|9|6X%}K2WZOM?=|h
zp88e;zl at v5r&EBD#mZAr$nEcVjDB7EOmpEk9P91qj+zGz{tWO2Tqa74b3y%*+=w&h
zv6c|6nn7pZ0q~A(H7jNR82UrKFoHbH at NSPV6!%TTc|(S}jIJhGF|W6f)`BcQxD*Ig
zD6WjQ%b-xgF5kqqXX8|q--M$3DTD$`VhHtIk|2 at WIP@_Dgy#E6P!0=OwJkgD%>2QE
zd_fp8MW6%64UO)x7p?6-`KJmVDnGwJ0ffcG(Sg2FA2={23#^#%zzyojklW1QN08Q*
z0b;^hSXlZ%dFpdeT^{LIRj}rmxBz*!p*nai9;A7Y>--ybvD|8OS?-}*AI87fC+V-;
zY;mL?+b>%<wL7Q|m2u$55F^R3YPdn1QIxD%Ssf)BUN`73l9>0k5Pg`map12vJ0(Z|
z3Vb1OS=ro4C`dKA{KbJ$8m$BS1z1k~eJ&>?LP?wIwSGswr553MKIZR4&3%K)Mol+R
zflXwaT|M68$GGS}fmbCM)SetpeQ at K%F{$u|)Au~3tDe;R7^N4zDq3}y{U?3X%<RNx
zaZ9h(tm3*zhS2Ak<!<6#g;N}$uPdR*J at M{ffoE at cpLx$fN#leXF<{Q at H8jgl2BXGX
zK!q}f(^7pBb8xQEYk;k=aq=nE0`UbZOI>>7Kb_!QdvO<rC86{oPE~=h+fbduU3hu=
zi-&pB<6^V=l*mDIuc5C))1ApSI at Hh}gCy#zo-F;j at LosKWwne-#-}C%jK_uZ(!$8I
zFCf5af~&$T1aH+2e)P1udQ8S~vaGpqB-ux;2125&^x_9yG7?s87?!dTS(zp8t-3*H
zujeIv>_0zKh>0{SG{4(Y<nqk at HZ6v=pd*oZF_z<I(}k;Fzu3g_aT0AP5+eqJRu3=F
ze$^X_jawCkLi(0YmV0|J{LEHwvuTU&)iw>OnQ=)=+{s><9TRab>L}HzBZSn>j5P2k
z at 7@Z<Ejl|s=kaBDo;K?SCrrd8Z%EP?*`7cupd;ekI0L`Z?A3aqDlrjt_RjR~sE)hQ
zv!;ecaH0-;6KMlD?xSpue&+)d9-S-PdG57DuMBbtgf67JB}zAx$xQe9+w;w}<(KGi
zee5mTI^pkPgGwF<9B2a)tRc%b7vm}Gv9>5LCi?}LlQ+~XTOF2}8tFs0o#=+9a=0s|
zOY*{s>-V19LkWx%O%q+*;7a2jCN$khFK!ryk{`lxl=UNAR+wZZ64Og0ts5frQ|wZ5
zkOeEEgPDY<3eIzIZb6+&ZZ!m?+Z~pymTZ=&U=XiJ%G3CW+IgmRPOO~vQqQ+gEO9d?
z!$G at W0t;|ulsUp!b*Zy~Mn3c{iR&(+5SYteg#`eW0;``y2rc at W&cfJvdW6T=e7 at dW
z)OJ-cpdEwah?cQNLl!-c9dHF{y;XT`b#OA4JR0x*^dM-D)cu0?iOf7lGy8A$tgc at a
zT<1C+l7m6E=0#~8!jQuK4zIz-{ho6?a?%8ocr^u&>iPgawEyd~Nl#6UTqMT0JCxkH
zbgGVhH5Tpth%S~xhcT??dVcrv3M>#>fDtifk>JnoSdsQ-=7cPvej8ZAqPm>nxbtdF
zQ*iv7$FFqeStAxZuDJHLzC%iK{W+x35#kiEPB+{A^d<8X{c3he2TfSB0(V0RJGtxx
zG_Ps at xntswJe|L1OW;Dv4;jZF)`K}aiRMgK+u<%_kqbBd($a+m;=!$10lO;?k?#Ew
zWjX7=^VZgdED}q81RB7s0VzHRF8Qs{lha<V1N!o>FM;lcjx9p4el#eZk5M+vb78VL
zdq~+(G(rzz)5mJjYIQ{mio_yu4AVhpl(BhfroT#Lk7zS=c}?Pir#ipRNW821kw4v9
zQE*cgPI91gnwaforu}kL)l<{$?_FGndv3pQZoQ!As?yN3GMa4j+__G*wJaIFvblgb
z8ot91FS$U3S|a`l7n>Z<IXH#JK4#YkM``k8(AZLN)U{;02#I!g at KU}vn&0Q8QX=zH
zd%<i-ZlvcE91B`ryd?&U8sgt0>EyPyKl9_GbeFDAiB#4dfNg^hLCPGa&A&kOI<|DK
z!0W;(Df>a(utiA%zv9t9w&z#Upq_AtjmyEe<Z7zn^hJWI;ldU9pzrOg%P~WrFW8`i
zgxF8C$?%&_Y7l?4X)F*wG|@|Zbg7v_N(rVx@^9ylJ4C_aJnQt3bs86PlxuVeoYL(R
zLlFyp7>OU47KmBhUJF0%OBQXSJw<mGzm7|*l%9K4F<qV>OuCL0 at pjCDi*l^%w)_yh
z_#x-#>91Vqr*wP85b6-b(R^#jqgBf1S%$@EwW^*f>JuxsgbB1jwLq8{Gy9PGu^Y#b
zkyy4*aC9FmHg&gws0`C^Lq5(ZP=$ova*f>&qmRuS)hrNW6J(sSO2l7!77oKRb|NQW
z6nJv$3ZQvh%(11^=_cQ~I5aC-mvGbBB at W*m7REljLeUf65eg#Vf46$OjGplFxSI01
zW0{t5`usFtip<KY;Id<bJtbBug&1Y2)Lr~BsTSkb#Ru}V=PoSDB)cAdDDt?eeluTV
z;Xu3q4=lcjZ#*R~L?Ptujd!bIye8l7?a;}gt6pSWJ|gpTbn1Ke!@BLODoa^Y6LcNk
z$9g07r5R{{m!QRTb^}8oY*H(76QnP(JrP2skxAajs{*SN+*}Z|oFD#Xk^DuTwy|`%
zuzCk}0G1uUDbXIY`0{P*sKn}+(J*o5(|2dP8;pr}<|DuNeR<rtTqtF)rAL9S!qEau
zvOKm`UMPD1gu;fz5W2GB)#)GoTMu2!5y5g^>RZhK&`EvIq9QrD7A!*v_Kr?mchs?{
zXqgqC1GGjpbnV_b*>GWVEMq*U-0Qkg3ZtESA~s<MMZs8x09QUrcYrP7L;@_M^1k_7
z#^ljZV%n9!C+7Fu at X}LJUs}jxkH>IT`T6a`66$ghn+&^pVF$iK5t6$PB-lKsx-}=t
z_Fe`dp|MwYf0}=9`~I{C7+w!#rc!~|E8kp(Z(iSz+*~E3>HIBY^Azt|?!$UGVYz#F
z8_r5i{xFQ=i<X3wR9FvlFDrjqNN>a$(7 at ayU=;6N+kFj>K3JKqmFxp>@b>?417LK*
z-S`5ltOE|N5)gv>m^n5aUugW$)c-Da46H+^s4Zi%Hh*XuP(EZGYffUikT}7I?j*({
zJ1&@RJ!u2Gc~g1ioxC(xkE at 4dZcdg>-==lFw;dk}>qO{RXdV3J=%*;Kr2XPYpa9L1
zr*G)RZN~U614FS(m at dTo_)sVxMT_KxQDX$BE5`EEg~-Z-mPScRm=C&SvU5rfDT+GA
znGJi9F1`HW)Et`}raG}XbQj*lX_$C}v>Z{-P at I(WsuNDuU$wKM!D<k>i)ifZW^USE
zB8z5;pa#PT_BB+Rn;1S_a&w{K{QP%jWhz_~<dh&2ji7hMZCK{$UjRsn@^*pDtrm7Q
z%&pe&ZBN+7qJhXhTshbdIOhP(>F$jXNF(;LGGGyq`^Ec6fL-*f)jwrXM^4_1%WjOh
z)z(gcrPTqe9|W|o&w%pO`8(T()F+O*ZwBG+fBZk37BbTTGh|hB at F<2I>pK2P;t&T^
z8Tkk9n40-oM%$#$+4Wf5V<;e$1 at D7S;P`xBi0tc6QwIye{kUscl=m&bQVuiw3*1}%
z)@M!diJ$J%6VZ{mMvyp%&_BlIn~Uooge;UDUjR`yAq~{aQQNzWx{xA>ZnK408<Mt<
zl1(6p)To2^ZjS4R9uv{-$*&7HLLkb_CJdgFkI_pRjL1<Ltl4p(xp3gz>Qlo|=Un6%
zb(mXy>;iYS-nFZt!)DNy7_R(U-7h-*W+Oti&X%|m!TA5-0EdOKVK_d4cVr=11S)$f
zO)6ImY#RgN^OUC(M1|Oh8U!9A!_Iu_2|&D1pz)Qt^&dOc-L0WmMl_5xB_Q*L*O at sv
z@$+4u(R$;RD#Who>s5-G=vz{jqWX-|h(A5N#&)EOCBz8L6|R08I;HugN^c7*Ud$NY
z$&wrGpQX8GH(Qk0#nn`Znd-Y$ikayLP?qXKRG at Jqz2s)B=8so=-AAqi13j;QyE4a2
z{~;wV74}tP_+agx`Jd^HK)O&FdTD{bWkVisprs}VU(Nr(l)!gh*Ei_f4L}FUApe`9
zQzRk at QfoUgOepG@f#-EpQiu&}UEkvWFD8(!jh#pKm*l5bJ#fi`#{gJ(E=#V>uUY^&
zHdnv3cVTAcL8krW3T)Cttk_OK7>x&mrS7wzBoLC*!`DN7wzDb1y5>BXnr<$m)tpF6
z*Hysm;llgMWJ11F2K1lR;5rus(oo{o_#g%;B{)GaS?w|Kd??7pY2KyZ_nQoqoTM?*
zDmK!`Qkq{l*TpSz!qzcBA-S2hT`F7aYr8SF)>16v92o3mKCh`@!c!JC5<`yrW1pU4
zU_WgzHs?Zx+3LZwWI<MuTO1BtfT+bxD|71kA1s|6UkAq;@OsGIzZl3w(28B{Z9kg!
zpig%<W({tkG~r&<qH=z+{b0p*#ISoN%Ej#U555z-p)XBUS_4tFhB)|lQF3UsXVV4@
zi{V2-<n)gr>F%}=A4c}mcZ6&Xi(p`Gsj!5GQa7b!=7!l)WuZ<&C#NlA+j;;68(Q}X
zoatqrMcb4?3617FZ`zB#cB!;X3Nr&ZAIrSM;2}_QEmw%%&~OM!z33nNboHRv*YX at c
zRs9KY%T8Ud#jmu|LygeK@}K!YMtGKG`bjCIR5+hnPZ{dg?&bDf08$jd0?HL14?3 at Y
zc-svsY&|!;kZ8W<M6~j<ujj?C&v1qiAaZAGkDUNV>sLD~2HXvxU4%2LwfbuEKsymy
zltb3H7I?tnWtaIlht;$ohp+YC&7VAj_feRgfHCtz#vd>n?NH2dzj%4MHOQiJ;7g$v
zJOYGBg8wn+rC`$AP;^2_ at ilf)U^nhz{TGIM>dM;XeZ<wa`-rBSaaBQE0|Cy~X-rfW
z*Z^zWA4rX{>P#1Utqu*qHNSwmYGXYC7`Yh^g|59N3Bb5WIsa{TR-CQ#cB!1LOPDB!
zw>0kd&E=Y at W}tof$w1D`WJ&*IH^zuF238~LH|X%^&csv&(|-1~%gItfs at 7}|5UyeU
z>1 at UlTkhqds2icMs=C$WS$8hZJV?(e1$jh5Eo|}O^A6(cI1Q(Uv-8^U+t(K#5sS8A
z9*RU|m@=sy27yf3hOjgHf%VBU#caRCx%(jPgq#cEoe?&SCM`%oqVJc>ya=j at -rYb+
z*hqg6boxyMRLnSxTZ at m&K!nNImU$M;6Ug})GDhOq0h&^>{)~^aA at nLus;G=2n}w3P
zY(Y0h(bB-Oh11C6iR+wx!D{AHd)inC7O_MH_jtcL=BeF0vX)qeEX=l!@fzbpF&Cx<
zDxDmMCqJ<ynTK7{fy*(c+xR_Z2?}b4BE+P>xOelp>ytz4^nApbR)+_~ua;5>mDOZ|
z=@Bu;i|vd#-kWvWotJ_z3wucn(W-uiiZ%C%wVZTk_OJVE>hoW+v6zN5{M^E5+$O+$
z&4H%S!C)E5=&j!UvocN8eGqrR{U-DeON0t<+)j`hl)+B`BEHpurxomAyWKnT0oX^3
z>}z${Tst8=Nc^X at dykMa4?-lo;?@|0UJ(`dPzr(+jA!RvhH~$i)dMn9)pp2f;pF}6
zgr_d@$~J+SB%*Eo1ntbfVP{IfSnAuzksJz>E`Xj!`yQx$hEkQx7z9G0?C1uX{`4ow
z&=}Xv&PD4jU3vh`KC9;!g`W;yu;eB?*aCXZyIN0Gek>%S=*^KvXD?i~N#*zM6c>bO
ze_y#`EVO1Ym{@~G9T$8Z$isPoiNU*Fr~XEpi*T)?GImA2<j`CpCrMVpUcnXfTgWjo
z;hXsN*CLK%W9o*TE~XKzoT{6%2I$#!LUP&X;%lRer(={k<35P+3 at tRCqM>UpuUQ^P
zR&$@i8nlr~XS9o9UXoqgy(1Q4Rt8r0SxpGWM^&s2D-dVKCgKlr>NAH?9DE5q;C>J#
z4seKH?|fAJ^L=pRoko{}qi2;?yH^)icm1W|D1rQL3A;*BVX?(~OagZ2)o&}gVbGNb
z<{VdJH8!XeCF550bg?_2=MZI<@^;fE6>}9Mnx)(G9SxU8RXYltyX}wK at d&NFdNCzp
z?&;cyc}MusE1{STA=h+d0;ej1YcoPWYWorROT*Dnj(o-ZF^7 at uRp(58_r5nTQ`zU@
z!eMlxXI~29KIe{Ku at IW={O&`n>Ghgu|AG5?CL%Gp;E0?l9;aIF69>rC9}%9wFb*Z*
z*~h%4>l-2ZcW|AZXG2qRx81ibkd<P=Lcxex`U{V6q`RAf5sknh>o&)+A)(gF6vfV-
z#f23rbI*mM at 0udRNqAj<dX at Ad$<S!m>9XlQ-??y+`j_ML^L at dovRYcZcHLWj*?vI9
zzzqpN&C&yn<u||V)Q|?-%G6u_;S`%z{-z>aR80JU at NMR85~EUXi|0CKXYYCqCMMoR
zjj?d4j@^2vsk+;=#$A0~#hr)S*qQw-w&!W0W^;Kc<<fqkkj-)59zVL832oYg7pi9B
zEc=P$h>*f17RP~g;dWZJH-<{NE`IclX}L?q^faG1Zq#q#$L8Gt0jsI&bx{L7{mCFo
zED?22!tLxF)SJ+ARCl{nMa!*d<n&ZDzMDOw)Pg}f%_r~hd^+Q at UOqaJH`5Ha?uYFL
z`)xSPVkSFXo7yCj-H(o5V502fr)}M at tWLSXl`BC|VTj6&xDvobL!Dz=fJ^6CGgMC(
z${Q!nmVFHIo8WZRnrg28+QAbYL4mzTwQ3nknQS?hHeRZ3?LYD)g#%pu?tK0c$~=5t
zhL}-!@pW|igxvi!cUwu-=-pE=kkSKy>X`O^%CY{1Fjr>p&uKPZul9sVZe<#-(%qAy
zPd~MQtXTF%IO*z-Naxcw(sMqX!{XLbG<#VLCUC|$l~Fq_G_Pz|`ptOJXhGFSuVVr6
z(b<h2ad8`gNAfQN^~NpQ4#QnrT3tEdt`gSFqpGX_e9{_%Qla_luqJq<?bLP^H|G`=
z at mKcY6m;C|-lkcqdl6@{2X;zuKxxjGUX=(|Hq?*8b~E}#q=Il!QK1e)LgWKjoY~<S
zSR8-02UCtuVGwGMnzbmf&aXkiaw~1e5|iGP_7p#A)QjJQi}fdVpN*_f%wfEFbSqO*
z!dY0L`1y{*VxGJ;>gwWkj2m!OVbYGH49TiFC_|k6I?<!;;;2<SG4U0QD=|p%m`*-x
z at 4y(^BR>6i8p8?>V1#~{M~D`47@?^i<$(4#oWlF`-K3?zoPTrGTU2iO($5#W9kqV-
zRWr|@efr5MwkwE=>2iO>7-{HXR?_WqFOn(O4tK?6kLA63%_hdc*xv%v9FzJPrr9U#
zY_+N7Y;*OS(Vvy8PeDCGsl4pJRrT7>ow6}hp3NS}*%MYFs0Cdb18;})4egQ`)#m+{
zJ<`#wdO<etN&Gv-rksj9iY}kQ{*d6II;JRh)39m|X4yNOipktD)jh*rth{q&=BXFR
z=kJ1?)oValL`Nz`Q>};<&6h?Yf4YG|;rUKUo&18(MWU%v-%z8%i*Qd-46lv~LE^U;
zo-Lf6PWDKofHs2%z>L@=qNUpP#>-;d-O4pZpg@}RWFDtjr?IgMiyFpow{S_Fn^xuS
zCB>__{BDo$)qV*kP$`WvfUK9OOEdM3oG at yE$uj3<(7wcZc)~{Zd#nR_p&@3&=%L93
zCYs%LjeUmNg0m$UE`)Y&X^eJnMGv^gSJplMIrKrBlNPHlg^h=k2VtA;gSd5m6=lmt
z7@`>r(eMg;!R#>&&nx`aUC1g~AAtRu?Qdx6`rPrjJ@=Jfp43;I0;~7!kP*Gk(}A9I
zcLGGrEv}!3fUsVJbW@#i^WcvZg=a@%sF+ at yV$ileWM?eaGTc~x5#k@*Ta;CCgtDcM
zfFh?@aY8?Ir4)|j58PO-!(#VPaK)#bUYb=o#Q at r1dC~UT_`yMHLKiZsf*f;Yz2U*J
zEVi7D3iZ3$Cm0m2roz-qmeaR_N1S=W!KT{E%%bb at 7bKwz`uc+9a>dVUT{f~cR2mY{
z+`yI2Ce!25j}QHpl|BCyMkYynP~z3kp}CJ<r;dqH;r4w~V=sJ*y$}aFiZ6Jnzi1?3
z at xz{rJLjuWf6G>hs~t|+&?FHWLy)@N8JKn0+1!M-ZnG_4a0*Eu%08wJeDj=Z8!Ltn
zvVJ;6i8WII7G|VD!@kxoPnj`+kKTUgZ{H5l(@R+dXpu1Z*<&AZOr-Y(^m8^CvP~EU
zksxCmQ?_91yV93*)q;;Irwg;V8=8u<+D3fXV_xcu^ueXF(4NPFbY!!}YD6%8_DXO&
z?aFcLgvdEgXukOhI?q}2S%0l`GbY1N^(IUQC1i|h%B`E}KJ?bB<gr69$BTPXs+BtP
z__HLIm0Kpp(GW<77f~h$kmvi}@QiZ|3SUhaw0VQ`$`)sqX&cE-CJCzO5|MnWA;J`9
zJs}t>ulauD8x>OmX)kTay1q9uH#;t<OIBv={9o4dm91o-k7lhIRVgI;w}tEp{*mlK
z(B-yWZuMQM@%9sVQ}(g>L?;$B*W5fGE-EKuUWws8q4iDz<BY1fRCxBqZs<ZNM|)6H
zd8&9AflcKkfDN*XBxG+|P!Bn(7|6B5!s;ikJn>Kja=9&k_4*jJM#Idf_~#vd{Tq3Z
z35uc3c~<~668)$fVASI67bt`r^w`|hEhF64J6?^Mtv*lNgb}vE<Z-<s6C>HevlpEi
z6t1f<XvbeFcRSqWdsak5Og4hqq)v|w<3feh85V2r4`Y^wOZUK~92N9m4Z2sX3%-~2
zi^_;cqzMS>@L@(;Bp0uGFX_ORE#u1kMc0zBngK-{r<iCb);Ep4zWq^23&at0;;j1t
zavC#d>!Cgne4&d44MDOdO3KMMF0LKrD73GVz0jy)++_vAq9ZML3q9?@Cckw+`oKzw
z#h`+iPVG^}vG%6)geV`!AKrco#MUl*b?BvMeqJJayj{<eQ at vOQ8Dvi`Olzq?g>`dU
z(Xwm1`6dZY=-o%0DNGLxa~`#Dej8-6b)wJ3f_H()S9cEvgyrpHA3q-jt)nWL%dS#i
z&1Bmd5kkdeSylEi`xabh-E$L0Z3kw~j7BWWRCu;8^JWgCXd&ILRe)FM92p|16Ry2Y
zBEGLkR?M>!ps|z>t!;jS%!!vruWr-*05mjHGh`_==APZ#Ank1vb7?Y+j~0o2-=e?}
zPzyzYL$2-8B>LlIL#5jS*E59)RKw^0bnYP9VAF=$W>(OTz|r%(qYvXN716=_&7g7M
zHs8e`cIx{axM_7CC45$4C5?*d0(AbI4DO|IT2cd?X5mvBPQnNqz$yt9<$_&_p3p_m
zTHwt~0AJ`s=Sf3*@a-6Jsaa(S8dNf1sYrqr01e5R*=<bm&Q4v~t#;%Mc`x<YL&Pp!
zj?idxSzkYePEoTc83WlOoCKRBd^jo0y!?@A4`uR=zByByg~ut~MOsu at d6!#r61pEA
zzAxW7*!6l97ZKx`zT}J?NPQ>FQhj--CFiK(osZeW-hK?)KEwWO-M>6&1Uh3Lq0tfK
zR)t#l-Wk5zBUudS61jjY at 4p=q>&u!rKG9-d;x_7J7$##=0G(XW9Tk4zmWDAjC2Zo+
z>@$rR$CcAj#wxyhcvwT)PTsxsRY~L;fie#VA4S-S-e9AGaIQWlRZ8G|k!3s;6ZB2A
z6!Pp|qfTgY0+EBFxBg|bcO31(6q&-r+SNX}z(;@EpoL<KdZ%!3ci9>x-$wRT^#n8|
zw4pWltYx=mGA$4vyS2mpXZCtB#@6zC3h{Mwn9rkuXrXl~1IR;QRu+i!Fn>fE$;?4d
zA>>wdf3N>- at V~g*I$eRRmpL at L;l6fcHk%mGT1fUbkd2_{vQBx2uuLBO1lCDvH?p<x
zTHoOtIgIr>+-)m>WT~J$OLw&%6fQig)c_SGtQwtW!NUn_k;yhnTokf2c0gDXq&+Po
z!VhSZ)8dY9)l!!h&7EH+(I}cFGO{Ha1M(!w13%vj-E`}ZS&us#29RE&hR?dxrpt=}
z*4FtNwceRQc_hcH`3Xd5TS=naC5vCfA0*M5Al_(G!e>nI2iv>{+ays4-F3T_^tgcY
zp^m^!se37>5Pwj&FgZY9-OEd~_t;XuWbJ9eTkEF-*6 at jfzyOPC6t%|x!N!<(QrsNX
zPW_52CsUxQt6Q=Od1p(2Rtd<7iI4%#g$>e2Bo8d^m6RkboF^1F9r}W@^AfdjW-Rpn
z%eZbn_4d2krw}->tnRkN{yDE-P=xv;3E!Y7ect^>LJ;w?%K1q4aV&#jRB?m#zFR-m
z_pMx3x6Jxhzd<c~4QLX1du^e`TF at EH7L7HaW6w*aYwR02VZH=Cj0HJU_7v4%G5zrA
z61OTZA>M9|i&Kb%p%^5C=9k5nCLIE}^G)(Oy5keQv{78|#K~h~+n2{5nkvfv0CXg{
z!sQzBnQsqKzC5~vi7S|{8u*ft6VBT1?P_H3(td-8qk6^Os23b5#V59{@LZoADow}9
z_|anxQvh&?VC!zj5)nr at e{nk7d3HL4QH~l*<jZ8 at ijDx0^~Ka#@KhSt(1QIlXg)DI
zc97G74!)j##TYkTD5U at 7jHYoc!VM)fnx}32%!TE>hplD~V>llFKuS`{Fu)eN0(3hp
z5i)`Ao+jEQ?uCE9OHU;oAk#k*arC?vu(q$LsD2N`RHm7)Uh{0h2)oN^ZULd{Sw3N|
zg8m&Dyp|ukksa4?OVHvyddy5I^QqB~wIH at E3A8^W(j1;ZmNl_}dRJuMYBQ?Ojg?U?
zUN+GMQ>vjb+E8qC8p}8`bzFpDM^@El%xr^Q&GuGVknwaRfpZz{?B&V~*uF0ZDqb};
z`KYj;$n-*bZx29N2fUi!ae7wr=uXUx^*4Rr5U>f8gv+=R=D8N+y5=X$El*tle2u4P
zli0lvtG}NnWN=XKg9NY&3JL-xng|Vd;Xv!AF=9n_s at p4hEegC(W at i&e$jxD6j9`y0
zxHXSwEqt?*KJ=lPOnBK2Vj8W?g0;_IWHvZ>4DoE<fN7x?I|uGErVOkEugX|;>F(!D
zDX^<DsDy(tA#oLqRkY78g~wzGuPvbWJSM%exC$82^*QSTBr`I`d;MPnHh at q{@FAHK
zs38-FW_O8U8G?Y$P$f{x3OpGX2r$u=^GeRDc#(q#th+pfQ7{3-8Tg at 5Aex`Ra$4f*
zRHYYWF`UPS)Y-(XkGNt4UU+Zihc>~Wr{l$-#2qij%;~;b*SgZ0omv>y9v}mDfltbx
zx=KW<$C2}x4lTU84&T)Aqf%YK%gy!XtgAq<{@Pgn**-7|L?s<Lbit`9Zx;*q>^-lY
zr)N=Ype^9qzDEAwgF24rNm5%m at 5go*S-mTIk(B^q8}xtyt<1Vps5)BW5P%P83SX8V
zHC|UT_Z^~4QFAv6O7D- at 4Ypp|9l-ZBbi^2YZ`CrGct=`xW#0I99PcKo+i&^f;J;o+
zF5^E1WXL!b+KlDZO=I|%h`S$OoQVtGLd_ME%pVsEut6WmnZsq95D!0F-Q!h$PDxJG
z9PbXn_jABqcuM^nkSb4 at A2JA!`5}(Ip9pE&BL$*}SJ>VhZd+5;9W*p^agTayFUR;(
zea*^=P1Z-XshI95*giqCM~$F&nj+8R2#AWana)8Q!<O at xjV7lKq4ogx<(sRolcX??
zJ}Nw~GdU*v7zI7ojzn%46Jq1EJlRtlQDtHBti$8|G{yJN8B?`uCKkzsiH5JmQP3Lo
zTF_O4v0-Dx-CI=Q0SBQI&|C^7P8ReQ+GOia`^Ot8akuq!mxNUVgCRYdSj`Dd?dED8
z%y8M760ZUCdF at qWfqezkLK0dCV4Si4$1t+N9r!VD2)ZNH7HrGYlz>JTbX}_-lCYFZ
ze~;NE4(E;&<7qMaURd|<PZPn)><c3{K#z$RAT$gsK{r9)q?I=xNq07ITWtDPIC1zm
zmZ*t#ByZh4Ft^0&AD__=U$DUs&cP3yc^6Z*qLFvyB*<B{<$a*0AgJjZ7C=W$j)o=%
zjqrv?jgbC$aSE>2MePa~84hl^Uq at EqKug6t?g%+75;x^w{_N^*?0aMlYNyr=T}kMl
z3Jbd&O^yIkabN!Lu_zf2bIW%gm9&`Ub<oyC#blw^6IV&{MaSy1BF`a!G~WfsU6w8{
zKh>goZ`u@^+uYEBFuDbhQ9U>?-ZEfwCH?*GgQU@$(@{FJszK=J%={V@?DsFgocq})
z5SlI^<u at ByvjKidF^jOAvb*s#^|)vX2rKf?69D90-^B3GT?Q&3P{MEV2mC&UA at Q=p
z|DT0j_$3qg$(+e)o^5$e^)DmB-+q4V>5SilBw0|B5GCCJNE|O3nkM9N^&a*U>SY`9
zHQ)Kv1S|5|Ch&uOmi)t>1c4Y=LXF;LbJI-Jp(_RYp&9NEgg!7gDrv~?FcG;oP_0Kz
zlOMv1D%4INlU!3&KUHI;Rtndu*P<;I>}R0K at kMiy=NIWZ&6VzWm%YpKg!UqsB*@1I
zk~p!YsLgRm2M@`Qn8_}=9wZ8l+*L>7J?Hi&Z at I5NUFbYJ8<#sa#!H8*(p#fe*;MDh
zoo at NG!ujpA2)yYu*jd}yicB&+`TFTNh-r=-$8>8U)G at bkKaY%l<^C9aszFV2dtTEK
zl3kXVe1culVxTfs0eN81b`tM}^9Lp<Z{N3>;eK~a7HT6baJ)yY3SN?<mO&d7F=Pp2
z6<rA1rzq;P1y!G at io_j;vHvuHuTscZ_+*1bDZoGC99+N5(nSIDTjJK*wUYgF+)ZUG
zKHjeXc9l6uF3{ce<FS}KVEE?H8BZ74CEt~~oP|T!cW9TACbMk*wo=uE4)?a8*g-(G
zSmqh at vpo{a9|xslO&_VpCk at dSoDgQjyN6n$RC at jCXGcu(Wohu8u>5G$K!PP;)QUCL
zm*LHRDztTdZhD;S)M<JPYc2v at YiyoRL@j0ktOh$@7{4{4lc4MTG66k`><I4|YiPJ)
z$U0XHu)5)M>lVyR$5nFSO4GAwr+HCtX?Gv6$#F6`HMIn#*?&SLa2WbIoN}yQntncm
zy|)qF++G*4cL{nexCg=2eReN%!5-b8nV7gap9RwzG0BI at eT6d~TX3FP7wcEtME<Vh
zwe{Wk-ok_d?F^f at mC{uxHl)f3MLQ$M&~V{>C&l;t2r+Dr7AI8<ylJw=u3bw?xgDs9
zks8w8$r#2&sUe~qz!}P at Pz2)od+aBqZ6 at Jm!E{qVEwJB at Om}?Tvt|kV4veTax(GF#
zN&+KbMP~^KN4#o>jnyJ~Qi4j^58R(A<kS+Ox?cww(%LJ*8!0t1*NqmyH<ITokFD<}
zV)KOT)lkx^o7xy!baYwY!cyAT#0_*yz<GI~G8+2;D at L7Gqr)i?h#I&pH2DNZf`!yM
zdJMr4em8~R2FswuW$SyO3O;twkj!qf`48yo358W(W2Ue$pGiRXv;c0;1KTVye0K{N
ztopjaZls*_U(0g9-8~`Ec?>+$S&_eox5L*@5vmugzIj4{<^tk!^B=^yFfQEYLZmC)
zG$9Qry6z2tqXrM9vkn!!Ky&r{f#;B1;=;}-96vuDE`gH;f~E>c2|%W+0#*|k9FJ6S
z4z7}h6j^9g(hTgmMFTv}(@`TWgc$;@)hIJ+eRg*iM0Ggptk2$wB@!oe0Nr(HNiQLp
z0$3D7*J1o>5y+v+R>H;_^^yx+pP&ST3!2u;A at 7>O^rn4V-dibXlnj?Krc&T!!3-K}
zucU*m at iIY?y^=BX34F3|132XC7obTk;v+hy at Bk0!FAk%%Z*OnVN<&y*9|mTYWc)3G
zFO>`D84Ke{sM*>QT*^MI at V~AYT75#E8SW0 at yD`ai%sz%|A(b$E8u~cufH``yiFbvQ
zlO|4@)QQHMSxg(7+sq1zrypFSd_Q2Jt>t#!V at ormw{-JU*d7;Nu9|t)Es*@5UB+;w
zfO9w(j{TzUQieMheBl9qcWLj4xmWkDr^R%gPlMJRu at uFcBL?J6$@<fLkt@?kpdPQs
z0PkYKy1!o>ckaG8diXfr(e|k*Od;XO1rlI1gX$*g7r8+6P1#L$resdIomz+LPv;AB
zS$`C6XaqORizS+lk+#knVDZvvP_;fzi~H~j%$(}HiD=w3)XST}@l!JmFc<0x>6E=V
z*^YvM7e#HrdI(DE=6i1km at i@t4D_I~)29gw?-CPv3+wXTKcgrsLC6Xi88yWLVG#Er
zp$I)K?i)fHy$)2W<}FX{Hg-PU2*@?X`IS>w9mtrKxiWhZvO#TVO1VZKW2xRx{5*6W
zJproGRi8u9D80E0VC8FbZeQ2;AmqVb!AX?NSdYuIug_3?h5zq6pvEq3=~KT4Uifby
ze2mx13c;YBw37)e{KAXxfbp6Sh^2UMBfh!a%f_c(AFeNl>l?;AkqyX#4P0bE&+3Hp
z9+0XB1XF-{i=JI0l%jkv`T3;fm)Al=%D!p2ckIwC*q5&My65ep#(oz40}c|N at EV@L
z4Nq8vFN+}1(~~avD2<+w3aXItsYL)^F~Cj$U-ihnqR<dBI}CyE8hsda=mz=#AzCG^
zXwGJ!K6cN}k6)+ddJIe8^?9D)2*$NxCk at T2<cJgJ%awn at 8BX)!e_Svf5~KtUjX29i
zoLh*VgWU&g4Ezn!{i(fua<k_zlUGe6T&|o(0!#=nsuVOK>Ip*;dT<8aMOmgc`Svt~
z2PEEr4h at F<yuqA3V(!Zf!K3U0)bDmhJ)Sbdl_~e#(<ER%ksS3~Vde!m?;;xZDw)*t
zeLrX*G5^dI!X+ibyGb{O3|+hXoD45ra~x!j)gZ`5rupsXs0OqTL>geJ0Bj>W-{QKz
z|82_6cSe+38zD3Vl6pWS;+(6#y0q;<O6Q(j5_fP8+kumX0)FT>HnT0{a1{i`U&Voj
zLyoo%suZ=sz`%rk(Q0nL>}INN*xqgzvysx$;y>JxS{A at XClk7^2?~3fSzte}lary~
z*2TaGn~Y<J+Iw$ZrusUk<g_0^!003lItiA?*>ueuojUcp;43)niMgcmX-K!%FazQq
zGLy6PDYc;M^zQs^ynB9mUX7jqMy~G2z4sxLnD{4hU6j><0RH|32u{2cTOZ3Fk;l8I
znXr8fN(!bp02!mCXTrksAx9P9(-b(*b;LEQSPy|jMDa_PJ}{j0=-%QDr%Aj?YV?2T
zVhsNQV{+=~j6CHptJQ$E5(E^T1)B!<y$Gjxe;H&L)694Cc=db at R@lcH;mH@(7puO}
zorfd+iQx#lRCaU43_63Bp={OBp}JMK^WUDADhF1^LJ-IqalBi^ifkY1UhNrn4>z6&
z0F?bB+%Z5a83Ct<EP3Jjo at L8;hTonS4sNZ-4EYq_7fGf{+XBbQb#8!9dAsIQ{4$D)
z+9GouC&XpV&OPR>jSp`OL!>Lsg!UPSn7oky%!nhh?ZK7J2Qd<Jg{q0jiQ;$EPtWL+
z6F4O1S7&+|e3nrSx;_NV`@^J%HYHcgTHauJyuK9a5OXMMcm<q3F#Zt-Oi&8IiUtd5
z>6gc)Q|Q+0^{E|fG7#dh{2CLeAdxs>1YK3U3(i3)0E7!<%v}qDsh`&Vf6kV22HH$C
zqdtL7g{$?$*w?HzDRY9sasN8vR#BlyAq`v*&Hz+U$K>CToBb>BZ2=f3bHz{VTu~#K
zdK^bQxMhnh2VXU!fP5Avxy~#zg>R)Uj+>VpJ$sIm>KFXazT8bY0~u4%zf(-UWdJrW
zL7<cM8Zp6?DA)`JW5{Y9k=3fpaspixrG$bC4VV+d4^D;X=H@?IPW&|bgu;ari4WGL
z6_G2*aGi1hY;mz5l+eFGDq~0gq}V|^a)>bsY)}hAM^LUwh*Af}Xnup5HL#T3%nah`
zvk>C^B!@U*T;~T*m;-*`uBDlv7WstBFylVXnk9?(KT*Gj8mq$D*@PPBZsS`SO8?_+
zaU$?^RUWd<W+jmWis+T>%YD4t|E{z9FIyDd0B`6380A83=lf~HdsDI!K3(`$0M=c_
z{Fp(+{@si~wn@<hRSg`u5>0(mYSdi4g*4f3W at oS1w6_#>Q188A-g`ZQKM)S8zK3)w
z$s1bu;2_?jQWYRaINGd#1PZ#k>u~}UEaH{O0giV(bRy6_fnwd3i7wL$itpx-*&H4n
zYMM|}1|Rrhsv%q0t?LcdR|$yzV#MSLpJ8%B!5rQ9lO1%nzDR6$lnL`6C<|6g&;no!
zJ^%k%t+~{Xril>e95_VrUcj|IxHd{k{QBRxWUxYkgQS_1n-;|0o5Iq!UmX23p{5BX
z5u4*O9j<xS-l7DY%}s_Fs{S9a!z!@D at hWoYw;tlKp8aLDGgJUq(pzV;cT=W<8QzDG
zOE!7~isSA5BErXrC*gB`_n^QTWJhoiKWiWmt}>wmy>tH29|kMpNDgr0PZQTt2TdS4
z9omMIy^wXcHWs+$N<b-l4>QSZ1vyGgWl3hRha?H|o+j%2haXbNLW^iyHWKMF6yaNQ
zvFQ=JTeQwssszT6gb_JYWQ+JZ7><rN9NkTf0GG*qJy>1~$XN?4CJ4H}6&eauXJT{*
z4D0Cm85R?of5Fv@{6C#53U5Qe6{jG5Mp}BInt=q%?M*RItabI)c_NemnSUPxE{TQg
zR^^ug9%|$WDy1Ze&`t=0m&tWx(R9l^RU)m$w2rg{(gdO*10ln9LSmDnHVH+)U$?G%
z*r^8{OVe&^5&!QHhx$E)i5eSVKJ>#@>W at LxpB*Ovdhd|4sTRl~<eZG~QL?iFdZ_`W
zak!oTkB^P&0F!NNfFyj^6YM)%&8^ui6FLocD8poha8mXWdF_!xY(*@bDg42IcK6yY
z+Pxm&QYQ++-Ra@(u^r0 at wA>MB?ExW(559**=7-1r<cBybP+~1okgpxpAcaj<UAm{G
z1Bw=idgs^qA!*OO{)heULNPyOGsLV$fk<s!<E*((4soOiR~H(Qg49SV)7XI9hZLr4
zxE|X58U at 0TIP1t_jzU{;QDK-9v)jFNe}nyj2?5*V>`kEqN;NX!O4<x3Sb`A(45{wo
ztHt|2f#rY}Smg1-%B^st_=EqE8dom|VU~~~&IkhY0U2ZBA}!e at f!QOmQ9J{Hw}~uC
zd|cWqJ_|x05`^(m5OxFe6C0uU?R;&7&+Zn{WL1C6t3-O`CCSaGH(QDbOe#A`saYVd
zekdR*j%!lQkQg2U-zwi{pk=-vvuJ7ZY^I|az73VJwGcO;u($nRl4F^a!+(StieW#v
zUJXoCDB;mU3e&$N$C1+inlwQc(uBkMWXaJIBuD$2d!BPMV9$S$MT%jFhzZAGp<>An
z3^w4z=#a9W^tecw7%FD^9q({PNjqL|+d?r60Vcs4Ni|%JjHzr8>ynEimdC}IfAPf=
znyXJRv00_-1+djo#D>u){`SA?A<ri`R8NX{+(njkFiR_vT62tC%A5fa!@mT_=7~!i
z{=*q@#^4S_^Zr1yEcc8g&pCI9q8Sv5il@)=6uaYHZN)lH-+)LLXAHO?>W^Zbb4nz#
z(eXM*BP|?d=rr}ck^h}JeBs-`@JbG4b0(Z)iUuj%BY?Vo9$rB;9y#GPr;rnS&~X-=
z at Q>XPMOrMWM8rg=RJFqA;7As|fy#^nm6Jn(qx&(pLs~Uka12oGjba|>hwH)(No~Yx
zAi-H*ZawVG`LgzpSf{ITyZ#@c4g$4rkbp3w02D#e%?u6Mb5AEgGAO5+I(<DQg5+|<
zA1NZB_dVeb3QY%x8AjF#q^L)U+xg1sN0m)+{^!_Vv*LZkB1!QDZUmftHUVbm%bGp{
z!X3F3Ric0XzhWb)5}^JW3P^}vUu6EIkO};}F8{S*U1*3vr~n&2E7H_DoQ1tlCg)Mo
zFE7HeKMxCcQK)E0zkLDD6Dg9vJs|*Y4R`V1ijAle8vmizci8=o>rPz56M<VXNHoU$
zKNK=OjqfNJ at lB+;;5&b*jf!-os8jYT7ugw$vabj2j;#|M>o!c9ni;Y;#$q5P)+6!<
zBm<&_B%8DpqGWBXlnK=5o}&Z~v0==#W-DF~eEnoTiXIXk`H+GzF_DhKfRV<D;?5>d
zyJyd3X}C((%<Gy6bq|8Gls`kCHPL2PEWDQ-L_{FL{1XPkqs-Jzuw?8Y1VBbwB%dtn
z;9mC?`~DeBSysofFSO9&NZC4-%sPSM_Av{u?kyBL{P5cOWLREoRoO}oS3c|IM1=pT
z+qgp5&VwZbaUyX4n at XM+EnBx<6l_ww2S<;qK*oDS_0NDed0{S{TzyLN^(cx>M9q}6
z;M+0pf(Wvj8~(6f;%s-xe}rZ#6oJ7>B3PrI<yD)BaXYrEaZv`&{hT_xj9wc1*$xwu
zV#8A&MP+1D*-^2)Wf!%i-H}IOPOG(7<Zz_F?xrWK+|}3d-hQ7;d$L!poIBzUc<BE#
z*LM at YQ6^0)VJz3vaiPdmjitxYbM+l(Bd6#5oL9SZ`oqIsD?=qshAYz#A8v3dQvKUW
z8or{W1aoa;Z$4aI-B~PMI?~*>;>)?hv%C^K;kDAb+OO_BR42FmILZm%nk+r`W6UDo
z)(0EC4M%b=RTR4gj;{_qr?@m=xH8l2xzf7ay}A;-o!X at +*>B9LouZAcj2(abecX#W
z5tdo_sMgVpf+pFHv`}XT4!p<qPKu+6`Vj$i6X>7X5>)@5ty9~LmuG^%-_?(h5)sLQ
z5(!+ at u-f94Lfu;SLzpjb9+j<V=ENn#Lc;<$;iGH2J-vM_o62^_Eoto3W91thoZ30?
zn^Mb^zT1hf)EM!`+d3%*@99UF|Lwd8#mdLt at t#=BX`&=-rgp}p_L-Or=Pm|Y(_nbM
z(JK+QmqFwggr^Ta*N-@}v~{L|o&uXZXm}-Ix$G%cF9y$uVqP2<dtGuv6T at PiIG+;L
z;7|MD(B5Vk)7!;~&Rtk(;wX1^2Yl)3hnhYU=CM`I=u>$3K^7WJn03Z$QMKF&TX?hC
z8FS^EC5|u}aCUNFrCh0+O7IzYY&sCk%?9R_e!|q62{YO%&V*jBUKt)-^jKL$nZITX
zszj%?iRLjj7pm?Yq$bqCYtZa{{7qCg$#qDP0(0%>mA$(#*p3ZK!^9u|5O<UF3$YmL
zx?iR8WOwKDVLm5dvG3cP3v$2ifE at 5(D4O)~4fv<<+Pkv#BMQc3(WKitI3{>x8VC%e
zQR1J%6z+NrGva>!6WprQuCx5qS<WYNm^`e8Fl)Z(08<wl*PcqL6N{-oXpFYNpcMHY
zo3Jj9o4}{(W{p{-$69My at P{SsI<R}HOFb7%O=R=k;Y8x6)j%<(4vJkoLhy*3Hs|zo
zqFm7OAq?vpRDKOj-55&EHjZPHa~^Z7UEPw<beJVSxZWDRW7Yt+({sVz++^yq7FyTt
z+yKUBf={+XcYk^~#~U*5ompG0FUbN6Yfzz92<HGxdhbYM$M(XkzblqK%7fu!)@FUu
z5vJGu)M#Prr02I34F8~A!3>^^b#uXCUXlLBW~;ey4=BS_STjQdDa<_vs&<6#E8o!d
z8dTvokdnZRdaQ?yZ;x609DGL6a}(a*<&J*D9C=>kvx4e92TUk>uA#r*{$=p^;tmC~
z)lpuG9!K=|*s$>M&#)q{7A%Z(%+MjQ#|r*zc1Ez~uQ<_Huq4x`$;(drm<F at qgYtqZ
zd-K}9kTz-4&6q>8NA<hT0xrxf7)IvykFrSMq_qhRHh9<I?^#O;=+Y={7msCdPTjs9
z75?+99|fKvaW(QPH}uV1ae?Y^+O3P at GdYW=2I#RpZI4|(!4zY&Do_wWb=PBVA!)Qa
zp9*u!J;SdG=2-fLZXC0v&KJ#k)ChQiWzd4D6dMSzFtA_ at RX)<#p5sfHzNtwXSV;Y|
z<Ti7b4vHSS*KjkQ0FOB-ksoCS7?z$L^m7-OysZLEzJr2b%}IA1WL%T_k at H-`rhGKm
zJM at b0zW$p29=2a7unlwYg_mT1q<n)lohU?P#3mW7d$ks0Z&To{!HNlQVO}(qZh%?f
zMzdRC>fu8!kuaBo-oIc#Se88GbfOIA5D7PvVG<D$fgcF77KVlCg#}aKJ-5Q0Ozq8i
zr{2z;f at Qfqv+tWRhyGz~8a-TQCm9BOG2vZvOzk!X{Ma;_c^Q_)@y#Mo*=Jcuhv1L!
zPEDT!o7P)0x`a$#2^)-Cn49zmb6g$(bKG(otd6rqF7E<1_}Wp)+ybWEM;>O10;Zj{
ztFBWBbExG#Q5fZf?b=nwj?o-?Y!Z4d0yZvQEpZKs*)d at iai}FJ?WJ9i61mYIP0^E>
zb|t|8J{m^x;|)8e$o=@6hm!ea$d)rCjc3>8Cih3dcc#9;1~R((3kUGapOG!zqcA!K
z6SeEbIu4{JNsk4LSx7pkV8XJnRQGhi9ud~0Q(-Pyk at Ne9Z^u&O?EoS0FkT*nDfq{F
zr_4$moiJf*_`#$^zGxE(;CmJU&eEfHV)x+ at J)HfGPbvX>8KB|hG=FY8Cp!~1xf$MZ
zKB>*w at cAQIslC{Iq|gjwJeVA2$OC2P-8;yWeh$0W=0WmYr4P}qE?(&_@|o+FJd7z`
zWg$WGqyb+L9p(~5NAGCz?V~q^@c*@U<zG=;S@<HZM+Dc<YCCAm1ToU!0R=bcxPhW@
z&=`^)0<E4Xjs_XUZi2KF5Tk^MCO`-pgc<DP!ikDPWD|&(n8X$vHy99T7!{(d(E(AG
z`EFJ7KjepbKlQ2C^_KhY{l4$ksd{hXe>*;%l!N^$6#yE+7Ji7sirtsd$dL36$7}G>
zcMv#`f*iZ+c1C#a{erB at B&(Y?aR;}6GY<L!fIuW$@JjaMYa at oy?pYYq_rK^D9XWa~
zXt6&<J`$n#4hdJ-9PdBAQ+%{Dv|)yzV0-NK!4bP?Ozkve^GqMu!?OrmLVW@|U38o8
z;*u~3>@Az$)?^cF3j`2!aA)D_O?}#RuT4PMFe|q%|9hiO+fZu~oK3z?aqCl&*5ub1
zdGC%S>vu5?YXzWp at PpE{snorhq1V at z+)qt9jo4NVKZXGOwb9ae=~d4+?1%C=TfDvF
z57N=K4OFhD&XK`Qo7mw at AsB7uB+<6o(BXn at zKFc!z8H(tk{o#aLn&e#E{VvC7d at xI
z4F%u$unma)hgRg5|3$h6HgB2CHm_hHsVuSy9U~;)S*&->1Hy)<U>4y)2>#Zhi~>i&
z-;BKB$8r6|YQ_3GO$H!QcBJrbN%i?}_6Fc;3|FmH+}csBDGlFCahi>T$MzMeJPPsZ
zs1uJkb<d7^uLuC9^So!H+qCUds0A8?TJjM5Yj<EhGJAj|QAMhtqP3KHfp6*AvTfTo
zRHSOU{N_0tum_0_;6rg=`MAVawL_b{YJ58=&okeN)T4O`!x(t;9xb^t*0`o8=k9 at L
zktEFGrTP(*JeW3BsHk2gQi#=^_?;u@^SQCUjJjW2B%UA8cCEyhyq_B&0o0RW+!D=T
z%g+|pPbIn|tCN`DmumqFRVmv;|DwLI&_RC|tD#=U9VZVtBA7G1yH}GJ=&mC5u3Z>x
z*5p}dz<9myQ09VwoVyBaCzkaH5aS$K;M%dZp})NP_Apb*gZXw_fibcLu*l3ucLG<k
zp*oj}nA<#pz<AV`G!*=ur_6Tu8cv;B_-I+cBLwZv9-n5*&gpJl=lUyiuw&Ra7;)z~
zr~olUgbZy>bM5^<9{6K(#dNN+G6O(N4lt%v^BiOi-9Sq>8VrWkBFou12|K<&*ek<X
z^DrR=%}L!hal+HA%a$Xb`n2YH=BxP-daiKb;EZmziit6MqG<|jBDhI5&%B`##S#_&
z7+(%-Ix+e^#C}rN at W?X*+A6kr#1i-+sTf35y0G)g8)p8eHtx53rWE at n${V{x{YD{a
z82v at BA)Yf at m}yR7Nor5-dD%^K?C&&rhc;!MIjSI1M{|wkknReb!#?OMC-tCs{ieR)
zFk?b>s;G5kWD4W!vwzi}t!)PZDHDcRZZ4HILi&(bGMw<}Ioh3ZhG@)B{4PL^c2xaS
z#v0RG7L*9OpcWzU_;Uu?m{b*G?;fHXP^A>^t+?fStw^Ue?H93kGAZ3a-ZUc#+*#Z1
zSvcJ^CSyx>f2D<mM5;#roQ at K22VJ<A^5up>Wd-D|(v62P1H{I<H^5m1zGFxZ{}$#k
zPJ(%=wS(zP;wsHPZ?v>mjG;`sAF at BzJqGKY51jht^8VYecnMl;cnKosz|^0;HVvr5
z9!TCT4Db>}&XbnlsB!-Zkv%DrQCWt`Nvibfd)gY?+WULjUlF}p&sB#5kKdivwqb2*
z`{c;~i13Te^<MdL)wgE-wL&W at UkJWNP&$pAoBHHUHc3mOsC;pFZ3HiYMM7E{WS)EB
zM|~F6*P`%EVHnSQ_AwuqH7vW!{qKnp7Zuh=RL&0kC5$V=@5N{=@|B8dq?U6_6MoaD
z{ag$f2x(AgKzNQ+mj7M;ZW6lU$A7>o;6TWx{@eH19x{8j$7%&c>CT>`TRq1{#5r|g
z6IF!TVeY*T7I~Ka(8Ye(ZF90g2tz7O at o`D8$*$2JI^EV3cV_JN;Z)|tAkaB|!uV$f
zLrPN2g+d8 at g@#UO0Kp#k4hS+O52YH|5E at 1@6 at iSJ%FlJzP0d>0nj5Woji61yx|UrY
z(!Hzy)t>7F&G7IbnwN9$PG3vHD_w4>LH1?$5jNSp&ED2I7f{0zV7vE&2{j!L=i<NO
z^|yflqE=iMAb~^8s$tZr;>LErAquY-M#aFIBa8x6&ugB!pujaLqAj!`-6KCfpv at +9
zEC~zQb8{7`PnHIaE8SZdZq&8rHWbRSf8<-}{GuB?*V$!-my~^hXMN at G5WSwb`ErFJ
zYR at n75Bqn9LGRK<zaacQY&;USt<9tCD=da!Kpx8ze^*Msd`~VjlTq1^+^>9<;?_LY
z;l7-Wf;|*+WGRQXVGk)G>+nn!Qyw`Mn2nw#8a?Z#{?m*Ns%mX>3hvoeq^e(}BuZSv
z^K&t)faXOk0+u)u6)O4qUZmkayf&09 at q@k-g%@rKkH^TA_N<ryzHZkqJiMOW?S&&k
zlvO;oa1|VpsZIAn8e4s0|4gD51wdX1`bD3%8Yu6fKulF_^~4wNg&ZH5ZX)UFCTr$9
z<T_(-JY_Jq^}-kWZcD4z6*q5AdpEa^vLI!tSo1z-NCOp)*4HHQMK8YQVRige^7@)#
z-R?FCH8ZPx197N`&i0=_fQ||b^=GvUk>QbS7`wVG89828cif4#T(jI2iIZffaJ{kL
zFi!iMB)n*(7Y3;|nhCEb%lza)*1L$vS<S8!hjf3M-KMMIwO;?2WVcEuZ|uN)Coq!8
zj+lerj#JV)*@4S=j|!{qytu&CmXop$ehkn&Yv2jtSYK`|E5&EymAdWSb${C^VT{MI
z1{<Q{!|W4h9^YBll!Yj1c)}QCY;M4QD#Zs;MbYCr#O$}!fQ~-NI8ce59c;M4K4=uz
z?z&rss9JQjFE#orY~JQA)*u7CTdf(a{CCv-)75{EZZ%yP2e(*_`3m;eB^@@kztyKd
zZZr}koIT7pN%`qO=&9}dq^AxPg$FPQJkSH6Ao1e{9h6>zbsx3 at lAb)!Qoqldkq|71
zot<5JgQXtb=A46ym$w!LpHB9$YV9+_FGVbZt5Cf}fzNsug-UBF1VG5*%c%m_eYLs=
z<+>h84?LH8sRG!E`RR@$RSx=_C%^lBegBGBq`=iN!DHb`tYpX$F<{qtHT!it6XA at P
zdDziH&F*y3UR;WzOC2Tg#(@IM(l>}?avnza9H=p`dTqn1m%+%yNa*J!H4$<#2Yv4Z
zAfgz69{JmG+=mn2VLgXI;Y4Ze^U`Nx9vn>MZpAf;Ga-c=uePP7aUR@*EkO?LYbr)-
zoo^nlN=x%|95_)m7|fXgC6+^yk^3d-Aw<a^0e}28C=btZz|Nu-X0urH_1ypDLP(O7
zGYFwfD4APDAMJG;8kpiCS_?mf#}L%=?dad3LY}@;dP&NI at oyx;Bv>N at 3HFFx%qp1b
z7$i}YW7mPb#2;*0ln_?CTpYP4l*|$A3 at Evb7AV3SY)lm6FrF`piX9zA$xpbr{J)Vu
fkxlC7>R${xgngVd`rsOGUY#|od{>@du8#d5r9`fy

literal 0
HcmV?d00001

diff --git a/mlir/utils/coc.nvim/language-configuration.json b/mlir/utils/coc.nvim/language-configuration.json
new file mode 100644
index 00000000000000..8a34cc83a53cb3
--- /dev/null
+++ b/mlir/utils/coc.nvim/language-configuration.json
@@ -0,0 +1,22 @@
+{
+    "comments": {
+        "lineComment": "//"
+    },
+    "brackets": [
+        ["{", "}"],
+        ["[", "]"],
+        ["(", ")"]
+    ],
+    "autoClosingPairs": [
+        ["{", "}"],
+        ["[", "]"],
+        ["(", ")"],
+        ["\"", "\""]
+    ],
+    "surroundingPairs": [
+        ["{", "}"],
+        ["[", "]"],
+        ["(", ")"],
+        ["\"", "\""]
+    ]
+}
diff --git a/mlir/utils/coc.nvim/markdown-grammar.json b/mlir/utils/coc.nvim/markdown-grammar.json
new file mode 100644
index 00000000000000..2a285a0705bcb0
--- /dev/null
+++ b/mlir/utils/coc.nvim/markdown-grammar.json
@@ -0,0 +1,117 @@
+{
+	"fileTypes": [],
+	"injectionSelector": "L:text.html.markdown",
+	"patterns": [
+		{
+			"include": "#mlir-code-block"
+		},
+		{
+			"include": "#pdll-code-block"
+		},
+		{
+			"include": "#tablegen-code-block"
+		}
+	],
+	"repository": {
+		"mlir-code-block": {
+			"begin": "(^|\\G)(\\s*)(\\`{3,}|~{3,})\\s*(?i:(mlir)(\\s+[^`~]*)?$)",
+			"name": "markup.fenced_code.block.markdown",
+			"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
+			"beginCaptures": {
+				"3": {
+					"name": "punctuation.definition.markdown"
+				},
+				"4": {
+					"name": "fenced_code.block.language.markdown"
+				},
+				"5": {
+					"name": "fenced_code.block.language.attributes.markdown"
+				}
+			},
+			"endCaptures": {
+				"3": {
+					"name": "punctuation.definition.markdown"
+				}
+			},
+			"patterns": [
+				{
+					"begin": "(^|\\G)(\\s*)(.*)",
+					"while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)",
+					"contentName": "meta.embedded.block.mlir",
+					"patterns": [
+						{
+							"include": "source.mlir"
+						}
+					]
+				}
+			]
+		},
+		"pdll-code-block": {
+			"begin": "(^|\\G)(\\s*)(\\`{3,}|~{3,})\\s*(?i:(pdll)(\\s+[^`~]*)?$)",
+			"name": "markup.fenced_code.block.markdown",
+			"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
+			"beginCaptures": {
+				"3": {
+					"name": "punctuation.definition.markdown"
+				},
+				"4": {
+					"name": "fenced_code.block.language.markdown"
+				},
+				"5": {
+					"name": "fenced_code.block.language.attributes.markdown"
+				}
+			},
+			"endCaptures": {
+				"3": {
+					"name": "punctuation.definition.markdown"
+				}
+			},
+			"patterns": [
+				{
+					"begin": "(^|\\G)(\\s*)(.*)",
+					"while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)",
+					"contentName": "meta.embedded.block.pdll",
+					"patterns": [
+						{
+							"include": "source.pdll"
+						}
+					]
+				}
+			]
+		},
+		"tablegen-code-block": {
+			"begin": "(^|\\G)(\\s*)(\\`{3,}|~{3,})\\s*(?i:(tablegen)(\\s+[^`~]*)?$)",
+			"name": "markup.fenced_code.block.markdown",
+			"end": "(^|\\G)(\\2|\\s{0,3})(\\3)\\s*$",
+			"beginCaptures": {
+				"3": {
+					"name": "punctuation.definition.markdown"
+				},
+				"4": {
+					"name": "fenced_code.block.language.markdown"
+				},
+				"5": {
+					"name": "fenced_code.block.language.attributes.markdown"
+				}
+			},
+			"endCaptures": {
+				"3": {
+					"name": "punctuation.definition.markdown"
+				}
+			},
+			"patterns": [
+				{
+					"begin": "(^|\\G)(\\s*)(.*)",
+					"while": "(^|\\G)(?!\\s*([`~]{3,})\\s*$)",
+					"contentName": "meta.embedded.block.tablegen",
+					"patterns": [
+						{
+							"include": "source.tablegen"
+						}
+					]
+				}
+			]
+		}
+	},
+	"scopeName": "markdown.mlir.codeblock"
+}
\ No newline at end of file
diff --git a/mlir/utils/coc.nvim/package-lock.json b/mlir/utils/coc.nvim/package-lock.json
new file mode 100644
index 00000000000000..d9d307a1f26cbe
--- /dev/null
+++ b/mlir/utils/coc.nvim/package-lock.json
@@ -0,0 +1,710 @@
+{
+  "name": "vscode-mlir",
+  "version": "0.0.11",
+  "lockfileVersion": 2,
+  "requires": true,
+  "packages": {
+    "": {
+      "name": "vscode-mlir",
+      "version": "0.0.11",
+      "dependencies": {
+        "base64-js": "^1.5.1",
+        "chokidar": "3.5.2"
+      },
+      "devDependencies": {
+        "@types/mocha": "^7.0.2",
+        "@types/node": "^14.17.0",
+        "clang-format": "^1.8.0",
+        "coc.nvim": "^0.0.83-next.9",
+        "typescript": "^4.6.4"
+      },
+      "engines": {
+        "coc": "^0.0.80"
+      }
+    },
+    "node_modules/@types/mocha": {
+      "version": "7.0.2",
+      "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz",
+      "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==",
+      "dev": true
+    },
+    "node_modules/@types/node": {
+      "version": "14.18.18",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.18.tgz",
+      "integrity": "sha512-B9EoJFjhqcQ9OmQrNorItO+OwEOORNn3S31WuiHvZY/dm9ajkB7AKD/8toessEtHHNL+58jofbq7hMMY9v4yig==",
+      "dev": true
+    },
+    "node_modules/anymatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+      "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+      "dependencies": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      },
+      "engines": {
+        "node": ">= 8"
+      }
+    },
+    "node_modules/async": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
+      "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==",
+      "dev": true
+    },
+    "node_modules/balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true
+    },
+    "node_modules/base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+      "funding": [
+        {
+          "type": "github",
+          "url": "https://github.com/sponsors/feross"
+        },
+        {
+          "type": "patreon",
+          "url": "https://www.patreon.com/feross"
+        },
+        {
+          "type": "consulting",
+          "url": "https://feross.org/support"
+        }
+      ]
+    },
+    "node_modules/binary-extensions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "dependencies": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "node_modules/braces": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "dependencies": {
+        "fill-range": "^7.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/chokidar": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
+      "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
+      "dependencies": {
+        "anymatch": "~3.1.2",
+        "braces": "~3.0.2",
+        "glob-parent": "~5.1.2",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.6.0"
+      },
+      "engines": {
+        "node": ">= 8.10.0"
+      },
+      "optionalDependencies": {
+        "fsevents": "~2.3.2"
+      }
+    },
+    "node_modules/clang-format": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz",
+      "integrity": "sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==",
+      "dev": true,
+      "dependencies": {
+        "async": "^3.2.3",
+        "glob": "^7.0.0",
+        "resolve": "^1.1.6"
+      },
+      "bin": {
+        "check-clang-format": "bin/check-clang-format.js",
+        "clang-format": "index.js",
+        "git-clang-format": "bin/git-clang-format"
+      }
+    },
+    "node_modules/coc.nvim": {
+      "version": "0.0.83-next.9",
+      "resolved": "https://registry.npmjs.org/coc.nvim/-/coc.nvim-0.0.83-next.9.tgz",
+      "integrity": "sha512-ek5+EgA9N92/6Wt07TAYpavmBgXZto4Dmwmm56oyBl/w4wy3Tod7LfpCp4k9M4xCxhxPtrflIcxvhdDUPIeMuw==",
+      "dev": true,
+      "engines": {
+        "node": ">=14.14.0"
+      },
+      "funding": {
+        "type": "opencollective",
+        "url": "https://opencollective.com/cocnvim"
+      },
+      "peerDependencies": {
+        "@types/node": "^14.14.0"
+      }
+    },
+    "node_modules/concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+      "dev": true
+    },
+    "node_modules/fill-range": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "dependencies": {
+        "to-regex-range": "^5.0.1"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+      "dev": true
+    },
+    "node_modules/fsevents": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+      "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+      "hasInstallScript": true,
+      "optional": true,
+      "os": [
+        "darwin"
+      ],
+      "engines": {
+        "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+      }
+    },
+    "node_modules/function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "dev": true
+    },
+    "node_modules/glob": {
+      "version": "7.1.7",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+      "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+      "dev": true,
+      "dependencies": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      },
+      "engines": {
+        "node": "*"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/isaacs"
+      }
+    },
+    "node_modules/glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "dependencies": {
+        "is-glob": "^4.0.1"
+      },
+      "engines": {
+        "node": ">= 6"
+      }
+    },
+    "node_modules/has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dev": true,
+      "dependencies": {
+        "function-bind": "^1.1.1"
+      },
+      "engines": {
+        "node": ">= 0.4.0"
+      }
+    },
+    "node_modules/inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dev": true,
+      "dependencies": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "node_modules/inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
+    },
+    "node_modules/is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "dependencies": {
+        "binary-extensions": "^2.0.0"
+      },
+      "engines": {
+        "node": ">=8"
+      }
+    },
+    "node_modules/is-core-module": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz",
+      "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==",
+      "dev": true,
+      "dependencies": {
+        "has": "^1.0.3"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-glob": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+      "dependencies": {
+        "is-extglob": "^2.1.1"
+      },
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+      "engines": {
+        "node": ">=0.12.0"
+      }
+    },
+    "node_modules/minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "dev": true,
+      "dependencies": {
+        "brace-expansion": "^1.1.7"
+      },
+      "engines": {
+        "node": "*"
+      }
+    },
+    "node_modules/normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dev": true,
+      "dependencies": {
+        "wrappy": "1"
+      }
+    },
+    "node_modules/path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+      "dev": true,
+      "engines": {
+        "node": ">=0.10.0"
+      }
+    },
+    "node_modules/path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "dev": true
+    },
+    "node_modules/picomatch": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
+      "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
+      "engines": {
+        "node": ">=8.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/jonschlinkert"
+      }
+    },
+    "node_modules/readdirp": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "dependencies": {
+        "picomatch": "^2.2.1"
+      },
+      "engines": {
+        "node": ">=8.10.0"
+      }
+    },
+    "node_modules/resolve": {
+      "version": "1.20.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
+      "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+      "dev": true,
+      "dependencies": {
+        "is-core-module": "^2.2.0",
+        "path-parse": "^1.0.6"
+      },
+      "funding": {
+        "url": "https://github.com/sponsors/ljharb"
+      }
+    },
+    "node_modules/to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "dependencies": {
+        "is-number": "^7.0.0"
+      },
+      "engines": {
+        "node": ">=8.0"
+      }
+    },
+    "node_modules/typescript": {
+      "version": "4.6.4",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz",
+      "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==",
+      "dev": true,
+      "bin": {
+        "tsc": "bin/tsc",
+        "tsserver": "bin/tsserver"
+      },
+      "engines": {
+        "node": ">=4.2.0"
+      }
+    },
+    "node_modules/wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+      "dev": true
+    }
+  },
+  "dependencies": {
+    "@types/mocha": {
+      "version": "7.0.2",
+      "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-7.0.2.tgz",
+      "integrity": "sha512-ZvO2tAcjmMi8V/5Z3JsyofMe3hasRcaw88cto5etSVMwVQfeivGAlEYmaQgceUSVYFofVjT+ioHsATjdWcFt1w==",
+      "dev": true
+    },
+    "@types/node": {
+      "version": "14.18.18",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.18.tgz",
+      "integrity": "sha512-B9EoJFjhqcQ9OmQrNorItO+OwEOORNn3S31WuiHvZY/dm9ajkB7AKD/8toessEtHHNL+58jofbq7hMMY9v4yig==",
+      "dev": true
+    },
+    "anymatch": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
+      "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
+      "requires": {
+        "normalize-path": "^3.0.0",
+        "picomatch": "^2.0.4"
+      }
+    },
+    "async": {
+      "version": "3.2.3",
+      "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz",
+      "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==",
+      "dev": true
+    },
+    "balanced-match": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+      "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+      "dev": true
+    },
+    "base64-js": {
+      "version": "1.5.1",
+      "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+      "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
+    },
+    "binary-extensions": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
+      "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
+    },
+    "brace-expansion": {
+      "version": "1.1.11",
+      "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+      "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+      "dev": true,
+      "requires": {
+        "balanced-match": "^1.0.0",
+        "concat-map": "0.0.1"
+      }
+    },
+    "braces": {
+      "version": "3.0.2",
+      "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
+      "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+      "requires": {
+        "fill-range": "^7.0.1"
+      }
+    },
+    "chokidar": {
+      "version": "3.5.2",
+      "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
+      "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
+      "requires": {
+        "anymatch": "~3.1.2",
+        "braces": "~3.0.2",
+        "fsevents": "~2.3.2",
+        "glob-parent": "~5.1.2",
+        "is-binary-path": "~2.1.0",
+        "is-glob": "~4.0.1",
+        "normalize-path": "~3.0.0",
+        "readdirp": "~3.6.0"
+      }
+    },
+    "clang-format": {
+      "version": "1.8.0",
+      "resolved": "https://registry.npmjs.org/clang-format/-/clang-format-1.8.0.tgz",
+      "integrity": "sha512-pK8gzfu55/lHzIpQ1givIbWfn3eXnU7SfxqIwVgnn5jEM6j4ZJYjpFqFs4iSBPNedzRMmfjYjuQhu657WAXHXw==",
+      "dev": true,
+      "requires": {
+        "async": "^3.2.3",
+        "glob": "^7.0.0",
+        "resolve": "^1.1.6"
+      }
+    },
+    "coc.nvim": {
+      "version": "0.0.83-next.9",
+      "resolved": "https://registry.npmjs.org/coc.nvim/-/coc.nvim-0.0.83-next.9.tgz",
+      "integrity": "sha512-ek5+EgA9N92/6Wt07TAYpavmBgXZto4Dmwmm56oyBl/w4wy3Tod7LfpCp4k9M4xCxhxPtrflIcxvhdDUPIeMuw==",
+      "dev": true,
+      "requires": {}
+    },
+    "concat-map": {
+      "version": "0.0.1",
+      "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+      "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
+      "dev": true
+    },
+    "fill-range": {
+      "version": "7.0.1",
+      "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
+      "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+      "requires": {
+        "to-regex-range": "^5.0.1"
+      }
+    },
+    "fs.realpath": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+      "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=",
+      "dev": true
+    },
+    "fsevents": {
+      "version": "2.3.2",
+      "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
+      "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+      "optional": true
+    },
+    "function-bind": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
+      "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
+      "dev": true
+    },
+    "glob": {
+      "version": "7.1.7",
+      "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz",
+      "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==",
+      "dev": true,
+      "requires": {
+        "fs.realpath": "^1.0.0",
+        "inflight": "^1.0.4",
+        "inherits": "2",
+        "minimatch": "^3.0.4",
+        "once": "^1.3.0",
+        "path-is-absolute": "^1.0.0"
+      }
+    },
+    "glob-parent": {
+      "version": "5.1.2",
+      "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+      "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+      "requires": {
+        "is-glob": "^4.0.1"
+      }
+    },
+    "has": {
+      "version": "1.0.3",
+      "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
+      "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
+      "dev": true,
+      "requires": {
+        "function-bind": "^1.1.1"
+      }
+    },
+    "inflight": {
+      "version": "1.0.6",
+      "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+      "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+      "dev": true,
+      "requires": {
+        "once": "^1.3.0",
+        "wrappy": "1"
+      }
+    },
+    "inherits": {
+      "version": "2.0.4",
+      "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+      "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+      "dev": true
+    },
+    "is-binary-path": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+      "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+      "requires": {
+        "binary-extensions": "^2.0.0"
+      }
+    },
+    "is-core-module": {
+      "version": "2.5.0",
+      "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.5.0.tgz",
+      "integrity": "sha512-TXCMSDsEHMEEZ6eCA8rwRDbLu55MRGmrctljsBX/2v1d9/GzqHOxW5c5oPSgrUt2vBFXebu9rGqckXGPWOlYpg==",
+      "dev": true,
+      "requires": {
+        "has": "^1.0.3"
+      }
+    },
+    "is-extglob": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+      "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI="
+    },
+    "is-glob": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz",
+      "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==",
+      "requires": {
+        "is-extglob": "^2.1.1"
+      }
+    },
+    "is-number": {
+      "version": "7.0.0",
+      "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+      "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="
+    },
+    "minimatch": {
+      "version": "3.0.4",
+      "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+      "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+      "dev": true,
+      "requires": {
+        "brace-expansion": "^1.1.7"
+      }
+    },
+    "normalize-path": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+      "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA=="
+    },
+    "once": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+      "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+      "dev": true,
+      "requires": {
+        "wrappy": "1"
+      }
+    },
+    "path-is-absolute": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+      "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
+      "dev": true
+    },
+    "path-parse": {
+      "version": "1.0.7",
+      "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+      "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+      "dev": true
+    },
+    "picomatch": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
+      "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw=="
+    },
+    "readdirp": {
+      "version": "3.6.0",
+      "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+      "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+      "requires": {
+        "picomatch": "^2.2.1"
+      }
+    },
+    "resolve": {
+      "version": "1.20.0",
+      "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
+      "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+      "dev": true,
+      "requires": {
+        "is-core-module": "^2.2.0",
+        "path-parse": "^1.0.6"
+      }
+    },
+    "to-regex-range": {
+      "version": "5.0.1",
+      "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+      "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+      "requires": {
+        "is-number": "^7.0.0"
+      }
+    },
+    "typescript": {
+      "version": "4.6.4",
+      "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.4.tgz",
+      "integrity": "sha512-9ia/jWHIEbo49HfjrLGfKbZSuWo9iTMwXO+Ca3pRsSpbsMbc7/IU8NKdCZVRRBafVPGnoJeFL76ZOAA84I9fEg==",
+      "dev": true
+    },
+    "wrappy": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+      "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=",
+      "dev": true
+    }
+  }
+}
diff --git a/mlir/utils/coc.nvim/package.json b/mlir/utils/coc.nvim/package.json
new file mode 100644
index 00000000000000..5b6c76efa4c555
--- /dev/null
+++ b/mlir/utils/coc.nvim/package.json
@@ -0,0 +1,213 @@
+{
+  "name": "coc-mlir",
+  "displayName": "MLIR",
+  "description": "MLIR Language Extension",
+  "version": "0.0.11",
+  "publisher": "llvm-vs-code-extensions",
+  "homepage": "https://mlir.llvm.org/",
+  "icon": "icon.png",
+  "engines": {
+    "coc": "^0.0.82"
+  },
+  "categories": [
+    "Programming Languages"
+  ],
+  "keywords": [
+    "coc.nvim",
+    "LLVM",
+    "MLIR",
+    "PDLL",
+    "TableGen",
+    "tblgen",
+    "tablegen"
+  ],
+  "activationEvents": [
+    "onFileSystem:mlir.bytecode-mlir",
+    "onCustomEditor:mlir.bytecode",
+    "onLanguage:mlir",
+    "onLanguage:pdll",
+    "onLanguage:tablegen"
+  ],
+  "main": "./out/extension.js",
+  "scripts": {
+    "prepare": "tsc -p ./",
+    "compile": "tsc -watch -p ./",
+    "format": "clang-format -i --glob=\"{src,test}/*.ts\"",
+    "package": "vsce package",
+    "git-clang-format": "git-clang-format"
+  },
+  "dependencies": {
+    "base64-js": "^1.5.1",
+    "chokidar": "3.5.2"
+  },
+  "devDependencies": {
+    "@types/mocha": "^7.0.2",
+    "@types/node": "^14.17.0",
+    "clang-format": "^1.8.0",
+    "coc.nvim": "^0.0.83-next.18",
+    "typescript": "^4.6.4",
+    "which": "^4.0.0"
+  },
+  "repository": {
+    "type": "git",
+    "url": "https://github.com/Freed-Wu/coc-mlir"
+  },
+  "contributes": {
+    "customEditors": [
+      {
+        "viewType": "mlir.bytecode",
+        "displayName": "MLIR Bytecode",
+        "priority": "default",
+        "selector": [
+          {
+            "filenamePattern": "*.mlirbc"
+          }
+        ]
+      }
+    ],
+    "languages": [
+      {
+        "id": "mlir",
+        "aliases": [
+          "MLIR",
+          "mlir"
+        ],
+        "extensions": [
+          ".mlir",
+          ".mlirbc"
+        ],
+        "configuration": "./language-configuration.json"
+      },
+      {
+        "id": "mlir-injection"
+      },
+      {
+        "id": "pdll",
+        "aliases": [
+          "PDLL",
+          "pdll"
+        ],
+        "extensions": [
+          ".pdll"
+        ],
+        "configuration": "./pdll-language-configuration.json"
+      },
+      {
+        "id": "tablegen",
+        "aliases": [
+          "TableGen",
+          "tblgen"
+        ],
+        "extensions": [
+          ".td"
+        ],
+        "configuration": "./tablegen-language-configuration.json"
+      }
+    ],
+    "grammars": [
+      {
+        "language": "mlir",
+        "scopeName": "source.mlir",
+        "path": "./grammar.json"
+      },
+      {
+        "language": "mlir-injection",
+        "scopeName": "markdown.mlir.codeblock",
+        "path": "markdown-grammar.json",
+        "injectTo": [
+          "text.html.markdown"
+        ],
+        "embeddedLanguages": {
+          "meta.embedded.block.mlir": "mlir",
+          "meta.embedded.block.pdll": "pdll",
+          "meta.embedded.block.tablegen": "tablegen"
+        }
+      },
+      {
+        "scopeName": "source.cpp.mlir",
+        "path": "./cpp-grammar.json",
+        "injectTo": [
+          "source.cpp"
+        ],
+        "embeddedLanguages": {
+          "source.mlir": "mlir"
+        }
+      },
+      {
+        "language": "pdll",
+        "scopeName": "source.pdll",
+        "path": "./pdll-grammar.json"
+      },
+      {
+        "language": "tablegen",
+        "scopeName": "source.tablegen",
+        "path": "./tablegen-grammar.json"
+      }
+    ],
+    "configuration": {
+      "type": "object",
+      "title": "MLIR",
+      "properties": {
+        "mlir.server_path": {
+          "scope": "resource",
+          "type": "string",
+          "description": "The file path of the mlir-lsp-server executable."
+        },
+        "mlir.pdll_server_path": {
+          "scope": "resource",
+          "type": "string",
+          "description": "The file path of the mlir-pdll-lsp-server executable."
+        },
+        "mlir.pdll_compilation_databases": {
+          "scope": "resource",
+          "type": "array",
+          "description": "A list of `pdll_compile_commands.yml` database files containing information about .pdll files processed by the server."
+        },
+        "mlir.tablegen_server_path": {
+          "scope": "resource",
+          "type": "string",
+          "description": "The file path of the tblgen-lsp-server executable."
+        },
+        "mlir.tablegen_compilation_databases": {
+          "scope": "resource",
+          "type": "array",
+          "description": "A list of `tablegen_compile_commands.yml` database files containing information about .td files processed by the server."
+        },
+        "mlir.onSettingsChanged": {
+          "type": "string",
+          "default": "prompt",
+          "description": "Action taken when a setting change requires a server restart to take effect.",
+          "enum": [
+            "prompt",
+            "restart",
+            "ignore"
+          ],
+          "enumDescriptions": [
+            "Prompt the user for restarting the server",
+            "Automatically restart the server",
+            "Do nothing"
+          ]
+        }
+      }
+    },
+    "commands": [
+      {
+        "command": "mlir.restart",
+        "title": "mlir: Restart language server"
+      },
+      {
+        "command": "mlir.viewPDLLOutput",
+        "title": "mlir-pdll: View PDLL output"
+      }
+    ],
+    "menus": {
+      "editor/context": [
+        {
+          "command": "mlir.viewPDLLOutput",
+          "group": "z_commands",
+          "when": "editorLangId == pdll"
+        }
+      ]
+    }
+  }
+}
diff --git a/mlir/utils/coc.nvim/pdll-grammar.json b/mlir/utils/coc.nvim/pdll-grammar.json
new file mode 100644
index 00000000000000..47c8968c3ac0c4
--- /dev/null
+++ b/mlir/utils/coc.nvim/pdll-grammar.json
@@ -0,0 +1,524 @@
+{
+  "name": "PDLL",
+  "fileTypes": [
+    "pdll"
+  ],
+  "patterns": [
+    {
+      "include": "#comment"
+    },
+    {
+      "include": "#string"
+    },
+    {
+      "include": "#string_block"
+    },
+    {
+      "include": "#integer"
+    },
+    {
+      "include": "#include"
+    },
+    {
+      "include": "#user_constraint"
+    },
+    {
+      "include": "#user_rewrite"
+    },
+    {
+      "include": "#pattern"
+    },
+    {
+      "include": "#inside_pattern"
+    }
+  ],
+  "repository": {
+    "comment": {
+      "match": "\/\/.*$",
+      "name": "comment.line.double-slash.pdll"
+    },
+    "string": {
+      "name": "string.quoted.double.pdll",
+      "begin": "\"",
+      "end": "\"",
+      "beginCaptures": {
+        "0": {
+          "name": "punctuation.definition.string.begin.pdll"
+        }
+      },
+      "patterns": [
+        {
+          "match": "\\\\[nt\"]",
+          "name": "constant.character.escape.pdll"
+        },
+        {
+          "match": "\\\\.",
+          "name": "invalid.illegal.pdll"
+        }
+      ],
+      "endCaptures": {
+        "0": {
+          "name": "punctuation.definition.string.end.pdll"
+        }
+      }
+    },
+    "string_block": {
+      "name": "string.quoted.triple.pdll",
+      "begin": "\\[{",
+      "end": "}]",
+      "beginCaptures": {
+        "0": {
+          "name": "punctuation.definition.string.begin.pdll"
+        }
+      },
+      "patterns": [
+        {
+          "match": "\\\\[nt\"]",
+          "name": "constant.character.escape.pdll"
+        },
+        {
+          "match": "\\\\.",
+          "name": "invalid.illegal.pdll"
+        }
+      ],
+      "endCaptures": {
+        "0": {
+          "name": "punctuation.definition.string.end.pdll"
+        }
+      }
+    },
+    "integer": {
+      "match": "[0-9]+",
+      "name": "constant.numeric.pdll"
+    },
+    "include": {
+      "patterns": [
+        {
+          "match": "(#include)",
+          "name": "keyword.control.pdll"
+        }
+      ]
+    },
+    "argument_or_result_list": {
+      "patterns": [
+        {
+          "match": "\\b([aA-zZ_0-9]*)\\b\\s*:\\s*([aA-zZ_0-9]+)\\b(\\<([^\\>]+)\\>)?",
+          "captures": {
+            "1": {
+              "name": "variable.parameter.pdll"
+            },
+            "2": {
+              "name": "entity.name.type.pdll"
+            },
+            "4": {
+              "name": "variable.other.enummember.pdll"
+            }
+          }
+        },
+        {
+          "match": "(\\(|\\>|,)\\s*([aA-zZ_0-9]+)\\b(\\<([^\\>]+)\\>)?\\s*(?=[^:])",
+          "captures": {
+            "2": {
+              "name": "entity.name.type.pdll"
+            },
+            "4": {
+              "name": "variable.other.enummember.pdll"
+            }
+          }
+        }
+      ]
+    },
+    "user_constraint": {
+      "patterns": [
+        {
+          "begin": "\\b(Constraint)\\b\\s*(\\b[aA-zZ_0-9]*\\b)?",
+          "beginCaptures": {
+            "1": {
+              "name": "keyword.other.pdll"
+            },
+            "2": {
+              "name": "entity.name.type.pdll"
+            }
+          },
+          "patterns": [
+            {
+              "begin": "(\\[{)",
+              "patterns": [
+                {
+                  "include": "source.cpp"
+                }
+              ],
+              "end": "(}])"
+            },
+            {
+              "begin": "(?=\\()",
+              "patterns": [
+                {
+                  "include": "#argument_or_result_list"
+                }
+              ],
+              "end": "\\)"
+            },
+            {
+              "include": "#argument_or_result_list"
+            },
+            {
+              "begin": "{",
+              "patterns": [
+                {
+                  "include": "#inside_pattern"
+                }
+              ],
+              "end": "(?=})"
+            },
+            {
+              "begin": "=>",
+              "patterns": [
+                {
+                  "include": "#inside_pattern"
+                }
+              ],
+              "end": "(?=;|,|\\))"
+            }
+          ],
+          "end": "(}|;|,)|(?=\\))"
+        }
+      ]
+    },
+    "user_rewrite": {
+      "patterns": [
+        {
+          "begin": "\\b(Rewrite)\\b\\s*(\\b[aA-zZ_0-9]*\\b)?",
+          "beginCaptures": {
+            "1": {
+              "name": "keyword.other.pdll"
+            },
+            "2": {
+              "name": "entity.name.function.pdll"
+            }
+          },
+          "patterns": [
+            {
+              "begin": "(\\[{)",
+              "patterns": [
+                {
+                  "include": "source.cpp"
+                }
+              ],
+              "end": "(}])"
+            },
+            {
+              "begin": "(?=\\()",
+              "patterns": [
+                {
+                  "include": "#argument_or_result_list"
+                }
+              ],
+              "end": "\\)"
+            },
+            {
+              "include": "#argument_or_result_list"
+            },
+            {
+              "begin": "{",
+              "patterns": [
+                {
+                  "include": "#inside_pattern"
+                }
+              ],
+              "end": "(?=})"
+            },
+            {
+              "begin": "=>",
+              "patterns": [
+                {
+                  "include": "#inside_pattern"
+                }
+              ],
+              "end": "(?=;|,|\\))"
+            }
+          ],
+          "end": "(}|;|,)|(?=\\))"
+        }
+      ]
+    },
+    "pattern_metadata": {
+      "patterns": [
+        {
+          "match": "\\b(with)\\b",
+          "name": "keyword.other.pdll"
+        },
+        {
+          "match": "\\b(benefit)\\b\\(([0-9]+)\\)",
+          "captures": {
+            "1": {
+              "name": "entity.name.variable.pdll"
+            },
+            "2": {
+              "name": "constant.numeric.pdll"
+            }
+          }
+        },
+        {
+          "match": "\\b(recursion)\\b",
+          "name": "entity.name.variable.pdll"
+        }
+      ]
+    },
+    "pattern": {
+      "patterns": [
+        {
+          "begin": "\\b(Pattern)\\b\\s*(\\b[aA-zZ_0-9]*\\b)?\\s*(\\bwith\\b\\s*[^\\{]*)?\\s*({)",
+          "beginCaptures": {
+            "1": {
+              "name": "keyword.other.pdll"
+            },
+            "2": {
+              "name": "entity.name.function.pdll"
+            },
+            "3": {
+              "patterns": [
+                {
+                  "include": "#pattern_metadata"
+                }
+              ]
+            }
+          },
+          "patterns": [
+            {
+              "include": "#inside_pattern"
+            }
+          ],
+          "end": "(})"
+        },
+        {
+          "begin": "\\b(Pattern)\\b\\s*(\\b[aA-zZ_0-9]*\\b)?\\s*(\\bwith\\b\\s*[^\\=]*)?\\s*(=>)",
+          "beginCaptures": {
+            "1": {
+              "name": "keyword.other.pdll"
+            },
+            "2": {
+              "name": "entity.name.function.pdll"
+            },
+            "3": {
+              "patterns": [
+                {
+                  "include": "#pattern_metadata"
+                }
+              ]
+            }
+          },
+          "patterns": [
+            {
+              "include": "#inside_pattern"
+            }
+          ],
+          "end": ";"
+        }
+      ]
+    },
+    "inside_pattern": {
+      "patterns": [
+        {
+          "match": "\\b(erase|let|replace|return|rewrite|with)\\b",
+          "captures": {
+            "1": {
+              "name": "keyword.control.pdll"
+            }
+          }
+        },
+        {
+          "include": "#expressions"
+        }
+      ]
+    },
+    "variable_constraint": {
+      "patterns": [
+        {
+          "match": "\\b(Op)<([a-zA-Z0-9_\\.$-]*)>",
+          "captures": {
+            "1": {
+              "name": "entity.name.type.pdll"
+            },
+            "2": {
+              "name": "variable.other.enummember.pdll"
+            }
+          }
+        },
+        {
+          "begin": "<",
+          "patterns": [
+            {
+              "include": "#expressions"
+            }
+          ],
+          "end": ">"
+        },
+        {
+          "match": "[a-zA-Z_0-9]+",
+          "name": "entity.name.type.pdll"
+        }
+      ]
+    },
+    "variable_definition": {
+      "patterns": [
+        {
+          "begin": "\\b([aA-zZ_0-9]*)\\b\\s*:\\s*\\[",
+          "beginCaptures": {
+            "1": {
+              "name": "entity.name.variable.pdll"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#variable_constraint"
+            }
+          ],
+          "end": "\\]"
+        },
+        {
+          "match": "\\b([aA-zZ_0-9]*)\\b\\s*:\\s*([aA-zZ_0-9]+(\\<([^\\>]+)\\>)?)",
+          "captures": {
+            "1": {
+              "name": "entity.name.variable.pdll"
+            },
+            "2": {
+              "patterns": [
+                {
+                  "include": "#variable_constraint"
+                }
+              ]
+            }
+          }
+        }
+      ]
+    },
+    "expressions": {
+      "patterns": [
+        {
+          "include": "#user_constraint"
+        },
+        {
+          "include": "#user_rewrite"
+        },
+        {
+          "include": "#attr_expr"
+        },
+        {
+          "include": "#op_expr"
+        },
+        {
+          "include": "#type_expr"
+        },
+        {
+          "include": "#call_expr"
+        },
+        {
+          "include": "#variable_definition"
+        },
+        {
+          "include": "#identifier_expr"
+        },
+        {
+          "include": "#string"
+        },
+        {
+          "include": "#string_block"
+        },
+        {
+          "include": "#comment"
+        },
+        {
+          "begin": "{",
+          "patterns": [
+            {
+              "include": "#inside_pattern"
+            }
+          ],
+          "end": "}"
+        },
+        {
+          "begin": "\\(",
+          "patterns": [
+            {
+              "include": "#expressions"
+            }
+          ],
+          "end": "\\)"
+        }
+      ]
+    },
+    "attr_expr": {
+      "patterns": [
+        {
+          "begin": "(attr)<",
+          "beginCaptures": {
+            "1": {
+              "name": "keyword.other.pdll"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#string"
+            },
+            {
+              "include": "#string_block"
+            }
+          ],
+          "end": ">"
+        }
+      ]
+    },
+    "call_expr": {
+      "begin": "\\b([a-zA-Z0-9_]+)\\(",
+      "beginCaptures": {
+        "1": {
+          "name": "entity.name.variable.pdll"
+        }
+      },
+      "patterns": [
+        {
+          "include": "#expressions"
+        }
+      ],
+      "end": "\\)"
+    },
+    "identifier_expr": {
+      "match": "\\b([a-zA-Z0-9_]+)\\b",
+      "name": "entity.name.variable.pdll"
+    },
+    "op_expr": {
+      "match": "\\b(op)<([0-9a-zA-Z_\\.]*)>",
+      "captures": {
+        "1": {
+          "name": "keyword.other.pdll"
+        },
+        "2": {
+          "name": "variable.other.enummember.pdll"
+        }
+      }
+    },
+    "type_expr": {
+      "patterns": [
+        {
+          "begin": "\\b(type)<",
+          "beginCaptures": {
+            "1": {
+              "name": "keyword.other.pdll"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#string"
+            },
+            {
+              "include": "#string_block"
+            }
+          ],
+          "end": ">"
+        }
+      ]
+    }
+  },
+  "scopeName": "source.pdll"
+}
\ No newline at end of file
diff --git a/mlir/utils/coc.nvim/pdll-language-configuration.json b/mlir/utils/coc.nvim/pdll-language-configuration.json
new file mode 100644
index 00000000000000..1357db8a9d4db1
--- /dev/null
+++ b/mlir/utils/coc.nvim/pdll-language-configuration.json
@@ -0,0 +1,67 @@
+{
+  "comments": {
+    "lineComment": "//"
+  },
+  "brackets": [
+    [
+      "{",
+      "}"
+    ],
+    [
+      "[",
+      "]"
+    ],
+    [
+      "(",
+      ")"
+    ],
+    [
+      "<",
+      ">"
+    ]
+  ],
+  "autoClosingPairs": [
+    [
+      "{",
+      "}"
+    ],
+    [
+      "[",
+      "]"
+    ],
+    [
+      "(",
+      ")"
+    ],
+    [
+      "<",
+      ">"
+    ],
+    [
+      "\"",
+      "\""
+    ]
+  ],
+  "surroundingPairs": [
+    [
+      "{",
+      "}"
+    ],
+    [
+      "[",
+      "]"
+    ],
+    [
+      "(",
+      ")"
+    ],
+    [
+      "<",
+      ">"
+    ],
+    [
+      "\"",
+      "\""
+    ]
+  ]
+}
\ No newline at end of file
diff --git a/mlir/utils/coc.nvim/src/config.ts b/mlir/utils/coc.nvim/src/config.ts
new file mode 100644
index 00000000000000..9e5e287ce4ed1f
--- /dev/null
+++ b/mlir/utils/coc.nvim/src/config.ts
@@ -0,0 +1,19 @@
+import * as vscode from 'coc.nvim';
+
+/**
+ *  Gets the config value `mlir.<key>`, with an optional workspace folder.
+ */
+export function get<T>(key: string,
+                       workspaceFolder: vscode.WorkspaceFolder = null,
+                       defaultValue: T = undefined): T {
+  return vscode.workspace.getConfiguration('mlir', workspaceFolder)
+      .get<T>(key, defaultValue);
+}
+
+/**
+ *  Sets the config value `mlir.<key>`.
+ */
+export function update<T>(key: string, value: T,
+                          target?: vscode.ConfigurationTarget) {
+  return vscode.workspace.getConfiguration('mlir').update(key, value, target);
+}
diff --git a/mlir/utils/coc.nvim/src/configWatcher.ts b/mlir/utils/coc.nvim/src/configWatcher.ts
new file mode 100644
index 00000000000000..ffb94ef4c558db
--- /dev/null
+++ b/mlir/utils/coc.nvim/src/configWatcher.ts
@@ -0,0 +1,86 @@
+import * as chokidar from 'chokidar';
+import * as vscode from 'coc.nvim';
+
+import * as config from './config';
+import {MLIRContext} from './mlirContext';
+
+/**
+ *  Prompt the user to see if we should restart the server.
+ */
+async function promptRestart(settingName: string, promptMessage: string) {
+  switch (config.get<string>(settingName)) {
+  case 'restart':
+    vscode.commands.executeCommand('mlir.restart');
+    break;
+  case 'ignore':
+    break;
+  case 'prompt':
+  default:
+    switch (await vscode.window.showInformationMessage(
+        promptMessage, 'Yes', 'Yes, always', 'No, never')) {
+    case 'Yes':
+      vscode.commands.executeCommand('mlir.restart');
+      break;
+    case 'Yes, always':
+      vscode.commands.executeCommand('mlir.restart');
+      config.update<string>(settingName, 'restart',
+                            vscode.ConfigurationTarget.Global);
+      break;
+    case 'No, never':
+      config.update<string>(settingName, 'ignore',
+                            vscode.ConfigurationTarget.Global);
+      break;
+    default:
+      break;
+    }
+    break;
+  }
+}
+
+/**
+ *  Activate watchers that track configuration changes for the given workspace
+ *  folder, or null if the workspace is top-level.
+ */
+export async function activate(
+    mlirContext: MLIRContext, workspaceFolder: vscode.WorkspaceFolder,
+    serverSettings: string[], serverPaths: string[]) {
+  // When a configuration change happens, check to see if we should restart the
+  // server.
+  mlirContext.subscriptions.push(vscode.workspace.onDidChangeConfiguration(event => {
+    for (const serverSetting of serverSettings) {
+      const expandedSetting = `mlir.${serverSetting}`;
+      if (event.affectsConfiguration(expandedSetting, workspaceFolder)) {
+        promptRestart(
+            'onSettingsChanged',
+            `setting '${
+                expandedSetting}' has changed. Do you want to reload the server?`);
+      }
+    }
+  }));
+
+  // Setup watchers for the provided server paths.
+  const fileWatcherConfig = {
+    disableGlobbing : true,
+    followSymlinks : true,
+    ignoreInitial : true,
+    awaitWriteFinish : true,
+  };
+  for (const serverPath of serverPaths) {
+    if (serverPath === '') {
+      return;
+    }
+
+    // If the server path actually exists, track it in case it changes.
+    // TODO: coc.nvim doesn't have this API
+    // const fileWatcher = chokidar.watch(serverPath, fileWatcherConfig);
+    // fileWatcher.on('all', (event, _filename, _details) => {
+    //   if (event != 'unlink') {
+    //     promptRestart(
+    //         'onSettingsChanged',
+    //         'MLIR language server file has changed. Do you want to reload the server?');
+    //   }
+    // });
+    // mlirContext.subscriptions.push(
+    //     new vscode.Disposable(() => { fileWatcher.close(); }));
+  }
+}
diff --git a/mlir/utils/coc.nvim/src/extension.ts b/mlir/utils/coc.nvim/src/extension.ts
new file mode 100644
index 00000000000000..363b8a21a5a404
--- /dev/null
+++ b/mlir/utils/coc.nvim/src/extension.ts
@@ -0,0 +1,30 @@
+import * as vscode from 'coc.nvim';
+
+// import {registerMLIRExtensions} from './MLIR/mlir';
+import {MLIRContext} from './mlirContext';
+// TODO: https://github.com/neoclide/coc.nvim/discussions/4918
+// import {registerPDLLExtensions} from './PDLL/pdll';
+
+/**
+ *  This method is called when the extension is activated. The extension is
+ *  activated the very first time a command is executed.
+ */
+export function activate(context: vscode.ExtensionContext) {
+  const outputChannel = vscode.window.createOutputChannel('MLIR');
+  context.subscriptions.push(outputChannel);
+
+  const mlirContext = new MLIRContext();
+  context.subscriptions.push(mlirContext);
+
+  // Initialize the commands of the extension.
+  context.subscriptions.push(
+      vscode.commands.registerCommand('mlir.restart', async () => {
+        // Dispose and reactivate the context.
+        mlirContext.dispose();
+        await mlirContext.activate(outputChannel);
+      }));
+  // registerMLIRExtensions(context, mlirContext);
+  // registerPDLLExtensions(context, mlirContext);
+
+  mlirContext.activate(outputChannel);
+}
diff --git a/mlir/utils/coc.nvim/src/mlirContext.ts b/mlir/utils/coc.nvim/src/mlirContext.ts
new file mode 100644
index 00000000000000..136ce7e33a79d7
--- /dev/null
+++ b/mlir/utils/coc.nvim/src/mlirContext.ts
@@ -0,0 +1,392 @@
+import * as fs from 'fs';
+import * as path from 'path';
+import * as vscode from 'coc.nvim';
+import * as vscodelc from 'coc.nvim';
+import * as which from 'which';
+
+import * as config from './config';
+import * as configWatcher from './configWatcher';
+
+/**
+ *  This class represents the context of a specific workspace folder.
+ */
+class WorkspaceFolderContext implements vscode.Disposable {
+  dispose() {
+    this.clients.forEach(async client => await client.stop());
+    this.clients.clear();
+  }
+
+  clients: Map<string, vscodelc.LanguageClient> = new Map();
+}
+
+/**
+ *  This class manages all of the MLIR extension state,
+ *  including the language client.
+ */
+export class MLIRContext implements vscode.Disposable {
+  subscriptions: vscode.Disposable[] = [];
+  workspaceFolders: Map<string, WorkspaceFolderContext> = new Map();
+  outputChannel: vscode.OutputChannel;
+
+  /**
+   *  Activate the MLIR context, and start the language clients.
+   */
+  async activate(outputChannel: vscode.OutputChannel) {
+    this.outputChannel = outputChannel;
+
+    // This lambda is used to lazily start language clients for the given
+    // document. It removes the need to pro-actively start language clients for
+    // every folder within the workspace and every language type we provide.
+    const startClientOnOpenDocument = async (document: vscode.TextDocument) => {
+      await this.getOrActivateLanguageClient(vscode.Uri.parse(document.uri), document.languageId);
+    };
+    // Process any existing documents.
+    for (const textDoc of vscode.workspace.textDocuments) {
+      await startClientOnOpenDocument(textDoc);
+    }
+
+    // Watch any new documents to spawn servers when necessary.
+    this.subscriptions.push(
+        vscode.workspace.onDidOpenTextDocument(startClientOnOpenDocument));
+    this.subscriptions.push(
+        vscode.workspace.onDidChangeWorkspaceFolders((event) => {
+          for (const folder of event.removed) {
+            const client = this.workspaceFolders.get(folder.uri.toString());
+            if (client) {
+              client.dispose();
+              this.workspaceFolders.delete(folder.uri.toString());
+            }
+          }
+        }));
+  }
+
+  /**
+   * Open or return a language server for the given uri and language.
+   */
+  async getOrActivateLanguageClient(uri: vscode.Uri, languageId: string):
+      Promise<vscodelc.LanguageClient> {
+    let serverSettingName: string;
+    if (languageId === 'mlir') {
+      serverSettingName = 'server_path';
+    } else if (languageId === 'pdll') {
+      serverSettingName = 'pdll_server_path';
+    } else if (languageId === 'tablegen') {
+      serverSettingName = 'tablegen_server_path';
+    } else {
+      return null;
+    }
+
+    // Check the scheme of the uri.
+    let validSchemes = [ 'file', 'mlir.bytecode-mlir' ];
+    if (!validSchemes.includes(uri.scheme)) {
+      return null;
+    }
+
+    // Resolve the workspace folder if this document is in one. We use the
+    // workspace folder when determining if a server needs to be started.
+    let workspaceFolder = vscode.workspace.getWorkspaceFolder(uri);
+    let workspaceFolderStr =
+        workspaceFolder ? workspaceFolder.uri.toString() : "";
+
+    // Get or create a client context for this folder.
+    let folderContext = this.workspaceFolders.get(workspaceFolderStr);
+    if (!folderContext) {
+      folderContext = new WorkspaceFolderContext();
+      this.workspaceFolders.set(workspaceFolderStr, folderContext);
+    }
+    // Start the client for this language if necessary.
+    let client = folderContext.clients.get(languageId);
+    if (!client) {
+      client = await this.activateWorkspaceFolder(
+          workspaceFolder, serverSettingName, languageId, this.outputChannel);
+      folderContext.clients.set(languageId, client);
+    }
+    return client;
+  }
+
+  /**
+   *  Prepare a compilation database option for a server.
+   */
+  async prepareCompilationDatabaseServerOptions(
+      languageName: string, workspaceFolder: vscode.WorkspaceFolder,
+      configsToWatch: string[], pathsToWatch: string[],
+      additionalServerArgs: string[]) {
+    // Process the compilation databases attached for the workspace folder.
+    let databases = config.get<string[]>(
+        `${languageName}_compilation_databases`, workspaceFolder, []);
+
+    // If no databases were explicitly specified, default to a database in the
+    // 'build' directory within the current workspace.
+    if (databases.length === 0) {
+      if (workspaceFolder) {
+        databases.push(vscode.Uri.parse(workspaceFolder.uri).fsPath +
+                       `/build/${languageName}_compile_commands.yml`);
+      }
+
+      // Otherwise, try to resolve each of the paths.
+    } else {
+      for await (let database of databases) {
+        database = await this.resolvePath(database, '', workspaceFolder);
+      }
+    }
+
+    configsToWatch.push(`${languageName}_compilation_databases`);
+    pathsToWatch.push(...databases);
+
+    // Setup the compilation databases as additional arguments to pass to the
+    // server.
+    databases.filter(database => database !== '');
+    additionalServerArgs.push(...databases.map(
+        (database) => `--${languageName}-compilation-database=${database}`));
+  }
+
+  /**
+   *  Prepare the server options for a PDLL server, e.g. populating any
+   *  accessible compilation databases.
+   */
+  async preparePDLLServerOptions(workspaceFolder: vscode.WorkspaceFolder,
+                                 configsToWatch: string[],
+                                 pathsToWatch: string[],
+                                 additionalServerArgs: string[]) {
+    await this.prepareCompilationDatabaseServerOptions(
+        'pdll', workspaceFolder, configsToWatch, pathsToWatch,
+        additionalServerArgs);
+  }
+
+  /**
+   *  Prepare the server options for a TableGen server, e.g. populating any
+   *  accessible compilation databases.
+   */
+  async prepareTableGenServerOptions(workspaceFolder: vscode.WorkspaceFolder,
+                                     configsToWatch: string[],
+                                     pathsToWatch: string[],
+                                     additionalServerArgs: string[]) {
+    await this.prepareCompilationDatabaseServerOptions(
+        'tablegen', workspaceFolder, configsToWatch, pathsToWatch,
+        additionalServerArgs);
+  }
+
+  /**
+   *  Activate the language client for the given language in the given workspace
+   *  folder.
+   */
+  async activateWorkspaceFolder(workspaceFolder: vscode.WorkspaceFolder,
+                                serverSettingName: string, languageName: string,
+                                outputChannel: vscode.OutputChannel):
+      Promise<vscodelc.LanguageClient> {
+    let configsToWatch: string[] = [];
+    let filepathsToWatch: string[] = [];
+    let additionalServerArgs: string[] = [];
+
+    // Initialize additional configurations for this server.
+    if (languageName === 'pdll') {
+      await this.preparePDLLServerOptions(workspaceFolder, configsToWatch,
+                                          filepathsToWatch,
+                                          additionalServerArgs);
+    } else if (languageName == 'tablegen') {
+      await this.prepareTableGenServerOptions(workspaceFolder, configsToWatch,
+                                              filepathsToWatch,
+                                              additionalServerArgs);
+    }
+
+    // Try to activate the language client.
+    const [server, serverPath] = await this.startLanguageClient(
+        workspaceFolder, outputChannel, serverSettingName, languageName,
+        additionalServerArgs);
+    configsToWatch.push(serverSettingName);
+    filepathsToWatch.push(serverPath);
+
+    // Watch for configuration changes on this folder.
+    await configWatcher.activate(this, workspaceFolder, configsToWatch,
+                                 filepathsToWatch);
+    return server;
+  }
+
+  /**
+   *  Start a new language client for the given language. Returns an array
+   *  containing the opened server, or null if the server could not be started,
+   *  and the resolved server path.
+   */
+  async startLanguageClient(workspaceFolder: vscode.WorkspaceFolder,
+                            outputChannel: vscode.OutputChannel,
+                            serverSettingName: string, languageName: string,
+                            additionalServerArgs: string[]):
+      Promise<[ vscodelc.LanguageClient, string ]> {
+    const clientTitle = languageName.toUpperCase() + ' Language Client';
+
+    // Get the path of the lsp-server that is used to provide language
+    // functionality.
+    var serverPath =
+        await this.resolveServerPath(serverSettingName, workspaceFolder);
+
+    // If the server path is empty, bail. We don't emit errors if the user
+    // hasn't explicitly configured the server.
+    if (serverPath === '') {
+      return [ null, serverPath ];
+    }
+
+    // Check that the file actually exists.
+    if (!fs.existsSync(serverPath)) {
+      vscode.window
+          .showErrorMessage(
+              `${clientTitle}: Unable to resolve path for '${
+                  serverSettingName}', please ensure the path is correct`,
+              "Open Setting")
+          .then((value) => {
+            if (value === "Open Setting") {
+              vscode.commands.executeCommand(
+                  'workbench.action.openWorkspaceSettings',
+                  {openToSide : false, query : `mlir.${serverSettingName}`});
+            }
+          });
+      return [ null, serverPath ];
+    }
+
+    // Configure the server options.
+    const serverOptions: vscodelc.ServerOptions = {
+      command : serverPath,
+      args : additionalServerArgs
+    };
+
+    // Configure file patterns relative to the workspace folder.
+    let filePattern: vscode.GlobPattern = '**/*.' + languageName;
+    let selectorPattern: string = null;
+    if (workspaceFolder) {
+      filePattern = new vscode.RelativePattern(workspaceFolder, filePattern);
+      selectorPattern = `${vscode.Uri.parse(workspaceFolder.uri).fsPath}/**/*`;
+    }
+
+    // Configure the middleware of the client. This is sort of abused to allow
+    // for defining a "fallback" language server that operates on non-workspace
+    // folders. Workspace folder language servers can properly filter out
+    // documents not within the folder, but we can't effectively filter for
+    // documents outside of the workspace. To support this, and avoid having two
+    // servers targeting the same set of files, we use middleware to inject the
+    // dynamic logic for checking if a document is in the workspace.
+    let middleware = {};
+    if (!workspaceFolder) {
+      middleware = {
+        didOpen : (document, next) : Promise<void> => {
+          if (!vscode.workspace.getWorkspaceFolder(document.uri)) {
+            return next(document);
+          }
+          return Promise.resolve();
+        }
+      };
+    }
+
+    // Configure the client options.
+    const clientOptions: vscodelc.LanguageClientOptions = {
+      documentSelector : [
+        {language : languageName, pattern : selectorPattern},
+      ],
+      synchronize : {
+        // Notify the server about file changes to language files contained in
+        // the workspace.
+        fileEvents : vscode.workspace.createFileSystemWatcher(filePattern)
+      },
+      outputChannel : outputChannel,
+      workspaceFolder : workspaceFolder,
+      middleware : middleware,
+
+      // Don't switch to output window when the server returns output.
+      revealOutputChannelOn : vscodelc.RevealOutputChannelOn.Never,
+    };
+
+    // Create the language client and start the client.
+    let languageClient = new vscodelc.LanguageClient(
+        languageName + '-lsp', clientTitle, serverOptions, clientOptions);
+    languageClient.start();
+    return [ languageClient, serverPath ];
+  }
+
+  /**
+   * Given a server setting, return the default server path.
+   */
+  static getDefaultServerFilename(serverSettingName: string): string {
+    if (serverSettingName === 'pdll_server_path') {
+      return 'mlir-pdll-lsp-server';
+    }
+    if (serverSettingName === 'server_path') {
+      return 'mlir-lsp-server';
+    }
+    if (serverSettingName === 'tablegen_server_path') {
+      return 'tblgen-lsp-server';
+    }
+    return '';
+  }
+
+  /**
+   * Try to resolve the given path, or the default path, with an optional
+   * workspace folder. If a path could not be resolved, just returns the
+   * input filePath.
+   */
+  async resolvePath(filePath: string, defaultPath: string,
+                    workspaceFolder: vscode.WorkspaceFolder): Promise<string> {
+    const configPath = filePath;
+
+    // If the path is already fully resolved, there is nothing to do.
+    if (path.isAbsolute(filePath)) {
+      return filePath;
+    }
+
+    // If a path hasn't been set, try to use the default path.
+    if (filePath === '') {
+      if (defaultPath === '') {
+        return filePath;
+      }
+      return await which(defaultPath);
+
+      // Fallthrough to try resolving the default path.
+    }
+
+    // Try to resolve the path relative to the workspace.
+    let filePattern: vscode.GlobPattern = '**/' + filePath;
+    if (workspaceFolder) {
+      filePattern = new vscode.RelativePattern(workspaceFolder, filePattern);
+    }
+    let foundUris = await vscode.workspace.findFiles(filePattern, null, 1);
+    if (foundUris.length === 0) {
+      // If we couldn't resolve it, just return the original path anyways. The
+      // file might not exist yet.
+      return configPath;
+    }
+    // Otherwise, return the resolved path.
+    return foundUris[0].fsPath;
+  }
+
+  /**
+   * Try to resolve the path for the given server setting, with an optional
+   * workspace folder.
+   */
+  async resolveServerPath(serverSettingName: string,
+                          workspaceFolder: vscode.WorkspaceFolder):
+      Promise<string> {
+    const serverPath = config.get<string>(serverSettingName, workspaceFolder);
+    const defaultPath = MLIRContext.getDefaultServerFilename(serverSettingName);
+    return this.resolvePath(serverPath, defaultPath, workspaceFolder);
+  }
+
+  /**
+   * Return the language client for the given language and uri, or null if no
+   * client is active.
+   */
+  getLanguageClient(uri: vscode.Uri,
+                    languageName: string): vscodelc.LanguageClient {
+    let workspaceFolder = vscode.workspace.getWorkspaceFolder(uri);
+    let workspaceFolderStr =
+        workspaceFolder ? workspaceFolder.uri.toString() : "";
+    let folderContext = this.workspaceFolders.get(workspaceFolderStr);
+    if (!folderContext) {
+      return null;
+    }
+    return folderContext.clients.get(languageName);
+  }
+
+  dispose() {
+    this.subscriptions.forEach((d) => { d.dispose(); });
+    this.subscriptions = [];
+    this.workspaceFolders.forEach((d) => { d.dispose(); });
+    this.workspaceFolders.clear();
+  }
+}
diff --git a/mlir/utils/coc.nvim/tablegen-grammar.json b/mlir/utils/coc.nvim/tablegen-grammar.json
new file mode 100644
index 00000000000000..8da8aaed193365
--- /dev/null
+++ b/mlir/utils/coc.nvim/tablegen-grammar.json
@@ -0,0 +1,452 @@
+{
+  "name": "TableGen",
+  "fileTypes": [
+    "td"
+  ],
+  "patterns": [
+    {
+      "include": "#comments"
+    },
+    {
+      "include": "#preprocessor"
+    },
+    {
+      "include": "#strings"
+    },
+    {
+      "include": "#integer"
+    },
+    {
+      "include": "#builtin_types"
+    },
+    {
+      "include": "#keywords"
+    },
+    {
+      "include": "#classes"
+    },
+    {
+      "include": "#defs"
+    },
+    {
+      "include": "#values"
+    }
+  ],
+  "repository": {
+    "comments": {
+      "patterns": [
+        {
+          "match": "\/\/.*$",
+          "name": "comment.line.double-slash.tablegen"
+        },
+        {
+          "begin": "/\\*",
+          "end": "\\*/",
+          "captures": {
+            "0": {
+              "name": "comment.block.tablegen"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#comments"
+            }
+          ],
+          "name": "comment.block.tablegen"
+        }
+      ]
+    },
+    "preprocessor": {
+      "patterns": [
+        {
+          "match": "^#ifdef\\s+(\\w+)",
+          "name": "keyword.control.ifdef.tablegen",
+          "captures": {
+            "1": {
+              "name": "entity.name.function.preprocessor.tablegen"
+            }
+          }
+        },
+        {
+          "match": "^#ifndef\\s+(\\w+)",
+          "name": "keyword.control.ifndef.tablegen",
+          "captures": {
+            "1": {
+              "name": "entity.name.function.preprocessor.tablegen"
+            }
+          }
+        },
+        {
+          "match": "^#else",
+          "name": "keyword.control.else.tablegen"
+        },
+        {
+          "match": "#endif",
+          "name": "keyword.control.endif.tablegen"
+        },
+        {
+          "match": "#define\\s+(\\w+)",
+          "name": "keyword.control.ifndef.tablegen",
+          "captures": {
+            "1": {
+              "name": "entity.name.function.preprocessor.tablegen"
+            }
+          }
+        },
+        {
+          "match": "^include\\s+",
+          "name": "keyword.control.include.tablegen"
+        }
+      ]
+    },
+    "strings": {
+      "patterns": [
+        {
+          "name": "string.quoted.double.tablegen",
+          "begin": "\"",
+          "end": "\"",
+          "beginCaptures": {
+            "0": {
+              "name": "punctuation.definition.string.begin.tablegen"
+            }
+          },
+          "patterns": [
+            {
+              "match": "\\\\['nt\"]",
+              "name": "constant.character.escape.tablegen"
+            }
+          ],
+          "endCaptures": {
+            "0": {
+              "name": "punctuation.definition.string.end.tablegen"
+            }
+          }
+        },
+        {
+          "name": "string.quoted.triple.tablegen",
+          "begin": "\\[{",
+          "end": "}]",
+          "beginCaptures": {
+            "0": {
+              "name": "punctuation.definition.string.begin.tablegen"
+            }
+          },
+          "patterns": [
+            {
+              "match": "\\\\[nt\"]",
+              "name": "constant.character.escape.tablegen"
+            }
+          ],
+          "endCaptures": {
+            "0": {
+              "name": "punctuation.definition.string.end.tablegen"
+            }
+          }
+        }
+      ]
+    },
+    "integer": {
+      "patterns": [
+        {
+          "match": "\\b\\d+\\b",
+          "name": "constant.numeric.tablegen"
+        },
+        {
+          "match": "\\b0[xX][a-fA-F0-9]+\\b",
+          "name": "constant.numeric.hex.tablegen"
+        },
+        {
+          "match": "\\b0b[01]+\\b",
+          "name": "constant.numeric.binary.tablegen"
+        }
+      ]
+    },
+    "builtin_types": {
+      "patterns": [
+        {
+          "match": "\\b(?:bit|code|dag|int|string)\\b",
+          "name": "entity.name.type.tablegen"
+        },
+        {
+          "begin": "\\b(bits)\\<",
+          "beginCaptures": {
+            "1": {
+              "name": "entity.name.type.tablegen"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#integer"
+            }
+          ],
+          "end": "\\>"
+        },
+        {
+          "begin": "\\b(list)\\<",
+          "beginCaptures": {
+            "1": {
+              "name": "entity.name.type.tablegen"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#types"
+            }
+          ],
+          "end": "\\>"
+        }
+      ]
+    },
+    "types": {
+      "patterns": [
+        {
+          "include": "#builtin_types"
+        },
+        {
+          "match": "\\b(\\w+)\\b",
+          "name": "entity.name.type.tablegen"
+        }
+      ]
+    },
+    "bang_operators": {
+      "patterns": [
+        {
+          "begin": "(\\!cast|\\!getdagop|\\!isa)\\<",
+          "beginCaptures": {
+            "1": {
+              "name": "entity.name.function"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#types"
+            }
+          ],
+          "end": "\\>"
+        },
+        {
+          "match": "(\\!\\w+)\\b",
+          "name": "entity.name.function"
+        }
+      ]
+    },
+    "keywords": {
+      "patterns": [
+        {
+          "match": "\\b(assert|else|foreach|defset|defvar|field|if|in|let|then)\\b",
+          "name": "keyword.other.tablegen"
+        }
+      ]
+    },
+    "record_body": {
+      "patterns": [
+        {
+          "begin": "\\:",
+          "patterns": [
+            {
+              "match": "\\b(\\w+)\\b",
+              "name": "entity.name.type.tablegen"
+            },
+            {
+              "begin": "\\<",
+              "patterns": [
+                {
+                  "include": "#values"
+                }
+              ],
+              "end": "\\>"
+            }
+          ],
+          "end": "(?=\\;|\\{)"
+        },
+        {
+          "begin": "\\{",
+          "patterns": [
+            {
+              "include": "#keywords"
+            },
+            {
+              "include": "#builtin_types"
+            },
+            {
+              "match": "\\b(\\w+\\s+)?\\b(\\w+)\\b\\s+\\=",
+              "captures": {
+                "1": {
+                  "name": "entity.name.type.tablegen"
+                },
+                "2": {
+                  "name": "variable.other.tablegen"
+                }
+              }
+            },
+            {
+              "include": "#values"
+            }
+          ],
+          "end": "(?=\\})"
+        }
+      ]
+    },
+    "classes": {
+      "begin": "\\b(multiclass|class)\\b\\s+(\\w+)\\b",
+      "beginCaptures": {
+        "1": {
+          "name": "keyword.other.class.tablegen"
+        },
+        "2": {
+          "name": "entity.name.type.tablegen"
+        }
+      },
+      "patterns": [
+        {
+          "begin": "\\<",
+          "patterns": [
+            {
+              "include": "#builtin_types"
+            },
+            {
+              "match": "\\b(\\w+\\s+)?\\b(\\w+)\\b",
+              "captures": {
+                "1": {
+                  "name": "entity.name.type.tablegen"
+                },
+                "2": {
+                  "name": "variable.other.tablegen"
+                }
+              }
+            },
+            {
+              "begin": "=",
+              "patterns": [
+                {
+                  "include": "#values"
+                }
+              ],
+              "end": "(?=\\>|\\,)"
+            }
+          ],
+          "end": "\\>"
+        },
+        {
+          "include": "#record_body"
+        }
+      ],
+      "end": "(\\;|\\})"
+    },
+    "defs": {
+      "begin": "\\b(defm|def)\\b",
+      "beginCaptures": {
+        "1": {
+          "name": "keyword.other.def.tablegen"
+        }
+      },
+      "patterns": [
+        {
+          "include": "#record_body"
+        },
+        {
+          "include": "#values"
+        }
+      ],
+      "end": "(\\;|\\})"
+    },
+    "values": {
+      "patterns": [
+        {
+          "include": "#builtin_types"
+        },
+        {
+          "include": "#bang_operators"
+        },
+        {
+          "include": "#classes"
+        },
+        {
+          "include": "#defs"
+        },
+        {
+          "include": "#comments"
+        },
+        {
+          "include": "#integer"
+        },
+        {
+          "include": "#strings"
+        },
+        {
+          "match": "\\b(?:false|true)\\b",
+          "name": "keyword.other.tablegen"
+        },
+        {
+          "match": "(\\?)",
+          "name": "keyword.other.tablegen"
+        },
+        {
+          "begin": "\\{",
+          "patterns": [
+            {
+              "include": "#values"
+            }
+          ],
+          "end": "\\}"
+        },
+        {
+          "begin": "\\[",
+          "patterns": [
+            {
+              "include": "#values"
+            }
+          ],
+          "end": "(?=\\])"
+        },
+        {
+          "begin": "\\]\\s*\\<",
+          "patterns": [
+            {
+              "include": "#types"
+            }
+          ],
+          "end": "\\>"
+        },
+        {
+          "begin": "\\(",
+          "patterns": [
+            {
+              "include": "#values"
+            }
+          ],
+          "end": "\\)"
+        },
+        {
+          "include": "#keywords"
+        },
+        {
+          "begin": "\\b(\\w+)\\<",
+          "beginCaptures": {
+            "1": {
+              "name": "entity.name.type.tablegen"
+            }
+          },
+          "patterns": [
+            {
+              "include": "#values"
+            }
+          ],
+          "end": "\\>"
+        },
+        {
+          "match": "(\\$\\w+)\\b",
+          "name": "variable.other.enummember.tablegen"
+        },
+        {
+          "match": "\\b(\\w+)\\b",
+          "name": "variable.other.tablegen"
+        },
+        {
+          "include": "#preprocessor"
+        }
+      ]
+    }
+  },
+  "scopeName": "source.tablegen"
+}
\ No newline at end of file
diff --git a/mlir/utils/coc.nvim/tablegen-language-configuration.json b/mlir/utils/coc.nvim/tablegen-language-configuration.json
new file mode 100644
index 00000000000000..6a1455bf8ca7fd
--- /dev/null
+++ b/mlir/utils/coc.nvim/tablegen-language-configuration.json
@@ -0,0 +1,89 @@
+{
+  "comments": {
+    "lineComment": "//",
+    "blockComment": [
+      "/*",
+      "*/"
+    ]
+  },
+  "colorizedBracketPairs": [
+    [
+      "{",
+      "}"
+    ],
+    [
+      "[",
+      "]"
+    ],
+    [
+      "(",
+      ")"
+    ],
+    [
+      "<",
+      ">"
+    ]
+  ],
+  "brackets": [
+    [
+      "{",
+      "}"
+    ],
+    [
+      "[",
+      "]"
+    ],
+    [
+      "(",
+      ")"
+    ],
+    [
+      "<",
+      ">"
+    ]
+  ],
+  "autoClosingPairs": [
+    [
+      "{",
+      "}"
+    ],
+    [
+      "[",
+      "]"
+    ],
+    [
+      "(",
+      ")"
+    ],
+    [
+      "<",
+      ">"
+    ],
+    [
+      "\"",
+      "\""
+    ]
+  ],
+  "surroundingPairs": [
+    [
+      "{",
+      "}"
+    ],
+    [
+      "[",
+      "]"
+    ],
+    [
+      "(",
+      ")"
+    ],
+    [
+      "<",
+      ">"
+    ],
+    [
+      "\"",
+      "\""
+    ]
+  ]
+}
\ No newline at end of file
diff --git a/mlir/utils/coc.nvim/tsconfig.json b/mlir/utils/coc.nvim/tsconfig.json
new file mode 100644
index 00000000000000..6e4d493ddfe023
--- /dev/null
+++ b/mlir/utils/coc.nvim/tsconfig.json
@@ -0,0 +1,17 @@
+{
+	"compilerOptions": {
+		"module": "commonjs",
+		"target": "es6",
+		"outDir": "out",
+		"rootDir": "src",
+		"allowSyntheticDefaultImports": true,
+		"sourceMap": true
+	},
+	"include": [
+		"src"
+	],
+	"exclude": [
+		"node_modules",
+		".vscode-test"
+	]
+}



More information about the Mlir-commits mailing list