[
  {
    "path": ".github/ISSUE_TEMPLATE/problem-report.md",
    "content": "---\nname: Problem report\nabout: Something may not work as inteded or requires fixing\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the problem**\nPlease describe your problem in a detailed way here, so others can understand it.\n\nSome tips:\n* Be objective\n* Make sure you read the Readme, documentation and wiki\n* Check if you installed all required programs (especially Rake)\n* Include all error messages and warnings potentially related to the problem\n* If the problem depends on specific steps, describe them in a way others can reproduce consistently\n\n**To Reproduce**\nPlease require a minimal working code example on how to reproduce the issue, if possible.\n\nAvoid any unnecessary detail, but make sure the problem still persists in the example. If you are unable to provide a minimal working example, you may also refer to a specific repository instead.\n\n**Expected behavior**\nIf something does not work the way you would expect it to, please describe the expected behavior shortly. This is only necessary if you don't encounter obvious errors or crashes.\n\n**Platform and version**\nPlease describe which versions of Crystal and Anyolite you are using, which Anyolite flags you are using and which platform you are on.\n\n**Additional context**\nIs there anything else you want to mention that did not fit into the previous sections?\n"
  },
  {
    "path": ".github/workflows/doc.yml",
    "content": "name: Doc\n\non:\n  release:\n    types: [published, edited, prereleased]\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    steps:\n    - uses: actions/checkout@v2\n    - name: Install Crystal\n      uses: oprypin/install-crystal@v1\n      with:\n        crystal: nightly\n    - name: Build documentation\n      run: ANYOLITE_DOCUMENTATION_MODE=1 crystal docs\n    - name: Deployment\n      uses: peaceiris/actions-gh-pages@v3\n      with:\n        github_token: ${{ secrets.GITHUB_TOKEN }}\n        publish_dir: ./docs\n"
  },
  {
    "path": ".github/workflows/mritest.yml",
    "content": "name: MRITest\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n  schedule:\n    - cron: '45 03 * * 6'\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    steps:\n    - uses: actions/checkout@v2\n    - name: Install Crystal\n      uses: oprypin/install-crystal@v1\n      with:\n        crystal: nightly\n    - name: Install Autoconf\n      run: sudo apt install -y autoconf\n    - name: Install Ruby\n      run: sudo apt install -y ruby\n    - name: Build shard\n      run: ANYOLITE_CONFIG_PATH=\"config_files/anyolite_config_mri.json\" rake build_shard\n    - name: Test script\n      run: crystal run test.cr --error-trace -Danyolite_implementation_ruby_3\n"
  },
  {
    "path": ".github/workflows/test.yml",
    "content": "name: Test\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n  schedule:\n    - cron: '45 03 * * 6'\n\njobs:\n  build:\n\n    runs-on: ubuntu-latest\n\n    steps:\n    - uses: actions/checkout@v2\n    - name: Install Crystal\n      uses: oprypin/install-crystal@v1\n      with:\n        crystal: nightly\n    - name: Install Ruby\n      run: sudo apt install -y ruby\n    - name: Build shard\n      run: rake build_shard\n    - name: Test script\n      run: crystal test.cr\n"
  },
  {
    "path": ".github/workflows/wintest.yml",
    "content": "name: WinTest\n\non:\n  push:\n    branches: [main]\n  pull_request:\n    branches: [main]\n  schedule:\n    - cron: '45 03 * * 6'\n\njobs:\n  build:\n\n    runs-on: windows-latest\n\n    steps:\n    - uses: actions/setup-ruby@v1\n    - uses: microsoft/setup-msbuild@v1.1\n    - uses: seanmiddleditch/gha-setup-vsdevenv@master\n     \n    - name: Download source\n      uses: actions/checkout@v2\n    - name: Install Crystal\n      uses: crystal-lang/install-crystal@v1\n      with:\n        crystal: nightly\n    - name: Build shard\n      run: rake build_shard\n    - name: Test directories\n      run: dir build/mruby/lib\n    - name: Test script\n      run: crystal build test.cr\n    - name: Run script\n      run: ./test\n"
  },
  {
    "path": ".gitignore",
    "content": "build/\r\nutility/mruby_build_config.rb.lock\r\nthird_party/\r\ndocs/\r\nexamples/bytecode_test.mrb\r\n.vscode/\r\n.crystal/"
  },
  {
    "path": ".gitmodules",
    "content": ""
  },
  {
    "path": "Changelog.md",
    "content": "# Changelog\r\n\r\n## Releases\r\n\r\n### Version 1.1.1\r\n\r\nNOTE: This version requires recompilation of mruby and the C files.\r\n\r\nNOTE: This version will only work with mruby 3.3.0 and above.\r\n\r\n#### Usability\r\n\r\n* Updated mruby to 3.3.0\r\n* Updated MRI to 3.0.6\r\n* Added error messages when Rake fails at installing\r\n* Added error messages when mruby/MRI is missing\r\n\r\n#### Bugfixes\r\n\r\n* Fixed Regex wrapper warnings when running Anyolite with newer Crystal versions\r\n* Fixed warning message when compiling glue files\r\n* Fixed some annotations not working properly\r\n\r\n### Version 1.1.0\r\n\r\nNOTE: This version requires recompilation of mruby and the C files.\r\n\r\nNOTE: This version will only work with mruby 3.2.0 and above.\r\n\r\n#### Features\r\n\r\n* Added direct bindings to `Regex` from Crystal (`Regexp` in Ruby)\r\n* Added option to use a separate Ruby interpreter\r\n* Added safeguard to catch non-fatal Crystal exceptions and raise them as Ruby errors\r\n* Added option to transform procs into bytecode\r\n* Added function to disable external program execution\r\n* Added interpreter depth counter\r\n* Updated to mruby 3.2.0\r\n* Updated to MRI 3.0.5\r\n* Added backtrace function for mruby\r\n* Added option to fully protect Crystal values from the Ruby GC\r\n* Added standalone wrappers for class properties\r\n\r\n#### Usability\r\n\r\n* Updated mruby config file to use `libucrt` instead of `msvcrt`\r\n* Discarded old and problematic Regex mruby gem\r\n* Made arguments for `Anyolite.call_rb_method_of_object` optional\r\n* Added automatic conversion from Ruby class names to class objects in method callers\r\n* Improved testing script\r\n* Added check for `RbValue` and `RbRef` to some macro methods\r\n* Added ability to pass Ruby blocks via Crystal to Ruby function calls \r\n* Added some internal methods to mruby to handle fibers\r\n* Added some exception checking methods\r\n* Added methods to check reference table size\r\n* Removed now optional `Dir` gem from default build config\r\n* Removed need for `use_general_object_format_chars` flag for MRI\r\n* Added global option to use keyword args for optional arguments only\r\n\r\n#### Bugfixes\r\n\r\n* Fixed error when running `shards install` on Windows\r\n* Fixed compilation warning messages for Windows\r\n* Fixed problems with Regexes due to PCRE conflicts\r\n* Fixed problems with Anyolite on Crystal 1.5.1\r\n* Unspecified arguments now always correctly throw warnings instead of confusing errors\r\n* Fixed compiletime error when casting to `Char`\r\n* Fixed errors when passing certain name arguments to Macros for calling Ruby functions \r\n* Fixed `Anyolite.call_rb_method_of_object` argument `args` not being optional\r\n* Fixed linker error due to typo in mruby bindings for block functions\r\n* Fixed crash when casting Ruby numbers into objects in some cases\r\n* Fixed script lines not printing exceptions\r\n* Fixed memory leak when calling Ruby scripts and script lines\r\n* Updated tests to account for reworked `inspect` method for enums\r\n* Fixed errors when building Anyolite in a path with spaces\r\n* Fixed problems on Linux when `LD` is set, but `gcc` should compile\r\n* Fixed Crystal functions for accessing global variables in mruby\r\n* Fixed Anyolite to allow enums with types different than `Int32`\r\n\r\n### Version 1.0.0\r\n\r\nThis release marks the first full release of Anyolite, mostly\r\nfocussed on code quality, specs and bugfixes.\r\n\r\n#### Features\r\n\r\n* `Anyolite.eval` can be used to get return values from script lines\r\n* Added check methods for Ruby references\r\n\r\n#### Breaking changes\r\n\r\n* Compacted most macro function options into hashes\r\n* Adds default `inspect` and `to_s` methods to wrapped enums automatically\r\n* Updated mruby to 3.1.0 and MRI to 3.0.4\r\n* Config files now require `rb_minor` argument for MRI specifically\r\n\r\n#### Security\r\n\r\n* Closing an interpreter will now correctly clean class and type caches\r\n* Fixed segmentation fault when overwriting Crystal content of a class\r\n* Changed block cache to a stack to avoid overwriting it\r\n\r\n#### Usability\r\n\r\n* Completed all wiki entries\r\n* Unit tests in test script\r\n* Converted macro body variables to fresh variables wherever possible\r\n* More compatibility between methods accepting `RbRef` and `RbValue`\r\n\r\n#### Bugfixes\r\n\r\n* Fixed error when passing blocks to certain method types\r\n* Methods `inspect`, `to_s` and `hash` will now correctly respond to annotations\r\n* Fixed UTF-8 problems in MRI tests\r\n* Fixed crash on returning a `RbRef`\r\n\r\n### Version 0.17.0\r\n\r\n#### Features\r\n\r\n* Added annotation to ignore class ancestors\r\n\r\n#### Breaking changes\r\n\r\n* Renamed `master` branch to `main`\r\n* Changed internal representation of wrapped pointers\r\n* Methods named `==` with no type specification will now return `false` instead of an error if types are incompatible\r\n\r\n#### Usability\r\n\r\n* Private ancestors will now be ignored automatically\r\n\r\n### Version 0.16.1\r\n\r\n#### Bugfixes\r\n\r\n* Fixed typo in keyword module function wrappers\r\n\r\n### Version 0.16.0\r\n\r\n#### Features\r\n\r\n* Added annotation `DefaultOptionalArgsToKeywordArgs`\r\n* Added option to include bytecode as an array at compiletime\r\n* Added environment variable for changing the mruby config path\r\n\r\n#### Usability\r\n\r\n* Added more debug information\r\n\r\n#### Bugfixes\r\n\r\n* Fixed argument error for block methods without arguments\r\n* Fixed build error on Windows while running Github Actions\r\n\r\n### Version 0.15.0\r\n\r\n#### Features\r\n\r\n* Methods for undefining Ruby methods\r\n\r\n#### Breaking changes\r\n\r\n* Excluding copy methods manually will undefine them from Ruby\r\n* Checks for overflow when casting numbers\r\n\r\n#### Usability\r\n\r\n* Anyolite now respects exclusions of `dup` and `clone`\r\n* Instance method exclude annotations on classes or modules will exclude them from all inheriting classes\r\n* Include annotations can reverse global exclusions\r\n\r\n#### Bugfixes\r\n\r\n* Ruby exceptions instead of Crystal exceptions for casting overflows\r\n* Casting to `Number` in mruby produced wrong values\r\n\r\n### Version 0.14.0\r\n\r\n#### Features\r\n\r\n* Support for copying wrapped objects\r\n* Ruby classes and modules can be obtained by name\r\n\r\n#### Breaking changes\r\n\r\n* All classes and structs automatically wrap the Crystal `dup` function as a copy constructor\r\n* Updates in C glue functions\r\n\r\n### Version 0.13.2\r\n\r\n#### Features\r\n\r\n* Windows support for the default mruby implementation\r\n\r\n#### Usability\r\n\r\n* CI for MRI (on Linux)\r\n\r\n#### Bugfixes\r\n\r\n* Fixed macro error for MRI\r\n\r\n### Version 0.13.1\r\n\r\n#### Bugfixes\r\n\r\n* Fixed documentation\r\n\r\n### Version 0.13.0\r\n\r\n#### Features\r\n\r\n* Full MRI Ruby as alternative implementation\r\n* AnyolitePointer helper class for accessing pointers\r\n* Infrastructure to convert script files into bytecode at runtime and compiletime\r\n* Support for setting and getting instance, class and global variables from Crystal\r\n\r\n#### Breaking changes\r\n\r\n* Changed `RClass*` to `RClassPtr` to allow compatibility with MRI\r\n* Reorganized some macros\r\n* Changed directory structure\r\n* Several code changes for compatibility with MRI\r\n* Block variables for functions definitions have now an underscore in front of them\r\n\r\n#### Usability\r\n\r\n* Option for defaulting to usage of RbValue as data container for regular arguments\r\n* Alternate build paths are now passed to Anyolite via the environment variable `ANYOLITE_BUILD_PATH`\r\n\r\n#### Security\r\n\r\n* Error messages for problems when loading scripts or bytecode files\r\n\r\n#### Bugfixes\r\n\r\n* Alternate build paths are not recognized properly in implementation files\r\n* Fixed typo in name of `rb_str_to_cstr`\r\n* Fixed inconsistent usage of `rb` in many functions\r\n\r\n### Version 0.12.0\r\n\r\n#### Features\r\n\r\n* Automatic wrapping of inherited methods from all non-trivial ancestors\r\n* Direct methods for Ruby error messages\r\n* Usage of `self` as argument type is now allowed\r\n* Option to default to regular args for an entire class\r\n\r\n#### Breaking changes\r\n\r\n* Renamed `wrap_superclass` to `connect_to_superclass` for clarity\r\n* Excluded wrapping of `dup` and `clone` methods\r\n\r\n#### Usability\r\n\r\n* Better handling for abstract classes\r\n* Correct handling of `inspect`, `to_s` and `hash` methods\r\n* Enum class method `parse?` is now wrapped automatically\r\n* Better error messages for invalid data pointers\r\n* Default exclusion of unwrappable `<=` class methods for inherited classes\r\n* More consistent debug information\r\n* Error message when trying to wrap slices (for now)\r\n* Added default equality method for structs and enums\r\n\r\n#### Bugfixes\r\n\r\n* Argument specialization was not possible for operator methods\r\n* Fixed class method exclusions not being recognized\r\n* Fixed config file parsing\r\n* Fixed generic argument parsing for regular arguments\r\n* Fixed error when converting some generics with default arguments\r\n* Default arguments for numeric regular arguments were not processed correctly\r\n* Fixed error when using unions in the style of `Bool?` at some points\r\n\r\n### Version 0.11.1\r\n\r\n#### Usability\r\n\r\n* `RbRef` values can now be used as argument type\r\n* Class inheritance wrapping can be disabled\r\n* Operator methods take arguments using the `ForceKeywordArg` annotations\r\n\r\n#### Bugfixes\r\n\r\n* Boolean operator methods with default arguments could not be wrapped correctly\r\n* Some wrappers had undocumented options\r\n\r\n### Version 0.11.0\r\n\r\n#### Features\r\n\r\n* Superclass hierarchies will be transferred to Ruby\r\n* Wrapping will skip classes if their superclass was not yet wrapped\r\n* `Anyolite.wrap` will run multiple tries to ensure superclasses being wrapped first\r\n* Classes will only be wrapped twice with `overwrite: true` option\r\n* Objects may check whether they are created in mruby\r\n* Ability to call mruby methods for mruby objects from Crystal by their name\r\n* Ability to call mruby class and module methods from Crystal\r\n* Macros to get the Ruby equivalents of modules and classes\r\n* Checks for Ruby method availability from within Crystal\r\n* Caching of RbValues in the reference table to avoid duplicate objects\r\n* Storing of pure Ruby objects in GC-safe containers\r\n* Annotations to enable obtaining Ruby block arguments\r\n* A method to call contained Ruby procs from their containers in Crystal\r\n\r\n#### Breaking changes\r\n\r\n* Reference table now has a reference to the interpreter\r\n* Interpreter and reference table operate together now\r\n* Reference table system was reworked completely\r\n\r\n#### Usability\r\n\r\n* Updated documentation to new features from 0.10.0 and 0.11.0\r\n* If nil is expected, cast everything to it without exceptions\r\n* Simplified internal object casting\r\n\r\n### Version 0.10.0\r\n\r\n#### Features\r\n\r\n* Support for block arguments\r\n* Support for array arguments\r\n* Support for hash arguments\r\n* Support for symbols, arrays and hashes as returned values\r\n* Support for chars\r\n* Experimental (unsafe) casting of pointers to integers and back\r\n\r\n#### Breaking changes\r\n\r\n* Rename `convert_arg` to `convert_regular_arg`\r\n* Rename `convert_keyword_arg` to `convert_from_ruby_to_crystal`\r\n* Rename `convert_resolved_arg` to `resolve_regular_arg`\r\n* Rename `convert_resolved_keyword_arg` to `resolve_from_ruby_to_crystal`\r\n\r\n#### Usability\r\n\r\n* Better error messages when casting incompatible values\r\n* Added dummy argument parsing to convert type calls into actual types\r\n* More intelligent conversions (Char <-> String, Int -> Float, Symbol -> String)\r\n\r\n#### Bugfixes\r\n\r\n* Fixed reference table throwing an error when increasing counter\r\n* Call rb_finalize only if reference counter is going to be 0\r\n* Fixed union type parsing\r\n* Removed possible error when casting unions\r\n\r\n### Version 0.9.1\r\n\r\n#### Usability\r\n\r\n* Allow for a wrapped function to return nil by default\r\n\r\n#### Bugfixes\r\n\r\n* Fixed broken documentation\r\n\r\n### Version 0.9.0\r\n\r\n#### Features\r\n\r\n* Additional compatibility layer between Anyolite and mruby\r\n* More configuration options\r\n\r\n#### Breaking changes\r\n\r\n* Renamed `MrbWrap` to `Anyolite`\r\n* Renamed `MrbMacro` to `Anyolite::Macro`\r\n* Renamed `mrb` and `mruby` in the code to `rb` and `ruby`\r\n* Reworked configurations for the Rakefile into a class\r\n* Dropped support for mruby 2\r\n\r\n#### Safety\r\n\r\n* Warning message when a reference table with values is reset\r\n* Added pedantic setting for reference table (default)\r\n* More reliable internal checks for union arguments\r\n\r\n#### Usability\r\n\r\n* Split macro source file into smaller parts\r\n* Update documentation to new code\r\n\r\n#### Bugfixes\r\n\r\n* Enums are now correctly tracked in the reference table\r\n\r\n### Version 0.8.1\r\n\r\n#### Usability\r\n\r\n* Explicitly exclude pointers\r\n* Explicitly exclude procs\r\n* Added recompilation options for the Rakefile\r\n\r\n#### Bugfixes\r\n\r\n* Fixed exception for class methods with empty regular argument list\r\n* Allow operator methods for class and module methods\r\n* Fixed path resolution for types starting with `::`\r\n* Resolve generics as arguments for generics properly\r\n* Fix broken floats in mruby\r\n\r\n### Version 0.8.0\r\n\r\n#### Features\r\n\r\n* Uses mruby 3.0.0 by default\r\n\r\n#### Breaking changes\r\n\r\n* Compatibility with mruby 2.1.2 requires additional flag\r\n\r\n#### Usability\r\n\r\n* Casting methods are more compatible between mruby versions\r\n\r\n### Version 0.7.0\r\n\r\n#### Features\r\n\r\n* Support for wrapping generics using annotations\r\n* Non-keyword arguments allow for union and generic type arguments\r\n* Annotation for non-keyword arguments accepts number as optional argument\r\n\r\n#### Breaking changes\r\n\r\n* Non-keyword arguments need to be specialized explicitly\r\n* More consistent wrapping of operator methods\r\n\r\n#### Usability\r\n\r\n* More helpful error messages when path resolution fails\r\n\r\n#### Bugfixes\r\n\r\n* Specialization to new arguments did not allow non-keyword annotations\r\n* Correct wrapping of most aliased types\r\n* Methods with non-letter-symbols could not be wrapped\r\n* Default arguments with colons were wrongly assumed to be keywords\r\n* Enabled support for regular string argument with default values\r\n* Fixed incomplete resolution of paths\r\n\r\n### Version 0.6.1\r\n\r\n#### Bugfixes\r\n\r\n* Non-public constructor methods could not be wrapped\r\n\r\n### Version 0.6.0\r\n\r\n#### Features\r\n\r\n* Wrappers for unions\r\n* Wrappers for nilable objects\r\n\r\n#### Breaking changes\r\n\r\n* Wrapping of specific functions has a more consistent syntax using Arrays instead of Hashes\r\n\r\n#### Safety\r\n\r\n* More useful compiletime errors for macros\r\n* More information when encountering type casting errors\r\n* Use Array(TypeDeclaration) instead of Hash for keywords in internal methods\r\n\r\n#### Usability\r\n\r\n* Cleaned up some code fragments\r\n\r\n#### Bugfixes\r\n\r\n* Wrapped struct objects were immutable\r\n\r\n### Version 0.5.0\r\n\r\n#### Features\r\n\r\n* Support for enums\r\n* Ability to rename classes and modules\r\n\r\n#### Usability\r\n\r\n* Empty argument list for specialization can be specified with nil\r\n* Exclusion message for mruby methods, finalize and to_unsafe\r\n* Exclusion of non-public methods\r\n* Exclusion of to_unsafe\r\n* Non-fatal runtime errors are triggered in mruby instead of Crystal\r\n\r\n#### Bugfixes\r\n\r\n* Proper resolution of class and module hierarchies\r\n\r\n### Version 0.4.1\r\n\r\n#### Usability\r\n\r\n* Method names in annotations can be given as strings\r\n* More and better verbose information for wrapping\r\n\r\n#### Bugfixes\r\n\r\n* Setters can be excluded correctly\r\n* Manually wrapped properties work correctly now\r\n* Correct handling of generic function arguments like Int, Number or Float\r\n\r\n### Version 0.4.0\r\n\r\n#### Features\r\n\r\n* Easier wrapping of classes and all of their methods and constants\r\n* Annotation to exclude functions from wrapping\r\n* Annotation to specialize functions for wrapping\r\n* Annotation to rename wrapped functions\r\n* Full wrapping of module and class hierarchies\r\n\r\n#### Breaking changes\r\n\r\n* Function names with operators do not include the operator into the ruby name anymore\r\n* Unified module and class cache\r\n\r\n#### Usability\r\n\r\n* Documentation updates for the new wrapping routines\r\n* Functions with only an operator in their name can now be wrapped using `MrbWrap::Empty`\r\n\r\n#### Bugfixes\r\n\r\n* Nested classes and modules can now be wrapped reliably\r\n\r\n### Version 0.3.0\r\n\r\n#### Features\r\n\r\n* Crystal structs are wrapped using wrapper objects\r\n\r\n#### Breaking changes\r\n\r\n* Struct hash values as object ID replacements are obsolete\r\n* Option hash for reference table instead of flags\r\n* Consistent naming for mruby hooks\r\n\r\n#### Safety\r\n\r\n* Structs with equal hash values do not interfere anymore\r\n\r\n#### Usability\r\n\r\n* MrbModule instances and Crystal modules can both be used in wrapper methods\r\n\r\n### Version 0.2.3\r\n\r\n#### Usability\r\n\r\n* More options for adjusting reference table\r\n\r\n#### Bugfixes\r\n\r\n* Fixed reference counter not increasing\r\n\r\n### Version 0.2.2\r\n\r\n#### Usability\r\n\r\n* Added more debugging methods\r\n* Allowed for custom object IDs by defining `mruby_object_id` for a class\r\n\r\n#### Bugfixes\r\n\r\n* Fixed problems with struct wrapping\r\n\r\n### Version 0.2.1\r\n\r\n#### Usability\r\n* Operator suffixes as general optional argument for MrbWrap functions\r\n* Option to inspect reference table\r\n* Reference counting in reference table\r\n* Reference table can be cleared\r\n\r\n#### Bugfixes\r\n* Fixed structs not being able to be wrapped\r\n* Fixed example in documentation\r\n* Fixed memory leak when returning nontrivial objects in mruby\r\n* Removed constructor limitations for types being able to be used as return values \r\n\r\n### Version 0.2.0\r\n\r\n#### Features\r\n\r\n* Keyword argument support\r\n* Support for optional keywords\r\n* Casting from MrbValue objects to closest Crystal values\r\n* Option to use a JSON config file\r\n\r\n#### Breaking changes\r\n\r\n* Optional arguments are passed using tuples instead of `MrbWrap::Opt`\r\n\r\n#### Safety\r\n\r\n* Class checks for arguments\r\n* Checks for correct keyword classes\r\n* Module cache analogous to the class cache\r\n\r\n#### Usability\r\n\r\n* Simplified some macro functions considerably\r\n* Arguments can be specified consistently as arrays or standalone\r\n* Documentation builds only for releases\r\n* Uniform system for passing optional arguments\r\n* Updated examples and documentation for keyword support\r\n\r\n#### Bugfixes\r\n\r\n* Fixed erros when naming MrbState instances anything other than 'mrb'\r\n\r\n### Version 0.1.1\r\n\r\n#### Safety\r\n\r\n* Added safeguards for reference table access\r\n\r\n#### Bugfixes\r\n\r\n* Fixed mruby function return values not being cached\r\n* Fixed minor documentation errors\r\n\r\n### Version 0.1.0\r\n\r\n#### Features\r\n\r\n* Basic structure\r\n* Ubuntu support\r\n* Wrappers for classes\r\n* Wrappers for modules\r\n* Support for classes in modules\r\n* Wrappers for properties\r\n* Wrappers for instance methods\r\n* Wrappers for module and class methods\r\n* Wrappers for constants\r\n* Optional values for simple argument types\r\n* Crystal GC respects the mruby GC\r\n* Hooks for mruby object creation and deletion\r\n* Simple examples\r\n* Build tests\r\n* Basic documentation"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 Anyolite\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Anyolite\r\n\r\nAnyolite is a Crystal shard which adds a fully functional mruby (or even regular Ruby) interpreter to Crystal.\r\n\r\n![Test](https://github.com/Anyolite/anyolite/workflows/Test/badge.svg)\r\n\r\n![Release](https://img.shields.io/github/v/release/Anyolite/anyolite)\r\n![ReleaseDate](https://img.shields.io/github/release-date/Anyolite/anyolite)\r\n\r\n![License](https://img.shields.io/github/license/Anyolite/anyolite)\r\n\r\n# Description\r\n\r\nAnyolite allows for wrapping Crystal classes and functions into Ruby with little effort.\r\nThis way, Ruby can be used as a scripting language to Crystal projects, with the major advantage of a similar syntax.\r\n\r\nUseful links for an overview:\r\n* Demo project: https://github.com/Anyolite/ScapoLite\r\n* Wiki: https://github.com/Anyolite/anyolite/wiki\r\n* Documentation: https://anyolite.github.io/anyolite\r\n\r\n# Features\r\n\r\n* Bindings to an mruby interpreter\r\n* Near complete support to regular Ruby as alternative implementation (also known as MRI or CRuby)\r\n* Wrapping of nearly arbitrary Crystal classes and methods to Ruby\r\n* Easy syntax without unnecessary boilerplate code\r\n* Simple system to prevent garbage collector conflicts\r\n* Support for keyword arguments and default values\r\n* Objects, arrays, hashes, structs, enums and unions as function arguments and return values are completely valid\r\n* Ruby methods can be called at runtime as long as all their possible return value types are known\r\n* Ruby closures can be handled as regular variables\r\n* Methods and constants can be excluded, modified or renamed with annotations\r\n* Options to compile scripts directly into the executable\r\n\r\n# Prerequisites\r\n\r\nYou need to have the following programs installed (and in your PATH variable, if you are on Windows):\r\n* Ruby (for building mruby)\r\n* Rake (for building the whole project)\r\n* Git (for downloading mruby)\r\n* GCC or Microsoft Visual Studio 19 (for building the object files required for Anyolite, depending on your OS)\r\n\r\n## Using regular Ruby instead of mruby\r\n\r\nIt is possible to use Anyolite with regular Ruby (MRI) instead of mruby. An instruction to install MRI can be found at [Using Ruby instead of mruby](https://github.com/Anyolite/anyolite/wiki/Using-Ruby-instead-of-mruby) in the wiki.\r\n\r\n# Installing\r\n\r\nPut this shard as a requirement into your shard.yml project file and then call\r\n```bash\r\nshards install\r\n```\r\nfrom a terminal.\r\n\r\nAlternatively, you can clone this repository into the lib folder of your project and run\r\n```bash\r\nrake build_shard\r\n```\r\nmanually from a terminal or the MSVC Developer Console (on Windows) to install the shard without using the crystal shards program.\r\n\r\nIf you want to use other options for Anyolite, visit [Changing build configurations](https://github.com/Anyolite/anyolite/wiki/Changing-build-configurations) in the wiki.\r\n\r\n# How to use\r\n\r\nImagine a Crystal class for a really bad RPG:\r\n\r\n```crystal\r\nmodule RPGTest\r\n  class Entity\r\n    property hp : Int32\r\n\r\n    def initialize(@hp : Int32)\r\n    end\r\n\r\n    def damage(diff : Int32)\r\n      @hp -= diff\r\n    end\r\n\r\n    def yell(sound : String, loud : Bool = false)\r\n      if loud\r\n        puts \"Entity yelled: #{sound.upcase}\"\r\n      else\r\n        puts \"Entity yelled: #{sound}\"\r\n      end\r\n    end\r\n\r\n    def absorb_hp_from(other : Entity)\r\n      @hp += other.hp\r\n      other.hp = 0\r\n    end\r\n  end\r\nend\r\n```\r\n\r\nNow, you want to wrap this class in Ruby. All you need to do is to execute the following code in Crystal (current commit; see documentation page for the version of the latest release):\r\n\r\n```crystal\r\nrequire \"anyolite\"\r\n\r\nAnyolite::RbInterpreter.create do |rb|\r\n  Anyolite.wrap(rb, RPGTest)\r\n\r\n  rb.load_script_from_file(\"examples/hp_example.rb\")\r\nend\r\n```\r\n\r\nWell, that's it already. \r\nThe last line in the block calls the following example script:\r\n\r\n```ruby\r\na = RPGTest::Entity.new(hp: 20)\r\na.damage(diff: 13)\r\nputs a.hp\r\n\r\nb = RPGTest::Entity.new(hp: 10)\r\na.absorb_hp_from(other: b)\r\nputs a.hp\r\nputs b.hp\r\nb.yell(sound: 'Ouch, you stole my HP!', loud: true)\r\na.yell(sound: 'Well, take better care of your public attributes!')\r\n```\r\n\r\nThe example above gives a good overview over the things you can already do with Anyolite.\r\nMore features will be added in the future.\r\n\r\n# Limitations\r\n\r\nSee [Limitations and solutions](https://github.com/Anyolite/anyolite/wiki/Limitations-and-solutions) in the Wiki section for a detailed list.\r\n\r\n# Why this name?\r\n\r\nhttps://en.wikipedia.org/wiki/Anyolite\r\n\r\nIn short, it is a rare variant of the crystalline mineral called zoisite, with ruby and other crystal shards (of pargasite) embedded.\r\n\r\nThe term 'anyoli' means 'green' in the Maasai language, thus naming 'anyolite'.\r\n\r\n# Roadmap\r\n\r\n## Upcoming releases\r\n\r\n### Version 1.1.2\r\n\r\n#### Bugfixes\r\n\r\n* [X] Fixed broken documentation\r\n* [X] Fixed pointers not working as regular arguments\r\n\r\n### Version 2.0.0\r\n\r\nIMPORTANT: Version 2.0.0 will introduce breaking changes to improve the general user experience.\r\n\r\nThis means that the build process and some parts of the API will change. There will be a dedicated\r\nsection in the Wiki for migrating from Anyolite 1 to Anyolite 2, so compatibility can easily be\r\nrestored.\r\n\r\nThe list of features for Anyolite 2 will expand over time, while development on Anyolite 1 continues\r\nuntil Anyolite 2 is released.\r\n\r\n#### Breaking changes\r\n\r\n* [ ] Discard postinstall option in favor of more sophisticated build script\r\n* [ ] Simplify building with custom options\r\n* [ ] Set optional arguments being keywords for method as default\r\n* [ ] Add option for using either dynamic or static linking\r\n\r\n#### Usability\r\n\r\n* [ ] Add Wiki section about migrating from Anyolite 1\r\n* [ ] Add error messages when using wrong annotation syntax\r\n\r\n### Later releases\r\n\r\n* [ ] Automated generation of Ruby documentations for wrapped functions\r\n* [ ] MRI support on Windows (does currently not work for some reason)\r\n* [ ] MRI support for version 3.1.0 and up\r\n* [ ] Support and continuous integration for Mac\r\n* [ ] Support for bindings using `Data` and `Struct` from Ruby\r\n* [ ] Multiple interpreters for mruby\r\n* [ ] Add option to make script calls thread-safe\r\n\r\n### Wishlist, entries might not be possible to implement\r\n\r\n* [ ] Splat argument and/or arbitrary keyword passing\r\n* [ ] Support for slices and bytes\r\n* [ ] Classes as argument type\r\n* [ ] Resolve context even in generic type union arguments\r\n* [ ] General improvement of type resolution\r\n* [ ] Bignum support\r\n* [ ] Range support\r\n"
  },
  {
    "path": "Rakefile.rb",
    "content": "require 'fileutils'\r\nrequire 'json'\r\n\r\ndef get_value(env_var_name, default)\r\n    ENV[env_var_name] ? ENV[env_var_name] : default\r\nend\r\n\r\ndef determine_compiler\r\n    if ENV[\"VisualStudioVersion\"] || ENV[\"VSINSTALLDIR\"]\r\n        return :msvc\r\n    else\r\n        return :gcc\r\n    end\r\nend\r\n\r\nclass AnyoliteConfig\r\n    OPTIONS = {\r\n        :implementation => \"mruby\",\r\n        :build_path => \"build\", \r\n        :rb_fork => \"https://github.com/mruby/mruby\",\r\n        :rb_release => \"3.3.0\",\r\n        :rb_minor => \"3.3\",\r\n        :rb_dir => \"third_party\", \r\n        :rb_config => \"utility/mruby_build_config.rb\", \r\n        :glue_dir => \"glue/mruby\",\r\n        :compiler => determine_compiler\r\n    }\r\n\r\n    OPTIONS.each_key{|option| attr_reader option}\r\n\r\n    def initialize\r\n        OPTIONS.each_key{|option| set_option(option, OPTIONS[option])}\r\n    end\r\n    \r\n    def load(config_file)\r\n        if File.exist?(config_file) then \r\n            File.open(config_file, \"r\") do |f|\r\n                content = JSON.load(f)\r\n                OPTIONS.each_key {|option| read_option(content, option)}\r\n            end\r\n        else\r\n            puts \"Anyolite config file at #{config_file} not found. Default settings are used.\"\r\n        end\r\n    end\r\n\r\n    def read_option(content, name)\r\n        read_value = content[\"ANYOLITE_#{name.to_s.upcase}\"] || content[name.to_s]\r\n        set_option(name, read_value) if read_value\r\n    end\r\n\r\n    def set_option(name, value)\r\n        self.instance_variable_set(\"@#{name}\".to_sym, value)\r\n    end\r\nend\r\n\r\ntask :build_shard => [:load_config, :install_ruby, :build_ruby, :build_glue]\r\ntask :recompile_glue => [:load_config, :build_glue]\r\ntask :recompile => [:load_config, :build_ruby, :build_glue]\r\n\r\nGLUE_FILES = [\"return_functions\", \"data_helper\", \"script_helper\", \"error_helper\"]\r\n\r\nANYOLITE_COMPILER = determine_compiler\r\n\r\n$config = nil\r\n\r\ntask :load_config do\r\n    if !$config\r\n        $config = AnyoliteConfig.new\r\n        config_file = get_value(\"ANYOLITE_CONFIG_PATH\", \"config_anyolite.json\")\r\n        $config.load(config_file)\r\n    end\r\nend\r\n\r\ntask :reload_config do\r\n    $config = AnyoliteConfig.new\r\n    config_file = get_value(\"ANYOLITE_CONFIG_PATH\", \"config_anyolite.json\")\r\n    $config.load(config_file)\r\nend\r\n\r\ntask :install_ruby => [:load_config] do\r\n    unless $config.rb_fork == \"___EXTERNAL___\"\r\n        FileUtils.mkdir_p($config.build_path)\r\n\r\n        unless File.exist?(\"#{$config.rb_dir}/#{$config.implementation}/README.md\")\r\n            system \"git clone #{$config.rb_fork} --branch #{$config.rb_release} --recursive #{$config.rb_dir}/#{$config.implementation}\"\r\n        end\r\n    end\r\nend\r\n\r\n# RUBY_OPT_DIR=\"C:/vcpkg/installed/x64-windows\"\r\n# NOTE: This will be relevant for MRI on Windows\r\n\r\ntask :build_ruby => [:load_config] do\r\n    unless $config.rb_fork == \"___EXTERNAL___\"\r\n        temp_path = Dir.pwd\r\n        temp_rb_config_path = get_value(\"ANYOLITE_RB_CONFIG_RELATIVE_PATH\", Dir.pwd)\r\n\r\n        if $config.implementation == \"mruby\"\r\n            if ANYOLITE_COMPILER == :msvc\r\n                system \"cd #{$config.rb_dir}/#{$config.implementation} & ruby minirake MRUBY_BUILD_DIR=\\\"#{temp_path}/#{$config.build_path}/#{$config.implementation}\\\" MRUBY_CONFIG=\\\"#{temp_rb_config_path}/#{$config.rb_config}\\\"\"\r\n            elsif ANYOLITE_COMPILER == :gcc\r\n                system \"unset LD; cd #{$config.rb_dir}/#{$config.implementation}; ruby minirake MRUBY_BUILD_DIR=\\\"#{temp_path}/#{$config.build_path}/#{$config.implementation}\\\" MRUBY_CONFIG=\\\"#{temp_rb_config_path}/#{$config.rb_config}\\\"\"\r\n            else\r\n                system \"cd #{$config.rb_dir}/#{$config.implementation}; ruby minirake MRUBY_BUILD_DIR=\\\"#{temp_path}/#{$config.build_path}/#{$config.implementation}\\\" MRUBY_CONFIG=\\\"#{temp_rb_config_path}/#{$config.rb_config}\\\"\"\r\n            end\r\n        elsif $config.implementation == \"mri\"\r\n            if ANYOLITE_COMPILER == :msvc\r\n                raise \"MSVC compilation of MRI is not supported yet.\"\r\n                \r\n                # TODO: Fix MRI on Windows\r\n                # FileUtils.cp_r(\"#{$config.rb_dir}/#{$config.implementation}\", \"#{temp_path}/#{$config.build_path}/src_#{$config.implementation}\")\r\n                # FileUtils.cd \"#{$config.build_path}/src_#{$config.implementation}\"\r\n                # system \"./win32/configure.bat --prefix=\\\"#{temp_path}/#{$config.build_path}/#{$config.implementation}\\\" --with-opt-dir=#{RUBY_OPT_DIR}\"\r\n                # system \"nmake incs\"\r\n                # system \"nmake extract-extlibs\"\r\n                # system \"nmake\"\r\n                # system \"nmake install\"\r\n                \r\n            elsif ANYOLITE_COMPILER == :gcc\r\n                system \"cp -r #{$config.rb_dir}/#{$config.implementation} #{temp_path}/#{$config.build_path}/src_#{$config.implementation}\"\r\n                system \"cd #{$config.build_path}/src_#{$config.implementation}; ./autogen.sh\"\r\n                system \"cd #{$config.build_path}/src_#{$config.implementation}; ./configure --prefix=\\\"#{temp_path}/#{$config.build_path}/#{$config.implementation}\\\"\"\r\n                system \"cd #{$config.build_path}/src_#{$config.implementation}; make\"\r\n                system \"cd #{$config.build_path}/src_#{$config.implementation}; make install\"\r\n            else\r\n            end\r\n        else\r\n            raise \"Invalid ruby implementation: #{$config.implementation}. Use either \\\"mruby\\\" or \\\"mri\\\".\"\r\n        end\r\n    end\r\nend\r\n\r\ntask :build_glue => [:load_config] do\r\n    FileUtils.mkdir_p($config.build_path + \"/glue/#{$config.implementation}\")\r\n\r\n    if $config.rb_fork == \"___EXTERNAL___\" && $config.rb_dir == \"___EMPTY___\"\r\n        puts \"NOTE: No Ruby directory specified. Glue object files will not be built!\"\r\n    else\r\n        if $config.implementation == \"mruby\"\r\n            if ANYOLITE_COMPILER == :msvc\r\n                GLUE_FILES.each do |name|\r\n                    # NOTE: For later versions, add flag /MD for dynamic linking only\r\n                    system \"cl /I \\\"#{$config.rb_dir}/#{$config.implementation}/include\\\" /D MRB_INT64 /c \\\"#{$config.glue_dir}/#{name}.c\\\" /Fo\\\"#{$config.build_path}/glue/#{$config.implementation}/#{name}.obj\\\"\"\r\n                end\r\n            elsif ANYOLITE_COMPILER == :gcc\r\n                GLUE_FILES.each do |name|\r\n                    system \"cc -std=c99 -I\\\"#{$config.rb_dir}/#{$config.implementation}/include\\\" -DMRB_INT64 -c \\\"#{$config.glue_dir}/#{name}.c\\\" -o \\\"#{$config.build_path}/glue/#{$config.implementation}/#{name}.o\\\"\"\r\n                end\r\n            else\r\n                GLUE_FILES.each do |name|\r\n                    system \"#{$config.compiler.to_s} -std=c99 -I\\\"#{$config.rb_dir}/#{$config.implementation}/include\\\" -DMRB_INT64 -c \\\"#{$config.glue_dir}/#{name}.c\\\" -o \\\"#{$config.build_path}/glue/#{$config.implementation}/#{name}.o\\\"\"\r\n                end\r\n            end\r\n        elsif $config.implementation == \"mri\"\r\n            if ANYOLITE_COMPILER == :msvc\r\n                GLUE_FILES.each do |name|\r\n                    system \"cl /I \\\"#{$config.build_path}/#{$config.implementation}/include/ruby-#{$config.rb_minor}\\\" /I \\\"#{$config.build_path}/#{$config.implementation}/include/ruby-#{$config.rb_minor}/x64-mswin64_140\\\" /c \\\"#{$config.glue_dir}/#{name}.c\\\" /Fo\\\"#{$config.build_path}/glue/#{$config.implementation}/#{name}.obj\\\"\"\r\n                end\r\n            elsif ANYOLITE_COMPILER == :gcc\r\n                GLUE_FILES.each do |name|\r\n                    system \"cc -std=c99 -I\\\"#{$config.build_path}/#{$config.implementation}/include/ruby-#{$config.rb_minor}\\\" -I\\\"#{$config.build_path}/#{$config.implementation}/include/ruby-#{$config.rb_minor}/x86_64-linux\\\" -I\\\"#{$config.build_path}/#{$config.implementation}/include/ruby-#{$config.rb_minor}/aarch64-linux\\\" -c \\\"#{$config.glue_dir}/#{name}.c\\\" -o \\\"#{$config.build_path}/glue/#{$config.implementation}/#{name}.o\\\"\"\r\n                end\r\n            else\r\n                GLUE_FILES.each do |name|\r\n                    system \"#{$config.compiler.to_s} -std=c99 -I\\\"#{$config.rb_dir}/#{$config.implementation}/include\\\" -c \\\"#{$config.glue_dir}/#{name}.c\\\" -o \\\"#{$config.build_path}/glue/#{$config.implementation}/#{name}.o\\\"\"\r\n                end\r\n            end\r\n        else\r\n            raise \"Invalid ruby implementation: #{$config.implementation}. Use either \\\"mruby\\\" or \\\"mri\\\".\"\r\n        end\r\n    end\r\nend\r\n\r\ntask :clean => [:load_config] do\r\n    temp_path = get_value(\"ANYOLITE_RB_CONFIG_RELATIVE_PATH\", Dir.pwd)\r\n\r\n    FileUtils.remove_dir($config.rb_dir, force: true) unless $config.rb_fork == \"___EXTERNAL___\"\r\n    FileUtils.remove_dir($config.build_path, force: true)\r\n    FileUtils.remove_entry(temp_path + \"/\" + $config.rb_config + \".lock\", force: true)\r\nend"
  },
  {
    "path": "anyolite.cr",
    "content": "require \"./src/Main.cr\"\n"
  },
  {
    "path": "config_files/anyolite_config_external_ruby.json",
    "content": "{\r\n  \"implementation\": \"mri\",\r\n  \"build_path\": \"build\",\r\n  \"rb_fork\": \"___EXTERNAL___\",\r\n  \"rb_release\": \"\",\r\n  \"rb_minor\": \"\",\r\n  \"rb_dir\": \"___EMPTY___\",\r\n  \"rb_config\": \"\",\r\n  \"glue_dir\": \"glue/mri\"\r\n}"
  },
  {
    "path": "config_files/anyolite_config_mri.json",
    "content": "{\r\n  \"implementation\": \"mri\",\r\n  \"build_path\": \"build\",\r\n  \"rb_fork\": \"https://github.com/ruby/ruby\",\r\n  \"rb_release\": \"v3_0_6\",\r\n  \"rb_minor\": \"3.0.0\",\r\n  \"rb_dir\": \"third_party\",\r\n  \"rb_config\": \"\",\r\n  \"glue_dir\": \"glue/mri\"\r\n}"
  },
  {
    "path": "config_files/anyolite_config_mruby.json",
    "content": "{\r\n  \"implementation\": \"mruby\",\r\n  \"build_path\": \"build\",\r\n  \"rb_fork\": \"https://github.com/mruby/mruby\",\r\n  \"rb_release\": \"3.3.0\",\r\n  \"rb_minor\": \"3.3.0\",\r\n  \"rb_dir\": \"third_party\",\r\n  \"rb_config\": \"utility/mruby_build_config.rb\",\r\n  \"glue_dir\": \"glue/mruby\"\r\n}"
  },
  {
    "path": "examples/bytecode_test.rb",
    "content": "class BytecodeTestClass\r\n  def initialize(str)\r\n    @str = str\r\n  end\r\n\r\n  def do_test(some_number)\r\n    ret_array = [@str]\r\n    some_number.times do |i|\r\n      ret_array.push i + 1\r\n    end\r\n\r\n    ret_array\r\n  end\r\nend\r\n\r\nputs \"This is a bytecode test file\"\r\n"
  },
  {
    "path": "examples/hp_example.rb",
    "content": "a = RPGTest::Entity.new(hp: 20)\r\na.damage(diff: 13)\r\nputs a.hp\r\n\r\nb = RPGTest::Entity.new(hp: 10)\r\na.absorb_hp_from(other: b)\r\nputs a.hp\r\nputs b.hp\r\nb.yell(sound: 'Ouch, you stole my HP!', loud: true)\r\na.yell(sound: 'Well, take better care of your public attributes!')\r\n"
  },
  {
    "path": "examples/mri_test.rb",
    "content": "require_relative \"./hp_example.rb\"\r\nrequire_relative \"./test_framework.rb\"\r\nrequire_relative \"./test.rb\"\r\n"
  },
  {
    "path": "examples/test.rb",
    "content": "begin\r\n  puts \"Initiate testing...\"\r\n\r\n  TestFramework.init\r\n\r\n  start_time = Time.now\r\n\r\n  # Testing bytecode if enabled\r\n  TestFramework.check(test_no: 1, should_be: [\"Hello world\", 1, 2, 3, 4, 5]) do\r\n    BytecodeTestClass.new(\"Hello world\").do_test(5)\r\n  end\r\n\r\n  # Testing attributes\r\n  TestFramework.check(test_no: 2, should_be: 5) do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.x\r\n  end\r\n\r\n  # Testing instance methods and returned arrays\r\n  TestFramework.check(test_no: 3, should_be: [19, false, \"Example string\", 0.4, 5 + 19]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.test(int: 19, bool: false, str: 'Example string')\r\n  end\r\n\r\n  # Testing attribute changes using an instance method\r\n  TestFramework.check(test_no: 4, should_be: 5 + 19) do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.test(int: 19, bool: false, str: 'Example string')\r\n    a.x\r\n  end\r\n\r\n  # Testing instance methods with keyword arguments\r\n  TestFramework.check(test_no: 5, should_be: [19, false, \"Example string\", 0.5, 5 + 19]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.test(int: 19, bool: false, str: 'Example string', float: 0.5)\r\n  end\r\n\r\n  # Testing module methods\r\n  TestFramework.check(test_no: 6, should_be: [\"Hello\", 3]) do\r\n    TestModule.test_method(int: 3, str: \"Hello\")\r\n  end\r\n\r\n  # Testing custom keyword arguments implemented using Anyolite\r\n  TestFramework.check(test_no: 7, should_be: [\"World\", 19]) do\r\n    TestModule.test_method(str: \"World\")\r\n  end\r\n\r\n  # Testing attribute setters\r\n  TestFramework.check(test_no: 8, should_be: 123) do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.x = 113\r\n    a.x += 10\r\n    a.x\r\n  end\r\n\r\n  # Testing struct attributes\r\n  TestFramework.check(test_no: 9, should_be: [-123, -234]) do\r\n    ts = TestModule::TestStructRenamed.new\r\n    [ts.value, ts.test.x]\r\n  end\r\n\r\n  # Testing returned structs\r\n  TestFramework.check(test_no: 10, should_be: [777, 999]) do\r\n    some_struct = TestModule::Test.give_me_a_struct\r\n    [some_struct.value, some_struct.test.x]\r\n  end\r\n\r\n  # Testing structs as arguments\r\n  TestFramework.check(test_no: 11, should_be: [\"5 -123 -234\", \"5 777 999\"]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    ts = TestModule::TestStructRenamed.new\r\n    some_struct = TestModule::Test.give_me_a_struct\r\n    [a.output_together_with(str: ts), a.output_together_with(str: some_struct)]\r\n  end\r\n\r\n  # Testing class methods\r\n  TestFramework.check(test_no: 12, should_be: [2, -15]) do\r\n    TestModule::Test.reset_counter\r\n    a = TestModule::Test.new(x: 5)\r\n    b = TestModule::Test.new(x: 5)\r\n    [TestModule::Test.counter, TestModule::Test - 17]\r\n  end\r\n\r\n  # Testing module methods\r\n  TestFramework.check(test_no: 13, should_be: \"Well, you can't just subtract #{13} from a module...\") do\r\n    TestModule::Test::UnderTestRenamed::DeepUnderTest - 13\r\n  end\r\n\r\n  # Testing constants\r\n  TestFramework.check(test_no: 14, should_be: \"Smile! 😊\") do\r\n    TestModule::SOME_CONSTANT\r\n  end\r\n\r\n  # Testing operator methods\r\n  TestFramework.check(test_no: 15, should_be: 37) do\r\n    a = TestModule::Test.new(x: 5)\r\n    b = TestModule::Test.new(x: 32)\r\n    (a + b).x\r\n  end\r\n\r\n  # Testing longer keyword methods\r\n  TestFramework.check(test_no: 16, should_be: \"str = Hi there, int = -121212, float = -0.313, stringkw = 💎, bool = true, other.x = 32\") do\r\n    a = TestModule::Test.new(x: 5)\r\n    b = TestModule::Test.new(x: 32)\r\n    a.keyword_test(strvar: \"Hi there\", intvar: -121212, floatvar: -0.313, strvarkw: \"💎\", othervar: b)\r\n  end\r\n\r\n  # Testing constants in a more nested type tree\r\n  TestFramework.check(test_no: 17, should_be: \"Hello\") do\r\n    TestModule::Test::RUBY_CONSTANT\r\n  end\r\n\r\n  # Testing methods without keywords\r\n  TestFramework.check(test_no: 18, should_be: 120) do\r\n    TestModule::Test.without_keywords(12)\r\n  end\r\n\r\n  # Testing deeply nested type trees\r\n  TestFramework.check(test_no: 19, should_be: \"This is a nested test\") do\r\n    # The absolute, ultimate and ridiculously complicated nesting test  \r\n    TestModule::Test::UnderTestRenamed::DeepUnderTest::VeryDeepUnderTest.new.nested_test\r\n  end\r\n\r\n  # Testing structs and enums\r\n  TestFramework.check(test_no: 20, should_be: [\"DeepTestStruct\", true, true, \"Seven\"]) do\r\n    struct_test_var = TestModule::Test::DeepTestStruct.new\r\n    enum_test_var = TestModule::Test::TestEnum::Seven\r\n    [struct_test_var.to_s, enum_test_var == TestModule::Test::TestEnum.new(7), enum_test_var != TestModule::Test::TestEnum.new(5), enum_test_var.inspect.split(\"::\")[-1]]  \r\n  end\r\n\r\n  # Testing specialized method\r\n  TestFramework.check(test_no: 21, should_be: \"No args\") do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.method_with_various_args\r\n  end\r\n\r\n  # Testing union arguments\r\n  TestFramework.check(test_no: 22, should_be: [\"\\\"Test String\\\"\", \"12345.0\", \"true\", \"nil\", \"0.6\", \"A test object with x = 32\", \"Four\", \"A generic test\", \"\\\"Default String\\\"\"]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    b = TestModule::Test.new(x: 32)\r\n    a_1 = a.overload_test(arg: \"Test String\")\r\n    a_2 = a.overload_test(arg: 12345)\r\n    a_3 = a.overload_test(arg: true)\r\n    a_4 = a.overload_test(arg: nil)\r\n    a_5 = a.overload_test(arg: 3.0 / 5.0)\r\n    a_6 = a.overload_test(arg: b)\r\n    a_7 = a.overload_test(arg: TestModule::Test::TestEnum::Four).split(\"::\")[-1]\r\n    a_8 = a.overload_test(arg: TestModule::Test::GTIntInt.new(u: 1, v: 3))\r\n    a_9 = a.overload_test\r\n    [a_1, a_2, a_3, a_4, a_5, a_6, a_7, a_8, a_9]\r\n  end\r\n\r\n  # Testing nilable methods\r\n  TestFramework.check(test_no: 23, should_be: [\"Received argument 123\", \"Received argument nil\"]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    [a.nilable_test(arg: 123), a.nilable_test(arg: nil)]\r\n  end\r\n\r\n  # Testing struct attributes\r\n  TestFramework.check(test_no: 24, should_be: [-123, 4242]) do\r\n    test_struct_thingy = TestModule::TestStructRenamed.new\r\n    initial_value = test_struct_thingy.value\r\n    test_struct_thingy.value = 4242\r\n    modified_value = test_struct_thingy.value\r\n    [initial_value, modified_value]\r\n  end\r\n\r\n  # Testing enum values\r\n  TestFramework.check(test_no: 25, should_be: 5) do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.returns_an_enum.value\r\n  end\r\n\r\n  # Testing random return types\r\n  TestFramework.check(test_no: 26, should_be: true) do\r\n    a = TestModule::Test.new(x: 5)\r\n    random_value = a.returns_something_random\r\n    puts \"Either a string or an int (it's random!): #{random_value}\"\r\n    (random_value == 3) || (random_value == \"Hello\")\r\n  end\r\n\r\n  # Testing generic types\r\n  TestFramework.check(test_no: 27, should_be: [\"u1 = 3 of Int32, v1 = 5.5 of Float32.\", \"u1 = 3 of Int32, v1 = 9 of Int32.\"]) do\r\n    first = TestModule::Test::GTIntFloat.new(u: 1, v: 0.4).test(u1: 3, v1: 5.5)\r\n    second = TestModule::Test::GTIntInt.new(u: 7, v: 10).test(u1: 3, v1: 9)\r\n    [first, second]\r\n  end\r\n\r\n  # Testing generic type functions with generics as arguments\r\n  TestFramework.check(test_no: 28, should_be: \"This has 1 and 10.0, the other has 2 and 5.0.\") do\r\n    TestModule::Test::GTIntFloat.new(u: 1, v: 10.0).compare(other: TestModule::Test::GTIntFloat.new(u: 2, v: 5.0))\r\n  end\r\n\r\n  results = []\r\n  results.push \"11 - 0.111 - 0.1 - Hello - 1\"\r\n  results.push \"22 - 0.222 - 0.2 - Hello - 32\"\r\n  results.push \"33 - 0.333 - 0.3 - 5 - 2\"\r\n  results.push \"44 - 0.444 - 0.4 - 32 - 32\"\r\n  results.push \"55 - 0.555 - 0.5 - true - 3\"\r\n  results.push \"66 - 0.666 - 0.6 - false - 32\"\r\n  results.push \"77 - 0.777 - 0.7 - Three - 4\"\r\n  results.push \"88 - 0.888 - 0.8 - Four - 32\"\r\n  results.push \"99 - 0.999 - 0.9 - Cookies - 5\"\r\n  results.push \"100 - 0.0 - 1.0 - Cookies - 32\"\r\n  results.push \"0 - 0.0 - 0.0 - SomeModule::Test::GenericTest(Int32, Int32)(@u=1, @v=1) - 32\"\r\n\r\n  # Testing unions as keyword arguments\r\n  TestFramework.check(test_no: 29, should_be: results) do\r\n    a = TestModule::Test.new(x: 5)\r\n    b = TestModule::Test.new(x: 32)\r\n    a_1 = a.complicated_method(11, 0.111, 0.1, \"Hello\", arg_opt_2: 1)\r\n    a_2 = a.complicated_method(22, 0.222, 0.2, \"Hello\")\r\n    a_3 = a.complicated_method(33, 0.333, 0.3, a, arg_opt_2: 2)\r\n    a_4 = a.complicated_method(44, 0.444, 0.4, b)\r\n    a_5 = a.complicated_method(55, 0.555, 0.5, true, arg_opt_2: 3)\r\n    a_6 = a.complicated_method(66, 0.666, 0.6, false)\r\n    a_7 = a.complicated_method(77, 0.777, 0.7, TestModule::Test::TestEnum::Three, arg_opt_2: 4)\r\n    a_8 = a.complicated_method(88, 0.888, 0.8, TestModule::Test::TestEnum::Four)\r\n    a_9 = a.complicated_method(99, 0.999, 0.9, arg_opt_2: 5)\r\n    a_10 = a.complicated_method(100, 0.000, 1.0)\r\n    a_11 = a.complicated_method(0, 0.0, 0.0, TestModule::Test::GTIntInt.new(u: 1, v: 1))\r\n    [a_1, a_2, a_3, a_4, a_5, a_6, a_7, a_8, a_9, a_10, a_11]\r\n  end\r\n\r\n  # Testing unicode strings\r\n  TestFramework.check(test_no: 30, should_be: \"😀 for number 1234567\") do\r\n    a = TestModule::Test.new(x: 5)\r\n    # TODO: For some reason, this does not work in MRI\r\n    a.inside_mri? ? \"😀 for number 1234567\" : a.happy😀emoji😀test😀😀😀(arg: 1234567)\r\n  end\r\n\r\n  # Testing equality methods\r\n  TestFramework.check(test_no: 31, should_be: [false, true, false, true, false]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    b = TestModule::Test.new(x: 32)\r\n    same_as_a = TestModule::Test.new(x: a.x)\r\n\r\n    [a == b, a == same_as_a, a == 10, a == TestModule::Test::TestChild.new(x: a.x), a == TestModule::Test::TestChild.new(x: a.x + 1)]\r\n  end\r\n\r\n  # Testing UInt8 and nil-returning methods\r\n  TestFramework.check(test_no: 32, should_be: [\"123\", NilClass]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    [a.uint_test(arg: 123), a.noreturn_test.class]\r\n  end\r\n\r\n  # Testing indirect overloads\r\n  TestFramework.check(test_no: 33, should_be: [\"This was an int\", \"This was a string\"]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    [a.overload_cheat_test(12334), a.overload_cheat_test(\"Something\")]\r\n  end\r\n\r\n  # Testing classes in modules\r\n  TestFramework.check(test_no: 34, should_be: true) do\r\n    s = TestModule::Bla.new\r\n    s != nil\r\n  end\r\n\r\n  # Testing block calls and storage\r\n  TestFramework.check(test_no: 35, should_be: [5, 5, \"2010\", 2005, 1005, \"4010\", 2005, 2005, false]) do\r\n    a = TestModule::Test.new(x: 5)\r\n\r\n    before_block_storage = a.x\r\n    new_carrier = nil\r\n    \r\n    a.block_store_test do |value|\r\n      new_carrier = value\r\n      value.x += 1000\r\n      value.x * 2\r\n    end\r\n\r\n    carrier = nil\r\n\r\n    after_block_storage = a.x\r\n\r\n    result = a.block_test do |value| \r\n      carrier = value\r\n      value.x += 1000\r\n      value.x * 2\r\n    end\r\n\r\n    after_block_test = a.x\r\n    block_store_call_result = a.block_store_call\r\n\r\n    after_block_call = a.x\r\n    carrier_result = new_carrier ? new_carrier.x : new_carrier\r\n\r\n    does_this_have_a_block = a.block_store_test\r\n\r\n    [before_block_storage, after_block_storage, result, carrier.x, after_block_test, block_store_call_result, after_block_call, carrier_result, does_this_have_a_block]\r\n  end\r\n\r\n  # Testing block methods with yield\r\n  TestFramework.check(test_no: 36, should_be: [\"1 2\", \"3\", \"They said: Hello, There\"]) do\r\n    a = TestModule::Test.new(x: 5)\r\n\r\n    other_result = a.block_test_2 do |x, y|\r\n      \"#{x} #{y}\"\r\n    end\r\n    \r\n    other_result_2 = a.block_test_2 do |x, y|\r\n      x + y\r\n    end\r\n\r\n    other_result_3 = TestModule::Test.block_test_3(arg: \"They said\") do |x, y|\r\n      \"#{x}, #{y}\"\r\n    end\r\n\r\n    [other_result, other_result_2, other_result_3]\r\n  end\r\n\r\n  # Testing arrays\r\n  TestFramework.check(test_no: 37, should_be: [[2, 4, \"HelloHello\"], [\"Not an array\"]]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    [a.array_test(arg: [1, 2, \"Hello\"]), a.array_test(arg: \"Not an array\")]\r\n  end\r\n\r\n  # Testing hashes\r\n  TestFramework.check(test_no: 38, should_be: {:hello => \"Nice\", :world => \"to see you!\", 3 => 15, \"test😊\" => :very_long_test_symbol}) do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.hash_return_test\r\n  end\r\n\r\n  # Testing unspecified floats\r\n  TestFramework.check(test_no: 39, should_be: 3.0) do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.float_test(arg: 3)\r\n  end\r\n\r\n  # Testing chars\r\n  TestFramework.check(test_no: 40, should_be: \"🌈\") do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.char_test(arg: \"🌈\")\r\n  end\r\n\r\n  results = []\r\n  results.push \"World\"\r\n  results.push TestModule::Test.new(x: 32)\r\n  results.push \"A number\"\r\n  results.push TestModule::Test.new(x: 5)\r\n  results.push \"The symbol should become a string\"\r\n  results.push TestModule::Test::TestEnum::Three\r\n\r\n  # Testing hash symbols\r\n  TestFramework.check(test_no: 41, should_be: results) do\r\n    a = TestModule::Test.new(x: 5)\r\n    b = TestModule::Test.new(x: 32)\r\n    test_hash = {\"Hello\" => \"World\", \"Test\" => b, 12334 => \"A number\", 999 => a, :test_symbol => \"The symbol should become a string\", :enum => TestModule::Test::TestEnum::Three}\r\n\r\n    result = a.hash_test(arg: test_hash).each do |key, value|\r\n      puts \"Ruby: #{key} -> #{value.is_a?(TestModule::Test) ? \"Test with x = #{value.x}\" : value.is_a?(TestModule::Test::TestEnum) ? value.value : value}\"\r\n    end\r\n\r\n    [result[\"Hello\"], result[\"Test\"], result[12334], result[999], result[\":test_symbol\"], result[\":enum\"]]\r\n  end\r\n\r\n  # Testing pointers\r\n  TestFramework.check(test_no: 42, should_be: [1002, 1005, 1005, AnyolitePointer]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.x = 1001\r\n\r\n    ptr = a.ptr_return_test\r\n    \r\n    a_1 = a.ptr_arg_test(arg: ptr)\r\n    a_2 = a.ptr_star_arg_test(arg: ptr)\r\n    a_3 = a.test_int_or_ptr(arg: ptr)\r\n\r\n    [a_1, a_2, a_3, ptr.class]\r\n  end\r\n\r\n  class InheritedTest < TestModule::Test\r\n    def initialize(x: 0, z: \"\")\r\n      super(x: x)\r\n      @y = x * 2\r\n      @z = z\r\n    end\r\n  end\r\n\r\n  class InheritedContentTest < TestModule::Test::ContentTest\r\n    def initialize(content, another_content)\r\n      super(content: content)\r\n      @another_content = another_content\r\n    end\r\n\r\n    def overloaded_content\r\n      content\r\n    end\r\n  end\r\n\r\n  # Testing inheriting wrapped classes\r\n  TestFramework.check(test_no: 43, should_be: [789789, 3, 4]) do\r\n    it = InheritedContentTest.new([InheritedTest.new(x: 123456, z: \"Hello\"), InheritedTest.new(x: 789789, z: \"World\")], InheritedTest.new(x: 111, z: \"Nice day\"))\r\n    mt = TestModule::Test::NewContentTest.new(content: [TestModule::Test::TestChild.new(x: 1), InheritedTest.new(x: 2, z: \"2\")], more_content: [InheritedTest.new(x: 3, z: \"3\"), InheritedTest.new(x: 4, z: \"4\")])\r\n    \r\n    # NOTE: This works, but only for methods directly inherited from Test.\r\n    # Overloading is therefore possible, but the other content will be cut.\r\n    # Overwriting the original content will result in errors.\r\n    \r\n    [it.overloaded_content[1].x, mt.more_content[0].x, mt.more_content[1].x]\r\n  end\r\n\r\n  module TestModule\r\n    class Test\r\n      def method_only_in_ruby(str, int)\r\n        \"#{str} #{int}\"\r\n      end\r\n\r\n      def self.class_method_in_ruby(str, int)\r\n        \"Class method with args #{str} and #{int}\"\r\n      end\r\n    end\r\n  end\r\n\r\n  # Testing method calls from Crystal\r\n  TestFramework.check(test_no: 44, should_be: [\"Hello 3\", \"Class method with args World and 4\", true, false, true]) do\r\n    a = TestModule::Test.new(x: 5)\r\n\r\n    [a.call_test, a.class_call_test, a.response_test('method_only_in_ruby'), a.response_test('method_not_in_ruby'), a.class_response_test('class_method_in_ruby')]\r\n  end\r\n\r\n  # Testing nested checks for Crystal and Ruby\r\n  TestFramework.check(test_no: 45, should_be: \"Do I have an identity crisis? Yes.\") do\r\n    a = TestModule::Test.new(x: 5)\r\n    # Try to explain in one sentence what that codeline does without losing your brain to the outer gods\r\n    \"Do I have an identity crisis? #{a.why_would_you_do_this?('am_i_in_ruby?') ? 'Yes' : 'No'}.\"\r\n  end\r\n\r\n  # Testing operator methods with boolean arguments\r\n  TestFramework.check(test_no: 46, should_be: [\"true\", \"true\", \"false\"]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    [a.bool_setter_test?, a.bool_setter_test?(true), a.bool_setter_test?(false)]\r\n  end\r\n\r\n  # Testing operator methods with keywords\r\n  TestFramework.check(test_no: 47, should_be: \"6.0\") do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.keyword_operator_arg?(arg: 5)\r\n  end\r\n\r\n  # Testing Ruby value references in Crystal\r\n  TestFramework.check(test_no: 48, should_be: \"Hello and a reference with 1223 were given.\") do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.ref_test(str: \"Hello\", ref: 1223)\r\n  end\r\n\r\n  # Testing struct constructors with custom default values\r\n  TestFramework.check(test_no: 49, should_be: [5678, 0.5678, \"Default\", 89, 0.89, \"Something\"]) do\r\n    a_1 = TestModule::Test::ValueStruct.new.i\r\n    a_2 = TestModule::Test::ValueStruct.new.f\r\n    a_3 = TestModule::Test::ValueStruct.new.s\r\n    a_4 = TestModule::Test::ValueStruct.new(89, 0.89, \"Something\").i\r\n    a_5 = TestModule::Test::ValueStruct.new(89, 0.89, \"Something\").f\r\n    a_6 = TestModule::Test::ValueStruct.new(89, 0.89, \"Something\").s\r\n\r\n    [a_1, a_2, a_3, a_4, a_5, a_6]\r\n  end\r\n\r\n  # Testing inspect methods\r\n  TestFramework.check(test_no: 50, should_be: \"x is 5\") do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.inspect\r\n  end\r\n\r\n  # Testing self as argument type\r\n  TestFramework.check(test_no: 51, should_be: \"Value is 1 and 2.3\") do\r\n    TestModule::Test::GTIntFloat.self_test(other: TestModule::Test::GTIntFloat.new(u: 1, v: 2.3))\r\n  end\r\n\r\n  # Testing equality methods of enums and structs\r\n  TestFramework.check(test_no: 52, should_be: [true, true]) do\r\n    [(TestModule::Test::TestEnum.new(3) == TestModule::Test::TestEnum.new(3)), (TestModule::TestStructRenamed.new == TestModule::TestStructRenamed.new)]\r\n  end\r\n\r\n  # Testing inherited contents and inspects\r\n  TestFramework.check(test_no: 53, should_be: [\"[x is 5, x is 5]\", \"[x is 32, x is 5, x is 32]\"]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    b = TestModule::Test.new(x: 32)\r\n    inherited_content_test = TestModule::Test::NewContentTest.new(content: [a, a], more_content: [b, a, b])\r\n    [inherited_content_test.content.inspect, inherited_content_test.more_content.inspect]\r\n  end\r\n\r\n  # Testing custom hashes\r\n  TestFramework.check(test_no: 54, should_be: [213345, 213345]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    b = TestModule::Test.new(x: 32)\r\n    [a.hash, b.hash]\r\n  end\r\n\r\n  # Testing access to instance variables\r\n  TestFramework.check(test_no: 55, should_be: [nil, 15667]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    before = a.get_instance_variable(name: \"hello\")\r\n    a.set_instance_variable_to_int(name: \"hello\", value: 15667)\r\n    after = a.get_instance_variable(name: \"hello\")\r\n    [before, after]\r\n  end\r\n\r\n  # Testing Number arguments\r\n  TestFramework.check(test_no: 56, should_be: 1.3) do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.num_test(1.3)\r\n  end\r\n\r\n  # Testing duplications\r\n  TestFramework.check(test_no: 57, should_be: [5, 8, 2, 3, 1, 0]) do\r\n    a = TestModule::Test.new(x: 5)\r\n    a_copy = a.dup\r\n    a_1 = a_copy.x\r\n\r\n    a_copy.x += 3\r\n    a.x -= 3\r\n\r\n    a_2 = a_copy.x\r\n    a_3 = a.x\r\n\r\n    enum_orig = TestModule::Test::TestEnum::Three\r\n    enum_copy = enum_orig.dup\r\n\r\n    a_4 = enum_copy.value\r\n\r\n    intfloat = TestModule::Test::GTIntFloat.new(u: 1, v: 2.3)\r\n    intfloat_copy = intfloat.dup\r\n\r\n    intfloat_copy.u -= 1\r\n\r\n    a_5 = intfloat.u\r\n    a_6 = intfloat_copy.u\r\n\r\n    [a_1, a_2, a_3, a_4, a_5, a_6]\r\n  end\r\n\r\n  # Testing regular expressions\r\n  TestFramework.check(test_no: 58, should_be: true) do\r\n    reg = /([\\S]+) [\\S]+/\r\n    reg.match?(\"Hello World\")\r\n  end\r\n\r\n  # Testing regular expression match data\r\n  TestFramework.check(test_no: 59, should_be: \"Hello\") do\r\n    reg = /([\\S]+) [\\S]+/\r\n    reg.match(\"Hello World\")[1]\r\n  end\r\n\r\n  # Testing giving Regex values to Crystal\r\n  TestFramework.check(test_no: 60, should_be: \"Hello\") do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.check_some_regex(r: /([\\S]+) [\\S]+/, str: \"Hello World\")\r\n  end\r\n\r\n  # Testing getting Regex values from Crystal\r\n  TestFramework.check(test_no: 61, should_be: \"Hello\") do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.give_some_regex.match(\"Hello World\")[1]\r\n  end\r\n\r\n  # Testing passing a Ruby block to Crystal and then to Ruby again\r\n  TestFramework.check(test_no: 62, should_be: 11) do\r\n    a = TestModule::Test.new(x: 5)\r\n    a.pass_a_ruby_block_to_another_method do |value|\r\n      value.x + 6\r\n    end\r\n  end\r\n\r\n  TestFramework.check(test_no: 63, should_be: 268) do\r\n    TestModule.some_class_property += 10\r\n    TestModule.some_class_property\r\n  end\r\n\r\n  final_time = Time.now\r\n\r\n  puts \"Tests done.\"\r\n  puts \"Total time for Ruby test script: #{(final_time - start_time)} s\"\r\nrescue => ex\r\n  puts \"\\e[31m*** FAILURE: Tests failed because of exception:\\e[0m\"\r\n  puts ex.backtrace\r\n  raise ex\r\nend\r\n\r\nTestFramework.results(raise_if_failures: true)\r\n"
  },
  {
    "path": "examples/test_framework.rb",
    "content": "module TestFramework\r\n  def self.init\r\n    @@failed_tests = []\r\n    @@test_count = 0\r\n  end\r\n\r\n  def self.check(test_no: -1, should_be: nil, &block)\r\n    result = block.call\r\n    \r\n    if result.is_a?(Array)\r\n      result.collect! {|x| x.is_a?(Float) ? x.round(5) : x}\r\n    end\r\n\r\n    if should_be.is_a?(Array)\r\n      should_be.collect! {|x| x.is_a?(Float) ? x.round(5) : x}\r\n    end\r\n\r\n    @@test_count += 1\r\n\r\n    if should_be == result\r\n      puts \"\\e[32m[Test #{test_no}] passed with result #{result.inspect}.\\e[0m\"\r\n    else\r\n      @@failed_tests.push test_no\r\n      puts \"\\e[31m*** FAILURE: [Test #{test_no}] was expected to return #{should_be.inspect}, but returned #{result.inspect}.\\e[0m\"\r\n    end\r\n  end\r\n\r\n  def self.results(raise_if_failures: false)\r\n    if @@failed_tests.empty?\r\n      puts \"\\e[32mA total number of #{@@test_count} tests was done without issues.\\e[0m\"\r\n    else\r\n      puts \"\\e[31m*** FAILURE: #{@@failed_tests.size} out of #{@@test_count} tests failed.\\e[0m\"\r\n      puts \"\\e[31m*** FAILURE: The following tests failed: #{@@failed_tests.inspect}.\\e[0m\"\r\n      if raise_if_failures\r\n        raise \"One or multiple tests failed\"\r\n      end\r\n    end\r\n  end\r\nend"
  },
  {
    "path": "glue/mri/data_helper.c",
    "content": "#include <ruby.h>\r\n\r\nextern VALUE rb_define_class_under_helper(void* rb, VALUE under, const char* name, VALUE superclass) {\r\n\r\n  rb_define_class_under(under, name, superclass);\r\n\r\n}\r\n\r\nextern VALUE rb_define_class_helper(void* rb, const char* name, VALUE superclass) {\r\n\r\n  rb_define_class(name, superclass);\r\n\r\n}\r\n\r\nextern VALUE rb_define_module_under_helper(void* rb, VALUE under, const char* name) {\r\n\r\n  rb_define_module_under(under, name);\r\n\r\n}\r\n\r\nextern VALUE rb_define_module_helper(void* rb, const char* name) {\r\n\r\n  rb_define_module(name);\r\n\r\n}\r\n\r\nextern VALUE rb_define_const_helper(void* rb, VALUE under, const char* name, VALUE value) {\r\n\r\n  rb_define_const(under, name, value);\r\n\r\n}\r\n\r\nextern void set_instance_tt_as_data(VALUE ruby_class) {\r\n\r\n  //! TODO: Is this function required?\r\n  //MRB_SET_INSTANCE_TT(ruby_class, MRB_TT_DATA);\r\n\r\n}\r\n\r\nextern bool rb_obj_is_kind_of_helper(void* rb, VALUE object, VALUE ruby_class) {\r\n\r\n  rb_obj_is_kind_of(object, ruby_class) == Qtrue ? true : false;\r\n\r\n}\r\n\r\nextern VALUE rb_obj_class_helper(void* rb, VALUE object) {\r\n\r\n  rb_obj_class(object);\r\n\r\n}\r\n\r\nextern const char* rb_class_name_helper(void* rb, VALUE ruby_class) {\r\n\r\n  VALUE class_name_value = rb_class_name(ruby_class);\r\n  rb_string_value_cstr(&class_name_value);\r\n\r\n}\r\n\r\nextern void* get_data_ptr(VALUE ruby_object) {\r\n\r\n  return DATA_PTR(ruby_object);\r\n\r\n}\r\n\r\n//! About the following method...\r\n//! It is highly hacky and just modifies a newly creates Ruby object, but that is okay.\r\n//! It tells the Ruby GC that this object is a pointer and how to free it.\r\n//! Crystal owns the pointer, so Ruby does not have to do anything else besides calling dfree.\r\n\r\nextern void set_data_ptr_and_type(VALUE ruby_object, void* data, struct rb_data_type_struct* data_type) {\r\n\r\n  DATA_PTR(ruby_object) = data;\r\n  RDATA(ruby_object)->basic.flags = T_DATA;\r\n  RDATA(ruby_object)->dmark = data_type->function.dmark;\r\n  RDATA(ruby_object)->dfree = data_type->function.dfree;\r\n\r\n}\r\n\r\nextern VALUE new_empty_object(void* rb, VALUE ruby_class, void* data_ptr, struct rb_data_type_struct* data_type) {\r\n\r\n  rb_data_object_wrap(ruby_class, data_ptr, data_type->function.dmark, data_type->function.dfree);\r\n\r\n}\r\n\r\nextern void rb_define_method_helper(void* rb, VALUE ruby_class, const char* name, VALUE (*func)(int argc, VALUE* argv, VALUE self), int aspec) {\r\n\r\n  rb_define_method(ruby_class, name, func, -1);\r\n\r\n}\r\n\r\nextern void rb_define_class_method_helper(void* rb, VALUE ruby_class, const char* name, VALUE (*func)(int argc, VALUE* argv, VALUE self), int aspec) {\r\n\r\n  rb_define_module_function(ruby_class, name, func, -1);\r\n\r\n}\r\n\r\nextern void rb_define_module_function_helper(void* rb, VALUE ruby_module, const char* name, VALUE (*func)(int argc, VALUE* argv, VALUE self), int aspec) {\r\n\r\n  rb_define_module_function(ruby_module, name, func, -1);\r\n\r\n}\r\n\r\nextern VALUE rb_inspect_helper(void* rb, VALUE value) {\r\n\r\n  rb_inspect(value);\r\n\r\n}\r\n\r\nextern VALUE rb_hash_new_helper(void* rb) {\r\n\r\n  rb_hash_new();\r\n\r\n}\r\n\r\nextern void rb_hash_set_helper(void* rb, VALUE hash, VALUE key, VALUE value) {\r\n\r\n  rb_hash_aset(hash, key, value);\r\n\r\n}\r\n\r\nextern VALUE rb_hash_get_helper(void* rb, VALUE hash, VALUE key) {\r\n\r\n  rb_hash_aref(hash, key);\r\n\r\n}\r\n\r\nextern VALUE rb_hash_keys_helper(void* rb, VALUE hash) {\r\n\r\n  //! NOTE: For some reason rb_hash_keys is not marked as extern, so for now this is a workaround\r\n  rb_funcall(hash, rb_intern(\"keys\"), 0);\r\n\r\n}\r\n\r\nextern int rb_hash_size_helper(void* rb, VALUE hash) {\r\n\r\n  rb_hash_size(hash);\r\n\r\n}\r\n\r\nextern VALUE convert_to_rb_sym_helper(void* rb, const char* value) {\r\n\r\n  rb_intern(value);\r\n\r\n}\r\n\r\nextern VALUE rb_ary_ref_helper(void* rb, VALUE ary, int pos) {\r\n\r\n  rb_ary_entry(ary, pos);\r\n\r\n}\r\n\r\nextern size_t rb_ary_length_helper(VALUE ary) {\r\n\r\n  size_t return_value = (size_t) RARRAY_LEN(ary);\r\n  return_value;\r\n\r\n}\r\n\r\nextern VALUE rb_ary_new_from_values_helper(void* rb, int size, VALUE* values) {\r\n\r\n  rb_ary_new_from_values(size, values);\r\n\r\n}\r\n\r\nextern void rb_gc_register_helper(void* rb, VALUE value) {\r\n\r\n  rb_gc_register_address(&value);\r\n\r\n}\r\n\r\nextern void rb_gc_unregister_helper(void* rb, VALUE value) {\r\n\r\n  rb_gc_unregister_address(&value);\r\n  \r\n}\r\n\r\nextern VALUE rb_yield_helper(void* rb, VALUE value, VALUE arg) {\r\n\r\n  rb_yield(arg);\r\n\r\n}\r\n\r\nextern VALUE rb_yield_argv_helper(void* rb, VALUE value, int argc, VALUE* argv) {\r\n\r\n  rb_yield_values2(argc, argv);\r\n\r\n}\r\n\r\nextern VALUE rb_call_block_helper(void* rb, VALUE value, VALUE arg) {\r\n\r\n  rb_proc_call(value, rb_ary_new_from_values(1, &arg));\r\n\r\n}\r\n\r\nextern VALUE rb_call_block_with_args_helper(void* rb, VALUE value, int argc, VALUE* argv) {\r\n\r\n  rb_proc_call(value, rb_ary_new_from_values(argc, argv));\r\n\r\n}\r\n\r\nextern bool rb_respond_to_helper(void* rb, VALUE obj, ID name) {\r\n\r\n  rb_respond_to(obj, name);\r\n\r\n}\r\n\r\nextern VALUE get_rb_obj_value(VALUE obj) {\r\n\r\n  return obj;\r\n\r\n}\r\n\r\nextern VALUE rb_funcall_argv_helper(void *rb, VALUE value, ID name, int argc, VALUE* argv) {\r\n\r\n  rb_funcallv(value, name, argc, argv);\r\n\r\n}\r\n\r\nextern VALUE rb_funcall_argv_with_block_helper(void *rb, VALUE value, ID name, int argc, VALUE* argv, VALUE block) {\r\n\r\n  rb_funcall_with_block(value, name, argc, argv, block);\r\n\r\n}\r\n\r\nextern VALUE rb_iv_get_helper(void* rb, VALUE obj, ID sym) {\r\n\r\n  rb_ivar_get(obj, sym);\r\n\r\n}\r\n\r\nextern void rb_iv_set_helper(void* rb, VALUE obj, ID sym, VALUE value) {\r\n  \r\n  rb_ivar_set(obj, sym, value);\r\n\r\n}\r\n\r\nextern VALUE rb_cv_get_helper(void* rb, VALUE mod, ID sym) {\r\n\r\n  rb_cvar_get(mod, sym);\r\n  \r\n}\r\n\r\nextern void rb_cv_set_helper(void* rb, VALUE mod, ID sym, VALUE value) {\r\n\r\n  rb_cvar_set(mod, sym, value);\r\n  \r\n}\r\n\r\nextern VALUE rb_gv_get_helper(void* rb, const char* name) {\r\n\r\n  rb_gv_get(name);\r\n  \r\n}\r\n\r\nextern void rb_gv_set_helper(void* rb, const char* name, VALUE value) {\r\n\r\n  rb_gv_set(name, value);\r\n  \r\n}\r\n\r\nextern bool does_constant_exist_under(void* rb, VALUE under, const char* name) {\r\n\r\n  rb_const_defined_at(under, rb_intern(name)) == Qtrue ? 1 : 0;\r\n\r\n}\r\n\r\nextern bool does_constant_exist(void* rb, const char* name) {\r\n\r\n  rb_const_defined(rb_cObject, rb_intern(name)) == Qtrue ? 1 : 0;\r\n\r\n}\r\n\r\nextern VALUE get_constant_under(void* rb, VALUE under, const char* name) {\r\n\r\n  rb_const_get_at(under, rb_intern(name));\r\n\r\n}\r\n\r\nextern VALUE get_constant(void* rb, const char* name) {\r\n\r\n  rb_const_get(rb_cObject, rb_intern(name));\r\n\r\n}\r\n\r\nextern VALUE rb_undef_method_helper(void* rb, VALUE mod, const char* name) {\r\n\r\n  rb_undef_method(mod, name);\r\n\r\n}\r\n"
  },
  {
    "path": "glue/mri/error_helper.c",
    "content": "#include <ruby.h>\r\n\r\nextern void rb_raise_runtime_error(void* rb, const char* msg) {\r\n\r\n  rb_raise(rb_eRuntimeError, \"%s\", msg);\r\n\r\n}\r\n\r\nextern void rb_raise_type_error(void* rb, const char* msg) {\r\n\r\n  rb_raise(rb_eTypeError, \"%s\", msg);\r\n\r\n}\r\n\r\nextern void rb_raise_argument_error(void* rb, const char* msg) {\r\n\r\n  rb_raise(rb_eArgError, \"%s\", msg);\r\n\r\n}\r\n\r\nextern void rb_raise_index_error(void* rb, const char* msg) {\r\n\r\n  rb_raise(rb_eIndexError, \"%s\", msg);\r\n\r\n}\r\n\r\nextern void rb_raise_range_error(void* rb, const char* msg) {\r\n\r\n  rb_raise(rb_eRangeError, \"%s\", msg);\r\n\r\n}\r\n\r\nextern void rb_raise_name_error(void* rb, const char* msg) {\r\n\r\n  rb_raise(rb_eNameError, \"%s\", msg);\r\n\r\n}\r\n\r\nextern void rb_raise_script_error(void* rb, const char* msg) {\r\n\r\n  rb_raise(rb_eScriptError, \"%s\", msg);\r\n\r\n}\r\n\r\nextern void rb_raise_not_implemented_error(void* rb, const char* msg) {\r\n\r\n  rb_raise(rb_eNotImpError, \"%s\", msg);\r\n\r\n}\r\n\r\nextern void rb_raise_key_error(void* rb, const char* msg) {\r\n\r\n  rb_raise(rb_eKeyError, \"%s\", msg);\r\n\r\n}\r\n\r\nextern void rb_raise_helper(void* rb, VALUE exc, const char* msg) {\r\n\r\n  rb_raise(exc, \"%s\", msg);\r\n\r\n}\r\n\r\nextern void clear_last_rb_error(void* rb) {\r\n\r\n  rb_set_errinfo(Qnil);\r\n\r\n}\r\n\r\nextern VALUE get_last_rb_error(void* rb) {\r\n\r\n  return rb_errinfo();\r\n\r\n}\r\n"
  },
  {
    "path": "glue/mri/return_functions.c",
    "content": "#include <ruby.h>\r\n\r\nextern VALUE get_object_class(void* rb) {\r\n\r\n    return rb_cObject;\r\n\r\n}\r\n\r\nextern VALUE get_nil_value() {\r\n\r\n    return Qnil;\r\n\r\n}\r\n\r\nextern VALUE get_false_value() {\r\n\r\n    return Qfalse;\r\n  \r\n}\r\n\r\nextern VALUE get_true_value() {\r\n\r\n    return Qtrue;\r\n  \r\n}\r\n\r\nextern VALUE get_fixnum_value(int value) {\r\n\r\n    return INT2FIX(value);\r\n\r\n}\r\n\r\nextern VALUE get_bool_value(bool value) {\r\n\r\n    return (value ? Qtrue : Qfalse);\r\n\r\n}\r\n\r\nextern VALUE get_float_value(void* mrb, double value) {\r\n\r\n    return DBL2NUM(value);\r\n\r\n}\r\n\r\nextern VALUE get_string_value(void* mrb, char* value) {\r\n\r\n    return rb_utf8_str_new(value, strlen(value));\r\n\r\n}\r\n\r\nextern VALUE get_symbol_value_of_string(void* mrb, char* value) {\r\n\r\n    ID sym = rb_intern(value);\r\n    return ID2SYM(sym);\r\n\r\n}\r\n\r\nextern int check_rb_fixnum(VALUE value) {\r\n\r\n    return FIXNUM_P(value);\r\n\r\n}\r\n\r\nextern int check_rb_float(VALUE value) {\r\n\r\n    return RB_FLOAT_TYPE_P(value);\r\n\r\n}\r\n\r\nextern int check_rb_true(VALUE value) {\r\n\r\n    return (value == Qtrue);\r\n\r\n}\r\n\r\nextern int check_rb_false(VALUE value) {\r\n\r\n    return (value == Qfalse);\r\n\r\n}\r\n\r\nextern int check_rb_nil(VALUE value) {\r\n\r\n    return NIL_P(value);\r\n\r\n}\r\n\r\nextern int check_rb_undef(VALUE value) {\r\n\r\n    return RB_TYPE_P(value, T_UNDEF);\r\n\r\n}\r\n\r\nextern int check_rb_string(VALUE value) {\r\n\r\n    return RB_TYPE_P(value, T_STRING);\r\n\r\n}\r\n\r\nextern int check_rb_symbol(VALUE value) {\r\n\r\n    return RB_TYPE_P(value, T_SYMBOL);\r\n\r\n}\r\n\r\nextern int check_rb_array(VALUE value) {   \r\n\r\n    return RB_TYPE_P(value, T_ARRAY);\r\n\r\n}\r\n\r\nextern int check_rb_hash(VALUE value) {\r\n\r\n    return RB_TYPE_P(value, T_HASH);\r\n\r\n}\r\n\r\nextern int check_rb_data(VALUE value) {\r\n\r\n    return RB_TYPE_P(value, T_DATA);\r\n\r\n}\r\n\r\nextern int get_rb_fixnum(VALUE value) {\r\n\r\n    return FIX2INT(value);\r\n\r\n}\r\n\r\nextern double get_rb_float(VALUE value) {\r\n\r\n    return NUM2DBL(value);\r\n\r\n}\r\n\r\nextern bool get_rb_bool(VALUE value) {\r\n\r\n    return (value != Qfalse);\r\n\r\n}\r\n\r\nextern const char* get_rb_string(void* mrb, VALUE value) {\r\n\r\n    return rb_string_value_cstr(&value);\r\n\r\n}\r\n"
  },
  {
    "path": "glue/mri/script_helper.c",
    "content": "#include <ruby.h>\r\n\r\nextern void* open_interpreter(void) {\r\n\r\n  static int first_run = 1;\r\n\r\n  if(!first_run) {\r\n\r\n    printf(\"ERROR: Only one Ruby interpreter can be used at this point.\\n\");\r\n    return (void*) 0;\r\n\r\n  }\r\n\r\n  RUBY_INIT_STACK;\r\n  ruby_init();\r\n\r\n  first_run = 0;\r\n\r\n  return (void*) 0;\r\n\r\n}\r\n\r\nextern void close_interpreter(void* rb) {\r\n\r\n  static int first_run = 1;\r\n\r\n  if(!first_run) {\r\n\r\n    return;\r\n\r\n  }\r\n\r\n  first_run = 0;\r\n\r\n  ruby_cleanup(0);\r\n\r\n}\r\n\r\nextern void load_script_from_file(void* rb, const char* filename) {\r\n\r\n  static int first_run = 1;\r\n\r\n  char* args[2] = {\"test\", (char*) filename};\r\n  \r\n  if(!first_run) {\r\n\r\n    printf(\"ERROR: Ruby scripts can only be run once at this point.\\n\");\r\n    return;\r\n\r\n  }\r\n\r\n  void* options = ruby_options(2, args);\r\n\r\n  int ex_node_status;\r\n  int ex_node_return = ruby_executable_node(options, &ex_node_status);\r\n\r\n  if(!ex_node_return) {\r\n\r\n    printf(\"Error: File %s could not be executed.\\n\", filename);\r\n    ruby_cleanup(ex_node_status);\r\n    return;\r\n\r\n  }\r\n\r\n  int return_value = ruby_exec_node(options);\r\n\r\n  VALUE exception = rb_errinfo();\r\n  if(exception != Qnil) {\r\n\r\n    VALUE exception_str = rb_inspect(exception);\r\n\r\n    printf(\"%s\\n\", rb_string_value_cstr(&exception_str));\r\n\r\n  }\r\n\r\n  first_run = 0;\r\n\r\n  //! TODO: Fix segfaults at second execution\r\n\r\n}\r\n\r\nextern VALUE execute_script_line(void* rb, const char* text) {\r\n\r\n  int status;\r\n  VALUE result = rb_eval_string_protect(text, &status);\r\n\r\n  if(status) {\r\n\r\n    VALUE exception = rb_errinfo();\r\n    VALUE exception_str = rb_inspect(exception);\r\n\r\n    //! TODO: Are there any internal methods to print this prettier?\r\n\r\n    printf(\"%s\\n\", rb_string_value_cstr(&exception_str));\r\n\r\n  }\r\n\r\n  return result;\r\n\r\n}"
  },
  {
    "path": "glue/mruby/data_helper.c",
    "content": "#include <mruby.h>\r\n#include <mruby/class.h>\r\n#include <mruby/data.h>\r\n#include <mruby/array.h>\r\n#include <mruby/string.h>\r\n#include <mruby/variable.h>\r\n#include <string.h>\r\n\r\nextern const mrb_data_type* data_type(mrb_value value) {\r\n\r\n    return DATA_TYPE(value);\r\n\r\n}\r\n\r\nextern void set_instance_tt_as_data(struct RClass* ruby_class) {\r\n\r\n    MRB_SET_INSTANCE_TT(ruby_class, MRB_TT_DATA);\r\n\r\n}\r\n\r\nextern mrb_value new_empty_object(mrb_state* mrb, struct RClass* ruby_class, void* data_ptr, const mrb_data_type* data_type) {\r\n\r\n    return mrb_obj_value(mrb_data_object_alloc(mrb, ruby_class, data_ptr, data_type));\r\n\r\n}\r\n\r\nextern void* get_data_ptr(mrb_value ruby_object) {\r\n\r\n    return DATA_PTR(ruby_object);\r\n\r\n}\r\n\r\nextern void set_data_ptr_and_type(mrb_value ruby_object, void* data, mrb_data_type* data_type) {\r\n\r\n    DATA_PTR(ruby_object) = data;\r\n    DATA_TYPE(ruby_object) = data_type;\r\n\r\n}\r\n\r\nextern struct RClass* get_class_of_obj(mrb_state* mrb, mrb_value object) {\r\n\r\n    return mrb_class(mrb, object);\r\n\r\n}\r\n\r\nextern mrb_sym convert_to_mrb_sym(mrb_state* mrb, const char* str) {\r\n\r\n    return mrb_intern(mrb, str, strlen(str));\r\n\r\n}\r\n\r\nextern size_t array_length(mrb_value array) {\r\n\r\n    return ARY_LEN(mrb_ary_ptr(array));\r\n\r\n}\r\n\r\nextern mrb_value get_mrb_obj_value(void* p) {\r\n\r\n    return mrb_obj_value(p);\r\n\r\n}\r\n\r\nextern mrb_value mrb_gv_get_helper(mrb_state* mrb, const char* name) {\r\n\r\n  mrb_sym sym = convert_to_mrb_sym(mrb, name);\r\n  return mrb_gv_get(mrb, sym);\r\n  \r\n}\r\n\r\nextern void mrb_gv_set_helper(mrb_state* mrb, const char* name, mrb_value value) {\r\n\r\n  mrb_sym sym = convert_to_mrb_sym(mrb, name);\r\n  mrb_gv_set(mrb, sym, value);\r\n  \r\n}\r\n"
  },
  {
    "path": "glue/mruby/error_helper.c",
    "content": "#include <mruby.h>\r\n\r\nextern void mrb_raise_runtime_error(mrb_state* mrb, const char* msg) {\r\n\r\n  mrb_raise(mrb, E_RUNTIME_ERROR, msg);\r\n\r\n}\r\n\r\nextern void mrb_raise_type_error(mrb_state* mrb, const char* msg) {\r\n\r\n  mrb_raise(mrb, E_TYPE_ERROR, msg);\r\n\r\n}\r\n\r\nextern void mrb_raise_argument_error(mrb_state* mrb, const char* msg) {\r\n\r\n  mrb_raise(mrb, E_ARGUMENT_ERROR, msg);\r\n\r\n}\r\n\r\nextern void mrb_raise_index_error(mrb_state* mrb, const char* msg) {\r\n\r\n  mrb_raise(mrb, E_INDEX_ERROR, msg);\r\n\r\n}\r\n\r\nextern void mrb_raise_range_error(mrb_state* mrb, const char* msg) {\r\n\r\n  mrb_raise(mrb, E_RANGE_ERROR, msg);\r\n\r\n}\r\n\r\nextern void mrb_raise_name_error(mrb_state* mrb, const char* msg) {\r\n\r\n  mrb_raise(mrb, E_NAME_ERROR, msg);\r\n\r\n}\r\n\r\nextern void mrb_raise_script_error(mrb_state* mrb, const char* msg) {\r\n\r\n  mrb_raise(mrb, E_SCRIPT_ERROR, msg);\r\n\r\n}\r\n\r\nextern void mrb_raise_not_implemented_error(mrb_state* mrb, const char* msg) {\r\n\r\n  mrb_raise(mrb, E_NOTIMP_ERROR, msg);\r\n\r\n}\r\n\r\nextern void mrb_raise_key_error(mrb_state* mrb, const char* msg) {\r\n\r\n  mrb_raise(mrb, E_KEY_ERROR, msg);\r\n\r\n}\r\n\r\nextern void clear_last_mrb_error(mrb_state* mrb) {\r\n\r\n  mrb->exc = NULL;\r\n\r\n}\r\n\r\nextern mrb_value get_last_mrb_error(mrb_state* mrb) {\r\n\r\n  return mrb_obj_value(mrb->exc);\r\n\r\n}\r\n"
  },
  {
    "path": "glue/mruby/return_functions.c",
    "content": "#include <mruby.h>\r\n#include <mruby/class.h>\r\n#include <mruby/data.h>\r\n#include <mruby/string.h>\r\n#include <string.h>\r\n\r\nextern struct RClass* get_object_class(mrb_state* mrb) {\r\n\r\n    return mrb->object_class;\r\n\r\n}\r\n\r\nextern mrb_value get_nil_value() {\r\n\r\n    return mrb_nil_value();\r\n\r\n}\r\n\r\nextern mrb_value get_false_value() {\r\n\r\n    return mrb_false_value();\r\n  \r\n}\r\n\r\nextern mrb_value get_true_value() {\r\n\r\n    return mrb_true_value();\r\n  \r\n}\r\n\r\nextern mrb_value get_fixnum_value(mrb_int value) {\r\n\r\n    return mrb_fixnum_value(value);\r\n\r\n}\r\n\r\nextern mrb_value get_bool_value(mrb_bool value) {\r\n\r\n    return mrb_bool_value(value);\r\n\r\n}\r\n\r\nextern mrb_value get_float_value(mrb_state* mrb, mrb_float value) {\r\n\r\n    return mrb_float_value(mrb, value);\r\n\r\n}\r\n\r\nextern mrb_value get_string_value(mrb_state* mrb, char* value) {\r\n\r\n    return mrb_str_new(mrb, value, strlen(value));\r\n\r\n}\r\n\r\nextern mrb_value get_symbol_value_of_string(mrb_state* mrb, char* value) {\r\n\r\n    mrb_sym sym = mrb_intern(mrb, value, strlen(value));\r\n    return mrb_symbol_value(sym);\r\n\r\n}\r\n\r\nextern int check_mrb_fixnum(mrb_value value) {\r\n\r\n    return mrb_integer_p(value);\r\n\r\n}\r\n\r\nextern int check_mrb_float(mrb_value value) {\r\n\r\n    return mrb_float_p(value);\r\n\r\n}\r\n\r\nextern int check_mrb_true(mrb_value value) {\r\n\r\n    return mrb_true_p(value);\r\n\r\n}\r\n\r\nextern int check_mrb_false(mrb_value value) {\r\n\r\n    return mrb_false_p(value);\r\n\r\n}\r\n\r\nextern int check_mrb_nil(mrb_value value) {\r\n\r\n    return mrb_nil_p(value);\r\n\r\n}\r\n\r\nextern int check_mrb_undef(mrb_value value) {\r\n\r\n    return mrb_undef_p(value);\r\n\r\n}\r\n\r\nextern int check_mrb_string(mrb_value value) {\r\n\r\n    return mrb_string_p(value);\r\n\r\n}\r\n\r\nextern int check_mrb_symbol(mrb_value value) {\r\n\r\n    return mrb_symbol_p(value);\r\n\r\n}\r\n\r\nextern int check_mrb_array(mrb_value value) {   \r\n\r\n    return mrb_array_p(value);\r\n\r\n}\r\n\r\nextern int check_mrb_hash(mrb_value value) {\r\n\r\n    return mrb_hash_p(value);\r\n\r\n}\r\n\r\nextern int check_mrb_data(mrb_value value) {\r\n\r\n    return mrb_data_p(value);\r\n\r\n}\r\n\r\nextern mrb_int get_mrb_fixnum(mrb_value value) {\r\n\r\n    return mrb_integer(value);\r\n\r\n}\r\n\r\nextern mrb_float get_mrb_float(mrb_value value) {\r\n\r\n    return mrb_float(value);\r\n\r\n}\r\n\r\nextern mrb_bool get_mrb_bool(mrb_value value) {\r\n\r\n    return mrb_bool(value);\r\n\r\n}\r\n\r\nextern const char* get_mrb_string(mrb_state* mrb, mrb_value value) {\r\n\r\n    return mrb_str_to_cstr(mrb, value);\r\n\r\n}\r\n"
  },
  {
    "path": "glue/mruby/script_helper.c",
    "content": "#include <mruby.h>\r\n#include <mruby/compile.h>\r\n#include <mruby/dump.h>\r\n#include <mruby/proc.h>\r\n#include <mruby/internal.h>\r\n\r\n#include <stdlib.h>\r\n\r\nextern mrb_value load_script_from_file(mrb_state* mrb, const char* filename) {\r\n\r\n    mrbc_context* new_context = mrbc_context_new(mrb);\r\n    mrbc_filename(mrb, new_context, filename);\r\n\r\n    FILE* file = fopen(filename, \"r\");\r\n\r\n    if(!file) {\r\n\r\n        mrb_raisef(mrb, E_RUNTIME_ERROR, \"Could not load script file: %s\", filename);\r\n\r\n    }\r\n\r\n    int ai = mrb_gc_arena_save(mrb);\r\n    mrb_value status = mrb_load_file_cxt(mrb, file, new_context);\r\n    mrb_gc_arena_restore(mrb, ai);\r\n\r\n    if(file) fclose(file);\r\n\r\n    if(mrb->exc) mrb_print_error(mrb);\r\n\r\n    mrbc_context_free(mrb, new_context);\r\n\r\n    return status;\r\n\r\n}\r\n\r\nextern mrb_value execute_script_line(mrb_state* mrb, const char* str) {\r\n\r\n    mrbc_context* new_context = mrbc_context_new(mrb);\r\n    mrbc_filename(mrb, new_context, \"Script\");\r\n\r\n    int ai = mrb_gc_arena_save(mrb);\r\n    mrb_value status = mrb_load_string_cxt(mrb, str, new_context);\r\n    mrb_gc_arena_restore(mrb, ai);\r\n\r\n    if(mrb->exc) mrb_print_error(mrb);\r\n\r\n    mrbc_context_free(mrb, new_context);\r\n\r\n    return status;\r\n    \r\n}\r\n\r\nextern mrb_value load_bytecode_from_file(mrb_state* mrb, const char* filename) {\r\n\r\n    FILE* file = fopen(filename, \"r\");\r\n\r\n\tif (!file) {\r\n\r\n        //! TODO: Find out why this does trigger an unstoppable IOT signal\r\n        mrb_raisef(mrb, E_RUNTIME_ERROR, \"Could not load bytecode file: %s\", filename);\r\n\r\n\t}\r\n\r\n\tmrb_value status = mrb_load_irep_file(mrb, file);\r\n\r\n\tif (file) fclose(file);\r\n\r\n    if(mrb->exc) mrb_print_error(mrb);\r\n\r\n    return status;\r\n\r\n}\r\n\r\nextern mrb_value execute_bytecode(mrb_state* mrb, const uint8_t* bytecode) {\r\n\r\n    int ai = mrb_gc_arena_save(mrb);\r\n    mrb_value status = mrb_load_irep(mrb, bytecode);\r\n    mrb_gc_arena_restore(mrb, ai);\r\n\r\n    return status;\r\n\r\n}\r\n\r\nextern int transform_script_to_bytecode(const char* filename, const char* target_filename) {\r\n\r\n    mrb_state *mrb = mrb_open_core(NULL, NULL);\r\n\r\n    mrbc_context* new_context = mrbc_context_new(mrb);\r\n    new_context->no_exec = TRUE;\r\n    mrbc_filename(mrb, new_context, filename);\r\n\r\n    FILE* file = fopen(filename, \"rb\");\r\n\r\n    if(!file) {\r\n\r\n        return 1;\r\n\r\n    }\r\n\r\n    mrb_value result = mrb_load_file_cxt(mrb, file, new_context);\r\n\r\n    if (mrb_undef_p(result)) {\r\n\r\n        return 2;\r\n\r\n    }\r\n\r\n    if(file) fclose(file);\r\n\r\n    const mrb_irep *irep = mrb_proc_ptr(result)->body.irep;\r\n\r\n    FILE* outfile = fopen(target_filename, \"wb\");\r\n\r\n    if (!outfile) {\r\n\r\n        return 3;\r\n\r\n    }\r\n\r\n    mrb_dump_irep_binary(mrb, irep, 4, outfile);\r\n\r\n    if(outfile) fclose(outfile);\r\n\r\n    mrbc_context_free(mrb, new_context);\r\n\r\n    return 0;\r\n\r\n}\r\n\r\ntypedef struct bytecode_container {\r\n\r\n    uint8_t* content;\r\n    size_t size;\r\n    int error_code;\r\n    int result;\r\n\r\n} bytecode_container_t;\r\n\r\nextern bytecode_container_t transform_script_to_bytecode_container(const char* filename) {\r\n\r\n    mrb_state *mrb = mrb_open_core(NULL, NULL);\r\n\r\n    mrbc_context* new_context = mrbc_context_new(mrb);\r\n    new_context->no_exec = TRUE;\r\n    mrbc_filename(mrb, new_context, filename);\r\n\r\n    bytecode_container_t container = {NULL, 0, 0, 0};\r\n\r\n    FILE* file = fopen(filename, \"rb\");\r\n\r\n    if(!file) {\r\n\r\n        container.error_code = 1;\r\n        return container;\r\n\r\n    }\r\n\r\n    mrb_value result = mrb_load_file_cxt(mrb, file, new_context);\r\n\r\n    if (mrb_undef_p(result)) {\r\n\r\n        container.error_code = 2;\r\n        return container;\r\n\r\n    }\r\n\r\n    if(file) fclose(file);\r\n\r\n    const mrb_irep *irep = mrb_proc_ptr(result)->body.irep;\r\n\r\n    uint8_t *bin = NULL;\r\n    size_t bin_size = 0;\r\n\r\n    container.result = mrb_dump_irep(mrb, irep, 4, &bin, &bin_size);\r\n\r\n    container.content = (uint8_t*) malloc(bin_size * sizeof(uint8_t));\r\n    memcpy(container.content, bin, bin_size);\r\n    container.size = bin_size;\r\n\r\n    return container;\r\n\r\n}\r\n\r\nextern bytecode_container_t transform_proc_to_bytecode_container(mrb_state* mrb, mrb_value proc_object) {\r\n\r\n    bytecode_container_t container = {NULL, 0, 0, 0};\r\n\r\n    const mrb_irep *irep = mrb_proc_ptr(proc_object)->body.irep;\r\n\r\n    uint8_t *bin = NULL;\r\n    size_t bin_size = 0;\r\n\r\n    container.result = mrb_dump_irep(mrb, irep, 4, &bin, &bin_size);\r\n\r\n    container.content = (uint8_t*) malloc(bin_size * sizeof(uint8_t));\r\n    memcpy(container.content, bin, bin_size);\r\n    container.size = bin_size;\r\n\r\n    return container;\r\n\r\n}\r\n\r\nextern void free_bytecode_container(bytecode_container_t container) {\r\n\r\n    free(container.content);\r\n\r\n}\r\n\r\nextern int mrb_gc_arena_save_helper(mrb_state* mrb) {\r\n\r\n    return mrb_gc_arena_save(mrb);\r\n\r\n}\r\n\r\n\r\nextern void mrb_gc_arena_restore_helper(mrb_state* mrb, int idx) {\r\n\r\n    mrb_gc_arena_restore(mrb, idx);\r\n\r\n}\r\n"
  },
  {
    "path": "install.cr",
    "content": "command = {% if flag?(:win32) %}\n  # TODO: Is there a better solution?\n  \"cmd /C rake build_shard\"\n{% else %}\n  \"rake build_shard\"\n{% end %}\n\n# system() inherits the parent process' IO descriptors.\n# Failing here will cause the shards process to output this; if we succeed, it is silenced automatically.\nraise Exception.new(\"Failed to install Anyolite\") unless system(command)\n\n"
  },
  {
    "path": "shard.yml",
    "content": "name: anyolite\nversion: 1.1.1\n\nauthors:\n  - Hadeweka\n\ndescription: |\n  A library which allows for binding crystal classes and methods to an embedded mruby interpreter.\n\nscripts:\n  postinstall: crystal run install.cr\n\nlicense: MIT\n\ncrystal: '>= 1.0.0'\n"
  },
  {
    "path": "src/BytecodeCompiler.cr",
    "content": "require \"./Main.cr\"\n\nAnyolite::Preloader.transform_script_to_bytecode(ARGV[0], ARGV[1])\n"
  },
  {
    "path": "src/BytecodeGetter.cr",
    "content": "require \"./Main.cr\"\n\nputs Anyolite::Preloader.transform_script_to_bytecode_array(ARGV[0])\n"
  },
  {
    "path": "src/Macro.cr",
    "content": "module Anyolite\n  # Helper methods which should not be used for trivial cases in the final version\n  module Macro\n  end\nend\n\nrequire \"./macros/RubyTypes.cr\"\nrequire \"./macros/ArgTuples.cr\"\nrequire \"./macros/ArgConversions.cr\"\nrequire \"./macros/UnionCasts.cr\"\nrequire \"./macros/RubyConversions.cr\"\nrequire \"./macros/FunctionCalls.cr\"\nrequire \"./macros/ObjectAllocations.cr\"\nrequire \"./macros/Wrappers.cr\"\nrequire \"./macros/WrapMethodIndex.cr\"\nrequire \"./macros/WrapAll.cr\"\nrequire \"./macros/FunctionGenerators.cr\"\n"
  },
  {
    "path": "src/Main.cr",
    "content": "require \"./RbInternal.cr\"\r\n\r\nrequire \"./RbInterpreter.cr\"\r\nrequire \"./RbClass.cr\"\r\nrequire \"./RbCast.cr\"\r\nrequire \"./Macro.cr\"\r\nrequire \"./RbClassCache.cr\"\r\nrequire \"./RbTypeCache.cr\"\r\nrequire \"./RbModule.cr\"\r\nrequire \"./RbRefTable.cr\"\r\nrequire \"./RbArgCache.cr\"\r\nrequire \"./Preloader.cr\"\r\n\r\n# Main wrapper module, which should be covering most of the use cases.\r\nmodule Anyolite\r\n  # Special struct representing undefined values in mruby.\r\n  struct Undefined\r\n    # :nodoc:\r\n    def initialize\r\n    end\r\n  end\r\n\r\n  # Use this special constant in case of a function to wrap, which has only an operator as a name.\r\n  struct Empty\r\n    # :nodoc:\r\n    def initialize\r\n    end\r\n  end\r\n\r\n  # Internal class to hide the `Struct` *T* in a special class\r\n  # to obtain all class-related properties.\r\n  class StructWrapper(T)\r\n    @content : T | Nil = nil\r\n\r\n    def initialize(value)\r\n      @content = value\r\n    end\r\n\r\n    def content : T\r\n      if c = @content\r\n        c\r\n      else\r\n        # This should not be called theoretically\r\n        raise(\"Content of struct wrapper for #{T} is undefined!\")\r\n      end\r\n    end\r\n\r\n    def content=(value)\r\n      @content = value\r\n    end\r\n  end\r\n\r\n  # Class to contain Ruby values in a GC-protected container\r\n  class RbRef\r\n    @value : RbCore::RbValue\r\n\r\n    # Create a new container with *value* as content\r\n    def initialize(value : RbCore::RbValue)\r\n      @value = value\r\n      RbCore.rb_gc_register(RbRefTable.get_current_interpreter, value)\r\n    end\r\n\r\n    # Return the contained value\r\n    def value\r\n      @value\r\n    end\r\n\r\n    # Return `true` if the value is undefined, otherwise `false`\r\n    def is_undef?\r\n      RbCast.check_for_undef(@value)\r\n    end\r\n\r\n    # Return `true` if the value is a Ruby bool, otherwise `false`\r\n    def is_bool?\r\n      RbCast.check_for_bool(@value)\r\n    end\r\n\r\n    # Return `true` if the value is a Ruby nil, otherwise `false`\r\n    def is_nil?\r\n      RbCast.check_for_nil(@value)\r\n    end\r\n\r\n    # Return `true` if the value is a Ruby fixnum, otherwise `false`\r\n    def is_fixnum?\r\n      RbCast.check_for_fixnum(@value)\r\n    end\r\n\r\n    # Return `true` if the value is a Ruby float, otherwise `false`\r\n    def is_float?\r\n      RbCast.check_for_float(@value)\r\n    end\r\n\r\n    # Return `true` if the value is a Ruby string, otherwise `false`\r\n    def is_string?\r\n      RbCast.check_for_string(@value)\r\n    end\r\n\r\n    # Return `true` if the value is a Ruby symbol, otherwise `false`\r\n    def is_symbol?\r\n      RbCast.check_for_symbol(@value)\r\n    end\r\n\r\n    # Return `true` if the value is a Ruby array, otherwise `false`\r\n    def is_array?\r\n      RbCast.check_for_array(@value)\r\n    end\r\n\r\n    # Return `true` if the value is a Ruby hash, otherwise `false`\r\n    def is_hash?\r\n      RbCast.check_for_hash(@value)\r\n    end\r\n\r\n    # Return `true` if the value is a wrapped objects, otherwise `false`\r\n    def is_custom?\r\n      RbCast.check_for_data(@value)\r\n    end\r\n\r\n    # Return `true` if the value is a wrapped object of class *class_name*, otherwise `false`\r\n    def is_custom?(class_name)\r\n      RbCast.check_custom_type(RbRefTable.get_current_interpreter, value, class_name)\r\n    end\r\n\r\n    # :nodoc:\r\n    def finalize\r\n      RbCore.rb_gc_unregister(RbRefTable.get_current_interpreter, value) if RbRefTable.check_interpreter\r\n    end\r\n\r\n    # :nodoc:\r\n    def to_unsafe\r\n      @value\r\n    end\r\n  end\r\n\r\n  # Undefined mruby value.\r\n  Undef = Undefined.new\r\n\r\n  # Returns the current implementation (either `:mruby` or `:mri`) as a `Symbol`.\r\n  macro implementation\r\n    {% if flag?(:anyolite_implementation_ruby_3) %}\r\n      :mri\r\n    {% else %}\r\n      :mruby\r\n    {% end %}\r\n  end\r\n\r\n  # Returns the depth of interpreter calls\r\n  def self.get_interpreter_depth\r\n    Anyolite::RbRefTable.get_current_interpreter.depth\r\n  end\r\n\r\n  # Wraps any Crystal object into an `RbRef`, securing it from the Ruby GC.\r\n  # This prevents the object from being deleted in Ruby, as long as this reference exists in Crystal.\r\n  # \r\n  # Note that this might lead to memory leaks if you close the Ruby interpreter before\r\n  # all of these objects are cleaned up properly using the Crystal GC.\r\n  # However, this is only a problem if you open much more than one interpreter while running a program.\r\n  def self.create_rb_ref(obj)\r\n    Anyolite::RbRef.new(Anyolite::RbCast.return_value(Anyolite::RbRefTable.get_current_interpreter.to_unsafe, obj))\r\n  end\r\n\r\n  # Disables any function that allows for running external programs \r\n  def self.disable_program_execution\r\n    Anyolite.eval(\"class IO; def self._popen(command, mode, **opts); raise \\\"No system commands allowed!\\\"; end; end\")\r\n    Anyolite.eval(\"class IO; def self.popen(command, mode = 'r', **opts, &block); raise \\\"No system commands allowed!\\\"; end; end\")\r\n  end\r\n\r\n  # Checks whether *value* is referenced in the current reference table.\r\n  macro referenced_in_ruby?(value)\r\n    !!Anyolite::RbRefTable.is_registered?(Anyolite::RbRefTable.get_object_id({{value}}))\r\n  end\r\n\r\n  # Returns the `RbValue` of the `Class`, `Module` or `String` *crystal_class*.\r\n  macro get_rb_class_obj_of(crystal_class)\r\n    {% if crystal_class.is_a?(StringLiteral) %}\r\n      %rb = Anyolite::RbRefTable.get_current_interpreter\r\n      Anyolite::RbCore.get_rb_obj_value(Anyolite::RbCore.rb_class_get(%rb, {{crystal_class}}))\r\n    {% else %}\r\n      Anyolite::RbCore.get_rb_obj_value(Anyolite::RbClassCache.get({{crystal_class}}))\r\n    {% end %}\r\n  end\r\n\r\n  # Returns a cached block argument (or `nil`, if none given) in form of a `RbRef`, if enabled.\r\n  # Otherwise, an error will be triggered.\r\n  macro obtain_given_rb_block\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n\r\n    if %bc = Anyolite::RbArgCache.get_block_cache\r\n      if Anyolite::RbCast.check_for_nil(%bc.value)\r\n        nil\r\n      else\r\n        %bc_ref = Anyolite::RbRef.new(%bc.value)\r\n        %bc_ref\r\n      end\r\n    else\r\n      raise \"This method does not accept block arguments.\"\r\n    end\r\n  end\r\n\r\n  # Calls the Ruby block *block_value*, given as a `RbRef`, with the arguments *args*\r\n  # as an `Array` of castable Crystal values (`nil` for none).\r\n  #\r\n  # If *cast_to* is set to a `Class` or similar, it will automatically cast\r\n  # the result to a Crystal value of that class, otherwise, it will return\r\n  # a `RbRef` value containing the result.\r\n  #\r\n  # If needed, *context* can be set to a `Path` in order to specify *cast_to*.\r\n  macro call_rb_block(block_value, args = nil, cast_to = nil, context = nil)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    {% options = {:context => context} %}\r\n\r\n    if %rb_block = {{block_value}}\r\n      {% if args %}\r\n        %argc = {{args}}.size\r\n        %argv = Pointer(Anyolite::RbCore::RbValue).malloc(size: %argc) do |i|\r\n          Anyolite::RbCast.return_value(%rb.to_unsafe, {{args}}[i])\r\n        end\r\n\r\n        %block_return_value = Anyolite::RbCore.rb_call_block_with_args(%rb, %rb_block.value, %argc, %argv)\r\n      {% else %}\r\n        %block_return_value = Anyolite::RbCore.rb_call_block(%rb, %rb_block.value, Anyolite::RbCast.return_nil)\r\n      {% end %}\r\n\r\n      {% if cast_to %}\r\n        Anyolite::Macro.convert_from_ruby_to_crystal(%rb.to_unsafe, %block_return_value, {{cast_to}}, options: {{options}})\r\n      {% else %}\r\n        Anyolite::RbRef.new(%block_return_value)\r\n      {% end %}\r\n    else\r\n      raise \"Empty block argument.\"\r\n    end\r\n  end\r\n\r\n  # Casts the `RbRef` *rbref* to the Crystal `Class` *cast_type*.\r\n  #\r\n  # If needed, *context* can be set to a `Path` in order to specify *cast_to*.\r\n  macro cast_to_crystal(rbref, cast_type, context = nil)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    {% options = {:context => context} %}\r\n\r\n    Anyolite::Macro.convert_from_ruby_to_crystal(%rb.to_unsafe, {{rbref}}.value, {{cast_type}}, options: {{options}})\r\n  end\r\n\r\n  # Raises a Ruby runtime error with `String` *message*.\r\n  macro raise_runtime_error(message)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    Anyolite::RbCore.rb_raise_runtime_error(%rb.to_unsafe, {{message}}.to_unsafe)\r\n  end\r\n\r\n  # Raises a Ruby type error with `String` *message*.\r\n  macro raise_type_error(message)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    Anyolite::RbCore.rb_raise_type_error(%rb.to_unsafe, {{message}}.to_unsafe)\r\n  end\r\n\r\n  # Raises a Ruby argument error with `String` *message*.\r\n  macro raise_argument_error(message)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    Anyolite::RbCore.rb_raise_argument_error(%rb.to_unsafe, {{message}}.to_unsafe)\r\n  end\r\n\r\n  # Raises a Ruby index error with `String` *message*.\r\n  macro raise_index_error(message)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    Anyolite::RbCore.rb_raise_index_error(%rb.to_unsafe, {{message}}.to_unsafe)\r\n  end\r\n\r\n  # Raises a Ruby range error with `String` *message*.\r\n  macro raise_range_error(message)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    Anyolite::RbCore.rb_raise_range_error(%rb.to_unsafe, {{message}}.to_unsafe)\r\n  end\r\n\r\n  # Raises a Ruby name error with `String` *message*.\r\n  macro raise_name_error(message)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    Anyolite::RbCore.rb_raise_name_error(%rb.to_unsafe, {{message}}.to_unsafe)\r\n  end\r\n\r\n  # Raises a Ruby script error with `String` *message*.\r\n  macro raise_script_error(message)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    Anyolite::RbCore.rb_raise_script_error(%rb.to_unsafe, {{message}}.to_unsafe)\r\n  end\r\n\r\n  # Raises a Ruby non-implementation error with `String` *message*.\r\n  macro raise_not_implemented_error(message)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    Anyolite::RbCore.rb_raise_not_implemented_error(%rb.to_unsafe, {{message}}.to_unsafe)\r\n  end\r\n\r\n  # Raises a Ruby key error with `String` *message*.\r\n  macro raise_key_error(message)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    Anyolite::RbCore.rb_raise_key_error(%rb.to_unsafe, {{message}}.to_unsafe)\r\n  end\r\n\r\n  # Checks whether the Ruby function *name* (`String` or `Symbol`) is defined\r\n  # for the Crystal object or `RbRef` *value*.\r\n  macro does_obj_respond_to(value, name)\r\n    %method_name = {{name}}\r\n    \r\n    if !%method_name.is_a?(Symbol) && !%method_name.is_a?(String)\r\n      raise \"Given name #{%method_name} is neither a String nor a Symbol.\"\r\n    end\r\n\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    %obj = Anyolite::RbCast.convert_to_unsafe_rb_value(%rb.to_unsafe, {{value}})\r\n    %name = Anyolite::RbCore.convert_to_rb_sym(%rb, %method_name.to_s)\r\n\r\n    Anyolite::RbCore.rb_respond_to(%rb, %obj, %name) == 0 ? false : true\r\n  end\r\n\r\n  # Checks whether the Ruby function *name* (`String` or `Symbol`) is defined\r\n  # for the Crystal `Class`, `Module` or `String` *crystal_class*.\r\n  macro does_class_respond_to(crystal_class, name)\r\n    %method_name = {{name}}\r\n    \r\n    if !%method_name.is_a?(Symbol) && !%method_name.is_a?(String)\r\n      raise \"Given name #{%method_name} is neither a String nor a Symbol.\"\r\n    end\r\n\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    %rb_class = Anyolite.get_rb_class_obj_of({{crystal_class}})\r\n    %name = Anyolite::RbCore.convert_to_rb_sym(%rb, %method_name.to_s)\r\n\r\n    Anyolite::RbCore.rb_respond_to(%rb, %rb_class, %name) == 0 ? false : true\r\n  end\r\n\r\n  # TODO: Is it possible to add block args to the two methods below?\r\n\r\n  # Calls the Ruby method with `String` or `Symbol` *name* for the Crystal object or `RbRef` *value* and the\r\n  # arguments *args* as an `Array` of castable Crystal values (`nil` for none).\r\n  # \r\n  # An additional block can be passed as `RbRef` *block*.\r\n  #\r\n  # If *cast_to* is set to a `Class` or similar, it will automatically cast\r\n  # the result to a Crystal value of that class, otherwise, it will return\r\n  # a `RbRef` value containing the result.\r\n  #\r\n  # If needed, *context* can be set to a `Path` in order to specify *cast_to*.\r\n  macro call_rb_method_of_object(value, name, args = nil, block = nil, cast_to = nil, context = nil)\r\n    %method_name = {{name}}\r\n    \r\n    if !%method_name.is_a?(Symbol) && !%method_name.is_a?(String)\r\n      raise \"Given name #{%method_name} is neither a String nor a Symbol.\"\r\n    end\r\n    \r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    %obj = Anyolite::RbCast.convert_to_unsafe_rb_value(%rb.to_unsafe, {{value}})\r\n    %name = Anyolite::RbCore.convert_to_rb_sym(%rb, %method_name.to_s)\r\n\r\n    {% options = {:context => context} %}\r\n\r\n    {% if args %}\r\n      %argc = {{args}}.size\r\n      %argv = Pointer(Anyolite::RbCore::RbValue).malloc(size: %argc) do |i|\r\n        Anyolite::RbCast.return_value(%rb.to_unsafe, {{args}}[i])\r\n      end\r\n    {% else %}\r\n      %argc = 0\r\n      %argv = [] of Anyolite::RbCore::RbValue\r\n    {% end %}\r\n\r\n    %rb.depth += 1\r\n\r\n    {% if block %}\r\n      %call_result = Anyolite::RbCore.rb_funcall_argv_with_block(%rb, %obj, %name, %argc, %argv, {{block}}.not_nil!.to_unsafe)\r\n    {% else %}\r\n      %call_result = Anyolite::RbCore.rb_funcall_argv(%rb, %obj, %name, %argc, %argv)\r\n    {% end %}\r\n\r\n    %rb.depth -= 1\r\n\r\n    {% if cast_to %}\r\n      Anyolite::Macro.convert_from_ruby_to_crystal(%rb.to_unsafe, %call_result, {{cast_to}}, options: {{options}})\r\n    {% else %}\r\n      Anyolite::RbRef.new(%call_result)\r\n    {% end %}\r\n  end\r\n\r\n  # Calls the Ruby method with `String` or `Symbol` *name* for `self` and the\r\n  # arguments *args* as an `Array` of castable Crystal values (`nil` for none).\r\n  # \r\n  # An additional block can be passed as `RbRef` *block*.\r\n  #\r\n  # If *cast_to* is set to a `Class` or similar, it will automatically cast\r\n  # the result to a Crystal value of that class, otherwise, it will return\r\n  # a `RbRef` value containing the result.\r\n  #\r\n  # If needed, *context* can be set to a `Path` in order to specify *cast_to*.\r\n  macro call_rb_method(name, args = nil, block = nil, cast_to = nil, context = nil)\r\n    Anyolite.call_rb_method_of_object(self, {{name}}, {{args}}, {{block}}, cast_to: {{cast_to}}, context: {{context}})\r\n  end\r\n\r\n  # Calls the Ruby method with `String` or `Symbol` *name* for `self.class` and the\r\n  # arguments *args* as an `Array` of castable Crystal values (`nil` for none).\r\n  # \r\n  # An additional block can be passed as `RbRef` *block*.\r\n  #\r\n  # If *cast_to* is set to a `Class` or similar, it will automatically cast\r\n  # the result to a Crystal value of that class, otherwise, it will return\r\n  # a `RbRef` value containing the result.\r\n  #\r\n  # If needed, *context* can be set to a `Path` in order to specify *cast_to*.\r\n  macro call_rb_class_method(name, args = nil, block = nil, cast_to = nil, context = nil)\r\n    Anyolite.call_rb_method_of_class(self.class, {{name}}, {{args}}, {{block}}, cast_to: {{cast_to}}, context: {{context}})\r\n  end\r\n\r\n  # Calls the Ruby method with `String` or `Symbol` *name*\r\n  # for the Crystal `Class`, `Module` or `String` *crystal_class* and the\r\n  # arguments *args* as an `Array` of castable Crystal values (`nil` for none).\r\n  # \r\n  # An additional block can be passed as `RbRef` *block*.\r\n  #\r\n  # If *cast_to* is set to a `Class` or similar, it will automatically cast\r\n  # the result to a Crystal value of that class, otherwise, it will return\r\n  # a `RbRef` value containing the result.\r\n  #\r\n  # If needed, *context* can be set to a `Path` in order to specify *cast_to*.\r\n  macro call_rb_method_of_class(crystal_class, name, args = nil, block = nil, cast_to = nil, context = nil)\r\n    %rb_class = Anyolite.get_rb_class_obj_of({{crystal_class}})\r\n    Anyolite.call_rb_method_of_object(%rb_class, {{name}}, {{args}}, {{block}}, cast_to: {{cast_to}}, context: {{context}})\r\n  end\r\n\r\n  # TODO: Block arguments?\r\n\r\n  # Calls the Ruby expression *str*.\r\n  #\r\n  # If *cast_to* is set to a `Class` or similar, it will automatically cast\r\n  # the result to a Crystal value of that class, otherwise, it will return\r\n  # a `RbRef` value containing the result.\r\n  #\r\n  # If needed, *context* can be set to a `Path` in order to specify *cast_to*.\r\n  macro eval(str, cast_to = nil, context = nil)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    {% options = {:context => context} %}\r\n\r\n    %call_result = %rb.execute_script_line({{str}})\r\n    \r\n    {% if cast_to %}\r\n      Anyolite::Macro.convert_from_ruby_to_crystal(%rb.to_unsafe, %call_result, {{cast_to}}, options: {{options}})\r\n    {% else %}\r\n      Anyolite::RbRef.new(%call_result)\r\n    {% end %}\r\n  end\r\n\r\n  # Returns current object as a `RbRef`\r\n  macro self_in_rb\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    Anyolite::RbRef.new(Anyolite::RbCast.return_value(%rb.to_unsafe, self))\r\n  end\r\n\r\n  # Gets the Ruby instance variable with `String` or `Symbol` *name* for the Crystal object or `RbRef` *object*.\r\n  #\r\n  # If *cast_to* is set to a `Class` or similar, it will automatically cast\r\n  # the result to a Crystal value of that class, otherwise, it will return\r\n  # a `RbRef` value containing the result.\r\n  #\r\n  # If needed, *context* can be set to a `Path` in order to specify *cast_to*.\r\n  macro get_iv(object, name, cast_to = nil, context = nil)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    %obj = Anyolite::RbCast.convert_to_unsafe_rb_value(%rb.to_unsafe, {{object}})\r\n    %name = Anyolite::RbCore.convert_to_rb_sym(%rb, {{name}}.to_s)\r\n\r\n    {% options = {:context => context} %}\r\n\r\n    %result = Anyolite::RbCore.rb_iv_get(%rb, %obj, %name)\r\n\r\n    {% if cast_to %}\r\n      Anyolite::Macro.convert_from_ruby_to_crystal(%rb.to_unsafe, %result, {{cast_to}}, options: {{options}})\r\n    {% else %}\r\n      Anyolite::RbRef.new(%result)\r\n    {% end %}\r\n  end\r\n\r\n  # Sets the Ruby instance variable with `String` or `Symbol` *name* for the Crystal object or `RbRef` *object*\r\n  # to the Crystal value *value*.\r\n  #\r\n  # If *cast_to* is set to a `Class` or similar, it will automatically cast\r\n  # the result to a Crystal value of that class, otherwise, it will return\r\n  # a `RbRef` value containing the result.\r\n  #\r\n  # If needed, *context* can be set to a `Path` in order to specify *cast_to*.\r\n  macro set_iv(object, name, value)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    %obj = Anyolite::RbCast.convert_to_unsafe_rb_value(%rb.to_unsafe, {{object}})\r\n    %name = Anyolite::RbCore.convert_to_rb_sym(%rb, {{name}}.to_s)\r\n    %value = Anyolite::RbCast.return_value(%rb.to_unsafe, {{value}})\r\n\r\n    Anyolite::RbCore.rb_iv_set(%rb, %obj, %name, %value)\r\n  end\r\n\r\n  # Gets the Ruby class variable with `String` or `Symbol` *name* for the Crystal `Class`, `Module` or `String` *crystal_class*.\r\n  #\r\n  # If *cast_to* is set to a `Class` or similar, it will automatically cast\r\n  # the result to a Crystal value of that class, otherwise, it will return\r\n  # a `RbRef` value containing the result.\r\n  #\r\n  # If needed, *context* can be set to a `Path` in order to specify *cast_to*.\r\n  macro get_cv(crystal_class, name, cast_to = nil, context = nil)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    %rb_class = Anyolite.get_rb_class_obj_of({{crystal_class}})\r\n    %name = Anyolite::RbCore.convert_to_rb_sym(%rb, {{name}}.to_s)\r\n\r\n    {% options = {:context => context} %}\r\n\r\n    %result = Anyolite::RbCore.rb_cv_get(%rb, %rb_class, %name)\r\n\r\n    {% if cast_to %}\r\n      Anyolite::Macro.convert_from_ruby_to_crystal(%rb.to_unsafe, %result, {{cast_to}}, options: {{options}})\r\n    {% else %}\r\n      Anyolite::RbRef.new(%result)\r\n    {% end %}\r\n  end\r\n\r\n  # Sets the Ruby class variable with `String` or `Symbol` *name* for the Crystal `Class`, `Module` or `String` *crystal_class*\r\n  # to the value *value*.\r\n  #\r\n  # If *cast_to* is set to a `Class` or similar, it will automatically cast\r\n  # the result to a Crystal value of that class, otherwise, it will return\r\n  # a `RbRef` value containing the result.\r\n  #\r\n  # If needed, *context* can be set to a `Path` in order to specify *cast_to*.\r\n  macro set_cv(crystal_class, name, value)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    %rb_class = Anyolite.get_rb_class_obj_of({{crystal_class}})\r\n    %name = Anyolite::RbCore.convert_to_rb_sym(%rb, {{name}}.to_s)\r\n    %value = Anyolite::RbCast.return_value(%rb.to_unsafe, {{value}})\r\n\r\n    Anyolite::RbCore.rb_cv_set(%rb, %rb_class, %name, %value)\r\n  end\r\n\r\n  # Gets the Ruby global variable with `String` or `Symbol` *name*.\r\n  #\r\n  # If *cast_to* is set to a `Class` or similar, it will automatically cast\r\n  # the result to a Crystal value of that class, otherwise, it will return\r\n  # a `RbRef` value containing the result.\r\n  #\r\n  # If needed, *context* can be set to a `Path` in order to specify *cast_to*.\r\n  macro get_gv(name, cast_to = nil, context = nil)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    {% options = {:context => context} %}\r\n\r\n    %result = Anyolite::RbCore.rb_gv_get(%rb, {{name}}.to_s.to_unsafe)\r\n\r\n    {% if cast_to %}\r\n      Anyolite::Macro.convert_from_ruby_to_crystal(%rb.to_unsafe, %result, {{cast_to}}, options: {{options}})\r\n    {% else %}\r\n      Anyolite::RbRef.new(%result)\r\n    {% end %}\r\n  end\r\n\r\n  # Sets the Ruby global variable with `String` or `Symbol` *name*\r\n  # to the Crystal value *value*.\r\n  #\r\n  # If *cast_to* is set to a `Class` or similar, it will automatically cast\r\n  # the result to a Crystal value of that class, otherwise, it will return\r\n  # a `RbRef` value containing the result.\r\n  #\r\n  # If needed, *context* can be set to a `Path` in order to specify *cast_to*.\r\n  macro set_gv(name, value)\r\n    %rb = Anyolite::RbRefTable.get_current_interpreter\r\n    %value = Anyolite::RbCast.return_value(%rb.to_unsafe, {{value}})\r\n\r\n    Anyolite::RbCore.rb_gv_set(%rb, {{name}}.to_s.to_unsafe, %value)\r\n  end\r\n\r\n  # Wraps a Crystal class directly into an mruby class.\r\n  #\r\n  # The Crystal `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with *name* as its new designation, returning an `Anyolite::RbClass`.\r\n  #\r\n  # To inherit from another mruby class, specify an `Anyolite::RbClass` as a *superclass*.\r\n  #\r\n  # Each class can be defined in a specifiy module by setting *under* to a `Anyolite::RbModule`.\r\n  macro wrap_class(rb_interpreter, crystal_class, name, under = nil, superclass = nil)\r\n    %new_class = Anyolite::RbClass.new({{rb_interpreter}}, {{name}}, under: Anyolite::RbClassCache.get({{under}}), superclass: Anyolite::RbClassCache.get({{superclass}}))\r\n    Anyolite::RbCore.set_instance_tt_as_data(%new_class)\r\n    Anyolite::RbClassCache.register({{crystal_class}}, %new_class)\r\n    Anyolite::RbClassCache.get({{crystal_class}})\r\n  end\r\n\r\n  # Wraps a Crystal module into an mruby module.\r\n  #\r\n  # The module *crystal_module* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with *name* as its new designation, returning an `Anyolite::RbModule`.\r\n  #\r\n  # The parent module can be specified with the module argument *under*.\r\n  macro wrap_module(rb_interpreter, crystal_module, name, under = nil)\r\n    %new_module = Anyolite::RbModule.new({{rb_interpreter}}, {{name}}, under: Anyolite::RbClassCache.get({{under}}))\r\n    Anyolite::RbClassCache.register({{crystal_module}}, %new_module)\r\n    Anyolite::RbClassCache.get({{crystal_module}})\r\n  end\r\n\r\n  # Wraps the constructor of a Crystal class into mruby.\r\n  #\r\n  # The constructor for the Crystal `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the arguments *proc_args* as an `Array of Class`.\r\n  #\r\n  # The value *operator* will append the specified `String`\r\n  # to the final name and *context* can give the function a `Path` for resolving types correctly.\r\n  #\r\n  # The arguments *block_arg_number* and *block_return_type* can be set to an `Int` and a `Class`,\r\n  # respectively, in order to require a block argument. If *store_block_arg* is set to `true`,\r\n  # any block argument given will be stored in a cache.\r\n  macro wrap_constructor(rb_interpreter, crystal_class, proc_args = nil, operator = \"\", context = nil, block_arg_number = nil, block_return_type = nil, store_block_arg = false)\r\n    {%\r\n      options = {\r\n        :context           => context,\r\n        :block_arg_number  => block_arg_number,\r\n        :block_return_type => block_return_type,\r\n        :store_block_arg   => store_block_arg,\r\n      }\r\n    %}\r\n    Anyolite::Macro.wrap_constructor_function_with_args({{rb_interpreter}}, {{crystal_class}}, {{crystal_class}}.new, {{proc_args}}, operator: {{operator}}, options: {{options}})\r\n  end\r\n\r\n  # Wraps the constructor of a Crystal class into mruby, using keyword arguments.\r\n  #\r\n  # The constructor for the Crystal `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the arguments *regular_args* as an `Array of Class` and *keyword_args* as an `Array of TypeDeclaration`.\r\n  #\r\n  # The value *operator* will append the specified `String`\r\n  # to the final name and *context* can give the function a `Path` for resolving types correctly.\r\n  #\r\n  # The arguments *block_arg_number* and *block_return_type* can be set to an `Int` and a `Class`,\r\n  # respectively, in order to require a block argument. If *store_block_arg* is set to `true`,\r\n  # any block argument given will be stored in a cache.\r\n  macro wrap_constructor_with_keywords(rb_interpreter, crystal_class, keyword_args, regular_args = nil, operator = \"\", context = nil, block_arg_number = nil, block_return_type = nil, store_block_arg = false)\r\n    {%\r\n      options = {\r\n        :context           => context,\r\n        :block_arg_number  => block_arg_number,\r\n        :block_return_type => block_return_type,\r\n        :store_block_arg   => store_block_arg,\r\n      }\r\n    %}\r\n    Anyolite::Macro.wrap_constructor_function_with_keyword_args({{rb_interpreter}}, {{crystal_class}}, {{crystal_class}}.new, {{keyword_args}}, {{regular_args}}, operator: {{operator}}, options: {{options}})\r\n  end\r\n\r\n  # Wraps a module function into mruby.\r\n  #\r\n  # The function *proc* under the module *under_module* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the arguments *proc_args* as an `Array of Class`.\r\n  #\r\n  # Its new name will be *name*.\r\n  #\r\n  # The value *operator* will append the specified `String`\r\n  # to the final name and *context* can give the function a `Path` for resolving types correctly.\r\n  # The value *return_nil* will override any returned value with `nil`.\r\n  #\r\n  # The arguments *block_arg_number* and *block_return_type* can be set to an `Int` and a `Class`,\r\n  # respectively, in order to require a block argument. If *store_block_arg* is set to `true`,\r\n  # any block argument given will be stored in a cache.\r\n  macro wrap_module_function(rb_interpreter, under_module, name, proc, proc_args = nil, operator = \"\", context = nil, return_nil = false, block_arg_number = nil, block_return_type = nil, store_block_arg = false)\r\n    {%\r\n      options = {\r\n        :context           => context,\r\n        :return_nil        => return_nil,\r\n        :block_arg_number  => block_arg_number,\r\n        :block_return_type => block_return_type,\r\n        :store_block_arg   => store_block_arg,\r\n      }\r\n    %}\r\n    Anyolite::Macro.wrap_module_function_with_args({{rb_interpreter}}, {{under_module}}, {{name}}, {{proc}}, {{proc_args}}, options: {{options}})\r\n  end\r\n\r\n  # Wraps a module function into mruby, using keyword arguments.\r\n  #\r\n  # The function *proc* under the module *under_module* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the arguments *regular_args* as an `Array of Class` and *keyword_args* as an `Array of TypeDeclaration`.\r\n  #\r\n  # Its new name will be *name*.\r\n  #\r\n  # The value *operator* will append the specified `String`\r\n  # to the final name and *context* can give the function a `Path` for resolving types correctly.\r\n  # The value *return_nil* will override any returned value with `nil`.\r\n  #\r\n  # The arguments *block_arg_number* and *block_return_type* can be set to an `Int` and a `Class`,\r\n  # respectively, in order to require a block argument. If *store_block_arg* is set to `true`,\r\n  # any block argument given will be stored in a cache.\r\n  macro wrap_module_function_with_keywords(rb_interpreter, under_module, name, proc, keyword_args, regular_args = nil, operator = \"\", context = nil, return_nil = false, block_arg_number = nil, block_return_type = nil, store_block_arg = false)\r\n    {%\r\n      options = {\r\n        :context           => context,\r\n        :return_nil        => return_nil,\r\n        :block_arg_number  => block_arg_number,\r\n        :block_return_type => block_return_type,\r\n        :store_block_arg   => store_block_arg,\r\n      }\r\n    %}\r\n    Anyolite::Macro.wrap_module_function_with_keyword_args({{rb_interpreter}}, {{under_module}}, {{name}}, {{proc}}, {{keyword_args}}, {{regular_args}}, operator: {{operator}}, options: {{options}})\r\n  end\r\n\r\n  # Wraps a class method into mruby.\r\n  #\r\n  # The class method *proc* of the Crystal `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the arguments *proc_args* as an `Array of Class`.\r\n  #\r\n  # Its new name will be *name*.\r\n  #\r\n  # The value *operator* will append the specified `String`\r\n  # to the final name and *context* can give the function a `Path` for resolving types correctly.\r\n  # The value *return_nil* will override any returned value with `nil`.\r\n  #\r\n  # The arguments *block_arg_number* and *block_return_type* can be set to an `Int` and a `Class`,\r\n  # respectively, in order to require a block argument. If *store_block_arg* is set to `true`,\r\n  # any block argument given will be stored in a cache.\r\n  macro wrap_class_method(rb_interpreter, crystal_class, name, proc, proc_args = nil, operator = \"\", context = nil, return_nil = false, block_arg_number = nil, block_return_type = nil, store_block_arg = false)\r\n    {%\r\n      options = {\r\n        :context           => context,\r\n        :return_nil        => return_nil,\r\n        :block_arg_number  => block_arg_number,\r\n        :block_return_type => block_return_type,\r\n        :store_block_arg   => store_block_arg,\r\n      }\r\n    %}\r\n    Anyolite::Macro.wrap_class_method_with_args({{rb_interpreter}}, {{crystal_class}}, {{name}}, {{proc}}, {{proc_args}}, operator: {{operator}}, options: {{options}})\r\n  end\r\n\r\n  # Wraps a class method into mruby, using keyword arguments.\r\n  #\r\n  # The class method *proc* of the Crystal `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the arguments *regular_args* as an `Array of Class` and *keyword_args* as an `Array of TypeDeclaration`.\r\n  #\r\n  # Its new name will be *name*.\r\n  #\r\n  # The value *operator* will append the specified `String`\r\n  # to the final name and *context* can give the function a `Path` for resolving types correctly.\r\n  # The value *return_nil* will override any returned value with `nil`.\r\n  #\r\n  # The arguments *block_arg_number* and *block_return_type* can be set to an `Int` and a `Class`,\r\n  # respectively, in order to require a block argument. If *store_block_arg* is set to `true`,\r\n  # any block argument given will be stored in a cache.\r\n  macro wrap_class_method_with_keywords(rb_interpreter, crystal_class, name, proc, keyword_args, regular_args = nil, operator = \"\", context = nil, return_nil = false, block_arg_number = nil, block_return_type = nil, store_block_arg = false)\r\n    {%\r\n      options = {\r\n        :context           => context,\r\n        :return_nil        => return_nil,\r\n        :block_arg_number  => block_arg_number,\r\n        :block_return_type => block_return_type,\r\n        :store_block_arg   => store_block_arg,\r\n      }\r\n    %}\r\n    Anyolite::Macro.wrap_class_method_with_keyword_args({{rb_interpreter}}, {{crystal_class}}, {{name}}, {{proc}}, {{keyword_args}}, {{regular_args}}, operator: {{operator}}, options: {{options}})\r\n  end\r\n\r\n  # Wraps an instance method into mruby.\r\n  #\r\n  # The instance method *proc* of the Crystal `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the arguments *proc_args* as an `Array of Class`.\r\n  #\r\n  # Its new name will be *name*.\r\n  #\r\n  # The value *operator* will append the specified `String`\r\n  # to the final name and *context* can give the function a `Path` for resolving types correctly.\r\n  # The value *return_nil* will override any returned value with `nil`.\r\n  #\r\n  # The arguments *block_arg_number* and *block_return_type* can be set to an `Int` and a `Class`,\r\n  # respectively, in order to require a block argument. If *store_block_arg* is set to `true`,\r\n  # any block argument given will be stored in a cache.\r\n  macro wrap_instance_method(rb_interpreter, crystal_class, name, proc, proc_args = nil, operator = \"\", context = nil, return_nil = false, block_arg_number = nil, block_return_type = nil, store_block_arg = false)\r\n    {%\r\n      options = {\r\n        :context           => context,\r\n        :return_nil        => return_nil,\r\n        :block_arg_number  => block_arg_number,\r\n        :block_return_type => block_return_type,\r\n        :store_block_arg   => store_block_arg,\r\n      }\r\n    %}\r\n    Anyolite::Macro.wrap_instance_function_with_args({{rb_interpreter}}, {{crystal_class}}, {{name}}, {{proc}}, {{proc_args}}, operator: {{operator}}, options: {{options}})\r\n  end\r\n\r\n  # Wraps an instance method into mruby, using keyword arguments.\r\n  #\r\n  # The instance method *proc* of the Crystal `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the arguments *regular_args* as an `Array of Class` and *keyword_args* as an `Array of TypeDeclaration`.\r\n  #\r\n  # Its new name will be *name*.\r\n  #\r\n  # The value *operator* will append the specified `String`\r\n  # to the final name and *context* can give the function a `Path` for resolving types correctly.\r\n  # The value *return_nil* will override any returned value with `nil`.\r\n  #\r\n  # The arguments *block_arg_number* and *block_return_type* can be set to an `Int` and a `Class`,\r\n  # respectively, in order to require a block argument. If *store_block_arg* is set to `true`,\r\n  # any block argument given will be stored in a cache.\r\n  macro wrap_instance_method_with_keywords(rb_interpreter, crystal_class, name, proc, keyword_args, regular_args = nil, operator = \"\", context = nil, return_nil = false, block_arg_number = nil, block_return_type = nil, store_block_arg = false)\r\n    {%\r\n      options = {\r\n        :context           => context,\r\n        :return_nil        => return_nil,\r\n        :block_arg_number  => block_arg_number,\r\n        :block_return_type => block_return_type,\r\n        :store_block_arg   => store_block_arg,\r\n      }\r\n    %}\r\n    Anyolite::Macro.wrap_instance_function_with_keyword_args({{rb_interpreter}}, {{crystal_class}}, {{name}}, {{proc}}, {{keyword_args}}, {{regular_args}}, operator: {{operator}}, options: {{options}})\r\n  end\r\n\r\n  # Wraps a setter into mruby.\r\n  #\r\n  # The setter *proc* (without the `=`) of the Crystal `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the argument *proc_arg* as its respective `Class`.\r\n  #\r\n  # Its new name will be *name*.\r\n  #\r\n  # The value *operator* will append the specified `String`\r\n  # to the final name and *context* can give the function a `Path` for resolving types correctly.\r\n  macro wrap_setter(rb_interpreter, crystal_class, name, proc, proc_arg, operator = \"=\", context = nil)\r\n    {% options = {:context => context} %}\r\n    Anyolite::Macro.wrap_instance_function_with_args({{rb_interpreter}}, {{crystal_class}}, {{name}}, {{proc}}, {{proc_arg}}, operator: {{operator}}, options: {{options}})\r\n  end\r\n\r\n  # Wraps a getter into mruby.\r\n  #\r\n  # The getter *proc* of the Crystal `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*.\r\n  #\r\n  # Its new name will be *name*.\r\n  #\r\n  # The value *operator* will append the specified `String`\r\n  # to the final name and *context* can give the function a `Path` for resolving types correctly.\r\n  macro wrap_getter(rb_interpreter, crystal_class, name, proc, operator = \"\", context = nil)\r\n    {% options = {:context => context} %}\r\n    Anyolite::Macro.wrap_instance_function_with_args({{rb_interpreter}}, {{crystal_class}}, {{name}}, {{proc}}, operator: {{operator}}, options: {{options}})\r\n  end\r\n\r\n  # Wraps a property into mruby.\r\n  #\r\n  # The property *proc* of the Crystal `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the argument *proc_arg* as its respective `Class`.\r\n  #\r\n  # Its new name will be *name*.\r\n  #\r\n  # The values *operator_getter* and *operator_setter* will append the specified `String`\r\n  # to the final names and *context* can give the function a `Path` for resolving types correctly.\r\n  macro wrap_property(rb_interpreter, crystal_class, name, proc, proc_arg, operator_getter = \"\", operator_setter = \"=\", context = nil)\r\n    Anyolite.wrap_getter({{rb_interpreter}}, {{crystal_class}}, {{name}}, {{proc}}, operator: {{operator_getter}}, context: {{context}})\r\n    Anyolite.wrap_setter({{rb_interpreter}}, {{crystal_class}}, {{name + \"=\"}}, {{proc}}, {{proc_arg}}, operator: {{operator_setter}}, context: {{context}})\r\n  end\r\n\r\n  # Wraps a class setter into mruby.\r\n  #\r\n  # The class setter *proc* (without the `=`) of the Crystal `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the argument *proc_arg* as its respective `Class`.\r\n  #\r\n  # Its new name will be *name*.\r\n  #\r\n  # The value *operator* will append the specified `String`\r\n  # to the final name and *context* can give the function a `Path` for resolving types correctly.\r\n  macro wrap_class_setter(rb_interpreter, crystal_class, name, proc, proc_arg, operator = \"=\", context = nil)\r\n    {% options = {:context => context} %}\r\n    Anyolite::Macro.wrap_module_function_with_args({{rb_interpreter}}, {{crystal_class}}, {{name}}, {{proc}}, {{proc_arg}}, operator: {{operator}}, options: {{options}})\r\n  end\r\n\r\n  # Wraps a class getter into mruby.\r\n  #\r\n  # The class getter *proc* of the Crystal `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*.\r\n  #\r\n  # Its new name will be *name*.\r\n  #\r\n  # The value *operator* will append the specified `String`\r\n  # to the final name and *context* can give the function a `Path` for resolving types correctly.\r\n  macro wrap_class_getter(rb_interpreter, crystal_class, name, proc, operator = \"\", context = nil)\r\n    {% options = {:context => context} %}\r\n    Anyolite::Macro.wrap_module_function_with_args({{rb_interpreter}}, {{crystal_class}}, {{name}}, {{proc}}, operator: {{operator}}, options: {{options}})\r\n  end\r\n\r\n  # Wraps a class property into mruby.\r\n  #\r\n  # The class property *proc* of the Crystal `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the argument *proc_arg* as its respective `Class`.\r\n  #\r\n  # Its new name will be *name*.\r\n  #\r\n  # The values *operator_getter* and *operator_setter* will append the specified `String`\r\n  # to the final names and *context* can give the function a `Path` for resolving types correctly.\r\n  macro wrap_class_property(rb_interpreter, crystal_class, name, proc, proc_arg, operator_getter = \"\", operator_setter = \"=\", context = nil)\r\n    Anyolite.wrap_class_getter({{rb_interpreter}}, {{crystal_class}}, {{name}}, {{proc}}, operator: {{operator_getter}}, context: {{context}})\r\n    Anyolite.wrap_class_setter({{rb_interpreter}}, {{crystal_class}}, {{name + \"=\"}}, {{proc}}, {{proc_arg}}, operator: {{operator_setter}}, context: {{context}})\r\n  end\r\n\r\n  # Wraps a constant value under a module into mruby.\r\n  #\r\n  # The value *crystal_value* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the name *name* and the parent module *under_module*.\r\n  macro wrap_constant(rb_interpreter, under_module, name, crystal_value)\r\n    Anyolite::RbCore.rb_define_const({{rb_interpreter}}, Anyolite::RbClassCache.get({{under_module}}), {{name}}, Anyolite::RbCast.return_value({{rb_interpreter}}.to_unsafe, {{crystal_value}}))\r\n  end\r\n\r\n  # Wraps a constant value under a class into mruby.\r\n  #\r\n  # The value *crystal_value* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the name *name* and the parent `Class` *under_class*.\r\n  macro wrap_constant_under_class(rb_interpreter, under_class, name, crystal_value)\r\n    Anyolite::RbCore.rb_define_const({{rb_interpreter}}, Anyolite::RbClassCache.get({{under_class}}), {{name}}, Anyolite::RbCast.return_value({{rb_interpreter}}.to_unsafe, {{crystal_value}}))\r\n  end\r\n\r\n  # NOTE: Annotations like SpecializeConstant are not defined for obvious reasons\r\n  # TODO: Annotations for constants are currently not obtainable with macros (?)\r\n\r\n  # Excludes the function from wrapping.\r\n  annotation Exclude; end\r\n\r\n  # Excludes the instance method given as the first argument from wrapping.\r\n  # Use it on `Object` to exclude the named method from all classes.\r\n  annotation ExcludeInstanceMethod; end\r\n\r\n  # Excludes the class method given as the first argument from wrapping.\r\n  annotation ExcludeClassMethod; end\r\n\r\n  # Excludes the constant given as the first argument from wrapping.\r\n  annotation ExcludeConstant; end\r\n\r\n  # Overrides `ExcludeInstanceMethod` on `Object`.\r\n  annotation Include; end\r\n\r\n  # Overrides `ExcludeInstanceMethod` on `Object`\r\n  # the instance method given as the first argument.\r\n  annotation IncludeInstanceMethod; end\r\n\r\n  # Excludes all definitions of this function besides this one from wrapping.\r\n  # The optional first argument overwrites the original argument array.\r\n  annotation Specialize; end\r\n\r\n  # Excludes all definitions of the instance method given as the first argument\r\n  # besides the one with the arguments given in the second argument (`nil` for none) from wrapping.\r\n  # The optional third argument overwrites the original argument array.\r\n  annotation SpecializeInstanceMethod; end\r\n\r\n  # Excludes all definitions of the class method given as the first argument\r\n  # besides the one with the arguments given in the second argument (`nil` for none) from wrapping.\r\n  # The optional third argument overwrites the original argument array.\r\n  annotation SpecializeClassMethod; end\r\n\r\n  # Renames the function to the first argument if wrapped.\r\n  annotation Rename; end\r\n\r\n  # Renames the instane method given as the first argument\r\n  # to the second argument if wrapped.\r\n  annotation RenameInstanceMethod; end\r\n\r\n  # Renames the class method given as the first argument\r\n  # to the second argument if wrapped.\r\n  annotation RenameClassMethod; end\r\n\r\n  # Renames the constant given as the first argument\r\n  # to the second argument if wrapped.\r\n  annotation RenameConstant; end\r\n\r\n  # Renames the class to the first argument if wrapped.\r\n  annotation RenameClass; end\r\n\r\n  # Renames the module to the first argument if wrapped.\r\n  annotation RenameModule; end\r\n\r\n  # Wraps all arguments of the function to positional arguments.\r\n  # The optional argument limits the number of arguments to wrap as positional\r\n  # arguments (`-1` for all arguments).\r\n  annotation WrapWithoutKeywords; end\r\n\r\n  # Wraps all arguments of the instance method given as the first argument\r\n  # to positional arguments.\r\n  # The optional seconds argument limits the number of arguments to wrap as positional\r\n  # arguments (`-1` for all arguments).\r\n  annotation WrapWithoutKeywordsInstanceMethod; end\r\n\r\n  # Wraps all arguments of the class method given as the first argument\r\n  # to positional arguments.\r\n  # The optional seconds argument limits the number of arguments to wrap as positional\r\n  # arguments (`-1` for all arguments).\r\n  annotation WrapWithoutKeywordsClassMethod; end\r\n\r\n  # Lets the function always return `nil`.\r\n  annotation ReturnNil; end\r\n\r\n  # Lets the instance method given as the first argument always return `nil`.\r\n  annotation ReturnNilInstanceMethod; end\r\n\r\n  # Lets the class method given as the first argument always return `nil`.\r\n  annotation ReturnNilClassMethod; end\r\n\r\n  # Specifies the generic type names for the following class as its argument,\r\n  # in form of an `Array` of their names.\r\n  annotation SpecifyGenericTypes; end\r\n\r\n  # Specifies the method to require a block argument with the first argument\r\n  # being the number of values yielded and the second argument the return\r\n  # type of the block.\r\n  annotation AddBlockArg; end\r\n\r\n  # Specifies the instance method given as the first argument\r\n  # to require a block argument with the second argument\r\n  # being the number of values yielded and the third argument the return\r\n  # type of the block.\r\n  annotation AddBlockArgInstanceMethod; end\r\n\r\n  # Specifies the class method given as the first argument\r\n  # to require a block argument with the second argument\r\n  # being the number of values yielded and the third argument the return\r\n  # type of the block.\r\n  annotation AddBlockArgClassMethod; end\r\n\r\n  # Instructs the function to cache an incoming Ruby block argument if given.\r\n  annotation StoreBlockArg; end\r\n\r\n  # Instructs the instance method given as the first argument to cache an incoming Ruby block argument if given.\r\n  annotation StoreBlockArgInstanceMethod; end\r\n\r\n  # Instructs the class method given as the first argument to cache an incoming Ruby block argument if given.\r\n  annotation StoreBlockArgClassMethod; end\r\n\r\n  # Forces the method to use keyword arguments (especially for operator methods) if given.\r\n  annotation ForceKeywordArg; end\r\n\r\n  # Forces the instance method given as the first argument to use\r\n  # keyword arguments (especially for operator methods) if given.\r\n  annotation ForceKeywordArgInstanceMethod; end\r\n\r\n  # Forces the class method given as the first argument to use\r\n  # keyword arguments (especially for operator methods) if given.\r\n  annotation ForceKeywordArgClassMethod; end\r\n\r\n  # The methods of the annotated class or module will not\r\n  # be wrapped with keyword arguments unless `ForceKeywordArg`\r\n  # or similar was used.\r\n  annotation NoKeywordArgs; end\r\n\r\n  # All methods of the respective class have their required arguments\r\n  # wrapped as regular arguments and their optional arguments wrapped\r\n  # as keyword arguments.\r\n  #\r\n  # The annotation can be overwritten with the respective\r\n  # `WrapWithoutKeywords` annotations for specific methods.\r\n  annotation DefaultOptionalArgsToKeywordArgs; end\r\n\r\n  # Specifies that only the directly defined methods of the respective\r\n  # class are wrapped, and no inherited methods.\r\n  annotation IgnoreAncestorMethods; end\r\n\r\n  # Wraps a whole class structure under a module into mruby.\r\n  #\r\n  # The `Class` *crystal_class* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the optional parent module *under*.\r\n  # Methods or constants to be excluded can be specified as\r\n  # `Symbol` or `String` in the `Array`\r\n  # *instance_method_exclusions* (for instance methods),\r\n  # *class_method_exclusions* (for class methods) or\r\n  # *constant_exclusions* (for constants).\r\n  #\r\n  # Enum classes can be wrapped by setting *use_enum_methods*.\r\n  # If *wrap_equality_method* is set, the `==` method will be wrapped\r\n  # automatically.\r\n  # Setting *connect_to_superclass* to `false` will force the algorithm\r\n  # to ignore any superclass.\r\n  # Setting *include_ancestor_methods* will include any methods\r\n  # from nontrivial ancestor classes.\r\n  # The option *overwrite* will iterate through all functions and\r\n  # constants again if set to `true`.\r\n  # If *verbose* is set, wrapping information will be displayed.\r\n  macro wrap_class_with_methods(rb_interpreter, crystal_class, under = nil,\r\n                                instance_method_exclusions = [] of String | Symbol,\r\n                                class_method_exclusions = [] of String | Symbol,\r\n                                constant_exclusions = [] of String | Symbol,\r\n                                use_enum_methods = false,\r\n                                wrap_equality_method = false,\r\n                                connect_to_superclass = true,\r\n                                include_ancestor_methods = true,\r\n                                overwrite = false,\r\n                                verbose = false)\r\n\r\n    {% if verbose %}\r\n      {% puts \">>> Going into class #{crystal_class} under #{under}\\n\\n\" %}\r\n    {% end %}\r\n\r\n    {% if crystal_class.is_a?(Generic) %}\r\n      {% puts \"> Wrapping of generics not supported, thus skipping #{crystal_class}\\e[0m\\n\\n\" if verbose %}\r\n    {% else %}\r\n      {% resolved_class = crystal_class.resolve %}\r\n\r\n      {% new_context = crystal_class %}\r\n\r\n      {% if resolved_class.annotation(Anyolite::RenameClass) %}\r\n        {% actual_name = resolved_class.annotation(Anyolite::RenameClass)[0] %}\r\n      {% else %}\r\n        {% actual_name = crystal_class.names.last.stringify %}\r\n      {% end %}\r\n\r\n      {% if connect_to_superclass %}\r\n        {% superclass = [Reference, Object, Struct, Enum, Value, Comparable(Enum), Enumerable].includes?(resolved_class.superclass) ? nil : resolved_class.superclass %}\r\n      {% else %}\r\n        {% superclass = nil %}\r\n      {% end %}\r\n\r\n      {% if superclass %}\r\n        if !Anyolite::RbClassCache.check({{superclass.resolve}})\r\n          puts \"Note: Superclass {{superclass}} to {{resolved_class}} was not wrapped before. Trying to find it...\"\r\n          _needs_more_iterations.push(\"{{superclass}}\") if _needs_more_iterations\r\n        else\r\n      {% else %}\r\n        if false\r\n\r\n        else\r\n      {% end %}\r\n        if {{overwrite}} || !Anyolite::RbClassCache.check({{resolved_class}}) \r\n          Anyolite.wrap_class({{rb_interpreter}}, {{resolved_class}}, {{actual_name}}, under: {{under}}, superclass: {{superclass}})\r\n\r\n          {% if include_ancestor_methods %}\r\n            {% reversed_ancestors = [] of TypeNode %}\r\n            {% for ancestor in resolved_class.ancestors.reject { |ancestor| [Object, Reference, Struct, Enum, Value, Comparable(Enum), Enumerable].includes?(ancestor) } %}\r\n              {% reversed_ancestors = [ancestor] + reversed_ancestors %}\r\n            {% end %}\r\n\r\n            {% puts \"> Ancestors for #{resolved_class}: #{reversed_ancestors}\" if !reversed_ancestors.empty? && verbose %}\r\n\r\n            {% if resolved_class.annotation(Anyolite::IgnoreAncestorMethods) %}\r\n              {% puts \"> Ignoring ancestors due to annotation.\" if !reversed_ancestors.empty? && verbose %}\r\n            {% else %}\r\n              {% for ancestor, ancestor_index in reversed_ancestors %}\r\n                {% puts \"> Going into ancestor #{ancestor} for #{resolved_class}...\" if verbose %}\r\n                {% later_ancestors = reversed_ancestors[ancestor_index + 1..-1] %}\r\n\r\n                Anyolite::Macro.wrap_all_instance_methods({{rb_interpreter}}, {{crystal_class}}, {{instance_method_exclusions}}, \r\n                  verbose: {{verbose}}, context: {{new_context}}, use_enum_methods: {{use_enum_methods}}, wrap_equality_method: {{wrap_equality_method}}, \r\n                  other_source: {{ancestor}}, later_ancestors: {{later_ancestors.empty? ? nil : later_ancestors}})\r\n              {% end %}\r\n            {% end %}\r\n          {% end %}\r\n\r\n          Anyolite::Macro.wrap_all_instance_methods({{rb_interpreter}}, {{crystal_class}}, {{instance_method_exclusions}}, \r\n            verbose: {{verbose}}, context: {{new_context}}, use_enum_methods: {{use_enum_methods}}, wrap_equality_method: {{wrap_equality_method}})\r\n          Anyolite::Macro.wrap_all_class_methods({{rb_interpreter}}, {{crystal_class}}, {{class_method_exclusions}}, verbose: {{verbose}}, context: {{new_context}})\r\n          Anyolite::Macro.wrap_all_constants({{rb_interpreter}}, {{crystal_class}}, {{constant_exclusions}}, verbose: {{verbose}}, context: {{new_context}})\r\n        end\r\n      end\r\n    {% end %}\r\n  end\r\n\r\n  # Wraps a whole module structure under a module into mruby.\r\n  #\r\n  # The module *crystal_module* will be integrated into the `RbInterpreter` *rb_interpreter*,\r\n  # with the optional parent module *under*.\r\n  # Methods or constants to be excluded can be specified as\r\n  # `Symbol` or `String` in the `Array`\r\n  # *class_method_exclusions* (for class methods) or\r\n  # *constant_exclusions* (for constants).\r\n  # The option *overwrite* will iterate through all functions and\r\n  # constants again if set to `true`.\r\n  # If *verbose* is set, wrapping information will be displayed.\r\n  macro wrap_module_with_methods(rb_interpreter, crystal_module, under = nil,\r\n                                 class_method_exclusions = [] of String | Symbol,\r\n                                 constant_exclusions = [] of String | Symbol,\r\n                                 overwrite = false,\r\n                                 verbose = false)\r\n\r\n    {% if verbose %}\r\n      {% puts \">>> Going into module #{crystal_module} under #{under}\\n\\n\" %}\r\n    {% end %}\r\n\r\n    {% new_context = crystal_module %}\r\n\r\n    {% if crystal_module.resolve.annotation(Anyolite::RenameModule) %}\r\n      {% actual_name = crystal_module.resolve.annotation(Anyolite::RenameModule)[0] %}\r\n    {% else %}\r\n      {% actual_name = crystal_module.names.last.stringify %}\r\n    {% end %}\r\n\r\n    if {{overwrite}} || !Anyolite::RbClassCache.check({{crystal_module.resolve}}) \r\n      Anyolite.wrap_module({{rb_interpreter}}, {{crystal_module.resolve}}, {{actual_name}}, under: {{under}})\r\n\r\n      Anyolite::Macro.wrap_all_class_methods({{rb_interpreter}}, {{crystal_module}}, {{class_method_exclusions}}, verbose: {{verbose}}, context: {{new_context}})\r\n      Anyolite::Macro.wrap_all_constants({{rb_interpreter}}, {{crystal_module}}, {{constant_exclusions}}, verbose: {{verbose}}, overwrite: {{overwrite}}, context: {{new_context}})\r\n    end\r\n  end\r\n\r\n  # Wraps a whole class or module structure under a module into mruby.\r\n  #\r\n  # The class or module *crystal_module_or_class* will be integrated\r\n  # into the `RbInterpreter` *rb_interpreter*,\r\n  # with the optional parent module *under*.\r\n  # Methods or constants to be excluded can be specified as\r\n  # `Symbol` or `String` in the `Array`\r\n  # *class_method_exclusions* (for class methods) or\r\n  # *constant_exclusions* (for constants).\r\n  #\r\n  # If *wrap_equality_method* is set, the `==` method will be wrapped\r\n  # automatically.\r\n  # Setting *connect_to_superclass* to `false` will force the algorithm\r\n  # to ignore any superclass.\r\n  # Setting *include_ancestor_methods* will include any methods\r\n  # from nontrivial ancestor classes.\r\n  # The option *overwrite* will iterate through all functions and\r\n  # constants again if set to `true`.\r\n  # If *verbose* is set, wrapping information will be displayed.\r\n  macro wrap(rb_interpreter, crystal_module_or_class, under = nil,\r\n             instance_method_exclusions = [] of String | Symbol,\r\n             class_method_exclusions = [] of String | Symbol,\r\n             constant_exclusions = [] of String | Symbol,\r\n             connect_to_superclass = false,\r\n             include_ancestor_methods = true,\r\n             use_enum_methods = false,\r\n             wrap_equality_method = false,\r\n             overwrite = false,\r\n             verbose = false)\r\n\r\n    _needs_more_iterations = [] of String\r\n    %previous_iterations = [] of String\r\n    %first_run = true\r\n\r\n    while %first_run || !_needs_more_iterations.empty?\r\n      %previous_iterations = _needs_more_iterations\r\n      _needs_more_iterations = [] of String\r\n\r\n      {% if !crystal_module_or_class.is_a?(Path) %}\r\n        {% puts \"\\e[31m> WARNING: Object #{crystal_module_or_class} of #{crystal_module_or_class.class_name.id} is neither a class nor module, so it will be skipped\\e[0m\" %}\r\n      {% elsif crystal_module_or_class.resolve.module? %}\r\n        Anyolite.wrap_module_with_methods({{rb_interpreter}}, {{crystal_module_or_class}}, under: {{under}},\r\n          class_method_exclusions: {{class_method_exclusions}},\r\n          constant_exclusions: {{constant_exclusions}},\r\n          overwrite: {{overwrite}},\r\n          verbose: {{verbose}}\r\n        )\r\n      {% elsif crystal_module_or_class.resolve.class? || crystal_module_or_class.resolve.struct? %}\r\n        Anyolite.wrap_class_with_methods({{rb_interpreter}}, {{crystal_module_or_class}}, under: {{under}},\r\n          instance_method_exclusions: {{instance_method_exclusions}},\r\n          class_method_exclusions: {{class_method_exclusions}},\r\n          constant_exclusions: {{constant_exclusions}},\r\n          use_enum_methods: {{use_enum_methods}},\r\n          wrap_equality_method: {{wrap_equality_method || crystal_module_or_class.resolve.struct?}},\r\n          connect_to_superclass: {{connect_to_superclass}},\r\n          include_ancestor_methods: {{include_ancestor_methods}},\r\n          overwrite: {{overwrite}},\r\n          verbose: {{verbose}}\r\n        )\r\n      {% elsif crystal_module_or_class.resolve.union? %}\r\n        {% puts \"\\e[31m> WARNING: Wrapping of unions not supported, thus skipping #{crystal_module_or_class}\\e[0m\" %}\r\n      {% elsif crystal_module_or_class.resolve < Enum %}\r\n        Anyolite.wrap_class_with_methods({{rb_interpreter}}, {{crystal_module_or_class}}, under: {{under}},\r\n          instance_method_exclusions: {{instance_method_exclusions}},\r\n          class_method_exclusions: {{class_method_exclusions}},\r\n          constant_exclusions: {{constant_exclusions}},\r\n          use_enum_methods: true,\r\n          wrap_equality_method: true,\r\n          connect_to_superclass: {{connect_to_superclass}},\r\n          include_ancestor_methods: {{include_ancestor_methods}},\r\n          overwrite: {{overwrite}},\r\n          verbose: {{verbose}}\r\n        )\r\n      {% elsif crystal_module_or_class.resolve.is_a?(TypeNode) %}\r\n        Anyolite.wrap_class_with_methods({{rb_interpreter}}, {{crystal_module_or_class}}, under: {{under}},\r\n          instance_method_exclusions: {{instance_method_exclusions}},\r\n          class_method_exclusions: {{class_method_exclusions}},\r\n          constant_exclusions: {{constant_exclusions}},\r\n          use_enum_methods: {{use_enum_methods}},\r\n          wrap_equality_method: {{wrap_equality_method}},\r\n          connect_to_superclass: {{connect_to_superclass}},\r\n          include_ancestor_methods: {{include_ancestor_methods}},\r\n          overwrite: {{overwrite}},\r\n          verbose: {{verbose}}\r\n        )\r\n      {% else %}\r\n        {% puts \"\\e[31m> WARNING: Could not resolve #{crystal_module_or_class}, so it will be skipped\\e[0m\" %}\r\n      {% end %}\r\n\r\n      %first_run = false\r\n\r\n      if !_needs_more_iterations.empty? && _needs_more_iterations == %previous_iterations\r\n        raise \"Could not wrap the following classes: #{_needs_more_iterations.inspect}\"\r\n      end\r\n    end\r\n  end\r\nend\r\n\r\nrequire \"./helper_classes/HelperClasses.cr\"\r\n"
  },
  {
    "path": "src/Preloader.cr",
    "content": "module Anyolite\n  module Preloader\n    @@content = {} of String => Array(UInt8)\n\n    module AtCompiletime\n      # Caches the bytecode from *filename*, so it is automatically included\n      # into the final application.\n      macro load_bytecode_file(filename)\n        {% file_content = read_file?(filename) %}\n        {% if file_content %}\n          Anyolite::Preloader.add_content({{filename}}, {{file_content}}.bytes)\n        {% else %}\n          puts \"Could not find #{filename}\"\n        {% end %}\n      end\n\n      # Caches the Ruby script in *filename* directly as bytecode.\n      macro load_bytecode_array_from_file(filename)\n        {% ary = run(\"./BytecodeGetter.cr\", filename) %}\n        Anyolite::Preloader.add_content({{filename}}, {{ary}}.map(&.to_u8))\n      end\n\n      # Converts the Ruby script in *filename* to bytecode, which is\n      # then stored in *target_filename*.\n      macro transform_script_to_bytecode(filename, target_filename)\n        {% run(\"./BytecodeCompiler.cr\", filename, target_filename) %}\n      end\n\n      # Converts the Ruby script in *filename* to bytecode.\n      macro transform_script_to_bytecode_string(filename)\n        {% run(\"./BytecodeGetter.cr\", filename) %}\n      end\n    end\n\n    # Caches the bytecode file *filename*\n    def self.add_content(filename : String, bytes : Array(UInt8))\n      @@content[filename] = bytes\n    end\n\n    # Executes the bytecode file *filename* in context of the `RbInterpreter` *rb*.\n    #\n    # If it was already cached, it will be taken from the cache instead.\n    def self.execute_bytecode_from_cache_or_file(rb : RbInterpreter, filename : String)\n      if @@content[filename]?\n        rb.execute_bytecode(@@content[filename])\n      else\n        rb.load_bytecode_from_file(filename)\n      end\n    end\n\n    # Converts the Ruby script in *filename* to bytecode, which is\n    # then stored in *target_filename*.\n    def self.transform_script_to_bytecode(filename : String, target_filename : String)\n      error_code = RbCore.transform_script_to_bytecode(filename, target_filename)\n\n      case error_code\n      when 1 then raise \"Could not load script file #{filename}\"\n      when 2 then raise \"Error when loading script file #{filename}\"\n      when 3 then raise \"Could not write to target file #{target_filename}\"\n      end\n    end\n\n    # Converts the Ruby script in *filename* to bytecode.\n    def self.transform_script_to_bytecode_array(filename : String)\n      container = RbCore.transform_script_to_bytecode_container(filename)\n\n      case container.error_code\n      when 1 then raise \"Could not load script file #{filename}\"\n      when 2 then raise \"Error when loading script file #{filename}\"\n      end\n\n      safe_result = String.new(container.content, container.size)\n\n      RbCore.free_bytecode_container(container)\n\n      safe_result.bytes\n    end\n  end\nend\n"
  },
  {
    "path": "src/RbArgCache.cr",
    "content": "module Anyolite\n  module RbArgCache\n    @@block_cache : Deque(Pointer(RbCore::RbValue)) = Deque(Pointer(RbCore::RbValue)).new\n\n    def self.get_block_cache\n      if @@block_cache.size > 0\n        @@block_cache.last\n      else\n        nil\n      end\n    end\n\n    def self.push_block_cache(value)\n      @@block_cache.push(value)\n    end\n\n    def self.pop_block_cache\n      @@block_cache.pop\n    end\n  end\nend\n"
  },
  {
    "path": "src/RbCast.cr",
    "content": "module Anyolite\n  # Module for specific casts of Crystal values into mruby values\n  module RbCast\n    # Explicit return methods\n\n    def self.return_nil\n      return RbCore.get_nil_value\n    end\n\n    def self.return_true\n      return RbCore.get_true_value\n    end\n\n    def self.return_false\n      return RbCore.get_false_value\n    end\n\n    def self.return_fixnum(value)\n      return RbCore.get_fixnum_value(value)\n    end\n\n    def self.return_bool(value)\n      return RbCore.get_bool_value(value ? 1 : 0)\n    end\n\n    def self.return_float(rb : RbCore::State*, value)\n      return RbCore.get_float_value(rb, value)\n    end\n\n    def self.return_string(rb : RbCore::State*, value)\n      return RbCore.get_string_value(rb, value)\n    end\n\n    def self.return_array(rb : RbCore::State*, value)\n      array_size = value.size\n\n      array_values = Pointer(RbCore::RbValue).malloc(size: array_size) do |i|\n        RbCast.return_value(rb, value[i])\n      end\n\n      return RbCore.rb_ary_new_from_values(rb, array_size, array_values)\n    end\n\n    def self.return_symbol(rb : RbCore::State*, value)\n      return RbCore.get_symbol_value_of_string(rb, value.to_s)\n    end\n\n    def self.return_regex(rb : RbCore::State*, value)\n      Anyolite::Macro.convert_regex_from_crystal_to_ruby(rb, value)\n    end\n\n    def self.return_hash(rb : RbCore::State*, value)\n      hash_size = value.size\n\n      rb_hash = RbCore.rb_hash_new(rb)\n\n      value.each do |index, element|\n        rb_element = RbCast.return_value(rb, element)\n        rb_key = RbCast.return_value(rb, index)\n\n        RbCore.rb_hash_set(rb, rb_hash, rb_key, rb_element)\n      end\n\n      return rb_hash\n    end\n\n    def self.return_struct_or_enum(rb : RbCore::State*, value : Struct | Enum)\n      # NOTE: Equal structs do not have the same object IDs, so they are not cached\n      ruby_class = RbClassCache.get(value.class)\n\n      destructor = RbTypeCache.destructor_method(typeof(value))\n\n      ptr = Pointer(Anyolite::StructWrapper(typeof(value))).malloc(size: 1, value: StructWrapper(typeof(value)).new(value))\n      new_ruby_object = RbCore.new_empty_object(rb, ruby_class, ptr.as(Void*), RbTypeCache.register(value.class, destructor))\n\n      RbRefTable.add(RbRefTable.get_object_id(ptr.value), ptr.as(Void*), new_ruby_object)\n\n      return new_ruby_object\n    end\n\n    def self.return_object(rb : RbCore::State*, value : Object)\n      ruby_class = RbClassCache.get(value.class)\n      value_id = RbRefTable.get_object_id(value)\n\n      if RbRefTable.is_registered?(value_id)\n        return RbRefTable.get_rb_value(value_id)\n      else\n        destructor = RbTypeCache.destructor_method(typeof(value))\n\n        ptr = Pointer(typeof(value)).malloc(size: 1, value: value)\n        new_ruby_object = RbCore.new_empty_object(rb, ruby_class, ptr.as(Void*), RbTypeCache.register(value.class, destructor))\n\n        RbRefTable.add(value_id, ptr.as(Void*), new_ruby_object)\n\n        return new_ruby_object\n      end\n    end\n\n    def self.return_value(rb : RbCore::State*, value : Object)\n      if value.is_a?(Nil)\n        RbCast.return_nil\n      elsif value.is_a?(Bool)\n        value ? RbCast.return_true : RbCast.return_false\n      elsif value.is_a?(Int)\n        RbCast.return_fixnum(value)\n      elsif value.is_a?(Float)\n        RbCast.return_float(rb, value)\n      elsif value.is_a?(Char)\n        RbCast.return_string(rb, value.to_s)\n      elsif value.is_a?(String)\n        RbCast.return_string(rb, value)\n      elsif value.is_a?(Symbol)\n        RbCast.return_symbol(rb, value)\n      elsif value.is_a?(Regex)\n        RbCast.return_regex(rb, value)\n      elsif value.is_a?(Array)\n        RbCast.return_array(rb, value)\n      elsif value.is_a?(Hash)\n        RbCast.return_hash(rb, value)\n      elsif value.is_a?(Pointer)\n        RbCast.return_object(rb, HelperClasses::AnyolitePointer.new(value))\n      elsif value.is_a?(RbRef)\n        value.to_unsafe\n      elsif value.is_a?(Struct) || value.is_a?(Enum)\n        RbCast.return_struct_or_enum(rb, value)\n      else\n        RbCast.return_object(rb, value)\n      end\n    end\n\n    # Class check methods\n\n    def self.check_for_undef(value : RbCore::RbValue)\n      RbCore.check_rb_undef(value) != 0\n    end\n\n    def self.check_for_nil(value : RbCore::RbValue)\n      RbCore.check_rb_nil(value) != 0\n    end\n\n    def self.check_for_true(value : RbCore::RbValue)\n      RbCore.check_rb_true(value) != 0\n    end\n\n    def self.check_for_false(value : RbCore::RbValue)\n      RbCore.check_rb_false(value) != 0\n    end\n\n    def self.check_for_bool(value : RbCore::RbValue)\n      RbCast.check_for_true(value) || RbCast.check_for_false(value)\n    end\n\n    def self.check_for_fixnum(value : RbCore::RbValue)\n      RbCore.check_rb_fixnum(value) != 0\n    end\n\n    def self.check_for_float(value : RbCore::RbValue)\n      RbCore.check_rb_float(value) != 0\n    end\n\n    def self.check_for_string(value : RbCore::RbValue)\n      RbCore.check_rb_string(value) != 0\n    end\n\n    def self.check_for_symbol(value : RbCore::RbValue)\n      RbCore.check_rb_symbol(value) != 0\n    end\n\n    def self.check_for_array(value : RbCore::RbValue)\n      RbCore.check_rb_array(value) != 0\n    end\n\n    def self.check_for_hash(value : RbCore::RbValue)\n      RbCore.check_rb_hash(value) != 0\n    end\n\n    def self.check_for_data(value : RbCore::RbValue)\n      RbCore.check_rb_data(value) != 0\n    end\n\n    def self.casting_error(rb : RbCore::State*, value, crystal_class, rescue_value)\n      rb_inspect_string = RbCore.rb_inspect(rb, value)\n      rb_class = RbCore.get_class_of_obj(rb, value)\n\n      class_name = String.new(RbCore.rb_class_name(rb, rb_class))\n\n      value_debug = RbCast.cast_to_string(rb, rb_inspect_string)\n      Anyolite.raise_argument_error(\"Could not cast value #{value_debug} of class #{class_name} to #{crystal_class}.\")\n      rescue_value\n    end\n\n    def self.cast_to_nil(rb : RbCore::State*, value : RbCore::RbValue)\n      # NOTE: If a nil class is expected, there is no point in rejecting objects\n      # TODO: Maybe add an option for this\n      if RbCast.check_for_nil(value) || true\n        nil\n      else\n        RbCast.casting_error(rb, value, Nil, nil)\n      end\n    end\n\n    def self.cast_to_bool(rb : RbCore::State*, value : RbCore::RbValue)\n      if RbCast.check_for_true(value)\n        true\n      elsif RbCast.check_for_false(value)\n        false\n      else\n        RbCast.casting_error(rb, value, Bool, false)\n      end\n    end\n\n    def self.cast_to_int(rb : RbCore::State*, value : RbCore::RbValue)\n      if RbCast.check_for_fixnum(value)\n        RbCore.get_rb_fixnum(value)\n      else\n        RbCast.casting_error(rb, value, Int, 0)\n      end\n    end\n\n    def self.cast_to_float(rb : RbCore::State*, value : RbCore::RbValue)\n      if RbCast.check_for_float(value)\n        RbCore.get_rb_float(value)\n      elsif RbCast.check_for_fixnum(value)\n        RbCore.get_rb_fixnum(value).to_f\n      else\n        RbCast.casting_error(rb, value, Float, 0.0)\n      end\n    end\n\n    def self.cast_to_char(rb : RbCore::State*, value : RbCore::RbValue)\n      if RbCast.check_for_string(value)\n        str = String.new(RbCore.get_rb_string(rb, value))\n        # TODO: Maybe also exclude longer strings to avoid confusion?\n        if str.empty?\n          RbCast.casting_error(rb, value, Char, '\\0')\n        else\n          str[0]\n        end\n      else\n        RbCast.casting_error(rb, value, Char, '\\0')\n      end\n    end\n\n    # TODO: Maybe add an option for implicit casts?\n    def self.cast_to_string(rb : RbCore::State*, value : RbCore::RbValue)\n      if RbCast.check_for_string(value)\n        String.new(RbCore.get_rb_string(rb, value))\n      elsif RbCast.check_for_symbol(value)\n        String.new(RbCore.get_rb_string(rb, RbCore.rb_inspect(rb, value)))\n      else\n        RbCast.casting_error(rb, value, String, \"\")\n      end\n    end\n\n    macro check_custom_type(rb, value, crystal_type)\n      Anyolite::RbCore.rb_obj_is_kind_of({{rb}}, {{value}}, Anyolite::RbClassCache.get({{crystal_type}})) != 0\n    end\n\n    def self.is_undef?(value) # Excludes non-RbValue types as well\n      if value.is_a?(RbCore::RbValue)\n        Anyolite::RbCast.check_for_undef(value)\n      else\n        false\n      end\n    end\n\n    def self.convert_to_unsafe_rb_value(rb : RbCore::State*, value)\n      if value.is_a?(Anyolite::RbRef)\n        value.to_unsafe\n      elsif value.is_a?(Anyolite::RbCore::RbValue)\n        value\n      else\n        RbCast.return_value(rb, value)\n      end\n    end\n\n    # TODO: Conversions of other objects like arrays and hashes\n  end\nend\n"
  },
  {
    "path": "src/RbClass.cr",
    "content": "module Anyolite\n  # Reference to a mruby class\n  class RbClass\n    @class_ptr : RbCore::RClassPtr\n\n    def initialize(@rb : RbInterpreter, @name : String, superclass : RbModule | RbClass | Nil = nil, @under : RbModule | RbClass | Nil = nil)\n      if superclass.is_a?(RbModule)\n        raise \"Super class #{superclass} of #{@name} is a RbModule.\"\n      end\n\n      actual_superclass = superclass ? superclass.to_unsafe : RbCore.get_object_class(@rb)\n\n      if mod = @under\n        @class_ptr = RbCore.rb_define_class_under(@rb, mod, @name, actual_superclass)\n      else\n        @class_ptr = RbCore.rb_define_class(@rb, @name, actual_superclass)\n      end\n    end\n\n    def initialize(@rb : RbInterpreter, @class_ptr : RbCore::RClassPtr, @under : RbModule | RbClass | Nil = nil)\n      @name = String.new(RbCore.rb_class_name(@rb, @class_ptr))\n    end\n\n    def self.get_from_ruby_name(rb : RbInterpreter, name : String, under : RbModule | RbClass | Nil = nil)\n      if under\n        available = (RbCore.rb_class_defined_under(rb, under, name) != 0)\n      else\n        available = (RbCore.rb_class_defined(rb, name) != 0)\n      end\n\n      return nil if !available\n\n      if under\n        ruby_class = RbCore.rb_class_get_under(rb, under, name)\n      else\n        ruby_class = RbCore.rb_class_get(rb, name)\n      end\n\n      self.new(rb, ruby_class, under) if ruby_class\n    end\n\n    def to_rb_obj\n      RbCore.get_rb_obj_value(@class_ptr)\n    end\n\n    def to_unsafe\n      return @class_ptr\n    end\n  end\nend\n"
  },
  {
    "path": "src/RbClassCache.cr",
    "content": "module Anyolite\n  # Cache for mruby class and module references\n  module RbClassCache\n    @@cache = {} of String => RbClass | RbModule\n\n    def self.register(crystal_class : Class, rb_class : RbClass)\n      @@cache[crystal_class.name] = rb_class\n    end\n\n    def self.register(crystal_module : Class, rb_module : RbModule)\n      @@cache[crystal_module.name] = rb_module\n    end\n\n    def self.get(n : Nil)\n      nil\n    end\n\n    def self.get(ruby_module : RbModule)\n      ruby_module\n    end\n\n    def self.get(crystal_class : Class)\n      if @@cache[crystal_class.name]?\n        return @@cache[crystal_class.name]\n      else\n        raise \"Uncached class or module: #{crystal_class}\"\n      end\n    end\n\n    def self.check(crystal_class : Class | RbModule | Nil)\n      if crystal_class.is_a?(Class)\n        @@cache[crystal_class.name]?\n      else\n        crystal_class\n      end\n    end\n\n    def self.reset\n      @@cache.clear\n    end\n  end\nend\n"
  },
  {
    "path": "src/RbInternal.cr",
    "content": "{% if flag?(:anyolite_implementation_mruby_3) %}\n  require \"./implementations/mruby/Implementation.cr\"\n{% elsif flag?(:anyolite_implementation_ruby_3) %}\n  require \"./implementations/mri/Implementation.cr\"\n{% else %}\n  # Default is mruby 3\n  require \"./implementations/mruby/Implementation.cr\"\n{% end %}\n"
  },
  {
    "path": "src/RbInterpreter.cr",
    "content": "module Anyolite\r\n  # Wrapper for an mruby state reference\r\n  # NOTE: Do not create more than one at a time!\r\n  class RbInterpreter\r\n    @rb_ptr : RbCore::State*\r\n    property depth : UInt32 = 0\r\n\r\n    def self.create\r\n      rb = self.new\r\n\r\n      Anyolite::HelperClasses.load_all(rb)\r\n\r\n      yield rb\r\n      rb.close\r\n    end\r\n\r\n    def initialize\r\n      @rb_ptr = \r\n      {% if flag?(:anyolite_external_ruby) %}\r\n        Pointer(Anyolite::RbCore::State).null\r\n      {% else %}\r\n        RbCore.rb_open\r\n      {% end %}\r\n      RbRefTable.set_current_interpreter(self)\r\n    end\r\n\r\n    def close\r\n      {% unless flag?(:anyolite_external_ruby) %}\r\n        RbCore.rb_close(@rb_ptr)\r\n      {% end %}\r\n      RbRefTable.reset\r\n      RbTypeCache.reset\r\n      RbClassCache.reset\r\n    end\r\n\r\n    def to_unsafe\r\n      return @rb_ptr\r\n    end\r\n\r\n    def execute_script_line(str : String, clear_error : Bool = true)\r\n      @depth += 1\r\n      value = RbCore.execute_script_line(@rb_ptr, str)\r\n      @depth -= 1\r\n      RbCore.clear_last_rb_error(@rb_ptr) if clear_error\r\n      value\r\n    end\r\n\r\n    def load_script_from_file(filename : String)\r\n      @depth += 1\r\n      RbCore.load_script_from_file(@rb_ptr, filename)\r\n      @depth -= 1\r\n    end\r\n\r\n    def execute_bytecode(bytecode : Array(UInt8))\r\n      @depth += 1\r\n      RbCore.execute_bytecode(@rb_ptr, bytecode)\r\n      @depth -= 1\r\n    end\r\n\r\n    def load_bytecode_from_file(filename : String)\r\n      @depth += 1\r\n      RbCore.load_bytecode_from_file(@rb_ptr, filename)\r\n      @depth -= 1\r\n    end\r\n\r\n    # TODO: Use internal mruby arg count in future versions\r\n    def define_method(name : String, c : RbClass | RbModule, proc : RbCore::RbFunc)\r\n      if c.is_a?(RbModule)\r\n        raise \"Tried to define method #{name} for RbModule #{c}\"\r\n      else\r\n        RbCore.rb_define_method(@rb_ptr, c, name, proc, 1)\r\n      end\r\n    end\r\n\r\n    def define_module_function(name : String, mod : RbModule | RbClass, proc : RbCore::RbFunc)\r\n      if mod.is_a?(RbModule)\r\n        RbCore.rb_define_module_function(@rb_ptr, mod, name, proc, 1)\r\n      else\r\n        RbCore.rb_define_class_method(@rb_ptr, mod, name, proc, 1)\r\n      end\r\n    end\r\n\r\n    def define_class_method(name : String, c : RbClass | RbModule, proc : RbCore::RbFunc)\r\n      if c.is_a?(RbModule)\r\n        RbCore.rb_define_module_function(@rb_ptr, c, name, proc, 1)\r\n      else\r\n        RbCore.rb_define_class_method(@rb_ptr, c, name, proc, 1)\r\n      end\r\n    end\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/RbModule.cr",
    "content": "module Anyolite\n  # Reference to a mruby module\n  class RbModule\n    @module_ptr : RbCore::RClassPtr\n\n    def initialize(@rb : RbInterpreter, @name : String, @under : RbModule | RbClass | Nil = nil)\n      if mod = @under\n        @module_ptr = RbCore.rb_define_module_under(@rb, mod, @name)\n      else\n        @module_ptr = RbCore.rb_define_module(@rb, @name)\n      end\n    end\n\n    def initialize(@rb : RbInterpreter, @module_ptr : RbCore::RClassPtr, @under : RbModule | RbClass | Nil = nil)\n      @name = String.new(RbCore.rb_class_name(@rb, @module_ptr))\n    end\n\n    def self.get_from_ruby_name(rb : RbInterpreter, name : String, under : RbModule | RbClass | Nil = nil)\n      if under\n        available = (RbCore.rb_module_defined_under(rb, under, name) != 0)\n      else\n        available = (RbCore.rb_module_defined(rb, name) != 0)\n      end\n\n      return nil if !available\n\n      if under\n        ruby_module = RbCore.rb_module_get_under(rb, under, name)\n      else\n        ruby_module = RbCore.rb_module_get(rb, name)\n      end\n\n      # Does not work yet, why?\n\n      self.new(rb, ruby_module, under) if ruby_module\n    end\n\n    def to_rb_obj\n      RbCore.get_rb_obj_value(@class_ptr)\n    end\n\n    def to_unsafe\n      return @module_ptr\n    end\n  end\nend\n"
  },
  {
    "path": "src/RbRefTable.cr",
    "content": "module Anyolite\r\n  # This is a very simple approach to generate artificial references to the wrapped objects.\r\n  # Therefore, the GC won't delete the wrapped objects until necessary.\r\n  # Furthermore, this is only possible as a module due to C closure limitations.\r\n  #\r\n  # TODO: Add compilation option for ignoring entry checks\r\n  # TODO: Put the hash value union into a struct\r\n  module RbRefTable\r\n    @@content = {} of UInt64 => Tuple(Void*, Int64, RbCore::RbValue | Nil)\r\n\r\n    @@current_interpreter : RbInterpreter | Nil = nil\r\n\r\n    @@options = {\r\n      # Log every change in the reference table\r\n      :logging => false,\r\n\r\n      # Display warning messages\r\n      :warnings => true,\r\n\r\n      # Throw an exception if any warning occurs\r\n      :pedantic => true,\r\n\r\n      # If true, values with same object IDs can overwrite each other\r\n      :replace_conflicting_pointers => false,\r\n    }\r\n\r\n    def self.get(identification)\r\n      return @@content[identification][0]\r\n    end\r\n\r\n    def self.get_rb_value(identification)\r\n      if rb_value = @@content[identification][2]\r\n        return rb_value\r\n      else\r\n        raise \"No ruby value given for object id #{identification}.\"\r\n      end\r\n    end\r\n\r\n    def self.set_current_interpreter(interpreter : RbInterpreter)\r\n      if @@current_interpreter\r\n        puts \"WARNING: One interpreter was already registered and will be overwritten!\" if option_active?(:warnings)\r\n        raise \"Current interpreter was overwritten.\" if option_active?(:pedantic)\r\n      else\r\n        @@current_interpreter = interpreter\r\n      end\r\n    end\r\n\r\n    def self.check_interpreter\r\n      !!@@current_interpreter\r\n    end\r\n\r\n    def self.get_current_interpreter : RbInterpreter\r\n      if c = @@current_interpreter\r\n        c\r\n      else\r\n        raise \"No interpreter instance available.\"\r\n      end\r\n    end\r\n\r\n    def self.add(identification, value, rb_value)\r\n      # TODO: Clean this up a bit\r\n      puts \"> Added reference #{identification} -> #{value}\" if option_active?(:logging)\r\n      if @@content[identification]?\r\n        if value != @@content[identification][0]\r\n          if option_active?(:replace_conflicting_pointers)\r\n            puts \"WARNING: Value #{identification} replaced pointers (#{value} vs #{@@content[identification][0]}).\" if option_active?(:warnings)\r\n            raise \"Corrupted reference table\" if option_active?(:pedantic)\r\n            @@content[identification] = {value, @@content[identification][1] + 1, rb_value}\r\n          else\r\n            if rb_value == @@content[identification][2]\r\n              @@content[identification] = {@@content[identification][0], @@content[identification][1] + 1, rb_value}\r\n            else\r\n              puts \"WARNING: Ruby value for #{identification} got updated.\" if option_active?(:warnings)\r\n              raise \"Corrupted reference table\" if option_active?(:pedantic)\r\n            end\r\n          end\r\n        else\r\n          @@content[identification] = {value, @@content[identification][1] + 1, rb_value}\r\n        end\r\n      else\r\n        @@content[identification] = {value, 1i64, rb_value}\r\n      end\r\n    end\r\n\r\n    def self.delete(identification)\r\n      puts \"> Removed reference #{identification}\" if option_active?(:logging)\r\n      if @@content[identification]?\r\n        @@content.delete(identification)\r\n      else\r\n        puts \"WARNING: Tried to remove unregistered object #{identification} from reference table.\" if option_active?(:warnings)\r\n        raise \"Corrupted reference table\" if option_active?(:pedantic)\r\n      end\r\n      nil\r\n    end\r\n\r\n    def self.is_registered?(identification)\r\n      return @@content[identification]?\r\n    end\r\n\r\n    def self.may_delete?(identification)\r\n      @@content[identification][1] <= 1\r\n    end\r\n\r\n    def self.inspect\r\n      @@content.inspect\r\n    end\r\n\r\n    def self.number_of_references\r\n      @@content.size\r\n    end\r\n\r\n    def self.reset\r\n      if !@@content.empty?\r\n        puts \"WARNING: Reference table is not empty (#{@@content.size} elements will be deleted).\" if option_active?(:warnings)\r\n        raise \"Corrupted reference table\" if option_active?(:pedantic)\r\n      end\r\n      @@content.clear\r\n\r\n      @@current_interpreter = nil\r\n    end\r\n\r\n    # TODO: If a struct wrapper is given here, call the struct methods instead of the wrapper methods\r\n    def self.get_object_id(value)\r\n      if value.responds_to?(:rb_ref_id)\r\n        value.rb_ref_id.to_u64\r\n      elsif value.responds_to?(:object_id)\r\n        value.object_id.to_u64\r\n      else\r\n        value.hash.to_u64\r\n      end\r\n    end\r\n\r\n    def self.option_active?(symbol)\r\n      if @@options[symbol]?\r\n        @@options[symbol]\r\n      else\r\n        false\r\n      end\r\n    end\r\n\r\n    def self.set_option(symbol)\r\n      @@options[symbol] = true\r\n    end\r\n\r\n    def self.unset_option(symbol)\r\n      @@options[symbol] = false\r\n    end\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/RbTypeCache.cr",
    "content": "module Anyolite\n  # Cache for mruby data types, holding the destructor methods\n  module RbTypeCache\n    @@cache = {} of String => RbCore::RbDataType*\n\n    def self.register(crystal_class : Class, destructor : RbCore::RbDataFunc)\n      unless @@cache[crystal_class.name]?\n        new_type = RbCore::RbDataType.new(struct_name: crystal_class.name, dfree: destructor)\n        @@cache[crystal_class.name] = Pointer(RbCore::RbDataType).malloc(size: 1, value: new_type)\n      end\n      return @@cache[crystal_class.name]\n    end\n\n    def self.register_custom_destructor(crystal_class : Class, destructor : RbCore::RbDataFunc)\n      new_type = RbCore::RbDataType.new(struct_name: crystal_class.name, dfree: destructor)\n      Pointer(RbCore::RbDataType).malloc(size: 1, value: new_type)\n    end\n\n    macro destructor_method(crystal_class)\n      Anyolite::Macro.new_rb_data_func do\n        if {{crystal_class}} <= Struct || {{crystal_class}} <= Enum\n          %crystal_ptr = __ptr.as(Anyolite::StructWrapper({{crystal_class}})*)\n          %obj_id = Anyolite::RbRefTable.get_object_id(%crystal_ptr.value)\n\n          # Call optional mruby callback\n          if (%crystal_value = %crystal_ptr.value.content).responds_to?(:rb_finalize)\n            if Anyolite::RbRefTable.may_delete?(%obj_id)\n              %crystal_value.rb_finalize(__rb)\n            end\n          end\n        else\n          %crystal_ptr = __ptr.as({{crystal_class}}*)\n          %obj_id = Anyolite::RbRefTable.get_object_id(%crystal_ptr.value)\n\n          if (%crystal_value = %crystal_ptr.value).responds_to?(:rb_finalize)\n            if Anyolite::RbRefTable.may_delete?(%obj_id)\n              %crystal_value.rb_finalize(__rb)\n            end\n          end\n        end\n\n        # Delete the Crystal reference to this object\n        Anyolite::RbRefTable.delete(%obj_id)\n      end\n    end\n\n    def self.reset\n      @@cache.clear\n    end\n  end\nend\n"
  },
  {
    "path": "src/helper_classes/AnyolitePointer.cr",
    "content": "module Anyolite\n  module HelperClasses\n    class AnyolitePointer\n      property ptr : Void* = Pointer(Void).null\n\n      @[Anyolite::Specialize]\n      def initialize\n        Anyolite.raise_runtime_error(\"Crystal pointers can not be created in Ruby\")\n      end\n\n      def initialize(obj)\n        @ptr = Box.box(obj)\n      end\n\n      def to_s\n        @ptr.address.to_s\n      end\n\n      @[Anyolite::Exclude]\n      def retrieve_ptr\n        if !@ptr\n          raise \"Anyolite pointer was not initialized\"\n        else\n          @ptr\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "src/helper_classes/HelperClasses.cr",
    "content": "require \"./AnyolitePointer.cr\"\nrequire \"./Regex.cr\"\n\nmodule Anyolite\n  module HelperClasses\n    macro load_helper_class(rb, helper_class)\n      Anyolite.wrap({{rb}}, Anyolite::HelperClasses::{{helper_class}})\n    end\n\n    def self.load_all(rb)\n      load_helper_class(rb, AnyolitePointer)\n\n      # We don't need two conflicting Regex classes in MRI\n      {% unless flag?(:anyolite_implementation_ruby_3) %}\n        Anyolite.wrap(rb, Regex)\n      {% end %}\n    end\n  end\nend\n"
  },
  {
    "path": "src/helper_classes/Regex.cr",
    "content": "{% if flag?(:anyolite_implementation_ruby_3) %}\r\n  {% skip_file %}\r\n{% end %}\r\n\r\n@[Anyolite::ExcludeConstant(\"SPECIAL_CHARACTERS\")]\r\n{% if compare_versions(Crystal::VERSION, \"1.7.3\") > 0 %}\r\n  {% if compare_versions(Crystal::VERSION, \"1.9.0\") > 0 %}\r\n    @[Anyolite::ExcludeInstanceMethod(\"match!\")]\r\n  {% end %}\r\n  @[Anyolite::SpecializeInstanceMethod(\"initialize\", [source : String, options : Options = Options::None], [source : String])]\r\n  @[Anyolite::SpecializeInstanceMethod(\"match\", [str : String, pos : Int32 = 0, options : Regex::MatchOptions = :none], [str : String, pos : Int32 = 0])]\r\n  @[Anyolite::SpecializeInstanceMethod(\"matches?\", [str : String, pos : Int32 = 0, options : Regex::MatchOptions = :none], [str : String, pos : Int32 = 0])]\r\n  @[Anyolite::SpecializeInstanceMethod(\"match_at_byte_index\", [str : String, byte_index : Int32 = 0, options : Regex::MatchOptions = :none], [str : String, byte_index : Int32 = 0])]\r\n  @[Anyolite::SpecializeInstanceMethod(\"matches_at_byte_index?\", [str : String, byte_index : Int32 = 0, options : Regex::MatchOptions = :none], [str : String, byte_index : Int32 = 0])]\r\n{% else %}\r\n  @[Anyolite::SpecializeInstanceMethod(\"initialize\", [source : String, options : Options = Options::None], [source : String])]\r\n  @[Anyolite::SpecializeInstanceMethod(\"match\", [str, pos = 0, options = Regex::Options::None], [str : String, pos : Int32 = 0])]\r\n  @[Anyolite::SpecializeInstanceMethod(\"matches?\", [str, pos = 0, options = Regex::Options::None], [str : String, pos : Int32 = 0])]\r\n  @[Anyolite::SpecializeInstanceMethod(\"match_at_byte_index\", [str, byte_index = 0, options = Regex::Options::None], [str : String, byte_index : Int32 = 0])]\r\n  @[Anyolite::SpecializeInstanceMethod(\"matches_at_byte_index?\", [str, byte_index = 0, options = Regex::Options::None], [str : String, byte_index : Int32 = 0])]\r\n{% end %}\r\n@[Anyolite::SpecializeInstanceMethod(\"+\", [other], [other : Regex])]\r\n@[Anyolite::SpecializeInstanceMethod(\"=~\", [other], [other : String | Regex])]\r\n@[Anyolite::SpecializeInstanceMethod(\"===\", [other : String])]\r\n@[Anyolite::ExcludeInstanceMethod(\"each_capture_group\")]\r\n@[Anyolite::ExcludeClassMethod(\"union\")]\r\n@[Anyolite::ExcludeClassMethod(\"append_source\")]\r\n@[Anyolite::SpecializeClassMethod(\"error?\", [source], [source : String])]\r\n@[Anyolite::SpecializeClassMethod(\"escape\", [str], [str : String])]\r\n@[Anyolite::SpecializeClassMethod(\"needs_escape?\", [str : String], [str : String | Char])]\r\n@[Anyolite::DefaultOptionalArgsToKeywordArgs]\r\n@[Anyolite::RenameClass(\"Regexp\")]\r\n@[Anyolite::ExcludeConstant(\"Engine\")]\r\n@[Anyolite::ExcludeConstant(\"PCRE2\")]\r\n@[Anyolite::ExcludeConstant(\"Error\")]\r\n@[Anyolite::ExcludeConstant(\"Options\")]\r\n{% if compare_versions(Crystal::VERSION, \"1.7.3\") > 0 %}\r\n  {% if compare_versions(Crystal::VERSION, \"1.9.0\") > 0 %}\r\n    @[Anyolite::ExcludeClassMethod(\"literal\")]\r\n  {% end %}\r\n  @[Anyolite::ExcludeConstant(\"MatchOptions\")]\r\n  @[Anyolite::ExcludeConstant(\"CompileOptions\")]\r\n  {% if compare_versions(Crystal::VERSION, \"1.8.0\") > 0 %}\r\n    @[Anyolite::ExcludeInstanceMethod(\"each_named_capture_group\")]\r\n  {% end %}\r\n{% end %}\r\nclass Regex\r\n  @[Anyolite::SpecializeInstanceMethod(\"[]?\", [n : Int])]\r\n  @[Anyolite::SpecializeInstanceMethod(\"[]\", [n : Int])]\r\n  @[Anyolite::SpecializeInstanceMethod(\"byte_begin\", [n = 0], [n : Int32 = 0])]\r\n  @[Anyolite::SpecializeInstanceMethod(\"byte_end\", [n = 0], [n : Int32 = 0])]\r\n  @[Anyolite::ExcludeInstanceMethod(\"begin\")]\r\n  @[Anyolite::ExcludeInstanceMethod(\"end\")]\r\n  @[Anyolite::ExcludeInstanceMethod(\"pretty_print\")]\r\n  @[Anyolite::SpecializeInstanceMethod(\"to_s\", [io : IO])]\r\n  @[Anyolite::DefaultOptionalArgsToKeywordArgs]\r\n  struct MatchData\r\n    {% if compare_versions(Crystal::VERSION, \"1.7.3\") > 0 %}\r\n      @[Anyolite::Specialize]\r\n      def initialize(@regex : ::Regex, @code : LibPCRE2::Code*, @string : String, @pos : Int32, @ovector : LibC::SizeT*, @group_size : Int32)\r\n        super\r\n      end\r\n    {% elsif compare_versions(Crystal::VERSION, \"1.6.2\") > 0 %}\r\n      @[Anyolite::Specialize]\r\n      def initialize(@regex : ::Regex, @code : LibPCRE::Pcre, @string : String, @pos : Int32, @ovector : Int32*, @group_size : Int32)\r\n        super\r\n      end\r\n    {% end %}\r\n  end\r\n\r\n  {% if compare_versions(Crystal::VERSION, \"1.6.2\") > 0 %}\r\n    def initialize(source : String, options : Options = Options::None)\r\n      super(_source: source, _options: Regex::Options::None)\r\n    end\r\n  {% end %}\r\n\r\n  def self.compile(str : String)\r\n    self.new(str)\r\n  end\r\n\r\n  def match?(str : String, pos : Int32 = 0)\r\n    matches?(str, pos)\r\n  end\r\n\r\n  def match_at_byte_index?(str : String, byte_index : Int32 = 0)\r\n    matches_at_byte_index?(str, byte_index)\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/implementations/mri/FormatString.cr",
    "content": "{% unless flag?(:anyolite_implementation_ruby_3) %}\r\n  {% skip_file %}\r\n{% end %}\r\n\r\nmodule Anyolite\r\n  module Macro\r\n    macro format_string(args, options = {} of Symbol => NoReturn)\r\n      {% if args %}\r\n        {% required_counter = 0 %}\r\n        {% optional_counter = 0 %}\r\n        {% optional_args = false %}\r\n\r\n        {% for arg in args %}\r\n          {% if arg.is_a?(TypeDeclaration) %}\r\n            {% if arg.value || optional_args %}\r\n              {% optional_counter += 1 %}\r\n              {% optional_args = true %}\r\n            {% else %}\r\n              {% required_counter += 1 %}\r\n            {% end %}\r\n          {% else %}\r\n            {% if optional_args %}\r\n              {% optional_counter += 1 %}\r\n            {% else %}\r\n              {% required_counter += 1 %}\r\n            {% end %}\r\n          {% end %}\r\n        {% end %}\r\n\r\n        \"{{required_counter}}{{optional_counter > 0 ? optional_counter : \"\".id}}\"\r\n      {% else %}\r\n        \"\"\r\n      {% end %}\r\n    end\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/implementations/mri/Implementation.cr",
    "content": "{% unless flag?(:anyolite_implementation_ruby_3) %}\n  {% skip_file %}\n{% end %}\n\nrequire \"./RbCore.cr\"\nrequire \"./FormatString.cr\"\n\nANYOLITE_INTERNAL_FLAG_USE_GENERAL_OBJECT_FORMAT_CHARS = true\n\nmodule Anyolite\n  module Macro\n    macro new_rb_func(&b)\n      Anyolite::RbCore::RbFunc.new do |_argc, _argv, _obj|\n        _rb = Pointer(Anyolite::RbCore::State).null\n        begin\n          {{b.body}}\n        rescue ex : ArgumentError\n          Anyolite.raise_argument_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : DivisionByZeroError\n          Anyolite.raise_runtime_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : IndexError\n          Anyolite.raise_index_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : KeyError\n          Anyolite.raise_key_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : NilAssertionError\n          Anyolite.raise_runtime_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : NotImplementedError\n          Anyolite.raise_not_implemented_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : OverflowError\n          Anyolite.raise_runtime_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : RuntimeError\n          Anyolite.raise_runtime_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : TypeCastError\n          Anyolite.raise_type_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex\n          Anyolite.raise_runtime_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        end\n      end\n    end\n\n    macro new_rb_data_func(&b)\n      Anyolite::RbCore::RbDataFunc.new do |__ptr|\n        __rb = Pointer(Anyolite::RbCore::State).null\n        {{b.body}}\n      end\n    end\n\n    macro convert_regex_from_ruby_to_crystal(rb, arg, arg_type)\n      {{arg_type}}.new(Anyolite.call_rb_method_of_object({{arg}}, :to_s, cast_to: String))\n    end\n\n    # TODO: This can potentially be done in a simpler way, but for now this is okay\n    # Why are you passing Regex values between Crystal and Ruby anyway?\n    macro convert_regex_from_crystal_to_ruby(rb, value)\n      %rb_class = Anyolite.get_rb_class_obj_of(\"Regexp\")\n      %new_method = Anyolite::RbCore.convert_to_rb_sym({{rb}}, \"new\")\n      %args = [Anyolite::RbCast.return_string({{rb}}, value.source)]\n      Anyolite::RbCore.rb_funcall_argv({{rb}}, %rb_class, %new_method, 1, %args)\n    end\n\n    macro set_default_args_for_regular_args(args, regular_arg_tuple, number_of_args)\n      {% c = 0 %}\n      {% if args %}\n        {% for arg in args %}\n          {% if arg.is_a? TypeDeclaration %}\n            {% if arg.value %}\n              if {{number_of_args}} <= {{c}} && Anyolite::RbCast.check_for_nil({{regular_arg_tuple}}[{{c}}].value)\n                {{regular_arg_tuple}}[{{c}}].value = Anyolite::RbCast.return_value(_rb, {{arg.value}})\n              end\n            {% end %}\n          {% elsif arg.is_a? Path %}\n            # No default argument was given, so no action is required here\n          {% else %}\n            {% raise \"Not a TypeDeclaration or a Path: #{arg} of #{arg.class_name}\" %}\n          {% end %}\n          {% c += 1 %}\n        {% end %}\n      {% end %}\n    end\n\n    macro load_args_into_vars(args, format_string, regular_arg_tuple, block_ptr = nil)\n      {% if block_ptr %}\n        %number_of_args = Anyolite::RbCore.rb_get_args(_argc, _argv, {{format_string}}, *{{regular_arg_tuple}}, {{block_ptr}})\n      {% else %}\n        %number_of_args = Anyolite::RbCore.rb_get_args(_argc, _argv, {{format_string}}, *{{regular_arg_tuple}})\n      {% end %}\n\n      Anyolite::Macro.set_default_args_for_regular_args({{args}}, {{regular_arg_tuple}}, %number_of_args)\n    end\n\n    macro load_kw_args_into_vars(regular_args, keyword_args, format_string, regular_arg_tuple, block_ptr = nil)\n      %kw_ptr = Pointer(Anyolite::RbCore::RbValue).malloc(size: 1, value: Anyolite::RbCast.return_nil)\n\n      {% if block_ptr %}\n        %number_of_args = Anyolite::RbCore.rb_get_args(_argc, _argv, {{format_string}}, *{{regular_arg_tuple}}, %kw_ptr, {{block_ptr}})\n      {% else %}\n        %number_of_args = Anyolite::RbCore.rb_get_args(_argc, _argv, {{format_string}}, *{{regular_arg_tuple}}, %kw_ptr)\n      {% end %}\n\n      # TODO: Is number_of_args for the regular arg function correct here?\n\n      Anyolite::Macro.set_default_args_for_regular_args({{regular_args}}, {{regular_arg_tuple}}, %number_of_args)\n\n      # TODO: This is relatively complicated and messy, so can this be simplified?\n\n      if Anyolite::RbCast.check_for_nil(%kw_ptr.value)\n        %hash_key_values = [] of String\n      else\n        %rb_hash_key_values = Anyolite::RbCore.rb_hash_keys(_rb, %kw_ptr.value)\n        %hash_key_values = Anyolite::Macro.convert_from_ruby_to_crystal(_rb, %rb_hash_key_values, k : Array(String))\n      end\n\n      %return_hash = {} of Symbol => Anyolite::RbCore::RbValue\n      {% for keyword_arg in keyword_args %}\n        {% if keyword_arg.is_a? TypeDeclaration %}\n          if %hash_key_values.includes?(\":{{keyword_arg.var.id}}\")\n            %ruby_hash_value = Anyolite::RbCore.rb_hash_get(_rb, %kw_ptr.value, Anyolite::RbCore.get_symbol_value_of_string(_rb, \"{{keyword_arg.var.id}}\"))\n            %return_hash[:{{keyword_arg.var.id}}] = %ruby_hash_value\n          else\n            {% if !keyword_arg.value.is_a? Nop %}\n              %return_hash[:{{keyword_arg.var.id}}] = Anyolite::RbCast.return_value(_rb, {{keyword_arg.value}})\n            {% else %}\n              Anyolite.raise_argument_error(\"Keyword #{\"{{keyword_arg.var.id}}\"} was not defined.\")\n            {% end %}\n          end\n        {% elsif arg.is_a? Path %}\n          # No default argument was given, so no action is required here\n        {% else %}\n          {% raise \"Not a TypeDeclaration or a Path: #{keyword_arg} of #{keyword_arg.class_name}\" %}\n        {% end %}\n      {% end %}\n\n      %return_hash\n    end\n  end\nend\n"
  },
  {
    "path": "src/implementations/mri/RbCore.cr",
    "content": "{% unless flag?(:anyolite_implementation_ruby_3) %}\r\n  {% skip_file %}\r\n{% end %}\r\n\r\nmodule Anyolite\r\n  macro link_libraries\r\n    {% build_path = env(\"ANYOLITE_BUILD_PATH\") ? env(\"ANYOLITE_BUILD_PATH\") : \"build\" %}\r\n\r\n    {% if flag?(:win32) %}\r\n      {% libruby_path = \"#{__DIR__}/../../../#{build_path.id}/mri/lib/x64-vcruntime140-ruby300-static.lib\" %}\r\n    {% else %}\r\n      {% libruby_path = \"#{__DIR__}/../../../#{build_path.id}/mri/lib/libruby-static.a\" %}\r\n    {% end %}\r\n\r\n    {% if !file_exists?(libruby_path) %}\r\n      {% raise \"File #{libruby_path} not found. Was MRI installed correctly?\" %}\r\n    {% end %}\r\n    \r\n    {% if flag?(:win32) %}\r\n      @[Link(ldflags: {{libruby_path.stringify + \" msvcrt.lib Ws2_32.lib iphlpapi.lib dbghelp.lib Shell32.lib User32.lib\"}})]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mri/return_functions.obj\\\"\")]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mri/data_helper.obj\\\"\")]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mri/script_helper.obj\\\"\")]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mri/error_helper.obj\\\"\")]\r\n    {% else %}\r\n      @[Link(ldflags: {{libruby_path.stringify + \" -lgmp -lcrypt -lz\"}})]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mri/return_functions.o\\\" -lgmp -lcrypt -lz\")]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mri/data_helper.o\\\" -lgmp -lcrypt -lz\")]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mri/script_helper.o\\\" -lgmp -lcrypt -lz\")]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mri/error_helper.o\\\" -lgmp -lcrypt -lz\")]\r\n    {% end %}\r\n  end\r\n\r\n  {% unless flag?(:anyolite_external_ruby) %}\r\n    Anyolite.link_libraries\r\n  {% end %}\r\n\r\n  lib RbCore\r\n    alias RbFunc = Proc(RbInt, RbValue*, RbValue, RbValue) # argc, argv, self -> VALUE\r\n    alias RbDataFunc = Proc(Void*, Nil)\r\n\r\n    type State = Void\r\n\r\n    alias RClassPtr = RbValue\r\n\r\n    alias RbFloat = LibC::Double\r\n    alias RbInt = Int64\r\n    alias RbBool = UInt8\r\n    alias RbSymbol = LibC::ULong\r\n\r\n    enum MrbVType\r\n      MRB_TT_FALSE     = 0\r\n      MRB_TT_TRUE\r\n      MRB_TT_SYMBOL\r\n      MRB_TT_UNDEF\r\n      MRB_TT_FREE\r\n      MRB_TT_FLOAT\r\n      MRB_TT_INTEGER\r\n      MRB_TT_CPTR\r\n      MRB_TT_OBJECT\r\n      MRB_TT_CLASS\r\n      MRB_TT_MODULE\r\n      MRB_TT_ICLASS\r\n      MRB_TT_SCLASS\r\n      MRB_TT_PROC\r\n      MRB_TT_ARRAY\r\n      MRB_TT_HASH\r\n      MRB_TT_STRING\r\n      MRB_TT_RANGE\r\n      MRB_TT_EXCEPTION\r\n      MRB_TT_ENV\r\n      MRB_TT_DATA\r\n      MRB_TT_FIBER\r\n      MRB_TT_ISTRUCT\r\n      MRB_TT_BREAK\r\n      MRB_TT_COMPLEX\r\n      MRB_TT_RATIONAL\r\n      MRB_TT_MAXDEFINE\r\n    end\r\n\r\n    struct RbValue\r\n      w : LibC::ULong\r\n    end\r\n\r\n    struct RbDataType\r\n      struct_name : LibC::Char*\r\n      dmark : RbDataFunc\r\n      dfree : RbDataFunc\r\n      dize : Proc(Void*, LibC::SizeT)\r\n      dcompact : RbDataFunc\r\n      reserved : Void**\r\n      parent : RbDataType*\r\n      data : Void*\r\n      flags : RbValue\r\n    end\r\n\r\n    struct KWArgs\r\n      num : UInt32\r\n      required : UInt32\r\n      table : RbSymbol*\r\n      values : RbValue*\r\n      rest : RbValue*\r\n    end\r\n\r\n    fun rb_open = open_interpreter : State*\r\n    fun rb_close = close_interpreter(rb : State*)\r\n\r\n    fun rb_define_module = rb_define_module_helper(rb : State*, name : LibC::Char*) : RClassPtr\r\n    fun rb_define_module_under = rb_define_module_under_helper(rb : State*, under : RClassPtr, name : LibC::Char*) : RClassPtr\r\n    fun rb_define_class = rb_define_class_helper(rb : State*, name : LibC::Char*, superclass : RClassPtr) : RClassPtr\r\n    fun rb_define_class_under = rb_define_class_under_helper(rb : State*, under : RClassPtr, name : LibC::Char*, superclass : RClassPtr) : RClassPtr\r\n\r\n    fun rb_define_method = rb_define_method_helper(rb : State*, c : RClassPtr, name : LibC::Char*, func : RbFunc, aspec : UInt32) # TODO: Aspec values\r\n    fun rb_define_class_method = rb_define_class_method_helper(rb : State*, c : RClassPtr, name : LibC::Char*, func : RbFunc, aspect : UInt32)\r\n    fun rb_define_module_function = rb_define_module_function_helper(rb : State*, c : RClassPtr, name : LibC::Char*, func : RbFunc, aspect : UInt32)\r\n\r\n    fun rb_define_const = rb_define_const_helper(rb : State*, c : RClassPtr, name : LibC::Char*, val : RbValue)\r\n\r\n    # UNUSED\r\n    # fun rb_print_error = mrb_print_error(rb : State*)\r\n\r\n    fun get_last_rb_error(rb : State*) : RbValue\r\n    fun clear_last_rb_error(rb : State*)\r\n\r\n    fun rb_raise = rb_raise_helper(rb : State*, c : RClassPtr, msg : LibC::Char*)\r\n    fun rb_raise_runtime_error = rb_raise_runtime_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_type_error = rb_raise_type_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_argument_error = rb_raise_argument_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_index_error = rb_raise_index_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_range_error = rb_raise_range_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_name_error = rb_raise_name_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_script_error = rb_raise_script_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_not_implemented_error = rb_raise_not_implemented_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_key_error = rb_raise_key_error(rb : State*, msg : LibC::Char*)\r\n\r\n    fun rb_get_args = rb_scan_args(argc : RbInt, argv : RbValue*, format : LibC::Char*, ...) : RbInt\r\n\r\n    # UNUSED\r\n    # fun rb_get_argc = mrb_get_argc(rb : State*) : RbInt\r\n    # fun rb_get_argv = mrb_get_argv(rb : State*) : RbValue*\r\n\r\n    fun rb_yield = rb_yield_helper(rb : State*, value : RbValue, arg : RbValue) : RbValue\r\n    fun rb_yield_argv = rb_yield_argv_helper(rb : State*, value : RbValue, argc : RbInt, argv : RbValue*) : RbValue\r\n\r\n    fun rb_call_block = rb_yield_helper(rb : State*, value : RbValue, arg : RbValue) : RbValue\r\n    fun rb_call_block_with_args = rb_call_block_with_args_helper(rb : State*, value : RbValue, argc : RbInt, argv : RbValue*) : RbValue\r\n\r\n    fun rb_ary_ref = rb_ary_ref_helper(rb : State*, value : RbValue, pos : RbInt) : RbValue\r\n    fun rb_ary_entry(value : RbValue, offset : RbInt) : RbValue\r\n    fun array_length = rb_ary_length_helper(value : RbValue) : LibC::SizeT\r\n\r\n    fun rb_ary_new_from_values = rb_ary_new_from_values_helper(rb : State*, size : RbInt, values : RbValue*) : RbValue\r\n\r\n    fun rb_hash_new = rb_hash_new_helper(rb : State*) : RbValue\r\n    fun rb_hash_set = rb_hash_set_helper(rb : State*, hash : RbValue, key : RbValue, value : RbValue)\r\n    fun rb_hash_get = rb_hash_get_helper(rb : State*, hash : RbValue, key : RbValue) : RbValue\r\n    fun rb_hash_keys = rb_hash_keys_helper(rb : State*, hash : RbValue) : RbValue\r\n    fun rb_hash_size = rb_hash_size_helper(rb : State*, hash : RbValue) : RbInt\r\n\r\n    fun get_nil_value : RbValue\r\n    fun get_false_value : RbValue\r\n    fun get_true_value : RbValue\r\n    fun get_fixnum_value(value : RbInt) : RbValue\r\n    fun get_bool_value(value : RbBool) : RbValue\r\n    fun get_float_value(rb : State*, value : RbFloat) : RbValue\r\n    fun get_string_value(rb : State*, value : LibC::Char*) : RbValue\r\n\r\n    fun check_rb_fixnum(value : RbValue) : LibC::Int\r\n    fun check_rb_float(value : RbValue) : LibC::Int\r\n    fun check_rb_true(value : RbValue) : LibC::Int\r\n    fun check_rb_false(value : RbValue) : LibC::Int\r\n    fun check_rb_nil(value : RbValue) : LibC::Int\r\n    fun check_rb_undef(value : RbValue) : LibC::Int\r\n    fun check_rb_string(value : RbValue) : LibC::Int\r\n    fun check_rb_symbol(value : RbValue) : LibC::Int\r\n    fun check_rb_array(value : RbValue) : LibC::Int\r\n    fun check_rb_hash(value : RbValue) : LibC::Int\r\n    fun check_rb_data(value : RbValue) : LibC::Int\r\n\r\n    fun get_rb_fixnum(value : RbValue) : RbInt\r\n    fun get_rb_float(value : RbValue) : RbFloat\r\n    fun get_rb_bool(value : RbValue) : RbBool\r\n    fun get_rb_string(rb : State*, value : RbValue) : LibC::Char*\r\n\r\n    fun rb_str_to_cstr(rb : State*, value : RbValue) : LibC::Char*\r\n\r\n    fun convert_to_rb_sym = convert_to_rb_sym_helper(rb : State*, value : LibC::Char*) : RbSymbol\r\n    fun get_symbol_value_of_string(rb : State*, value : LibC::Char*) : RbValue\r\n\r\n    # Base class, not to be confused with `get_class_of_obj`\r\n    fun get_object_class(rb : State*) : RClassPtr\r\n\r\n    # UNUSED\r\n    # fun rb_obj_inspect = mrb_obj_inspect(rb : State*, value : RbValue) : RbValue\r\n    # fun rb_any_to_s = mrb_any_to_s(rb : State*, value : RbValue) : RbValue\r\n\r\n    fun rb_inspect = rb_inspect_helper(rb : State*, value : RbValue) : RbValue\r\n\r\n    fun rb_gc_register = rb_gc_register_helper(rb : State*, value : RbValue) : Void\r\n    fun rb_gc_unregister = rb_gc_unregister_helper(rb : State*, value : RbValue) : Void\r\n\r\n    fun rb_class_name = rb_class_name_helper(rb : State*, class_ptr : RClassPtr) : LibC::Char*\r\n\r\n    # UNUSED\r\n    # fun data_type(value : RbValue) : RbDataType*\r\n    # fun rb_data_get_ptr = mrb_data_get_ptr(rb : State*, obj : RbValue, type : RbDataType*) : Void*\r\n\r\n    fun set_instance_tt_as_data(ruby_class : RClassPtr) : Void\r\n    fun new_empty_object(rb : State*, ruby_class : RClassPtr, data_ptr : Void*, type : RbDataType*) : RbValue\r\n    fun set_data_ptr_and_type(ruby_object : RbValue, data : Void*, type : RbDataType*)\r\n    fun get_data_ptr(ruby_object : RbValue) : Void*\r\n\r\n    fun get_rb_obj_value(p : RClassPtr) : RbValue\r\n\r\n    fun rb_obj_is_kind_of = rb_obj_is_kind_of_helper(rb : State*, obj : RbValue, c : RClassPtr) : RbBool\r\n    fun get_class_of_obj = rb_obj_class_helper(rb : State*, obj : RbValue) : RClassPtr\r\n\r\n    fun rb_funcall_argv = rb_funcall_argv_helper(rb : State*, value : RbValue, name : RbSymbol, argc : RbInt, argv : RbValue*) : RbValue\r\n    fun rb_funcall_argv_with_block = rb_funcall_argv_with_block_helper(rb : State*, value : RbValue, name : RbSymbol, argc : RbInt, argv : RbValue*, block : RbValue) : RbValue\r\n\r\n    fun rb_respond_to = rb_respond_to_helper(rb : State*, obj : RbValue, name : RbSymbol) : RbBool\r\n\r\n    fun rb_class_get = get_constant(rb : State*, name : LibC::Char*) : RClassPtr\r\n    fun rb_class_get_under = get_constant_under(rb : State*, under : RClassPtr, name : LibC::Char*) : RClassPtr\r\n\r\n    fun rb_class_defined = does_constant_exist(rb : State*, name : LibC::Char*) : RbBool\r\n    fun rb_class_defined_under = does_constant_exist_under(rb : State*, under : RClassPtr, name : LibC::Char*) : RbBool\r\n\r\n    fun rb_module_get = get_constant(rb : State*, name : LibC::Char*) : RClassPtr\r\n    fun rb_module_get_under = get_constant_under(rb : State*, under : RClassPtr, name : LibC::Char*) : RClassPtr\r\n\r\n    fun rb_module_defined = does_constant_exist(rb : State*, name : LibC::Char*) : RbBool\r\n    fun rb_module_defined_under = does_constant_exist_under(rb : State*, under : RClassPtr, name : LibC::Char*) : RbBool\r\n\r\n    fun rb_iv_set = rb_iv_set_helper(rb : State*, obj : RbValue, sym : RbSymbol, value : RbValue) : Void\r\n    fun rb_iv_get = rb_iv_get_helper(rb : State*, obj : RbValue, sym : RbSymbol) : RbValue\r\n\r\n    fun rb_cv_set = rb_cv_set_helper(rb : State*, mod : RbValue, sym : RbSymbol, value : RbValue) : Void\r\n    fun rb_cv_get = rb_cv_get_helper(rb : State*, mod : RbValue, sym : RbSymbol) : RbValue\r\n\r\n    fun rb_gv_set = rb_gv_set_helper(rb : State*, name : LibC::Char*, value : RbValue) : Void\r\n    fun rb_gv_get = rb_gv_get_helper(rb : State*, name : LibC::Char*) : RbValue\r\n\r\n    fun rb_undef_method = rb_undef_method_helper(rb : State*, class_ptr : RClassPtr, name : LibC::Char*) : Void\r\n    fun rb_undef_class_method = rb_undef_method_helper(rb : State*, class_ptr : RClassPtr, name : LibC::Char*) : Void\r\n\r\n    fun load_script_from_file(rb : State*, filename : LibC::Char*) : Void\r\n\r\n    fun execute_script_line(rb : State*, str : LibC::Char*) : RbValue\r\n\r\n    # UNUSED\r\n    # fun execute_bytecode(rb : State*, bytecode : UInt8*) : RbValue\r\n    # fun load_bytecode_from_file(rb : State*, filename : LibC::Char*) : RbValue\r\n    # fun transform_script_to_bytecode(filename : LibC::Char*, target_filename : LibC::Char*) : LibC::Int\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/implementations/mruby/FormatString.cr",
    "content": "module Anyolite\r\n  module Macro\r\n    macro format_string(args, options = {} of Symbol => NoReturn)\r\n      \"\" +\r\n      {% if args %}\r\n        {% for arg in args %}\r\n          Anyolite::Macro.format_char({{arg}}, options: {{options}}) +\r\n        {% end %}\r\n      {% end %}\r\n      \"\"\r\n    end\r\n\r\n    macro format_char(arg, options = {} of Symbol => NoReturn)\r\n      {% if arg.is_a?(TypeDeclaration) %}\r\n        {% if arg.type.is_a?(Union) %}\r\n          {% if options[:optional_values] != true %}\r\n            \"|o\"\r\n          {% else %}\r\n            \"o\"\r\n          {% end %}\r\n        {% elsif options[:optional_values] != true && arg.value %}\r\n          {% options[:optional_values] = true %}\r\n          \"|\" + Anyolite::Macro.format_char({{arg.type}}, options: {{options}})\r\n        {% else %}\r\n          Anyolite::Macro.format_char({{arg.type}}, options: {{options}})\r\n        {% end %}\r\n      {% elsif options[:context] %}\r\n        Anyolite::Macro.resolve_format_char({{options[:context]}}::{{arg.stringify.starts_with?(\"::\") ? arg.stringify[2..-1].id : arg}}, {{arg}}, options: {{options}})\r\n      {% else %}\r\n        Anyolite::Macro.resolve_format_char({{arg}}, {{arg}})\r\n      {% end %}\r\n    end\r\n\r\n    macro resolve_format_char(arg, raw_arg, options = {} of Symbol => NoReturn)\r\n      {% if arg.resolve? %}\r\n        {% if ANYOLITE_INTERNAL_FLAG_USE_GENERAL_OBJECT_FORMAT_CHARS %}\r\n          \"o\"\r\n        {% else %}\r\n          {% if arg.resolve <= Bool %}\r\n            \"b\"\r\n          {% elsif arg.resolve <= Pointer %}\r\n            \"o\"\r\n          {% elsif arg.resolve <= Int %}\r\n            \"i\"\r\n          {% elsif arg.resolve <= Float || arg.resolve == Number %}\r\n            \"f\"\r\n          {% elsif arg.resolve <= String %}\r\n            \"z\"\r\n          {% elsif arg.resolve <= Array %}\r\n            \"A\"\r\n          {% elsif arg.resolve <= Anyolite::RbRef %}\r\n            \"o\"\r\n          {% else %}\r\n            \"o\"\r\n          {% end %}\r\n        {% end %}\r\n      {% elsif options[:context] %}\r\n        {% if options[:context].names[0..-2].size > 0 %}\r\n          {% new_context = options[:context].names[0..-2].join(\"::\").gsub(/(::)+/, \"::\").id %}\r\n          {% options[:context] = new_context %}\r\n          Anyolite::Macro.resolve_format_char({{new_context}}::{{raw_arg.stringify.starts_with?(\"::\") ? raw_arg.stringify[2..-1].id : raw_arg}}, {{raw_arg}}, options: {{options}})\r\n        {% else %}\r\n          # No context available anymore\r\n          Anyolite::Macro.resolve_format_char({{raw_arg}}, {{raw_arg}})\r\n        {% end %}\r\n      {% else %}\r\n        \"o\"\r\n      {% end %}\r\n    end\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/implementations/mruby/Implementation.cr",
    "content": "require \"./RbCore.cr\"\nrequire \"./FormatString.cr\"\nrequire \"./KeywordArgStruct.cr\"\n\n{% if flag?(:use_general_object_format_chars) %}\n  ANYOLITE_INTERNAL_FLAG_USE_GENERAL_OBJECT_FORMAT_CHARS = true\n{% else %}\n  ANYOLITE_INTERNAL_FLAG_USE_GENERAL_OBJECT_FORMAT_CHARS = false\n{% end %}\n\nmodule Anyolite\n  module Macro\n    macro new_rb_func(&b)\n      Anyolite::RbCore::RbFunc.new do |_rb, _obj|\n        begin\n          {{b.body}}\n        rescue ex : ArgumentError\n          Anyolite.raise_argument_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : DivisionByZeroError\n          Anyolite.raise_runtime_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : IndexError\n          Anyolite.raise_index_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : KeyError\n          Anyolite.raise_key_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : NilAssertionError\n          Anyolite.raise_runtime_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : NotImplementedError\n          Anyolite.raise_not_implemented_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : OverflowError\n          Anyolite.raise_runtime_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : RuntimeError\n          Anyolite.raise_runtime_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex : TypeCastError\n          Anyolite.raise_type_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        rescue ex\n          Anyolite.raise_runtime_error(\"#{ex.inspect_with_backtrace} (raised from Crystal)\")\n          Anyolite::RbCast.return_nil\n        end\n      end\n    end\n\n    macro new_rb_data_func(&b)\n      Anyolite::RbCore::RbDataFunc.new do |__rb, __ptr|\n        {{b.body}}\n      end\n    end\n\n    macro convert_regex_from_ruby_to_crystal(rb, arg, arg_type)\n      Anyolite::Macro.convert_from_ruby_object({{rb}}, {{arg}}, {{arg_type}}).value\n    end\n\n    macro convert_regex_from_crystal_to_ruby(rb, value)\n      RbCast.return_object({{rb}}, {{value}})\n    end\n\n    macro load_args_into_vars(args, format_string, regular_arg_tuple, block_ptr = nil)\n      {% if block_ptr %}\n        Anyolite::RbCore.rb_get_args(_rb, {{format_string}}, *{{regular_arg_tuple}}, {{block_ptr}})\n      {% else %}\n        Anyolite::RbCore.rb_get_args(_rb, {{format_string}}, *{{regular_arg_tuple}})\n      {% end %}\n    end\n\n    macro load_kw_args_into_vars(regular_args, keyword_args, format_string, regular_arg_tuple, block_ptr = nil)\n      %kw_args = Anyolite::Macro.generate_keyword_argument_struct(_rb, {{keyword_args}})\n\n      {% if block_ptr %}\n        Anyolite::RbCore.rb_get_args(_rb, {{format_string}}, *{{regular_arg_tuple}}, pointerof(%kw_args), {{block_ptr}})\n      {% else %}\n        Anyolite::RbCore.rb_get_args(_rb, {{format_string}}, *{{regular_arg_tuple}}, pointerof(%kw_args))\n      {% end %}\n\n      %kw_args\n    end\n  end\nend\n"
  },
  {
    "path": "src/implementations/mruby/KeywordArgStruct.cr",
    "content": "module Anyolite\n  module Macro\n    macro generate_keyword_argument_struct(rb_interpreter, keyword_args)\n      %kw_names = Anyolite::Macro.generate_keyword_names({{rb_interpreter}}, {{keyword_args}})\n      %kw_args = Anyolite::RbCore::KWArgs.new\n      %kw_args.num = {{keyword_args.size}}\n      %kw_args.values = Pointer(Anyolite::RbCore::RbValue).malloc(size: {{keyword_args.size}})\n      %kw_args.table = %kw_names\n      %kw_args.required = {{keyword_args.select { |i| !i.var }.size}}\n      %kw_args.rest = Pointer(Anyolite::RbCore::RbValue).malloc(size: 1)\n      %kw_args\n    end\n\n    macro generate_keyword_names(rb_interpreter, keyword_args)\n      [\n        {% for keyword in keyword_args %}\n          Anyolite::RbCore.convert_to_rb_sym({{rb_interpreter}}, {{keyword.var.stringify}}),\n        {% end %}\n      ]\n    end\n  end\nend\n"
  },
  {
    "path": "src/implementations/mruby/RbCore.cr",
    "content": "module Anyolite\r\n  macro link_libraries\r\n    {% build_path = env(\"ANYOLITE_BUILD_PATH\") ? env(\"ANYOLITE_BUILD_PATH\") : \"build\" %}\r\n\r\n    {% if flag?(:win32) %}\r\n      {% libmruby_path = \"#{__DIR__}/../../../#{build_path.id}/mruby/lib/libmruby.lib\" %}\r\n    {% else %}\r\n      {% libmruby_path = \"#{__DIR__}/../../../#{build_path.id}/mruby/lib/libmruby.a\" %}\r\n    {% end %}\r\n\r\n    {% if !file_exists?(libmruby_path) %}\r\n      {% raise \"File #{libmruby_path} not found. Was mruby installed correctly?\" %}\r\n    {% end %}\r\n    \r\n    {% if flag?(:win32) %}\r\n      {% if flag?(:anyolite_use_msvcrt_lib) %}\r\n        # Not recommended, might be removed in a later release\r\n        @[Link(ldflags: {{libmruby_path.stringify + \" msvcrt.lib\"}})]\r\n      {% elsif compare_versions(Crystal::VERSION, \"1.5.1\") >= 0 %}\r\n        # Crystal links against libucrt since 1.5.1\r\n        @[Link(ldflags: {{libmruby_path.stringify}})]\r\n      {% else %}\r\n        @[Link(ldflags: {{libmruby_path.stringify + \" libucrt.lib\"}})]\r\n      {% end %}\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mruby/return_functions.obj\\\"\")]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mruby/data_helper.obj\\\"\")]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mruby/script_helper.obj\\\"\")]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mruby/error_helper.obj\\\"\")]\r\n    {% else %}\r\n      @[Link(ldflags: {{libmruby_path.stringify + \" -lm\"}})]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mruby/return_functions.o\\\"\")]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mruby/data_helper.o\\\"\")]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mruby/script_helper.o\\\"\")]\r\n      @[Link(ldflags: \"\\\"#{__DIR__}/../../../{{build_path.id}}/glue/mruby/error_helper.o\\\"\")]\r\n    {% end %}\r\n  end\r\n\r\n  {% unless env(\"ANYOLITE_DOCUMENTATION_MODE\") %}\r\n    Anyolite.link_libraries\r\n  {% end %}\r\n\r\n  lib RbCore\r\n    alias RbFunc = Proc(State*, RbValue, RbValue)\r\n    alias RbDataFunc = Proc(State*, Void*, Nil)\r\n\r\n    type State = Void\r\n    type RClass = Void\r\n\r\n    alias RbFloat = LibC::Double\r\n    alias RbInt = Int64\r\n    alias RbBool = UInt8\r\n    alias RbSymbol = UInt32\r\n\r\n    alias RClassPtr = RClass*\r\n\r\n    enum MrbVType\r\n      MRB_TT_FALSE     = 0\r\n      MRB_TT_TRUE\r\n      MRB_TT_SYMBOL\r\n      MRB_TT_UNDEF\r\n      MRB_TT_FREE\r\n      MRB_TT_FLOAT\r\n      MRB_TT_INTEGER\r\n      MRB_TT_CPTR\r\n      MRB_TT_OBJECT\r\n      MRB_TT_CLASS\r\n      MRB_TT_MODULE\r\n      MRB_TT_ICLASS\r\n      MRB_TT_SCLASS\r\n      MRB_TT_PROC\r\n      MRB_TT_ARRAY\r\n      MRB_TT_HASH\r\n      MRB_TT_STRING\r\n      MRB_TT_RANGE\r\n      MRB_TT_EXCEPTION\r\n      MRB_TT_ENV\r\n      MRB_TT_DATA\r\n      MRB_TT_FIBER\r\n      MRB_TT_ISTRUCT\r\n      MRB_TT_BREAK\r\n      MRB_TT_COMPLEX\r\n      MRB_TT_RATIONAL\r\n      MRB_TT_MAXDEFINE\r\n    end\r\n\r\n    struct RbValue\r\n      w : LibC::ULongLong\r\n    end\r\n\r\n    struct RbDataType\r\n      struct_name : LibC::Char*\r\n      dfree : RbDataFunc\r\n    end\r\n\r\n    struct KWArgs\r\n      num : RbInt\r\n      required : RbInt\r\n      table : RbSymbol*\r\n      values : RbValue*\r\n      rest : RbValue*\r\n    end\r\n\r\n    struct BytecodeContainer\r\n      content : UInt8*\r\n      size : LibC::SizeT\r\n      error_code : LibC::Int\r\n      result : LibC::Int\r\n    end\r\n\r\n    fun rb_open = mrb_open : State*\r\n    fun rb_close = mrb_close(rb : State*)\r\n\r\n    fun rb_define_module = mrb_define_module(rb : State*, name : LibC::Char*) : RClassPtr\r\n    fun rb_define_module_under = mrb_define_module_under(rb : State*, under : RClassPtr, name : LibC::Char*) : RClassPtr\r\n    fun rb_define_class = mrb_define_class(rb : State*, name : LibC::Char*, superclass : RClassPtr) : RClassPtr\r\n    fun rb_define_class_under = mrb_define_class_under(rb : State*, under : RClassPtr, name : LibC::Char*, superclass : RClassPtr) : RClassPtr\r\n\r\n    fun rb_define_method = mrb_define_method(rb : State*, c : RClassPtr, name : LibC::Char*, func : RbFunc, aspec : UInt32) # TODO: Aspec values\r\n    fun rb_define_class_method = mrb_define_class_method(rb : State*, c : RClassPtr, name : LibC::Char*, func : RbFunc, aspect : UInt32)\r\n    fun rb_define_module_function = mrb_define_module_function(rb : State*, c : RClassPtr, name : LibC::Char*, func : RbFunc, aspect : UInt32)\r\n\r\n    fun rb_define_const = mrb_define_const(rb : State*, c : RClassPtr, name : LibC::Char*, val : RbValue)\r\n\r\n    fun rb_print_error = mrb_print_error(rb : State*)\r\n    fun rb_print_backtrace = mrb_print_backtrace(rb : State*)\r\n\r\n    fun get_last_rb_error = get_last_mrb_error(rb : State*) : RbValue\r\n    fun clear_last_rb_error = clear_last_mrb_error(rb : State*)\r\n\r\n    fun rb_raise = mrb_raise(rb : State*, c : RClassPtr, msg : LibC::Char*)\r\n    fun rb_raise_runtime_error = mrb_raise_runtime_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_type_error = mrb_raise_type_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_argument_error = mrb_raise_argument_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_index_error = mrb_raise_index_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_range_error = mrb_raise_range_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_name_error = mrb_raise_name_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_script_error = mrb_raise_script_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_not_implemented_error = mrb_raise_not_implemented_error(rb : State*, msg : LibC::Char*)\r\n    fun rb_raise_key_error = mrb_raise_key_error(rb : State*, msg : LibC::Char*)\r\n\r\n    fun rb_get_args = mrb_get_args(rb : State*, format : LibC::Char*, ...) : RbInt\r\n\r\n    fun rb_get_argc = mrb_get_argc(rb : State*) : RbInt\r\n    fun rb_get_argv = mrb_get_argv(rb : State*) : RbValue*\r\n\r\n    fun rb_yield = mrb_yield(rb : State*, value : RbValue, arg : RbValue) : RbValue\r\n    fun rb_yield_argv = mrb_yield_argv(rb : State*, value : RbValue, argc : RbInt, argv : RbValue*) : RbValue\r\n\r\n    fun rb_call_block = mrb_yield(rb : State*, value : RbValue, arg : RbValue) : RbValue\r\n    fun rb_call_block_with_args = mrb_yield_argv(rb : State*, value : RbValue, argc : RbInt, argv : RbValue*) : RbValue\r\n\r\n    fun rb_ary_ref = mrb_ary_ref(rb : State*, value : RbValue, pos : RbInt) : RbValue\r\n    fun rb_ary_entry = mrb_ary_entry(value : RbValue, offset : RbInt) : RbValue\r\n    fun array_length(value : RbValue) : LibC::SizeT\r\n\r\n    fun rb_ary_new_from_values = mrb_ary_new_from_values(rb : State*, size : RbInt, values : RbValue*) : RbValue\r\n\r\n    fun rb_hash_new = mrb_hash_new(rb : State*) : RbValue\r\n    fun rb_hash_set = mrb_hash_set(rb : State*, hash : RbValue, key : RbValue, value : RbValue)\r\n    fun rb_hash_get = mrb_hash_get(rb : State*, hash : RbValue, key : RbValue) : RbValue\r\n    fun rb_hash_keys = mrb_hash_keys(rb : State*, hash : RbValue) : RbValue\r\n    fun rb_hash_size = mrb_hash_size(rb : State*, hash : RbValue) : RbInt\r\n\r\n    fun get_nil_value : RbValue\r\n    fun get_false_value : RbValue\r\n    fun get_true_value : RbValue\r\n    fun get_fixnum_value(value : RbInt) : RbValue\r\n    fun get_bool_value(value : RbBool) : RbValue\r\n    fun get_float_value(rb : State*, value : RbFloat) : RbValue\r\n    fun get_string_value(rb : State*, value : LibC::Char*) : RbValue\r\n\r\n    fun check_rb_fixnum = check_mrb_fixnum(value : RbValue) : LibC::Int\r\n    fun check_rb_float = check_mrb_float(value : RbValue) : LibC::Int\r\n    fun check_rb_true = check_mrb_true(value : RbValue) : LibC::Int\r\n    fun check_rb_false = check_mrb_false(value : RbValue) : LibC::Int\r\n    fun check_rb_nil = check_mrb_nil(value : RbValue) : LibC::Int\r\n    fun check_rb_undef = check_mrb_undef(value : RbValue) : LibC::Int\r\n    fun check_rb_string = check_mrb_string(value : RbValue) : LibC::Int\r\n    fun check_rb_symbol = check_mrb_symbol(value : RbValue) : LibC::Int\r\n    fun check_rb_array = check_mrb_array(value : RbValue) : LibC::Int\r\n    fun check_rb_hash = check_mrb_hash(value : RbValue) : LibC::Int\r\n    fun check_rb_data = check_mrb_data(value : RbValue) : LibC::Int\r\n\r\n    fun get_rb_fixnum = get_mrb_fixnum(value : RbValue) : RbInt\r\n    fun get_rb_float = get_mrb_float(value : RbValue) : RbFloat\r\n    fun get_rb_bool = get_mrb_bool(value : RbValue) : RbBool\r\n    fun get_rb_string = get_mrb_string(rb : State*, value : RbValue) : LibC::Char*\r\n\r\n    fun rb_str_to_cstr = mrb_str_to_cstr(rb : State*, value : RbValue) : LibC::Char*\r\n\r\n    fun convert_to_rb_sym = convert_to_mrb_sym(rb : State*, value : LibC::Char*) : RbSymbol\r\n    fun get_symbol_value_of_string(rb : State*, value : LibC::Char*) : RbValue\r\n\r\n    # Base class, not to be confused with `get_class_of_obj`\r\n    fun get_object_class(rb : State*) : RClassPtr\r\n\r\n    fun rb_obj_inspect = mrb_obj_inspect(rb : State*, value : RbValue) : RbValue\r\n    fun rb_any_to_s = mrb_any_to_s(rb : State*, value : RbValue) : RbValue\r\n    fun rb_inspect = mrb_inspect(rb : State*, value : RbValue) : RbValue\r\n\r\n    fun rb_gc_register = mrb_gc_register(rb : State*, value : RbValue) : Void\r\n    fun rb_gc_unregister = mrb_gc_unregister(rb : State*, value : RbValue) : Void\r\n\r\n    fun rb_class_name = mrb_class_name(rb : State*, class_ptr : RClassPtr) : LibC::Char*\r\n\r\n    fun data_type(value : RbValue) : RbDataType*\r\n    fun rb_data_get_ptr = mrb_data_get_ptr(rb : State*, obj : RbValue, type : RbDataType*) : Void*\r\n    fun set_instance_tt_as_data(ruby_class : RClassPtr) : Void\r\n    fun new_empty_object(rb : State*, ruby_class : RClassPtr, data_ptr : Void*, type : RbDataType*) : RbValue\r\n    fun set_data_ptr_and_type(ruby_object : RbValue, data : Void*, type : RbDataType*)\r\n    fun get_data_ptr(ruby_object : RbValue) : Void*\r\n\r\n    fun get_rb_obj_value = get_mrb_obj_value(p : RClassPtr) : RbValue\r\n\r\n    fun rb_obj_is_kind_of = mrb_obj_is_kind_of(rb : State*, obj : RbValue, c : RClassPtr) : RbBool\r\n    fun get_class_of_obj(rb : State*, obj : RbValue) : RClassPtr\r\n\r\n    fun rb_funcall_argv = mrb_funcall_argv(rb : State*, value : RbValue, name : RbSymbol, argc : RbInt, argv : RbValue*) : RbValue\r\n    fun rb_funcall_argv_with_block = mrb_funcall_with_block(rb : State*, value : RbValue, name : RbSymbol, argc : RbInt, argv : RbValue*, block : RbValue) : RbValue\r\n\r\n    fun rb_respond_to = mrb_respond_to(rb : State*, obj : RbValue, name : RbSymbol) : RbBool\r\n\r\n    fun rb_class_get = mrb_class_get(rb : State*, name : LibC::Char*) : RClassPtr\r\n    fun rb_class_get_under = mrb_class_get_under(rb : State*, under : RClassPtr, name : LibC::Char*) : RClassPtr\r\n\r\n    fun rb_class_defined = mrb_class_defined(rb : State*, name : LibC::Char*) : RbBool\r\n    fun rb_class_defined_under = mrb_class_defined_under(rb : State*, under : RClassPtr, name : LibC::Char*) : RbBool\r\n\r\n    fun rb_module_get = mrb_module_get(rb : State*, name : LibC::Char*) : RClassPtr\r\n    fun rb_module_get_under = mrb_module_get_under(rb : State*, under : RClassPtr, name : LibC::Char*) : RClassPtr\r\n\r\n    fun rb_module_defined = mrb_class_defined(rb : State*, name : LibC::Char*) : RbBool\r\n    fun rb_module_defined_under = mrb_class_defined_under(rb : State*, under : RClassPtr, name : LibC::Char*) : RbBool\r\n\r\n    fun rb_iv_set = mrb_iv_set(rb : State*, obj : RbValue, sym : RbSymbol, value : RbValue) : Void\r\n    fun rb_iv_get = mrb_iv_get(rb : State*, obj : RbValue, sym : RbSymbol) : RbValue\r\n\r\n    fun rb_cv_set = mrb_cv_set(rb : State*, mod : RbValue, sym : RbSymbol, value : RbValue) : Void\r\n    fun rb_cv_get = mrb_cv_get(rb : State*, mod : RbValue, sym : RbSymbol) : RbValue\r\n\r\n    # NOTE: These are differing due to global variable methods by ID being private in MRI\r\n    # NOTE: You should not use globals that often, anyway\r\n\r\n    fun rb_gv_set = mrb_gv_set_helper(rb : State*, name : LibC::Char*, value : RbValue) : Void\r\n    fun rb_gv_get = mrb_gv_get_helper(rb : State*, name : LibC::Char*) : RbValue\r\n\r\n    fun rb_undef_method = mrb_undef_method(rb : State*, class_ptr : RClassPtr, name : LibC::Char*) : Void\r\n    fun rb_undef_class_method = mrb_undef_class_method(rb : State*, class_ptr : RClassPtr, name : LibC::Char*) : Void\r\n\r\n    fun load_script_from_file(rb : State*, filename : LibC::Char*) : RbValue\r\n    fun execute_script_line(rb : State*, str : LibC::Char*) : RbValue\r\n    fun execute_bytecode(rb : State*, bytecode : UInt8*) : RbValue\r\n    fun load_bytecode_from_file(rb : State*, filename : LibC::Char*) : RbValue\r\n\r\n    fun transform_script_to_bytecode(filename : LibC::Char*, target_filename : LibC::Char*) : LibC::Int\r\n    fun transform_script_to_bytecode_container(filename : LibC::Char*) : BytecodeContainer\r\n    fun transform_proc_to_bytecode_container(rb : State*, proc_object : RbValue) : BytecodeContainer\r\n    fun free_bytecode_container(container : BytecodeContainer) : Void\r\n\r\n    fun rb_fiber_resume = mrb_fiber_resume(rb : State*, fiber : RbValue, argc : RbInt, argv : RbValue*) : RbValue\r\n    fun rb_fiber_yield = mrb_fiber_yield(rb : State*, argc : RbInt, argv : RbValue*) : RbValue\r\n    fun rb_fiber_alive = mrb_fiber_alive_p(rb : State*, fiber : RbValue) : RbValue\r\n\r\n    fun rb_gc_arena_save = mrb_gc_arena_save_helper(rb : State*) : LibC::Int\r\n    fun rb_gc_arena_restore = mrb_gc_arena_restore_helper(rb : State*, idx : LibC::Int) : Void\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/macros/ArgConversions.cr",
    "content": "module Anyolite\r\n  module Macro\r\n    macro get_raw_args(rb, regular_args, context = nil)\r\n      {% options = {:context => context} %}\r\n      %args = Anyolite::Macro.generate_arg_tuple({{rb}}, {{regular_args}}, options: {{options}})\r\n      %format_string = Anyolite::Macro.format_string({{regular_args}}, options: {{options}})\r\n      Anyolite::Macro.load_args_into_vars({{regular_args}}, %format_string, %args)\r\n      %args\r\n    end\r\n\r\n    # Converts Ruby values to Crystal values\r\n    macro convert_regular_arg(rb, arg, arg_type, options = {} of Symbol => NoReturn, debug_information = nil)\r\n      {% if arg_type.stringify.includes?(\"->\") || arg_type.stringify.includes?(\" Proc(\") %}\r\n        {% puts \"\\e[33m> INFO: Proc types are not allowed as arguments.\\e[0m\" %}\r\n        raise \"Proc types are not allowed as arguments ({{debug_information.id}})\"\r\n      {% elsif arg_type.stringify.includes?(\" Slice(\") %}\r\n        {% puts \"\\e[33m> INFO: Slice types are not allowed as arguments (#{debug_information.id}).\\e[0m\" %}\r\n        raise \"Slice types are not allowed as arguments ({{debug_information.id}})\"\r\n      {% elsif arg_type.is_a?(Generic) %}\r\n        Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{arg}}, dummy_arg : {{arg_type}}, options: {{options}}, debug_information: {{debug_information}})\r\n      {% elsif arg_type.is_a?(TypeDeclaration) && arg_type.type.is_a?(Union) %}\r\n        Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{arg}}, {{arg_type}}, options: {{options}}, debug_information: {{debug_information}})\r\n      {% elsif arg_type.is_a?(TypeDeclaration) %}\r\n        Anyolite::Macro.convert_regular_arg({{rb}}, {{arg}}, {{arg_type.type}}, options: {{options}}, debug_information: {{debug_information}})\r\n      {% elsif options[:context] %}\r\n        Anyolite::Macro.resolve_regular_arg({{rb}}, {{arg}}, {{options[:context]}}::{{arg_type.stringify.starts_with?(\"::\") ? arg_type.stringify[2..-1].id : arg_type}}, {{arg_type}}, options: {{options}}, debug_information: {{debug_information}})\r\n      {% else %}\r\n        Anyolite::Macro.resolve_regular_arg({{rb}}, {{arg}}, {{arg_type}}, {{arg_type}}, debug_information: {{debug_information}})\r\n      {% end %}\r\n    end\r\n\r\n    macro resolve_regular_arg(rb, arg, arg_type, raw_arg_type, options = {} of Symbol => NoReturn, debug_information = nil)\r\n      {% if arg_type.resolve? %}\r\n        {% if arg_type.resolve <= Nil %}\r\n          nil\r\n        {% elsif arg_type.resolve <= Bool %}\r\n          ({{arg}} != 0)\r\n        {% elsif arg_type.resolve == Number %}\r\n          begin\r\n            Float64.new({{arg}})\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{{{arg}}} to {{arg_type}}.\")\r\n            Float64.new(0.0)\r\n          end\r\n        {% elsif arg_type.resolve == Int %}\r\n          begin\r\n            Int64.new({{arg}})\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{{{arg}}} to {{arg_type}}.\")\r\n            Int64.new(0)\r\n          end\r\n        {% elsif arg_type.resolve <= Int %}\r\n          begin\r\n            {{arg_type}}.new({{arg}})\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{{{arg}}} to {{arg_type}}.\")\r\n            {{arg_type}}.new(0)\r\n          end\r\n        {% elsif arg_type.resolve == Float %}\r\n          begin\r\n            Float64.new({{arg}})\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{{{arg}}} to {{arg_type}}.\")\r\n            Float64.new(0.0)\r\n          end\r\n        {% elsif arg_type.resolve <= Float %}\r\n          begin\r\n            {{arg_type}}.new({{arg}})\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{{{arg}}} to {{arg_type}}.\")\r\n            {{arg_type}}.new(0.0)\r\n          end\r\n        {% elsif arg_type.resolve <= Char %}\r\n          Anyolite::RbCast.cast_to_char({{rb}}, {{arg}})\r\n        {% elsif arg_type.resolve <= String %}\r\n          {{arg_type}}.new({{arg}})\r\n        {% elsif arg_type.resolve <= Anyolite::RbRef %}\r\n          {{arg_type}}.new({{arg}})\r\n        {% elsif arg_type.resolve <= Regex %}\r\n          Anyolite::Macro.convert_regex_from_ruby_to_crystal({{rb}}, {{arg}}, {{arg_type}})\r\n        {% elsif arg_type.resolve <= Array %}\r\n          %array_size = Anyolite::RbCore.array_length({{arg}})\r\n          %converted_array = {{arg_type}}.new(size: %array_size) do |%index|\r\n            Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, Anyolite::RbCore.rb_ary_entry({{arg}}, %index), {{arg_type.type_vars[0]}}, options: {{options}}, debug_information: {{debug_information}})\r\n          end\r\n          %converted_array\r\n        {% elsif arg_type.resolve <= Hash %}\r\n          %hash_size = Anyolite::RbCore.rb_hash_size({{rb}}, {{arg}})\r\n\r\n          %all_rb_hash_keys = Anyolite::RbCore.rb_hash_keys({{rb}}, {{arg}})\r\n          %all_converted_hash_keys = Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %all_rb_hash_keys, Array({{arg_type.type_vars[0]}}), options: {{options}}, debug_information: {{debug_information}})\r\n\r\n          %converted_hash = {{arg_type}}.new(initial_capacity: %hash_size)\r\n          %all_converted_hash_keys.each_with_index do |%key, %index|\r\n            %rb_key = Anyolite::RbCore.rb_ary_entry(%all_rb_hash_keys, %index)\r\n            %rb_value = Anyolite::RbCore.rb_hash_get({{rb}}, {{arg}}, %rb_key)\r\n            %converted_hash[%key] = Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %rb_value, {{arg_type.type_vars[1]}}, options: {{options}}, debug_information: {{debug_information}})\r\n          end\r\n\r\n          %converted_hash\r\n        {% elsif arg_type.resolve <= Pointer %}\r\n          {{arg_type}}.new(address: UInt64.new({{arg.address}}))\r\n        {% elsif arg_type.resolve <= Struct || arg_type.resolve <= Enum %}\r\n          Anyolite::Macro.convert_from_ruby_struct({{rb}}, {{arg}}, {{arg_type}}).value.content\r\n        {% else %}\r\n          Anyolite::Macro.convert_from_ruby_object({{rb}}, {{arg}}, {{arg_type}}).value\r\n        {% end %}\r\n      {% elsif options[:context] %}\r\n        {% if options[:context].names[0..-2].size > 0 %}\r\n          {% new_context = options[:context].names[0..-2].join(\"::\").gsub(/(\\:\\:)+/, \"::\").id %}\r\n          {% options[:context] = new_context %}\r\n          Anyolite::Macro.resolve_regular_arg({{rb}}, {{arg}}, {{new_context}}::{{raw_arg_type.stringify.starts_with?(\"::\") ? raw_arg_type.stringify[2..-1].id : raw_arg_type}}, {{raw_arg_type}}, options: {{options}}, debug_information: {{debug_information}})\r\n        {% else %}\r\n          Anyolite::Macro.resolve_regular_arg({{rb}}, {{arg}}, {{raw_arg_type}}, {{raw_arg_type}}, debug_information: {{debug_information}})\r\n        {% end %}\r\n      {% else %}\r\n        {% raise \"Could not resolve #{arg_type}, which is a #{arg_type.class_name}, in any meaningful way (#{debug_information.id})\" %}\r\n      {% end %}\r\n    end\r\n\r\n    macro convert_from_ruby_to_crystal(rb, arg, arg_type, options = {} of Symbol => NoReturn, debug_information = nil)\r\n      {% if arg_type.stringify.includes?(\"->\") || arg_type.stringify.includes?(\" Proc(\") %}\r\n        {% puts \"\\e[33m> INFO: Proc types are not allowed as arguments (#{debug_information.id}).\\e[0m\" %}\r\n        raise \"Proc types are not allowed as arguments ({{debug_information.id}})\"\r\n      {% elsif arg_type.stringify.includes?(\" Slice(\") %}\r\n        {% puts \"\\e[33m> INFO: Slice types are not allowed as arguments (#{debug_information.id}).\\e[0m\" %}\r\n        raise \"Slice types are not allowed as arguments ({{debug_information.id}})\"\r\n      {% elsif options[:type_var_names] && options[:type_var_names].includes?(arg_type.type) %}\r\n        {% options[:type_var_names].each_with_index { |element, index| result = index if element == arg_type.type } %}\r\n        Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{arg}}, {{options[:type_vars][result]}}, options: {{{:context => options[:context]}}}, debug_information: {{debug_information}})\r\n      {% elsif options[:type_var_names] %}\r\n        {% magical_regex = /([\\(\\s\\:])([A-Z]+)([\\),\\s])/ %}\r\n        {% replacement_arg_type = arg_type.type.stringify.gsub(magical_regex, \"\\\\1\\#\\\\2\\#\\\\3\") %}\r\n\r\n        {% for type_var_name, index in options[:type_var_names] %}\r\n          {% split_types = replacement_arg_type.split(\"\\#\") %}\r\n          {% odd = true %}\r\n          {% final_split_types = [] of ASTNode %}\r\n          {% for split_type, split_type_index in split_types %}\r\n            {% if !odd %}\r\n              {% result = nil %}\r\n              {% options[:type_var_names].each_with_index { |element, index| result = index if element.stringify == split_type } %}\r\n              {% if result %}\r\n                {% final_split_types.push(options[:type_vars][result].stringify) %}\r\n              {% else %}\r\n                {% final_split_types.push(split_type) %}\r\n              {% end %}\r\n            {% else %}\r\n              {% final_split_types.push(split_type) %}\r\n            {% end %}\r\n            {% odd = !odd %}\r\n          {% end %}\r\n        {% end %}\r\n\r\n        {% if arg_type.value %}\r\n          {% final_type_def = \"#{arg_type.var} : #{final_split_types.join(\"\").id} = #{arg_type.value}\" %}\r\n        {% else %}\r\n          {% final_type_def = \"#{arg_type.var} : #{final_split_types.join(\"\").id}\" %}\r\n        {% end %}\r\n\r\n        Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{arg}}, {{final_type_def.id}}, options: {{{:context => options[:context]}}}, debug_information: {{debug_information}})\r\n      {% elsif arg_type.is_a?(Call) %}\r\n        Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{arg}}, dummy_arg : {{arg_type}}, options: {{options}}, debug_information: {{debug_information}})\r\n      {% elsif arg_type.is_a?(TypeDeclaration) %}\r\n        if Anyolite::RbCast.is_undef?({{arg}})\r\n          {% if arg_type.value || arg_type.value == false || arg_type.value == nil %}\r\n            {{arg_type.value}}\r\n          {% else %}\r\n            # Should only happen if no default value was given\r\n            Anyolite.raise_argument_error(\"Undefined argument #{{{arg}}} of {{arg_type}} in context {{options[:context]}} (#{{{debug_information.stringify}}})\")\r\n            # Code should jump to somewhere else before this point, but we want to have a NoReturn type here\r\n            raise(\"Should not be reached\")\r\n          {% end %}\r\n        else\r\n          {% if arg_type.type.is_a?(Union) %}\r\n            Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{arg}}, Union({{arg_type.type}}), options: {{options}}, debug_information: {{debug_information}})\r\n          {% else %}\r\n            Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{arg}}, {{arg_type.type}}, options: {{options}}, debug_information: {{debug_information}})\r\n          {% end %}\r\n        end\r\n      # TODO: Check if this might need some improvement\r\n      {% elsif options[:context] && !arg_type.stringify.starts_with?(\"Union\") %}\r\n        Anyolite::Macro.resolve_from_ruby_to_crystal({{rb}}, {{arg}}, {{options[:context]}}::{{arg_type.stringify.starts_with?(\"::\") ? arg_type.stringify[2..-1].id : arg_type}}, {{arg_type}}, options: {{options}}, debug_information: {{debug_information}})\r\n      {% else %}\r\n        Anyolite::Macro.resolve_from_ruby_to_crystal({{rb}}, {{arg}}, {{arg_type}}, {{arg_type}}, options: {{options}}, debug_information: {{debug_information}})\r\n      {% end %}\r\n    end\r\n\r\n    macro resolve_from_ruby_to_crystal(rb, arg, arg_type, raw_arg_type, options = {} of Symbol => NoReturn, debug_information = nil)\r\n      {% if arg_type.stringify.starts_with?(\"Union\") || arg_type.stringify.starts_with?(\"::Union\") %}\r\n        # This sadly needs some uncanny magic\r\n        {% char_parser = \"\" %}\r\n        {% brace_counter = 0 %}\r\n        {% for c in arg_type.stringify[(arg_type.stringify.starts_with?(\"::\") ? 8 : 6)..-2].chars %}\r\n          {% brace_counter += 1 if c == '(' %}\r\n          {% brace_counter -= 1 if c == ')' %}\r\n          {% char_parser += (brace_counter == 0 && c == '|' ? ',' : c) %}\r\n        {% end %}\r\n\r\n        Anyolite::Macro.cast_to_union_value({{rb}}, {{arg}}, {{\"[#{char_parser.id}]\".id}}, options: {{options}}, debug_information: {{debug_information}})\r\n      {% elsif arg_type.resolve? %}\r\n        {% if arg_type.resolve <= Nil %}\r\n          Anyolite::RbCast.cast_to_nil({{rb}}, {{arg}})\r\n        {% elsif arg_type.resolve <= Bool %}\r\n          Anyolite::RbCast.cast_to_bool({{rb}}, {{arg}})\r\n        {% elsif arg_type.resolve == Number %}\r\n          begin\r\n            Float64.new(Anyolite::RbCast.cast_to_float({{rb}}, {{arg}}))\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{Anyolite::RbCast.cast_to_float({{rb}}, {{arg}})} to {{arg_type}}.\")\r\n            Float64.new(0.0)\r\n          end\r\n        {% elsif arg_type.resolve == Int %}\r\n          begin\r\n            Int64.new(Anyolite::RbCast.cast_to_int({{rb}}, {{arg}}))\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{Anyolite::RbCast.cast_to_int({{rb}}, {{arg}})} to {{arg_type}}.\")\r\n            Int64.new(0)\r\n          end\r\n        {% elsif arg_type.resolve <= Int %}\r\n          begin\r\n            {{arg_type}}.new(Anyolite::RbCast.cast_to_int({{rb}}, {{arg}}))\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{Anyolite::RbCast.cast_to_int({{rb}}, {{arg}})} to {{arg_type}}.\")\r\n            {{arg_type}}.new(0)\r\n          end\r\n        {% elsif arg_type.resolve == Float %}\r\n          begin\r\n            Float64.new(Anyolite::RbCast.cast_to_float({{rb}}, {{arg}}))\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{Anyolite::RbCast.cast_to_float({{rb}}, {{arg}})} to {{arg_type}}.\")\r\n            Float64.new(0.0)\r\n          end\r\n        {% elsif arg_type.resolve <= Float %}\r\n          begin\r\n            {{arg_type}}.new(Anyolite::RbCast.cast_to_float({{rb}}, {{arg}}))\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{Anyolite::RbCast.cast_to_float({{rb}}, {{arg}})} to {{arg_type}}.\")\r\n            {{arg_type}}.new(0.0)\r\n          end\r\n        {% elsif arg_type.resolve <= Char %}\r\n          Anyolite::RbCast.cast_to_char({{rb}}, {{arg}})\r\n        {% elsif arg_type.resolve <= String %}\r\n          Anyolite::RbCast.cast_to_string({{rb}}, {{arg}})\r\n        {% elsif arg_type.resolve <= Regex %}\r\n          Anyolite::Macro.convert_regex_from_ruby_to_crystal({{rb}}, {{arg}}, {{arg_type}})\r\n        {% elsif arg_type.resolve <= Anyolite::RbRef %}\r\n          {{arg_type}}.new({{arg}})\r\n        {% elsif arg_type.resolve <= Array %}\r\n          # TODO: Make a macro out of this\r\n          %array_size = Anyolite::RbCore.array_length({{arg}})\r\n          %converted_array = {{arg_type}}.new(size: %array_size) do |%index|\r\n            Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, Anyolite::RbCore.rb_ary_entry({{arg}}, %index), {{arg_type.type_vars[0]}}, options: {{options}}, debug_information: {{debug_information}})\r\n          end\r\n          %converted_array\r\n        {% elsif arg_type.resolve <= Hash %}\r\n          %hash_size = Anyolite::RbCore.rb_hash_size({{rb}}, {{arg}})\r\n\r\n          %all_rb_hash_keys = Anyolite::RbCore.rb_hash_keys({{rb}}, {{arg}})\r\n          %all_converted_hash_keys = Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %all_rb_hash_keys, Array({{arg_type.type_vars[0]}}), options: {{options}}, debug_information: {{debug_information}})\r\n\r\n          %converted_hash = {{arg_type}}.new(initial_capacity: %hash_size)\r\n          %all_converted_hash_keys.each_with_index do |%key, %index|\r\n            %rb_key = Anyolite::RbCore.rb_ary_entry(%all_rb_hash_keys, %index)\r\n            %rb_value = Anyolite::RbCore.rb_hash_get({{rb}}, {{arg}}, %rb_key)\r\n            %converted_hash[%key] = Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %rb_value, {{arg_type.type_vars[1]}}, options: {{options}}, debug_information: {{debug_information}})\r\n          end\r\n\r\n          %converted_hash\r\n        {% elsif arg_type.resolve <= Pointer %}\r\n          %helper_ptr = Anyolite::Macro.convert_from_ruby_object({{rb}}, {{arg}}, Anyolite::HelperClasses::AnyolitePointer).value\r\n          Box({{arg_type}}).unbox(%helper_ptr.retrieve_ptr)\r\n        {% elsif arg_type.resolve <= Struct || arg_type.resolve <= Enum %}\r\n          Anyolite::Macro.convert_from_ruby_struct({{rb}}, {{arg}}, {{arg_type}}).value.content\r\n        {% elsif arg_type.resolve? %}\r\n          Anyolite::Macro.convert_from_ruby_object({{rb}}, {{arg}}, {{arg_type}}).value\r\n        {% else %}\r\n          {% raise \"Could not resolve type #{arg_type}, which is a #{arg_type.class_name.id} (#{debug_information.id})\" %}\r\n        {% end %}\r\n      {% elsif options[:context] %}\r\n        {% if options[:context].names[0..-2].size > 0 %}\r\n          {% new_context = options[:context].names[0..-2].join(\"::\").gsub(/(\\:\\:)+/, \"::\").id %}\r\n          {% options[:context] = new_context %}\r\n          Anyolite::Macro.resolve_from_ruby_to_crystal({{rb}}, {{arg}}, {{new_context}}::{{raw_arg_type.stringify.starts_with?(\"::\") ? raw_arg_type.stringify[2..-1].id : raw_arg_type}}, {{raw_arg_type}}, options: {{options}}, debug_information: {{debug_information}})\r\n        {% else %}\r\n          Anyolite::Macro.resolve_from_ruby_to_crystal({{rb}}, {{arg}}, {{raw_arg_type}}, {{raw_arg_type}}, debug_information: {{debug_information}})\r\n        {% end %}\r\n      {% else %}\r\n        {% raise \"Could not resolve type #{arg_type}, which is a #{arg_type.class_name.id} (#{debug_information.id})\" %}\r\n      {% end %}\r\n    end\r\n\r\n    macro convert_regular_args(rb, args, regular_args, options = {} of Symbol => NoReturn, debug_information = nil)\r\n      Tuple.new(\r\n        {% c = 0 %}\r\n        {% if regular_args %}\r\n          {% for arg in regular_args %}\r\n            {% if ANYOLITE_INTERNAL_FLAG_USE_GENERAL_OBJECT_FORMAT_CHARS %}\r\n              Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{args}}[{{c}}].value, {{arg}}, options: {{options}}, debug_information: {{debug_information}}),\r\n            {% else %}\r\n              Anyolite::Macro.convert_regular_arg({{rb}}, {{args}}[{{c}}].value, {{arg}}, options: {{options}}, debug_information: {{debug_information}}),\r\n            {% end %}\r\n            {% c += 1 %}\r\n          {% end %}\r\n        {% end %}\r\n      )\r\n    end\r\n\r\n    macro get_converted_args(rb, regular_args, options = {} of Symbol => NoReturn)\r\n      %args = Anyolite::Macro.generate_arg_tuple({{rb}}, {{regular_args}}, options: {{options}})\r\n      %format_string = Anyolite::Macro.format_string({{regular_args}}, options: {{options}})\r\n      \r\n      Anyolite::Macro.load_args_into_vars({{regular_args}}, %format_string, %args)\r\n\r\n      Anyolite::Macro.convert_regular_args({{rb}}, %args, {{regular_args}}, options: {{options}})\r\n    end\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/macros/ArgTuples.cr",
    "content": "module Anyolite\r\n  module Macro\r\n    macro generate_arg_tuple(rb, args, options = {} of Symbol => NoReturn)\r\n      Tuple.new(\r\n        {% if args %}\r\n          {% for arg in args %}\r\n            {% if arg.is_a?(TypeDeclaration) %}\r\n              {% if arg.value %}\r\n                {% if ANYOLITE_INTERNAL_FLAG_USE_GENERAL_OBJECT_FORMAT_CHARS %}\r\n                  Anyolite::Macro.pointer_type({{arg}}, options: {{options}}).malloc(size: 1, value: Anyolite::RbCast.return_value({{rb}}, {{arg.value}})),\r\n                {% else %}\r\n                  {% if arg.type.is_a?(Union) %}\r\n                    # This does work, but I'm a bit surprised\r\n                    Anyolite::Macro.pointer_type({{arg}}, options: {{options}}).malloc(size: 1, value: Anyolite::RbCast.return_value({{rb}}, {{arg.value}})),\r\n                  {% elsif arg.type.resolve <= String %}\r\n                    # The outer gods bless my wretched soul that this does neither segfault nor leak\r\n                    Anyolite::Macro.pointer_type({{arg}}, options: {{options}}).malloc(size: 1, value: {{arg.value}}.to_unsafe),\r\n                  {% elsif arg.type.resolve <= Anyolite::RbRef %}\r\n                    Anyolite::Macro.pointer_type({{arg}}, options: {{options}}).malloc(size: 1, value: {{arg.value}}),\r\n                  # NOTE: This might need some extensions\r\n                  {% elsif arg.type.resolve <= Bool %}\r\n                    Anyolite::Macro.pointer_type({{arg}}, options: {{options}}).malloc(size: 1, value: Anyolite::Macro.type_in_ruby({{arg}}, options: {{options}}).new({{arg.value}} ? 1 : 0)),\r\n                  {% elsif arg.type.resolve <= Number %}\r\n                    Anyolite::Macro.pointer_type({{arg}}, options: {{options}}).malloc(size: 1, value: Anyolite::Macro.type_in_ruby({{arg}}, options: {{options}}).new({{arg.value}})),\r\n                  {% else %}\r\n                    Anyolite::Macro.pointer_type({{arg}}, options: {{options}}).malloc(size: 1, value: Anyolite::RbCast.return_value({{rb}}, {{arg.value}})),\r\n                  {% end %}\r\n                {% end %}\r\n              {% else %}\r\n                Anyolite::Macro.pointer_type({{arg}}, options: {{options}}).malloc(size: 1),\r\n              {% end %}\r\n            {% else %}\r\n              Anyolite::Macro.pointer_type({{arg}}, options: {{options}}).malloc(size: 1),\r\n            {% end %}\r\n          {% end %}\r\n        {% end %}\r\n      )\r\n    end\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/macros/FunctionCalls.cr",
    "content": "module Anyolite\r\n  module Macro\r\n    macro call_and_return(rb, proc, regular_args, converted_args, operator = \"\", options = {} of Symbol => NoReturn, block_ptr = nil)\r\n      {% if !options[:block_arg_number] %}\r\n        {% proc_arg_string = \"\" %}\r\n      {% elsif options[:block_arg_number] == 0 %}\r\n        {% proc_arg_string = \"do\" %}\r\n      {% else %}\r\n        {% proc_arg_string = \"do |\" + (0..options[:block_arg_number] - 1).map { |x| \"block_arg_#{x}\" }.join(\", \") + \"|\" %}\r\n      {% end %}\r\n\r\n      {% if proc.stringify == \"Anyolite::Empty\" %}\r\n        %return_value = {{operator.id}}(*{{converted_args}}) {{proc_arg_string.id}}\r\n      {% else %}\r\n        %return_value = {{proc}}{{operator.id}}(*{{converted_args}}) {{proc_arg_string.id}}\r\n      {% end %}\r\n\r\n      {% if options[:block_arg_number] == 0 %}\r\n          %yield_value = Anyolite::RbCore.rb_yield({{rb}}, {{block_ptr}}.value, Anyolite::RbCast.return_nil)\r\n          Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %yield_value, {{options[:block_return_type]}})\r\n        end\r\n      {% elsif options[:block_arg_number] %}\r\n          %block_arg_array = [\r\n            {% for i in 0..options[:block_arg_number] - 1 %}\r\n              Anyolite::RbCast.return_value({{rb}}, {{\"block_arg_#{i}\".id}}),\r\n            {% end %}\r\n          ]\r\n          %yield_value = Anyolite::RbCore.rb_yield_argv({{rb}}, {{block_ptr}}.value, {{options[:block_arg_number]}}, %block_arg_array)\r\n          Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %yield_value, {{options[:block_return_type]}})\r\n        end\r\n      {% end %}\r\n\r\n      {% if options[:return_nil] %}\r\n        Anyolite::RbCast.return_nil\r\n      {% else %}\r\n        Anyolite::RbCast.return_value({{rb}}, %return_value)\r\n      {% end %}\r\n    end\r\n\r\n    macro call_and_return_keyword_method(rb, proc, converted_regular_args, keyword_args, kw_args, operator = \"\", options = {} of Symbol => NoReturn, block_ptr = nil)\r\n      {% if !options[:block_arg_number] %}\r\n        {% proc_arg_string = \"\" %}\r\n      {% elsif options[:block_arg_number] == 0 %}\r\n        {% proc_arg_string = \"do\" %}\r\n      {% else %}\r\n        {% proc_arg_string = \"do |\" + (0..options[:block_arg_number] - 1).map { |x| \"block_arg_#{x}\" }.join(\", \") + \"|\" %}\r\n      {% end %}\r\n\r\n      {% if proc.stringify == \"Anyolite::Empty\" %}\r\n        %return_value = {{operator.id}}(\r\n      {% else %}\r\n        %return_value = {{proc}}{{operator.id}}(\r\n      {% end %}\r\n        {% if options[:empty_regular] %}\r\n          {% c = 0 %}\r\n          {% for keyword in keyword_args %}\r\n            {{keyword.var.id}}: Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{kw_args}}.values[{{c}}], {{keyword}}, options: {{options}}, debug_information: {{proc.stringify + \" - \" + keyword_args.stringify}}),\r\n            {% c += 1 %}\r\n          {% end %}\r\n        {% else %}\r\n          *{{converted_regular_args}},\r\n          {% c = 0 %}\r\n          {% for keyword in keyword_args %}\r\n            {{keyword.var.id}}: Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{kw_args}}.values[{{c}}], {{keyword}}, options: {{options}}, debug_information: {{proc.stringify + \" - \" + keyword_args.stringify}}),\r\n            {% c += 1 %}\r\n          {% end %}\r\n        {% end %}\r\n      ) {{proc_arg_string.id}}\r\n\r\n      {% if options[:block_arg_number] == 0 %}\r\n          %yield_value = Anyolite::RbCore.rb_yield({{rb}}, {{block_ptr}}.value, Anyolite::RbCast.return_nil)\r\n          Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %yield_value, {{options[:block_return_type]}})\r\n        end\r\n      {% elsif options[:block_arg_number] %}\r\n          %block_arg_array = [\r\n            {% for i in 0..options[:block_arg_number] - 1 %}\r\n              Anyolite::RbCast.return_value({{rb}}, {{\"block_arg_#{i}\".id}}),\r\n            {% end %}\r\n          ]\r\n          %yield_value = Anyolite::RbCore.rb_yield_argv({{rb}}, {{block_ptr}}.value, {{options[:block_arg_number]}}, %block_arg_array)\r\n          Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %yield_value, {{options[:block_return_type]}})\r\n        end\r\n      {% end %}\r\n\r\n      {% if options[:return_nil] %}\r\n        Anyolite::RbCast.return_nil\r\n      {% else %}\r\n        Anyolite::RbCast.return_value({{rb}}, %return_value)\r\n      {% end %}\r\n    end\r\n\r\n    macro call_and_return_instance_method(rb, proc, converted_obj, converted_args, operator = \"\", options = {} of Symbol => NoReturn, block_ptr = nil)\r\n      {% if !options[:block_arg_number] %}\r\n        {% proc_arg_string = \"\" %}\r\n      {% elsif options[:block_arg_number] == 0 %}\r\n        {% proc_arg_string = \"do\" %}\r\n      {% else %}\r\n        {% proc_arg_string = \"do |\" + (0..options[:block_arg_number] - 1).map { |x| \"block_arg_#{x}\" }.join(\", \") + \"|\" %}\r\n      {% end %}\r\n      \r\n      if {{converted_obj}}.is_a?(Anyolite::StructWrapper)\r\n        %working_content = {{converted_obj}}.content\r\n\r\n        {% if proc.stringify == \"Anyolite::Empty\" %}\r\n          %return_value = %working_content.{{operator.id}}(*{{converted_args}}) {{proc_arg_string.id}}\r\n        {% else %}\r\n          %return_value = %working_content.{{proc}}{{operator.id}}(*{{converted_args}}) {{proc_arg_string.id}}\r\n        {% end %}\r\n\r\n        {% if options[:block_arg_number] == 0 %}\r\n            %yield_value = Anyolite::RbCore.rb_yield({{rb}}, {{block_ptr}}.value, Anyolite::RbCast.return_nil)\r\n            Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %yield_value, {{options[:block_return_type]}})\r\n          end\r\n        {% elsif options[:block_arg_number] %}\r\n            %block_arg_array = [\r\n              {% for i in 0..options[:block_arg_number] - 1 %}\r\n                Anyolite::RbCast.return_value({{rb}}, {{\"block_arg_#{i}\".id}}),\r\n              {% end %}\r\n            ]\r\n            %yield_value = Anyolite::RbCore.rb_yield_argv({{rb}}, {{block_ptr}}.value, {{options[:block_arg_number]}}, %block_arg_array)\r\n            Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %yield_value, {{options[:block_return_type]}})\r\n          end\r\n        {% end %}\r\n\r\n        {{converted_obj}}.content = %working_content\r\n      else\r\n        {% if proc.stringify == \"Anyolite::Empty\" %}\r\n          %return_value = {{converted_obj}}.{{operator.id}}(*{{converted_args}}) {{proc_arg_string.id}}\r\n        {% else %}\r\n          %return_value = {{converted_obj}}.{{proc}}{{operator.id}}(*{{converted_args}}) {{proc_arg_string.id}}\r\n        {% end %}\r\n\r\n        {% if options[:block_arg_number] == 0 %}\r\n            %yield_value = Anyolite::RbCore.rb_yield({{rb}}, {{block_ptr}}.value, Anyolite::RbCast.return_nil)\r\n            Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %yield_value, {{options[:block_return_type]}})\r\n          end\r\n        {% elsif options[:block_arg_number] %}\r\n            %block_arg_array = [\r\n              {% for i in 0..options[:block_arg_number] - 1 %}\r\n                Anyolite::RbCast.return_value({{rb}}, {{\"block_arg_#{i}\".id}}),\r\n              {% end %}\r\n            ]\r\n            %yield_value = Anyolite::RbCore.rb_yield_argv({{rb}}, {{block_ptr}}.value, {{options[:block_arg_number]}}, %block_arg_array)\r\n            Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %yield_value, {{options[:block_return_type]}})\r\n          end\r\n        {% end %}\r\n      end\r\n\r\n      {% if options[:return_nil] %}\r\n        Anyolite::RbCast.return_nil\r\n      {% else %}\r\n        Anyolite::RbCast.return_value({{rb}}, %return_value)\r\n      {% end %}\r\n    end\r\n\r\n    macro call_and_return_keyword_instance_method(rb, proc, converted_obj, converted_regular_args, keyword_args, kw_args, operator = \"\", options = {} of Symbol => NoReturn, block_ptr = nil)\r\n      {% if !options[:block_arg_number] %}\r\n        {% proc_arg_string = \"\" %}\r\n      {% elsif options[:block_arg_number] == 0 %}\r\n        {% proc_arg_string = \"do\" %}\r\n      {% else %}\r\n        {% proc_arg_string = \"do |\" + (0..options[:block_arg_number] - 1).map { |x| \"block_arg_#{x}\" }.join(\", \") + \"|\" %}\r\n      {% end %}\r\n\r\n      if {{converted_obj}}.is_a?(Anyolite::StructWrapper)\r\n        %working_content = {{converted_obj}}.content\r\n\r\n        {% if proc.stringify == \"Anyolite::Empty\" %}\r\n          %return_value = %working_content.{{operator.id}}(\r\n        {% else %}\r\n          %return_value = %working_content.{{proc}}{{operator.id}}(\r\n        {% end %}\r\n          {% if options[:empty_regular] %}\r\n            {% c = 0 %}\r\n            {% for keyword in keyword_args %}\r\n              {{keyword.var.id}}: Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{kw_args}}.values[{{c}}], {{keyword}}, options: {{options}}, debug_information: {{proc.stringify + \" - \" + keyword_args.stringify}}),\r\n              {% c += 1 %}\r\n            {% end %}\r\n          {% else %}\r\n            *{{converted_regular_args}},\r\n            {% c = 0 %}\r\n            {% for keyword in keyword_args %}\r\n              {{keyword.var.id}}: Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{kw_args}}.values[{{c}}], {{keyword}}, options: {{options}}, debug_information: {{proc.stringify + \" - \" + keyword_args.stringify}}),\r\n              {% c += 1 %}\r\n            {% end %}\r\n          {% end %}\r\n        ) {{proc_arg_string.id}}\r\n\r\n        {% if options[:block_arg_number] == 0 %}\r\n            %yield_value = Anyolite::RbCore.rb_yield({{rb}}, {{block_ptr}}.value, Anyolite::RbCast.return_nil)\r\n            Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %yield_value, {{options[:block_return_type]}})\r\n          end\r\n        {% elsif options[:block_arg_number] %}\r\n            %block_arg_array = [\r\n              {% for i in 0..options[:block_arg_number] - 1 %}\r\n                Anyolite::RbCast.return_value({{rb}}, {{\"block_arg_#{i}\".id}}),\r\n              {% end %}\r\n            ]\r\n            %yield_value = Anyolite::RbCore.rb_yield_argv({{rb}}, {{block_ptr}}.value, {{options[:block_arg_number]}}, %block_arg_array)\r\n            Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %yield_value, {{options[:block_return_type]}})\r\n          end\r\n        {% end %}\r\n\r\n        {{converted_obj}}.content = %working_content\r\n      else\r\n\r\n        {% if proc.stringify == \"Anyolite::Empty\" %}\r\n          %return_value = {{converted_obj}}.{{operator.id}}(\r\n        {% else %}\r\n          %return_value = {{converted_obj}}.{{proc}}{{operator.id}}(\r\n        {% end %}\r\n          {% if options[:empty_regular] %}\r\n            {% c = 0 %}\r\n            {% for keyword in keyword_args %}\r\n              {{keyword.var.id}}: Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{kw_args}}.values[{{c}}], {{keyword}}, options: {{options}}, debug_information: {{proc.stringify + \" - \" + keyword_args.stringify}}),\r\n              {% c += 1 %}\r\n            {% end %}\r\n          {% else %}\r\n            *{{converted_regular_args}},\r\n            {% c = 0 %}\r\n            {% for keyword in keyword_args %}\r\n              {{keyword.var.id}}: Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, {{kw_args}}.values[{{c}}], {{keyword}}, options: {{options}}, debug_information: {{proc.stringify + \" - \" + keyword_args.stringify}}),\r\n              {% c += 1 %}\r\n            {% end %}\r\n          {% end %}\r\n        ) {{proc_arg_string.id}}\r\n\r\n        {% if options[:block_arg_number] == 0 %}\r\n            %yield_value = Anyolite::RbCore.rb_yield({{rb}}, {{block_ptr}}.value, Anyolite::RbCast.return_nil)\r\n            Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %yield_value, {{options[:block_return_type]}})\r\n          end\r\n        {% elsif options[:block_arg_number] %}\r\n            %block_arg_array = [\r\n              {% for i in 0..options[:block_arg_number] - 1 %}\r\n                Anyolite::RbCast.return_value({{rb}}, {{\"block_arg_#{i}\".id}}),\r\n              {% end %}\r\n            ]\r\n            %yield_value = Anyolite::RbCore.rb_yield_argv({{rb}}, {{block_ptr}}.value, {{options[:block_arg_number]}}, %block_arg_array)\r\n            Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %yield_value, {{options[:block_return_type]}})\r\n          end\r\n        {% end %}\r\n      end\r\n\r\n      {% if options[:return_nil] %}\r\n        Anyolite::RbCast.return_nil\r\n      {% else %}\r\n        Anyolite::RbCast.return_value({{rb}}, %return_value)\r\n      {% end %}\r\n    end\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/macros/FunctionGenerators.cr",
    "content": "module Anyolite\n  module Macro\n    macro add_default_constructor(rb_interpreter, crystal_class, verbose)\n      {% puts \"> Adding constructor for #{crystal_class}\\n\\n\" if verbose %}\n      Anyolite.wrap_constructor({{rb_interpreter}}, {{crystal_class}})\n    end\n\n    macro add_enum_constructor(rb_interpreter, crystal_class, verbose)\n      {% puts \"> Adding enum constructor for #{crystal_class}\\n\\n\" if verbose %}\n      {% type_hash = {:u8 => UInt8, :u16 => UInt16, :u32 => UInt32, :u64 => UInt64, :i8 => Int8, :i16 => Int16, :i32 => Int32, :i64 => Int64} %}\n      {% enum_type = type_hash[parse_type(\"#{crystal_class}::#{crystal_class.resolve.constants.first.id}\").resolve.kind] %}\n      Anyolite.wrap_constructor({{rb_interpreter}}, {{crystal_class}}, [{{enum_type}}])\n    end\n\n    macro add_enum_inspect(rb_interpreter, crystal_class, verbose)\n      {% puts \"> Adding enum inspect method for #{crystal_class}\\n\\n\" if verbose %}\n      Anyolite.wrap_instance_method({{rb_interpreter}}, {{crystal_class}}, \"inspect\", inspect)\n    end\n\n    macro add_enum_to_s(rb_interpreter, crystal_class, verbose)\n      {% puts \"> Adding enum to_s method for #{crystal_class}\\n\\n\" if verbose %}\n      Anyolite.wrap_instance_method({{rb_interpreter}}, {{crystal_class}}, \"to_s\", to_s)\n    end\n\n    macro add_equality_method(rb_interpreter, crystal_class, context, verbose)\n      {% puts \"> Adding equality method for #{crystal_class}\\n\\n\" if verbose %}\n      {% options = {:context => context} %}\n      Anyolite::Macro.wrap_equality_function({{rb_interpreter}}, {{crystal_class}}, \"==\", Anyolite::Empty, operator: \"==\", options: {{options}})\n    end\n\n    macro add_copy_constructor(rb_interpreter, crystal_class, context, verbose)\n      {% puts \"> Adding copy constructor for #{crystal_class}\\n\\n\" if verbose %}\n      {% options = {:context => context} %}\n\n      %copy_proc = Anyolite::Macro.new_rb_func do\n        %converted_args = Anyolite::Macro.get_converted_args(_rb, [other : {{crystal_class}}], options: {{options}})\n        %new_obj = %converted_args[0].dup\n        Anyolite::Macro.allocate_constructed_object(_rb, {{crystal_class}}, _obj, %new_obj)\n        _obj\n      end\n\n      {{rb_interpreter}}.define_method(\"initialize_copy\", Anyolite::RbClassCache.get({{crystal_class}}), %copy_proc)\n    end\n  end\nend\n"
  },
  {
    "path": "src/macros/ObjectAllocations.cr",
    "content": "module Anyolite\n  module Macro\n    macro allocate_constructed_object(rb, crystal_class, obj, new_obj)\n      # Call initializer method if available\r\n      if {{new_obj}}.responds_to?(:rb_initialize)\r\n        {{new_obj}}.rb_initialize({{rb}})\r\n      end\r\n\r\n      # Allocate memory so we do not lose this object\r\n      if {{crystal_class}} <= Struct || {{crystal_class}} <= Enum\r\n        %struct_wrapper = Anyolite::StructWrapper({{crystal_class}}).new({{new_obj}})\r\n        %new_obj_ptr = Pointer(Anyolite::StructWrapper({{crystal_class}})).malloc(size: 1, value: %struct_wrapper)\r\n        Anyolite::RbRefTable.add(Anyolite::RbRefTable.get_object_id(%new_obj_ptr.value), %new_obj_ptr.as(Void*), {{obj}})\r\n\r\n        puts \"> S: {{crystal_class}}: #{%new_obj_ptr.value.inspect}\" if Anyolite::RbRefTable.option_active?(:logging)\r\n\r\n        %destructor = Anyolite::RbTypeCache.destructor_method({{crystal_class}})\r\n        Anyolite::RbCore.set_data_ptr_and_type({{obj}}, %new_obj_ptr, Anyolite::RbTypeCache.register({{crystal_class}}, %destructor))\r\n      else\r\n        %new_obj_ptr = Pointer({{crystal_class}}).malloc(size: 1, value: {{new_obj}})\r\n        Anyolite::RbRefTable.add(Anyolite::RbRefTable.get_object_id(%new_obj_ptr.value), %new_obj_ptr.as(Void*), {{obj}})\r\n\r\n        puts \"> C: {{crystal_class}}: #{%new_obj_ptr.value.inspect}\" if Anyolite::RbRefTable.option_active?(:logging)\r\n\r\n        %destructor = Anyolite::RbTypeCache.destructor_method({{crystal_class}})\r\n        Anyolite::RbCore.set_data_ptr_and_type({{obj}}, %new_obj_ptr, Anyolite::RbTypeCache.register({{crystal_class}}, %destructor))\r\n      end\r\n    end\n  end\nend\n"
  },
  {
    "path": "src/macros/RubyConversions.cr",
    "content": "module Anyolite\r\n  module Macro\r\n    macro convert_from_ruby_object(rb, obj, crystal_type)\r\n      if !Anyolite::RbCast.check_for_data({{obj}})\r\n        %obj_class = Anyolite::RbCore.get_class_of_obj({{rb}}, {{obj}})\r\n\r\n        %rb_class_name = String.new(Anyolite::RbCore.rb_class_name({{rb}}, %obj_class))\r\n        Anyolite.raise_argument_error \"Could not convert data type #{%rb_class_name} into object class #{{{crystal_type.stringify}}}.\"\r\n      end\r\n\r\n      if !Anyolite::RbCore.get_data_ptr({{obj}})\r\n        %obj_class = Anyolite::RbCore.get_class_of_obj({{rb}}, {{obj}})\r\n\r\n        %rb_class_name = String.new(Anyolite::RbCore.rb_class_name({{rb}}, %obj_class))\r\n        Anyolite.raise_runtime_error \"Object of class #{%rb_class_name} has content incompatible to Crystal class #{{{crystal_type.stringify}}}.\"\r\n      end\r\n\r\n      if !Anyolite::RbCast.check_custom_type({{rb}}, {{obj}}, {{crystal_type}})\r\n        %obj_class = Anyolite::RbCore.get_class_of_obj({{rb}}, {{obj}})\r\n\r\n        %rb_class_name = String.new(Anyolite::RbCore.rb_class_name({{rb}}, %obj_class))\r\n        Anyolite.raise_argument_error \"Invalid data type #{%rb_class_name} for object class #{{{crystal_type.stringify}}}.\"\r\n      end\r\n\r\n      %ptr = Anyolite::RbCore.get_data_ptr({{obj}})\r\n      %ptr.as({{crystal_type}}*)\r\n    end\r\n\r\n    macro convert_from_ruby_struct(rb, obj, crystal_type)\r\n      if !Anyolite::RbCast.check_for_data({{obj}})\r\n        %obj_class = Anyolite::RbCore.get_class_of_obj({{rb}}, {{obj}})\r\n\r\n        %rb_class_name = String.new(Anyolite::RbCore.rb_class_name({{rb}}, %obj_class))\r\n        Anyolite.raise_argument_error \"Could not convert data type #{%rb_class_name} into struct class #{{{crystal_type.stringify}}}.\"\r\n      end\r\n\r\n      if !Anyolite::RbCore.get_data_ptr({{obj}})\r\n        %obj_class = Anyolite::RbCore.get_class_of_obj({{rb}}, {{obj}})\r\n\r\n        %rb_class_name = String.new(Anyolite::RbCore.rb_class_name({{rb}}, %obj_class))\r\n        Anyolite.raise_runtime_error \"Object of class #{%rb_class_name} has content incompatible to Crystal struct #{{{crystal_type.stringify}}}.\"\r\n      end\r\n\r\n      if !Anyolite::RbCast.check_custom_type({{rb}}, {{obj}}, {{crystal_type}})\r\n        %obj_class = Anyolite::RbCore.get_class_of_obj({{rb}}, {{obj}})\r\n\r\n        %rb_class_name = String.new(Anyolite::RbCore.rb_class_name({{rb}}, %obj_class))\r\n        Anyolite.raise_argument_error \"Invalid data type #{%rb_class_name} for struct class #{{{crystal_type.stringify}}}\"\r\n      end\r\n      \r\n      %ptr = Anyolite::RbCore.get_data_ptr({{obj}})\r\n      %ptr.as(Anyolite::StructWrapper({{crystal_type}})*)\r\n    end\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/macros/RubyTypes.cr",
    "content": "module Anyolite\r\n  module Macro\r\n    macro type_in_ruby(type, options = {} of Symbol => NoReturn)\r\n      {% if type.is_a?(TypeDeclaration) %}\r\n        {% if type.type.is_a?(Union) %}\r\n          Anyolite::RbCore::RbValue\r\n        {% else %}\r\n          Anyolite::Macro.type_in_ruby({{type.type}})\r\n        {% end %}\r\n      {% elsif options[:context] %}\r\n        Anyolite::Macro.resolve_type_in_ruby({{options[:context]}}::{{type.stringify.starts_with?(\"::\") ? type.stringify[2..-1].id : type}}, {{type}}, options: {{options}})\r\n      {% else %}\r\n        Anyolite::Macro.resolve_type_in_ruby({{type}}, {{type}})\r\n      {% end %}\r\n    end\r\n\r\n    macro resolve_type_in_ruby(type, raw_type, options = {} of Symbol => NoReturn)\r\n      {% if type.resolve? %}\r\n        {% if ANYOLITE_INTERNAL_FLAG_USE_GENERAL_OBJECT_FORMAT_CHARS %}\r\n          Anyolite::RbCore::RbValue\r\n        {% else %}\r\n          {% if type.resolve <= Bool %}\r\n            Anyolite::RbCore::RbBool\r\n          {% elsif type.resolve <= Int || type.resolve <= Pointer %}\r\n            Anyolite::RbCore::RbInt\r\n          {% elsif type.resolve <= Float || type.resolve == Number %}\r\n            Anyolite::RbCore::RbFloat\r\n          {% elsif type.resolve <= String %}\r\n            # Should actually never occur due to special handling before this function\r\n            Pointer(LibC::Char)\r\n          {% elsif type.resolve <= Anyolite::RbRef %}\r\n            Anyolite::RbCore::RbValue\r\n          {% elsif type.resolve <= Regex %}\r\n            Anyolite::RbCore::RbValue\r\n          {% elsif type.resolve <= Array %}\r\n            Anyolite::RbCore::RbValue\r\n          {% else %}\r\n            Anyolite::RbCore::RbValue\r\n          {% end %}\r\n        {% end %}\r\n      {% elsif options[:context] %}\r\n        {% if options[:context].names[0..-2].size > 0 %}\r\n          {% new_context = options[:context].names[0..-2].join(\"::\").gsub(/(\\:\\:)+/, \"::\").id %}\r\n          {% options[:context] = new_context %}\r\n          Anyolite::Macro.resolve_type_in_ruby({{new_context}}::{{raw_type.stringify.starts_with?(\"::\") ? raw_type.stringify[2..-1].id : raw_type}}, {{raw_type}}, options: {{options}})\r\n        {% else %}\r\n          Anyolite::Macro.resolve_type_in_ruby({{raw_type}}, {{raw_type}})\r\n        {% end %}\r\n      {% else %}\r\n        Anyolite::RbCore::RbValue\r\n      {% end %}\r\n    end\r\n\r\n    macro pointer_type(type, options = {} of Symbol => NoReturn)\r\n      {% if type.is_a?(TypeDeclaration) %}\r\n        {% if type.type.is_a?(Union) %}\r\n          Pointer(Anyolite::RbCore::RbValue)\r\n        {% else %}\r\n          Anyolite::Macro.pointer_type({{type.type}}, options: {{options}})\r\n        {% end %}\r\n      {% elsif options[:context] %}\r\n        Anyolite::Macro.resolve_pointer_type({{options[:context]}}::{{type.stringify.starts_with?(\"::\") ? type.stringify[2..-1].id : type}}, {{type}}, options: {{options}})\r\n      {% else %}\r\n        Anyolite::Macro.resolve_pointer_type({{type}}, {{type}})\r\n      {% end %}\r\n    end\r\n\r\n    macro resolve_pointer_type(type, raw_type, options = {} of Symbol => NoReturn)\r\n      {% if type.resolve? %}\r\n        {% if ANYOLITE_INTERNAL_FLAG_USE_GENERAL_OBJECT_FORMAT_CHARS %}\r\n          Pointer(Anyolite::RbCore::RbValue)\r\n        {% else %}\r\n          {% if type.resolve <= Bool %}\r\n            Pointer(Anyolite::RbCore::RbBool)\r\n          {% elsif type.resolve <= Int %}\r\n            Pointer(Anyolite::RbCore::RbInt)\r\n          {% elsif type.resolve <= Float || type.resolve == Number %}\r\n            Pointer(Anyolite::RbCore::RbFloat)\r\n          {% elsif type.resolve <= String %}\r\n            Pointer(LibC::Char*)\r\n          {% elsif type.resolve <= Anyolite::RbRef %}\r\n            Pointer(Anyolite::RbCore::RbValue)\r\n          {% elsif type.resolve <= Array %}\r\n            Pointer(Anyolite::RbCore::RbValue)\r\n          {% else %}\r\n            Pointer(Anyolite::RbCore::RbValue)\r\n          {% end %}\r\n        {% end %}\r\n      {% elsif options[:context] %}\r\n        {% if options[:context].names[0..-2].size > 0 %}\r\n          {% new_context = options[:context].names[0..-2].join(\"::\").gsub(/(\\:\\:)+/, \"::\").id %}\r\n          {% options[:context] = new_context %}\r\n          Anyolite::Macro.resolve_pointer_type({{new_context}}::{{raw_type.stringify.starts_with?(\"::\") ? raw_type.stringify[2..-1].id : raw_type}}, {{raw_type}}, options: {{options}})\r\n        {% else %}\r\n          Anyolite::Macro.resolve_pointer_type({{raw_type}}, {{raw_type}})\r\n        {% end %}\r\n      {% else %}\r\n        Pointer(Anyolite::RbCore::RbValue)\r\n      {% end %}\r\n    end\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/macros/UnionCasts.cr",
    "content": "module Anyolite\r\n  module Macro\r\n    macro cast_to_union_value(rb, value, types, options = {} of Symbol => NoReturn, debug_information = nil)\r\n      _final_value = :invalid\r\n\r\n      {% for type in types %}\r\n        {% if type.resolve? %}\r\n          Anyolite::Macro.check_and_cast_union_type({{rb}}, {{value}}, {{type}}, {{type}}, options: {{options}})\r\n        {% elsif options[:context] %}\r\n          Anyolite::Macro.check_and_cast_union_type({{rb}}, {{value}}, {{options[:context]}}::{{type.stringify.starts_with?(\"::\") ? type.stringify[2..-1].id : type}}, {{type}}, options: {{options}})\r\n        {% else %}\r\n          {% raise \"Could not resolve type #{type}, which is a #{type.class_name}, in context #{options[:context]} (#{debug_information.id})\" %}\r\n        {% end %}\r\n      {% end %}\r\n      \r\n      if _final_value.is_a?(Symbol)\r\n        # TODO: Better value description\r\n        Anyolite::RbCast.casting_error({{rb}}, {{value}}, \"{{types}}\", nil)\r\n        #Anyolite.raise_argument_error(\"Could not determine any value for #{{{value}}} with types {{types}} in context {{options[:context]}}\")\r\n        raise(\"Should not be reached\")\r\n      else\r\n        _final_value\r\n      end\r\n    end\r\n\r\n    macro check_and_cast_union_type(rb, value, type, raw_type, options = {} of Symbol => NoReturn, debug_information = nil)\r\n      {% if type.resolve? %}\r\n        Anyolite::Macro.check_and_cast_resolved_union_type({{rb}}, {{value}}, {{type}}, {{type}})\r\n      {% elsif options[:context] %}\r\n        {% if options[:context].names[0..-2].size > 0 %}\r\n          {% new_context = options[:context].names[0..-2].join(\"::\").gsub(/(\\:\\:)+/, \"::\").id %}\r\n          {% options[:context] = new_context %}\r\n          Anyolite::Macro.check_and_cast_union_type({{rb}}, {{value}}, {{options[:context]}}::{{raw_type.stringify.starts_with?(\"::\") ? raw_type[2..-1] : raw_type}}, {{raw_type}}, options: {{options}})\r\n        {% else %}\r\n          Anyolite::Macro.check_and_cast_union_type({{rb}}, {{value}}, {{raw_type}}, {{raw_type}})\r\n        {% end %}\r\n      {% else %}\r\n        {% raise \"Could not resolve type #{type}, which is a #{type.class_name} (#{debug_information.id})\" %}\r\n      {% end %}\r\n    end\r\n\r\n    # TODO: Some double checks could be omitted\r\n\r\n    macro check_and_cast_resolved_union_type(rb, value, type, raw_type, options = {} of Symbol => NoReturn, debug_information = nil)\r\n      {% if type.resolve <= Nil %}\r\n        if Anyolite::RbCast.check_for_nil({{value}})\r\n          _final_value = Anyolite::RbCast.cast_to_nil({{rb}}, {{value}})\r\n        end\r\n      {% elsif type.resolve <= Bool %}\r\n        if Anyolite::RbCast.check_for_bool({{value}})\r\n          _final_value = Anyolite::RbCast.cast_to_bool({{rb}}, {{value}})\r\n        end\r\n      {% elsif type.resolve == Number %}\r\n        if Anyolite::RbCast.check_for_float({{value}})\r\n          begin\r\n            _final_value = Float64.new(Anyolite::RbCast.cast_to_float({{rb}}, {{value}}))\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{Anyolite::RbCast.cast_to_float({{rb}}, {{value}})} to {{type}}.\")\r\n            Float64.new(0.0)\r\n          end\r\n        end\r\n      {% elsif type.resolve == Int %}\r\n        if Anyolite::RbCast.check_for_fixnum({{value}})\r\n          begin\r\n            _final_value = Int64.new(Anyolite::RbCast.cast_to_int({{rb}}, {{value}}))\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{Anyolite::RbCast.cast_to_int({{rb}}, {{value}})} to {{type}}.\")\r\n            Int64.new(0)\r\n          end\r\n        end\r\n      {% elsif type.resolve <= Int %}\r\n        if Anyolite::RbCast.check_for_fixnum({{value}})\r\n          begin\r\n            _final_value = {{type}}.new(Anyolite::RbCast.cast_to_int({{rb}}, {{value}}))\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{Anyolite::RbCast.cast_to_int({{rb}}, {{value}})} to {{type}}.\")\r\n            {{type}}.new(0)\r\n          end\r\n        end\r\n      {% elsif type.resolve == Float %}\r\n        if Anyolite::RbCast.check_for_float({{value}}) || Anyolite::RbCast.check_for_fixnum({{value}})\r\n          begin\r\n            _final_value = Float64.new(Anyolite::RbCast.cast_to_float({{rb}}, {{value}}))\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{Anyolite::RbCast.cast_to_int({{rb}}, {{value}})} to {{type}}.\")\r\n            Float64.new(0)\r\n          end\r\n        end\r\n      {% elsif type.resolve <= Float %}\r\n        if Anyolite::RbCast.check_for_float({{value}}) || Anyolite::RbCast.check_for_fixnum({{value}})\r\n          begin\r\n            _final_value = {{type}}.new(Anyolite::RbCast.cast_to_float({{rb}}, {{value}}))\r\n          rescue OverflowError\r\n            Anyolite.raise_range_error(\"Overflow while casting #{Anyolite::RbCast.cast_to_int({{rb}}, {{value}})} to {{type}}.\")\r\n            {{type}}.new(0)\r\n          end\r\n        end\r\n      {% elsif type.resolve <= Char %}\r\n        if Anyolite::RbCast.check_for_string({{value}})\r\n          _final_value = Anyolite::RbCast.cast_to_char({{rb}}, {{value}})\r\n        end\r\n      {% elsif type.resolve <= String %}\r\n        if Anyolite::RbCast.check_for_string({{value}}) || Anyolite::RbCast.check_for_symbol({{value}})\r\n          _final_value = Anyolite::RbCast.cast_to_string({{rb}}, {{value}})\r\n        end\r\n      {% elsif type.resolve <= Anyolite::RbRef %}\r\n        _final_value = {{type}}.new({{value}})\r\n      {% elsif type.resolve <= Array %}\r\n        if Anyolite::RbCast.check_for_array({{value}})\r\n          %array_size = Anyolite::RbCore.array_length({{value}})\r\n          %converted_array = {{type}}.new(size: %array_size) do |%index|\r\n            Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, Anyolite::RbCore.rb_ary_entry({{value}}, %index), {{type.type_vars[0]}})\r\n          end\r\n          _final_value = %converted_array\r\n        end\r\n      {% elsif type.resolve <= Regex %}\r\n        Anyolite::Macro.convert_regex_from_ruby_to_crystal({{rb}}, {{value}}, {{type}})\r\n      {% elsif type.resolve <= Hash %}\r\n        if Anyolite::RbCast.check_for_hash({{value}})\r\n        %hash_size = Anyolite::RbCore.rb_hash_size({{rb}}, {{value}})\r\n\r\n          %all_rb_hash_keys = Anyolite::RbCore.rb_hash_keys({{rb}}, {{value}})\r\n          %all_converted_hash_keys = Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %all_rb_hash_keys, Array({{type.type_vars[0]}}), options: {{options}})\r\n\r\n          %converted_hash = {{type}}.new(initial_capacity: %hash_size)\r\n          %all_converted_hash_keys.each_with_index do |%key, %index|\r\n            %rb_key = Anyolite::RbCore.rb_ary_entry(%all_rb_hash_keys, %index)\r\n            %rb_value = Anyolite::RbCore.rb_hash_get({{rb}}, {{value}}, %rb_key)\r\n            %converted_hash[%key] = Anyolite::Macro.convert_from_ruby_to_crystal({{rb}}, %rb_value, {{type.type_vars[1]}}, options: {{options}})\r\n          end\r\n\r\n          _final_value = %converted_hash\r\n        end\r\n      {% elsif type.resolve <= Pointer %}\r\n        if Anyolite::RbCast.check_for_data({{value}}) && Anyolite::RbCast.check_custom_type({{rb}}, {{value}}, Anyolite::HelperClasses::AnyolitePointer)\r\n          %helper_ptr = Anyolite::Macro.convert_from_ruby_object({{rb}}, {{value}}, Anyolite::HelperClasses::AnyolitePointer).value\r\n          _final_value = Box({{type}}).unbox(%helper_ptr.retrieve_ptr)\r\n        end\r\n      {% elsif type.resolve <= Struct || type.resolve <= Enum %}\r\n        if Anyolite::RbCast.check_for_data({{value}}) && Anyolite::RbCast.check_custom_type({{rb}}, {{value}}, {{type}})\r\n          _final_value = Anyolite::Macro.convert_from_ruby_struct({{rb}}, {{value}}, {{type}}).value.content\r\n        end\r\n      {% elsif type.resolve? %}\r\n        if Anyolite::RbCast.check_for_data({{value}}) && Anyolite::RbCast.check_custom_type({{rb}}, {{value}}, {{type}})\r\n          _final_value = Anyolite::Macro.convert_from_ruby_object({{rb}}, {{value}}, {{type}}).value\r\n        end\r\n      {% else %}\r\n        {% raise \"Could not resolve type #{type}, which is a #{type.class_name} (#{debug_information.id})\" %}\r\n      {% end %}\r\n    end\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/macros/WrapAll.cr",
    "content": "module Anyolite\r\n  module Macro\r\n    macro wrap_all_instance_methods(rb_interpreter, crystal_class, exclusions, verbose, context = nil,\r\n                                    use_enum_methods = false, wrap_equality_method = false, other_source = nil, later_ancestors = nil)\r\n      {% has_specialized_method = {} of String => Bool %}\r\n\r\n      {% method_source = other_source ? other_source : crystal_class %}\r\n\r\n      {% default_optional_args_to_keyword_args = parse_type(\"ANYOLITE_DEFAULT_OPTIONAL_ARGS_TO_KEYWORD_ARGS\").resolve? %}\r\n\r\n      {% if !crystal_class.resolve.annotations(Anyolite::DefaultOptionalArgsToKeywordArgs).empty? %}\r\n        {% default_optional_args_to_keyword_args = true %}\r\n      {% else %}\r\n        {% for class_ancestor in crystal_class.resolve.ancestors %}\r\n          {% if !class_ancestor.resolve.annotations(Anyolite::DefaultOptionalArgsToKeywordArgs).empty? %}\r\n            {% default_optional_args_to_keyword_args = true %}\r\n          {% end %}\r\n        {% end %}\r\n      {% end %}\r\n\r\n      {% if !method_source.resolve? %}\r\n        {% puts \"> Skipping #{method_source} due to private visibility.\" if verbose %}\r\n      {% else %}\r\n        {% for method in method_source.resolve.methods %}\r\n          {% all_annotations_specialize_im = crystal_class.resolve.annotations(Anyolite::SpecializeInstanceMethod) + method_source.resolve.annotations(Anyolite::SpecializeInstanceMethod) %}\r\n          {% annotation_specialize_im = all_annotations_specialize_im.find { |element| element[0].stringify == method.name.stringify || element[0] == method.name.stringify } %}\r\n\r\n          {% if method.annotation(Anyolite::Specialize) %}\r\n            {% has_specialized_method[method.name.stringify] = true %}\r\n          {% end %}\r\n\r\n          {% if annotation_specialize_im %}\r\n            {% has_specialized_method[annotation_specialize_im[0].id.stringify] = true %}\r\n          {% end %}\r\n        {% end %}\r\n\r\n        {% how_many_times_wrapped = {} of String => UInt32 %}\r\n\r\n        {% for method, index in method_source.resolve.methods %}\r\n          {% all_annotations_exclude_im = crystal_class.resolve.annotations(Anyolite::ExcludeInstanceMethod) + method_source.resolve.annotations(Anyolite::ExcludeInstanceMethod) + crystal_class.resolve.ancestors.map { |ancestor| ancestor.resolve.annotations(Anyolite::ExcludeInstanceMethod) } %}\r\n          {% annotation_exclude_im = all_annotations_exclude_im.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n          {% all_annotations_include_im = crystal_class.resolve.annotations(Anyolite::IncludeInstanceMethod) + method_source.resolve.annotations(Anyolite::IncludeInstanceMethod) %}\r\n          {% annotation_include_im = all_annotations_include_im.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n          {% all_annotations_specialize_im = crystal_class.resolve.annotations(Anyolite::SpecializeInstanceMethod) + method_source.resolve.annotations(Anyolite::SpecializeInstanceMethod) %}\r\n          {% annotation_specialize_im = all_annotations_specialize_im.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n          {% all_annotations_rename_im = crystal_class.resolve.annotations(Anyolite::RenameInstanceMethod) + method_source.resolve.annotations(Anyolite::RenameInstanceMethod) %}\r\n          {% annotation_rename_im = all_annotations_rename_im.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n          {% all_annotations_without_keywords_im = crystal_class.resolve.annotations(Anyolite::WrapWithoutKeywordsInstanceMethod) + method_source.resolve.annotations(Anyolite::WrapWithoutKeywordsInstanceMethod) %}\r\n          {% annotation_without_keyword_im = all_annotations_without_keywords_im.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n          {% all_annotations_return_nil_im = crystal_class.resolve.annotations(Anyolite::ReturnNilInstanceMethod) + method_source.resolve.annotations(Anyolite::ReturnNilInstanceMethod) %}\r\n          {% annotation_return_nil_im = all_annotations_return_nil_im.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n          {% all_annotations_add_block_arg_im = crystal_class.resolve.annotations(Anyolite::AddBlockArgInstanceMethod) + method_source.resolve.annotations(Anyolite::AddBlockArgInstanceMethod) %}\r\n          {% annotation_add_block_arg_im = all_annotations_add_block_arg_im.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n          {% all_annotations_store_block_arg_im = crystal_class.resolve.annotations(Anyolite::StoreBlockArgInstanceMethod) + method_source.resolve.annotations(Anyolite::StoreBlockArgInstanceMethod) %}\r\n          {% annotation_store_block_arg_im = all_annotations_store_block_arg_im.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n          {% all_annotations_force_keyword_arg_im = crystal_class.resolve.annotations(Anyolite::ForceKeywordArgInstanceMethod) + method_source.resolve.annotations(Anyolite::ForceKeywordArgInstanceMethod) %}\r\n          {% annotation_force_keyword_arg_im = all_annotations_force_keyword_arg_im.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n          {% if crystal_class.resolve.annotation(Anyolite::NoKeywordArgs) || method_source.resolve.annotation(Anyolite::NoKeywordArgs) %}\r\n            {% no_keyword_args = true %}\r\n          {% else %}\r\n            {% no_keyword_args = false %}\r\n          {% end %}\r\n\r\n          {% if method.annotation(Anyolite::Rename) %}\r\n            {% ruby_name = method.annotation(Anyolite::Rename)[0].id %}\r\n          {% elsif annotation_rename_im && method.name.stringify == annotation_rename_im[0].id.stringify %}\r\n            {% ruby_name = annotation_rename_im[1].id %}\r\n          {% else %}\r\n            {% ruby_name = method.name %}\r\n          {% end %}\r\n\r\n          {% if method.annotation(Anyolite::AddBlockArg) %}\r\n            {% block_arg_number = method.annotation(Anyolite::AddBlockArg)[0] %}\r\n            {% block_return_type = method.annotation(Anyolite::AddBlockArg)[1] %}\r\n          {% elsif annotation_add_block_arg_im && method.name.stringify == annotation_add_block_arg_im[0].id.stringify %}\r\n            {% block_arg_number = annotation_add_block_arg_im[1] %}\r\n            {% block_return_type = annotation_add_block_arg_im[2] %}\r\n          {% else %}\r\n            {% block_arg_number = nil %}\r\n            {% block_return_type = nil %}\r\n          {% end %}\r\n\r\n          {% added_keyword_args = nil %}\r\n\r\n          {% if method.annotation(Anyolite::Specialize) && method.annotation(Anyolite::Specialize)[0] %}\r\n            {% added_keyword_args = method.annotation(Anyolite::Specialize)[0] %}\r\n          {% end %}\r\n\r\n          {% if annotation_specialize_im && (method.args.stringify == annotation_specialize_im[1].stringify || (method.args.stringify == \"[]\" && annotation_specialize_im[1] == nil)) %}\r\n            {% added_keyword_args = annotation_specialize_im[2] %}\r\n          {% end %}\r\n\r\n          {% without_keywords = false %}\r\n\r\n          {% if method.annotation(Anyolite::WrapWithoutKeywords) %}\r\n            {% without_keywords = method.annotation(Anyolite::WrapWithoutKeywords)[0] ? method.annotation(Anyolite::WrapWithoutKeywords)[0] : -1 %}\r\n          {% elsif annotation_without_keyword_im %}\r\n            {% without_keywords = annotation_without_keyword_im[1] ? annotation_without_keyword_im[1] : -1 %}\r\n          {% elsif default_optional_args_to_keyword_args %}\r\n            {% without_keywords = -2 %}\r\n          {% end %}\r\n\r\n          {% return_nil = false %}\r\n          {% if method.annotation(Anyolite::ReturnNil) || (annotation_return_nil_im) %}\r\n            {% return_nil = true %}\r\n          {% end %}\r\n\r\n          {% store_block_arg = false %}\r\n          {% if method.annotation(Anyolite::StoreBlockArg) || (annotation_store_block_arg_im) %}\r\n            {% store_block_arg = true %}\r\n          {% end %}\r\n\r\n          {% force_keyword_arg = false %}\r\n          {% if method.annotation(Anyolite::ForceKeywordArg) || (annotation_force_keyword_arg_im) %}\r\n            {% force_keyword_arg = true %}\r\n          {% end %}\r\n\r\n          {% puts \"> Processing instance method #{crystal_class}::#{method.name} to #{ruby_name}\\n--> Args: #{method.args}\" if verbose %}\r\n\r\n          {% if method.accepts_block? %}\r\n            {% puts \"--> Block arg possible for #{crystal_class}::#{method.name}\" if verbose %}\r\n          {% end %}\r\n\r\n          # Ignore private and protected methods (can't be called from outside, they'd need to be wrapped for this to work)\r\n          {% if method.name == \"dup\" || method.name == \"clone\" %}\r\n            {% puts \"--> Excluding #{crystal_class}::#{method.name} (Exclusion due to copy property)\" if verbose %}\r\n          {% elsif crystal_class.resolve.abstract? && method.name == \"initialize\" %}\r\n            {% puts \"--> Excluding #{crystal_class}::#{method.name} (Exclusion due to abstract class)\" if verbose %}\r\n          {% elsif method.visibility != :public && method.name != \"initialize\" %}\r\n            {% puts \"--> Excluding #{crystal_class}::#{method.name} (Exclusion due to visibility)\" if verbose %}\r\n          {% elsif crystal_class != method_source && (later_ancestors ? later_ancestors + [crystal_class] : [crystal_class]).find { |later_ancestor| later_ancestor.resolve? ? later_ancestor.resolve.methods.find { |orig_methods| orig_methods.name == method.name } : [] of Def } %}\r\n            {% puts \"--> Excluding #{crystal_class}::#{method.name} (Exclusion due to finalization)\" if verbose %}\r\n          # Ignore rb hooks, to_unsafe and finalize (unless specialized, but this is not recommended)\r\n          {% elsif (method.name.starts_with?(\"rb_\") || method.name == \"finalize\" || method.name == \"to_unsafe\") && !has_specialized_method[method.name.stringify] %}\r\n            {% puts \"--> Excluding #{crystal_class}::#{method.name} (Exclusion by default)\" if verbose %}\r\n          # Exclude methods if given as arguments\r\n          {% elsif exclusions.includes?(method.name.symbolize) || exclusions.includes?(method.name.stringify) %}\r\n            {% puts \"--> Excluding #{crystal_class}::#{method.name} (Exclusion argument)\" if verbose %}\r\n          # Exclude methods which were annotated to be excluded\r\n          {% elsif method.annotation(Anyolite::Exclude) || (annotation_exclude_im && !annotation_include_im && !method.annotation(Anyolite::Include)) %}\r\n            {% puts \"--> Excluding #{crystal_class}::#{method.name} (Exclusion annotation)\" if verbose %}\r\n          # Exclude methods which are not the specialized methods\r\n          {% elsif has_specialized_method[method.name.stringify] && !(method.annotation(Anyolite::Specialize) || (annotation_specialize_im && (method.args.stringify == annotation_specialize_im[1].stringify || (method.args.stringify == \"[]\" && annotation_specialize_im[1] == nil)))) %}\r\n            {% puts \"--> Excluding #{crystal_class}::#{method.name} #{method.args} (Specialization)\" if verbose %}\r\n          # These methods are a bit tricky and technically require an argument, but usually they are called without one, so we just do it here, too\r\n          {% elsif method.name == \"inspect\" || method.name == \"to_s\" || method.name == \"hash\" %}\r\n            Anyolite::Macro.wrap_method_index({{rb_interpreter}}, {{crystal_class}}, {{index}}, \"{{ruby_name}}\", without_keywords: {{without_keywords || (no_keyword_args && !force_keyword_arg)}}, added_keyword_args: [] of NoReturn, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}}, other_source: {{other_source}})\r\n            {% how_many_times_wrapped[ruby_name.stringify] = how_many_times_wrapped[ruby_name.stringify] ? how_many_times_wrapped[ruby_name.stringify] + 1 : 1 %} \r\n          # Handle operator methods (including setters) by just transferring the original name into the operator\r\n          # TODO: This might still be a source for potential bugs, so this code might need some reworking in the future\r\n          {% elsif method.name[-1..-1] =~ /\\W/ %}\r\n            {% operator = ruby_name %}\r\n\r\n            Anyolite::Macro.wrap_method_index({{rb_interpreter}}, {{crystal_class}}, {{index}}, \"{{ruby_name}}\", operator: \"{{operator}}\", without_keywords: {{force_keyword_arg ? false : -1}}, added_keyword_args: {{added_keyword_args}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}}, other_source: {{other_source}})\r\n            {% how_many_times_wrapped[ruby_name.stringify] = how_many_times_wrapped[ruby_name.stringify] ? how_many_times_wrapped[ruby_name.stringify] + 1 : 1 %}\r\n          # Handle constructors\r\n          {% elsif method.name == \"initialize\" && use_enum_methods == false %}\r\n            Anyolite::Macro.wrap_method_index({{rb_interpreter}}, {{crystal_class}}, {{index}}, \"{{ruby_name}}\", is_constructor: true, without_keywords: {{without_keywords || (no_keyword_args && !force_keyword_arg)}}, added_keyword_args: {{added_keyword_args}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}}, other_source: {{other_source}})\r\n            {% how_many_times_wrapped[ruby_name.stringify] = how_many_times_wrapped[ruby_name.stringify] ? how_many_times_wrapped[ruby_name.stringify] + 1 : 1 %}\r\n          # Handle other instance methods\r\n          {% else %}\r\n            Anyolite::Macro.wrap_method_index({{rb_interpreter}}, {{crystal_class}}, {{index}}, \"{{ruby_name}}\", without_keywords: {{without_keywords || (no_keyword_args && !force_keyword_arg)}}, added_keyword_args: {{added_keyword_args}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}}, other_source: {{other_source}})\r\n            {% how_many_times_wrapped[ruby_name.stringify] = how_many_times_wrapped[ruby_name.stringify] ? how_many_times_wrapped[ruby_name.stringify] + 1 : 1 %}\r\n          {% end %}\r\n\r\n          {% if how_many_times_wrapped[ruby_name.stringify] && how_many_times_wrapped[ruby_name.stringify] > 1 %}\r\n            {% puts \"\\e[31m> WARNING: Method #{crystal_class}::#{ruby_name}\\n--> New arguments: #{method.args}\\n--> Wrapped more than once (#{how_many_times_wrapped[ruby_name.stringify]}).\\e[0m\" %}\r\n          {% end %}\r\n          {% puts \"\" if verbose %}\r\n        {% end %}\r\n        \r\n        {% if method_source == crystal_class && !crystal_class.resolve.abstract? %}\r\n          # Make sure to add a default constructor if none was specified with Crystal\r\n          {% if !how_many_times_wrapped[\"initialize\"] && !use_enum_methods %}\r\n            Anyolite::Macro.add_default_constructor({{rb_interpreter}}, {{crystal_class}}, {{verbose}})\r\n          {% elsif !how_many_times_wrapped[\"initialize\"] && use_enum_methods %}\r\n          Anyolite::Macro.add_enum_constructor({{rb_interpreter}}, {{crystal_class}}, {{verbose}})\r\n          {% end %}\r\n\r\n          {% if !how_many_times_wrapped[\"inspect\"] && use_enum_methods %}\r\n            Anyolite::Macro.add_enum_inspect({{rb_interpreter}}, {{crystal_class}}, {{verbose}})\r\n          {% end %}\r\n\r\n          {% all_annotations_exclude_im = crystal_class.resolve.annotations(Anyolite::ExcludeInstanceMethod) + method_source.resolve.annotations(Anyolite::ExcludeInstanceMethod) %}\r\n          {% if all_annotations_exclude_im.find { |element| element[0].id.stringify == \"dup\" || element[0].id.stringify == \"clone\" } %}\r\n            Anyolite::RbCore.rb_undef_method({{rb_interpreter}}, Anyolite::RbClassCache.get({{crystal_class}}), \"dup\")\r\n            Anyolite::RbCore.rb_undef_method({{rb_interpreter}}, Anyolite::RbClassCache.get({{crystal_class}}), \"clone\")\r\n          {% else %}\r\n            Anyolite::Macro.add_copy_constructor({{rb_interpreter}}, {{crystal_class}}, {{context}}, {{verbose}})\r\n          {% end %}\r\n\r\n          {% if wrap_equality_method && !how_many_times_wrapped[\"==\"] %}\r\n            Anyolite::Macro.add_equality_method({{rb_interpreter}}, {{crystal_class}}, {{context}}, {{verbose}})\r\n          {% end %}\r\n        {% end %}\r\n      {% end %}\r\n    end\r\n\r\n    macro wrap_all_class_methods(rb_interpreter, crystal_class, exclusions, verbose, context = nil)\r\n      {% has_specialized_method = {} of String => Bool %}\r\n\r\n      {% for method in crystal_class.resolve.class.methods %}\r\n        {% all_annotations_specialize_cm = crystal_class.resolve.annotations(Anyolite::SpecializeClassMethod) %}\r\n        {% annotation_specialize_cm = all_annotations_specialize_cm.find { |element| element[0].stringify == method.name.stringify || element[0] == method.name.stringify } %}\r\n\r\n        {% if method.annotation(Anyolite::Specialize) %}\r\n          {% has_specialized_method[method.name.stringify] = true %}\r\n        {% end %}\r\n\r\n        {% if annotation_specialize_cm %}\r\n          {% has_specialized_method[annotation_specialize_cm[0].id.stringify] = true %}\r\n        {% end %}\r\n      {% end %}\r\n\r\n      {% how_many_times_wrapped = {} of String => UInt32 %}\r\n\r\n      {% default_optional_args_to_keyword_args = false %}\r\n\r\n      {% if !crystal_class.resolve.annotations(Anyolite::DefaultOptionalArgsToKeywordArgs).empty? %}\r\n        {% default_optional_args_to_keyword_args = true %}\r\n      {% else %}\r\n        {% for class_ancestor in crystal_class.resolve.ancestors %}\r\n          {% if !class_ancestor.resolve.annotations(Anyolite::DefaultOptionalArgsToKeywordArgs).empty? %}\r\n            {% default_optional_args_to_keyword_args = true %}\r\n          {% end %}\r\n        {% end %}\r\n      {% end %}\r\n\r\n      {% for method, index in crystal_class.resolve.class.methods %}\r\n        {% all_annotations_exclude_cm = crystal_class.resolve.annotations(Anyolite::ExcludeClassMethod) %}\r\n        {% annotation_exclude_cm = all_annotations_exclude_cm.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n        {% all_annotations_specialize_cm = crystal_class.resolve.annotations(Anyolite::SpecializeClassMethod) %}\r\n        {% annotation_specialize_cm = all_annotations_specialize_cm.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n        {% all_annotations_rename_cm = crystal_class.resolve.annotations(Anyolite::RenameClassMethod) %}\r\n        {% annotation_rename_cm = all_annotations_rename_cm.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n        {% all_annotations_without_keywords_cm = crystal_class.resolve.annotations(Anyolite::WrapWithoutKeywordsClassMethod) %}\r\n        {% annotation_without_keyword_cm = all_annotations_without_keywords_cm.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n        {% all_annotations_return_nil_cm = crystal_class.resolve.annotations(Anyolite::ReturnNilClassMethod) %}\r\n        {% annotation_return_nil_cm = all_annotations_return_nil_cm.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n        {% all_annotations_add_block_arg_cm = crystal_class.resolve.annotations(Anyolite::AddBlockArgClassMethod) %}\r\n        {% annotation_add_block_arg_cm = all_annotations_add_block_arg_cm.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n        {% all_annotations_store_block_arg_cm = crystal_class.resolve.annotations(Anyolite::StoreBlockArgClassMethod) %}\r\n        {% annotation_store_block_arg_cm = all_annotations_store_block_arg_cm.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n        {% all_annotations_force_keyword_arg_cm = crystal_class.resolve.annotations(Anyolite::ForceKeywordArgClassMethod) %}\r\n        {% annotation_force_keyword_arg_cm = all_annotations_force_keyword_arg_cm.find { |element| element[0].id.stringify == method.name.stringify } %}\r\n\r\n        {% if crystal_class.resolve.annotation(Anyolite::NoKeywordArgs) %}\r\n          {% no_keyword_args = true %}\r\n        {% else %}\r\n          {% no_keyword_args = false %}\r\n        {% end %}\r\n\r\n        {% if method.annotation(Anyolite::Rename) %}\r\n          {% ruby_name = method.annotation(Anyolite::Rename)[0].id %}\r\n        {% elsif annotation_rename_cm && method.name.stringify == annotation_rename_cm[0].stringify %}\r\n          {% ruby_name = annotation_rename_cm[1].id %}\r\n        {% else %}\r\n          {% ruby_name = method.name %}\r\n        {% end %}\r\n\r\n        {% if method.annotation(Anyolite::AddBlockArg) %}\r\n          {% block_arg_number = method.annotation(Anyolite::AddBlockArg)[0] %}\r\n          {% block_return_type = method.annotation(Anyolite::AddBlockArg)[1] %}\r\n        {% elsif annotation_add_block_arg_cm && method.name.stringify == annotation_add_block_arg_cm[0].stringify %}\r\n          {% block_arg_number = annotation_add_block_arg_cm[1] %}\r\n          {% block_return_type = annotation_add_block_arg_cm[2] %}\r\n        {% else %}\r\n          {% block_arg_number = nil %}\r\n          {% block_return_type = nil %}\r\n        {% end %}\r\n\r\n        {% added_keyword_args = nil %}\r\n\r\n        {% if method.annotation(Anyolite::Specialize) && method.annotation(Anyolite::Specialize)[1] %}\r\n          {% added_keyword_args = method.annotation(Anyolite::Specialize)[1] %}\r\n        {% end %}\r\n\r\n        {% if annotation_specialize_cm && (method.args.stringify == annotation_specialize_cm[1].stringify || (method.args.stringify == \"[]\" && annotation_specialize_cm[1] == nil)) %}\r\n          {% added_keyword_args = annotation_specialize_cm[2] %}\r\n        {% end %}\r\n\r\n        {% without_keywords = false %}\r\n\r\n        {% if method.annotation(Anyolite::WrapWithoutKeywords) %}\r\n          {% without_keywords = method.annotation(Anyolite::WrapWithoutKeywords)[0] ? method.annotation(Anyolite::WrapWithoutKeywords)[0] : -1 %}\r\n        {% elsif annotation_without_keyword_cm %}\r\n          {% without_keywords = annotation_without_keyword_cm[1] ? annotation_without_keyword_cm[1] : -1 %}\r\n        {% elsif default_optional_args_to_keyword_args %}\r\n          {% without_keywords = -2 %}\r\n        {% end %}\r\n\r\n        {% return_nil = false %}\r\n        {% if method.annotation(Anyolite::ReturnNil) || (annotation_return_nil_cm) %}\r\n          {% return_nil = true %}\r\n        {% end %}\r\n\r\n        {% store_block_arg = false %}\r\n        {% if method.annotation(Anyolite::StoreBlockArg) || (annotation_store_block_arg_cm) %}\r\n          {% store_block_arg = true %}\r\n        {% end %}\r\n\r\n        {% force_keyword_arg = false %}\r\n        {% if method.annotation(Anyolite::ForceKeywordArg) || (annotation_force_keyword_arg_cm) %}\r\n          {% force_keyword_arg = true %}\r\n        {% end %}\r\n\r\n        {% puts \"> Processing class method #{crystal_class}::#{method.name} to #{ruby_name}\\n--> Args: #{method.args}\" if verbose %}\r\n\r\n        {% if method.accepts_block? %}\r\n          {% puts \"--> Block arg possible for #{crystal_class}::#{method.name}\" if verbose %}\r\n        {% end %}\r\n        \r\n        # Ignore private and protected methods (can't be called from outside, they'd need to be wrapped for this to work)\r\n        {% if method.visibility != :public %}\r\n          {% puts \"--> Excluding #{crystal_class}::#{method.name} (Exclusion due to visibility)\" if verbose %}\r\n        # We already wrapped 'initialize', so we don't need to wrap these\r\n        {% elsif method.name == \"allocate\" || method.name == \"new\" %}\r\n          {% puts \"--> Excluding #{crystal_class}::#{method.name} (Allocation method)\" if verbose %}\r\n        {% elsif method.name == \"parse?\" && method.args.stringify == \"[string]\" %}\r\n          {% operator = ruby_name %}\r\n\r\n          Anyolite::Macro.wrap_method_index({{rb_interpreter}}, {{crystal_class}}, {{index}}, \"{{ruby_name}}\", operator: \"{{operator}}\", is_class_method: true, added_keyword_args: [string : String], without_keywords: {{force_keyword_arg ? false : -1}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n          {% how_many_times_wrapped[ruby_name.stringify] = how_many_times_wrapped[ruby_name.stringify] ? how_many_times_wrapped[ruby_name.stringify] + 1 : 1 %}\r\n        {% elsif method.name == \"<=\" %}\r\n          {% puts \"--> Excluding #{crystal_class}::#{method.name} (Class argument method)\" if verbose %}\r\n        # Exclude methods if given as arguments\r\n        {% elsif exclusions.includes?(method.name.symbolize) || exclusions.includes?(method.name.stringify) %}\r\n          {% puts \"--> Excluding #{crystal_class}::#{method.name} (Exclusion argument)\" if verbose %}\r\n        # Exclude methods which were annotated to be excluded\r\n        {% elsif method.annotation(Anyolite::Exclude) || (annotation_exclude_cm) %}\r\n          {% puts \"--> Excluding #{crystal_class}::#{method.name} (Exclusion annotation)\" if verbose %}\r\n        # Exclude methods which are not the specialized methods\r\n        {% elsif has_specialized_method[method.name.stringify] && !(method.annotation(Anyolite::Specialize) || (annotation_specialize_cm && (method.args.stringify == annotation_specialize_cm[1].stringify || (method.args.stringify == \"[]\" && annotation_specialize_cm[1] == nil)))) %}\r\n          {% puts \"--> Excluding #{crystal_class}::#{method.name} (Specialization)\" if verbose %}\r\n        {% elsif method.name[-1..-1] =~ /\\W/ %}\r\n          {% operator = ruby_name %}\r\n\r\n          Anyolite::Macro.wrap_method_index({{rb_interpreter}}, {{crystal_class}}, {{index}}, \"{{ruby_name}}\", operator: \"{{operator}}\", is_class_method: true, added_keyword_args: {{added_keyword_args}}, without_keywords: {{force_keyword_arg ? false : -1}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n          {% how_many_times_wrapped[ruby_name.stringify] = how_many_times_wrapped[ruby_name.stringify] ? how_many_times_wrapped[ruby_name.stringify] + 1 : 1 %}\r\n        # Handle other class methods\r\n        {% else %}\r\n          Anyolite::Macro.wrap_method_index({{rb_interpreter}}, {{crystal_class}}, {{index}}, \"{{ruby_name}}\", is_class_method: true, without_keywords: {{without_keywords || (no_keyword_args && !force_keyword_arg)}}, added_keyword_args: {{added_keyword_args}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n          {% how_many_times_wrapped[ruby_name.stringify] = how_many_times_wrapped[ruby_name.stringify] ? how_many_times_wrapped[ruby_name.stringify] + 1 : 1 %}\r\n        {% end %}\r\n\r\n        {% if how_many_times_wrapped[ruby_name.stringify] && how_many_times_wrapped[ruby_name.stringify] > 1 %}\r\n          {% puts \"\\e[31m> WARNING: Method #{crystal_class}::#{ruby_name}\\n--> New arguments: #{method.args}\\n--> Wrapped more than once (#{how_many_times_wrapped[ruby_name.stringify]}).\\e[0m\" %}\r\n        {% end %}\r\n        {% puts \"\" if verbose %}\r\n      {% end %}\r\n    end\r\n\r\n    macro wrap_all_constants(rb_interpreter, crystal_class, exclusions, verbose = false, overwrite = false, context = nil)\r\n      # TODO: Is the context needed here?\r\n\r\n      # NOTE: This check is necessary due to https://github.com/crystal-lang/crystal/issues/5757\r\n      {% if crystal_class.resolve.type_vars.empty? %}\r\n        {% for constant, index in crystal_class.resolve.constants %}\r\n          {% all_annotations_exclude_cm = crystal_class.resolve.annotations(Anyolite::ExcludeConstant) %}\r\n          {% annotation_exclude_cm = all_annotations_exclude_cm.find { |element| element[0].id.stringify == constant.stringify } %}\r\n\r\n          {% all_annotations_rename_cm = crystal_class.resolve.annotations(Anyolite::RenameConstant) %}\r\n          {% annotation_rename_cm = all_annotations_rename_cm.find { |element| element[0].id.stringify == constant.stringify } %}\r\n\r\n          {% if annotation_rename_cm && constant.stringify == annotation_rename_cm[0].stringify %}\r\n            {% ruby_name = annotation_rename_cm[1].id %}\r\n          {% else %}\r\n            {% ruby_name = constant %}\r\n          {% end %}\r\n\r\n          {% puts \"> Processing constant #{crystal_class}::#{constant} to #{ruby_name}\" if verbose %}\r\n          # Exclude methods which were annotated to be excluded\r\n          {% if exclusions.includes?(constant.symbolize) || exclusions.includes?(constant) %}\r\n            {% puts \"--> Excluding #{crystal_class}::#{constant} (Exclusion argument)\" if verbose %}\r\n          {% elsif annotation_exclude_cm %}\r\n            {% puts \"--> Excluding #{crystal_class}::#{constant} (Exclusion annotation)\" if verbose %}\r\n          {% else %}\r\n            Anyolite::Macro.wrap_constant_or_class({{rb_interpreter}}, {{crystal_class}}, \"{{ruby_name}}\", {{constant}}, overwrite: {{overwrite}}, verbose: {{verbose}})\r\n          {% end %}\r\n          {% puts \"\" if verbose %}\r\n        {% end %}\r\n      {% end %}\r\n    end\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/macros/WrapMethodIndex.cr",
    "content": "module Anyolite\r\n  module Macro\r\n    macro wrap_method_index(rb_interpreter, crystal_class, method_index, ruby_name,\r\n                            is_constructor = false, is_class_method = false,\r\n                            operator = \"\", cut_name = nil,\r\n                            without_keywords = false, added_keyword_args = nil,\r\n                            context = nil, return_nil = false,\r\n                            block_arg_number = nil, block_return_type = nil,\r\n                            store_block_arg = false, other_source = nil)\r\n\r\n      {% method_source = other_source ? other_source : crystal_class %}\r\n\r\n      {% if is_class_method %}\r\n        {% method = method_source.resolve.class.methods[method_index] %}\r\n      {% else %}\r\n        {% method = method_source.resolve.methods[method_index] %}\r\n      {% end %}\r\n\r\n      {% if !operator.empty? %}\r\n        {% if cut_name %}\r\n          {% if is_class_method %}\r\n            {% final_method_name = \"#{crystal_class}.#{cut_name}\".id %}\r\n            {% final_operator = \"#{crystal_class}.#{operator.id}\" %}\r\n          {% else %}\r\n            {% final_method_name = cut_name %}\r\n            {% final_operator = operator %}\r\n          {% end %}\r\n        {% else %}\r\n          {% final_method_name = Anyolite::Empty %}\r\n          {% if is_class_method %}\r\n            {% final_operator = \"#{crystal_class}.#{operator.id}\" %}\r\n          {% else %}\r\n            {% final_operator = operator %}\r\n          {% end %}\r\n        {% end %}\r\n      {% else %}\r\n        {% if is_class_method %}\r\n          {% final_method_name = \"#{crystal_class}.#{method.name}\".id %}\r\n        {% else %}\r\n          {% final_method_name = method.name %}\r\n        {% end %}\r\n        {% final_operator = operator %}\r\n      {% end %}\r\n\r\n      {% final_arg_array = added_keyword_args ? added_keyword_args : method.args %}\r\n\r\n      # Routine to check all arguments for validity and potential self values\r\n\r\n      {% try_again = false %}\r\n      {% for arg, index in final_arg_array %}\r\n        {% if arg.is_a?(Arg) %}\r\n          {% if arg.restriction.is_a?(Self) %}\r\n            {% try_again = true %}\r\n            {% if arg.default_value %}\r\n              {% final_arg_array[index] = \"#{arg.name} : #{crystal_class} = #{arg.default_value}\".id %}\r\n            {% else %}\r\n              {% final_arg_array[index] = \"#{arg.name} : #{crystal_class}\".id %}\r\n            {% end %}\r\n          {% end %}\r\n        {% elsif arg.is_a?(TypeDeclaration) %}\r\n          {% if arg.type.is_a?(Self) %}\r\n            {% try_again = true %}\r\n            {% if arg.value %}\r\n              {% final_arg_array[index] = \"#{arg.var} : #{crystal_class} = #{arg.value}\".id %}\r\n            {% else %}\r\n              {% final_arg_array[index] = \"#{arg.var} : #{crystal_class}\".id %}\r\n            {% end %}\r\n          {% end %}\r\n        {% else %}\r\n          {% raise \"Argument #{arg} in function #{final_method_name} of class #{crystal_class} is neither Arg nor TypeDeclaration.\" %}\r\n        {% end %}\r\n      {% end %}\r\n\r\n      {% if try_again %}\r\n        Anyolite::Macro.wrap_method_index({{rb_interpreter}}, {{crystal_class}}, {{method_index}},\r\n          {{ruby_name}}, is_constructor: {{is_constructor}}, is_class_method: {{is_class_method}},\r\n          operator: {{operator}}, cut_name: {{cut_name}}, without_keywords: {{without_keywords}},\r\n          added_keyword_args: {{final_arg_array}}, context: {{context}}, return_nil: {{return_nil}},\r\n          block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}},\r\n          store_block_arg: {{store_block_arg}}, other_source: {{other_source}})\r\n      {% else %}\r\n        {% if final_arg_array.empty? %}\r\n          {% if is_class_method %}\r\n            Anyolite.wrap_class_method({{rb_interpreter}}, {{crystal_class}}, {{ruby_name}}, {{final_method_name}}, operator: {{final_operator}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n          {% elsif is_constructor %}\r\n            # Do not ever let a constructor return nil (for now)\r\n            Anyolite.wrap_constructor({{rb_interpreter}}, {{crystal_class}}, context: {{context}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n          {% else %}\r\n            Anyolite.wrap_instance_method({{rb_interpreter}}, {{crystal_class}}, {{ruby_name}}, {{final_method_name}}, operator: {{final_operator}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n          {% end %}\r\n\r\n        # A complicated check, but it is more stable than simply checking for colons\r\n        {% elsif !final_arg_array.find { |m| !((m.is_a?(TypeDeclaration) && m.type) || (m.is_a?(Arg) && m.restriction)) } %}\r\n          {% if without_keywords %}\r\n            {% if without_keywords >= final_arg_array.size %}\r\n              {% regular_arg_partition = nil %}\r\n              {% keyword_arg_partition = final_arg_array %}\r\n            {% elsif without_keywords == -2 %}\r\n              {% first_optional_arg = 0 %}\r\n              {% final_arg_array.each { |arg| first_optional_arg += 1 unless (arg.is_a?(TypeDeclaration) && !arg.value.is_a?(Nop)) || (arg.is_a?(Arg) && !arg.default_value.is_a?(Nop)) } %}\r\n\r\n              {% regular_arg_partition = final_arg_array[0..first_optional_arg - 1] %}\r\n              {% keyword_arg_partition = final_arg_array[first_optional_arg..-1] %}\r\n\r\n              {% regular_arg_partition = nil if first_optional_arg == 0 || regular_arg_partition.empty? %}\r\n              {% keyword_arg_partition = nil if keyword_arg_partition.empty? %}\r\n            {% elsif without_keywords < 0 %}\r\n              {% regular_arg_partition = final_arg_array %}\r\n              {% keyword_arg_partition = nil %}\r\n            {% else %}\r\n              {% regular_arg_partition = final_arg_array[0..without_keywords - 1] %}\r\n              {% keyword_arg_partition = final_arg_array[without_keywords..-1] %}\r\n\r\n              {% regular_arg_partition = nil if without_keywords == 0 || regular_arg_partition.empty? %}\r\n              {% keyword_arg_partition = nil if keyword_arg_partition.empty? %}\r\n            {% end %}\r\n\r\n            {% if keyword_arg_partition %}\r\n              {% if is_class_method %}\r\n                Anyolite.wrap_class_method_with_keywords({{rb_interpreter}}, {{crystal_class}}, {{ruby_name}}, {{final_method_name}}, \r\n                  {{keyword_arg_partition}}, regular_args: {{regular_arg_partition}}, operator: {{final_operator}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n              {% elsif is_constructor %}\r\n                Anyolite.wrap_constructor_with_keywords({{rb_interpreter}}, {{crystal_class}}, \r\n                  {{keyword_arg_partition}}, regular_args: {{regular_arg_partition}}, operator: {{final_operator}}, context: {{context}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n              {% else %}\r\n                Anyolite.wrap_instance_method_with_keywords({{rb_interpreter}}, {{crystal_class}}, {{ruby_name}}, {{final_method_name}}, \r\n                  {{keyword_arg_partition}}, regular_args: {{regular_arg_partition}}, operator: {{final_operator}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n              {% end %}\r\n            {% else %}\r\n              {% if is_class_method %}\r\n                Anyolite.wrap_class_method({{rb_interpreter}}, {{crystal_class}}, {{ruby_name}}, {{final_method_name}}, \r\n                  {{regular_arg_partition}}, operator: {{final_operator}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n              {% elsif is_constructor %}\r\n                Anyolite.wrap_constructor({{rb_interpreter}}, {{crystal_class}}, \r\n                  {{regular_arg_partition}}, operator: {{final_operator}}, context: {{context}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n              {% else %}\r\n                Anyolite.wrap_instance_method({{rb_interpreter}}, {{crystal_class}}, {{ruby_name}}, {{final_method_name}}, \r\n                  {{regular_arg_partition}}, operator: {{final_operator}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n              {% end %}\r\n            {% end %}\r\n          {% else %}\r\n            {% if is_class_method %}\r\n              Anyolite.wrap_class_method_with_keywords({{rb_interpreter}}, {{crystal_class}}, {{ruby_name}}, {{final_method_name}}, \r\n                {{final_arg_array}}, operator: {{final_operator}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n            {% elsif is_constructor %}\r\n              Anyolite.wrap_constructor_with_keywords({{rb_interpreter}}, {{crystal_class}}, \r\n                {{final_arg_array}}, operator: {{final_operator}}, context: {{context}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n            {% else %}\r\n              Anyolite.wrap_instance_method_with_keywords({{rb_interpreter}}, {{crystal_class}}, {{ruby_name}}, {{final_method_name}}, \r\n                {{final_arg_array}}, operator: {{final_operator}}, context: {{context}}, return_nil: {{return_nil}}, block_arg_number: {{block_arg_number}}, block_return_type: {{block_return_type}}, store_block_arg: {{store_block_arg}})\r\n            {% end %}\r\n          {% end %}\r\n\r\n        {% elsif !is_class_method && operator == \"==\" && final_arg_array[0] && !final_arg_array[1] %}\r\n          {% options = {:context => context} %}\r\n          Anyolite::Macro.wrap_equality_function({{rb_interpreter}}, {{crystal_class}}, {{ruby_name}}, {{final_method_name}}, operator: {{final_operator}}, options: {{options}})\r\n        {% else %}\r\n          {% if is_class_method %}\r\n            {% puts \"\\e[33m> INFO: Could not wrap function '#{crystal_class}.#{method.name}' with args #{method.args}.\\e[0m\" %}\r\n          {% else %}\r\n            {% puts \"\\e[33m> INFO: Could not wrap function '#{method.name}' with args #{method.args}.\\e[0m\" %}\r\n          {% end %}\r\n        {% end %}\r\n      {% end %}\r\n    end\r\n  end\r\nend\r\n"
  },
  {
    "path": "src/macros/Wrappers.cr",
    "content": "module Anyolite\r\n  module Macro\r\n    macro wrap_module_function_with_args(rb_interpreter, under_module, name, proc, regular_args = nil, operator = \"\", options = {} of Symbol => NoReturn)\r\n      {% if regular_args.is_a?(ArrayLiteral) %}\r\n        {% regular_arg_array = regular_args %}\r\n      {% elsif regular_args == nil %}\r\n        {% regular_arg_array = nil %}\r\n      {% else %}\r\n        {% regular_arg_array = [regular_args] %}\r\n      {% end %}\r\n\r\n      {% options[:type_vars] = under_module.resolve.type_vars %}\r\n      {% options[:type_var_names_annotation] = under_module.resolve.annotation(Anyolite::SpecifyGenericTypes) %}\r\n      {% options[:type_var_names] = options[:type_var_names_annotation] ? options[:type_var_names_annotation][0] : nil %}\r\n\r\n      %wrapped_method = Anyolite::Macro.new_rb_func do\r\n        # TODO: Put these kinds of commands into a new macro\r\n        {% if options[:block_arg_number] || options[:store_block_arg] %}\r\n          %block_ptr = Pointer(Anyolite::RbCore::RbValue).malloc(size: 1)\r\n          \r\n          {% if options[:store_block_arg] %}\r\n            Anyolite::RbArgCache.push_block_cache(%block_ptr)\r\n          {% end %}\r\n\r\n          %args = Anyolite::Macro.generate_arg_tuple(_rb, {{regular_args}}, options: {{options}})\r\n          %format_string = Anyolite::Macro.format_string({{regular_args}}, options: {{options}}) + \"&\"\r\n          \r\n          Anyolite::Macro.load_args_into_vars({{regular_args}}, %format_string, %args, %block_ptr)\r\n\r\n          {% if options[:block_arg_number] %}\r\n            if Anyolite::RbCast.check_for_nil(%block_ptr.value)\r\n              Anyolite.raise_argument_error(\"No block given.\")\r\n              Anyolite::RbCast.return_nil\r\n            end\r\n          {% end %}\r\n\r\n          %converted_args = Anyolite::Macro.convert_regular_args(_rb, %args, {{regular_args}}, options: {{options}})\r\n        {% else %}\r\n          %block_ptr = nil\r\n          %converted_args = Anyolite::Macro.get_converted_args(_rb, {{regular_arg_array}}, options: {{options}})\r\n        {% end %}\r\n\r\n        %return_value = Anyolite::Macro.call_and_return(_rb, {{proc}}, {{regular_arg_array}}, %converted_args, operator: {{operator}}, options: {{options}}, block_ptr: %block_ptr)\r\n\r\n        {% if options[:store_block_arg] %}\r\n          Anyolite::RbArgCache.pop_block_cache\r\n        {% end %}\r\n\r\n        %return_value\r\n      end\r\n\r\n      {{rb_interpreter}}.define_module_function({{name}}, Anyolite::RbClassCache.get({{under_module}}), %wrapped_method)\r\n    end\r\n\r\n    macro wrap_module_function_with_keyword_args(rb_interpreter, under_module, name, proc, keyword_args, regular_args = nil, operator = \"\", options = {} of Symbol => NoReturn)\r\n      {% if regular_args.is_a?(ArrayLiteral) %}\r\n        {% regular_arg_array = regular_args %}\r\n      {% elsif regular_args == nil %}\r\n        {% regular_arg_array = nil %}\r\n      {% else %}\r\n        {% regular_arg_array = [regular_args] %}\r\n      {% end %}\r\n\r\n      {% options[:type_vars] = under_module.resolve.type_vars %}\r\n      {% options[:type_var_names_annotation] = under_module.resolve.annotation(Anyolite::SpecifyGenericTypes) %}\r\n      {% options[:type_var_names] = options[:type_var_names_annotation] ? options[:type_var_names_annotation][0] : nil %}\r\n\r\n      %wrapped_method = Anyolite::Macro.new_rb_func do\r\n        %regular_arg_tuple = Anyolite::Macro.generate_arg_tuple(_rb, {{regular_arg_array}}, options: {{options}})\r\n\r\n        {% if options[:block_arg_number] || options[:store_block_arg] %}\r\n          %block_ptr = Pointer(Anyolite::RbCore::RbValue).malloc(size: 1)\r\n\r\n          {% if options[:store_block_arg] %}\r\n            Anyolite::RbArgCache.push_block_cache(%block_ptr)\r\n          {% end %}\r\n\r\n          %format_string = Anyolite::Macro.format_string({{regular_arg_array}}, options: {{options}}) + \":&\"\r\n          %kw_args = Anyolite::Macro.load_kw_args_into_vars({{regular_arg_array}}, {{keyword_args}}, %format_string, %regular_arg_tuple, %block_ptr)\r\n\r\n          {% if options[:block_arg_number] %}\r\n            if Anyolite::RbCast.check_for_nil(%block_ptr.value)\r\n              Anyolite.raise_argument_error(\"No block given.\")\r\n              Anyolite::RbCast.return_nil\r\n            end\r\n          {% end %}\r\n        {% else %}\r\n          %block_ptr = nil\r\n          %format_string = Anyolite::Macro.format_string({{regular_arg_array}}, options: {{options}}) + \":\"\r\n          %kw_args = Anyolite::Macro.load_kw_args_into_vars({{regular_arg_array}}, {{keyword_args}}, %format_string, %regular_arg_tuple)\r\n        {% end %}\r\n\r\n        %converted_regular_args = Anyolite::Macro.convert_regular_args(_rb, %regular_arg_tuple, {{regular_arg_array}}, options: {{options}})\r\n\r\n        {% if !regular_arg_array || regular_arg_array.size == 0 %}\r\n          {% options[:empty_regular] = true %}\r\n        {% end %}\r\n\r\n        %return_value = Anyolite::Macro.call_and_return_keyword_method(_rb, {{proc}}, %converted_regular_args, {{keyword_args}}, %kw_args, operator: {{operator}}, options: {{options}}, block_ptr: %block_ptr)\r\n        \r\n        {% if options[:store_block_arg] %}\r\n          Anyolite::RbArgCache.pop_block_cache\r\n        {% end %}\r\n\r\n        %return_value\r\n      end\r\n\r\n      {{rb_interpreter}}.define_module_function({{name}}, Anyolite::RbClassCache.get({{under_module}}), %wrapped_method)\r\n    end\r\n\r\n    macro wrap_class_method_with_args(rb_interpreter, crystal_class, name, proc, regular_args = nil, operator = \"\", options = {} of Symbol => NoReturn)\r\n      {% if regular_args.is_a?(ArrayLiteral) %}\r\n        {% regular_arg_array = regular_args %}\r\n      {% elsif regular_args == nil %}\r\n        {% regular_arg_array = nil %}\r\n      {% else %}\r\n        {% regular_arg_array = [regular_args] %}\r\n      {% end %}\r\n\r\n      {% options[:type_vars] = crystal_class.resolve.type_vars %}\r\n      {% options[:type_var_names_annotation] = crystal_class.resolve.annotation(Anyolite::SpecifyGenericTypes) %}\r\n      {% options[:type_var_names] = options[:type_var_names_annotation] ? options[:type_var_names_annotation][0] : nil %}\r\n\r\n      %wrapped_method = Anyolite::Macro.new_rb_func do\r\n        {% if options[:block_arg_number] || options[:store_block_arg] %}\r\n          %block_ptr = Pointer(Anyolite::RbCore::RbValue).malloc(size: 1)\r\n\r\n          {% if options[:store_block_arg] %}\r\n            Anyolite::RbArgCache.push_block_cache(%block_ptr)\r\n          {% end %}\r\n\r\n          %args = Anyolite::Macro.generate_arg_tuple(_rb, {{regular_args}}, options: {{options}})\r\n          %format_string = Anyolite::Macro.format_string({{regular_args}}, options: {{options}}) + \"&\"\r\n\r\n          Anyolite::Macro.load_args_into_vars({{regular_args}}, %format_string, %args, %block_ptr)\r\n\r\n          {% if options[:block_arg_number] %}\r\n            if Anyolite::RbCast.check_for_nil(%block_ptr.value)\r\n              Anyolite.raise_argument_error(\"No block given.\")\r\n              Anyolite::RbCast.return_nil\r\n            end\r\n          {% end %}\r\n\r\n          %converted_args = Anyolite::Macro.convert_regular_args(_rb, %args, {{regular_args}}, options: {{options}})\r\n        {% else %}\r\n          %block_ptr = nil\r\n          %converted_args = Anyolite::Macro.get_converted_args(_rb, {{regular_arg_array}}, options: {{options}})\r\n        {% end %}\r\n\r\n        %return_value = Anyolite::Macro.call_and_return(_rb, {{proc}}, {{regular_arg_array}}, %converted_args, operator: {{operator}}, options: {{options}}, block_ptr: %block_ptr)\r\n\r\n        {% if options[:store_block_arg] %}\r\n          Anyolite::RbArgCache.pop_block_cache\r\n        {% end %}\r\n\r\n        %return_value\r\n      end\r\n      \r\n      {{rb_interpreter}}.define_class_method({{name}}, Anyolite::RbClassCache.get({{crystal_class}}), %wrapped_method)\r\n    end\r\n\r\n    macro wrap_class_method_with_keyword_args(rb_interpreter, crystal_class, name, proc, keyword_args, regular_args = nil, operator = \"\", options = {} of Symbol => NoReturn)\r\n      {% if regular_args.is_a?(ArrayLiteral) %}\r\n        {% regular_arg_array = regular_args %}\r\n      {% elsif regular_args == nil %}\r\n        {% regular_arg_array = nil %}\r\n      {% else %}\r\n        {% regular_arg_array = [regular_args] %}\r\n      {% end %}\r\n\r\n      {% options[:type_vars] = crystal_class.resolve.type_vars %}\r\n      {% options[:type_var_names_annotation] = crystal_class.resolve.annotation(Anyolite::SpecifyGenericTypes) %}\r\n      {% options[:type_var_names] = options[:type_var_names_annotation] ? options[:type_var_names_annotation][0] : nil %}\r\n\r\n      %wrapped_method = Anyolite::Macro.new_rb_func do\r\n        %regular_arg_tuple = Anyolite::Macro.generate_arg_tuple(_rb, {{regular_arg_array}}, options: {{options}})\r\n\r\n        {% if options[:block_arg_number] || options[:store_block_arg] %}\r\n          %block_ptr = Pointer(Anyolite::RbCore::RbValue).malloc(size: 1)\r\n\r\n          {% if options[:store_block_arg] %}\r\n            Anyolite::RbArgCache.push_block_cache(%block_ptr)\r\n          {% end %}\r\n\r\n          %format_string = Anyolite::Macro.format_string({{regular_arg_array}}, options: {{options}}) + \":&\"\r\n          %kw_args = Anyolite::Macro.load_kw_args_into_vars({{regular_arg_array}}, {{keyword_args}}, %format_string, %regular_arg_tuple, %block_ptr)\r\n\r\n          {% if options[:block_arg_number] %}\r\n            if Anyolite::RbCast.check_for_nil(%block_ptr.value)\r\n              Anyolite.raise_argument_error(\"No block given.\")\r\n              Anyolite::RbCast.return_nil\r\n            end\r\n          {% end %}\r\n        {% else %}\r\n          %block_ptr = nil\r\n          %format_string = Anyolite::Macro.format_string({{regular_arg_array}}, options: {{options}}) + \":\"\r\n          %kw_args = Anyolite::Macro.load_kw_args_into_vars({{regular_arg_array}}, {{keyword_args}}, %format_string, %regular_arg_tuple)\r\n        {% end %}\r\n\r\n        %converted_regular_args = Anyolite::Macro.convert_regular_args(_rb, %regular_arg_tuple, {{regular_arg_array}}, options: {{options}})\r\n\r\n        {% if !regular_arg_array || regular_arg_array.size == 0 %}\r\n          {% options[:empty_regular] = true %}\r\n        {% end %}\r\n\r\n        %return_value = Anyolite::Macro.call_and_return_keyword_method(_rb, {{proc}}, %converted_regular_args, {{keyword_args}}, %kw_args, operator: {{operator}}, options: {{options}}, block_ptr: %block_ptr)\r\n\r\n        {% if options[:store_block_arg] %}\r\n          Anyolite::RbArgCache.pop_block_cache\r\n        {% end %}\r\n\r\n        %return_value\r\n      end\r\n\r\n      {{rb_interpreter}}.define_class_method({{name}}, Anyolite::RbClassCache.get({{crystal_class}}), %wrapped_method)\r\n    end\r\n\r\n    macro wrap_instance_function_with_args(rb_interpreter, crystal_class, name, proc, regular_args = nil, operator = \"\", options = {} of Symbol => NoReturn)\r\n      {% if regular_args.is_a?(ArrayLiteral) %}\r\n        {% regular_arg_array = regular_args %}\r\n      {% elsif regular_args == nil %}\r\n        {% regular_arg_array = nil %}\r\n      {% else %}\r\n        {% regular_arg_array = [regular_args] %}\r\n      {% end %}\r\n\r\n      {% options[:type_vars] = crystal_class.resolve.type_vars %}\r\n      {% options[:type_var_names_annotation] = crystal_class.resolve.annotation(Anyolite::SpecifyGenericTypes) %}\r\n      {% options[:type_var_names] = options[:type_var_names_annotation] ? options[:type_var_names_annotation][0] : nil %}\r\n\r\n      %wrapped_method = Anyolite::Macro.new_rb_func do\r\n        {% if options[:block_arg_number] || options[:store_block_arg] %}\r\n          %block_ptr = Pointer(Anyolite::RbCore::RbValue).malloc(size: 1)\r\n\r\n          {% if options[:store_block_arg] %}\r\n            Anyolite::RbArgCache.push_block_cache(%block_ptr)\r\n          {% end %}\r\n\r\n          %args = Anyolite::Macro.generate_arg_tuple(_rb, {{regular_args}}, options: {{options}})\r\n          %format_string = Anyolite::Macro.format_string({{regular_args}}, options: {{options}}) + \"&\"\r\n          \r\n          Anyolite::Macro.load_args_into_vars({{regular_args}}, %format_string, %args, %block_ptr)\r\n\r\n          {% if options[:block_arg_number] %}\r\n            if Anyolite::RbCast.check_for_nil(%block_ptr.value)\r\n              Anyolite.raise_argument_error(\"No block given.\")\r\n              Anyolite::RbCast.return_nil\r\n            end\r\n          {% end %}\r\n\r\n          %converted_args = Anyolite::Macro.convert_regular_args(_rb, %args, {{regular_args}}, options: {{options}})\r\n        {% else %}\r\n          %block_ptr = nil\r\n          %converted_args = Anyolite::Macro.get_converted_args(_rb, {{regular_arg_array}}, options: {{options}})\r\n        {% end %}\r\n\r\n        if {{crystal_class}} <= Struct || {{crystal_class}} <= Enum\r\n          %converted_obj = Anyolite::Macro.convert_from_ruby_struct(_rb, _obj, {{crystal_class}}).value\r\n        else\r\n          %converted_obj = Anyolite::Macro.convert_from_ruby_object(_rb, _obj, {{crystal_class}}).value\r\n        end\r\n\r\n        %return_value = Anyolite::Macro.call_and_return_instance_method(_rb, {{proc}}, %converted_obj, %converted_args, operator: {{operator}}, options: {{options}}, block_ptr: %block_ptr)\r\n        \r\n        {% if options[:store_block_arg] %}\r\n          Anyolite::RbArgCache.pop_block_cache\r\n        {% end %}\r\n\r\n        %return_value\r\n      end\r\n\r\n      {{rb_interpreter}}.define_method({{name}}, Anyolite::RbClassCache.get({{crystal_class}}), %wrapped_method)\r\n    end\r\n\r\n    macro wrap_instance_function_with_keyword_args(rb_interpreter, crystal_class, name, proc, keyword_args, regular_args = nil, operator = \"\", options = {} of Symbol => NoReturn)\r\n      {% if regular_args.is_a?(ArrayLiteral) %}\r\n        {% regular_arg_array = regular_args %}\r\n      {% elsif regular_args == nil %}\r\n        {% regular_arg_array = nil %}\r\n      {% else %}\r\n        {% regular_arg_array = [regular_args] %}\r\n      {% end %}\r\n\r\n      {% options[:type_vars] = crystal_class.resolve.type_vars %}\r\n      {% options[:type_var_names_annotation] = crystal_class.resolve.annotation(Anyolite::SpecifyGenericTypes) %}\r\n      {% options[:type_var_names] = options[:type_var_names_annotation] ? options[:type_var_names_annotation][0] : nil %}\r\n\r\n      %wrapped_method = Anyolite::Macro.new_rb_func do\r\n        %regular_arg_tuple = Anyolite::Macro.generate_arg_tuple(_rb, {{regular_arg_array}}, options: {{options}})\r\n\r\n        # TODO: Add annotation argument for required blocks ('&!' then)\r\n\r\n        {% if options[:block_arg_number] || options[:store_block_arg] %}\r\n          %block_ptr = Pointer(Anyolite::RbCore::RbValue).malloc(size: 1)\r\n\r\n          {% if options[:store_block_arg] %}\r\n            Anyolite::RbArgCache.push_block_cache(%block_ptr)\r\n          {% end %}\r\n\r\n          %format_string = Anyolite::Macro.format_string({{regular_arg_array}}, options: {{options}}) + \":&\"\r\n          %kw_args = Anyolite::Macro.load_kw_args_into_vars({{regular_arg_array}}, {{keyword_args}}, %format_string, %regular_arg_tuple, %block_ptr)\r\n\r\n          {% if options[:block_arg_number] %}\r\n            if Anyolite::RbCast.check_for_nil(%block_ptr.value)\r\n              Anyolite.raise_argument_error(\"No block given.\")\r\n              Anyolite::RbCast.return_nil\r\n            end\r\n          {% end %}\r\n        {% else %}\r\n          %block_ptr = nil\r\n          %format_string = Anyolite::Macro.format_string({{regular_arg_array}}, options: {{options}}) + \":\"\r\n          %kw_args = Anyolite::Macro.load_kw_args_into_vars({{regular_arg_array}}, {{keyword_args}}, %format_string, %regular_arg_tuple)\r\n        {% end %}\r\n\r\n        %converted_regular_args = Anyolite::Macro.convert_regular_args(_rb, %regular_arg_tuple, {{regular_arg_array}}, options: {{options}})\r\n\r\n        if {{crystal_class}} <= Struct || {{crystal_class}} <= Enum\r\n          %converted_obj = Anyolite::Macro.convert_from_ruby_struct(_rb, _obj, {{crystal_class}}).value\r\n        else\r\n          %converted_obj = Anyolite::Macro.convert_from_ruby_object(_rb, _obj, {{crystal_class}}).value\r\n        end\r\n\r\n        {% if !regular_arg_array || regular_arg_array.size == 0 %}\r\n          {% options[:empty_regular] = true %}\r\n        {% end %}\r\n\r\n        %return_value = Anyolite::Macro.call_and_return_keyword_instance_method(_rb, {{proc}}, %converted_obj, %converted_regular_args, {{keyword_args}}, %kw_args, operator: {{operator}}, options: {{options}}, block_ptr: %block_ptr)\r\n\r\n        {% if options[:store_block_arg] %}\r\n          Anyolite::RbArgCache.pop_block_cache\r\n        {% end %}\r\n\r\n        %return_value\r\n      end\r\n\r\n      {{rb_interpreter}}.define_method({{name}}, Anyolite::RbClassCache.get({{crystal_class}}), %wrapped_method)\r\n    end\r\n\r\n    macro wrap_constructor_function_with_args(rb_interpreter, crystal_class, proc, regular_args = nil, operator = \"\", options = {} of Symbol => NoReturn)\r\n      {% if regular_args.is_a?(ArrayLiteral) %}\r\n        {% regular_arg_array = regular_args %}\r\n      {% elsif regular_args == nil %}\r\n        {% regular_arg_array = nil %}\r\n      {% else %}\r\n        {% regular_arg_array = [regular_args] %}\r\n      {% end %}\r\n\r\n      {% if !options[:block_arg_number] %}\r\n        {% proc_arg_string = \"\" %}\r\n      {% elsif options[:block_arg_number] == 0 %}\r\n        {% proc_arg_string = \"do\" %}\r\n      {% else %}\r\n        {% proc_arg_string = \"do |\" + (0..options[:block_arg_number] - 1).map { |x| \"block_arg_#{x}\" }.join(\", \") + \"|\" %}\r\n      {% end %}\r\n\r\n      {% options[:type_vars] = crystal_class.resolve.type_vars %}\r\n      {% options[:type_var_names_annotation] = crystal_class.resolve.annotation(Anyolite::SpecifyGenericTypes) %}\r\n      {% options[:type_var_names] = options[:type_var_names_annotation] ? options[:type_var_names_annotation][0] : nil %}\r\n\r\n      %wrapped_method = Anyolite::Macro.new_rb_func do\r\n        {% if options[:block_arg_number] || options[:store_block_arg] %}\r\n          %block_ptr = Pointer(Anyolite::RbCore::RbValue).malloc(size: 1)\r\n\r\n          {% if options[:store_block_arg] %}\r\n            Anyolite::RbArgCache.push_block_cache(%block_ptr)\r\n          {% end %}\r\n\r\n          %args = Anyolite::Macro.generate_arg_tuple(_rb, {{regular_args}}, options: {{options}})\r\n          %format_string = Anyolite::Macro.format_string({{regular_args}}, options: {{options}}) + \"&\"\r\n\r\n          Anyolite::Macro.load_args_into_vars({{regular_args}}, %format_string, %args, %block_ptr)\r\n\r\n          {% if options[:block_arg_number] %}\r\n            if Anyolite::RbCast.check_for_nil(%block_ptr.value)\r\n              Anyolite.raise_argument_error(\"No block given.\")\r\n              Anyolite::RbCast.return_nil\r\n            end\r\n          {% end %}\r\n\r\n          %converted_args = Anyolite::Macro.convert_regular_args(_rb, %args, {{regular_args}}, options: {{options}})\r\n        {% else %}\r\n          %block_ptr = nil\r\n          %converted_args = Anyolite::Macro.get_converted_args(_rb, {{regular_arg_array}}, options: {{options}})\r\n        {% end %}\r\n\r\n        %new_obj = {{proc}}{{operator.id}}(*%converted_args) {{proc_arg_string.id}}\r\n\r\n        {% if options[:block_arg_number] == 0 %}\r\n            %yield_value = Anyolite::RbCore.rb_yield(_rb, %block_ptr.value, Anyolite::RbCast.return_nil)\r\n            Anyolite::Macro.convert_from_ruby_to_crystal(_rb, %yield_value, options: {{options}})\r\n          end\r\n        {% elsif options[:block_arg_number] %}\r\n            %block_arg_array = [\r\n              {% for i in 0..options[:block_arg_number] - 1 %}\r\n                Anyolite::RbCast.return_value(_rb, {{\"block_arg_#{i}\".id}}),\r\n              {% end %}\r\n            ]\r\n            %yield_value = Anyolite::RbCore.rb_yield_argv(_rb, %block_ptr.value, {{options[:block_arg_number]}}, %block_arg_array)\r\n            Anyolite::Macro.convert_from_ruby_to_crystal(_rb, %yield_value, options: {{options}})\r\n          end\r\n        {% end %}\r\n\r\n        Anyolite::Macro.allocate_constructed_object(_rb, {{crystal_class}}, _obj, %new_obj)\r\n\r\n        {% if options[:store_block_arg] %}\r\n          Anyolite::RbArgCache.pop_block_cache\r\n        {% end %}\r\n\r\n        _obj\r\n      end\r\n\r\n      {{rb_interpreter}}.define_method(\"initialize\", Anyolite::RbClassCache.get({{crystal_class}}), %wrapped_method)\r\n    end\r\n\r\n    macro wrap_constructor_function_with_keyword_args(rb_interpreter, crystal_class, proc, keyword_args, regular_args = nil, operator = \"\", options = {} of Symbol => NoReturn)\r\n      {% if regular_args.is_a?(ArrayLiteral) %}\r\n        {% regular_arg_array = regular_args %}\r\n      {% elsif regular_args == nil %}\r\n        {% regular_arg_array = nil %}\r\n      {% else %}\r\n        {% regular_arg_array = [regular_args] %}\r\n      {% end %}\r\n\r\n      {% if !options[:block_arg_number] %}\r\n        {% proc_arg_string = \"\" %}\r\n      {% elsif options[:block_arg_number] == 0 %}\r\n        {% proc_arg_string = \"do\" %}\r\n      {% else %}\r\n        {% proc_arg_string = \"do |\" + (0..options[:block_arg_number] - 1).map { |x| \"block_arg_#{x}\" }.join(\", \") + \"|\" %}\r\n      {% end %}\r\n\r\n      {% options[:type_vars] = crystal_class.resolve.type_vars %}\r\n      {% options[:type_var_names_annotation] = crystal_class.resolve.annotation(Anyolite::SpecifyGenericTypes) %}\r\n      {% options[:type_var_names] = options[:type_var_names_annotation] ? options[:type_var_names_annotation][0] : nil %}\r\n      \r\n      %wrapped_method = Anyolite::Macro.new_rb_func do\r\n        %regular_arg_tuple = Anyolite::Macro.generate_arg_tuple(_rb, {{regular_arg_array}}, options: {{options}})\r\n\r\n        {% if options[:block_arg_number] || options[:store_block_arg] %}\r\n          %block_ptr = Pointer(Anyolite::RbCore::RbValue).malloc(size: 1)\r\n\r\n          {% if options[:store_block_arg] %}\r\n            Anyolite::RbArgCache.push_block_cache(%block_ptr)\r\n          {% end %}\r\n\r\n          %format_string = Anyolite::Macro.format_string({{regular_arg_array}}, options: {{options}}) + \":&\"\r\n          %kw_args = Anyolite::Macro.load_kw_args_into_vars({{regular_arg_array}}, {{keyword_args}}, %format_string, %regular_arg_tuple, %block_ptr)\r\n\r\n          {% if options[:block_arg_number] %}\r\n            if Anyolite::RbCast.check_for_nil(%block_ptr.value)\r\n              Anyolite.raise_argument_error(\"No block given.\")\r\n              Anyolite::RbCast.return_nil\r\n            end\r\n          {% end %}\r\n        {% else %}\r\n          %block_ptr = nil\r\n          %format_string = Anyolite::Macro.format_string({{regular_arg_array}}, options: {{options}}) + \":\"\r\n          %kw_args = Anyolite::Macro.load_kw_args_into_vars({{regular_arg_array}}, {{keyword_args}}, %format_string, %regular_arg_tuple)\r\n        {% end %}\r\n\r\n        %converted_regular_args = Anyolite::Macro.convert_regular_args(_rb, %regular_arg_tuple, {{regular_arg_array}}, options: {{options}})\r\n\r\n        {% if !regular_arg_array || regular_arg_array.size == 0 %}\r\n          %new_obj = {{proc}}{{operator.id}}(\r\n            {% c = 0 %}\r\n            {% for keyword in keyword_args %}\r\n              {{keyword.var.id}}: Anyolite::Macro.convert_from_ruby_to_crystal(_rb, %kw_args.values[{{c}}], {{keyword}}, options: {{options}}, debug_information: {{proc.stringify + \" - \" + keyword_args.stringify}}),\r\n              {% c += 1 %}\r\n            {% end %}\r\n          ) {{proc_arg_string.id}}\r\n        {% else %}\r\n          %new_obj = {{proc}}{{operator.id}}(*%converted_regular_args,\r\n            {% c = 0 %}\r\n            {% for keyword in keyword_args %}\r\n              {{keyword.var.id}}: Anyolite::Macro.convert_from_ruby_to_crystal(_rb, %kw_args.values[{{c}}], {{keyword}}, options: {{options}}, debug_information: {{proc.stringify + \" - \" + keyword_args.stringify}}),\r\n              {% c += 1 %}\r\n            {% end %}\r\n          ) {{proc_arg_string.id}}\r\n        {% end %}\r\n\r\n        {% if options[:block_arg_number] == 0 %}\r\n            %yield_value = Anyolite::RbCore.rb_yield(_rb, %block_ptr.value, Anyolite::RbCast.return_nil)\r\n            Anyolite::Macro.convert_from_ruby_to_crystal(_rb, %yield_value, options: {{options}})\r\n          end\r\n        {% elsif options[:block_arg_number] %}\r\n            %block_arg_array = [\r\n              {% for i in 0..options[:block_arg_number] - 1 %}\r\n                Anyolite::RbCast.return_value(_rb, {{\"block_arg_#{i}\".id}}),\r\n              {% end %}\r\n            ]\r\n            %yield_value = Anyolite::RbCore.rb_yield_argv(_rb, %block_ptr.value, {{options[:block_arg_number]}}, %block_arg_array)\r\n            Anyolite::Macro.convert_from_ruby_to_crystal(_rb, %yield_value, options: {{options}})\r\n          end\r\n        {% end %}\r\n\r\n        Anyolite::Macro.allocate_constructed_object(_rb, {{crystal_class}}, _obj, %new_obj)\r\n\r\n        {% if options[:store_block_arg] %}\r\n          Anyolite::RbArgCache.pop_block_cache\r\n        {% end %}\r\n        \r\n        _obj\r\n      end\r\n\r\n      {{rb_interpreter}}.define_method(\"initialize\", Anyolite::RbClassCache.get({{crystal_class}}), %wrapped_method)\r\n    end\r\n\r\n    macro wrap_equality_function(rb_interpreter, crystal_class, name, proc, operator = \"\", options = {} of Symbol => NoReturn)\r\n      {% options[:type_vars] = crystal_class.resolve.type_vars %}\r\n      {% options[:type_var_names_annotation] = crystal_class.resolve.annotation(Anyolite::SpecifyGenericTypes) %}\r\n      {% options[:type_var_names] = options[:type_var_names_annotation] ? options[:type_var_names_annotation][0] : nil %}\r\n\r\n      %wrapped_method = Anyolite::Macro.new_rb_func do\r\n        %args = Anyolite::Macro.generate_arg_tuple(_rb, [other : {{crystal_class}}], options: {{options}})\r\n        %format_string = Anyolite::Macro.format_string([other : {{crystal_class}}], options: {{options}})\r\n      \r\n        Anyolite::Macro.load_args_into_vars([other : {{crystal_class}}], %format_string, %args)\r\n\r\n        if !Anyolite::RbCast.check_custom_type(_rb, %args[0].value, {{crystal_class}})\r\n          Anyolite::RbCast.return_false\r\n        else\r\n          %converted_args = Anyolite::Macro.convert_regular_args(_rb, %args, [other : {{crystal_class}}], options: {{options}})\r\n\r\n          if {{crystal_class}} <= Struct || {{crystal_class}} <= Enum\r\n            %converted_obj = Anyolite::Macro.convert_from_ruby_struct(_rb, _obj, {{crystal_class}}).value\r\n          else\r\n            %converted_obj = Anyolite::Macro.convert_from_ruby_object(_rb, _obj, {{crystal_class}}).value\r\n          end\r\n\r\n          %return_value = Anyolite::Macro.call_and_return_instance_method(_rb, {{proc}}, %converted_obj, %converted_args, operator: {{operator}}, options: {{options}})\r\n\r\n          %return_value\r\n        end\r\n      end\r\n\r\n      {{rb_interpreter}}.define_method({{name}}, Anyolite::RbClassCache.get({{crystal_class}}), %wrapped_method)\r\n    end\r\n\r\n    macro wrap_constant_or_class(rb_interpreter, under_class_or_module, ruby_name, value, overwrite = false, verbose = false)\r\n      {% actual_constant = under_class_or_module.resolve.constant(value.id) %}\r\n      {% if actual_constant.is_a?(TypeNode) %}\r\n        {% if actual_constant.module? %}\r\n          Anyolite.wrap_module_with_methods({{rb_interpreter}}, {{actual_constant}}, under: {{under_class_or_module}}, overwrite: {{overwrite}}, verbose: {{verbose}})\r\n        {% elsif actual_constant.class? || actual_constant.struct? %}\r\n          Anyolite.wrap_class_with_methods({{rb_interpreter}}, {{actual_constant}}, under: {{under_class_or_module}}, wrap_equality_method: {{actual_constant.struct?}}, overwrite: {{overwrite}}, verbose: {{verbose}})\r\n        {% elsif actual_constant.union? %}\r\n          {% puts \"\\e[31m> WARNING: Wrapping of unions not supported, thus skipping #{actual_constant}\\e[0m\" %}\r\n        {% elsif actual_constant < Enum %}\r\n          Anyolite.wrap_class_with_methods({{rb_interpreter}}, {{actual_constant}}, under: {{under_class_or_module}}, use_enum_methods: true, wrap_equality_method: true, overwrite: {{overwrite}}, verbose: {{verbose}})\r\n        {% else %}\r\n          # Could be an alias, just try the default case\r\n          Anyolite.wrap_class_with_methods({{rb_interpreter}}, {{actual_constant}}, under: {{under_class_or_module}}, overwrite: {{overwrite}}, verbose: {{verbose}})\r\n        {% end %}\r\n      {% else %}\r\n        Anyolite.wrap_constant_under_class({{rb_interpreter}}, {{under_class_or_module}}, {{ruby_name}}, {{under_class_or_module}}::{{value}})\r\n      {% end %}\r\n    end\r\n  end\r\nend\r\n"
  },
  {
    "path": "test.cr",
    "content": "require \"./anyolite.cr\"\n\n# TODO: Pass flags to temporary executable\n{% unless flag?(:anyolite_implementation_ruby_3) %}\n  Anyolite::Preloader::AtCompiletime.transform_script_to_bytecode(\"examples/bytecode_test.rb\", \"examples/bytecode_test.mrb\")\n  Anyolite::Preloader::AtCompiletime.load_bytecode_file(\"examples/bytecode_test.mrb\")\n{% end %}\n\nmodule SomeModule\n  class_property some_class_property : Int32 = 258\n\n  def self.test_method(int : Int32, str : String)\n    [str, int]\n  end\n\n  @[Anyolite::RenameClass(\"TestStructRenamed\")]\n  struct TestStruct\n    property value : Int32 = -123\n    property test : Test = Test.new(-234)\n\n    def rb_initialize(rb)\n      puts \"Struct initialized!\"\n    end\n  end\n\n  @[Anyolite::SpecializeInstanceMethod(output_this_and_struct, [str : TestStruct])]\n  @[Anyolite::RenameInstanceMethod(output_this_and_struct, \"output_together_with\")]\n  @[Anyolite::ExcludeInstanceMethod(do_not_wrap_this_either)]\n  @[Anyolite::ExcludeConstant(CONSTANT_NOT_TO_WRAP)]\n  @[Anyolite::RenameConstant(CONSTANT, RUBY_CONSTANT)]\n  @[Anyolite::SpecializeInstanceMethod(method_without_keywords, [arg], [arg : String])]\n  @[Anyolite::SpecializeInstanceMethod(method_with_various_args, nil)]\n  @[Anyolite::SpecializeInstanceMethod(inspect, nil)]\n  class Test\n    struct ValueStruct\n      property i : Int32 = 1234\n      property f : Float32 = 0.1234\n      property s : String = \"Empty\"\n\n      @[Anyolite::WrapWithoutKeywords]\n      def initialize(new_i : Int = 5678, new_f : Float = 0.5678, new_s : String = \"Default\")\n        @i = new_i.to_i32\n        @f = new_f.to_f32\n        @s = new_s\n      end\n    end\n\n    @[Anyolite::RenameClass(\"UnderTestRenamed\")]\n    class UnderTest\n      module DeepUnderTest\n        def self.-(value : Int)\n          \"Well, you can't just subtract #{value} from a module...\"\n        end\n\n        class VeryDeepUnderTest\n          def nested_test\n            \"This is a nested test\"\n          end\n        end\n      end\n    end\n\n    enum TestEnum : UInt64\n      Three = 3\n      Four\n      Five\n      Seven = 7\n    end\n\n    struct DeepTestStruct\n      def to_s\n        \"DeepTestStruct\"\n      end\n    end\n\n    @[Anyolite::SpecifyGenericTypes([U, V])]\n    struct GenericTest(U, V)\n      property u : U\n      property v : V\n\n      def initialize(u : U, v : V)\n        @u = u\n        @v = v\n      end\n\n      def test(u1 : U, v1 : V)\n        \"u1 = #{u1} of #{U}, v1 = #{v1} of #{V}.\"\n      end\n\n      def self.self_test(other : self)\n        \"Value is #{other.u} and #{other.v}\"\n      end\n\n      @[Anyolite::WrapWithoutKeywords]\n      def +(other : GenericTest(U, V))\n        GenericTest(U, V).new(u: @u + other.u, v: @v + other.v)\n      end\n\n      def compare(other : GenericTest(U, V))\n        \"This has #{@u} and #{@v}, the other has #{other.u} and #{other.v}.\"\n      end\n    end\n\n    alias GTIntFloat = GenericTest(Int32, Float32)\n    alias GTIntInt = GenericTest(Int32, Int32)\n\n    property x : Int32 = 0\n\n    @@counter : Int32 = 0\n\n    @@magic_block_store : Anyolite::RbRef | Nil = nil\n\n    CONSTANT = \"Hello\"\n\n    CONSTANT_NOT_TO_WRAP = 123\n\n    def self.increase_counter\n      @@counter += 1\n    end\n\n    def self.reset_counter\n      @@counter = 0\n    end\n\n    def self.-(other_value : Int)\n      @@counter - other_value\n    end\n\n    def self.counter\n      return @@counter\n    end\n\n    def self.give_me_a_struct\n      s = TestStruct.new\n      s.value = 777\n      s.test = Test.new(999)\n      s\n    end\n\n    @[Anyolite::WrapWithoutKeywords]\n    def self.without_keywords(int : Int32)\n      int * 10\n    end\n\n    @[Anyolite::Rename(\"test\")]\n    def test_instance_method(int : Int32, bool : Bool, str : String, float : Float32 = 0.4f32)\n      @x += int\n      return [int, bool, str, float, @x]\n    end\n\n    def inspect(io : IO)\n      io.puts \"x is #{@x}\"\n    end\n\n    def inspect\n      \"x is #{@x}\"\n    end\n\n    def give_some_regex\n      /([\\S]+) [\\S]+/\n    end\n\n    def check_some_regex(r : Regex, str : String)\n      match_data = r.match(str)\n      if match_data\n        match_data[1]?\n      else\n        nil\n      end\n    end\n\n    @[Anyolite::StoreBlockArg]\n    def pass_a_ruby_block_to_another_method\n      block_arg = Anyolite.obtain_given_rb_block\n      Anyolite.call_rb_method(\"block_test\", block: block_arg, cast_to: String).to_i\n    end\n\n    # Would all trigger an error!\n    # def proc_test(pr : Int32 | (Int32 -> Int32))\n    #   pr.call(12)\n    # end\n\n    # def proc_test_2(pr : Proc(Int32))\n    #   pr.call(12)\n    # end\n\n    # def slice_test(s : Slice(Int32))\n\n    # end\n\n    # Gets called in Crystal and Ruby\n    def initialize(@x : Int32 = 0)\n      Test.increase_counter\n      puts \"Test object initialized with value #{@x}\"\n    end\n\n    # Gets called in Ruby\n    def rb_initialize(rb)\n      puts \"Object registered in Ruby\"\n    end\n\n    def ==(other)\n      (self.x == other.x)\n    end\n\n    # Gets called in Crystal unless program terminates early\n    def finalize\n      puts \"Finalized with value #{@x}\"\n    end\n\n    def +(other : Test)\n      Test.new(@x + other.x)\n    end\n\n    @[Anyolite::Exclude]\n    def do_not_wrap_this\n    end\n\n    def do_not_wrap_this_either\n    end\n\n    @[Anyolite::Exclude]\n    def self.do_not_wrap_this_class_method\n    end\n\n    def add(other : Test)\n      ret = self + other\n    end\n\n    def uint_test(arg : UInt8)\n      arg.to_s\n    end\n\n    @[Anyolite::ReturnNil]\n    def noreturn_test\n      puts \"This will still be executed.\"\n      [1]\n    end\n\n    def overload_test(arg : Int32 | String | Bool | Nil | Float32 | Test | TestEnum | GenericTest(Int32, Int32) = \"Default String\")\n      if arg.is_a?(Test)\n        \"A test object with x = #{arg.x}\"\n      elsif arg.is_a?(GenericTest(Int32, Int32))\n        \"A generic test\"\n      else\n        \"#{arg.inspect}\"\n      end\n    end\n\n    # TODO: This method does not work in MRI for some encoding reason - fix this if possible\n    # Also emojis in method names seem not to work in recent Crystal releases :(\n\n    {% unless flag?(:anyolite_implementation_ruby_3) %}\n      @[Anyolite::Rename(\"happy😀emoji😀test😀😀😀\")]\n      def happy_emoji_test(arg : Int32)\n        \"😀 for number #{arg}\"\n      end\n    {% end %}\n\n    def inside_mri?\n      Anyolite.implementation == :mri\n    end\n\n    def nilable_test(arg : Int32?)\n      \"Received argument #{arg.inspect}\"\n    end\n\n    @[Anyolite::Specialize([arg1 : Int32, arg2 : Float32, arg_req : Float32, arg_opt_1 : String | Test | Bool | TestEnum | GenericTest(Int32, Int32) = \"Cookies\", arg_opt_2 : Int32 = 32])]\n    @[Anyolite::WrapWithoutKeywords(4)]\n    def complicated_method(arg1, arg2, arg_req : Float32, arg_opt_1 : String | Test | Bool | TestEnum | GenericTest(Int32, Int32) = \"Cookies\", arg_opt_2 : Int32 = 32)\n      \"#{arg1} - #{arg2} - #{arg_req} - #{arg_opt_1.is_a?(Test) ? arg_opt_1.x : arg_opt_1} - #{arg_opt_2}\"\n    end\n\n    def returns_an_enum\n      TestEnum::Five\n    end\n\n    def returns_something_random\n      if rand < 0.5\n        3\n      else\n        \"Hello\"\n      end\n    end\n\n    def method_without_keywords(arg)\n      puts \"Argument is #{arg}\"\n    end\n\n    def output_this_and_struct(str : TestStruct)\n      \"#{@x} #{str.value} #{str.test.x}\"\n    end\n\n    def output_this_and_struct(i : Int32)\n      raise \"This should not be wrapped\"\n    end\n\n    @[Anyolite::Specialize([strvar : String, intvar : Int32, floatvar : Float64 = 0.123, strvarkw : String = \"nothing\", boolvar : Bool = true, othervar : Test = SomeModule::Test.new(17)])]\n    def keyword_test(strvar : String, intvar : Int32, floatvar : Float64 = 0.123, strvarkw : String = \"nothing\", boolvar : Bool = true, othervar : Test = Test.new(17))\n      \"str = #{strvar}, int = #{intvar}, float = #{floatvar.round(3)}, stringkw = #{strvarkw}, bool = #{boolvar}, other.x = #{othervar.x}\"\n    end\n\n    def keyword_test(whatever)\n      raise \"This should not be wrapped\"\n    end\n\n    def array_test(arg : Array(String | Int32) | String)\n      if arg.is_a?(String)\n        [arg]\n      else\n        arg.map { |element| element * 2 }\n      end\n    end\n\n    def hash_test(arg : Hash(String | Int32, String | SomeModule::Test | SomeModule::Test::UnderTest | SomeModule::Test::TestEnum))\n      arg.each do |key, value|\n        puts \"Crystal: #{key} -> #{value.is_a?(Test) ? \"Test with x = #{value.x}\" : value}\"\n      end\n\n      arg\n    end\n\n    @[Anyolite::StoreBlockArg]\n    def block_test\n      block_cache = Anyolite.obtain_given_rb_block\n      ret_value = Anyolite.call_rb_block(block_cache, [self], cast_to: Int32)\n      ret_value.to_s\n    end\n\n    @[Anyolite::AddBlockArg(2, String | Int32)]\n    def block_test_2\n      return_value = yield 1, 2\n      return_value.to_s\n    end\n\n    @[Anyolite::AddBlockArg(2, String)]\n    def self.block_test_3(arg : String)\n      return_value = yield \"Hello\", \"There\"\n      arg.to_s + \": \" + return_value.to_s\n    end\n\n    @[Anyolite::StoreBlockArg]\n    def block_store_test\n      if block_cache = Anyolite.obtain_given_rb_block\n        @@magic_block_store = block_cache\n        true\n      else\n        false\n      end\n    end\n\n    def block_store_call\n      if mbs = @@magic_block_store\n        ret_value = Anyolite.call_rb_block(mbs, [self], cast_to: Int32)\n        ret_value.to_s\n      else\n        false\n      end\n    end\n\n    def hash_return_test\n      {:hello => \"Nice\", :world => \"to see you!\", 3 => 15, \"test😊\" => :very_long_test_symbol}\n    end\n\n    private def private_method\n    end\n\n    def method_with_various_args(int_arg : Int)\n      \"Some args\"\n    end\n\n    def method_with_various_args\n      \"No args\"\n    end\n\n    @[Anyolite::Specialize([arg : Int | String])]\n    @[Anyolite::WrapWithoutKeywords]\n    def overload_cheat_test(arg : Int)\n      \"This was an int\"\n    end\n\n    @[Anyolite::Exclude]\n    def overload_cheat_test(arg : String)\n      \"This was a string\"\n    end\n\n    def float_test(arg : Float)\n      arg\n    end\n\n    def char_test(arg : Char)\n      arg\n    end\n\n    def bool_setter_test?(arg : Bool = true)\n      \"#{arg}\"\n    end\n\n    @[Anyolite::ForceKeywordArg]\n    def keyword_operator_arg?(arg : Float)\n      \"#{arg + 1.0}\"\n    end\n\n    def am_i_in_ruby?\n      Anyolite.referenced_in_ruby?(self)\n    end\n\n    @[Anyolite::WrapWithoutKeywords]\n    def response_test(name : String)\n      Anyolite.does_obj_respond_to(self, name)\n    end\n\n    @[Anyolite::WrapWithoutKeywords]\n    def class_response_test(name : String)\n      Anyolite.does_class_respond_to(self.class, name)\n    end\n\n    # This annotation will prevent the method from its global exclusion\n    @[Anyolite::Include]\n    def call_test\n      result = Anyolite.call_rb_method(:method_only_in_ruby, [\"Hello\", 3], cast_to: String)\n      result\n    end\n\n    def class_call_test\n      Anyolite.call_rb_method_of_class(self.class, :class_method_in_ruby, [\"World\", 4], cast_to: String)\n    end\n\n    @[Anyolite::WrapWithoutKeywords]\n    def why_would_you_do_this?(name : String)\n      result = Anyolite.call_rb_method(name, nil, cast_to: String | Int32 | Float32 | Bool | Nil)\n      result\n    end\n\n    def set_instance_variable_to_int(name : String, value : Int)\n      Anyolite.set_iv(self, name, value)\n    end\n\n    def get_instance_variable(name : String)\n      Anyolite.get_iv(self, name, cast_to: Int?)\n    end\n\n    def ref_test(str : String, ref : Anyolite::RbRef)\n      converted_arg = Anyolite.cast_to_crystal(ref, Int32?)\n      puts \"Reference: #{ref.value}\"\n      \"#{str} and a reference with #{converted_arg} were given.\"\n    end\n\n    def hash\n      213345\n    end\n\n    @[Anyolite::WrapWithoutKeywords]\n    def num_test(n : Number)\n      n\n    end\n\n    def ptr_return_test\n      pointerof(@x)\n    end\n\n    def ptr_arg_test(arg : Pointer(Int32))\n      arg.value += 1\n      arg.value\n    end\n\n    def ptr_star_arg_test(arg : Int32*)\n      arg.value += 3\n      arg.value\n    end\n\n    def test_int_or_ptr(arg : Int32 | Int32*)\n      if arg.is_a?(Int32)\n        arg\n      else\n        arg.value\n      end\n    end\n\n    @[Anyolite::ExcludeInstanceMethod(\"dup\")]\n    class TestChild < Test\n      property y : String\n\n      def initialize(x : Int32 = 0)\n        super(x: x)\n        @y = x.to_s\n      end\n    end\n\n    class ContentTest\n      def initialize(content : Array(SomeModule::Test))\n        @content = content\n      end\n\n      def content\n        @content\n      end\n    end\n\n    class NewContentTest < ContentTest\n      def initialize(content : Array(SomeModule::Test), more_content : Array(SomeModule::Test))\n        super(content: content)\n        @more_content = more_content\n      end\n\n      def more_content\n        @more_content\n      end\n    end\n\n    # Gets called in Ruby unless program crashes\n    def rb_finalize(rb)\n      puts \"Ruby destructor called for value #{@x}\"\n    end\n  end\n\n  class SubTest < SomeModule::Test\n  end\n\n  class Bla\n    def initialize\n    end\n  end\nend\n\n# For testing purposes, let's exclude this method globally (and include it again locally)\n@[Anyolite::ExcludeInstanceMethod(\"call_test\")]\nclass Object\nend\n\nmodule RPGTest\n  class Entity\n    property hp : Int32\n\n    def initialize(@hp : Int32)\n    end\n\n    def damage(diff : Int32)\n      @hp -= diff\n    end\n\n    def yell(sound : String, loud : Bool = false)\n      if loud\n        puts \"Entity yelled: #{sound.upcase}\"\n      else\n        puts \"Entity yelled: #{sound}\"\n      end\n    end\n\n    def absorb_hp_from(other : Entity)\n      @hp += other.hp\n      other.hp = 0\n    end\n  end\nend\n\nmacro load_test_module\n  Anyolite.wrap_module(rb, SomeModule, \"TestModule\")\n  Anyolite.wrap_module_function_with_keywords(rb, SomeModule, \"test_method\", SomeModule.test_method, [int : Int32 = 19, str : String])\n  Anyolite.wrap_class_property(rb, SomeModule, \"some_class_property\", SomeModule.some_class_property, Int32)\n  Anyolite.wrap_constant(rb, SomeModule, \"SOME_CONSTANT\", \"Smile! 😊\")\n  Anyolite.wrap(rb, SomeModule::Bla, under: SomeModule, verbose: true)\n  Anyolite.wrap(rb, SomeModule::TestStruct, under: SomeModule, verbose: true)\n  Anyolite.wrap(rb, SomeModule::Test, under: SomeModule, instance_method_exclusions: [:add], verbose: true)\n  Anyolite.wrap_instance_method(rb, SomeModule::Test, \"add\", add, [SomeModule::Test])\nend\n\n{% unless flag?(:anyolite_implementation_ruby_3) %}\n  Anyolite::RbInterpreter.create do |rb|\n    Anyolite.wrap(rb, RPGTest)\n\n    rb.load_script_from_file(\"examples/hp_example.rb\")\n  end\n\n  puts \"------------------------------\"\n\n  Anyolite::RbInterpreter.create do |rb|\n    Anyolite::Preloader.execute_bytecode_from_cache_or_file(rb, \"examples/bytecode_test.mrb\")\n    load_test_module()\n\n    rb.load_script_from_file(\"examples/test_framework.rb\")\n    rb.load_script_from_file(\"examples/test.rb\")\n  end\n{% else %}\n  Anyolite::RbInterpreter.create do |rb|\n    load_test_module()\n\n    Anyolite.wrap(rb, RPGTest)\n\n    Anyolite.eval(\"puts TestModule::Test.new(x: 12345).inspect\")\n\n    Anyolite.eval(\"require_relative './examples/bytecode_test.rb'\")\n\n    rb.load_script_from_file(\"examples/mri_test.rb\")\n\n    Anyolite.eval(\"puts TestModule::Test.new(x: 67890).inspect\")\n  end\n{% end %}\n"
  },
  {
    "path": "utility/mruby_build_config.rb",
    "content": "MRuby::Build.new do |conf|\r\n\r\n  if ENV['VisualStudioVersion'] || ENV['VSINSTALLDIR']\r\n    toolchain :visualcpp\r\n    # NOTE: If you want to use dynamic linking, change /MT to /MD instead\r\n    conf.cc.flags = [\"/nologo\", \"/W3\", \"/MT\", \"/O2\", \"/D_CRT_SECURE_NO_WARNINGS\"]\r\n  else\r\n    toolchain :gcc\r\n  end\r\n\r\n  conf.gembox 'default'\r\n\r\n  conf.gem :mgem => 'json'\r\n\r\n  conf.cc.flags << '-DMRB_UTF8_STRING -DMRB_INT64'\r\n\r\n  conf.build_dir = ENV[\"MRUBY_BUILD_DIR\"] || raise(\"MRUBY_BUILD_DIR undefined!\")\r\n\r\nend\r\n"
  }
]