pax_global_header00006660000000000000000000000064144031323440014510gustar00rootroot0000000000000052 comment=7680ac6dbd5b2845d78cb5f216dfa262ea9cee0d datatype99-1.6.4/000077500000000000000000000000001440313234400135155ustar00rootroot00000000000000datatype99-1.6.4/.clang-format000066400000000000000000000005521440313234400160720ustar00rootroot00000000000000Language: Cpp BasedOnStyle: LLVM IndentWidth: 4 ContinuationIndentWidth: 4 ColumnLimit: 100 AllowShortFunctionsOnASingleLine: Empty AllowAllArgumentsOnNextLine: false BinPackArguments: false AllowAllParametersOfDeclarationOnNextLine: true BinPackParameters: true AlignConsecutiveMacros: true AlignAfterOpenBracket: AlwaysBreak StatementMacros: ["ML99_EVAL"] datatype99-1.6.4/.github/000077500000000000000000000000001440313234400150555ustar00rootroot00000000000000datatype99-1.6.4/.github/workflows/000077500000000000000000000000001440313234400171125ustar00rootroot00000000000000datatype99-1.6.4/.github/workflows/c-cpp.yml000066400000000000000000000017431440313234400206440ustar00rootroot00000000000000name: C/C++ CI on: push: branches: [master] pull_request: branches: [master] jobs: test: strategy: matrix: os: [ubuntu-latest, macos-latest, windows-latest] include: - os: ubuntu-latest compiler: gcc - os: macos-latest compiler: clang - os: windows-latest compiler: msvc runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v2 - name: Test run: ./scripts/test-all.sh test-tcc: runs-on: ubuntu-latest env: CC: tcc steps: - uses: actions/checkout@v2 - name: Install TCC run: sudo apt install tcc - name: Test run: ./scripts/test-all.sh check-fmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: Download run-clang-format run: git submodule update --init run-clang-format - name: Check code formatting run: ./scripts/check-fmt.sh datatype99-1.6.4/.gitignore000066400000000000000000000007121440313234400155050ustar00rootroot00000000000000# Prerequisites *.d # Object files *.o *.ko *.obj *.elf # Linker output *.ilk *.map *.exp # Precompiled Headers *.gch *.pch # Libraries *.lib *.a *.la *.lo # Shared objects (inc. Windows DLLs) *.dll *.so *.so.* *.dylib # Executables *.exe *.out *.app *.i*86 *.x86_64 *.hex # Debug files *.dSYM/ *.su *.idb *.pdb # Kernel Module Compile Results *.mod* *.cmd .tmp_versions/ modules.order Module.symvers Mkfile.old dkms.conf # CMake build files build/ datatype99-1.6.4/.gitmodules000066400000000000000000000001531440313234400156710ustar00rootroot00000000000000[submodule "run-clang-format"] path = run-clang-format url = https://github.com/Sarcasm/run-clang-format datatype99-1.6.4/CHANGELOG.md000066400000000000000000000117261440313234400153350ustar00rootroot00000000000000# Changelog All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## unreleased ## 1.6.4 - 2023-03-11 ### Fixed - Fix the `DOWNLOAD_EXTRACT_TIMESTAMP` CMake warning ([issue #15](https://github.com/Hirrolot/datatype99/issues/15)). ## 1.6.3 - 2022-05-15 ### Fixed - Generation of binding variables when compiling on C++ ([issue #14](https://github.com/Hirrolot/datatype99/issues/14)). ## 1.6.2 - 2022-01-02 ### Fixed - Initialise `.data.dummy` to `'\0'` for empty variants. Previously, it was uninitialised. ## 1.6.1 - 2021-12-09 ### Fixed - Specify `C` as the project language in `CMakeLists.txt`. Previously, CMake detected C++ and required a C++ compiler to compile the project. - Require CMake v3.11.4. ## 1.6.0 - 2021-12-01 ### Added - Add the root `CMakeLists.txt` to be able to use CMake with [`FetchContent`] or [`add_subdirectory`]. [`FetchContent`]: https://cmake.org/cmake/help/latest/module/FetchContent.html [`add_subdirectory`]: https://cmake.org/cmake/help/latest/command/add_subdirectory.html ## 1.5.2 - 2021-11-09 ### Fixed - The `derive` attribute was made into a macro (see [issue #12](https://github.com/Hirrolot/datatype99/issues/12)). ## 1.5.1 - 2021-10-06 ### Fixed - Previously, shortcuts referring to functional macros were object-like. To avoid nasty compilation errors, now they are function-like too: - `datatype(...)` - `record(...)` - `match(val)` - `MATCHES(val, tag)` - `matches(val, tag)` - `ifLet(val, tag, ...)` - `of(...)` ## 1.5.0 - 2021-08-27 ### Added - `DATATYPE99_VERSION_COMPATIBLE` to check for a SemVer-compatible version. - `DATATYPE99_VERSION_EQ` to check for an exact version. ## 1.4.0 - 2021-08-13 ### Added - `MATCHES`/`MATCHES99` to know where is a macro and where is a function. ### Deprecated - `matches`/`matches99`; use `MATCHES`/`MATCHES99` instead. ## 1.3.0 - 2021-07-27 ### Added - An empty record -- `record(Foo)`. ## 1.2.0 - 2021-06-06 ### Added - `record`, `DATATYPE99_record`, `DATATYPE99_RECORD_DERIVE_` to generate a record type. - The `dummy` deriver for record types. ### Fixed - Add the missing arity specifier for `DATATYPE99_datatype`. - Make Datatype99 work on TCC (see [issue #10](https://github.com/Hirrolot/datatype99/issues/10)). ## 1.1.0 - 2021-04-24 ### Added - A mechanism for deriving: `datatype` now can be specified with `derive(...)`. - Manipulation of attributes: - `DATATYPE99_attrIsPresent`/`DATATYPE99_ATTR_IS_PRESENT` to check the presence of an attribute. - `DATATYPE99_attrValue`/`DATATYPE99_ATTR_VALUE` to extract an attribute's value. - `DATATYPE99_assertAttrIsPresent` to assert a mandatory attribute. - A deriver `dummy` which generates nothing. - Metalang99-compliant counterparts: `DATATYPE99_of`, `DATATYPE99_ifLet`. ### Changed - Do **not** suppress `-Wmisleading-indentation` (GCC) automatically in `match`. ### Fixed - `#pragma GCC diagnostic` inside functions error on GCC older than 4.6 ([issue #8](https://github.com/Hirrolot/datatype99/issues/8)). - Inconsistent suppression of `-Wreturn-type` ([issue #9](https://github.com/Hirrolot/datatype99/issues/9)). - Suppress Clang's `-Wcast-qual` in `ifLet`. ## 1.0.0 - 2021-03-28 ### Added - `DATATYPE99_MAJOR`, `DATATYPE99_MINOR`, `DATATYPE99_PATCH`. ### Changed - `Unit` => `UnitT`, `unit` => `unit_v` (less likely to conflict with user-defined identifiers). ### Fixed - Suppress Clang's `-Wcast-qual` in `match`. ## 0.4.0 - 2021-03-27 ### Added - `ifLet` to match only a single variant. ### Changed - `Data` => `Variants` (less likely to conflict with user-defined types). ### Fixed - Avoid using `METALANG99_semicolon` because it turned out to be [dangerous](https://github.com/Hirrolot/metalang99/commit/f17f06adf1a747a8897bbc90c598b2be21c945c8). - Clang's `-Wused-but-marked-unused` in `of`. - The specification now requires an lvalue for `match`. ## 0.3.1 - 2021-02-28 ### Added - Generate `Tag` and `Data`. ### Fixed - Suppress `-Wmisleading-indentation` only when `__GNUC__ >= 6`. - Suppress `-Wreturn-type` for Clang too. - Make it work on C++11. ## 0.3.0 - 2021-02-26 ### Changed - Force users to download Metalang99 as well, i.e. don't use it as a Git submodule. - Annotate value constructors with `__attribute__((warn_unused_result))` and `__attribute__((const))` if supported. ### Added - Generate `typedef struct ;` beforehand so ` *` can be used instead of `struct *` inside variants. - The reserved `_` identifier for `of`. - Error reporting about an unparenthesised variant like `Bar(int)`. - `Unit` and `unit`. ## 0.2.0 - 2021-02-05 ### Changed - Replace `Epilepsy` with `Metalang99` (more neutral). ## 0.1.0 - 2021-02-04 ### Added - This excellent project. datatype99-1.6.4/CMakeLists.txt000066400000000000000000000011401440313234400162510ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.11.4) project(datatype99 LANGUAGES C) # Fix the warnings about `DOWNLOAD_EXTRACT_TIMESTAMP` in newer CMake versions. if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") cmake_policy(SET CMP0135 NEW) endif() include(FetchContent) FetchContent_Declare( metalang99 URL https://github.com/Hirrolot/metalang99/archive/refs/tags/v1.13.2.tar.gz ) FetchContent_MakeAvailable(metalang99) add_library(${PROJECT_NAME} INTERFACE) target_include_directories(${PROJECT_NAME} INTERFACE ${CMAKE_CURRENT_SOURCE_DIR}) target_link_libraries(${PROJECT_NAME} INTERFACE metalang99) datatype99-1.6.4/LICENSE000066400000000000000000000020561440313234400145250ustar00rootroot00000000000000MIT License Copyright (c) 2020-2023 Hirrolot Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. datatype99-1.6.4/README.md000066400000000000000000000714641440313234400150100ustar00rootroot00000000000000

Datatype99

Safe, intuitive [algebraic data types] with exhaustive pattern matching & compile-time introspection facilities. No external tools required, pure C99.
[algebraic data types]: https://en.wikipedia.org/wiki/Algebraic_data_type ## Highlights - **Type-safe.** Such things as improperly typed variants, non-exhaustive pattern matching, and invalid field access are caught at compile-time. - **Portable.** Everything you need is a standard-conforming C99 compiler; neither the standard library, nor compiler/platform-specific functionality or VLA are required. - **Predictable.** Datatype99 comes with formal [code generation semantics], meaning that the generated data layout is guaranteed to always be the same. - **Comprehensible errors.** Datatype99 is [resilient to bad code]. - **Battle-tested.** Datatype99 is used at [OpenIPC] to develop real-time streaming software for IP cameras; this includes an [RTSP 1.0 implementation] along with ~50k lines of private code. [resilient to bad code]: #q-what-about-compile-time-errors [OpenIPC]: https://openipc.org/ [RTSP 1.0 implementation]: https://github.com/OpenIPC/smolrtsp/ ## Installation Datatype99 consists of one header file `datatype99.h` and one dependency [Metalang99]. To use it in your project, you need to: [Metalang99]: https://github.com/Hirrolot/metalang99 1. Add `datatype99` and `metalang99/include` to your include directories. 2. Specify [`-ftrack-macro-expansion=0`] (GCC) or [`-fmacro-backtrace-limit=1`] (Clang) to avoid useless macro expansion errors. [`-ftrack-macro-expansion=0`]: https://gcc.gnu.org/onlinedocs/gcc/Preprocessor-Options.html [`-fmacro-backtrace-limit=1`]: https://clang.llvm.org/docs/ClangCommandLineReference.html#cmdoption-clang-fmacro-backtrace-limit If you use CMake, the recommended way is [`FetchContent`]: [`FetchContent`]: https://cmake.org/cmake/help/latest/module/FetchContent.html ```cmake include(FetchContent) FetchContent_Declare( datatype99 URL https://github.com/Hirrolot/datatype99/archive/refs/tags/v1.2.3.tar.gz # v1.2.3 ) FetchContent_MakeAvailable(datatype99) target_link_libraries(MyProject datatype99) # Disable full macro expansion backtraces for Metalang99. if(CMAKE_C_COMPILER_ID STREQUAL "Clang") target_compile_options(MyProject PRIVATE -fmacro-backtrace-limit=1) elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU") target_compile_options(MyProject PRIVATE -ftrack-macro-expansion=0) endif() ``` (By default, `datatype99/CMakeLists.txt` downloads Metalang99 [v1.13.2](https://github.com/Hirrolot/metalang99/releases/tag/v1.13.2) from the GitHub releases; if you want to override this behaviour, you can do so by invoking [`FetchContent_Declare`] earlier.) [`FetchContent_Declare`]: https://cmake.org/cmake/help/latest/module/FetchContent.html#command:fetchcontent_declare Optionally, you can [precompile headers] in your project that rely on Datatype99. This will decrease compilation time, because the headers will not be compiled each time they are included. [precompile headers]: https://en.wikipedia.org/wiki/Precompiled_header Happy hacking! ## Usage Put simply, Datatype99 is just a syntax sugar over [tagged unions]; the only difference is that it is more safe and concise. For example, to represent a binary tree, you would normally write something like this: ```c typedef struct { struct BinaryTree *lhs; int x; struct BinaryTree *rhs; } BinaryTreeNode; typedef struct { enum { Leaf, Node } tag; union { int leaf; BinaryTreeNode node; } data; } BinaryTree; ``` To avoid this boilerplate, you can use Datatype99: ```c datatype( BinaryTree, (Leaf, int), (Node, BinaryTree *, int, BinaryTree *) ); ``` Say you want to sum all nodes and leafs in your binary tree. Then you may write something like this: ```c int sum(const BinaryTree *tree) { switch (tree->tag) { case Leaf: return tree->data.leaf; case Node: return sum(tree->data.node.lhs) + tree->data.node.x + sum(tree->data.node.rhs); } // Invalid input (no such variant). return -1; } ``` ... but what if you accidentally access `tree->data.node` after `case Leaf:`? Your compiler would not warn you, thus resulting in a business logic bug. With Datatype99, you can rewrite `sum` as follows, using a technique called _pattern matching_: ```c int sum(const BinaryTree *tree) { match(*tree) { of(Leaf, x) return *x; of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs); } // Invalid input (no such variant). return -1; } ``` `of` gives you variables called _bindings_: `x`, `lhs`, or `rhs`. This design has a few neat aspects: - **Compile-time safety.** The bindings of `Node` are invisible after `of(Leaf, x)` and vice versa, so compilation will fail to proceed if you access them inappropriately. - **Flexibility.** Bindings have pointer types so that you can mutate them, thereby mutating the whole `tree`; in order to obtain a value, you can dereference them, as shown in the example: `return *x;`. The last thing unmentioned is how you construct variants. Internally, Datatype99 generates `inline static` functions called _value constructors_; you can use them as follows: ```c BinaryTree leaf5 = Leaf(5); BinaryTree leaf7 = Leaf(7); BinaryTree node = Node(&leaf5, 123, &leaf7); ``` Finally, just a few brief notes about pattern matching: - To match the default case, write `otherwise { ... }` at the end of `match`. - To ignore a binding, write `_`: `of(Foo, a, b, _, d)`. - **PLEASE**, [do **not** use top-level `break`/`continue`](#top-level-breakcontinue) inside statements provided to `of` and `ifLet`; use `goto` labels instead. Congratulations, this is all you need to know to write most of the stuff! If you feel fancy, you can also introspect your types at compile-time; see [`examples/derive/`](examples/derive/) for the examples. [tagged unions]: https://en.wikipedia.org/wiki/Tagged_union ## Syntax and semantics Having a well-defined semantics of the macros, you can write an FFI which is quite common in C. ### EBNF syntax ```ebnf ::= "datatype(" [ "," ] { "," }+ ")" ; ::= "record(" [ "," ] { "," }* ")" ; ::= ; ::= ; ::= "(" { "," }* ")" ; ::= "(" "," ")" ; ::= ; ::= ; ::= "derive(" { "," }* ")" ; ::= ; ::= "match(" ") {" { }* [ ] "}" ; ::= "MATCHES(" "," ")" ; ::= "ifLet(" "," "," { "," }* ")" ; ::= "of(" { "," }* ")" ; ::= "otherwise" ; ```
Note: shortened vs. postfixed versions Each listed identifier in the above grammar corresponds to a macro name defined by default -- these are called _shortened versions_. On the other hand, there are also _postfixed versions_ (`match99`, `of99`, `derive99`, etc.), which are defined unconditionally. If you want to avoid name clashes caused by shortened versions, define `DATATYPE99_NO_ALIASES` before including `datatype99.h`. Library headers are strongly advised to use the postfixed macros, but without resorting to `DATATYPE99_NO_ALIASES`.
### Semantics (It might be helpful to look at the [generated data layout](https://godbolt.org/z/rebxMxW43) of [`examples/binary_tree.c`](examples/binary_tree.c).) #### `datatype` 1. Before everything, the following type definition is generated: ``` typedef struct ; ``` 2. For each non-empty variant, the following type definition is generated (the metavariable `` ranges over a corresponding variant's types): ``` typedef struct { 0 _0; ... N _N; } ; ``` 3. For each non-empty variant, the following type definitions to types of each field of `` are generated: ``` typedef 0 _0; ... typedef N _N; ``` 4. For each variant, the following type definition to a corresponding sum type is generated: ``` typedef struct SumT; ``` 5. For each sum type, the following tagged union is generated (inside the union, only fields to structures of non-empty variants are generated): ``` typedef enum Tag { 0Tag, ..., NTag } Tag; typedef union Variants { char dummy; 0 0; ... N N; } Variants; struct { Tag tag; Variants data; }; ```
Note on char dummy; `char dummy;` is needed to make the union contain at least one item, according to the standard, even if all variants are empty. Such a `datatype` would enforce strict type checking unlike plain C `enum`s.
6. For each variant, the following function called a _value constructor_ is generated: ``` inline static (/* ... */) { /* ... */ } ``` If the variant has no parameters, this function will take `void` and initialise `.data.dummy` to `'\0'`; otherwise, it will take the corresponding variant parameters and initialise the result value as expected. 7. Now, when a sum type is fully generated, the derivation process takes place. Each deriver taken from `derive(...)` is invoked sequentially, from left to right, as ``` ML99_call(DATATYPE99_DERIVE_##I, v(), variants...) ``` where - `I` corresponds to a [Metalang99-compliant] macro of the form `#define DATATYPE99_DERIVE_##I_IMPL(name, variants) /* ... */`. - `variants...` is a [list] of variants represented as two-place [tuples]: `(, types...)`, where - `types...` is a [list] of types of the corresponding variant. Put simply, a deriver is meant to generate something global for a sum type, like interface implementations or almost any other stuff. In terms of Rust, you can think of it as of the [`derive` attribute]. [list]: https://metalang99.readthedocs.io/en/latest/list.html [tuples]: https://metalang99.readthedocs.io/en/latest/tuple.html [`derive` attribute]: https://doc.rust-lang.org/reference/attributes/derive.html #### `record` `record` represents a _record type_: it is simply a `struct` for which the derivation process is defined. 1. The following structure is generated: ``` typedef struct { // Only if has no fields: char dummy; 0 0; ... N N; } ; ```
Note on char dummy; `char dummy;` is needed to make the structure contain at least one item, according to the standard. Such `record(Foo)` can be used to implement interfaces for it (see [Interface99]).
[Interface99]: https://github.com/Hirrolot/interface99 2. Each deriver taken from `derive(...)` is invoked sequentially, from left to right, as ``` ML99_call(DATATYPE99_RECORD_DERIVE_##I, v(), fields...) ``` where - `I` corresponds to a [Metalang99-compliant] macro of the form `#define DATATYPE99_RECORD_DERIVE_##I_IMPL(name, fields) /* ... */`. - `fields...` is a [list] of fields represented as two-place [tuples]: `(, )`. If a record contains no fields, the list would consist only of `(char, dummy)`. #### `match` `match` has the expected semantics: it sequentially tries to match the given instance of a sum type against the given variants, and, if a match has succeeded, it executes the corresponding statement and moves down to the next instruction (`match(val) { ... } next-instruction;`). If all the matches have failed, it executes the statement after `otherwise` and moves down to the next instruction. A complete `match` construct results in a single C statement. #### `of` `of` accepts a matched variant name as a first argument and the rest of arguments comprise a comma-separated list of bindings. - A binding equal to `_` is ignored. - A binding **not** equal to `_` stands for a pointer to a corresponding data of the variant (e.g., let there be `(Foo, T1, T2)` and `of(Foo, x, y)`, then `x` has the type `T1 *` and `y` is `T2 *`). There can be more than one `_` binding, however, non-`_` bindings must be distinct. To match an empty variant, write `of(Bar)`. #### `MATCHES` `MATCHES` just tests an instance of a sum type for a given variant. If the given instance corresponds to the given variant, it expands to truthfulness, otherwise it expands to falsehood. #### `matches` **DEPRECATED**: use [`MATCHES`](#MATCHES) instead. #### `ifLet` `ifLet` tries to match the given instance of a sum type against the given variant, and, if a match has succeeded, it executes the corresponding statement. Think of `ifLet(, , vars...) { /* ... */ }` as of an abbreviation of ``` match() { of(, vars...) { /* ... */ } otherwise {} } ``` A complete `ifLet` construct results in a single C statement. ## Unit type The unit type `UnitT99` represents the type of a single value, `unit_v99` (it should not be assigned to anything else). These are defined as follows: ```c typedef char UnitT99; static const UnitT99 unit_v99 = '\0'; ``` If `DATATYPE99_NO_ALIASES` remains undefined prior to `#include `, `UnitT99` and `unit_v99` are also accessible through object-like macros `UnitT` & `unit_v`. ## Derive helper attributes You can pass named arguments to a deriver; these are called _derive helper attributes_. They must be specified as object-like macros of the form: ``` #define __ attr(/* attribute value */) ``` where `` is either ``/`` or ``/`` for `datatype`/`record`-specific and variant/field-specific attributes, respectively. To manipulate derive helper attributes, there are a few predefined macros: - `DATATYPE99_attrIsPresent`/`DATATYPE99_ATTR_IS_PRESENT` Accepts an attribute name and checks if it is present or not. It can be used to check the presence of an optional attribute. - `DATATYPE99_attrValue`/`DATATYPE99_ATTR_VALUE` Accepts an attribute name extracts its value. A provided attribute **must** be present. - `DATATYPE99_assertAttrIsPresent` Accepts an attribute name and emits a fatal error if the attribute is not present, otherwise results in emptiness. It can be used for mandatory attributes. (The naming convention here is the same [as of Metalang99](https://metalang99.readthedocs.io/en/latest/#naming-conventions).) ## Miscellaneous - The macros `DATATYPE99_MAJOR`, `DATATYPE99_MINOR`, `DATATYPE99_PATCH`, `DATATYPE99_VERSION_COMPATIBLE(x, y, z)`, and `DATATYPE99_VERSION_EQ(x, y, z)` have the [same semantics as of Metalang99](https://metalang99.readthedocs.io/en/latest/#version-manipulation-macros). - For each macro using `ML99_EVAL`, Datatype99 provides its [Metalang99-compliant] counterpart which can be used inside derivers and other Metalang99-compliant macros: | Macro | Metalang99-compliant counterpart | |----------|----------| | `datatype` | `DATATYPE99_datatype` | | `record` | `DATATYPE99_record` | | `of` | `DATATYPE99_of` | | `ifLet` | `DATATYPE99_ifLet` | (An [arity specifier] and [desugaring macro] are provided for each of the above macros.) - There is a built-in deriver `dummy` which generates nothing. It is defined both for record and sum types. [SemVer]: https://semver.org [Metalang99-compliant]: https://metalang99.readthedocs.io/en/latest/#definitions [arity specifier]: https://hirrolot.gitbook.io/metalang99/partial-application [desugaring macro]: https://metalang99.readthedocs.io/en/latest/#definitions ## Guidelines ### Clang-Format issues If you use [Clang-Format], cancel formatting for a `datatype` definition using `// clang-format off` & `// clang-format on` to make it look prettier, as in the examples. ### `#undef` derive helper attributes Always `#undef` derive helper attributes after a corresponding `datatype` definition not to pollute your namespace. ### Descriptive names If the meaning of variant parameters is not clear from the context, give them descriptive names. This can be achieved in several ways: ```c // 1. Define type aliases to variant parameters. typedef double XCoordinate; typedef double YCoordinate; typedef double Width; typedef double Height; datatype( Shape, (Point, XCoordinate, YCoordinate), (Rectangle, Width, Height) ); // 2. Define separate structures. typedef struct { double x, y; } Point; typedef struct { double width, height; } Rectangle; datatype( Shape, (MkPoint, Point), (MkRectangle, Rectangle) ); ``` Comparison: - The former option has more concise syntax: `MkPoint(x, y)` instead of `MkPoint((Point){x, y})`. - The latter option is more appropriate when the structures are to be used separately from the containing sum type. - The latter option allows for more graduate control over the data layout: you can accompain the structures with compiler-specific attributes, alignment properties like `__attribute__ ((__packed__))`, etc. [Clang-Format]: https://clang.llvm.org/docs/ClangFormatStyleOptions.html ## Pitfalls ### Top-level `break`/`continue` Do **not** use `break`/`continue` inside a statement provided to `of`/`ifLet` but outside of any `for`/`while` loops in that statement. For example, this code is fine: ```c match(x) { of(Foo, a, b, c) { for (int i = 0; i < 10; i++) { continue; } } } ``` But this code is **not** fine: ```c for (int i = 0; i < 10; i++) { match(x) { of(Foo, a, b, c) { if (a == 7) { break; } continue; } } } ``` To make it valid, you can rewrite it as follows: ```c for (int i = 0; i < 10; i++) { match(x) { of(Foo, a, b, c) { if (a == 7) { goto my_break; } goto my_continue; } } // Datatype99 prohibits top-level `break`/`continue`. my_continue:; } my_break:; ``` ### Array as a variant parameter To specify an array as a variant parameter, you must put it into a separate `struct`; see [`examples/array_in_variant.c`](examples/array_in_variant.c). ### Mutable bindings Bindings introduced by `of` are **always** mutable, so make sure you do **not** mutate them if the value passed to `match` is qualified as `const`. ## Credits Thanks to Rust and ML for their implementations of sum types. ## Publications - [_Pretty-Printable Enumerations in Pure C_](https://hirrolot.github.io/posts/pretty-printable-enumerations-in-pure-c.html) by Hirrolot. - [_What’s the Point of the C Preprocessor, Actually?_](https://hirrolot.github.io/posts/whats-the-point-of-the-c-preprocessor-actually.html) by Hirrolot. - [_Macros on Steroids, Or: How Can Pure C Benefit From Metaprogramming_](https://hirrolot.github.io/posts/macros-on-steroids-or-how-can-pure-c-benefit-from-metaprogramming.html) by Hirrolot. - [_Extend Your Language, Don’t Alter It_](https://hirrolot.github.io/posts/extend-your-language-dont-alter-it.html) by Hirrolot. - [_Compiling Algebraic Data Types in Pure C99_] by Hirrolot. - [_Comparing Rust and Datatype99_](https://www.reddit.com/r/ProgrammingLanguages/comments/nc1o18/comparing_algebraic_data_types_rust_and_datatype99/) by Hirrolot. - [_Compile-Time Introspection of Sum Types in Pure C99_](https://hirrolot.github.io/posts/compile-time-introspection-of-sum-types-in-pure-c99.html) by Hirrolot. - [_Unleashing Sum Types in Pure C99_](https://hirrolot.github.io/posts/unleashing-sum-types-in-pure-c99.html) by Hirrolot. [_Compiling Algebraic Data Types in Pure C99_]: https://hirrolot.github.io/posts/compiling-algebraic-data-types-in-pure-c99.html ## Release procedure 1. Update `DATATYPE99_MAJOR`, `DATATYPE99_MINOR`, and `DATATYPE99_PATCH` in `datatype99.h`. 2. Update `CHANGELOG.md`. 3. Release the project in [GitHub Releases]. [GitHub Releases]: https://github.com/Hirrolot/datatype99/releases ## FAQ ### Q: Why use C instead of Rust/Zig/whatever else? A: There is a lot of software written in plain C that can benefit from Datatype99; C is #1 programming language as of 2020, [according to TIOBE](https://jaxenter.com/c-programming-may-2020-171598.html). People use C due to technical and social reasons: - Datatype99 can be seamlessly integrated into existing codebases written in pure C -- just `#include ` and you are ready to go. On the other hand, other languages force you to separate native C files from their sources, which is clearly less convenient. - In some environments, developers strick to pure C for historical reasons (e.g., embedded devices, Linux and other operating systems). - C has a stable ABI which is vital for some projects (e.g., plugin systems such as [MetaCall]). - C is a mature language with a complete specification and a plenitude of libraries. Rust has no complete specification, and [Zig] is not yet production-ready. I know a few stories when these two languages were rejected for new projects, and I can understand this decision. - Historically, C has been targeting nearly all platforms. This is not the case with Rust, which depends on LLVM as for now. - Your company obligates you to use C. - Etc. [MetaCall]: https://github.com/metacall/core [Zig]: https://ziglang.org/ See also: - [_Rust is not a good C replacement_](https://drewdevault.com/2019/03/25/Rust-is-not-a-good-C-replacement.html) by Drew DeVault. Overall, if you can afford a more modern/high-level language, I encourage you to do so instead of using old C. However, many people do not have this possibility (or it would be too costly). ### Q: Why not third-party code generators? A: See [Metalang99's README >>](https://github.com/Hirrolot/metalang99#q-why-not-third-party-code-generators). ### Q: How does it work? A: In short, `datatype` expands to a tagged union with value constructors; `match` expands to a switch statement. To generate all this stuff, [Metalang99] is used, a preprocessor metaprogramming library. More on it in [_Compiling Algebraic Data Types in Pure C99_]. ### Q: Does it work on C++? A: Yes, C++11 and onwards is supported. ### Q: What is the difference between Datatype99 and Metalang99? A: [Metalang99] is a functional language for metaprogramming, whereas Datatype99 is an implementation of algebraic data types written in this language. ### Q: What about compile-time errors? A: Some kinds of syntactic errors are detected by the library itself: #### Error: `Bar(int)` instead of `(Bar, int)` [`playground.c`] ```c datatype(A, (Foo, int), Bar(int)); ``` [`/bin/sh`] ``` $ gcc playground.c -Imetalang99/include -Idatatype99 -ftrack-macro-expansion=0 playground.c:3:1: error: static assertion failed: "ML99_assertIsTuple: Bar(int) must be (x1, ..., xN)" 3 | datatype(A, (Foo, int), Bar(int)); | ^~~~~~~~ ``` ---------- #### Error: Missing comma [`playground.c`] ```c datatype(A, (Foo, int) (Bar, int)); ``` [`/bin/sh`] ``` $ gcc playground.c -Imetalang99/include -Idatatype99 -ftrack-macro-expansion=0 playground.c:3:1: error: static assertion failed: "ML99_assertIsTuple: (Foo, int) (Bar, int) must be (x1, ..., xN), did you miss a comma?" 3 | datatype(A, (Foo, int) (Bar, int)); | ^~~~~~~~ ``` ---------- #### Error: Trailing comma is prohibited [`playground.c`] ```c datatype(A, (Foo, int), (Bar, int), /* trailing comma is prohibited */); ``` [`/bin/sh`] ``` $ gcc playground.c -Imetalang99/include -Idatatype99 -ftrack-macro-expansion=0 playground.c:3:1: error: static assertion failed: "ML99_assertIsTuple: must be (x1, ..., xN)" 3 | datatype(A, (Foo, int), (Bar, int), /* trailing comma is prohibited */); | ^~~~~~~~ ``` (For better diagnostics, use the latest Metalang99.) The others are understandable as well: #### Error: unknown type name specified in `datatype` [`playground.c`] ```c datatype(Foo, (FooA, NonExistingType)); ``` [`/bin/sh`] ``` playground.c:3:1: error: unknown type name ‘NonExistingType’ 3 | datatype( | ^~~~~~~~ playground.c:3:1: error: unknown type name ‘NonExistingType’ playground.c:3:1: error: unknown type name ‘NonExistingType’ ``` ---------- #### Error: non-exhaustive `match` [`playground.c`] ```c match(*tree) { of(Leaf, x) return *x; // of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs); } ``` [`/bin/sh`] ``` playground.c: In function ‘sum’: playground.c:6:5: warning: enumeration value ‘NodeTag’ not handled in switch [-Wswitch] 6 | match(*tree) { | ^~~~~ ``` ---------- #### Error: excess binders in `of` [`playground.c`] ```c match(*tree) { of(Leaf, x, excess) return *x; of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs); } ``` [`/bin/sh`] ``` playground.c: In function ‘sum’: playground.c:15:9: error: unknown type name ‘Leaf_1’; did you mean ‘Leaf_0’? 15 | of(Leaf, x, excess) return *x; | ^~ | Leaf_0 playground.c:15:9: error: ‘BinaryTreeLeaf’ has no member named ‘_1’; did you mean ‘_0’? 15 | of(Leaf, x, excess) return *x; | ^~ | _0 ``` ---------- #### Error: improperly typed variant arguments [`playground.c`] ```c BinaryTree tree = Leaf("hello world"); ``` [`/bin/sh`] ``` playground.c: In function ‘main’: playground.c:18:28: warning: passing argument 1 of ‘Leaf’ makes integer from pointer without a cast [-Wint-conversion] 18 | BinaryTree tree = Leaf("hello world"); | ^~~~~~~~~~~~~ | | | char * playground.c:6:1: note: expected ‘int’ but argument is of type ‘char *’ 6 | datatype( | ^~~~~~~~ ``` ---------- #### Error: an undereferenced binder [`playground.c`] ```c int sum(const BinaryTree *tree) { match(*tree) { of(Leaf, x) return x; // x is int * of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs); } } ``` [`/bin/sh`] ``` playground.c: In function ‘sum’: playground.c:17:28: warning: returning ‘Leaf_0 *’ {aka ‘int *’} from a function with return type ‘int’ makes integer from pointer without a cast [-Wint-conversion] 17 | of(Leaf, x) return x; // x is int * | ^ ``` ---------- From my experience, nearly 95% of errors make sense. If an error is not comprehensible at all, try to look at generated code (`-E`). Hopefully, the [code generation semantics] is formally defined so normally you will not see something unexpected. [code generation semantics]: #semantics ### Q: What about IDE support? A: VS Code automatically enables suggestions of generated types but, of course, it does not support macro syntax highlighting. ### Q: Which compilers are tested? A: Datatype99 is known to work on these compilers: - GCC - Clang - MSVC - TCC ## Troubleshooting ### `warning: control reaches end of non-void function [-Wreturn-type]` This warning happens when you try to return control from within a `match` statement, and your compiler thinks that not all hypothetical variants are handled. For example: ```c datatype(MyType, (Foo), (Bar)); int handle(MyType val) { match(val) { of(Foo) return 5; of(Bar) return 7; } } ``` The above code may seem perfect at first glance, but in fact, it is not. The reason is this: `match(val)` boils down to `switch(val.tag)` under the hood, with `val.tag` being an ordinary C enumeration consisting of the variants `Foo` and `Bar`. But what if a caller provides us with neither `Foo` nor `Bar`, but with something like `42` (not a valid variant)? Since `enum` is merely another way to give integers names, a compiler would not complain on the _caller_ site. However, on the _callee_ site, we would have the warning: ``` test.c: In function ‘handle’: test.c:10:1: warning: control reaches end of non-void function [-Wreturn-type] 10 | } | ^ ``` The solution is to either panic or return some error-signaling code, like this: ```c int handle(MyType val) { match(val) { of(Foo) return 5; of(Bar) return 7; } // Invalid input (no such variant). return -1; } ``` See [issue #9](https://github.com/Hirrolot/datatype99/issues/9). datatype99-1.6.4/datatype99.h000066400000000000000000000543751440313234400157010ustar00rootroot00000000000000/* MIT License Copyright (c) 2020-2023 Hirrolot Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ // The official repository: . #ifndef DATATYPE99_H #define DATATYPE99_H #include #if !ML99_VERSION_COMPATIBLE(1, 13, 2) #error Please, update Metalang99 to v1.13.2 or later. #endif #ifndef DATATYPE99_NO_ALIASES #define datatype(...) datatype99(__VA_ARGS__) #define derive(...) derive99(__VA_ARGS__) #define record(...) record99(__VA_ARGS__) #define match(val) match99(val) #define MATCHES(val, tag) MATCHES99(val, tag) /// @deprecated Use `MATCHES` instead. #define matches(val, tag) \ DATATYPE99_PRIV_PRAGMA_WARN("GCC warning \"`matches` is deprecated, use `MATCHES` instead\"") \ MATCHES(val, tag) #define ifLet(val, tag, ...) ifLet99(val, tag, __VA_ARGS__) #define of(...) of99(__VA_ARGS__) #define otherwise otherwise99 #define UnitT UnitT99 #define unit_v unit_v99 #endif // DATATYPE99_NO_ALIASES // Public stuff { // Metalang99-compliant macros { #define DATATYPE99_datatype(...) ML99_call(DATATYPE99_datatype, __VA_ARGS__) #define DATATYPE99_record(...) ML99_call(DATATYPE99_record, __VA_ARGS__) #define DATATYPE99_of(...) ML99_call(DATATYPE99_of, __VA_ARGS__) #define DATATYPE99_ifLet(val, tag, ...) ML99_call(DATATYPE99_ifLet, val, tag, __VA_ARGS__) #define datatype99(...) ML99_EVAL(DATATYPE99_datatype_IMPL(__VA_ARGS__)) #define record99(...) ML99_EVAL(DATATYPE99_record_IMPL(__VA_ARGS__)) #define of99(...) ML99_EVAL(DATATYPE99_of_IMPL(__VA_ARGS__)) #define ifLet99(val, tag, ...) ML99_EVAL(DATATYPE99_ifLet_IMPL(val, tag, __VA_ARGS__)) // } (Metalang99-compliant macros) // Attributes manipulation { #define DATATYPE99_attrIsPresent(attr) ML99_call(DATATYPE99_attrIsPresent, attr) #define DATATYPE99_attrValue(attr) ML99_call(DATATYPE99_attrValue, attr) #define DATATYPE99_assertAttrIsPresent(attr) ML99_call(DATATYPE99_assertAttrIsPresent, attr) #define DATATYPE99_attrIsPresent_IMPL(attr) v(DATATYPE99_ATTR_IS_PRESENT(attr)) #define DATATYPE99_attrValue_IMPL(attr) v(DATATYPE99_ATTR_VALUE(attr)) #define DATATYPE99_assertAttrIsPresent_IMPL(attr) \ ML99_IF( \ DATATYPE99_ATTR_IS_PRESENT(attr), \ ML99_empty(), \ ML99_fatal(DATATYPE99_assertAttrIsPresent, attr must be defined)) #define DATATYPE99_ATTR_IS_PRESENT(attr) \ ML99_IS_TUPLE(ML99_CAT(DATATYPE99_PRIV_ATTR_IS_PRESENT_, attr)) #define DATATYPE99_PRIV_ATTR_IS_PRESENT_attr(...) () #define DATATYPE99_ATTR_VALUE(attr) ML99_CAT(DATATYPE99_PRIV_ATTR_VALUE_, attr) #define DATATYPE99_PRIV_ATTR_VALUE_attr(...) __VA_ARGS__ // } (Attributes manipulation) #define DATATYPE99_DERIVE_dummy_IMPL(...) ML99_empty() #define DATATYPE99_RECORD_DERIVE_dummy_IMPL(...) ML99_empty() #define derive99(...) \ 0derive(__VA_ARGS__) /* 0 is used as a prefix to cancel macro expansion; see \ . */ #define DATATYPE99_MAJOR 1 #define DATATYPE99_MINOR 6 #define DATATYPE99_PATCH 4 #define DATATYPE99_VERSION_COMPATIBLE(x, y, z) \ (DATATYPE99_MAJOR == (x) && \ ((DATATYPE99_MINOR == (y) && DATATYPE99_PATCH >= (z)) || (DATATYPE99_MINOR > (y)))) #define DATATYPE99_VERSION_EQ(x, y, z) \ (DATATYPE99_MAJOR == (x) && DATATYPE99_MINOR == (y) && DATATYPE99_PATCH == (z)) // } (Public stuff) // Unit type { typedef char UnitT99; static const UnitT99 unit_v99 = '\0'; // } (Unit type) // Sum type generation { #define DATATYPE99_datatype_IMPL(x, ...) \ ML99_TERMS( \ ML99_CAT(DATATYPE99_PRIV_withDerive_, DATATYPE99_PRIV_IS_DERIVE(x))(x, __VA_ARGS__), \ v(ML99_TRAILING_SEMICOLON())) #define DATATYPE99_PRIV_withDerive_0(name, ...) \ DATATYPE99_PRIV_withDerive_1(derive99(dummy), name, __VA_ARGS__) #define DATATYPE99_PRIV_withDerive_1(derivers, name, ...) \ ML99_call( \ DATATYPE99_PRIV_genDatatype, \ v(name), \ DATATYPE99_PRIV_parseVariants(__VA_ARGS__), \ v(ML99_CAT(DATATYPE99_PRIV_ELIM_, derivers))) #define DATATYPE99_PRIV_genDatatype_IMPL(name, variants, ...) \ ML99_TERMS( \ v(typedef struct name name;), \ DATATYPE99_PRIV_genVariantTypedefsForEach(name, variants), \ ML99_typedef( \ v(name##Tag), \ ML99_enum(v(name##Tag), DATATYPE99_PRIV_genTagForEach(variants))), \ ML99_typedef( \ v(name##Variants), \ ML99_union(v(name##Variants), DATATYPE99_PRIV_genUnionFieldForEach(name, variants))), \ v(struct name { \ name##Tag tag; \ name##Variants data; \ };), \ DATATYPE99_PRIV_genCtorForEach(name, variants), \ DATATYPE99_PRIV_invokeDeriverForEach(DATATYPE99_DERIVE_, name, variants, __VA_ARGS__)) // } (Sum type generation) // Record type generation { #define DATATYPE99_record_IMPL(...) \ ML99_TERMS( \ ML99_CAT( \ DATATYPE99_PRIV_recordWithDerive_, \ DATATYPE99_PRIV_IS_DERIVE(ML99_VARIADICS_GET(0)(__VA_ARGS__)))(__VA_ARGS__), \ v(ML99_TRAILING_SEMICOLON())) #define DATATYPE99_PRIV_recordWithDerive_0(...) \ DATATYPE99_PRIV_recordWithDerive_1(derive99(dummy), __VA_ARGS__) #define DATATYPE99_PRIV_recordWithDerive_1(derivers, ...) \ ML99_call( \ DATATYPE99_PRIV_genRecord, \ DATATYPE99_PRIV_recordName(__VA_ARGS__), \ DATATYPE99_PRIV_recordFields(__VA_ARGS__), \ v(ML99_CAT(DATATYPE99_PRIV_ELIM_, derivers))) #define DATATYPE99_PRIV_recordName(...) v(ML99_VARIADICS_GET(0)(__VA_ARGS__)) #define DATATYPE99_PRIV_recordFields(...) \ ML99_CAT(DATATYPE99_PRIV_recordFields_, ML99_VARIADICS_IS_SINGLE(__VA_ARGS__))(__VA_ARGS__) #define DATATYPE99_PRIV_recordFields_1(_name) ML99_list(v((char, dummy))) #define DATATYPE99_PRIV_recordFields_0(_name, ...) DATATYPE99_PRIV_parseFields(__VA_ARGS__) #define DATATYPE99_PRIV_genRecord_IMPL(name, fields, ...) \ ML99_TERMS( \ ML99_typedef( \ v(name), \ ML99_struct(v(name), DATATYPE99_PRIV_genRecordFieldForEach(fields))), \ DATATYPE99_PRIV_invokeDeriverForEach( \ DATATYPE99_RECORD_DERIVE_, \ name, \ fields, \ __VA_ARGS__)) // } (Record type generation) // Parse variants { #define DATATYPE99_PRIV_parseVariants(...) \ ML99_listFromTuples(v(DATATYPE99_PRIV_parseVariant), v(__VA_ARGS__)) #define DATATYPE99_PRIV_parseVariant_IMPL(...) \ ML99_CAT(DATATYPE99_PRIV_parseVariantIsEmpty_, ML99_VARIADICS_IS_SINGLE(__VA_ARGS__)) \ (__VA_ARGS__) #define DATATYPE99_PRIV_parseVariantIsEmpty_1(tag) DATATYPE99_PRIV_variant(v(tag), ML99_nil()) #define DATATYPE99_PRIV_parseVariantIsEmpty_0(tag, ...) \ DATATYPE99_PRIV_variant(v(tag), ML99_list(v(__VA_ARGS__))) // } (Parse variants) // Parse fields { #define DATATYPE99_PRIV_parseFields(...) \ ML99_listFromTuples(v(DATATYPE99_PRIV_parseField), v(__VA_ARGS__)) #define DATATYPE99_PRIV_parseField_IMPL(ty, ident) v((ty, ident)) // } (Parse fields) // Variant { #define DATATYPE99_PRIV_variant(tag, sig) ML99_tuple(tag, sig) #define DATATYPE99_PRIV_forEachVariant(f, variants) \ ML99_listMapInPlace(ML99_compose(f, v(ML99_untuple)), variants) // } (Variant) // Derivation { #define DATATYPE99_PRIV_IS_DERIVE(x) ML99_IS_TUPLE(ML99_CAT(DATATYPE99_PRIV_IS_DERIVE_, x)) #define DATATYPE99_PRIV_IS_DERIVE_0derive(...) () #define DATATYPE99_PRIV_ELIM_0derive(...) __VA_ARGS__ #define DATATYPE99_PRIV_invokeDeriverForEach(prefix, name, repr, ...) \ ML99_variadicsForEach( \ ML99_appl(v(DATATYPE99_PRIV_invokeDeriver), v(prefix, name, repr)), \ v(__VA_ARGS__)) #define DATATYPE99_PRIV_invokeDeriver_IMPL(prefix, name, repr, deriver) \ ML99_callUneval(prefix##deriver, name, repr) // } (Derivation) // Pattern matching { // clang-format off #define match99(val) \ ML99_CLANG_PRAGMA("clang diagnostic push") \ ML99_CLANG_PRAGMA("clang diagnostic ignored \"-Wcast-qual\"") \ ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(void, datatype99_priv_matched_val, (void *)&(val)) \ ML99_CLANG_PRAGMA("clang diagnostic pop") \ switch ((val).tag) #define DATATYPE99_of_IMPL(...) \ ML99_TERMS( \ v(break; case ML99_CAT(ML99_VARIADICS_GET(0)(__VA_ARGS__), Tag):), \ ML99_IF( \ ML99_VARIADICS_IS_SINGLE(__VA_ARGS__), \ ML99_empty(), \ DATATYPE99_PRIV_genBindingForEach(v(__VA_ARGS__)))) // clang-format on #define otherwise99 \ break; \ default: // clang-format off #define DATATYPE99_ifLet_IMPL(val, tag_, ...) \ ML99_TERMS( \ v(if (tag_##Tag == (val).tag) \ ML99_CLANG_PRAGMA("clang diagnostic push") \ ML99_CLANG_PRAGMA("clang diagnostic ignored \"-Wcast-qual\"") \ ML99_INTRODUCE_NON_NULL_PTR_TO_STMT(void, datatype99_priv_matched_val, (void *)&(val)) \ ML99_CLANG_PRAGMA("clang diagnostic pop")), \ DATATYPE99_PRIV_genBindingForEach(v(tag_, __VA_ARGS__))) // clang-format on #define DATATYPE99_PRIV_genBindingForEach(...) \ ML99_call(DATATYPE99_PRIV_genBindingForEach, __VA_ARGS__) #define DATATYPE99_PRIV_genBindingForEach_IMPL(tag, ...) \ ML99_variadicsForEachI(ML99_appl(v(DATATYPE99_PRIV_genBinding), v(tag)), v(__VA_ARGS__)) #define DATATYPE99_PRIV_genBinding_IMPL(tag_, x, i) \ ML99_IF( \ ML99_DETECT_IDENT(ML99_UNDERSCORE_DETECTOR, x), \ ML99_empty(), \ v(ML99_INTRODUCE_VAR_TO_STMT( \ tag_##_##i *x = &((tag_##SumT *)datatype99_priv_matched_val)->data.tag_._##i))) #define MATCHES99(val, tag_) ((val).tag == tag_##Tag) /// @deprecated Use `MATCHES99` instead. #define matches99(val, tag) \ DATATYPE99_PRIV_PRAGMA_WARN( \ "GCC warning \"`matches99` is deprecated, use `MATCHES99` instead\"") \ MATCHES99(val, tag) // } (Pattern matching) /* * For each variant: * * typedef struct SumT; * * (For a non-empty variant:) * typedef struct { * 0 _0; * ... * N _N; * } ; * * typedef 0 _0; * ... * typedef N _N; */ #define DATATYPE99_PRIV_genVariantTypedefsForEach(name, variants) \ DATATYPE99_PRIV_forEachVariant( \ ML99_appl(v(DATATYPE99_PRIV_genVariantTypedefs), v(name)), \ v(variants)) #define DATATYPE99_PRIV_genVariantTypedefs_IMPL(name, tag, sig) \ ML99_TERMS( \ v(typedef struct name tag##SumT;), \ ML99_IF( \ ML99_IS_CONS(sig), \ DATATYPE99_PRIV_genVariantStruct(name, tag, sig), \ ML99_empty()), \ DATATYPE99_PRIV_genParamTypedefForEach(tag, sig)) /* * typedef struct { * 0 _0; * ... * N _N; * } ; */ #define DATATYPE99_PRIV_genVariantStruct(name, tag, sig) \ ML99_typedef(v(name##tag), ML99_struct(v(name##tag), ML99_indexedFields(v(sig)))) /* * typedef 0 _0; * ... * typedef N _N; */ #define DATATYPE99_PRIV_genParamTypedefForEach(tag, sig) \ ML99_listMapInPlaceI(ML99_appl(v(DATATYPE99_PRIV_genParamTypedef), v(tag)), v(sig)) #define DATATYPE99_PRIV_genParamTypedef_IMPL(tag, type, i) v(typedef type tag##_##i;) /* * 0Tag, ..., NTag */ #define DATATYPE99_PRIV_genTagForEach(variants) \ DATATYPE99_PRIV_forEachVariant(v(DATATYPE99_PRIV_genTag), v(variants)) #define DATATYPE99_PRIV_genTag_IMPL(tag, _sig) v(tag##Tag, ) /* * 0 0; * ... * N N; */ #define DATATYPE99_PRIV_genUnionFieldForEach(name, variants) \ ML99_uncomma(ML99_QUOTE( \ v(char dummy;), \ DATATYPE99_PRIV_forEachVariant( \ ML99_appl(v(DATATYPE99_PRIV_genUnionField), v(name)), \ v(variants)))) #define DATATYPE99_PRIV_genUnionField_IMPL(name, tag, sig) \ ML99_IF(ML99_IS_CONS(sig), v(name##tag tag;), ML99_empty()) /* * inline static 0(...) { ... } * ... * inline static N(...) { ... } */ #define DATATYPE99_PRIV_genCtorForEach(name, variants) \ DATATYPE99_PRIV_forEachVariant(ML99_appl(v(DATATYPE99_PRIV_genCtor), v(name)), v(variants)) #define DATATYPE99_PRIV_genCtor_IMPL(name, tag, sig) \ ML99_call( \ DATATYPE99_PRIV_genCtorTemplate, \ v(name, tag), \ ML99_indexedParams(v(sig)), \ ML99_repeat(ML99_listLen(v(sig)), ML99_appl(v(DATATYPE99_PRIV_assignResult), v(tag)))) #define DATATYPE99_PRIV_assignResult_IMPL(tag, i) v(result.data.tag._##i = _##i;) #define DATATYPE99_PRIV_genCtorTemplate_IMPL(name, tag_, params, assigned_fields) \ v(inline static DATATYPE99_PRIV_CTOR_ATTRS name tag_ params { \ name result; \ result.tag = tag_##Tag; \ result.data.dummy = '\0'; /* Ensure that we always initialise memory (even if the variant \ has no parameters). */ \ { assigned_fields } \ return result; \ }) /* * 0 0; * ... * N N; */ #define DATATYPE99_PRIV_genRecordFieldForEach(fields) \ ML99_listMapInPlace(ML99_compose(v(DATATYPE99_PRIV_genRecordField), v(ML99_untuple)), v(fields)) #define DATATYPE99_PRIV_genRecordField_IMPL(ty, ident) v(ty ident;) // Compiler-specific stuff { #define DATATYPE99_PRIV_CTOR_ATTRS DATATYPE99_PRIV_WARN_UNUSED_RESULT DATATYPE99_PRIV_CONST #if defined(__GNUC__) #define DATATYPE99_PRIV_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) #else #define DATATYPE99_PRIV_WARN_UNUSED_RESULT #endif #if defined(__GNUC__) && !defined(__clang__) #define DATATYPE99_PRIV_CONST __attribute__((const)) #else #define DATATYPE99_PRIV_CONST #endif #define DATATYPE99_PRIV_IS_GCC_4_8_1_OR_HIGHER \ ((__GNUC__ == 4 && \ (__GNUC_MINOR__ >= 8 && __GNUC_PATCHLEVEL__ >= 1 || __GNUC_MINOR__ >= 9)) || \ __GNUC__ >= 5) #if defined(__clang__) || DATATYPE99_PRIV_IS_GCC_4_8_1_OR_HIGHER #define DATATYPE99_PRIV_PRAGMA_WARN _Pragma #else #define DATATYPE99_PRIV_PRAGMA_WARN ML99_EMPTY #endif // } (Compiler-specific stuff) // Arity specifiers { #define DATATYPE99_PRIV_parseVariant_ARITY 1 #define DATATYPE99_PRIV_parseField_ARITY 1 #define DATATYPE99_PRIV_invokeDeriver_ARITY 2 #define DATATYPE99_PRIV_genBinding_ARITY 3 #define DATATYPE99_PRIV_genVariantTypedefs_ARITY 2 #define DATATYPE99_PRIV_genParamTypedef_ARITY 3 #define DATATYPE99_PRIV_genTag_ARITY 1 #define DATATYPE99_PRIV_genUnionField_ARITY 2 #define DATATYPE99_PRIV_genCtor_ARITY 2 #define DATATYPE99_PRIV_assignResult_ARITY 2 #define DATATYPE99_PRIV_genRecordField_ARITY 1 // Public: #define DATATYPE99_datatype_ARITY 1 #define DATATYPE99_record_ARITY 1 #define DATATYPE99_of_ARITY 1 #define DATATYPE99_ifLet_ARITY 3 #define DATATYPE99_attrIsPresent_ARITY 1 #define DATATYPE99_attrValue_ARITY 1 #define DATATYPE99_assertAttrIsPresent_ARITY 1 // } (Arity specifiers) #endif // DATATYPE99_H datatype99-1.6.4/examples/000077500000000000000000000000001440313234400153335ustar00rootroot00000000000000datatype99-1.6.4/examples/.gitignore000066400000000000000000000000071440313234400173200ustar00rootroot00000000000000build/ datatype99-1.6.4/examples/CMakeLists.txt000066400000000000000000000026071440313234400201000ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.16) project(examples LANGUAGES C) set(GCC_OPTIONS -Wall -Wextra -pedantic -ftrack-macro-expansion=0 -fsanitize=address) set(CLANG_OPTIONS -fmacro-backtrace-limit=1 -fsanitize=address) # Enable a standard-conforming C99/C11 preprocessor. set(MSVC_OPTIONS /std:c11) if(CMAKE_C_COMPILER_ID STREQUAL "GNU") add_compile_options(${GCC_OPTIONS}) add_link_options(-fsanitize=address) elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang") add_compile_options(${CLANG_OPTIONS}) add_link_options(-fsanitize=address) elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC") add_compile_options(${MSVC_OPTIONS}) elseif(CMAKE_C_COMPILER_ID STREQUAL "TinyCC") add_compile_definitions(ML99_ALLOW_POOR_DIAGNOSTICS) endif() add_executable(array_in_variant array_in_variant.c) add_executable(ast ast.c) add_executable(binary_tree_malloc binary_tree_malloc.c) add_executable(binary_tree binary_tree.c) add_executable(token token.c) add_subdirectory(derive) add_subdirectory(.. build) get_property( EXAMPLES DIRECTORY . PROPERTY BUILDSYSTEM_TARGETS) get_property( DERIVE_EXAMPLES DIRECTORY derive PROPERTY BUILDSYSTEM_TARGETS) foreach(TARGET ${EXAMPLES};${DERIVE_EXAMPLES}) target_link_libraries(${TARGET} datatype99) set_target_properties(${TARGET} PROPERTIES C_STANDARD 99 C_STANDARD_REQUIRED ON) endforeach() datatype99-1.6.4/examples/array_in_variant.c000066400000000000000000000006061440313234400210310ustar00rootroot00000000000000#include // Your array must be put into a structure because value constructors, which are ordinary C // functions, cannot accept an array. typedef struct { int data[5]; } MyArray; // clang-format off datatype( Foo, (MkFoo, MyArray) ); // clang-format on int main(void) { Foo foo = MkFoo((MyArray){.data = {1, 2, 3, 4, 5}}); (void)foo; return 0; } datatype99-1.6.4/examples/ast.c000066400000000000000000000023661440313234400162750ustar00rootroot00000000000000/* * Let us have a simple arithmetical language, consisting of: * * 1) Constants of double; * 2) Expressions: either expr1 (+ | - | * | /) expr2 or a constant. * * * A sum type can be used to represent the hierarchical structure of ASTs, and pattern matching is a * technique to evaluate them. */ #include #include // clang-format off datatype( Expr, (Const, double), (Add, Expr *, Expr *), (Sub, Expr *, Expr *), (Mul, Expr *, Expr *), (Div, Expr *, Expr *) ); // clang-format on double eval(const Expr *expr) { match(*expr) { of(Const, number) return *number; of(Add, lhs, rhs) return eval(*lhs) + eval(*rhs); of(Sub, lhs, rhs) return eval(*lhs) - eval(*rhs); of(Mul, lhs, rhs) return eval(*lhs) * eval(*rhs); of(Div, lhs, rhs) return eval(*lhs) / eval(*rhs); } // Invalid input (no such variant). return -1; } #define EXPR(expr) ((Expr *)(Expr[]){expr}) #define OP(lhs, op, rhs) op(EXPR(lhs), EXPR(rhs)) int main(void) { // 53 + ((155 / 5) - 113) Expr expr = OP(Const(53), Add, OP(OP(Const(155), Div, Const(5)), Sub, Const(113))); /* * Output: * -29.000000 */ printf("%f\n", eval(&expr)); return 0; } datatype99-1.6.4/examples/binary_tree.c000066400000000000000000000014571440313234400200110ustar00rootroot00000000000000// Sums all nodes of a binary tree. #include #include // clang-format off datatype( BinaryTree, (Leaf, int), (Node, BinaryTree *, int, BinaryTree *) ); // clang-format on int sum(const BinaryTree *tree) { match(*tree) { of(Leaf, x) return *x; of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs); } // Invalid input (no such variant). return -1; } #define TREE(tree) ((BinaryTree *)(BinaryTree[]){tree}) #define NODE(left, number, right) TREE(Node(left, number, right)) #define LEAF(number) TREE(Leaf(number)) int main(void) { const BinaryTree *tree = NODE(NODE(LEAF(1), 2, NODE(LEAF(3), 4, LEAF(5))), 6, LEAF(7)); /* * Output: * 28 */ printf("%d\n", sum(tree)); return 0; } datatype99-1.6.4/examples/binary_tree_malloc.c000066400000000000000000000023571440313234400213400ustar00rootroot00000000000000// The binary_tree.c counterpart that allocates & releases trees using malloc & free. #include #include #include #include #include // clang-format off datatype( BinaryTree, (Leaf, int), (Node, BinaryTree *, int, BinaryTree *) ); // clang-format on BinaryTree *alloc_tree(BinaryTree tree) { BinaryTree *res = malloc(sizeof(*res)); assert(res); memcpy((void *)res, (const void *)&tree, sizeof(tree)); return res; } void destroy_tree(BinaryTree *tree) { ifLet(*tree, Node, lhs, _, rhs) { destroy_tree(*lhs); destroy_tree(*rhs); } free(tree); } int sum(const BinaryTree *tree) { match(*tree) { of(Leaf, x) return *x; of(Node, lhs, x, rhs) return sum(*lhs) + *x + sum(*rhs); } // Invalid input (no such variant). return -1; } #define TREE(tree) alloc_tree(tree) #define NODE(left, number, right) TREE(Node(left, number, right)) #define LEAF(number) TREE(Leaf(number)) int main(void) { BinaryTree *tree = NODE(NODE(LEAF(1), 2, NODE(LEAF(3), 4, LEAF(5))), 6, LEAF(7)); /* * Output: * 28 */ printf("%d\n", sum(tree)); destroy_tree(tree); return 0; } datatype99-1.6.4/examples/derive/000077500000000000000000000000001440313234400166115ustar00rootroot00000000000000datatype99-1.6.4/examples/derive/CMakeLists.txt000066400000000000000000000002401440313234400213450ustar00rootroot00000000000000add_executable(metadata metadata.c) add_executable(record_metadata record_metadata.c) add_executable(print print.c) add_executable(command_menu command_menu.c) datatype99-1.6.4/examples/derive/command_menu.c000066400000000000000000000044101440313234400214160ustar00rootroot00000000000000#include #include // Deriver implementation { #define DATATYPE99_DERIVE_Menu_IMPL(name, variants) \ ML99_prefixedBlock( \ v(inline static void name##_print_menu(void)), \ ML99_listMapInPlace(ML99_compose(v(genCommand), v(ML99_untuple)), v(variants))) #define genCommand_IMPL(tag, _sig) \ ML99_TERMS( \ DATATYPE99_assertAttrIsPresent(v(tag##_Menu_description)), \ v(ML99_IF(DATATYPE99_ATTR_IS_PRESENT(tag##_Menu_note), GEN_NOTE, ML99_EMPTY)(tag)), \ ML99_invokeStmt( \ v(printf), \ v(#tag ": %s.\n"), \ DATATYPE99_attrValue(v(tag##_Menu_description)))) #define genCommand_ARITY 1 #define GEN_NOTE(tag) printf("(" DATATYPE99_ATTR_VALUE(tag##_Menu_note) ") "); // } (Deriver implementation) typedef const char *MessageContent; typedef int UserId; typedef int ChannelId; #define SendMessage_Menu_description attr("Send a private message to someone") #define SubscribeToChannel_Menu_description attr("Subscribe to channel") #define DeleteAccount_Menu_description attr("Delete my account") #define DeleteAccount_Menu_note attr("DANGEROUS") // clang-format off datatype( derive(Menu), UserCommand, (SendMessage, MessageContent, UserId), (SubscribeToChannel, ChannelId), (DeleteAccount) ); // clang-format on #undef SendMessage_Menu_description #undef SubscribeToChannel_Menu_description #undef DeleteAccount_Menu_description #undef DeleteAccount_Menu_note /* * Output: * * SendMessage: Send a private message to someone. * SubscribeToChannel: Subscribe to channel. * (DANGEROUS) DeleteAccount: Delete my account. */ int main(void) { UserCommand_print_menu(); return 0; } datatype99-1.6.4/examples/derive/metadata.c000066400000000000000000000074701440313234400205450ustar00rootroot00000000000000#include #include #include // Deriver implementation { #define DATATYPE99_DERIVE_Metadata_IMPL(name, variants) \ ML99_TERMS(genVariantsMetadata(name, variants), genMetadata(name, variants)) #define genVariantsMetadata(name, variants) \ ML99_assignStmt( \ v(static const VariantMetadata name##_variants_metadata[]), \ genVariantsInitializerList(name, variants)) #define genVariantsInitializerList(name, variants) \ ML99_braced(ML99_listMapInPlace( \ ML99_compose(ML99_appl(v(genVariant), v(name)), v(ML99_untuple)), \ v(variants))) #define genVariant_IMPL(name_, tag, sig) \ ML99_TERMS( \ ML99_braced( \ ML99_assign(v(.name), v(#tag)), \ ML99_assign(v(.arity), ML99_listLen(v(sig))), \ ML99_assign(v(.size), v(sizeof(name_##tag)))), \ v(, )) #define genVariant_ARITY 2 #define genMetadata(name_, variants_) \ ML99_assignStmt( \ v(static const DatatypeMetadata name_##_metadata), \ ML99_braced( \ ML99_assign(v(.name), v(#name_)), \ ML99_assign(v(.variants), v((const VariantMetadata *)&name_##_variants_metadata)), \ ML99_assign(v(.variants_count), ML99_listLen(v(variants_))))) // } (Deriver implementation) typedef struct { const char *name; size_t arity; size_t size; } VariantMetadata; typedef struct { const char *name; const VariantMetadata *variants; size_t variants_count; } DatatypeMetadata; // clang-format off datatype( derive(Metadata), Num, (Char, char), (Int, int), (Double, double) ); // clang-format on /* The generated metadata: static const VariantMetadata Num_variants_metadata[] = { {.name = "Char", .arity = 1, .size = sizeof(NumChar)}, {.name = "Int", .arity = 1, .size = sizeof(NumInt)}, {.name = "Double", .arity = 1, .size = sizeof(NumDouble)}, }; static const DatatypeMetadata Num_metadata = { .name = "Num", .variants = (const VariantMetadata *)&Num_variants_metadata, .variants_count = 3, }; */ int main(void) { #define CHECK(idx, name_, arity_, size_) \ do { \ assert(strcmp(Num_metadata.variants[idx].name, name_) == 0); \ assert(arity_ == Num_metadata.variants[idx].arity); \ assert(size_ == Num_metadata.variants[idx].size); \ } while (0) CHECK(0, "Char", 1, sizeof(char)); CHECK(1, "Int", 1, sizeof(int)); CHECK(2, "Double", 1, sizeof(double)); #undef CHECK assert(strcmp(Num_metadata.name, "Num") == 0); assert(3 == Num_metadata.variants_count); return 0; } datatype99-1.6.4/examples/derive/print.c000066400000000000000000000034021440313234400201100ustar00rootroot00000000000000#include #include // Deriver implementation { #define DATATYPE99_DERIVE_Print_IMPL(name, variants) \ ML99_prefixedBlock( \ v(inline static void name##_print(name self, FILE *stream)), \ ML99_prefixedBlock( \ v(match(self)), \ ML99_listMapInPlace(ML99_compose(v(genArm), v(ML99_untuple)), v(variants)))) #define genArm_IMPL(tag, sig) \ ML99_TERMS( \ DATATYPE99_assertAttrIsPresent(v(tag##_Print_fmt)), \ ML99_prefixedBlock( \ DATATYPE99_of(v(tag), ML99_indexedArgs(ML99_listLen(v(sig)))), \ ML99_invokeStmt(v(fprintf), v(stream), DATATYPE99_attrValue(v(tag##_Print_fmt))))) #define genArm_ARITY 1 // (Deriver implementation) #define Foo_Print_fmt attr("Foo(\"%s\")", *_0) #define Bar_Print_fmt attr("Bar(%d, %d)", *_0, *_1) // clang-format off datatype( derive(Print), MyType, (Foo, const char *), (Bar, int, int) ); // clang-format on #undef Foo_Print_fmt #undef Bar_Print_fmt /* * Output: * * Foo("hello world") * Bar(3, 5) */ int main(void) { MyType_print(Foo("hello world"), stdout); puts(""); MyType_print(Bar(3, 5), stdout); puts(""); return 0; } datatype99-1.6.4/examples/derive/record_metadata.c000066400000000000000000000062641440313234400221030ustar00rootroot00000000000000#include #include #include // Deriver implementation { #define DATATYPE99_RECORD_DERIVE_Metadata_IMPL(name, fields) \ ML99_TERMS(genFieltsMetadata(name, fields), genMetadata(name, fields)) #define genFieltsMetadata(name, fields) \ ML99_assignStmt( \ v(static const FieldMetadata name##_fields_metadata[]), \ genFieltsInitializerList(name, fields)) #define genFieltsInitializerList(name, fields) \ ML99_braced(ML99_listMapInPlace( \ ML99_compose(ML99_appl(v(genField), v(name)), v(ML99_untuple)), \ v(fields))) #define genField_IMPL(name_, ty, ident) \ ML99_TERMS( \ ML99_braced(ML99_assign(v(.name), v(#ident)), ML99_assign(v(.size), v(sizeof(ty)))), \ v(, )) #define genField_ARITY 2 #define genMetadata(name_, fields_) \ ML99_assignStmt( \ v(static const RecordMetadata name_##_metadata), \ ML99_braced( \ ML99_assign(v(.name), v(#name_)), \ ML99_assign(v(.fields), v((const FieldMetadata *)&name_##_fields_metadata)), \ ML99_assign(v(.fields_count), ML99_listLen(v(fields_))))) // } (Deriver implementation) typedef struct { const char *name; size_t size; } FieldMetadata; typedef struct { const char *name; const FieldMetadata *fields; size_t fields_count; } RecordMetadata; // clang-format off record( derive(Metadata), Point, (int, x), (int, y) ); // clang-format on /* The generated metadata: static const FieldMetadata Point_fields_metadata[] = { {.name = "x", .size = sizeof(int)}, {.name = "y", .size = sizeof(int)}, }; static const RecordMetadata Point_metadata = { .name = "Point", .fields = (const FieldMetadata *)&Point_fields_metadata, .fields_count = 2}; */ int main(void) { #define CHECK(idx, name_, size_) \ do { \ assert(strcmp(Point_metadata.fields[idx].name, name_) == 0); \ assert(size_ == Point_metadata.fields[idx].size); \ } while (0) CHECK(0, "x", sizeof(int)); CHECK(1, "y", sizeof(int)); #undef CHECK assert(strcmp(Point_metadata.name, "Point") == 0); assert(2 == Point_metadata.fields_count); return 0; } datatype99-1.6.4/examples/token.c000066400000000000000000000015671440313234400166300ustar00rootroot00000000000000#include #include // Does not work properly on TCC for some reason. #ifndef __TINYC__ // clang-format off datatype( Token, (Ident, const char *), (Int, int), (LParen), (RParen), (Plus) ); // clang-format on void print_token(Token token) { match(token) { of(Ident, ident) printf("%s", *ident); of(Int, x) printf("%d", *x); of(LParen) printf("("); of(RParen) printf(")"); of(Plus) printf(" + "); } } int main(void) { Token tokens[] = { LParen(), Ident("x"), Plus(), Int(123), RParen(), }; /* * Output: * (x + 123) */ for (size_t i = 0; i < sizeof(tokens) / sizeof(tokens[0]); i++) { print_token(tokens[i]); } puts(""); return 0; } #else int main(void) { return 0; } #endif // __TINYC__ datatype99-1.6.4/images/000077500000000000000000000000001440313234400147625ustar00rootroot00000000000000datatype99-1.6.4/images/preview.png000066400000000000000000003712041440313234400171600ustar00rootroot00000000000000PNG  IHDRď5sRGB IDATx^ymV$$!@B 0b;%v;NNb;n86`)ӛ@PABHHBu?̽3sݻ{=sΙwf/or?2g#crnG7 a1{iΙ\a< @?:S4粶Ɯi̡wr-:gysgzy目!>xF9s٘{O[[<(F%. @sc̍0 @ztb02LM,ˇz8>VkS.EwKEV8DYIV Pɵ,=hz4a *)^-Lu@ @@&\_-MԩܚDiȨGISaݮ…Y 72,'?cEˣnd^˟; YCKI)+||v@ t [Wpfu"ͅLq'LQ!,,, 3OW+y++F YJ$Q$)Pd!D"t'G "b @ $"н0Dg-3d/2~~3M:!ʢʤz) sr~ޘAGELߴ.!TCEYE%^=Oez,  @7+tg (iQz0r=iˊ|5e1Zf䘺Ȱ"k7I P%Ҧ @ @U\z( W&x9߉T(EY"Yw Dјũk&ܧ&ĺBNuŜQy1 @ @:˹jsv@+ޘ/ͺ.-3Ua摊]eo"SEzW`ze"DЅ-ϿӒ 4UsbA<  @@I 9HElr"N"(*( di"ȊF/ǂX b2ź_@ @(L4vم)K9/+Tnq9&HQyY]Ce ܻ$OTeJs"BJN6JWHBQ!USg΅ @ dTrY fdzN?,ZTZkd|9'Jj$,YsH"XH$)9IԻs-=&4΃ @ $Pp6\N_7ZI1vSb?JY4ew(,5 |wC,B"b^;PIa6Ղ̣A쿊)yQ6ؕsS\Td @ sF˶*2Ν4^@ t5P(S!SL]|hzbн>w*0%3Hyaeߡ0YeiIr+8C3z$ ceTxk(1=KG3K,H  @ $P" @ !*—RVL AEFHx}-BD˶/eR,ӥE_eLA}[GI,DEcQM$1+Rc$2@ XtE]x_F@ @@HEv%n#bz2TB""G9 P@:ia?-30]a#_dFFI#Ӗ]"bF%c#x2,TD%]sF"Nni@ @D raW{dq$wugA.-&0+Di NQ7F$SI"zZEmŐHz!"2 @{ᤀ!ҺC[idE9>OQD_!oK(ɺ2ŲP9) -<4-ňZ>*i_I-גd@ @DKIK<%Y/8m)?+ƣFYFٗ+YfBb0He=2@ @ P4gu짰2T̐"?oO^?$grGvY4& @ @K@_>gEe떙$YLKgyw&{j @ @=@@i[Y"b%2 mϼ[bJH2$SY=p X @ @X%z+=)˴( /Pi 2F ʊd @ @gXZ=]aw V˦{̈2[ؘOWGYҮq=sX @ @(2krKz*i Qb.Ԃx @ @1JyIt# :Kd̈2(H2wm3DY=, @ @%ʬأƺEiQvej#(s&`unI a @ @=Cgy20+$ ]!ʼu!ɔ g@V @ @EB"e-K&S0,$SISjw\" QV$O$ۀ @ @=D@2ɬm,,3{1NYEYOJ2>z, @ @@1r{HenתQn%,x^g.G @ @@OdejoIE92Cu$b07@#Ⱥ @ @8hQMS^v̱ɮe[륿4n^kx=xI2QVO$ @ @=D&SGEE]pɮ.dJ}{, @ @@1Eȱeو%Y^Y&Y6(+Ǒ=@ @ #E:4K_YfcKc]BV @ @@@2-ìڔ9kɲyyAy0>S#dp3ϓIbeҲjn&uqɀj);Zʏ<\2=uvIޕZI:(e%SҧG&ռ)HM!erqrOgףpX @ (KQu4EpvQ77Lf<-fꥵ! ='q2)_2)m{(-Ni㏑](37^&k& HyU)!Ң.V"-wl?J~Lor兝Z:d;KMNy|nrЙݺ? @ @h5lcyQe,QՒ^.ɔ7•!7ܢ)~URRRttt&mke|ԥOY{S[siٳ\TJ}RhmSڤLʇ͔%Ctk+% )W)uvtJ&)o蔓O Qѵҋgr@ @ "xiL+u,Ӣ Iv˺If3/\yJA 8YE鯤I kuC~]]lbo_m5˰S~ee*K]:l`Xk= i.E @ ?U@YY%2~1jDy2{]2ڟnIfUiQ$ 4@VU&zdZK])Ik7e2W6]*#>ed,>}+kkhurI,KD @ @!L!ˌOB"l,k,sw?b+5Ҕ`$W\DJȐĒz ,ii7wji*rSĒڟe{ZJ^SP5n鷸JY QS"f\b,$S(Sdo~銞 4urQe*b?^?ViWxT&k~Sʪ–yK]^qQe1 @ л (Qf-HdY,sX?w=l4`e]&ni5{$ȗvydaRRR![w1&DswvɖC*$Wt.d:::e&wӒ)IM&?qT*!Ⱥ >dKs@ @ }~+f[Ewt˲gZu,`:sY|ӺJW_./<7Zai]{ hט5!T8yv-? &䭻E~lA߻\_cF #9˂'C @zC嘵{Qa"<{+1׌5ʲ.\24U%2WH2H@7UVz iS &6Dm£ɬWJtdYˁ9j:d}+ Yk;3nC !@ @].nj?mdvXl̈˕*,=/s,oH2djLOFU  4 ,SlZ+87^* RX)IUF QXʥ{*ߕՉed-{䮓=n!@ @P̐a2٢vf:5K#fθٲ/32냎|(].$D>s֝TlO%KJbatB]2'K+3_%vJk*aGudgX$vJlM~$K嫅I @ @oPƾeY(XR,^ڴI8ji5sU(\je_}$MYLOYwOaiYF)~URRR⹷9$mR~2קnCa[ iٳ\TJ}nYsgvttJ}C6I2x?n?ݕVJkߌW)uvtJ&)k蔓O -⯀M@ @zox^̐g־CS0eYF\bKmĘ_jTJD䬑'&\AYP> @ X.4{jf6ͦ$%ʢ\Z2z]2+,' Vlz:ڥ5ҺutKTKR~SڣigG4Y!uRV=^*͐LIa ֎6YMYWEjZ )(%e=B!@ @H!x-"+ˋ3S/2\J+%ҔaPI0m~L8+=@ @ //jőe|Y/ C3[.LUHʥ_K/y(u. @ @P̐\V1,T)43;T2CS.ŘiTxĶ&, @ @@#`pY6˥je^]0.R0;,K3%ɳ{c @ @g[[E+gzedqc( 3uaH5N 7e=U@ @z!_Qj̪摂i|VTYV9$YuŒdeEMIF#z˖!@ @@(",Dy2L"q {232W,?̊ .l.QCT @ @7pD,\:c]뚩ˮJ Kf{x3 @ @@Je*Lef^vE frfE]Lm'h2$Ss"Rz @ RJif(3^8˥WƫUUhQdBk$>l @ He]%V @ @D@2~XTY?M{2㰺Y\5˜EGY)O_L@ @ t3\WVY,I2NoE!be%Vj2[dߋM< @ @EF[Ke*EEeqɌFUL5o]ODY=l @ t+e$^`&#LG7ДK-R&$gFub @ @-*LƬk%e+ꖙEidb{, @ @~yLK3oYf[b͙i#J U{&a~3t?}V @ @(s1f`jey14j%eiDeˌH4DYsaQ6@ @ н'l)jvuUUv4eYJT!ʺc5@ @ Pl.tWH̠: YgE(sUj K3Kk|b{8 @ @N}THR#svFQzO9řMiYq&>7<9֗|X  @ (S3eY6u'ܳ#+E3,,( Jt$˥aH4h25;`v@ @ mǭ F2Тb,Je混mV⏞vvf.q(獅 @ @@ejJ:SvyQYqYHÚioQVO) @ @@n|\K1#=Ҩ?fQH/D{/Ih2DY7s7+9f6(LK ʺ1cn@ @ PLkE/m- 2?y2Y,qf 3W\HjY"?ODY? @ ttKeAEmƮݵ9DYPڥo+,J4+(뺇!@ @@o"`eZk-cʂe~s]FGe"3gh2?qoo @ @ e?c:ˊ"ˋ*jd"VM2MKTK]fk儘Q,YK} - @ @OQVvi*3vg>QeE]闖(KvYH[QDYzn, @ @H!Դ"^be<}|Crk˨;ud̈iDYB @ ^E.ʺ22ӣ(Ụۥ0WSKzՍc @ @E%JE)!NY(SOY̖f6jg8DYA @ F 'ʴ2S%ס)Ӣ,d .hCGB @ t EYKtlYhQfMnv42,m,NڥQl @ @0DYɺ_Z\b+үN(^ؿKH_@ @ &Gm]/m,K Jԕ问VKKe_S/#''YQgVZe5eA,L;"gzu V*e!ll @ P<r,"92[lΙ%ƌU̙+waaJ+gVevMEOԺ̨o5036{[DW+jftE9 # 'Sძ{tŰzdrM+m@ @@$`eQ/u4X(sk%̬d5<]ZB_W%D;fEo# WC*~`VX~i2lPsIYYb @ :d#r_/٨2|H\-ʼyO5R&ʞ[,\NG_Z&+m꾕=*n۳rQ4F>t[nOc㏐^%Ć!@ @B) Kt)eu,Q>e.ҝfviȶwEu({dY]_U!_fN=Y=(&>Q [R^GsȐA=[ L @ @GTJ~K+S6Nٯoγt$u`4}XurOC/,U(H]CLDGumYuF4Y! @ (s]jەgF}%3EXVe_2\k]-'7XhXKN/]VtOJ{{ٴ]ːVW%GL]:\'[v2cX][_i^پwk(q#e~XeyˤUƎ,gL;a_e=@~=a0}tXpپgld԰ԢSQUIuGMX;hVYy{7m!;6n#?1=:]f9fs@ @?#rEb"nVe6L-bF)1NCEOXiʴ13428Ribe{-I'鷂j\UR;Ə*qgo,%3N7+՛DI;C=$9KҒ!sjqE=.2qG˱;նG_֟sQbqVzuYaL3\N9Eߛ\e}Ju : s斶ajO8R;bBHUr`cl{ ur՜}֞lk7LEvwܴ 2nX4߿'_]!KVoG|孍u(nM-mr#}PcͦjsL=t:ϿJX?S'$445˺-uZ:?yF,{QC;~P˜ @ EY!闅)e2#~/K5"ʞx Yf;\.J= i1^lwUeؼFB={a:~lh\s՛vjQtE+/+ȴ!  GL \rzO2%Gm]]vzj4u9#ѷJʲkxijQW%C;OuacˇΚ%=HlDؕȇΘ)Σ2{aNT_9zPz*LF f%e{Uq^}Ͼs<0ŝzfNO\/.7 @ @%D:TT~_uUxmW?cH,OXdٔM˧Y)E$Tԯ|JGM1H -"[Z[e׾:۳go(kjnf TJKJjU#L _\&asxH[Z=ZܨXCQ2QGƨh-t}KKK+zO*PERُFC-ӢLEs]xs䖺^sOzMU[Ƀ/L/>m̘rCE1SɩGOBNqU*);s\~ޘtXey'25GI&hkmQJ*g|t~6%~~z+Ξ%|4_q @ @ +ʌKX.R|qf\y~n_,C\̊&3;Yf9ke1x/G1 v]O.зYS&9&u t::DYKQ?K\KD,o򃁏SҮMMMI TBGIMm6v\5'?Z;$]/0|%aݵWĪɦ>S]]y,0v֡REN95 @ @'7bfJ+"J_:^Y:eوy)TaFgGl6l׵˔sϼgˌ) @ @ K~VЋNǴ3+-LfFi~ 1tDٯnV^Vc,@9ĘGw}2kn#ҬjVTeb2tP>>o,{{~K)!̂7eۛ5}b3k|RQvA{ylھ't%25G^ѩ*%RFZ•Ek?8[ƌ%TW:7/Sܭ$;ƘutHˌzE==<&'&:% @ @ eKK/)s27ūLnE0 @ @@/#2/2+%΢)F).FWC;VZQ_l) OVLV5/|,2 CL[e*'fN+<󱜷|,_Ulʲz O9J&湏{}]쯗C Ou(S o۹[B5gt9ȉc#/}9u$p}XL'.3塹#}E-Y-/,hiaP]7l[?q)r1( c @ (DQcLmLPLcX~AK̫]'3r2)30>GD7 4_xz\zzߺ[s_{KTw9N2):N7Ewsuy "!JQvۣ/˶u؇%bݻZQocˇ>^K2uW+m"8}Nw4f\}~pLD3ԥO-9z9KaeW9I&7LKO/:3;f=00 &{t/]\K:'A @ b2:eF%z>Y1VuDUW#Ǫwޕ^\}Qԫo7ꜩu|_P>nJYr~+ϕ>n~EٵNW/ [Խ:T /_ynߥeDu_֒qؠ:S9A&zt氋Fʕ睘7ɧ>eCcZ[[u4{lgȐ|UijiӲ}(w=ʛl*忿q5e @ @eV2g][,P9řUֵROfKTL7zjfm)ekeRQOi;kge{nQ;[!~lz%YTQ%}J]EؑC|/`mriQEs9y`JO\6ꨝr!g5 P+DI?um*MεB|f[TYgLՉ2ꡄճ ߔfPuި! N*;k^(S~7yWT::;uZ5sNtDglӶrsKezL7QڸMIN=f:^XRyf?t 5*A @ {Q\euʌtK.Yf"CY[W'lYQ%qH_#&*|j555iiqQJ;kyUUy'N.c.8e̚6oBRiȎQˊvSBG.ڏ5宧I}C~_e _;d!FIc%gFZS#}) KKK|.:9rvO]#YSdS"X_U0wAW.?X7jr:d햝·,S꼩PQI2Cf̩=@mۍhaD @ F@2tKGA[]wX},0f^fEYl1=C6&h251]VLE6+˪ uu[!g4Sf-wDY[[w8WBfrIZ-zM8D.?xߧI͹N,}u%tرJW+-^~xrqԪ(nwymFٲkl4$u(i4j_w>Pvj9veʰϱDYuJߖM;:9Z%%OT|JMAYrlܶqo+&'N$CwTTdO-ȡ_oΆ @ @(s[FMtAfNqc[Ck=&(S -f4uxe12uID)s_N_Y!#V)Ut^u vg"TSK[w5l`?SݬUUzuƃJ[ $ck[UGeETRcRh}=pP*9bpjiulljV}SIlmGG'ЯTT_Gjdp3aB.>u)Rd,_רe*2 SUWiCcɯ]pklnsh45qTUIOsv>u1J @ @vQS~iE~Ht[f[TQ.WK9ꕙdzf:l"EQf(%u(/Q{Ɨ*-uRMCҢ:~(ĎP\ĜljڇC,c1'V׹Zsf6CO94֚ge_\^I/R-w/&*MPMu-ȦzSr^k6ˬi8N @ @@2uO Y.~i( e fU"ȜeVڥS.L]STK꧂"<qedNPsͫ䖺A}][{G\RuμS__g$(!jJJKC{^(I>_1ݲ}gtݷ q-c!@ @Grm.ęEl1Q/X~tX昭kedVvY̢P}@ljek6I'v"G/Q>̧"^YVl)GL#xdi8 @ q2we.@G\Y҂0sm,A!lQSZ8%.YhʸruM(G2AzUm4w(@ @ (ˉ+{d~,n4%)蟉$"FOa^N`ꍲxmzU뎒& ,^Wߐ :ZRAձSJ ).T @ ْU-뒹/;_zVf~KD{tAjl`?4/W)5 -@ @@-t.oD3yTDYBzeQ߬ueB4"ʊL}#*Jw5ۯ*It9TJ))T?܌ @ @8hQfZ/#` ӞG"̌eeˎL <@Uv˺,@ @@qȊ2k2VLf`ad!/Fy1Wa&&?}ާ۱l۽?ՃW^GCJYȄ6n#w>9_?rGD><]Vۚ @ +~NCيFYb EYso4Ųb:MG9 #ʊWKV$ٌc!Ueoxw=n ="u<JLr@ @@RQfu7S*zFeQg~Ί(˥GZː`F},+\d:lD#5ҷUU":E[[5'/>U*/fνrs(̜Z_dR얇zM;g}+:spԤ"*@ @ТLR"ì* 0bf2IEɪWEU?+afYtL 3w!wDY(s@CߒW{2ᐡ54˼w;bkjkk zLEETVT5b\GG{nWߔ ی{p%HGdxs@ @[!Ϣ2+̪KfI0+̜ɨg.蟮(/o߷E!ʊO!GWKNik_T4?~kjoowԍSD_YeT_QVnc,@ @q X5f,(^gfn]'<"e0sb!|JO+>N0ڱ$Dܧ?'?Wܿɳ)dؠUS+tSn)GT͵y^ٳ^[DWUQCduQ[(ɁwzhSK\UvUtPu_4v11ۛwTfaש=({1*yjwkHߪhc:]W{PJJJd~2mh}M~zTD*E$#=DuwʻICSTM8D_@ @xeVD(S:]AeH5{QGjYgf mF|DtMSiI|rZq''V^gWߐ%7IuJi^ IDAT}SJPy*< 3{zTKQܥrV9ds^+.;kju׵Ex{y+6ynQUxϿJ0 u?>745˺-Id8' @ (Qrb:#t@eVjM:`Ze'H %{SVihl̾_#'ynqe}g#Ô2{ktJJysn޹WVL4ZUESBj)"?uZz< ِU;=lc=D5`lܾW~理@ @@$QfKTWgE$t"Q,ey$"ѬzeDCleV-ɩ#W G%U~9e]*Ғ_\bQvчɱSJY>RRZSBeRާTw,--%~l+7kom~cs_e~m,(SQT=gRVznSs;M}XMG}9o|@_0[*+sI)T9UBJ))H;SWuʉ3Re*lacoUdCEih{w=)4+=Nw^ssyo1* u89ةzm= ?DTj N}@ @}_Vr9atZUG+!EUo,(fDYQbj{d(˞JDZ(=}: g>wAYil2R/O)GOɥ]`RQ?~<ȏZZy~j*?~JSQRh OC=EٜcMtH$}bWi5.P]_v c7wӗ*#f߽L+4]*Aj][;E O-0HU=^Sg͵stvtc//)*W!@ @eRuܢhڠi.o50EeϋR̿EQV]]ttpH~{KoէD>wYyTo~%5EoBlT+j=^=$4vD=k?QG9Td%o>3$46ʴ fPQ7>6GmoAkΝgӗ!Zn//]l9udQ QVlPKk9PW/E_Iv(S:UM-%6P.9m.Z>6l#j(">3ddԻ"\ڸCwqUi٤:@PO*Q:i8jrmmYq7xyjyyZ=ڋfkyvO€a|@ @@(Sב-_?fggb:R/DTF2׋2gӈTCE+z :w==2c>kZg-jw{N]ծ;CC [3x{<6 }S3ʁ(B1 @z'Kkie[{Deu"ʲ`Faye.-diĎ3jEzYOpTQVn~hIc_4ʑFˇ<. eo"L Oq{|ٸmwɴ (S666ϗCGɸCE#2M6rؐP.րexQ5a1u!5k'駅{K}c:s=5Dkr> @ C~}.(bfS0-fww4g"V -?,(3̘!Ȣ2Ketg"ʔ|eͦz3";-p+=ls@/_yNhmBEq Μ>1?osyב(Seo˼tsd_A9lpY"Bks-=7-|Yr1ET-4hmm{}M6n߫#U!0X՚M-mRUQn},+;>s1뢥| @ .(:XzEy2e ȯlX62L]UÃyDeEaf(s"ό4cNDYVZEN#(N7׿+%Uk/:Y#5ojyiQUK8.PQVW ioByU],˲l7{S @n.!7I7B/``lܻ-Wٖ\dɶ$w|sjVνysfh{2;1uc`+DMM **USG䑎I %I7rʝlzY8e(V<B_e!X }FI0;WTtV6N^Pqn2'|d̝4 l^PT/LLÜ,{(-jXtHolHHHHHH (L2t191ffkfLN-/4PVjYgeVLĤPք{+M[ e!ddF*(,ćCLڗ}6ec*l;xҒRnب0 E M Nq1P&A?r~BEڲ:PV^Qy|OdU%Ct}cT[D ikS+LJP,5Xk[++?k&ojYga}s9 @p%IubY,V.@(]-XeY.] eѢy6\C{O(1D\b"C+3&nD YX"5)2sEH;=2U#B]NH6|YsP&JێY)C`2T-!؋Q\V}3UO{2 qLz )!f^bWT\prJf`_"B'!FtD֊"žxi~C '7'+ {L&el2M(ktK;M` e-Z^^rw~'Y _#EӥǞŲ+KMeeqMn WYs'%,4abUVV\GIy|@u_X TTV:12w:NbSWKERcMwmeVe& qwCSD yEJ8VVe/YFkRĪL K˫T{&D!,X[^ک{m--wL9CIHHHHHZz2d륣[ںlj.ge_&KKKiV(DzK 8gtlTNT<1?R@V^ j:ü!I"ɜ"(0PN]]qQ%2s@N_y7"zd.roc6"4d}7+y[bÞc1n\Y'ΊHHHHHZ?ʬEN/99ۜ%`Fd(k#lZ~YK`UCK@TXJ@8ť*֙,88q j      f%8.%XuL[f%Y]̲fVʘY;kA6dt準Ts$@$@$@$@$@$ 8eslfL^)fLˈigQ[u-A2eR(CοX/`8&NCwHh'[RHHHHHHZ e6m3][ft̂)8^"ҿ4UL)ճ<Xh :v#GA$@$@$@$@$@$@$@-H"iʕؓ?ִ1R} `Z0G2UŪ念V3U1l2-S̒2=^&YY - 5 F2]O(t69 eV5PigvgZQncِ*.'BxHX̓uIHHHHH=hJLt*fܚU(=-vf`0V9z}{J+wR̛6&fzǷWZ)I3S͚L&VUUD5 Eƽ{!_%cvEEk_TX' IHHHHHp)i*V]`~,ZT(-l\/BIBY[j=cRf^2 jᦏ,"Y_MVWWeT}|,W2*hl9p Svxʔב @[#`/iUfJ+K3^((vW:Vl/~Eah$Yƅl\ I rou-"%IlР@^bJYyN/ťXqDDMjsYXH cZ.(/ƅkn>>?}:7c2|-+ ](u'`󧗴 W~J\Es/H$'P^Q0n>v0FJr:'%|,\  /c>t-o~0֞2-/ql̩X8}0zwz`Ū\W^b?x4AmlMa1&+ &ᱻn5|-+ e@&hBYxO u_h?+K $sP(kgׂR_ {7f-lc}M산@##: Kgs& u*|٭.QaʪjTTU)GmcI,-SbS?!6 c{5ec|Kh˃G7)C{ 1j̨@Qq|rJ,MpD ,Ȥȭą꿓" VX  lפ>d55xiz={Ax f^ vG$@$@$@$@$@$`&x.R2bąLwl eu0)}v^h#&x\F7l|n21. s'߯.Tuu >WrT,Ǘppüg/aHn r%BG*wNq|d)J:a oNUum()-硦uRhv IDATQg,C%E${B ~D\0+* V_z9x|}DG e(!,4S>۴w~z]a41V&     vJPfiBY;kZijP?ztz7>ۊ|t8e &BONEUe%J֗Kica°6c \/v555SaLuSKg#$.)+%Vv|;c@ ݦ?A."VǿP֯?$Důb5*w/êu볏ǣGB@)+*5 2)JFheVcI;GN}cVmgtXHHHHH3 efWL(kϷaaOލp=rϏ7G HĔFW\R7kyHs'@aHDt/"<5Ģ`yxle7{|2 nnFv3?X([4Ó]śY/N}e&}(̛8 !     h!(kX/Ng^߯ds{tRcC.`CbHf<ښZ| b=y,Cdy5'R~ $(:D,/,3)\nʲW}fu]9 @ xB YV_3e @]:,^CqrTcmObSGU8e?xh55s@}Sл{( e|;IbWۿ]U ]c4pSe">'ic9-;?'     hAN2.$ SL]_0)k@x#@`+msgU~&;&_Jʫ狨`DhׅCAiAA.-;@Ș=)" ۿ~TzTRS Z*NH6*d=hD #'kb_OHd&t 54yx叕{OA.U˭iM MHHHHHHP&Hgz}KM2[~ڏ1( {+9)u P&"bWeU~E 3\)틈e"X܁DKRLa{K(ʼ?1c+%JP^9cBY؋uE6,ԘP;iǗLShCJkZuIHHHHHP&ɬeg2E#?架b"`9z| Yy"blhRX _+☑==~z5W·G~NW 'X&|M=&{AS?Wx,zi߳lm5ijlHHHHHZ L2Zj&a\/24[V(CVgeh.bQ(k}ؠ-i/*q1W]u6=ϷDIYNHƌq [Msg`s5 3 n5ׄ;HHHHHZgB3BY˭bYw P;ǷVfa1N=\GY<'`*vZ}sMHHHHHH9z2B޶WެU2[)aͅnQfnےŎe'HHHHHHHH84 > QN\seQ Ls.ftMA$@$@$@$@$@$@$@P de;SO<0КC(DYZ7 @G& B;*X,,ƚJ(ӭl^j,/e)5+3Lsf6[9{&-:= "P d҂YdG(ӭlKkc9r40%i#ՉavXb2K&LZ~        NBo)Jτ2] PѷO$@$@$@$@$@$@$@@ (s3jum@OGsMsd(:GzL.7 ոzwךTU]*nlT8B[p96h*+kq|쎏GdoK{9Fhp Dq.$x>KBHHHqL$kEn}fvԂzI6A[k8STTV'\0*鋖Fk\Rt=Z˖'i=Efde̡+N3)36*<Ș_RU' icשƑ{@D".=жXm8u O["pvd FnB|bchhWs!/{X)?qR^/T7&7tXѳP^QeG wZg~Jd1Fg .h_(ſ߹NS}g!6ƽtᶃ')Y,jJWZڇn^Q|U5HĒY)e~o܆E%b.%FθcOB3 7pd)~Dz,++a[ZQ;HHPg2륻Z>ϧ[Y'2 e#ļ]8wfXW퀈R[{*W? {'HHH8 eʌ)\r{(L7^KPbLxY*uP| l-}Ω6B|]+ćA*΃swIXVHe\4ɥPOֆ{?DB}~p-P5k;c٧Z,6y(zu~5[_VebMsܮr7^"mU(*.v)咔ׅPF7_sJ(uRYbUwBVv7XHH PFVijkwc}0^Α[ eC&7L[zO|ŨEhPzwF] wҟ̼PVV^ nQhpox=*FX e>8nS ^RZ|{G0lESl%Hkjp&Kg]GW[+5gk&}TpRIv{ws矜rnHVy|" .e碸KNʙlοOc>-ܢ#01wA9圳>%3 Ɉ$j Lf9]ݛWnDF5}CxH$mz U/e\T\/TV"4wW;-TL>3א 3(;㗯\VKgÙP6_weEy;l3&(/_lKs2WqPwtuR(uGv/!AXtHCJ-2WIi9bN bӃ'9 WDeHO6ȱn{ޤa9W:Oy=3lmj[Tm e+I2JɽZ%J4zXU5&dXSñp`UصLLmlUL ?}uddNrJx=?wE{ u1 g>?E[ؗ1X:wSQ[_~Q յdvC};::<>ߚ#YKdL|㰺VY֫6fREً֣Tdb &"” 2q' E/2bŦj"M,0酫ꞓ"i.ƽǰ7d= Y璲rdd]GaI̙u76l/cD,`z$|V9:!./kR>;2ӧsTx.[:Z*= gzՉ&7r+q>y@ l-6C}pVUX놶aD( }Y?qax[U!^UK{ IDATzY󈁬]ƧˇK9\Yp"yoT}iquȽ9\YIY"ZglSl喃H?sq1'䅌}eFUUQP^Xy9 # =[l$|:uR72*,XҾD?hR34nklԀ6f >|@ }p-uotk_b;Ce~z\ "\wza<~-b^ug#@869T04z`$'<{la8vVn=,Uozc->?+|eZ,p8iv/X%ȿ ]"xppYޒfE$뵷R2U3ODԑA?I=Hʪ*SjΣ go[j dzv%6q4DE he&z<&냑+>J%o:dɛq6s{\IZ:!Y"2ٛKfRVTƺ{XH&8wƑ3Svx_+ĕPY<0wSlP&mY=*l_YgY;7"<܆ԣ*ES)K5a L\l~喦7Y7g[!MX:gǥ YbTo},v-q{SFJIi-J>+4w8p&2>I@!_]X(_[?ڽ i.>,".^/4? 35ʬ?~* 0MDzgY,nxц e=vm8Kz&Vj1uY e״1W͹!gCLMu5V(y=3F)A^msuE}~q yKWV7$+ӗTŧcghcY+{V%ڻE+P~,ay'w_U۱ݜlwOݫ,YHHH[(Q(^jv|vܨ~݈7f)`/͝4%%xꍵ+Lq7qCF1~eܦKۘu{|v&ƚ|,.)QYXWB"e3^ &E㟟ldMe@LnIЮqkUw\Ά\m e_n]:&v+C_%B1vd: 獾g~Px^0&P^d?;w>xm%륫5 ]0"z%)]UO,Yܱ$e,7gk H82$ڼq꾵Ϩ|gSĒlH5{\rJWXq%߼}"Ôd]D̸pEYIyh$2ƞYC>W"xe%Ҏݏ  |qJF=" ˽5;p EȁuIHH@'@BY^p\^߯drI:K掴SqzwOW+9xwN}1yfc_ro[ԯKĂ)#,U=PrM8$0is3{lH?sI_ 2B,qUYYܦ7{ֲBmZyDyrUTTƯ2(+ ePY݇Oc9wZO.B[+̥k̥ۙBA9hnbY2љ@,qdDSiP6AXvիezhD".nnNW57RqԳkZz[0i(a_mۨ*)y0Ҧ*//NGq#o//RYn25s'2*zz9y!4F([2c4;)]?߮qHbg矵P;&sS]4 q ۺĺ\:o<e_^oYC?/-rXzW( P\Rw0;G VR;,$@$@$-(yk/5i;/~ND"hÇlױ3L_>ߩ>ݻ$˥dӾuQqC$p=R,[;oAH"ŗӐfe/ȼ!ř[ZCoBc'+">ܰe啈 UYJYx* s\ %VLdWܼ ov zw0_k9ICG2)uRĽoUA&umzmPֳk4;$袩|R< 2א"O5E_k7*C}vlYC7^tJGYqY en ښMq5V(u{`n}} ސbm3!}ފcҸ@̝Y:S>,Bt ?|_>k{˾xTUV]IHH eV>ވ'N/9+L\$ىl\(P֑ԻS&b=ǷW+K"yY:oG|{g",y,u`PʭI"5Fk (1Dܩ$2(⮱y1X:oXbYϩ1B6)G`]f$ևQB$W$ RB00)1!*_vn;k$:`B7MA\LdK ^lڃ)C`8aSNDmP&/X &t&+AE`.Km9͜9nÞHMXKLA"8Q699ӂU)ʊK"ͬ7A‘G6Eʾxz&8]t0LQTC6Vs-1uԀzW1BNFXDŽ) O4KigB?klAHڷ;_c2 2Yyq7Wy;TB}1abghs3ex?`£K,q[ 6(íqǽng[O? zӢ3~N$@$`2 ewK `.lRW߹&P~}r%y7P_bX2QҮ[;{n־6E\`Pc/l{ h1־}41V8'5A^(Oqgh5*՗R^Ąg9ۭcba[( uF;Ιu/ e\<]2Y j!?Ue{YJl *6AAƂ7V(@w4We~/57g6.+8miZW⥻"g@xk7?w׻\z6˫a Ě9xB6Aqye>25}4$9<ߨ"fUU]lPɈw#>g-Lq}M}yC(k/Bf[)Bx 5ҧ:k6c9В`C,eWUox^KBZe/E*+1oR]}G`*U*n*â{p$憳x/\·bD(1μu?o|\_ NCN[C'eg.^òS ]e1b$YuYc7΂DEٷQcOPOg^G,:3qhoL5p J c9ws3>/kI/zNL#)2uΔ aY%@Aa%b:862斬feb\v(8}ʎcǡ m3JYu|Iŷ],4gD(g-Je>ZB({ +(Ab(~pk($.y 5ԩJ"])FX!s,/(CXH-Lu϶B⿊ݟwCbws  2 em O|+5Vylh eDOmJYD jEYiy9*BCM-zuQ130gB2Fmv c}Fh|{_8RR셲'a9}sCy̼M{yϟ<\=5u1*I?f[Gܬ;kPVQaNBYbyy)H5p U1Љ72i_෾܅bq!bY&dq1ߺ7P&?WlV(D닦]C I5 &X9 *V!F'!N~(nFnH9zx o e ǚB|ZLFkxSHץ"#B5X̛72o-!ܼg/E߽wVooMC> B?g-;WV ; 7]~N$@$@BB6q'ȗ1J*T oyq'Iyi^,k2)VC(D}b"mݴAϷʍcwLETD]7U3q٤;{ n, e%*ib11WE$_Le^? Ưs n@%#BYiy^7g6oʭ|#!Axnc4V(;q2Vl=,2Cd˼r,-Ldu~(CChX,6by`d[(h57ŷ`7qgLX@zvUX JGJ/}UT!(HQ}g2jUJCB^E/| )BٱSE9jKFʨζgD(}!gyR2.W֧csj}iS,ʼyyK(B٬+`fE=r`Oby Yz\?bLNKM @'@BY˯w,S Myls[ eʥQ/1Kbf99"wk&֥#[lHn˭_݃rP;AYo$h{,dR^(Xj#K$fL],|={I""Եի+m8>)P&\ZWoHFKկŒO,tWc~WւRdډ JǛTL$*qVn=WTVqLzK(>nᵕ;UK,2Ct+ZmnLzٺ}-(VBߴ1zp(\^QYjyp۔:7g_3/gc*v(;i%]\31iD? s"r6=Iے4b9ف\/V=5k7_Ǫu%1=-a},d{@{[(+,pU2c__lZ(wqf+Z=_g.Z^L@Dxb\ϟ4,kL_4̛֢矷2o-!a#*Τ9$wL~'+98o$3֥gX4x|ɭ?IH e̖>r<\ l桯́q'}rP&` =i'V]~&z-)X|DG:X0.d窺/6:fBeի[gdQ&Hx8D  T_aCwݔbUUP&e~mʦT02wI)6p~HIo³flP&WO=V/~ۗ'/V+yP%2yvwŅw9b"C&/ DHw){fl#oeK' s-BA7' h;(Q(k3Ub/ոS?0۱ʤyl'řP&_^[^*lkPRW a!Nɗwqq %48 P_>~moQ&RzϱLdjED8?L.9ɼs[R p2ƷP&&_cKT%Ƣ{(%HIJ oaȸxb%B(iz肩\aȾUV,OH6|YB72WzF&>vD EKJbɸ1Wh L^\\}3=gU'"I q6S >_EP۝~/oze$`ܐވr6ʧܛʭtƃwOݫȽ_Jqx+γԽWTʰPdWn 1&لzWP&ĕX^9P֠򲤨Nf)+"EB7?o e:ZB(SIJKU\3qEԉZuX"VPso}4? e¼X0uTX6d̬K$@$P(Pfv=~(|8T])K=W<偦LῚ*BtGheOÏ2"q줎usn{Il=pJU[:g,3mkC,*4%'\kv~\+"%UUU,"4PUªLDeb9$VU@‚fδ&K;{#(x&)芋~ՈtiEЄxl/mI`o=Kug5> E"EmfQkA(v-q"r~8 zL$^Uu_('Xo6kF8Mږ3:B}cs\wYrv&%D7aH :V2w޾x {s\i=.'i  AB6 𻷾Bn~1[ wF2i@,XzEJ%n_֝z%ޔ+źHE\,3Ml+W"_K^ry* Zen7@O("js!Eg,l]!JQ*sÓW>ڨ,Ě큹)*Z2}_ S~!{ܙ"mâܯg!SԞk EX| Vm?qɽS ޞ_C5o2/CSЕ`FK eOY,QEy@5m_K e}-c6:~Wƞ>3۞xO ag R)8,$@$@$M(ys?5y[q3xT֪)%eWƷAVгA5T $_k<B2X`M),5E?Ҧϲ'Zx{LXH9v F'i1#oMjH,_~mYcrt&%ƞM7p|r7fsc<؆$@$@$2 em϶! Ơ^Zˀ7=ϷjNHƌqqr t]^qg$yxhwA#Mn:N*+tgF,ϿFkeke Dx^\qI1'ɚ3% (Q(ks."RF 6j,,©1g /h,mo^EQ-2 t .)-U=ێ7zGe%YϿ3l--k-+q @ @BYɜGD$k+<`X2 HF%I6H)k-{k{,[%-HH e׎lHHHHHHHHC(yux /(ِ (Q(p2       h_(Q(k_;!        P(Pe$@$@$@$@$@$@$@$оP(P־v4gC$@$@$@$@$@$@$@PFíHHHHHHHH}P7QP\Dِ @+!@ eN]7":<Z0HHHHHHHHP8w:OEl?;3!       VBBY*.'BxHP+B ڀP&[|mJ1wP,6}@΂HHHHHHHZ  emD(=u/Ldq$@$@$@$@$@$@$@$ P(k#Bl/OSw܂1{ @+!@ eeeexOQP\Q]F%eH;yAY>:IHHHHHHH#Pֆl=d@**)/^]G 7H$@$@$@$@$@$@$@ P(kCBgat=b#.']6~̜+ t$ژPz4^_Co,ɽiΪ6ZV        BBYʎ}^ۧ¼Ղb5W 酯/jmm@$@$@$@$@$@$@$@6&e]^\mY)ɸkX[8u;!aaܒc       DBYʮW>Q{tژwxEŨQu:V        DBY]߽ڣs'ic W˪d2t + @G"@ e2-F=b䎴_9W       h2ژP#6g|گGm6L$@$@$@$@$@$@$@6&Nl;x KbxVTV~t4 IHHHHHH:  emL(ի+]G7TlwB(1vl.DIHHHHHHH6$WGMM-f 3)]t-g6~|ݥHHHHHHH:  emH(۞v ͘Еy~/l6mSG)#:FDIHHHHHHH emH(۫qB6pzl?u,7D$@$@$@$@$@$@$@6"]+s/ ?{g啽7$ $$Hjn]붻uoS@S !!nsI&If&yw+{ߛsϙ=clVUU eXIn`g#       h(]!B٢e[1 ^?>vgz}%f#Μm3cxx`c        P(2&ӛߨhGnQ6W4u3gsϏ~+6|fHHHHHHHH.ʮlS}$"0apd'+_T#1exo,lL$@$@$@$@$@$@$@W3 eWPV]]R凾>>pqq'kjjqq,ݸM__899 NB zTpqu]>)˓c%e2, Òciw?v $@$@$@$@$@$@$@$pPveW)g7Wr$@$@$@$@$@$@$@$pP29)G0==Oim>V+}"}  e _/ğU՘;~ $%m4dԍiZ?"  h;(QL\WyJ.8SmE5:D#4j_s:hu5 vŠ>s荩Z"Zo)TpP{\=\6"OX_ Eg_/kyZ-4x yV4U؝kHp=(+82OXǠNN1=c04œD=(h1~`̝8rnAѽ(9j^8.Vjf?GGFSSGў-_pB7siꈰWx~Q}=*2Nήp W;b!BHL_w<:f6~f1[Q䇻d8s._۫+4:5+:3/yͬU㝧3rT: E:}yE*^DZ'92IBhQ/w{L"RO\r Hq9U\;$/k$Ku U5M'Q{):<ѦY zזUkPM#K¹|U㉨ wllaI9NDžhuj$Qz|HBȁDd<|<X5ɿEo}Sm. BзWwK*5ֵYyj*◃g9׭y؎s=qľ/f><{ߜVMLBbltHHHHPF%Ki[ܿ06$2Ǥ1HN»^@%Kޣ1d>Oł9!6ᆬa~huh'g{_M@l)%bjA}pmߤ߶-1X2- 1YcSdߟ2CX3~@ypSm5 g>=ѷ7:x.`ˎr47 ;TG炧<+?V{IJlhmeO &fہZQV'[(iC$@$@$ P(kB]8vBOYy5N1 ==GUU z%x8U\|Bͪ#fUpssR[CA͓KIDy6A_] O C_o;;#BE8RX h6UY6PxH$gKpʍs{cN׺IգlEEͫs^XQXBY#<";·PTWWhϥ=c!/U2膖{50~-4B n, ]N&=2w6}zg(e?=iGO>jPl>UOl~H5?Ҵf!y3f e;s*kT<.0D* orm-8o T}HM)JW|Cdfq-J2J*p,5K%"$"Tԫ4)ޛ_DDa5#C=RUn&]PfKKD;u"d}skT(OZoUUlVH4DI+ K48քm3G"҂)?^ÿ&|ÔLs烻f(F.5ؼ" KQ)Ě_Xn(,jb1j/QְaϱڟuJ'&>a)Jq0xn {}mlNeߟR8Gڻu = _ۑ JBY4kGgBVO &^ s5}ԱImQ c3&bQYyʑdoa!QăB)R(3_Ji9r+0QR0IGN`* ³{a^HlƁ"t#B(.,}B\2s}G\ϙ yl`Ͽ==cWҍ\GEpA+ɼ:ZΟQ6??!2y͏"`~:V/Qף?ywC_\wU 9 ]o=݆߇oQΣp F?SjjP~x':AT$F=>3-`BcBDHTծ#)qOd?n6f+--hNUml4ZZ,k1Vn?3 m3FcDVn=!dC)},]'Bf/VA((.Gҳ+U,&MJls 2}!$y⿟ý#* AauGRz|D,K)>pqr H!=Կ\6Sdw^; DbIDDOS&QnFZ$??.))UbUغKS)h2މ6QN|Mr5|^ע GRWsA-#1ɗ+U3Rb~|!wB !   $@ eR(TB'"{?b]^$^_Z$}tUdaA~y>WWWXv۰B`Tz''uDL^䏼({J\sP6C8S [eZ-Ƭ4A uƒ՜ᆍ;˧Ey$摿O\GLsW݇꣈߁c|\doEQ~#\$Whbg2$ϘWB?D=S!z2~s+Yp G7eF3$Bӿ/飪g;-ѷ>Y ITc!FQ59$TU>71p]meP&Ms_;bXr,&eĶ<"{2غmxɍ*CB 0$6e2G_3[JA)L`ɌB\I)D"6ҟa||bhrwd%z4%S92q[Ge2Q1];HxMrx Dԋ }Oܧs/mr4ډX}20Q?xX<LQUeGxw lZw4_$en],ϳ><%@ ZcϫP{}mjo˻? +~xy&+{KUDLHHHH=PF2Sgt>t 5_;zbpxmm[uS G,F} :=~' z pC0AK9r)G/&IuKeG 0GOQt-mմ_>DpAY?/Gk4{y^۽P2.tZ!"ݡ{&cf"?M6yk:ZxwIo, cpW*|>N5riTWSv9B^]1nPO{W`Ec9I.2I//RQhc W˒2arf]Sk'Rl!լO`bgԨgBY6HZ~ذGq٣ bƿIt?lRyzvƵ&b(Uo6rdpgmO5@~Q1:cdUp쭏rp#{bX/|y R3*1e\O-񼣄G쫵ycu,Ygnx%*זExy`FϺoXlG$@$@$@W eWPoO-̓:sk e=8RTWPruCR?EabHߒ9J([ؽ3W'~5u:on몆 oW5rw5=+{ߐL~[cS_ )q쩛T#fh= [e? xY=.>u-z10P~8{>5U5 YGpGPUb8V, .=- G/6!-e$ ŧԬ|,rPQ*9JEǦr11JRS*dJ}O* .۴iTW4$H92 ;2 `H`Х掯'9$GCiهMlDn3 (´ ?XV{~mv;%(7:a 45xHDE6+طG쫵x}4M57[֭gzN~~JOgRX٣7j̗2C$@$@$@m\(K} #-{f6/2aU,6T3<|b,Tl-͑0P&Iwjcl^(='pjyǓ>{ ϼ, ^~zZY| NvX B;k2"oy QfqBiP&#y(X{6CogjA&CVZS2AFc89݆8wPSձr2I e0{\"Z=nzixs]!NwY^P&Mxu/ <)j ]0 MoVAcƒpAf-l D I]*ϔD14)27\%Gdr\6wLj>1wM$ {9S]}v?JeOy}YQ,j{vP{" }e?JMRy^fɭ(Ϙ|MD: xFKŊm>ې OB6/SfL2.p; 6+%zCuNlNcjѥƪ^.OY۵2mU5~j戁Qo.-~g{vŝ%Rzǟ4Tv D3{, buKVCpbDYO ra\zB٭#a e jLz>Q~p;lR9Z][mrmE({Xls2P^%ARq]f2qnrm](ɯ~;u̟<5]ǰyAzMFI`_ܐoh% e.݄ E1Vh4}Q![(jNdd "$w];®#)twݳGw0qP6iH!-ݸOSgƜYzT|cZ's׎6ãY2yV/IdBE練JgXG e'Wk_ܿyeQx֚;/ >p:5A QʮlVj{v [^G e~{4p?|myNŬJ g.׻ _9w%3me>bFGEsQզ92+‘,x{_dI~ɛM? ?$ n2۽iL}u#m8^R_ Ez;taHt\U9 zn[6 2Dd3=W4WOS5u ,Sl,Ljv0w\3[ĺ]ԏ0BkנT0g@2ٜ|,ZE zG//'La߱fGvǬQbvh:)Òm.fBc)c?ơ3puu7NGE ߞ[4ZiW/3hƐ㽯~F]7 L*}ZfP=qDMQ~_&#!q=GRT< ]7;"   ++@(j+񛿜CU507n Vb2>8!WWí7"P,9y7 a!?[Ri+ [\<ٷ|VUSy6g)x?nڋ6WsT-&k~j1VDxJL,*p*-{xz5mE8,TWh9hxҩ}+D~mESbNBMUDW U6ma|)ml$Rk͐Jnx M<'ӲZkKCGe~3r J`BT5L19R u78B(JJT@_uSlArEK{BYIY9n{D?^3:}Ғ4 ~/ٔI:hq^" UZֆk{>ڟ'3⵪׎^Ż}{,o}&#+eIHHLʮL"<Ы$sg_7<< /Trť~G eO x q^` u9붠_H0ftBBP@d 뭻q^S w76N &VmDF.{1wXN9%#ʤ/-G [f Ⱦ6))*DsA~J>}:p/\| uy8prvA]O8;]y*BML3/>Hf;fLD$w3ZSM?!QSOQ%/G{;*NRZm3KmhUAYVU>,CEf,qd:kGCr8׿ZJIZ =!  hc(]!BYigXPSKe^PTM[+pyU= IDATtF: ?(_A񆥨ZsrwB?Iͺ\B!~A1?g܂Iשnn#!UUh_Q~p;7>Ȏ7I٣IdYC.oUHmeTƄ29FC* mJ("KJf.JEnA(6ZsePP$Sq10!z,["'t1HLي8_ıР@2>^"r8|Cё&G3DŽaxx5h4*סә{,J+>8L~u]Z<T%جbSS{IcC\{>,>>Y.=|8ީY*^6S3ҧ w&b| #   V%@ D\ 9"?Z *ZgZEN_^lWVV 6N'C}O~9^."@2*!.B/˔Wytz=S8XP mM5"== W''xyybwwqHKdT;$Bsw TTlxn4@r/e(,`H&,*hSOjZ8s\BԜ;&)"6 sP<&c@X44Y]g|,cڇ>'.+Q/N~pg[\d=.)?,R[y[kgokzCj˸"$%?_z퍣D|]J2Hor^Jr$PL7Lc|fEdr r5*ztBc{l[_YXSEþE}/4xmWHN4:AT%*,$%]--_\ r|]E]nܛ]U$gBUp[G% F<:e?;_~Q ~aa5IHHH @ M^P/LF$5P&/l /2SkLTqS"/"t5ط,`DΧ/6{E`yZ@(vŒ{Q>|]$ָEDQ~wPcϜgU-}: .qa5mg˞=qDr K7Q?7qeׇˑvot Mfs{e{   hk(]ABYC(( yongk(D4 tDŲ99XrQh*kZs2,*)˟AVnn<%^pDE]&☭{aTMk4A+7gW;X-اa~99`?.DžURo>sԼRM|DĽjoy3+l}*z^'׏n36 wa%Mtz&>]Cdj?/9.%1HHHH P(BVN Hsy i[eO@3(,)G~Q)*t*|ن$Mnތd$PK@2|t3t:=#Z8T9%)(Q&U *r IHHHj%@BWĺ/%X$'Ivز$61T5Z\LeS.E;bSh3$G򤩼-1YXx {7s%1HHHH% P(P֒Ʊɩ%@KOh$О9]GRQBOwtUChOL֫yT2jj\dǯǾE'As͋ @KPF%c MD86 F$@$@$@$@$@2 e!  C@;I'Qe"I5G  eZ8 y(y'IHHHHHHH%P(P~1HHHHHHHHPF;)'H$@$@$@$@$@$@$@-AB3A$@$@$@$@$@$@$@m2 emI9A       h (q        h(Q(kN . 9(*-N_tں$@$@$@$@$@$ (Q(kbElv*|<a Kʑ_ /OwD;_vtiΜʪ*Dn-g?mŎC!7ڤ!=1o֚%     f#@BY9qAI|<=bK}۟q"q2ÂC1f@Bt ZnҠ_ށ;B;olMmXq? cĮQإŁIHHHHHP(P\u_\DSٸ8Zg .&Oq79B{%:] )E\'"욗 v4wqqi97*SХC,󹷿CBW7M;<==[eNHHHHH2 e_We",۴OM[[_C^QE)C/{\~j0w\?wwwͯ/ܙ3Ϯ%kת{ ~ jl\QQ¦}%*1U CcI͵")[eHHHHH]PF]:,zt,߼_uqܱ O-m{:> 8_2.Ю%֩{&퉁Iv56gΞǿT{t$$FRED}1'NļHF#     2 eW7KŊ_^B[rOۯyIdt{'Gi!vq/(.K(5&Qe/~խ#?.X=OU7Sœ/KO$@$@$@$@$@m2 emI+t*ԹCOGr(B$7ڙs9s,V@]¬r\c樣Z<쏸N*q%kQWs8W ~JT ~453`٣?)֦¢Jť.2(#{k=/!u$izV^J5cЭcc;"s Ojb*\qFU S  Gu*=.@|*?'чqX~|aڗ?r=.Ϫs9AVmʦ(9+     h(Q(k.y7W$ty4OTDhch8;׉8reURLĸж<;)\?2ߟۈ(?3 K6n*KDY};.9/^vQ ̃mE ^zsuqE#R 8yu ]$#)_/ (-"5+꺈-zwdy>s30-R?w Wo顪7Z2pZ|SQr>9v>gs T=sƚuaʢ :w7䗨H*g?o<L6z[dSd0Z8]%h(ņHM7 rAy=\TSAAp p>=_~"JMĩcUD G-٫_Q;.BqӴaU]' MbFuiD MKzl>8ěۦAhPSCJ(o/FLyp>J޹,ﶃյ3cXx@{y<_]p:UW'7Z^Q)z7=*KT(nZ[Š_fO>]֧3~HTU(S^rET{$@$@$@$@$@$К(Q(kMkrlS[$OaΣ*r>AQBKҲp.XD96ύcFvBٛK! !>mp g2YӆYޮr~x'ZbjNu#9SQl,ҕrŝ7af 6n@x8ThG e~^}8͆(#ѫ{"'Ikkl^IR?;Ga mdnL--v_Esqv5zcXXX5 $@$@$@$@$@$ P(Pf]T({*G؎çfI"ʌzA< It5+5+?nޏ’rtBٿ?Is]BՑrn55AP&M,YC~ E67 7MBBWŗ\=J\݀oGHZG_"%]gc (sd0Lf3M{cVч lu4}qӣ[.?Q`F)`!%& I¼7 HB6뷍 e;ꦄ>ktSrL3KOj!bL\~B?X^w u-BYtOj-Bϻ$~ ] ]<6{gҴy/=UԑJ~XU)sP'U:!K~1DI(FGa O {ULBb11]Vāgխ7fې JB6뻦BS g(B(IGE#);LoAFvd9w\?Hw7$o.?@N.BpӴ(uÍ!9٠pˌ׾eExHNtJ$3FINg*ɒRz}(nr$uvD>ms Ts[8c(ğ/ FsDzN~X5=lKn,JTV̹ x}E>##4 D$@$@$@$@$@LBVvƇwPy1WWU%RUDXRf_0WԈw9%Mf/.U]3/fkmhypv7\]ƄuIi)55z'Ұl!p޸~J`L2Gam߈@r$v\_?b֘~>t{IHHHHH @BYuTGeťxZ;΢peIl}LSnˁXɐY!4&?nދ}' G$R%++K_q1x vMEKT4$i줲RiT X|Y\_h܀ g\U/(/,ƛ&wAIv+чA7+FtX ~w,£l^W\56<׎`lG$@$@$@$@$@W, eڬ:B(!H<3G3[oyo_^ݢ1kLF8+FmO~2$e[7xLU 2^r Ʉ'|@"(bcf>^xf.U(jNfw&STGxk>_ʏ6n6}d}^=nvHHHHHH!@BYuVGe"}Fd s D|5jrR*QBps95xuF:&ar4IѣơәYר0L\O\i{Xji֝2xCr.5EXj YyEQ})RWإ e2nZf6ZG(:7b" x45{aD8g4G:[mc;޾ k ˡ{IHHHHT(YuP&Bn~TWK\@?oUh_>E8"3)+\0vM$UbA>{3"c#H̫DNRU34kև#<h4,|P3F{諗*IgRx #UbTC2Shf>}4yRGY[D} 9QR9 @PFȎdҲ2f'P\VQoT?oO ME|LecNC{Ch>#)Y▱q\?⽚ hZNf󑛂}0(3$u3ÑB=b6l!s[d2a dCDS{IqP&⥌_\mR64bPWR9KE8}/i{bpu{za1_N'hxwNCxHkǟFǟmx{IHHHHH-PF-98J(SKeDP15_Ng6&K%IK")XdѲ_x:'tƽƵ?)B4=im?.W(/***j̆dODthTsDqE{oIC1sT_%涴}r+: @BtGx$@$@$@$@$@$(Q(kv'kKcD/GXCaj\$BLU| to S]*ww]-di=rȸB={>8nFu2$V\qtfmĤ\4'Mȡ ( G$Zܲі Zo2YzNd^(]зGV&yq"kVa2J$@$@$@$@$pPFj.d %eg$ظ1`9,Z#L&$>!Ǒ9pwWGi$@$@$@$@$@$pPFjiH4 AhK@򥉀WW֝pAcRBԖ8     vCBv\( 4EB2>!$@$@$@$@$@$@$@$@(Q(@$@$@$@$@$@$@$@$@̐55@        hQF?N$@$@$@$@$@$@$@u(Q(@$@$@$@$@$@$@$@$FaVAٷN_= AMSU]'2T_/tnu+Ajf.Vl:*m?齑  !PCoREE@]k]uյaTޤB!@gL&LIf&{3߭Ͻ}[Zv6VXhJw^m%읯o?zw/d͸>p8G#pI8QƉ{rbN#.e 'g[{z`°P=5߯GZGwIPRQuO-,Xm-d܌pu{ե. H[p#@ohDĐLsssX[YiiݮX_OCo?w<`Vb ӍXޮO{b_R ?̉Óp&?9Ĕle3K;(s7D|/\G q %p8G#p8QƉ252& >-$.Ȑ7ʴO„a]DW[|s Lbvy i%$b3 7DO't|T>2_t1#$?G#p8>pKnzy; "s_#S|yw.GVAiKkjpϫȾ둃5ݜ$8s33puv Ck555!=w055z]Q] /Fm#_m6 w:U;Ȃ"P@rLѫ . Rs,ZRED%vڤZ(?ۍjabat6Չ r5!|ll؈Ps +a >4tL4\T$B;>$3TqYr Z!q f|=%Ȭ<776Z5>zܵY,?ܩRuYJe}ߛuۉfbj =_7C`%*/Ngߑ+WWLd-vfϩH֌g *ؚ;($ƞ~+xFG#p8]D't'̞ lPDYJfv҈Cm\@NVAY ?ԏbl:xOK|2#㢩Th!QHÌ;E."I"6q.׮)B`fqÂ!bѮoxK]eg"]F= u04QsG>e>zӐCʪlXQDIY=gz4663v@ ƏvD-m!؅,b||(%k9wdP S4=KG/7xyG#p8'8Qqפ7tILd0ƒMN_+%F`Td:Q]ӪyEfgi y.MQ/ImYG1f!2~ ԉ1Jf 72qzkÓOUVa)nb@/(kQێ_P$f%fgR)[<((<\ڮV$BI^!=1o'bK-so`_L&MxLqC%]玮DH~ABYy@\%/!f`jPRѵ\ѹ?E_o.3ǃ+!oJԗ0,dF5B!JQ!,J mLr\{bK-Fi!WFA9FOGQ GȓoO-MM:{.Q l5,9}YRWa75(Ccer?| E0Eĺc0P~t;UK´W!KZ<֦d(K76֭DY}}=jjD"ʫ$ZsBbI 1I󿷯;es\KY&BFsp8G#pesއ&W_l:̴Hln@,:H74`xjDޡ_+X q}=޹S177qbEBXj^N/{OvX8i0ծ2O'}+?.G#p8Nq{շ2x9E tD8u.ޔazpqTVؔaRU٫wأU/GG{GDxpĂIA~YdI̯>6M. t'2P_!:'ii n@uF¼ CuƤ+$Y{6悂,96Ȩ/M䍕˲D 66J%KoCyu5\<s0EEkjԞ"<3akcHcwI(s_wxN'#W%Ws^/'e|1W_ظ 6&pu1CN~‚ΒYa-m"!L>KʫN7>dvnk=P]$z@͎Y( B9G#pBe(k@[!Y2->*+O&g€Zb!ʾr Wngּ574!/QV^UoJ>#aRh{ݮ f V:Kf?DQɧXjv!&!F$ҋ 0ܧ@vg 5O~",khk 8竟 vś+$%DؙZmݗ{Jڒ2zwV^[lyA/[mwQ8LeoHyLtUz n?mƷVԄUAPՈ _$@ϯDޭ斪DJ|RsBi@1,fD,V U[k 3ƚ\G#p8#2N3WpDSd/x_ژB~8IΨF!~Iwr&֚7hDYva6쓘EV̎Q`o2D)姚DC<~k+ 7>ߌZO^e2 t.?Fu0h](`a?9B-uH( `=Ô)̾,`=<&6mG)_ƨa֘6AIrG[o􁥅HFuaZ6`P#D/Z;3p8G#t:(DYOBs#H^^< b~ϜOmeo?KwM{M ma/@QF}/*oY`xD͵ ⋫70m~ksYk#:sͥMΜh6j >}B9 #mx%|+zN pYIݺ# k`ooduu5 qF:gU LǣL#sEy(-3$wk G#p8@Fe(3>jFً 'NyQF^1~;x!3iX(Igq-V/̇S(*(ůwIBO!i!뤜47nN5:nWJ/DiǬwyOD-9NzG n`y J8Y{kPvgQs->@>B(3*Q|+uz肁k%GuY^ Q;4F㕈=+j Q-bj44bSZ\As62p8G#p"2Nݿe'aQy$6B_2AkcE!uMrO'$wry N1YL:Ȟho)!`P{i^(dV;;&q(V̍E۵fJ+I)ѡ7iNcDDϊ,.XZW`i {{j.*Z"|.SjD3X<͍ QFXqi ͙PDJvV,%ێ]`GFb] !j'!mG#p8]NqRB@JF?q獅q^f ɇ' heEN_U~$;9c1m%aEh{4GYd䕰t& FHOu(n0 7ȧ-f;!,@$ j%ԟSM*/;N|Oa}絹p! E7d#nRBʼn=0CXkjh@@s3f>6#7.q4z:zʲD^vg2d['3LUdi@*hTV vW,DzFcQ.8$m.G#p8Nq{Bn;wNxLAV(7[Aw,5|QF7lP$=Լq:Dc/wXW(֖-infa]q֘HQּ/g[=hG_Z([kprŪ注"~Ό@ A$jj.N^D]2bjSsgȟܪmnb}2a_~ ~SK+hK1q֯_d샥fDJG<٨/΃MW6d} %GL KL3JHfA~I[NΎhjldm=~El !yH8?4=Sp8G#"pe]d*fhCLb/Ĺtofĉ~Uۏ' =ux(Ժ֥QFZ]?EBr&l bQ'%ʈ3H}i.RGi=A&pRvv!oe6^R'ء D١yjv!^fA}1ZK[%(?%Sݘ"K P`G& PSSgNN1#&MEf~)s%S\""ߍ?` { IDAT GSo2ҬE!HA(9 ,k\Cև/ah5Ap{^4CE6!oL$P["|A&Wn }-*ǿ-פ#p8GpeUD!PQ)޸.aD y:2"Lf{hsCQk)jĜե%"YLWHkmd~UXR"dDF% ìA-x|%%iP^;k+ YkpKj1;ԗ(A~IeK[5ZiK'K 5%RŨ#Q%1qŜVSd(LoSEmmW\TUt:YR,]=\/F]A[h{5eg!JRL%Zhg1LQJo'#cC ,\ .G,FsqLD%~Ǩ`o2bߟI ¤u: )1r|{/p8G#ype7xmFkO`pWGVHhpD ,,$fD_9R %ԩO!ʢB1mdDKDSHQb(+ ve{z寪Fl'g*መA^D{id$DI[.5.;WN'$%"}3Q(+ZdbD457_7_w,8jЗ(#20)~(r5&&w֣0R@٪2T߈S0cRq0ϾTGH(i5-H2Ǚ" ve&} ux8`oHpTi%햣HR{LT?,_;c\G#p8pefj:tIVT^|6%>xnx/sjj]CYA!)UJ o(V}5ܦJh~);X ›'+H."mhQFcebj''›-LY:#nn։ Q_߀v"-KgȾƼ G#p8N@e(iǫ4tûL, Cԥ "33?NZehAb2h#AS33E*bI8j2FeWd>>2~E̊aaB}Ȉ*'44Uѭ.5Dq rr/aei{f.յ+cp8G#2Nu9 -ݧQY-„a>_hnn‰ 7@>Ȥvڈ0L֟uG!GainA/b;b|#@fDlUVSGFUG#p8@"2Nu HM?9GDN|*j0+f B=i#8vW^w3oi^04'#xLKG#pY8QƉ{vru,o*Gۚ[[qY%,M()Ϲ*d K߈8%Dw'omvjD:"#{?p8G#=D'ʺL'PdDEXpOw"S; XYmv7#p8}'8QvLuM@@E3!}2.@WGL?I G#p8@Ge(#p8S\Ur8G#0(D/#p8G#p8@Be(^3#p8G#p8D'ʌ4xG#p8G#p(DYG#p8G#p'8Qfŋp8G#p8G#нD'ʺ׌p8G#p8G#`$8QƉ2#M-^,G#p8G#p8'8Qֽf,ohjjFIEjDuhnjfZãNuWZ(=\u jP!aMܮ6 EbT +K֡K syxj055EO.鴜b446v6V]]!@]}2JLLf=6 fpњ#TVײo\;J^G"|m\9QƉ{c&^i8ںzrB|0w`e jvA\߀<9: Jiy /W'6f&7@k;ś8s6+QE(3->- Gvǎ ,scCj-'8t.Ȁ9.ӿGq,>Q!=uvuVCk(Og5Er<_{yW/T1j`)C,ݤ0 5OG$};_og$=+b G#@[] ?Jpe=<=#.0{Uj;O!!9zYֈ:!7nyL3GLHC?UMkxϏf́sX{;SѮE`ۏI.^r;Ȉ`_kdB=<vOsWv˃迪:27:ގG- u+*ǭTDZĐ{Cyeqe7x]vDqy\lHXY67مeXv@3\ߟ;Vp'Scq>)^&P#Knqv^8yz{jI+!] owZ )Nĕlfc]P(a<.1|=!9Ƭo}<]tn;[Y돥3Gj住rk'hx2*vMriE^X[^̍}DbպLUw::7lGx @[*>PM;KF{Cepe? y : 2x3'd`&w5amoϺ]~x~hUD٠@LægW‰!k) ;N\fsnSgh2B{㣡ܽ\\~6{:ÀwX5e3 oOZp|+t[(syC>d͉2ꃨ?9Ĕl:ar&jܸWqjE u؝Z UqN|9HN[Qo 3uz04ꄴ:Qٴoi!PFf&M I4 kacm we 7S4R]7/yALPdan@ys3/C^SWZn bY´;l%fdu9(;QA6La`^˭UWΣˊ%=}2$a9rR;'I$>L%\BgajL>Wα4T-Qqjn]A}e9,]=ag\]UI(M@oXyq LFQ-ïǘ`d!m)TM"mmXDhRQ4߳~{85Q*iv69chh,-ɫ,N+ #"Wz-t6o0&5&Y@x,xy͕R|ii'Aie5s}uw\U-F1Qx{ k},444c"wD}ש9El軡)xTe]1Eyc;` 4s^Od$74aSXSM2no~w/'ő\+z,FњGzZ= ,)dǥ= _Zw(X[}=.iF%Fof# 5"1貟 wrϣϸ띵1{g9QƉ2c-^(0'dJ@=6J妏6ȿqZizc;^Z<cUe1- v~AHZe"v҆@Q>y?J*"iV2 G38u&# CC@K=>sf~m иI1hcJhSBe+ ۏ]`M84 =.CMWeQh鏡aA,p,smYKLMv -"Q3FT m^^ƭ|ihMYxNzi!g#S[2z9w , $#U+Vn &́o\~mI7kSÿ Wy7{j3[{ E?JQJoC|WeDMYiN= W^?\FOCI~e#\Έ^a䟬?:^9g,!Qe9Um?9&}[Fi(Dn(t̠~r4^n],]TZ?s!e=\lao˴O6z8὿W x]:FPZM/QfkmrMEYK Z >oPrVNDx~#D!ƑsIȉoźݱloGsbQll,;%Ƚ}%*+&g*:qyRytχJJmmeGDo>IR!z%I=ZQ fl- E)ƙx!sH!1Ik7pr0/)k7͈@9ΊsEl=n/yh6se1xBFTNGpf^.+*bYcЂ{fOt{]vsJ N$}?L٦,Q6_Ρ$mD)n6V>ftO*d&$sF!Fd~yw?Annne0&J^3qDc6l+!5UB{Jk@SK bZ~ՑݾF>&kiI OMML3hLe?t:v.`sD*F?pmH0A[cdMD&+HںzVwni],(e;m+LƗV*!,)5=rwv@+l,ػ^*hQUb1r]fmw5>ǢLdbj zY\QM4T#KEIuFaC7MbjC!Y]FNF_?kg]a.r&XZƴ%af(s֏VDYѡQRW{`塼Hr6~]`ݫ?L,@i7͈EYIq(ԦDSc==j3R LhϙZX!tGV[D|\wz8ڲo1}OK*;BW]";ND*,(ʹҖƤ ÁiF&Hz"@eXSҴ|a8qDױ\Ke"4|-] x[ 'OB$ZYb ;LW>DYO!$Ṷ̈̄d.뤸;+޽Ĭۻ.x0g{㮁C7GȊ=_ZVUU RLӈ HMobvi#Z˄4զ%ъZ FhO/yD稬 WnbcqU7ۻ硋 I>!_.U'8Q֥&$oz#& OZdscRҭK}C6gZ7!{a$FڤHnm8%RC1<9miԾDMdy\1޺ݜ)eSFF N^e7DO$}}ݝ&>zOzZ>N\hULgb(Jx67C\_-G["Eai%-ͱx0v47iPQJ__,Ыfg󓴤hCcr55o.=Ft'"6} OrxƖGпv誢2.N '{ZW韔( a!l}ï5d7##zcP_?WL3BNN1,M~W~'}0?;P47Xm>4N'W\ȴ݌)R{?ʚI]OE5OP7<6C{Bk{Ѐ R[;Qf=6J(6x,}cg/j3/szeE({+Xcbdp7?7n<'jtuâ)CY[iL&m? EQ z'6I@A^O~ɓ9"ٯHfn`g;Ţ(&6o+Q'{{%hL%LiCمZBHqE6N`Rg&jlUxm,>xt(Muv4QfAdu5.I򢮓.:(V.:@ѷD({lz4{8.r .bxv7֓g"%|0w`|ALڻԼXֶԱA{+! ZwTD*y4} 1ĸjZLڳY+K==C׬e(ɳd3GNuYĢm.śO>8.Ue?SaH'.8*!V8=odTHM5Z!~'%4eR#[+,9R鶐>`e}}𡉭~>bHX/9k ~9fFH1[q[K*gK)*gɷVW}22%7s0Mcއ& AZ'M.9%TӦOaX*n=%U[W,Qapwq~M#m}<\t KTu4@DH1MBʘ(~hׄ 8gK1E(Xd"Y@3\}j *Jaի?GH'L\˜F4QFr82Aw)Qf^;^q-F͇3F"e{xs(=jnjRI(#M'mRu)7 wQ?x˭Dn/5͘xݵgD2CEe#mwWWM}~>*cB/`~Nkw\5G?/DhmY MI۪ܠ}7.Kgf>eg]BuQvZ*_%3SUJu E$8Jޱ7w6 lrQ_n*X|!I_\ZϾ+c}pRfrF ~)<6}[;Ib\ IÚ-Ǚ&'ۏLCYR^Nq+G ]`iQg7ӱaoA[ټCZ>D7[1g$k^EETet93W05rM :%>eXH\AiOSrQ*Ii8/:STw)ef ǀ`i0ɭ }sS3|%u]04e'PY??P#od$&|ȿh:SoZj.U$ <1&2E(mm\J9;`QJNMFɰR (﹫qV&xv#JJak5lmL>m@uC CÔH9".I[eEqՄ~;ˡ7Wj :j[Ek `o zaXźRO$2?\D546u%ԗ?"7_9`G n$L/g DyExPF|57"^}lZ˥kW+YZ :{odÅb9RZfl*dd7`x'<0Y#{> ##M2Ğ㪩kk3ѽ\tU$D'ʺ4M$B.<`UOY,}5Aҝ\f捥:2j_qY9B$:|$ ͌Q3ڀ sK7Z{tz 7Ϊ57_Q(| q%䥮B0+5Gӗ([:c$<7EeqD+hp #[V^!.R!<{8ݙmI3fM/vudK22]4mV3)ټm_Y2UeT܊6Gu !6'5UJr*66?Lt)-iD5~>S`*ed[biCV ^v%m3x6OJ ~o6k:EƐjl9JQ%uH҇%?`OI1Ў42:JI} zafݧ@ /uB40҆aCC3>Zz,~}IԱX!N) p[,{DwM}Q}1*&~"};pzLI nH!AV:QÔWSC ETgG\B}u>sGUAvXa/E}|Ε.i!>_[Um3QF[wp|2#HL*G]Å P$e*4U{ׅ5u[ }ͱb;WU5ڵ #{>57n֔!<WM`{<#+:_[Rߵ3se9xm@`ϩK"yyPsUSPwDh5CA[M/~ %к:Lc/B{Ij/7aQ@2T'R:F;|3XNjD:S$d'St![4K4SfM:#DٲYq(eŅ\H5T,$9&M;Gi5Zl>3tCٙDE{xrt#i;8r>="R(%BvA3ѕ"%{>%BrdM֒ř "~Eԇ(>(:ܖM+Q捹[K;&70w򼱱g%ZڊP Ӏ: ^ʦ}z 97Jxԉ%߃`xDIH@UE% 00}o 4iK# BA)C^Ie姠V,(D(ss2Q8{TU݈U?]7k)iues|,3ސh ,Q6qhDͷ!<WMs{o61+B<9QƉ8o6jp20y,l6ɤaf$ɻaO2*3[_bФ02DV ]QQFf R;';rI GR9q!gI|=3Zk+iɘ<>c8mT.egL1bO7%*(ǝ▛MR=%WRL|KbHv$dM~s+:WRua5u 8r^bSNF(VNܼwVO4פhTl&1k.Q/W u%MW!ʨA78$D[9EH.l9zq&GeZ^(kQ&+1,,+dL9u^S!|[PPҲZ1t=LSTQU^Dِ6LqՄ({ ,ɠ~xz]mS%*,k~6䀽=>55Аs A^qE.F OWR}}e_ŠŒhmT䣘]"]I5\Sq}f&eRnMQ/_{|FK4s)QF{4ʒp!9Y(kB ɍZTsǺ%Y]gj(ʧo,QF[7CyWMs<ˉ2NuYTU߬9c#_mM^;G%JruDůΡ&2}ArŒFG!eX7%];8|W{ȅ*|GH]Mg>Hw sZLen}'Q( 4zW&bשDfB;#MJfыHN/`WtX&ӈ ](#QӤ..ff4wHѴ4nw,w!ݐ~Beb$?-!]=4rOATI{WZ rlE~`?Bx ^ݘ(~J#>J 3[}Ib? }$+i9uRQUAf`び,12Zw_b H;^hi7]TANVJQ>IsXPU7W;ReDM5 }m:ҍӓ(g\55H^N<rZ;؆dƥJO>#ʖwBd2C[E#mC3ZjnH/ %2bn #!5r(Jp;Ç~KcE릋$KF/?1-WUk4;N0 7ZAlGLʔ|.#/ {U1a$%lH}ɞ&Gbh'e'}U=1Ccɉ2N{ Ev\hZ62b%]'|oQ>}Ԭ||A𤡘ڤG}2:TS؍2 ʔ4#8v ']2U/dDɛTdFLT?VES=t,HUS r2E>ްFN04QqԷ72Î,sǴ@ ntVKC K( 08$eYpeSZ}1Ӕ3^zduz Ӓb_(&4oLK(S鄷& (`3,4*qtr Rx[a1Fu~IjD,"ӄ\:y%"QFG//DحN,P!LKJ@ ֚m$NX@歟vYy/ ʤdJ4}"nd0L^_6C?WQxr6Bq ' FgG456̘W躙OJi!~my &OM0};>0Jnod~c`t\Bedm__^^QTAPsGsQ\KǠ.cg"ԭc$f7>1ry!4KYuLqKHNk#%𤬲n?R5E?: 12*e쉽3˔n=L\([D5Qjj#ΫΎƉ0 EQ{M1'pfPD|\$ 4e zfDAi6Vq{c"`LTRWwL@rZ>ƒ>Uv?ll/d;mm+eWus{"](R amifb{{U8QƉ{unsK7q.)osfN  Gl?IŠ ZetӞX$$gM/.YQF%ZjkUDYiy%?˴9Y'ā?>dz$jqmSX/_%֓SXG"/*eTvf^!$3P0mT({0TFF.da#h"#7_^2)) H) #ILM4 AKRTH B|dߪBx_}69rZ@ğThgUP8>dJ _w6߄L!b?wH<P%/^{j i9M%br:#)ݵG2E%mMT"KB>8D5ƯD_PV Ĺ013>mL-[$6 Qc;avJМ2R`bng߅q0d )/ͥ/'h"WM}`^!9'xckCge;PȤ!puvg3D,94;(FH>vP[. >ʑf/HJe-fvɋlݡ=ce=_w>2C:Lڻ!k:H.?1f IDATxiL 9)e(kϼy: J]Ev # Z܄y1GdQF\KW[%&.dF &mD|DQFj)y:? v/;82?gIBJH) XX뷫.uo׶4XP!])@RET P IH$yyO?s;2yo<~Mm }+n^u}乕؞njLZb`<Dw.TJf!;towc5TĬ*?p/?%+Wןu9x/]Oݚ-κFyhsǎc 6i#kʥCnѝeFk+Uvԁr!l?irϐݲ?B/=?uur/һf*acmq*Yr]fv}o{|BW%`ݷ^ћE.j$uS߻C#nhD-gMӻj6[LUee\4&~ڶOxdu˼>j Q(kZpCסʶi@ԇWdei^w:3q2u܆aw%2[D)S[jBn32v â>yA{h)qL=hDzШ~ R~?"ԎmOv[/EJR ~-w=%J=ŢL[ynjGi(S_߫kө/yћ%SU iN`ZWBTeއ;l䟏9Wdr*%;?Eg=jZA /J,_[|=:P]&%"-ʔ(.*ONj׀{k?kTNIs4QQJM͎nUy6 PI7ulw2k_>vW_8zW$A3+nӌ-1fyVUmޢ>j9F^oU塾X^oب7}2w{w@skuxooTKQ)t=p't=cF ާPe^F?Suri;zڠ߷.w|Z;,)Suiu[2DY@@}Ȩ [6?R ƾ5(T{ꯑ]t ;_{2gXDT)Lݲ~TDԗ%/O|էeF=oO(SUUDJX޾]bTߒX²JlBn7Th>,Qf9F׷KqT^_rbVrV͓!`̓6˼Pㅾ̫QQO׷ْ/KD2-kZ z, ~+ukK}LJKiQQƤփ#J$^>~AJ"KUh{IҎA%ާjch2{-|nzʫ+h~&3kN/e}xN‡ަ>k5=,QVuuOM}=J.5QЯ=#/jK)dH*̫1^Ԏ>zRգKk(S}E# 6T(+뺺sk;j-r5>V;5ie^"m!eE Tq~Q\E~*{*JG)qQeeA>􇻷ÖbQe˞igRצBs%?oZޢY0cLT@d'ZNCL/YyTy9hG|6(T<^V_8yK ̱m3몿(AΕl9}娃F%?>& gڡ2)V2TO[e]WwYynʛ]JNxW7!c= e΁@ -uv: eTRQմ4:V=3еy[y-fά*Lxx&w˭wUGs(p[V 1+~{S wرed͘ mBYT_{Z~uC2{֠_Vhf}brmJowxd֌m+Z0jrOy\~j-_2DY@Zl(7%a48]tvs~z;*e[}pDf T~  @ (CU~._V.wq,]c}<9ݯ  @ @AQ(JuqeK} z̝5X90@@ @OQ(* &LIGZ&.M? @ @e9׏͇ˡvs` @ T QVU3Wg>]o8L?` @ @zeʜ=bJDY]9 @ @6D+4at(7&GQvאC @HQ(kscqvs` @ T QVU3uC_>wzn  @ @!ʪ*sF466&'}\^z{`ܶ @ @Zej;el|\:;;d lR;@K@ @2DY[֮['/}^~te9wAC_ܖb @ LDlV_=?ly/e՚!@_llb49t]Ż@ @ @T$(CEO>C#xtwۖb @ LDlV_=o<*%jDt՚ro(]]ٖn;l%=2cƌʏB @ eʯQY~}h2m`@+?~@ @@{@!*ReddD:DD ή.]  @ EQ(+k- @ @hk2DY[/`@ @"(Ch @ 5D0 @ @e@!ZK@ @ښ Q C @  ee%ځ @ @mMQ(k!@ @@Ye@ @ &(Cf @ @,2DYYkv @ @@[@!z3x@ @ PDD; @ @ em< @ @( QVZ@ @ e^  @ EQ(+k- @ @hk2DY[/`@ @"(Ch @ 5D0 @ @e@!ZK@ @ښ Q C @ (qq?VwES?O?N~?f\>wŔv @ @ڐ@(5C:#gyss-ۦS=EedV+ìCZc @ @G2+ 6#ҋA @ V(.lY e~6k, QuA_ @ @`(t*3˨Qf뒙e jM̈́!@ @@ je^M:ʨQQfѧs5QSAK{, @ @@/"cZ,m"efMv@ @:%̮YxK#vLkiL]8 @ @`ТnQzuvneQo `dl-nf@ @j!e03;\Zi6DYD)XZ Z#=%3H4TUòeyŐMփ2xC @ v!(H?]&l K䩋)M~kۡ%I>)llzv]_9l @ eD^,hķO[WJ @3A­$>^;A#[@ @hG2DY; 7]%K^g,;NxrO}nٻ\ch,;&d%d篿~*a @ P#) ʴ SNqp%܍?}QV%~z<>dt\>v1׆!@ @hGDW_UM)S?4gzL_S̻o鐎/p\7_jR[}w9v\5/yδgC <胲gwV2m ULm?gn響@8oR';>YYƕyv-yky#>)}CVp>v~Rzgo:@f{H/}ľ6xN4} 8(==2Gׯ^9qXNfLck{Z/ vF7U]/C> 49GA߹fh.N锇X_>@ @re^d?6S?3_rtL 3kb3]r.en\WȰͭgΓ}z^}(#*G~\6.]"2j]zTGmxA$3ztN ?$Cߥ铽XzWUki2}z~!?[ ʉ}igE @ *VY1ddze9DYY6&ko@nV.%Fi6JϼBZuŲv7dAGϏl(,i/]"=)3c~/ʪ_^!enM3~nﳮ4RFZetÐl}ҿ6'^/[dӏTu Ɋȼ[E-4"ʞ[ZNYteh=rOAm^ @ 0 DE(υkU4,Q~m3"e[Qۻv)Hg_MĔIjUӧ}]]#~We`Gy"yfݼY2a?Ӟ߸iS nVGIC;;:?LEm"~AIT ؘI__Ι+ʶoK [ruM5/>uF,iD-_VN:\+T7@ @ REMǴ"[̿E,(.ܟVQ6+ʶ׏xLrȽ)$Fh e/Yp">mZ켑Yz:L[u[^6CxѲ{?-ӦMf%ƴtoVuJv92}`Iƍ?"C8tqA;eJ,wrCݶ[Β˴l @j'LQkR ]T sw 2s'qˠ'2 KmÜ@NKpEX,[l $wvˇޢQV,eU?9>.KoN=s³J=JlOy~s(.XQ6ׁ)}+%~Nmk cC *%fը([n<2ٸi`5c0& !@ @2Yf"L/<(b(F}}х_i-D[$<5gZQ/ +DIdC'y%2mϫ(eke8\trZ߾qY{Ǎ3wgu5_ৗnȡ@z+T?C6&/VE&4^n @ 0u4".eƂ"ш2D^~1e ~Q(LY}o/~DM~uϑV^Keٸ*lec6A-}n|>^z{/T_&*n\x@ @mMiLGYdI?#b;VzrQfܙ^9wE~eᩮyIW{?-3{Ms'553Ȯ{~LaBsUA֭__x3g($I,< @ IK Qf.Lb)2+5L2D٤]+ʆW.:ܷ~ӻ Sݝ3e_p2/u8t,5eSDؘADt9 @!lQg.2mȼH"ʒE$K( R45):bS(SK82m˞_/Zyu;{vLOehϒ&m7ç}LI/) Qv޸Y6k @ @%$ldZbVxϙAI\6$B;]vvtR/e]ou^Qr\]Yqٺ?EfcU=sv1]‡ >xlc MߔY/9"t_8ߴQVhFEٝ~T2q|yq:Gi @ nZ%ʬDK(;}хXD|DYRͲ(SL(m6 ]lLoƧn^?:NVVy+odfd r GwӇ>+_b*}Jƾm]?uog'?"ʊ_'S߻?)3_;~È[^yGB @@[e֘"k9R"9NYx]֬aQDok 9߈(ٸQ.yD~i3d;*}yJ~f~n+$;}3HծO~LYu%1x뛷ߴi<~ɲ::;oN2yA @@("1Q5/͍ %ttw%] [E[74M"bX81#䤳CRl  @&?(󢼬3ٖN~q<3d]ٔ 2;zQ(+B69$?<9:Z@ @hG2+@(3fK)G~z^mGd _*yf V[ȿ{l9g .[90@ @hDH.W ,e(sҌS<)G1gC \|ou^B6/S6;h2~@ @H&DYRWz)͹Fn^Q$}?D1^?;bj!Fl6+Ȇ 2kp@׌S,&!@ L>(3;RHJ_x'@ @&ϜPM2 ʜQQf"5lt#bhs񈲦2'SdڲeFUMsMLJm3 'd[ @ Te~eH%$3RM,Ezbc&P҉(ӞW:;Xs bVM]{۽Sdа貱1wNvq^% @ @@L9lMha?2̋,Z}oeΎ~Q)ʌSJ/ҟ'罢vZU2lhhH6mެ>b|қdttLG1O5\ @ @@%2'2Zؿ&Q=,863(ͣ:jnttT]|<`\S @ @d"2ND2AԈP*fBIR5HD_uQ.ѱ197lŠ|x`2  @ @S@(ZF#ʬD3mp}l `ktBDi2Gٚf8 29#UzwMrKdicep @ @ |[Wa+iKmC̞$3EL+2?F2g󀪋,w=̞1MDY;3 @ @&2f1`A=Qf;`j&Himf bF7@U{2:@ @ lDS:)̯혎J+YوH2.i5˒E{>ۯaVuQv?̘/_;.h @ L9J5ȌS-Aed~-2}+kYO[?E95\Q*o[fYEvCE~be @ @BwR-"ȢOٴbs/yXDJg'.V37R2iW̪[z@~;4C^˛N5s6 @ @*Ej'lY&a&QVieΗUek֭.Qeg\q:Bc/mdZ2m/ҶRQVU @ @@ D!wô̮^/}Vk!^(StK\)#. @ @@ XQf@#dpi6+~"Z @ TϹʫ+W]z̳`z7KORLK2+ܟECD_"*F @ @h (sR(}e/!cI̞W@iUWAQO@ @ j9Wi]&]6ZL+O@21/e\  @ +lͰz.O+ʌrv'meH2^^%UK~ @ @@5 xڥi:LMF9ÑDY b,~ߗ`.IOO4闟R/D @ @h /-ۙ2#ҦYzzҘe2 )Kaƶ~i@f  @ @*#ʂhiNKtd#e 1^yE]-(1{?8>}KDYU( @ @!eAV\ [zZIt7,8?&qj̊(EXBhu_"Z @ T@ tΥM4˹viea1fEZ(,MYa4uI׈qA @ ]gŴ(ޏOIei9udR}̦ZZQ3?^֛~(kj @ @ Pa(;`KgYsV 3b,Ue^+_"*J @ @h#M RLǦO*ʬNR=6}u#. @ @@e |kvUL?ww蹭:/e/M!3d˲OH  @ @|"^4 3agm]SՙWeKvYIEmM4U(kb@ @ Pe(w{gɻ[f폈3?,Mi'K;2.<*/T@ @M]wT7+ʬʍ&NXHPߋ"t"QЮY_cG5{> @ @6( 7;Yz)V7'Bλwâ0_MOEZ?qKhQ'C @ @h*λNK&+Xfw4'ame<%)_F#ʚh @ T@HiU/μ(" /[`i,3_4ӤwcN[}kB @ P"qVdK/S:DYO \f(s. QuF @ @\QVkKΊ2W_h b̓b(3%>(je @ @rQVd6v>/5$1#d.-mJ ^h]i4 @ @@% ^p}X%b,XT.m=2}t,ճ(3+,j-oH]wFwWB1(@ @ ,g] /,\?) SK.c9Of~+MihYVOQs_ǼL̛\@ @ PIODYX%~*YrT 8cc9 kK!@ @*AG7!^ߦ\Z)oEY"^72ͼMʐeX  @ 4@$MiIMV>(Lsr[1VFTYUA.LnE@ @ P5~w?>d &f,b6%y 1>]Ge?2{-@ @`" L|DHǙO9"9ՏV^zbԤǎ:pDχW]χ2Gۛ߭eQ8bKߵ5DFӌ;P?;1zgGQx\X ol.c"E"i2#"r2NJZ]dac#d#RP`w'xwj@WȭXg $%}g# t=*[bmd6Q򓈯 @0|QJ8ȯ(6T):AEk?M9 : 94>GӓFvȬ K2*A:dy)K*_kQfEZeF[IZy[U,\da8|wF~H98{g 3sjZ4ՠ8-hńX+"Z1D_ @Kyw1kA"\ \$z̜>-{5&3A木yWQiA{Z|'Ih0pX0Yd9je. )R,8h2 /K)͈*SHu G՘J0ò<z,p*rټʚ"Bfk23/͢ &^@Kj !6__>O @ڏ@Y勫1淑71{rB7PdW3zLwY Ȉ0Jt '<6yy֔r3JH\:ױdʥ2_|Sџl1-1[czep:cf?@%s/TL *77_\wFř3xu:VH7#8@ @VҪӎoJV!fۨW ! 9$m\j 1;2W5Χdc/jdM{E1-OQբL5nQeUeiܢhY42yޙ~A&I5xZfpR8,`gf3RHݣi&*iJXYw@  eU-iƴ2#vcɝf2s.` sǂÂ̜>ҟn=$Y(QVjm2 g2RL+\Sw2xeꕙiE,2*3Dt, r-&BX*Ӥym%%*ULʉTy@ @%leg^X'čZueSchY~he~/*Ȃqf~lK2)=2qʹMξ 1&U扖R03Z- ԲfH,5,˼yư{r묙"âh\hnXuߟ=,1P@KhiTk @K1Պ)R5˯q'OYiibL`$I(oOL(3-#cu狰zd^C[s;w: USx`N6JṵH2J81A$SejGy#tj{oNXcA=2YOɍJ[׾fqsDx*(wKjT+2C[ @@(jJZ;ZTH.f(cګ$E=۰ h$ZNanΎkC)1Sr$ę("}'Fs%֐riXD%˻`9LXz2hˊ*3Q,9wZ(E1- s6?p",ff%μ]}ȩ\TT+:Zku@ LR$UF@+:B2̞[sĐ;c6*ȼN|aZIzBt2,s.Xn]Za DzEgoRhNtVc`"KMVcdY0Y+gY4%ӾTc&nZ0Ɋ$suU) t'EZ>h @&deSՔY+cI޿Y\0MDBzZVF^΋$Ey}7S]X pҼLd^GT-?q|7FD^Rj>ϦcR,PmY4Y}1Jg XFNs8/& ",*̂}NDDRL%R#JUeH>*s#v @ )CN>u/w4)-} ""͐tcX1Gy5P#Qrnc0!7j+*ς@3#TʤJod|"in|wl27]k6fǒ49c8{';,6eҮA/s| *ӿq[QezD^̌!K΍=׆}QWD܂Gɳ6!kBiI|j( @  4S~C~2̶;27:.-,qPk ɏxH13' `Ӆڲi%өYc,(:v^dޱ̗*Fn9,MYQe 9#ݲ2O%2fJ]XAX^ 9Qfޘ7 X\yKڛs> Yë  @ "Pj6n9GcQe8"Ò>,*|Oe|XޕZdCK2w,#<06̟M$s ɁKz$ 1ݜoɢ,.5ק|&{c3݄je~[-1,ԿRGt VoGvjf#![zܪG*ww{= Lnh @ IY 1[nd 74bId5Gixiov 1',hzGGsqe{m$Yh8$Yt^%דpJx,()Ev^}S0aB򨵸oeA =Aht8:~z]-E -:тcEcrXFcx@ @S@jė#GbQ@EO ݍֲxr)!?"N(2` ={.uΖI2|b$3C/x{;"dQi`NܢK93j6̪^gvlXP?AV,&ȯP+B Y{:Л]I)1AkY)fA$+)ς $~l4$ʔbjsy61B @S@pjDAaUhJrYqE"*˵2ߌ)1<#ȼƢcaxT>Ό$fEv"2%׫ߔUzqk5T2Gʈ*MM4E ˲hݯZw 5)!+,`Jtſ32zR(6uEE2TS%PU8|@ @IΨ첝4>3H 5n\9f/cBuǼ Po39W0liZHa[DGB,.YXGET4߹,|#<a,q1*3&=ڜ$Ycʒ-[% e, @ $j3kGJPq%TkٴzhksOgȼ©d0ds5^P ; DYY$ Nvk%E}Xk\Y bx 1o~0VtL}h0Ekqw Ҧ`$blY{g#*v!o@ @j*Sh@|*\nR2ӢŲ'PKZn)E;)oԗfiO.zGE_~$?H2bZX].^ܨH4":QRO֛5&KD)"Y5^WE4-i^'!wk4?\ш9Noa>ޙFߗ%Ϣ-dH2UXKk]L5 $@ @e($:,H#ˎXjI Jq%&efڈ wM4F>wN$-1&MWu0ۤtK}\8,-nPWʥe~,R{LDHES ueFcq7(0=e.;j1g@Ee{ܷ1wމX[|iiޙ|G; > VEڀ @&PLV5¨ PZ5T_c.*ƜB*ޒjY,xxDL(Fuy)uʲR-]9L'8CB0% +}wKg1f=^\c.? gK}~񯨄%S]P}\YFdS$4Na 23"s e^5 `ȱ41|?)b)[巓#jpOeD5aù @ڝ@!e'vdF刱΋/%SE&*LCnZf(,6wg(?o+F$Yk$MB$GNʼn$ _Z7pAR`@(SLLKV$JM݋f!X{4Yf&wJ_̐e>C e^ˌ̤ȱ4f'̣{7lWGBR-d^M>>(A· @%P뤘RY+mŌIo]QcAO,K4ˈ3n)iyyZz$lzfdiL͵gd4;"72t˔d}@'Vh MXݍ "Ƽ5?,:/I "Dչ|MO(C2sp} ˂)ظbbm0,B"%RSGX;sN1FEęn?X#ueTc+(ϱ-g @ L"k_ll9}g<YW4,}7M7ћ~?1آQbCwzQd^ {GEe0s15jcRy1E ]Bd48?!TSь#r<)U,F,YqxC5ˌE mTX#Qp^)~% 35w} ?S *rcg|us @ )JUO:N"bI[NX  zعezܱ4rW4ydZz'(6Ifm/|x噿@||VVvHDi%8]f+*4|Yf)AWDT2g 3>.BؗoFY5VD~'!kK.L+A @@q|=)X7S3W֓έEb[yAAZXj=2on[sCf~,J2o%3;zKݘeFQXɻGrϏ, >1e9 ]ak)̼Ir,5[b2lPLbzePx*$>brC @hVLʐ^ZT䎥̢R̗$vy锑FUs:sl\NDXh p:+Zy,iIQf9ehqמ麛dnJe?2zk(3ꓙ##̢ǘ$X' `}Q弥gᩅś{a3)seU!PYr-M?9(@ @(@Y!K/l5rZBti,,h3ŗ7"ǘZ;>2lٍZcM$k$%k ) L=Jdžw4J 쌙/Ѳ"˼eOf饥bF Pԙf»ez̾TRR̿x-gyy}%͢tE3s @  ZyVym0ZpDZD:gEَye sZwb~KzXvbt.i R{tzM0pi,p/ t<=b+Wv15u2sOᘞ9ue;bΈ\neXDv㯹.;akeƯH5+OM/otzM}L,K3sO5& X(b,ip'G`z$Fe=2㚜;[^ psK29vb#c2mT\!S$*˷5IZqsVGne2`*ߝWt E]#EeX\seI&5(ϒsETAYTZ(܊|.p  @ #P@pET+`)Ōlqn9*t#I5=\̛?δt:R'B dI$If?CD' IENDB`datatype99-1.6.4/images/suggestion.png000066400000000000000000002046061440313234400176670ustar00rootroot00000000000000PNG  IHDRo\dsBIT|dtEXtSoftwaregnome-screenshot>-tEXtCreation TimeSun 08 May 2022 11:24:36 PM +06Nx IDATx{p}H$D$ċHYEQHǺEbXqk5k)ٕϩ㍳۸۞ɬ3;gsfiN:7v+8R*J"YwiA A @ $M$HFPf4yy ?>߲[HZXL oEDDDDDDDDDҐ[4VDDDDDDDDD$ )IC oEDDDDDDDDDҐ[4VDDDDDDDDD$ )IC oEDDDDDDDDDҐ[4VDDDDDDDDD$ {= v(|({Gt"438bCU`11UoGyNk x;iG$V>``#%>2W}(`e7{Hw /y) )Ym|rCuGŽy8`$q/O\!ɒ8Ma0`̶SQn3 mk=-h2lji5)|-n,/""""""3)} 9x!ɯUĒ-WNl;l'G8 *%g02P(H Jx!ڎ0(ڰs|zr~mB]*a~ZK?sa[\=XIͣ d͵1_WyNg/Zy8n,Kb#4:fV΅!XCOos/Ad*+0%E"/7A K~T/iαjuS\>v} ;'SVo)i}?m~qVlwzs0QsI-j9;@8b&VK=TmɞFM9p9x FMvPjK9H n7u9$bթ{Ά 88;{܄>."VOi]#6ԽVq9yHC&nF<1̧lX76R\VlݜL1S&uLճtńjfU ,+cuxb *6Sbkx=Ǯꕳku)M5n%{!HvLXkhaMQo]'tPD^v*wO>w2MDDDDDDPڅٴnt]PCKݒMq׍N'=)z'f/ 2_r-I~`bPqcثzr{.1v ;j}.H Ey{v ^zEeϖ]\OO5s!6'b3 n== o23A;Br+4fR?g8Yzz20-\[EN`?NFGVE!=Xo1vγstkixer(C%յMD 8;EF= 3*N3,v +L aaQ%Bf|RVN\ao]IL!">^#\|G[/S>csfrl'k {=XWoM6I\Xq3DؾyPoӡx# H}{O1W@ k 8 E 97Md}ERO;M/O*"#2uAt^KF2G^#SΏh{?׶ yM7mcPcε#3\^JXSG{3/'Ͼ(2\DDDDDDSxYfdYC1C&ˌe YW~O5[gV.ȉPz5ch}=\?˷?MUT[5ol=OCn}G^W'N:~38sǃLr>e%!'ik(Eisv]M,0Zʍ;($k\u" WSν:y`D=)/zpW8ƆYufk]#n>@-UϽJpV٫)CF֠;/s r)llvz-|5IܟW9!bE}acʪE㸃i;@_p3 ʉ4?*fӃĚoö3{7_ g?~Ɲ$q=*J3O߇\8xP׻?^FcA{dlPY԰/af1_/SW7cLx"AM^&0-k{?9ȅ =uOCowczJvQ"sz7kI o4d}\O ˟Gj7^7W=MR3RCYS.q컛9@.bIkgUr_UNaٵ[/kqy?+Ϧ5۩N.Maz/77~$5Yh^;!z8׻Suߪ} iJɷrSIKo:+c;/qsWZaӟ~m>lx_y~n4n׽Hk^2gζS x~<͔oyCuB4]-oLFFO1K|-ggG'L-2+ᖽt'{!Dcf,[_gv 4}}("bwp35Uc5CpiMXop]#(s9Y.J*dZw f`[+Ѻ?޹>|#t= k}ۿ۞}Y.u|`<ʰ*ECЬ=̫b4 2c~1%wȽf neox1Qqc]W 6t=}gŃll;dUMiIE~1@w?|6aOg4SĬZ1l:F&2t#}v Yn7SqjJ"6wmW$ȱobNN `lg ;Pl[_'G"M%O+ CeNԾ#Zɷ/ά1YkMd1cOrF|)*J]lL);ynnoWV61eǫ1ɾzFjR;7xן֓0](4>Yq3y]7tLZR+ZJR- fLʄiRtQiAx`:DOw.G<6rCxLEm?CkSSWy.1<6 +{imqF+´]LtMI`5彼fvEďj3m w>©֛n}ǎo}=v|;~k|񋈈<(6fXi\z݃PZe&L: R\^d$O`kn9Kiy1QWLNl%r,p7މ<Ɠ)mB- Ǹ/e'>]eufrP5g[ -fYgRۊ!;[ gMR]yDxʰY^~Uj(@g<>e@ۡ 캧RO06H6ktF!( }o=l"lbzr71 2i8FSSK;/pe'eudèwA}a2) 9}_ Sc/}A߼﫬],?| [y ~~)r=v8^f2"6SC ؛dҧ_a辰 oG{նSo&@Cx27!L}΃h6=O| swm.&`p>K""""""K%{70_zes?_!/96  ٴTNdu1k0\es-:,:F; b~˜?35yfw|ʼA_m.u=ENU0o[  u R} ݳ$u%#9nQW3 -8Xs-j g;9 VRo?c𹬤rc-Enqch-ay*kI}]ⷌVNԒop73M}\mZsD_3[h^t=41\OI.6b1VDDDDDd.K6˓I~FڄtF'LLbY~4~{hfWXijtf5'?a¾q'/GpAձ)]g;\ΞlI p'TrvfWϞhCbkÂZĜ)i庳7~Fa XC-EMwK^X,/uJK| TͬMw^6'{6rqv9y5_es? }'w( d9L @#G Kmz].Dc}!9kj=9 *eO`+IbXFm=E94y88x~rߜ W+O`y\ç_fݬn/_eÓ($Y% W& |1sFʄ )5 S2g߮ir$Ke%9_\$_-~ Ms·ʚcoq->ٞbiɾ{q֧6!?$~sX_;tj r~ȹI)yr7V #\|{DuwvͷDͰnϵ,ò ۓΖADDDDDd6a ̪"wbAf>4iKbݣPl{ֲ݃c2Q\pS)[3;:>NYmaȌwt]LQ~hj^reR0W$툰|Z2}(0rj IDATUO&/7BōG9XExptqTPյx&>Cɷ@I߾_ubp^oWĪ+\E|n"܌{'g?fl'#ŔBef;+͊9r{vO>p?6g/!ii` J,py>4Qs%"2 1iLP^B r-یl!O)+ɞ<2XR:CeRZz!L/Ud siGC1}N'eofEu7~nN5j;9saºq} F vF09ŋ46j{i;6RIqNn&n*U7SdwVڎn;Ơ7D;k/޽Fa-f 81=i65q4?Kz%5Z2@wrfUe러Kf,5ߤfeն%4nv7>1tm 3kg|kOf}gɥ͢{ momA(Kq^:3i%_p~ngiFN$`La6T(Ƿg|:~s8~1[x mq?hڶ0Rlzc,ؾu"S]H/oxZZ2a&IK۬oSŦb?sش h0:{&Kjy=xG0![\[QIW^t?Y< ijn2:[e_W=D)qB/ \}8WgHƗX|4?(l tu8)lbw_z lfSs14P>K'Yq7}sMt/Q2$5Q ^d3zlfY;͔0b4߱})Wɰ̔~5 -ƫMl^@Ǿ*U)y'ddE.ӶM+n|Bk)Ý\nnĽ .l /%6=M%{5%;_c sĭf;_tWx>p CdfsFd!o̱ڱŤ?eIȳRXopgSR}6f&~=w;=8 EX;$i0&rl ,jhSz;xx6~? )nNլvꦧlþ^›SOl&""""""zinhXÆ5= Y10װ_FDDDDDDdxpZȢu쥵k쎡wBUDDDDDDSJ5Q""r|5z|!b>7~F6>O&# oED6&>Gvݷy|gO&"""""")T!`y5Eu;UVpUHI0r,}ƒ'n- DDDDDDDDDDd*MX&"""""""""ފ!""""""""""iHᭈHRx+"""""""""ފ!""""""""""iHᭈHRx+"""""""""ފ!""""""""""iHᭈHRx+"""""""""ފ!b 7nd#4eIJedey""""""""""VڄHO:\|эoh$zZ]ƣ v233EDDDDDDDDDipB{vٲ۱XvG#?iSyV*֒fl}]8.w9̅3mlVȣ']%߰s~y{/\Z/uc.R6m lh6G*ɚC&eˠ`"FDDDDDDDDDXr-2&g0\ """""""""2%| 'n߭<\x;8c8fddPVn]}K.BՏTb4q4""""""""""ƒ o;]f=d~ /\ #ch4,DDDDDDDDDD%G7b,DDDDDDDDDDoQ}phGWQp"JDDDDDDDDDJ6xxM?ȣ6DT,3,DDDDDDDDDD oc'~}!VYٴu=˖-[䑉i޺?lwJe,Pp+"""""""""iޞ=JEl\=i7L{*RѦsv:3_x !sG%"""""""""r{]7hwM2rLۜ+(c]ݪ{94.mp(2~_y=Zba oEDDDDDDDDVmDDDDDDDDDDd̲[=J""""""""""iHᭈHRx+"""""""""ފ!""""""""""iHᭈHRx+"""""""""ފ!""""""""""iHᭈHRx+"""""""""ފ!""""""""""iHᭈHRx+""""""""" =F{ B~bHAFa0 oĊ-,7.ƌ\;@J*y@K [DgwP^y0]xD 9̰ohSŌE,(]rڐ>+hȠ2*3{HK# RV춧ߗV9˱֭,[+l &S"VfY["GDDDDDDDHf˖M\z#a<rCoo@ FK |$c~b xn_EDDDDDDDdvi& n{d9YFW-0{otH|4oשN.㬝vF[?7z- KңW?.+O|E9r2 / 80|2D,ȧ5ƈO <c9NmfQ%y0!0৷}@B=cاWaΟFxSQ>I*3fԹ%n0<MZϏboLY pC6ۭ|\ xb`ȦdKt9Doxߕmov?^\M݂ P~Mv_;3߳ n+(/ɯ$``25e-]~s25/=WPs~}^2j,X _lXԵrx#>.|8y?lv^!̜<*bC$#^.qB0LJ=T?7- -TNyZ_ Aٞ-Hto.VBF7 4ίԺaD`uu!]ȵ*Dc(q>wi0NREe8꼎sh #}|t>~f i3[5m~ay|鸘#ЍAn1¥E""""""""mk\.;8f lzKc˱QB>7ޫD0z}G)M`h֖OFشu"r%V3]9绸3k&1=D4d.n4y"""""""">iNg2XۊbF!9ݬ(RQ98쁓"@8Ggk}D:85[cԖ\} ʾ6ck /Y]|"^ 1858oY8g۸92hd24̝:e8y>ǿnQBdY m&ͦn"E"3f;~i}dV0up DӋ=W9oNUod F߱slyfuM q< &򧆳=FzP!K"7Qݷ[ۊə8ŖOD5K0}NVeb+gom&4eBBۆ}~|O(-x#^\ dyWuTw\Qz]0Ph%t.D+0r?}:˴r o6!/<}Z~i#?;6j+N]x*Y|x.Qpy_59IGo9:`a^'m?}\A,K %LfO/;5N{wb! YX&+3>1݉}`3yh*_1Gp~8@ #?73ܛMh|Pt,(-R\dNm'Ag/z#Db!F#xoeQhgfzb![d)z( 6k Ljx*Vg6#?nKAq oiv7'XT9WYN':D2c)"7#7hi3'?q g9$*vvsb l"l (C#]_..qSm+0Ϲd^bDdbg,}pEDDDDDDD^h";'X:t5q~ /z\gh qVRƺb7.2Wi%7%Bo^~1۞+2W1g"*;/OruroM{U{jnsߝW@3G/4mO8{hrL]d{^~k LemeƇP^ƺ#38>gp,:٬~ڔt/$mwuHDDDDDDDDfӂ`ss]T)o`6qu'MZNΜXKSX;`/u5CT{2:z>^>HfHQAk[F3S^j>z;hrv#D43H23I ^~wxz 䳬֚ EDDDDDDDB36!gb܎7Zq1,]Iꜫz^DLwd%m"ҖFU+6Bve=00Y}J,.2xƕEҌR@6?Lr2go""""""""W oSZH]hOWg?`Q !99,вH}boMy$Oohh5_ϋy,"38 i FffR*O2:~v?pWKs]ȼy/ m?xE ZJ\vm,9(K}̜hmeYͫ#e!xm( cפSV Kz1 ٰ X-v?7EXQs]\HᭈHRx+"""""""""$>>plː+y&xqҰ}yh楓^ҽ)Z?uA oYlw[DuSQu$~C(W kA&E^]ecA,/P&""""""""2uurx @T>9%ɕlc[V5u^Wu᫼ fvUu0yV! M.cANV6P)p*OԲDæ#Wz1Lv,{]e wzql6k͙,3Mڀ ``_YY6m̦=>DDDDDDDDDޞ?GG,[ME=e6Ų؊ gM'' FH&7 R2?`hÚ-U< `-f 1yZyol׏Pܱ׷6Ҧ1fVzIG,}[>la=A-}-;mVND!8~/q1.̝"MJ^6EN(L/Mk#?vt]UI g&n*Idr𴳦IV[ 8?b̳sum nTŶ~oL{{OQŬbԟ;EDDDDDDD"yQ]u y[g6nGqcY4r8Xٞ twhJJlWB?M4o%cS<Ɏ6Ws<.vխ!xhKlrziƝđ:{kz!+o׳˹\08u5ȽpұޯT9V1mEzDDDDDDDD浈jIMKfR%6rThi?njLDRv v7h9xzeINPs6űic: xv(uNm3N-1m7t0ݷz/@6$qC],]SwhkuߊU%"ӧfXW2i|&2# W(uLT0al) eW[[y7pڐʎ(}B6 ݎzo^S7i )4Mb#W<4?UlP^OY $3qe14qx""""""""W o{{yY$k2LlG>J>>,ZllbklF} Zz&)q6 1+( ;Csxl)B`mIpͲR;X7Ɖf DmcIe剈\)"nᏏ5H`d}q:Fn)LU ]uk(3_6򡙲l*q/!Z,oy3yԳkp1+SPbLK/@Z0f6i͡(<+ODͮ6N$Ik0')2yY`bKq4n*'nB,w]9Ў)kc܅.:γ~p9ufEFF_xPvPL\sqz 0VnOC36OLN9H*&;Kޞ^?XcIjMNEDDDDDDDBy qigC ΆIo0 uϖKY3ّWMeM\NJix%IadUI.YÛɶiMmRIpyk7sm2E(~P'}l3EDDDDDDD摈oE F6ciˎv ّ? -a.󛲾9+KrX6}[GI5Vzs-nfd}q*FYٳj;|C݃UW c&"8#k&ݮڦY@A{bl4{T8(<=?9n!JRmCmfņTOs__zXvc 45v찜 t;ޟQ#ILԗ`qc!OmKZu=#gvngn)"""""""Qy+Wh6=ivMfvoR:x`eǴgʎfdq'gњ] tH/Stsxc/6*^!H0ɵ,qpu?=tvP;1# 3Yi $_çgL""""""""B,֜b`BM1S`W17ElY4Ŏ؉Y4eKgW46Y0}̍y.Z=e@ Mӧ=SRV;(6fcsI8z"4p:V׭cy+2kԼW+iܷt3e/gi "cͺjN=5yl^uފDFU- ~^+bv[ޜ.TVyV`70V誋v1vnBSX=u"3v̅:X>i^Wǜ1&rs4Tj*DDDDDDDDf[0$FQ@V[ Sdq X6n EL\,yl[|q3xͩl*'"nbEDDDDDDD$> e"""""""""W-X&"""""""""ފD """"""""""HᭈHRx+"""""""""ފD """"""""""HᭈHRx+"""""""""ފD \ z[[%`,ʸxߥҍ{_ ekKG4]! .V&?('Պ*R '9xj\;D/@2j0oS3Ed>|c8J]_f>tD%,ʝ&۷.J8)VDDDDd^)oughv̎hpLM(ywĮ9UfS-s]Ȕq3p/v!n'sa-w9/3%18%ǩr6O>HDDDDD^D"sKK8}ys\\MLZn?#"IW?#]4n%..ol2KhDDDDDdDlxtY&)np+#Ӷ,Nr:'4h&Lɩs7piLzk~*h$cBkXnaڻ>NVS {mLV6;N`FJ=@4ּ,&n:i!\{&;6Pbd?Cz./;A LIө5ry:tCtR6 kIݸKF̤{<^wv/}dd@u[I˚ yՄ2n s .Fj^01f"ud,Ox/݇w<ÂbSIXkI'P>:^ fTt')_~bo./ 1MdRTɦL좼j8=A#iVl\1׽Î6ֵQAL\,VK2 NSu~E `Ig[a2f{ ʝtziKƖv,b77y-^{k F H/-@lXz=M}4a5y*Gb>DDDDD䲋va%:O.c@9r?7̈́λ!>[l{/^cc(/>l#|[,.|DH/eGxZkuʁho=S;qAhiPV]cK/ υ|lFWq l9IcgKB _;Nkp>7+?yYm_ ,( #'~C:Ϋon.Mv~ɟ~ k?&*?,K.8݋wOhta0z[m%o8/\By5$xKȟ$㙗+)GKk'5zwcAp{ԾN^PYSϋ޹ǖO}owj8ͦxj+}g`e|ieO뙉!v=\}+מ؞j/E;.*kj*駙*W^"""""rI˨Fdvh9J?V,yK氖V>zzb(3T ZN;}T]yۄ ϖ/d衫8NBh~*Ω,iHrE~/ZϏ'PWS5M8CҳZ;:y*6=+%Yc~Z\_DnKl 0|0K2"!5(N;I_c}\v?ݻC0]Â$-&Ct56sn3G}Oᣛ'Oߥb *LOQz}Aszسۉ~|- ), @_g3!?l>1c5 0x e1&]jԋG t[*Xn?t:h1qxwNjnj~h \>S ր5Z@?3X μs> nI~$_~.":k8>jNp oE8Msn ɶ;Cmt:=>-?E'K_oqC[9_ni? Ͻ>~߬X_o#4qXUC1P:y%PT86EI)\ G_ůe/ّ8"LU<}.bK=9rnXk|s(bO{p6O8?h^si3,#bQhQN˓4u'iSv߆:.H,+kX|j> *lC=0og7Gto= ܯF[Oܻ- @53]9k0x0qs3x)-kϤ Fr $gQ ~w`kGMnђ1gϰazgWCVo;^2ƃ/škYxdơ -¹s^0ʚ\RjJ̎>o;kǙ'隝I;oü|iKf1y;kȋ'@)`w~ơ+(6n NN6fWgKzudi/^j'0w. R/vhrs5]Mk,`bR2t8Nf%ii )ĥ+!/qf&nnw:Q fJ`:id/ xlBgW7SDObGuz#fYT?L[u~R1rPk;L6\p p͞?`2V_֚ 5QbfH,W7vutbm``cq2|FK0:40OMƄ*d8lnնnpUŎ!j$ q5Swz~fxzjF$SF 8:u{] &L5\x Aĕ9xKVRVG|FuhK#w1G@1? rQ0 ƿ|$N}KeA>7QGqmq)?ٳ] UN=Π\|# ̓0 wwޚA38Ӥؑ-|7~1DT 3rص1i|>/CMwGf H_wm3u?{XP\!{`$:%Z!cyJ$"l61kXf>ÏU]i|!#LTؔ?6"O{"V&4.fMR>{Ύr0dՅD(@%8sqLYp$0NF5wG-f 8..& ?g!~wӴ-ڪ W^Mo|߱Lл|DүU_ ?~|d!$6/fSV2f]T}1=#&:{t"QȐHĤ O0qÖb?#3,[1E.mN! œ.FC< .o M\a xc?5V*bs=^~M0D(V PQ3 '&k+lN^QNq<Շ̣`?` ѵz5W Y|,pvk x,w+""""ݑq,j`+iq@bH1m-HFeƄ$vl=ΎI+n&b E%|ND*:e.bI|˾ Ǐ^54ᄋl11jgd`瓙w['{\5&'uqyhn)iӪ["z̡Wˆnj8o­'i9jgt:GP@ů&DZ.S]nkcN]mVrjq8s CɆ$ 'xyѯi:=C/%$ϯpҼbbF HXKfYtr]NM!¶۶WS?t&c 6[A~*lwPT%KϜZ=ƿj<`H |30iKFZ/N-Nɲ_Kr *h;NqBYxZ(Z,~ŧ`4]/DY6~S|n\6ѣ{0gjz }h;:WLımbeLDdI:q,\՚)>(z{Pw y7¾ o=u &W2?1gwoek좽HL$)Υ-uQ@sG'! R\rCGW~FY/|{g#'Σt9 cI&ޞGBԻ{N8K?`Hd_MRE4 :t77 (جI!iOIMŝl,CWJOo׬KϿL]U׸+=LڌnjN l=5HDDDD䒊2=y{i: K\׌Dq@kq2yO fl,8 Xw?V1ד=1"""""rS oEDDDDDDDDl3VDDDDDDDDDDF(@ oEDDDDDDDDD"[VDDDDDDDDD$)@ oEDDDDDDDDD"[VDDDDDDDDD$)@ oEDDDDDDDDD"[VDDDDDDDDD$H@,i.G{U]g%7?]UD]xZہbmyYDDDDDDΣ?E[tNzp4 01%ad^Zx'Wۦ?3&./?&( oEh iw6֝O=>^ Y䭸[6o!O`&+L¨=^ܡ9f Ŭy-o PNJDDDDDD"HDhinM?@_?XxlR1ursH, u;ߨ9:Q'^z ;<]?g%]UϘl{=ICy6Ls]D oO׹8qz{NS`\aeJl.C|)ӻy&Z<&x ;ho:'G bk?'/ ٫\D)C1K7p}BoEDDDDDd@D>9XGE-y/p9˒+\_k48,H(;▒//¶1:#n˝Ed3߉uO5P3}Xas]D oYK2[ŚD!Pw{'ΆtL?`yذqݍi&ٽ̛ɴ~k4z>E:EDDDDD oG>d%yYc1YneauLȌ?8mٿT` 7ކ=E__M$Yld.)fCS^rC*BconI.h ׮]s7]_~g'NO`6Ǔe$M{RG5/- [)-N}`%מɎ9XTJ˜wziOn^6;7fE f֥/f{UnC@Z&;WCSq`$#ʖ+رt3Իܼ_QGiM' C,Y6meS ldg8I/.&8h*?M%SGDDDDDDh:&|QQ .GYr:v 3\t:ChLpѓ+荽߇I}m9?ȿK|qSBN*kH*,t{{amOq^>)&t$y,-״x|:[~"#q2nK;(z^wO-*ylDd?6c.t< O[_䚝W9E `7-g^3z#-T4޶ލL4mDOzyU*r{T[0o  Hw>:},""""""rՉFsn>P@r ^s~X.E[5O q* n.^CM\&6ZKN`TF͞Z;<$;{}(5,ғ O+X xh ۋ;o~)5PW=HZƂlI Wqxf<5*MXX6VZ=B]gۄ4 1Bpmcʙwh;ƙ)]y5)iIt=o.""""""W졻{@ԅL)*2ciuEbKHJxTw kvނM\&);+<^ZB45{-Sʇh3~yvJ ||-\oSuWUl~)XUC1p:y%Pn_Z-mpF:.?oNjg%zuNLl:(Legtvjek^!y;ˆﶏ &^샷l3Cp `g7vxO-I/^bbXę".7;3m/#BAmNݴq 6%}\3qANQu+[6MuHo3M&m{6. \qޮ,}wc]B~O XnN(WGCr'ܷ?εYh牛;SS {kR91-@%ws/#ƥ|Ƚ:Yx GfNu-ԒNyT;5ZvbsqYO" @7P0 'ȼ1mgg餤xB>}|:[,uFN/18Xoܒ}D9~6YlDQM?#-c'""""""Wy SW{=8t,QP}vCg35M%yt[}H@$N%Z"PhJLyS؉u3M{nL:vΩi$N܌OOXI$KEJ\}'@ oIuι .~.p?/НXTgQDQ3={&@>r`[f|n}͸d<$who e#=giWȪX|Z"0~A;>L}\v2g"'3hMΜKLR{\;;FO˯ޠ@SӉ3o]}]/ܙR""B dZd61a(ʟI3(+~w>=G`5^KAzZ 9{z:)cͦƉbUzOpRfLDA`8$ s ^ ~ CnS9֮qNKqCc+anNhq'!κ +G:n2K$-""""""w oDŽM IDATVLcɧ\aVhȜCRa~L+=7ή6&w4ssj{ν-9x>9n@#@#gEXiA6ho\,2 ,7$dsk0bq &""""""2ל7r6f na]|A!lv7~~^SB|MXq,JISo@ :` vm^^q#mM>Ӊ 4}OȜ3#F{sKGrΗ+z `QEnƾ>j4u Ri # p% m5qD:3 r A$%FAm ࠥpwdoxwFo#jpqQZx'[i=vnŒMhJac6AcWOl?,ۙ1^CNwx:.ȝk-:HHH37-$t <׈HbL[۠u\+X0wn{_=;UHh]>+3O8kbXκfm;@u t-;hl5ޮW[6$d42a\aL;d״.r3 VKm/\ q];;\K$݅PI^I#I ,\L%s ?dŏ<>'M)7E-?n\Z&89V7$""""""ˈcz: M7܎T#}jny`-sTq}32*~kw;%:sĥ0pm~'~?h #FA@SѮefx9Z6D%:W(W9ziVsb+ؔXv#[̮0M+olE3W/dM/ oQuFC&6Dfmr},tUT,a;wKfqƍܶRQ| `j\/J (~_~:JD=NO޿A9+-[(lٙDVzz<,٫wer^9=?9?݉.5HGo%2bƵEDDDDDUĘiidxxvc\yGD&+c܁ U\u]}CTP9t78{~?>Zu`pV`HIq`l8@f̍:v ?&SMKC55XERb:"fRY/ $Kqnr}]vnGpH)f̞N+ q7W>i`o7sH殝oa|㷦(1Qg^RHkde""""""u_)שibxhrΆwOʃRfT]:Dz)p6~VW62g`< [P6Oc*F# !:WcDKߪBB'~ldұR҃qϯi2܊^\i`˶٘V V _2HTT8AK9TV$N檏)я峷-rg.KrrJfO%ܬkts٘K:[/ 4DDDDDDU5o'2OfuFw%VY$)P]lt ]nsԺ]_營6Q;Wy%%6 Ksmm姇jh {gmgva`@Fz݊x^WVF5o`{V`'"ZE@]|iӯ+Z؆`BxڔDV۹\ fFntSnb&HNM)'̡Э)Q oEDDDDDDDD7LDDDDDDDDDNVDDDDDDDDD )B*"̚HDDDDDDDDd9S[/VDDDDDDDDD )B oEDDDDDDDDD[/VDDDDDDDDD <Y8]9B""""""""">Lrur +D|۬-RلeoRA~n*y3vK1o-ԝ>2 hO7JDDDDDDDDDnׄׯQu܅ϸ-QHpCXc-=(//h ` Z*?-3mUVW5VkZdϣ񙚷mzy?CD Fb?mc( >τՕMUu;'A/pDT'Yj>Q6nP⾝:Y|>hfhhظHgy N"""""""""ՕU*0WIʌ1PVDDDDDDDDD<[Kgݮh'19-6]()^ގu7K6Oh'""""""""""ՅPCC4oVɄjݵDhĭnRyx7{!,@EDDDDDDDDdz^h 4,sT[;wg|[R*׻G6f['"""""""""Uc&*[nDlOZDDDDDDDDD&Lgw+ UݼA%de]w;cnMnm"""""""""2'^VU5 \ǥ" rᷳLoy"""""""""2^}Aݍ&4MT6}!Lry(6'"""""""""sm}} 7o:X`$!1-!7t9ɛ+}3\8@/'"""""""""su;PMjZŐ?~b%""""VDDDD|ZOS#Ő`CC.,{w#5M6)!pOHvCM53o4Yފx1kS p6'9C85rb^h&-ÌqA[KCYCP x{tVjߣ}!Mxa -!jJ(mm 5':}3ÖSd3Ɂ:2|{oM/q}5|g'in&:8!$e/.@<(j_ ?<ŸuqSmlkq6xo%i!eWP}}i a Ҩ;U'^}O;Gxo }N8 ~{v=ݠhJF+9ac {kS=0ew* ڰulP%c9TR^ [`x;JEY5UTVQSۆmo#ə&ضqS$YA p5 oEDD|IeJ K>5.ۦCdy6 WiR=O[ҖMx[WH _O=%kx {yZVRϙCW9 Z{x""">h\Q+LC^|2+`0`p8ݎ2r<*;Ĺf-=Ӈ+q>ݙG-HF₵LfxWo[H<%Nzc jp~3{UWcl)IY7Nܒx'q`ODa^=!mm: ąM4֖CTC%Yg6?R"w2""">"tҊl.bmIc2mX.\P+E.j&pE>Qf׾8LV^J$gi3;?kgw02O ~˻pٝN0L9;CZZ-X` 2cNH%{G.[s>hG;l {)䵖ˊ²ض&nvYz13g-#:9u-:Ҹ+{ITHoY.[GtsdeN?7UD66HM,%{+u2lg{n}l ԑ\*xVqƦ>v;CL!1{#[8S{c׶mLͤeo`΍r^;T#* bYv2]x~&LfbRN'+'u@B'WhSU`=GLՏL$-!JCe /\s !6c w#+aZʊ(/Bou!6!rٜ;2EMW8QleltY\1j IDAT'PS;}.ߏ\._!'}Ռ)l >Ba#e 5 oEDD|F(;Vs:Eiؗ*`59g iƶdXC58{ 3s@5 tǷ߹g {v$ҾYzRګ8C )<;aMx@6 pG,iMxRzǮFkU);ɗ{f;P}zvKGU׹}ٓ|4|pbnvZuG?"`=~ֺ=ex#TLVuՔ=λw%k'TgZC,GN_&t =T_<̑[Ǽu?wPg֣'o1^#ui, o{&Ժeuw$h@ u|p/:Mׅ E|?MP@3Ɵo[Gj?+K/~kcO9 KmQ;`u;xj{Vc[OҢ?c|9^ Og=y旷[9k[7񬣍֪jJNݔmlK\{`~(.Ppk|yY|B$^y\_>ept<#S1,A%gؗ:DdYtDDDdr7aK))j;p2A֎u88}fb9 Ǫ]'l*H_aIܽZϜfձ=yRz1rvlmwu||Tk~#X(y܎n+֦G8;(5~n#3m[|&?>0Rޱ{vl`mJ몿coO^aRV3}^{eLc!cs.䒽6=!8miҖPz_3g/۱Cfk[[ۄ?)y„q4Mz)O1s{#cs袦j wp;X(ױFɛ?O涳ﻂ@wmkhӟOL3Ϲ!,mh_*ƦĎki$>/1~; ,;y]GF[Ck9_5Zȏi4 J c6l# B]۲՝~ } _}}45`O 1%БL.3/ɡ3s_cX[VD"""$h QrX;{!Fgk0mf$`#'%:wdչX2VFg*~iQrk&@ X܄_9GSQ8C_orBf]<“<:nc#Z>9e/ui5xn_}k%{ooK)zkyit { yㆳڛ+)GI\KA#' zQor2;GK>g20!Z uKc1۰ "mYLcm `kzN,M`(f;=C#Cy}9c?׏F_r*ypQ l7_1PMgxCE(z{V!ռk|z,+ci>ߩ<ҷy`#\vN™?yֳE3xbkn(|/G~Q#;<(kfI{Px+""SLdo[:"jw9wYdlcsI>n8ݴ= 9y g?954}B.XG`elQr֜S9.xtd~COnlIjkGI>-ɾc?ۋ8A31$paXV^/26G޻/_He:7h㕷pGNE)lv݈SɛTҘs `Hgl'M4vbH牬1YPG~OZq{S˃\9f21Oc(9 ]7~?ܞ4ǻW" + L78,vddJ,X{Tx;pw\ Yy~ԑ1a {^.Sʧ]wm@g&d= ^@ ||Ov(< 3cB;\Þ7UJM+T&]+b$2+ogRыQ۞_X?1(O?OFesnw_qC@P"^xtr+]5̵tjo]D|IZ_mcJyh6ݶ#-‰6@F8~^se1%84Ax7MXnZ,\nru;umȝ̍r*jʹ51Kz5cAdY40?vf]fs?6̾bF3޾d,q¢RwɄmsK~jWącSMث8ufdjOWqrv ۊP2!g1`˛Ih MSN˜ή#(9[;icgܡfh<>EpTL0ox^țzr4}䥿}C (nO7InUN;{|[4G Ho- k?{"3w&e!W( `Uo=jKPf_H$[l폩?^@uc?b=״e!h [ tqbsL<Dz;qrXΜbWɜph/;)GRٞùmਦL/[wO,&`u|:Y3 N^M{mt:shɵ O`m&Y SNC&lj]6KAkXj&iv$!#'vM&9h{wh]}1C3Y7oLt,0[R6{X<@ݘHߔ?[} ;6rdbR!cݤcXƌ5d:'p2r1gN߮p蛦h(@@6u_]Pk\4dioϕYs5-)r|o5Faϋ/0,ah p^\u-]_Vʫ )z/Jc$t&ׯ@/.'L l >5Q&vPRޜ;{ɄA}6)td/kXdϘP rIN]zZe{Fp"+'eq dJ]rcޑ8C0Uгg饏cXs6d)N#.w@YN7Wͱ3:s4˰@Lp&N5N$ٓcNL.QIʸ ذlh"t>1 j7xYUL&+v"ğZ_CoP&V|iqn !6zjZGH>&Lϛ ,ߧd_8pu1u㤁r6_KV/;0r3` Y-/)~~ڞ1%S?xSx eq`|((" >vΟ-ibp,wlwI-:G(+ocrjJ)O?vukiS٥a}~x=Z`:6XGFРïqd̋#ynpXG_7O]Uv>9zѯ|)@J֛\ª+`iε$$\ I'w<su@Y0Alۆ_K9-{/-MV^JʻG%oŻ/w >#w8R+5sӌZ=S3eͫ ݹb;F]fνLK6|XF3#'}ŇCG@n;13^Nhыe^wO=CPSD9qSwpAude#['#Ǣ[ pֿ-|u6Ͱ&zӄMNd %.c [~g^z}oF^6."G]N*JFȄ nVTd}sHd[;פ-}VZݷ@yWPL/l#gkuܕB@ʥnfZN'9;{4{5oC YR2Ag]?ors !kU OL"e }M |X1 ws_[aOW ǯ`@ۉw>/FSZ+*₠ǎp!U6,Ndkk4ti>ƀ0BSX[;44'{1ӴcX[ 9[ՃLEn{W9g OpAG]]tNWuƍsCe7$kns7ۚxo1?:\#h1GCȚC#m;CypU;z.6R>!!dMѷ<4xFTDg&1co ?}*/ؠӵ;|US6u=j$`#ǎӊX3ux715h#lÜnt6IuŐa8j)y)k/" `q4@ҴV*kG!&LCbȤIMa}P5lE%@Oݐ剐j1M{).}-T]k`|ݥN״`h};LZjTu6jJj!ֺF&H6VH'vn=Y` i^xRRgMm\Sp6rkHg !.EdQ&@OZ5mc,q񑓂a!FUCCC4ַ:c9ڜ{_)41ϥ0e \C߱3yR_f?E _Q>r?+)1o2/jxko=a@FZ^b XBwڂȟ4iԍOO?g긯j*ckصjLgT6N}ohN۪8t;=#Vus֡t^)vմp}?n+?, b]g%OⱩVr9~T7}kW7zt+/n g=-%izDge>᭽2vvQuέ3'`az!]|u^(6JZ>[G~qOqޫG>>ojA^N֔U^~&p}LOPkAM:QMaQ/[wNsūfײ!Ir3YP N^Ú~* F!fL1ddi h5I&1]5XH,24b#\M6w89aꋈl:%cŻܵ=C~ivy Hܶcg,cϰ.2֐fL+BN4Zg%jFzn:yk5q v;k {ɘLeuglOgyޏ3N?t7ZOe" yMل.ؙGb$99a$Ky!~CٕON|.]NÔC+acl Ï ;/!W@j>7j5Bawiwb{Fb]Z95yKͣm@ٜw$kcnC֐/1:jG[d}٩ɣ\ s_qu?,uEd3y(júYַrbdX˜1;îM<ڑςʉwN™ xg#wpk 697%`V7W[1 }WNa#j9ysn<2< ~3 ZnC͙|*jk~ 6qsЬ5/m s]'-/i'=b7%6_ RA.Ȗd%ܳ/I G~r?GT%TKdNLo;,oo_w-S,͜@F]%m}&QL8i溕!WEvl8ėF´UpuC2᜾i~?ɥC':lŎcNf:ʿMX޺VQ2Gx4e]݁Z~?Gx12.B@OQ)6Rhv"/͋"X)qw#ON.ƬUS^sO;ױ<%KGu!7ngH}(>j3{6ͷ撑A FۥrJ 98Q뷳h=vnaMV,&Ņ||T0yG^7pv?9/(_]*;xK?w@j&x4)fg№1|ȇF]Ѱ 5g4H><6xkNrfhE{J6=7 |V8:9~xB΀6~fN٠ ~wx:Vg%dK˞>dc~,‡gޠg_߫XFcn \EƄuܕ7_8g!=/4R\2ξ7雭` n#g~A ڈL\V,!l83>*w@y~O? ؘFlvZ/]1>z8A7fn@dVgsp;8y{GnH,CNSk3蠭U^lFǠ27|<ݑ6I ;'VZF.r5mZ4p} I!cl>w-Z9v!t@dⲁ/{dAq-@,ˈ8hia͌ۿM֘z^-^r@)NTY:{Ⱥ47߽8XX=sދYgb'-tyٻ8ڢr !cĖvuepʰu[ndߒWEp4&nc&qem]34p ɓ,GK!"" /ttu5XnkTЋG۔K⟜rY u|X}u,_9饳udd>~&f>c%v0Mx`̻ߔmOMտJq+8Hm|l'Gi!S K8;#vNL7f wBi^m 6v/yfHsA0.[_qbQwІIL8p `1ғ<(9_S{~q=4Iz|9?κg?~0rLv<}fD(xmpE{ +`#7sv4|}!mpܔO={@l88(g|Lvq^h8ϛH䦝lx^`%D<LىaK7pD ÖJu A'?X:>DMd֎xl"+e/s퀰ADp Z1}H 7P0ˏY l[|h:r-5j[AA{#Du@w.Vͻ]ٶd *eohghfnXRT[TIdi#qI1.\S|_bcbȓOsDQy1}ݜԻ̒?kݒ7$^{;^94o'_ݬLȜxf&2bȹ5as9st&5rV"bo6eygĂͧd~-wX1Ax۟c_GV>EH6b;s g!#Mxe,Lsop)Q6 riV*v`s}Bd2hdz_:qOP^*HHܒѿ@zJ-qx#&3ju$~EX&$rN^ڑ #fW4ѷz=~5d+hn"A@ܫhF(7)a)s[ 7DuנMsڲG;+X5:J&pkfaSȚNHۥ1^Oc3/c7ӸMARF2qȐ24ۨ,.R;6ɂ%<f3d.ҸɧKַ1('f5E1?$L9mJYCAӡ}Gƿ; ; 3TWOCI˺;lobBe%M6 q$ōSY! ّ;+K8_u@HLI)Ncǥ2hjB@PDMeM_7Md38߯:(-ņd!$&*o&t1߽|h߷&wͳqުRDc!R@Ue-+r2,]oe. %sODHF/qos$E paxpBqb렦ϟV:8,;6> bu`,?5Uj>섦rNY=A&Xa_Xjh(Iƕkf* 6qO7-39>rUfrx)ܨ铅#;uK{{.V0y/1s$/ˇe\0<%}ګ*\leuPַ $a;|k36޺b|?p(<gPɄo6EgQ69*AbLci*gm̀?|@|\ $nbl_GkZ5 DD<8D-@`.9 D*1E^νCPI$&Fa5i%6HmsGB)&OgiqɊ"W9xaNn^~w}*YWGr&8YK51jΖ6ye< @v`Ð|op?G؈m*,(Wl:[[*.3=k̇9gS!/=ULƶlX,&5;[oPp7+7jyU^N~̼| PYHŻӉNP֭A[(l+;9}pֶ^`b\(Ѥ̍/nͱog(Ɇ5qpyuS0;>+xEUǰͮl]>XM12i{3{=>~ƁE qF fs=n)_XAp 4|7 +"LjqV_GSk #;t7~':qtXL߻1y zJ>x|ɴ2NU.#ل\+"f5l7qb$2onEd~ \BhJGoH""*s4bwE[Ҭd9w6>K̄z &Y}-@[CW3A,ˀ31mڠwzXMzXM #/(gD &kvjb[feS0v.F|o (+Zi,̹ aoܹIac0;恬 )+:!dNXOӠxXFxf6e惷M5?Ed~3ENj#U:x\ 8$;ꦷ2f7970|2( Yi]πGmJm_<MRXm)rZt뫱lJ{e&*ppd5Kh:[sjƋcl+TD ᣷ok/itn^6SB &ZB sSRW/6" ?(L@Z+]ue_ALd\,A`Ĉ%!y٤ꀀLV !iy6+s Jf:sw\ϟrULo&=$w%"2 N20X߂ǹQp&ʤv93 S%5j楈8¡jcX~]lԜtJ15c젟H2UsU|Pw Eܶl9˦Hf40:ts;j4]#fq }+&QZٿܐ1L IN&̨4n{,mG1?7U|l:XYn$$Zy"2G|ILuП&SRDdNx|v$/_%R#DB.N4<4Kls9qoNUpV/kw^~H?Y""2/ces= iwg-m\,q0zyypWwP\$z(ou]ZD͙'0 IGyZ~j_̭X׀wxstwbJղs8AnJ' 8Xx~Y[诃+8j[cVSTi5@,OݐH+IMIq~cWSx2]>^D:ύut wN )!_cVoM%+gДy~)_ښ|KZ pPr&dZT j?glSÉwljwlg;3 ysw(~ȉћt k k7>2{0u^?M]=؏ Rm8LŠ#ٖ:3VR@"٢G2bv_5W_^Y"islX&Owuq f/=us @ IYnglmՕR@e!ǂ_j<&Q5*k?26F6e$9#y:b5TVVkgM%AӻtD-f>X\@DDDDDDdZdo9pyѧq\, eliŁKP4I  `X}9l5_Bm{/xOpt7/;5auxDvjQSiEKo%Vy o㿩5gJBHDDDDjW~]=-37.U.#icS!A\DTB [i"| xG t ܳ>lDDDDDDD :6 \q%[:w;0yĢEs=J,̈́~"-5Ծ\DR=eH[\ [HmkR3nGwS56znyg` "2DdD~,ޙBOC,Y<׃Z:C}=`# s_bDˈ[["Ϳq]gJ! DDDDDDD[_7CVR3=W[Y 0M!=v7^5a708zqUl+v׽twNA/f,ʺoEDdfy1Gc3EDDDDDD<@ ފx M%*z""""""2(VDDDDDDDDD)vjkc6a4x4N=\ADĭ?.uK?OGC~:>3&Mzٻz"2 ^պjnw?o6jONũ4Ut!5˖⣣CDDDDDDDDd(ADd=mt76w\{6C7qцe Y딕ZҕuבL{}#Z =4 Z9S=ُ8 nU%mX?(HdT]mǯ9(PߙlkM{/⛄L~y5~{tvWSDiFUDDDDDDPvk>NwusvVmg??*"y ?GiǃRaHv3n?KC cL"e=_|KkfdHq L M ifdypD6nd)lwoZ` ЋXF+ZtWr 0xa靹`}F>fOȴkx m ~\y/DfS$+6m#};Q3?@{熐>k |4S`;_~5!crʴ-^wW^xngl" p`mw(,(]lKe*X8^…J*nLV:3MX0" (Xʎ:;F%2c#03Xmq̎hrfb̖)q#mVx5 dLDDDDDDOٛ%S _7ncx|摛ynOmlvfVW5py7| - (gFnj]3z:o2CݼAt%ޕyI=ttax"""""" L;d2tcB #($_ 퓫Z\TICC fnkݐZ l%#N,fEnZ@W %(.*ԟ 7!" g:8tGj/x͆D/~7un0glM49srCg`1;%8 Y@Dr"2-WhXhۇ8Xe~~~,I厵1$O"󲻹NTq;v}EeM,3eZtE8K2eپ$?nY6-vw"ܥ j[p`FlRVd_H߉wh>_0ey^5~WiX&`ӠPB5ˢӡ,iK;3/̽fM"Aa~)+Žl5tD,TDea%7 i6vC]Ul'ht|;vt1AM9??Lߋmc^/` g& __,#GZymZ:PeqJ2^S9GZ3Gٴ>>- iLGiW3i^Y~oϹFp]tPu9~z]ZK]ǜ:1lBk+x+Y+]ފʃwI$Fy6+|%&NaǁI˶OFN׻&OMݷŚ<`RU})i/AMf:iݥ_=$ƹ'dL`tA $DzU:aOߡY^LNvٴHmĮ]?{N6>3!7|1$$\YXA8I:/0sm*]0gŲyiK_]-q^y^9+HoWછ[7^gP{G>԰}Hҧ> ݺKg[c`ױ*3׌KGomj?+>$\˪kYI\Kgꅗ)LK}"ݐ%k^+~)Nhh^9y53̴ۢig޺Kmu3==4&? oRe=pX4#*~s:ƊǐMuL`? IsC¶` 9%hrs#/wv<[{ћd.aC>Tsvj3ʺ'%+*Z+?~Z;:OC$j^l4ՕRV=Om^ž%׮biM}\v }n"}MѮ+{> +訦19wmg hಛc2o*ZX2*8~kegvyj=09o}8W<>s_*Ζ$/NtgW1 ( ,kZ88sc0Y^Yݥu1ē7{ٞifϑNib./~a}ux}Y;uPhJښjTJҾ7yAd<ʋZz3 ;W'~2_[6(T2tF̾q?X,>#9~뼍-Zp֔mr؞3^OK ϧ]P{&owi\K˃ȝRޱ8z{yLCf#_,xgZ+ǟyU^k?~kf%RBOQ?RW0)Gc4a;u8pzG@d W_#vf?w4"s }1o/[!""""""W797[Ҩlu՘FRIuȆX@y'Xy3<"ώgT)ˆ v0gwk-{;O;bfCn8 3&dd!/HEs'fsp KƝ|fkK{:meL~ 5cc@[k[倠aE||ŘlmFs%| pcPi 0eފdln]UP<4S>lj+]u5eF2'3K܉TЉZzW7,q计 emvqnn6xz8^Æ٬pzQ lk^ZGz$<voA$1tf&rC04`CGiJ(/kt?ql}N>+utRx71&JYgN%=JꀞO8Z=Ĺ\bc7#9>cKy4'ؗ@bD ^G=n H':>yYv{ClJDDDDDDdNxLBVDd0XrWQVU-H+8ݶj坔H^r홋q%LF%;S%683 {x@3jaK!1t{ŔSwe1.t]ao#kIqc{%^>={r8zAt"g9ջ~2X"٩E%^숏m :ouP9iY.Bt;FNW8wU`.L$hj'&u{mn3B^L9N[Q1E%?#u<&xh"|\:b˗/S?p+Rd >Q)ę<ƾ |̳ O !c#0sg/s>w2$3\3%ųc^sݕ61iy2WNgHwgpp_s]ŭt]||a:I5oXB~_Ro%tٝ\חq>3+8:ht?^peRٶ>sȭܒWR!? v??R$F'YV)>vqԞsar """"""rU 9}=xT1K3:47:+~~fRqk3qEf[![&zL6P8Ld%L3G=͛CgFr"l/- VU_U&v[𨛠'eVQKmYOWfًW/&sXX|pU6#'t۫q1uUϿ@I8ZHm l3_E6<6rlr_(eFbZoL ]~ [vLS.AWE;F%өw>$l2z""""""2W=,-CYr.`0 McIJ,可| Ň%RoeW!'r#45\Y&'j SHŔlI, hKuXGLl^^Dpn[6隲3"{M lצt"Ӷ(vRo=t'~ I$;va/s4?mr]`=kD_@y;͓9v ;_b73w7_w]ue䮍P[q;^!-eX2s+>B%]5ؚ:DDDDDDdytV_?_*ыjWÛ[Fela/.j:R#ZJ-6[1^2yp7DŽ'7bt35zQ5{[Xz-c"ʺYJ q/G'Z0l `ij&r~Վ9 *,D&go'=D9I%w G,$ ފL1a !/3.` 8)=v06{$9SB{ %i@]vұ^"vnK2pEDDDDDdPVd:ySWrr:ME%JpSg"#n;DP%O!WDDDDDD f-=؏-9 ='15[GNDDDDDD(oEDDfY;'F "lSDDDDDD昂"""os}MF=5<-. DDDDDDDDDDd(eފx oEDDDDDDDDD<""""""""""H[ୈRVDDDDDDDDDz2} uɈ1K"""""""""󜂷 /pnu&?,KӉٹL4o#nb;}|꺹L"{ˁs=qN:/S7)/jgKDDDDDDDDD&kF&XmX3.4eˮ|̘/# 0]@'t\MDDDDDDDDD&e^jijhƆCܸm5aAꯩ[hlhq,_B–t.;RO(x+""""""""2L;xjc'1n et>x;`u;Ise>&bb0 `","IDAT?Fvu"""""""""ϴ3o&KRb &<"_^lIA`?aAkGnPEDDDDDDDDDio}Yꎱ/e8z"""""""""2 .HFe]t`DDDDDDDDDd ]±D.ګi*(x :u_:Ie|o촕E91|%yg*s=H2o*hKm`4o6f"""""""""N Uw[*OclnEDDDDDDDD< 77oSVDDDDDDDDdPل5ATVDDDDDDDDdQvAjVh&(iN#"""""""""SAY"""""""""󎂷 G ފx oEDDDD)oǐgcD&i j4}{=G}=YZ3mT;jjF,,@Xz`%aȃ^K?{k?w $S]'@ٕ?1ʖ{kLLkf;?j[e^>*3Lշ~~`x -hW-uܶ{/Q6?7?]MxoidzV>(S}/ߴ<{~(Qevaod:aiBɜ/s쌓QO_zNe?Z@c~&K7ShOtkT}?NRml'H(x P @-@[o $H(x P @-@[ŦK,-]O$MGǷr^KmkIή汑tuwqm4ze>s.lm3~?)C}gf#NN/S_Xjə翗PJzc|ǃ˙xǵJ%oF&/Nevv;h^>;:24ԛ+Y__==:':#9ӝJG1|r|IŌa^~;m9~r$C~/$I~m%yؑ;x@{T{'I4Ϟȡhe՝ns;gύ1~[}}r3c>е3q}*dpw&N7Z.&I%j[K ԒsaaiPZjLJ<kx'OKGGG-o'/NekI{쑖3L$V+y3hoT{%m}q9o^$ٗ~&OwWn?gZyH[E՛y,-_Ox扌hT{x{s}=xjKIcO>ϞjTGhŸ'rmv!Iph,Jɓ<ۍ䝷ϕkIG gR _W$+?SEU\$I_,W[]]ۼ`b2][ϝK֣ɋS:w?wtt"J<Ż_vŗGSͭSk7;>ҟшRcZevaCo $H(x P @-@[o $H(x P @-@[o $H(x P @~ IENDB`datatype99-1.6.4/run-clang-format/000077500000000000000000000000001440313234400166715ustar00rootroot00000000000000datatype99-1.6.4/scripts/000077500000000000000000000000001440313234400152045ustar00rootroot00000000000000datatype99-1.6.4/scripts/check-fmt.sh000077500000000000000000000002241440313234400174020ustar00rootroot00000000000000#!/bin/bash ./run-clang-format/run-clang-format.py \ --exclude examples/build \ --exclude tests/build \ -r datatype99.h tests examples datatype99-1.6.4/scripts/fmt.sh000077500000000000000000000002751440313234400163350ustar00rootroot00000000000000#!/bin/bash find tests examples \ \( -path examples/build -o -path tests/build \) -prune -false -o \ \( -iname "*.h" \) -or \( -iname "*.c" \) | xargs clang-format -i datatype99.h datatype99-1.6.4/scripts/test-all.sh000077500000000000000000000001021440313234400172610ustar00rootroot00000000000000#!/bin/bash set -e ./scripts/test.sh ./scripts/test-examples.sh datatype99-1.6.4/scripts/test-examples.sh000077500000000000000000000007431440313234400203420ustar00rootroot00000000000000#!/bin/bash set -e mkdir -p examples/build cd examples/build cmake .. cmake --build . run_example() { echo "executing ./$1 ..." ./$1 } if [[ "$OSTYPE" == "linux-gnu" ]]; then run_example "array_in_variant" run_example "ast" run_example "binary_tree_malloc" run_example "binary_tree" run_example "token" run_example "derive/metadata" run_example "derive/record_metadata" run_example "derive/print" run_example "derive/command_menu" fi datatype99-1.6.4/scripts/test.sh000077500000000000000000000004471440313234400165270ustar00rootroot00000000000000#!/bin/bash set -e mkdir -p tests/build cd tests/build cmake .. cmake --build . if [[ "$OSTYPE" == "linux-gnu" ]]; then echo "Executing ./tests ..." ./tests echo "Executing ./derive ..." ./derive echo "Executing ./metalang99_compliant ..." ./metalang99_compliant fi datatype99-1.6.4/tests/000077500000000000000000000000001440313234400146575ustar00rootroot00000000000000datatype99-1.6.4/tests/.gitignore000066400000000000000000000000071440313234400166440ustar00rootroot00000000000000build/ datatype99-1.6.4/tests/CMakeLists.txt000066400000000000000000000027351440313234400174260ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.16) project(tests LANGUAGES C) set(GCC_OPTIONS -Wall -Wextra -pedantic -ftrack-macro-expansion=0 -fsanitize=address) set(CLANG_OPTIONS -fmacro-backtrace-limit=1 -fsanitize=address) # Enable a standard-conforming C99/C11 preprocessor. set(MSVC_OPTIONS /std:c11) if(CMAKE_C_COMPILER_ID STREQUAL "GNU") add_compile_options(${GCC_OPTIONS}) add_link_options(-fsanitize=address) elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang") add_compile_options(${CLANG_OPTIONS}) add_link_options(-fsanitize=address) elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC") add_compile_options(${MSVC_OPTIONS}) elseif(CMAKE_C_COMPILER_ID STREQUAL "TinyCC") add_compile_definitions(ML99_ALLOW_POOR_DIAGNOSTICS) endif() function(set_standard TARGET NUM) set_target_properties(${TARGET} PROPERTIES C_STANDARD ${NUM} C_STANDARD_REQUIRED ON) endfunction() add_executable(tests tests.c) add_executable(metalang99_compliant metalang99_compliant.c) add_executable(derive derive.c) add_executable(record_derive record_derive.c) add_executable(version version.c) set_standard(tests 99) set_standard(metalang99_compliant 99) set_standard(version 99) # For `_Static_assert`, which can be used on the same line number. set_standard(derive 11) set_standard(record_derive 11) add_subdirectory(.. build) get_property( TESTS DIRECTORY . PROPERTY BUILDSYSTEM_TARGETS) foreach(TARGET ${TESTS}) target_link_libraries(${TARGET} datatype99) endforeach() datatype99-1.6.4/tests/derive.c000066400000000000000000000104601440313234400163020ustar00rootroot00000000000000#include #include #include // `static_assert` is not working on TCC for some reason. #ifndef __TINYC__ // TestDerive { #define DATATYPE99_DERIVE_TestDerive_IMPL(name, variants) \ ML99_TERMS( \ v(static_assert(CMP_IDENTS(MyType, name), "Must be MyType");), \ ASSERT_VARIANTS(variants)) #define ASSERT_VARIANTS(variants) \ ML99_TERMS( \ ML99_invokeStmt( \ v(static_assert), \ ML99_natEq(ML99_listLen(v(variants)), v(3)), \ v("not 3 variants")), \ ML99_listMapInPlaceI(v(visitVariant), v(variants))) #define visitVariant_IMPL(variant, i) ML99_call(assertVariant_##i, ML99_untuple(v(variant))) #define visitVariant_ARITY 2 #define assertVariant_0_IMPL(tag, sig) assertVariant(tag, sig, Foo, A) #define assertVariant_1_IMPL(tag, sig) assertVariant(tag, sig, Bar, B, C) #define assertVariant_2_IMPL(tag, sig) \ ML99_TERMS( \ v(static_assert(CMP_IDENTS(tag, Baz), "Variant #3 is not Baz");), \ v(static_assert(ML99_IS_NIL(sig), "Baz is not empty");)) // } (TestDerive) // assertVariant { #define assertVariant(tag, sig, expected_tag, ...) \ ML99_TERMS( \ v(static_assert(CMP_IDENTS(tag, expected_tag), "Non-equal tags");), \ assertSig(sig, __VA_ARGS__)) #define assertSig(sig, ...) \ ML99_TERMS( \ ML99_invokeStmt( \ v(static_assert), \ ML99_natEq(ML99_listLen(v(sig)), ML99_variadicsCount(v(__VA_ARGS__))), \ v("Invalid variant arity")), \ ML99_invokeStmt( \ v(static_assert), \ ML99_listEq(ML99_appl(v(ML99_identEq), v(CHECK_)), v(sig), ML99_list(v(__VA_ARGS__))), \ v("Non-equal types"))) // } (assertVariant) // Identifiers { #define CMP_IDENTS(x, y) ML99_IDENT_EQ(CHECK_, x, y) #define CHECK_MyType_MyType () #define CHECK_Foo_Foo () #define CHECK_Bar_Bar () #define CHECK_Baz_Baz () #define CHECK_A_A () #define CHECK_B_B () #define CHECK_C_C () // } (Identifiers) typedef UnitT A; typedef UnitT B; typedef UnitT C; // clang-format off datatype( derive(TestDerive, dummy), MyType, (Foo, A), (Bar, B, C), (Baz) ); // clang-format on #endif // __TINYC__ int main(void) { #define FOO attr(~, ~, ~) // DATATYPE99_attrIsPresent { ML99_ASSERT(DATATYPE99_attrIsPresent(v(FOO))); ML99_ASSERT(ML99_not(DATATYPE99_attrIsPresent(v(BAR)))); } // DATATYPE99_ATTR_IS_PRESENT { ML99_ASSERT_UNEVAL(DATATYPE99_ATTR_IS_PRESENT(FOO)); ML99_ASSERT_UNEVAL(!DATATYPE99_ATTR_IS_PRESENT(BAR)); } #undef FOO #define FOO attr(678) // DATATYPE99_attrValue { ML99_ASSERT_EQ(DATATYPE99_attrValue(v(FOO)), v(678)); } // DATATYPE99_ATTR_VALUE { ML99_ASSERT_UNEVAL(DATATYPE99_ATTR_VALUE(FOO) == 678); } #undef FOO #define FOO attr(~, ~, ~) // DATATYPE99_assertAttrIsPresent { ML99_EVAL(DATATYPE99_assertAttrIsPresent(v(FOO))); } #undef FOO return 0; } datatype99-1.6.4/tests/metalang99_compliant.c000066400000000000000000000027741440313234400210550ustar00rootroot00000000000000#include #include #include #include #include ML99_ASSERT_UNEVAL(DATATYPE99_datatype_ARITY == 1); ML99_ASSERT_UNEVAL(DATATYPE99_record_ARITY == 1); ML99_ASSERT_UNEVAL(DATATYPE99_of_ARITY == 1); ML99_ASSERT_UNEVAL(DATATYPE99_ifLet_ARITY == 3); ML99_ASSERT_UNEVAL(DATATYPE99_attrIsPresent_ARITY == 1); ML99_ASSERT_UNEVAL(DATATYPE99_attrValue_ARITY == 1); ML99_ASSERT_UNEVAL(DATATYPE99_assertAttrIsPresent_ARITY == 1); // clang-format off ML99_EVAL(DATATYPE99_datatype( v(MyType), v((A, const char *)), v((B, int, int)) )); ML99_EVAL(DATATYPE99_record( v(MyRecord), v((int, x)), v((int, y)) )); ML99_EVAL(DATATYPE99_record(v(MyEmptyRecord))); // clang-format on int main(void) { // DATATYPE99_of { const MyType expr = A("hello world"); match(expr) { ML99_EVAL(DATATYPE99_of(v(A), v(str))) { assert(strcmp(*str, "hello world") == 0); } ML99_EVAL(DATATYPE99_of(v(B), v(_), v(_))) { assert(false); } otherwise { assert(false); } } } // DATATYPE99_ifLet { const MyType expr = B(5, 7); ML99_EVAL(DATATYPE99_ifLet(v(expr), v(B), v(x), v(y))) { assert(*x == 5); assert(*y == 7); } } // Record type usage. { MyRecord r = {.x = 3, .y = 5}; (void)r; MyEmptyRecord empty_r = {.dummy = '\0'}; (void)empty_r; } } datatype99-1.6.4/tests/record_derive.c000066400000000000000000000055261440313234400176470ustar00rootroot00000000000000#include #include #include // `static_assert` is not working on TCC for some reason. #ifndef __TINYC__ // Common { #define assertFields(fields, n) \ ML99_TERMS(assertFieldsCount(fields, n), ML99_listMapInPlaceI(v(visitField), v(fields))) #define assertFieldsCount(fields, n) \ ML99_invokeStmt( \ v(static_assert), \ ML99_natEq(ML99_listLen(v(fields)), v(n)), \ v("expected " #n " fields")) #define visitField_IMPL(field, i) ML99_call(assertField_##i, ML99_untuple(v(field))) #define visitField_ARITY 2 #define assertField(ty, ident, expected_ty, expected_ident) \ ML99_TERMS(assertIdentsEq(ty, expected_ty), assertIdentsEq(ident, expected_ident)) #define assertIdentsEq(x, y) v(static_assert(ML99_IDENT_EQ(CHECK_, x, y), #x " must be " #y);) // } (Common) // TestDerive { #define DATATYPE99_RECORD_DERIVE_TestDerive_IMPL(name, fields) \ ML99_TERMS(assertIdentsEq(name, MyType), assertFields(fields, 3)) #define CHECK_MyType_MyType () #define CHECK_a_a () #define CHECK_b_b () #define CHECK_c_c () #define CHECK_A_A () #define CHECK_B_B () #define CHECK_C_C () typedef UnitT A; typedef UnitT B; typedef UnitT C; #define assertField_0_IMPL(ty, ident) assertField(ty, ident, A, a) #define assertField_1_IMPL(ty, ident) assertField(ty, ident, B, b) #define assertField_2_IMPL(ty, ident) assertField(ty, ident, C, c) // clang-format off record( derive(TestDerive, dummy), MyType, (A, a), (B, b), (C, c) ); // clang-format on #undef DATATYPE99_RECORD_DERIVE_TestDerive_IMPL #undef CHECK_MyType_MyType #undef CHECK_a_a #undef CHECK_b_b #undef CHECK_c_c #undef CHECK_A_A #undef CHECK_B_B #undef CHECK_C_C #undef assertField_0_IMPL #undef assertField_1_IMPL #undef assertField_2_IMPL // } (TestDerive) // TestEmptyDerive { #define DATATYPE99_RECORD_DERIVE_TestEmptyDerive_IMPL(name, fields) \ ML99_TERMS(assertIdentsEq(name, MyEmptyType), assertFields(fields, 1)) #define CHECK_MyEmptyType_MyEmptyType () #define CHECK_char_char () #define CHECK_dummy_dummy () #define assertField_0_IMPL(ty, ident) assertField(ty, ident, char, dummy) record(derive(TestEmptyDerive), MyEmptyType); #undef DATATYPE99_RECORD_DERIVE_TestEmptyDerive_IMPL #undef CHECK_MyEmptyType_MyEmptyType #undef CHECK_char_char #undef CHECK_dummy_dummy #undef assertField_0_IMPL // } (TestEmptyDerive) #endif // __TINYC__ int main(void) {} datatype99-1.6.4/tests/tests.c000066400000000000000000000163461440313234400161770ustar00rootroot00000000000000#include #include #include #include // clang-format off datatype( EmptyDatatype, (EmptyA), (EmptyB) ); datatype( ComplexDatatype, (A), (B, int), (C, const char *, int), (D, char, unsigned, long long, int *) ); record( MyTinyRecord, (int, x) ); record( MyRecord, (int, x), (long long, d), (const char *, str) ); record(MyEmptyRecord); // clang-format on #define FAIL assert(false) static void test_match_complex(ComplexDatatype expr) { match(expr) { of(A) { assert(ATag == expr.tag); return; } of(B, x) { assert(BTag == expr.tag); assert(x == &expr.data.B._0); return; } of(C, str, x) { assert(CTag == expr.tag); assert(str == &expr.data.C._0); assert(x == &expr.data.C._1); return; } of(D, c, x, y, ptr) { assert(DTag == expr.tag); assert(c == &expr.data.D._0); assert(x == &expr.data.D._1); assert(y == &expr.data.D._2); assert(ptr == &expr.data.D._3); return; } } FAIL; } static void test_match_empty(EmptyDatatype expr) { match(expr) { of(A) { assert(EmptyATag == expr.tag); return; } of(B) { assert(EmptyBTag == expr.tag); return; } } FAIL; } int main(void) { const char *const hello = "hello"; const ComplexDatatype a = A(), b = B(42), c = C(hello, 12), d = D('~', 0, 5274, NULL); const EmptyDatatype empty_a = EmptyA(), empty_b = EmptyB(); // Test the contents of the values. { assert(ATag == a.tag); assert(BTag == b.tag); assert(42 == b.data.B._0); assert(CTag == c.tag); assert(hello == c.data.C._0); assert(12 == c.data.C._1); assert(DTag == d.tag); assert('~' == d.data.D._0); assert(0 == d.data.D._1); assert(5274 == d.data.D._2); assert(NULL == d.data.D._3); assert(EmptyATag == empty_a.tag); assert('\0' == empty_a.data.dummy); assert(EmptyBTag == empty_b.tag); assert('\0' == empty_b.data.dummy); } // Tag { ComplexDatatypeTag tag; tag = ATag; tag = BTag; tag = CTag; tag = DTag; (void)tag; } // Variants { ComplexDatatypeVariants data = {.dummy = 0}; data.B._0 = (int)123; data.C._0 = (const char *)"abc"; data.C._1 = (int)9; data.D._0 = (char)'A'; data.D._1 = (unsigned)2924; data.D._2 = (long long)-1811; data.D._3 = (int *)(int[]){123}; (void)data; } // SumT { const ASumT a_indirect = a; const BSumT b_indirect = b; const CSumT c_indirect = c; const DSumT d_indirect = d; (void)a_indirect; (void)b_indirect; (void)c_indirect; (void)d_indirect; } // _I { B_0 b_0 = (int)123; (void)b_0; C_0 c_0 = (const char *)"baba"; C_1 c_1 = (int)-91; (void)c_0; (void)c_1; D_0 d_0 = (char)'('; D_1 d_1 = (unsigned)12322; D_2 d_2 = (long long)-7; D_3 d_3 = (int *)(int[]){42}; (void)d_0; (void)d_1; (void)d_2; (void)d_3; } // MATCHES { assert(MATCHES(a, A)); assert(MATCHES(b, B)); assert(MATCHES(c, C)); assert(MATCHES(d, D)); assert(!MATCHES(a, C)); assert(!MATCHES(b, D)); assert(!MATCHES(c, B)); assert(!MATCHES(d, A)); // Pass an rvalue to `matches`. assert(MATCHES(A(), A)); } // Test a single `otherwise` branch. { match(a) { otherwise goto end_single_otherwise; } FAIL; end_single_otherwise:; } // Test `match`. { test_match_complex(a); test_match_complex(b); test_match_complex(c); test_match_complex(d); test_match_empty(empty_a); test_match_empty(empty_b); } // Test the reserved identifier `_`. { const ComplexDatatype expr = C("abc", 124); match(expr) { of(A) {} of(B, _) {} of(C, _, x) { (void)x; } of(D, c, _, _, ptr) { (void)c; (void)ptr; } } } // Test a nested `match`. { match(a) { of(A) { match(b) { of(B) goto end_nested_match; otherwise FAIL; } } otherwise FAIL; } FAIL; end_nested_match:; } // Test two `match` in the same lexical scope. { #define TEST_MATCH \ match(a) { \ of(A); \ of(B, _); \ of(C, _, _); \ of(D, _, _, _, _); \ } TEST_MATCH; TEST_MATCH; #undef TEST_MATCH } // The same identifiers from different branches shall not clash with each other. { const ComplexDatatype expr = A(); match(expr) { of(A) {} of(B, same1) { (void)same1; } of(C, same1, same2) { (void)same1; (void)same2; } of(D, same1, same2, _, _) { (void)same1; (void)same2; } } } // ifLet { const ComplexDatatype expr = C("abc", 918); ifLet(expr, C, str, x) { assert(str == &expr.data.C._0); assert(x == &expr.data.C._1); goto end_if_let; } FAIL; end_if_let:; ifLet(expr, B, _) FAIL; } // Test two `ifLet` in the same lexical scope. { ifLet(b, B, _); ifLet(b, B, _); } // Make sure that `match` and `ifLet` result in a single C statement. { const ComplexDatatype expr = B(42); if (true) match(expr) { otherwise {} } if (true) ifLet(expr, B, _) {} } // Test record types. { MyTinyRecord tiny = (MyTinyRecord){.x = 123}; struct MyTinyRecord tiny2 = tiny; (void)tiny; (void)tiny2; MyRecord r = (MyRecord){.x = 123, .d = 15, .str = "hello world"}; struct MyRecord r2 = r; (void)r; (void)r2; MyEmptyRecord empty_r = {.dummy = '\0'}; struct MyEmptyRecord empty_r2 = empty_r; (void)empty_r; (void)empty_r2; } UnitT dummy = unit_v; (void)dummy; return 0; } datatype99-1.6.4/tests/version.c000066400000000000000000000031331440313234400165100ustar00rootroot00000000000000#include #include int main(void) { #undef DATATYPE99_MAJOR #undef DATATYPE99_MINOR #undef DATATYPE99_PATCH #define DATATYPE99_MAJOR 1 #define DATATYPE99_MINOR 2 #define DATATYPE99_PATCH 3 // DATATYPE99_VERSION_COMPATIBLE { ML99_ASSERT_UNEVAL(DATATYPE99_VERSION_COMPATIBLE(1, 0, 0)); ML99_ASSERT_UNEVAL(DATATYPE99_VERSION_COMPATIBLE(1, 1, 0)); ML99_ASSERT_UNEVAL(DATATYPE99_VERSION_COMPATIBLE(1, 1, 1)); ML99_ASSERT_UNEVAL(DATATYPE99_VERSION_COMPATIBLE(1, 2, 0)); ML99_ASSERT_UNEVAL(DATATYPE99_VERSION_COMPATIBLE(1, 2, 1)); ML99_ASSERT_UNEVAL(DATATYPE99_VERSION_COMPATIBLE(1, 2, 2)); ML99_ASSERT_UNEVAL(DATATYPE99_VERSION_COMPATIBLE(1, 2, 3)); // Major-incompatible. ML99_ASSERT_UNEVAL(!DATATYPE99_VERSION_COMPATIBLE(2, 0, 0)); ML99_ASSERT_UNEVAL(!DATATYPE99_VERSION_COMPATIBLE(7, 1, 2)); // Minor-incompatible. ML99_ASSERT_UNEVAL(!DATATYPE99_VERSION_COMPATIBLE(1, 3, 0)); ML99_ASSERT_UNEVAL(!DATATYPE99_VERSION_COMPATIBLE(1, 4, 9)); // Patch-incompatible. ML99_ASSERT_UNEVAL(!DATATYPE99_VERSION_COMPATIBLE(1, 2, 4)); ML99_ASSERT_UNEVAL(!DATATYPE99_VERSION_COMPATIBLE(1, 2, 5)); } // DATATYPE99_VERSION_EQ { ML99_ASSERT_UNEVAL(DATATYPE99_VERSION_EQ(1, 2, 3)); ML99_ASSERT_UNEVAL(!DATATYPE99_VERSION_EQ(1, 2, 7)); ML99_ASSERT_UNEVAL(!DATATYPE99_VERSION_EQ(1, 7, 3)); ML99_ASSERT_UNEVAL(!DATATYPE99_VERSION_EQ(7, 2, 3)); } #undef DATATYPE99_MAJOR #undef DATATYPE99_MINOR #undef DATATYPE99_PATCH }