diff --git a/.gitignore b/.gitignore index 088ba6b..b73286e 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,6 @@ Cargo.lock # These are backup files generated by rustfmt **/*.rs.bk + +# vscode +/.vscode/ diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..d085ce7 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "uwucode" +version = "0.1.0" +authors = ["Sai kumar Murali krishnan "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +colored = "2" \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..eb00a6c --- /dev/null +++ b/README.md @@ -0,0 +1,160 @@ + +
+

+ + Logo + + +

uwucode

+ +

+ A language based around egirl slang... +
+ Explore the docs » +
+
+ Report Bug / Request Feature +

+

+ + +# Table of Contents + +1. [What is uwucode?](#what-is-uwucode?) + 1. [Technical details](##technical-details) + +2. [Getting started](#getting-started) + 1. [Cargo requirements](##cargo-requirements) + 2. [Building](##build-instructions) + +3. [Writing with uwucode](#writing-with-uwucode) + 1. [Syntax](##syntax) + +4. [Future plans](#future-plans) + +5. [Contributing](#contributing) + +6. [License](#license) + +7. [Contact](#contact) + +8. [Extra](#extra) + 1. [Why?](#why?) + +9. [Acknowledgements](#acknowledgements) + + + +# What is uwucode? + +uwucode is an interpreted language written in Rust and consists of a nonsensical grammar for keywords, for instance uwu and owo are used for function and variable declarations respectively. While the language itself brings no unique features, the code used to interpret the language is good for beginners who wish to learn about language design. + +## Technical details + +TBA. + + +# Getting Started + +To get a local copy up and running follow these simple steps. + +## Cargo requirements + +The toml file contains information on any dependencies which are automatically fetched. + +## Build Instructions + +1. Use Cargo to build uwucode. + ``` + cargo build + ``` +2. Done. + + +# Writing with uwucode + +Note: uwucode output often contains characters (emojis and colored text) that may not be readable by some terminals. + +Upon building uwucode, one may open a REPL by passing in the argument repl as follows: +``` +uwucode repl +``` + +Alternatively, you can execute a file by using the open argument, supplying a file path, for instance: +``` +uwucode open example.uwu +``` + +## Syntax + +uwucode does not enforce typing and is interpreted. It is also independent of whitespace, which means indenting and spaces don't matter, but you must terminate the end of a statement. To define a variable, one would write: + +```owo var = value :3``` + +For the sake of reference, `:3` can be replaced with `;`. For defining functions, the keyword `owo` is utilised: + +``` +uwu square(x) {sugoi x*x;}; +``` + +There are more examples in the examples folder, however a list of all keywords include: + +* owo - let +* uwu - define +* sugoi - return +* nuzzles - if +* dab - elif +* rawr - else +* truwu - true +* fowose - false + +As of now, there are also three builtins: + +* quwuit - Takes in zero arguments, terminates the program. +* len - Returns the length of a string. +* dprint - Takes in one argument, prints the object. + +_For more examples, please refer to the [Documentation](https://github.com/Theorvolt/uwucode/doc)_ + + + +# Roadmap + +TBD, but there's a lot I have in mind. As of now, a few things that will come are: + +* while loops +* a more robust interpreter +* inputs +* basic logical operations +* compilation to bytecode + +# Contributing + +You forfeit any right to sue me should your sanity disappear while contributing to this code. Follow standard procedure if you wish to contribute, i.e fork->commit->pull request. You can also ask for a feature in the issues section. + + +# License + +Distributed under the MIT License. See `LICENSE` for more information. + + +# Contact + +Sai kumar Murali krishnan - [LinkedIn](https://www.linkedin.com/in/sai-kumar-murali-krishnan/) - theorvoltbusiness@gmail.com + +Project Link: [https://github.com/Theorvolt/uwucode](https://github.com/Theorvolt/uwucode) + + +# Extra + +## Why? + +The inspiration for this language came about since a friend of mine had made a relatively simple gag language primarily using the letter X [over here](https://github.com/lduck11007/x/). I also wanted to learn a bit about language design and manually designing a parser was a painful but worthwhile experience. As for the actual language itself, we found it a funny idea to write docstrings in uwu speak, something I intend to add in the future. Either way, this language serves no practical use but is a great way to break into language design. I highly recommend checking out the following: [https://interpreterbook.com/](https://interpreterbook.com/). + +# Acknowledgements + +* Thanks to Satya for inspiration on keywords for the language and designing the logo. +* +* + + diff --git a/examples/factorial.uwu b/examples/factorial.uwu new file mode 100644 index 0000000..ff7d086 --- /dev/null +++ b/examples/factorial.uwu @@ -0,0 +1,15 @@ +owo hehexd = 1; + +/* Comments can be written similar to Rust/C++. */ +uwu fact(lel) { + nuzzles (lel==hehexd) { + sugoi lel; + } + rawr { + sugoi lel*fact(lel-hehexd); + }; +}; + +/* One can use dprint to print function values */ +dprint(fact(4)); +dprint(fact(20)); \ No newline at end of file diff --git a/examples/fib.uwu b/examples/fib.uwu new file mode 100644 index 0000000..f204ca8 --- /dev/null +++ b/examples/fib.uwu @@ -0,0 +1,13 @@ + + +uwu fib(x) { + nuzzles (x<=1) { + sugoi x; + } + rawr { + sugoi fib(x-1)+fib(x-2); + }; +}; + +dprint(fib(10)); +dprint(fib(20)); /* This takes a very long time to evaluate. */ \ No newline at end of file diff --git a/examples/prints.uwu b/examples/prints.uwu new file mode 100644 index 0000000..c35b018 --- /dev/null +++ b/examples/prints.uwu @@ -0,0 +1,5 @@ + + +dprint("Hello world!"); + +dprint(2+5); \ No newline at end of file diff --git a/examples/rec_fizzbuzz.uwu b/examples/rec_fizzbuzz.uwu new file mode 100644 index 0000000..6058a55 --- /dev/null +++ b/examples/rec_fizzbuzz.uwu @@ -0,0 +1,29 @@ + +/* Not operational as of now. */ +uwu fizzbuzz(x) { + nuzzles (x==0) { + dprint("Done!"); + } + + rawr { + nuzzles (x%3==0) { + nuzzles (x%5==0) { + dprint("FizzBuzz"); + sugoi fizzbuzz(x-1); + } + + rawr { + dprint("Fizz"); + sugoi fizzbuzz(x-1); + }; + } + + rawr { + nuzzles (x%5==0) { + dprint("Buzz"); + sugoi fizzbuzz(x-1); + }; + }; + }; +}; +fizzbuzz(10); \ No newline at end of file diff --git a/images/uwucode_logo.svg b/images/uwucode_logo.svg new file mode 100644 index 0000000..ba15f38 --- /dev/null +++ b/images/uwucode_logo.svg @@ -0,0 +1 @@ +uwucode logo>>> \ No newline at end of file diff --git a/src/doc/.lock b/src/doc/.lock new file mode 100644 index 0000000..e69de29 diff --git a/src/doc/COPYRIGHT.txt b/src/doc/COPYRIGHT.txt new file mode 100644 index 0000000..af77776 --- /dev/null +++ b/src/doc/COPYRIGHT.txt @@ -0,0 +1,45 @@ +These documentation pages include resources by third parties. This copyright +file applies only to those resources. The following third party resources are +included, and carry their own copyright notices and license terms: + +* Fira Sans (FiraSans-Regular.woff, FiraSans-Medium.woff): + + Copyright (c) 2014, Mozilla Foundation https://mozilla.org/ + with Reserved Font Name Fira Sans. + + Copyright (c) 2014, Telefonica S.A. + + Licensed under the SIL Open Font License, Version 1.1. + See FiraSans-LICENSE.txt. + +* rustdoc.css, main.js, and playpen.js: + + Copyright 2015 The Rust Developers. + Licensed under the Apache License, Version 2.0 (see LICENSE-APACHE.txt) or + the MIT license (LICENSE-MIT.txt) at your option. + +* normalize.css: + + Copyright (c) Nicolas Gallagher and Jonathan Neal. + Licensed under the MIT license (see LICENSE-MIT.txt). + +* Source Code Pro (SourceCodePro-Regular.woff, SourceCodePro-Semibold.woff): + + Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), + with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark + of Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceCodePro-LICENSE.txt. + +* Source Serif Pro (SourceSerifPro-Regular.ttf.woff, + SourceSerifPro-Bold.ttf.woff, SourceSerifPro-It.ttf.woff): + + Copyright 2014 Adobe Systems Incorporated (http://www.adobe.com/), with + Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of + Adobe Systems Incorporated in the United States and/or other countries. + + Licensed under the SIL Open Font License, Version 1.1. + See SourceSerifPro-LICENSE.txt. + +This copyright file is intended to be distributed with rustdoc output. diff --git a/src/doc/FiraSans-LICENSE.txt b/src/doc/FiraSans-LICENSE.txt new file mode 100644 index 0000000..d444ea9 --- /dev/null +++ b/src/doc/FiraSans-LICENSE.txt @@ -0,0 +1,94 @@ +Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. +with Reserved Font Name < Fira >, + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/doc/FiraSans-Medium.woff b/src/doc/FiraSans-Medium.woff new file mode 100644 index 0000000..7d742c5 Binary files /dev/null and b/src/doc/FiraSans-Medium.woff differ diff --git a/src/doc/FiraSans-Regular.woff b/src/doc/FiraSans-Regular.woff new file mode 100644 index 0000000..d8e0363 Binary files /dev/null and b/src/doc/FiraSans-Regular.woff differ diff --git a/src/doc/LICENSE-APACHE.txt b/src/doc/LICENSE-APACHE.txt new file mode 100644 index 0000000..16fe87b --- /dev/null +++ b/src/doc/LICENSE-APACHE.txt @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/src/doc/LICENSE-MIT.txt b/src/doc/LICENSE-MIT.txt new file mode 100644 index 0000000..31aa793 --- /dev/null +++ b/src/doc/LICENSE-MIT.txt @@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/src/doc/README.html b/src/doc/README.html new file mode 100644 index 0000000..2085c5c --- /dev/null +++ b/src/doc/README.html @@ -0,0 +1,30 @@ + + + + + + + Docs + + + + + + + + +

Docs

+

This is the documentation for uwucode.

+

0.1 Introduction

+
+owo var_name = value;
+ + + + \ No newline at end of file diff --git a/src/doc/SourceCodePro-LICENSE.txt b/src/doc/SourceCodePro-LICENSE.txt new file mode 100644 index 0000000..0754257 --- /dev/null +++ b/src/doc/SourceCodePro-LICENSE.txt @@ -0,0 +1,93 @@ +Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/doc/SourceCodePro-Regular.woff b/src/doc/SourceCodePro-Regular.woff new file mode 100644 index 0000000..5576670 Binary files /dev/null and b/src/doc/SourceCodePro-Regular.woff differ diff --git a/src/doc/SourceCodePro-Semibold.woff b/src/doc/SourceCodePro-Semibold.woff new file mode 100644 index 0000000..ca972a1 Binary files /dev/null and b/src/doc/SourceCodePro-Semibold.woff differ diff --git a/src/doc/SourceSerifPro-Bold.ttf.woff b/src/doc/SourceSerifPro-Bold.ttf.woff new file mode 100644 index 0000000..ca25431 Binary files /dev/null and b/src/doc/SourceSerifPro-Bold.ttf.woff differ diff --git a/src/doc/SourceSerifPro-It.ttf.woff b/src/doc/SourceSerifPro-It.ttf.woff new file mode 100644 index 0000000..a287bbe Binary files /dev/null and b/src/doc/SourceSerifPro-It.ttf.woff differ diff --git a/src/doc/SourceSerifPro-LICENSE.md b/src/doc/SourceSerifPro-LICENSE.md new file mode 100644 index 0000000..22cb755 --- /dev/null +++ b/src/doc/SourceSerifPro-LICENSE.md @@ -0,0 +1,93 @@ +Copyright 2014-2018 Adobe (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe in the United States and/or other countries. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. + +This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/src/doc/SourceSerifPro-Regular.ttf.woff b/src/doc/SourceSerifPro-Regular.ttf.woff new file mode 100644 index 0000000..a3d55cf Binary files /dev/null and b/src/doc/SourceSerifPro-Regular.ttf.woff differ diff --git a/src/doc/ayu.css b/src/doc/ayu.css new file mode 100644 index 0000000..4e0a88a --- /dev/null +++ b/src/doc/ayu.css @@ -0,0 +1 @@ + body{background-color:#0f1419;color:#c5c5c5;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:white;}h1.fqn{border-bottom-color:#5c6773;}h1.fqn a{color:#fff;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod){border-bottom-color:#5c6773;}h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){border:none;}.in-band{background-color:#0f1419;}.invisible{background:rgba(0,0,0,0);}code{color:#ffb454;}h3>code,h4>code,h5>code{color:#e6e1cf;}pre>code{color:#e6e1cf;}span code{color:#e6e1cf;}.docblock a>code{color:#39AFD7 !important;}.docblock code,.docblock-short code{background-color:#191f26;}pre{color:#e6e1cf;background-color:#191f26;}.sidebar{background-color:#14191f;}.logo-container.rust-logo>img{filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);}*{scrollbar-color:#5c6773 transparent;}.sidebar{scrollbar-color:#5c6773 transparent;}::-webkit-scrollbar-track{background-color:transparent;}::-webkit-scrollbar-thumb{background-color:#5c6773;}.sidebar::-webkit-scrollbar-track{background-color:transparent;}.sidebar::-webkit-scrollbar-thumb{background-color:#5c6773;}.sidebar .current{background-color:transparent;color:#ffb44c;}.source .sidebar{background-color:#0f1419;}.sidebar .location{border-color:#000;background-color:#0f1419;color:#fff;}.sidebar-elems .location{color:#ff7733;}.sidebar-elems .location a{color:#fff;}.sidebar .version{border-bottom-color:#424c57;}.sidebar-title{border-top-color:#5c6773;border-bottom-color:#5c6773;}.block a:hover{background:transparent;color:#ffb44c;}.line-numbers span{color:#5c6773;}.line-numbers .line-highlighted{color:#708090;background-color:rgba(255,236,164,0.06);padding-right:4px;border-right:1px solid #ffb44c;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#5c6773;}.docblock table,.docblock table td,.docblock table th{border-color:#5c6773;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#c5c5c5;}.content .highlighted{color:#000 !important;background-color:#c6afb3;}.content .highlighted a,.content .highlighted span{color:#000 !important;}.content .highlighted{background-color:#c6afb3;}.search-results a{color:#0096cf;}.search-results a span.desc{color:#c5c5c5;}.content .stability::before{color:#ccc;}.content span.foreigntype,.content a.foreigntype{color:#ef57ff;}.content span.union,.content a.union{color:#98a01c;}.content span.constant,.content a.constant,.content span.static,.content a.static{color:#6380a0;}.content span.primitive,.content a.primitive{color:#32889b;}.content span.traitalias,.content a.traitalias{color:#57d399;}.content span.keyword,.content a.keyword{color:#de5249;}.content span.externcrate,.content span.mod,.content a.mod{color:#acccf9;}.content span.struct,.content a.struct{color:#ffa0a5;}.content span.enum,.content a.enum{color:#99e0c9;}.content span.trait,.content a.trait{color:#39AFD7;}.content span.type,.content a.type{color:#cfbcf5;}.content span.fn,.content a.fn,.content span.method,.content a.method,.content span.tymethod,.content a.tymethod,.content .fnname{color:#fdd687;}.content span.attr,.content a.attr,.content span.derive,.content a.derive,.content span.macro,.content a.macro{color:#a37acc;}pre.rust .comment{color:#788797;}pre.rust .doccomment{color:#a1ac88;}nav:not(.sidebar){border-bottom-color:#424c57;}nav.main .current{border-top-color:#5c6773;border-bottom-color:#5c6773;}nav.main .separator{border:1px solid #5c6773;}a{color:#c5c5c5;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.stability a{color:#39AFD7;}.collapse-toggle{color:#999;}#crate-search{color:#c5c5c5;background-color:#141920;box-shadow:0 0 0 1px #424c57,0 0 0 2px transparent;border-color:#424c57;}.search-input{color:#ffffff;background-color:#141920;box-shadow:0 0 0 1px #424c57,0 0 0 2px transparent;transition:box-shadow 150ms ease-in-out;}#crate-search+.search-input:focus{box-shadow:0 0 0 1px #148099,0 0 0 2px transparent;}.search-focus:disabled{color:#929292;}.module-item .stab{color:#000;}.stab.unstable,.stab.deprecated,.stab.portability{color:#c5c5c5;background:#314559 !important;border-style:none !important;border-radius:4px;padding:3px 6px 3px 6px;}.stab.portability>code{color:#e6e1cf;background-color:transparent;}#help>div{background:#14191f;box-shadow:0px 6px 20px 0px black;border:none;border-radius:4px;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:#788797;}.line-numbers :target{background-color:transparent;}pre.rust .number,pre.rust .string{color:#b8cc52;}pre.rust .kw,pre.rust .kw-2,pre.rust .prelude-ty,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .op,pre.rust .lifetime{color:#ff7733;}pre.rust .macro,pre.rust .macro-nonterminal{color:#a37acc;}pre.rust .question-mark{color:#ff9011;}pre.rust .self{color:#36a3d9;font-style:italic;}pre.rust .attribute{color:#e6e1cf;}pre.rust .attribute .ident,pre.rust .attribute .op{color:#e6e1cf;}.example-wrap>pre.line-number{color:#5c67736e;border:none;}a.test-arrow{font-size:100%;color:#788797;border-radius:4px;background-color:rgba(57,175,215,0.09);}a.test-arrow:hover{background-color:rgba(57,175,215,0.368);color:#c5c5c5;}.toggle-label{color:#999;}:target>code,:target>.in-band{background:rgba(255,236,164,0.06);border-right:3px solid rgba(255,180,76,0.85);}pre.compile_fail{border-left:2px solid rgba(255,0,0,.4);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.4);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#39AFD7;}.tooltip .tooltiptext{background-color:#314559;color:#c5c5c5;border:1px solid #5c6773;}.tooltip .tooltiptext::after{border-color:transparent #314559 transparent transparent;}.notable-traits-tooltiptext{background-color:#314559;border-color:#5c6773;}#titles>div.selected{background-color:#141920 !important;border-bottom:1px solid #ffb44c !important;border-top:none;}#titles>div:not(.selected){background-color:transparent !important;border:none;}#titles>div:hover{border-bottom:1px solid rgba(242,151,24,0.3);}#titles>div>div.count{color:#888;}.content .highlighted.mod,.content .highlighted.externcrate{}.search-input:focus{}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{}.content .highlighted.trait{}.content span.struct,.content a.struct,.block a.current.struct{}#titles>div:hover,#titles>div.selected{}.content .highlighted.traitalias{}.content span.type,.content a.type,.block a.current.type{}.content span.union,.content a.union,.block a.current.union{}.content .highlighted.foreigntype{}pre.rust .lifetime{}.content .highlighted.primitive{}.content .highlighted.constant,.content .highlighted.static{}.stab.unstable{}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){}.content span.enum,.content a.enum,.block a.current.enum{}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{}.content span.keyword,.content a.keyword,.block a.current.keyword{}pre.rust .comment{}.content .highlighted.enum{}.content .highlighted.struct{}.content .highlighted.keyword{}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{}pre.rust .kw{}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{}pre.rust .doccomment{}.stab.deprecated{}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{}.stab.portability{}.content .highlighted.union{}.content span.primitive,.content a.primitive,.block a.current.primitive{}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{}.content .highlighted.type{}pre.rust .kw-2,pre.rust .prelude-ty{}.content span.trait,.content a.trait,.block a.current.trait{}@media (max-width:700px){.sidebar-menu{background-color:#14191f;border-bottom-color:#5c6773;border-right-color:#5c6773;}.sidebar-elems{background-color:#14191f;border-right-color:#5c6773;}#sidebar-filler{background-color:#14191f;border-bottom-color:#5c6773;}}kbd{color:#c5c5c5;background-color:#314559;border-color:#5c6773;border-bottom-color:#5c6773;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,.help-button{border-color:#5c6773;background-color:#0f1419;color:#fff;}#theme-picker>img,#settings-menu>img{filter:invert(100);}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,.help-button:hover,.help-button:focus{border-color:#e0e0e0;}#theme-choices{border-color:#5c6773;background-color:#0f1419;}#theme-choices>button:not(:first-child){border-top-color:#5c6773;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:rgba(110,110,110,0.33);}@media (max-width:700px){#theme-picker{background:#0f1419;}}#all-types{background-color:#14191f;}#all-types:hover{background-color:rgba(70,70,70,0.33);}.search-results td span.alias{color:#c5c5c5;}.search-results td span.grey{color:#999;}#sidebar-toggle{background-color:#14191f;}#sidebar-toggle:hover{background-color:rgba(70,70,70,0.33);}#source-sidebar{background-color:#14191f;}#source-sidebar>.title{color:#fff;border-bottom-color:#5c6773;}div.files>a:hover,div.name:hover{background-color:#14191f;color:#ffb44c;}div.files>.selected{background-color:#14191f;color:#ffb44c;}.setting-line>.title{border-bottom-color:#5c6773;}input:checked+.slider{background-color:#ffb454 !important;} \ No newline at end of file diff --git a/src/doc/brush.svg b/src/doc/brush.svg new file mode 100644 index 0000000..ea266e8 --- /dev/null +++ b/src/doc/brush.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/doc/dark.css b/src/doc/dark.css new file mode 100644 index 0000000..5c15577 --- /dev/null +++ b/src/doc/dark.css @@ -0,0 +1 @@ +body{background-color:#353535;color:#ddd;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:#ddd;}h1.fqn{border-bottom-color:#d2d2d2;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#d2d2d2;}.in-band{background-color:#353535;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#2A2A2A;}pre{background-color:#2A2A2A;}.sidebar{background-color:#505050;}.logo-container.rust-logo>img{filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff)}*{scrollbar-color:rgb(64,65,67) #717171;}.sidebar{scrollbar-color:rgba(32,34,37,.6) transparent;}::-webkit-scrollbar-track{background-color:#717171;}::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar::-webkit-scrollbar-track{background-color:#717171;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(32,34,37,.6);}.sidebar .current{background-color:#333;}.source .sidebar{background-color:#353535;}.sidebar .location{border-color:#fff;background:#575757;color:#DDD;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#444;}.line-numbers span{color:#3B91E2;}.line-numbers .line-highlighted{background-color:#0a042f !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#DDD;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#ddd;}.content .highlighted{color:#eee !important;background-color:#616161;}.content .highlighted a,.content .highlighted span{color:#eee !important;}.content .highlighted.trait{background-color:#013191;}.content .highlighted.traitalias{background-color:#013191;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.mod{background-color:#803a1b;}.content .highlighted.externcrate{background-color:#396bac;}.content .highlighted.enum{background-color:#5b4e68;}.content .highlighted.struct{background-color:#194e9f;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#4950ed;}.content .highlighted.type{background-color:#38902c;}.content .highlighted.foreigntype{background-color:#b200d6;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#217d1c;}.content .highlighted.constant,.content .highlighted.static{background-color:#0063cc;}.content .highlighted.primitive{background-color:#00708a;}.content .highlighted.keyword{background-color:#884719;}.content .stability::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#82b089;}.content span.struct,.content a.struct,.block a.current.struct{color:#2dbfb8;}.content span.type,.content a.type,.block a.current.type{color:#ff7f00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#dd7de8;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#09bd00;}.content span.union,.content a.union,.block a.current.union{color:#a6ae37;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#82a5c9;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#43aec7;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#bda000;}.content span.trait,.content a.trait,.block a.current.trait{color:#b78cf2;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#b397da;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#2BAB63;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8d8d8b;}pre.rust .doccomment{color:#8ca375;}nav:not(.sidebar){border-bottom-color:#4e4e4e;}nav.main .current{border-top-color:#eee;border-bottom-color:#eee;}nav.main .separator{border-color:#eee;}a{color:#ddd;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.stability a{color:#D2991D;}a.test-arrow{color:#dedede;}.collapse-toggle{color:#999;}#crate-search{color:#111;background-color:#f0f0f0;border-color:#000;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input{color:#111;background-color:#f0f0f0;box-shadow:0 0 0 1px #000,0 0 0 2px transparent;}.search-input:focus{border-color:#008dfd;}.search-focus:disabled{background-color:#c5c4c4;}#crate-search+.search-input:focus{box-shadow:0 0 8px 4px #078dd8;}.module-item .stab{color:#ddd;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;color:#2f2f2f;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;color:#2f2f2f;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;color:#2f2f2f;}.stab.portability>code{color:#ddd;}#help>div{background:#4d4d4d;border-color:#bfbfbf;}#help dt{border-color:#bfbfbf;background:rgba(0,0,0,0);color:black;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:#ddd;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#ab8ac1;}pre.rust .kw-2,pre.rust .prelude-ty{color:#769acb;}pre.rust .number,pre.rust .string{color:#83a300;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#ee6868;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#d97f26;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#4a4949;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background-color:#494a3d;border-right:3px solid #bb7410;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.8);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.8);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.8);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.8);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;border-color:#000;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#111;border-color:#777;}#titles>div:not(.selected){background-color:#252525;border-top-color:#252525;}#titles>div:hover,#titles>div.selected{border-top-color:#0089ff;}#titles>div>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#505050;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#505050;border-right-color:#000;}#sidebar-filler{background-color:#505050;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,.help-button{border-color:#e0e0e0;background:#f0f0f0;color:#000;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,.help-button:hover,.help-button:focus{border-color:#ffb900;}#theme-choices{border-color:#e0e0e0;background-color:#353535;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#4e4e4e;}@media (max-width:700px){#theme-picker{background:#f0f0f0;}}#all-types{background-color:#505050;}#all-types:hover{background-color:#606060;}.search-results td span.alias{color:#fff;}.search-results td span.grey{color:#ccc;}#sidebar-toggle{background-color:#565656;}#sidebar-toggle:hover{background-color:#676767;}#source-sidebar{background-color:#565656;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#444;}div.files>.selected{background-color:#333;}.setting-line>.title{border-bottom-color:#ddd;} \ No newline at end of file diff --git a/src/doc/down-arrow.svg b/src/doc/down-arrow.svg new file mode 100644 index 0000000..35437e7 --- /dev/null +++ b/src/doc/down-arrow.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/doc/favicon-16x16.png b/src/doc/favicon-16x16.png new file mode 100644 index 0000000..7cfe6c1 Binary files /dev/null and b/src/doc/favicon-16x16.png differ diff --git a/src/doc/favicon-32x32.png b/src/doc/favicon-32x32.png new file mode 100644 index 0000000..5109c1d Binary files /dev/null and b/src/doc/favicon-32x32.png differ diff --git a/src/doc/favicon.svg b/src/doc/favicon.svg new file mode 100644 index 0000000..8b34b51 --- /dev/null +++ b/src/doc/favicon.svg @@ -0,0 +1,24 @@ + + + + + diff --git a/src/doc/implementors/core/clone/trait.Clone.js b/src/doc/implementors/core/clone/trait.Clone.js new file mode 100644 index 0000000..69bace6 --- /dev/null +++ b/src/doc/implementors/core/clone/trait.Clone.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["token"] = [{"text":"impl Clone for Token","synthetic":false,"types":[]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/src/doc/implementors/core/cmp/trait.PartialEq.js b/src/doc/implementors/core/cmp/trait.PartialEq.js new file mode 100644 index 0000000..136ad63 --- /dev/null +++ b/src/doc/implementors/core/cmp/trait.PartialEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["token"] = [{"text":"impl PartialEq<Token> for Token","synthetic":false,"types":[]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/src/doc/implementors/core/fmt/trait.Debug.js b/src/doc/implementors/core/fmt/trait.Debug.js new file mode 100644 index 0000000..ed0173e --- /dev/null +++ b/src/doc/implementors/core/fmt/trait.Debug.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["token"] = [{"text":"impl Debug for Token","synthetic":false,"types":[]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/src/doc/implementors/core/marker/trait.Freeze.js b/src/doc/implementors/core/marker/trait.Freeze.js new file mode 100644 index 0000000..9563416 --- /dev/null +++ b/src/doc/implementors/core/marker/trait.Freeze.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["token"] = [{"text":"impl Freeze for Token","synthetic":true,"types":[]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/src/doc/implementors/core/marker/trait.Send.js b/src/doc/implementors/core/marker/trait.Send.js new file mode 100644 index 0000000..ea79197 --- /dev/null +++ b/src/doc/implementors/core/marker/trait.Send.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["token"] = [{"text":"impl Send for Token","synthetic":true,"types":[]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/src/doc/implementors/core/marker/trait.StructuralPartialEq.js b/src/doc/implementors/core/marker/trait.StructuralPartialEq.js new file mode 100644 index 0000000..b7d7cbb --- /dev/null +++ b/src/doc/implementors/core/marker/trait.StructuralPartialEq.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["token"] = [{"text":"impl StructuralPartialEq for Token","synthetic":false,"types":[]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/src/doc/implementors/core/marker/trait.Sync.js b/src/doc/implementors/core/marker/trait.Sync.js new file mode 100644 index 0000000..b01fc70 --- /dev/null +++ b/src/doc/implementors/core/marker/trait.Sync.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["token"] = [{"text":"impl Sync for Token","synthetic":true,"types":[]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/src/doc/implementors/core/marker/trait.Unpin.js b/src/doc/implementors/core/marker/trait.Unpin.js new file mode 100644 index 0000000..3ab3748 --- /dev/null +++ b/src/doc/implementors/core/marker/trait.Unpin.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["token"] = [{"text":"impl Unpin for Token","synthetic":true,"types":[]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/src/doc/implementors/std/panic/trait.RefUnwindSafe.js b/src/doc/implementors/std/panic/trait.RefUnwindSafe.js new file mode 100644 index 0000000..dd32e90 --- /dev/null +++ b/src/doc/implementors/std/panic/trait.RefUnwindSafe.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["token"] = [{"text":"impl RefUnwindSafe for Token","synthetic":true,"types":[]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/src/doc/implementors/std/panic/trait.UnwindSafe.js b/src/doc/implementors/std/panic/trait.UnwindSafe.js new file mode 100644 index 0000000..81e61d5 --- /dev/null +++ b/src/doc/implementors/std/panic/trait.UnwindSafe.js @@ -0,0 +1,3 @@ +(function() {var implementors = {}; +implementors["token"] = [{"text":"impl UnwindSafe for Token","synthetic":true,"types":[]}]; +if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file diff --git a/src/doc/light.css b/src/doc/light.css new file mode 100644 index 0000000..41a6074 --- /dev/null +++ b/src/doc/light.css @@ -0,0 +1 @@ + body{background-color:white;color:black;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){color:black;}h1.fqn{border-bottom-color:#D5D5D5;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod){border-bottom-color:#DDDDDD;}.in-band{background-color:white;}.invisible{background:rgba(0,0,0,0);}.docblock code,.docblock-short code{background-color:#F5F5F5;}pre{background-color:#F5F5F5;}.sidebar{background-color:#F1F1F1;}*{scrollbar-color:rgba(36,37,39,0.6) #e6e6e6;}.sidebar{scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;}.logo-container.rust-logo>img{}::-webkit-scrollbar-track{background-color:#ecebeb;}::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar::-webkit-scrollbar-track{background-color:#dcdcdc;}.sidebar::-webkit-scrollbar-thumb{background-color:rgba(36,37,39,0.6);}.sidebar .current{background-color:#fff;}.source .sidebar{background-color:#fff;}.sidebar .location{border-color:#000;background-color:#fff;color:#333;}.sidebar .version{border-bottom-color:#DDD;}.sidebar-title{border-top-color:#777;border-bottom-color:#777;}.block a:hover{background:#F5F5F5;}.line-numbers span{color:#c67e2d;}.line-numbers .line-highlighted{background-color:#f6fdb0 !important;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom-color:#ddd;}.docblock table,.docblock table td,.docblock table th{border-color:#ddd;}.content .method .where,.content .fn .where,.content .where.fmt-newline{color:#4E4C4C;}.content .highlighted{color:#000 !important;background-color:#ccc;}.content .highlighted a,.content .highlighted span{color:#000 !important;}.content .highlighted.trait{background-color:#c7b6ff;}.content .highlighted.traitalias{background-color:#c7b6ff;}.content .highlighted.mod,.content .highlighted.externcrate{background-color:#afc6e4;}.content .highlighted.enum{background-color:#b4d1b9;}.content .highlighted.struct{background-color:#e7b1a0;}.content .highlighted.union{background-color:#b7bd49;}.content .highlighted.fn,.content .highlighted.method,.content .highlighted.tymethod{background-color:#c6afb3;}.content .highlighted.type{background-color:#ffc891;}.content .highlighted.foreigntype{background-color:#f5c4ff;}.content .highlighted.attr,.content .highlighted.derive,.content .highlighted.macro{background-color:#8ce488;}.content .highlighted.constant,.content .highlighted.static{background-color:#c3e0ff;}.content .highlighted.primitive{background-color:#9aecff;}.content .highlighted.keyword{background-color:#f99650;}.content .stability::before{color:#ccc;}.content span.enum,.content a.enum,.block a.current.enum{color:#508157;}.content span.struct,.content a.struct,.block a.current.struct{color:#ad448e;}.content span.type,.content a.type,.block a.current.type{color:#ba5d00;}.content span.foreigntype,.content a.foreigntype,.block a.current.foreigntype{color:#cd00e2;}.content span.attr,.content a.attr,.block a.current.attr,.content span.derive,.content a.derive,.block a.current.derive,.content span.macro,.content a.macro,.block a.current.macro{color:#068000;}.content span.union,.content a.union,.block a.current.union{color:#767b27;}.content span.constant,.content a.constant,.block a.current.constant,.content span.static,.content a.static,.block a.current.static{color:#546e8a;}.content span.primitive,.content a.primitive,.block a.current.primitive{color:#2c8093;}.content span.externcrate,.content span.mod,.content a.mod,.block a.current.mod{color:#4d76ae;}.content span.trait,.content a.trait,.block a.current.trait{color:#7c5af3;}.content span.traitalias,.content a.traitalias,.block a.current.traitalias{color:#6841f1;}.content span.fn,.content a.fn,.block a.current.fn,.content span.method,.content a.method,.block a.current.method,.content span.tymethod,.content a.tymethod,.block a.current.tymethod,.content .fnname{color:#9a6e31;}.content span.keyword,.content a.keyword,.block a.current.keyword{color:#de5249;}pre.rust .comment{color:#8E908C;}pre.rust .doccomment{color:#4D4D4C;}nav:not(.sidebar){border-bottom-color:#e0e0e0;}nav.main .current{border-top-color:#000;border-bottom-color:#000;}nav.main .separator{border:1px solid #000;}a{color:#000;}.docblock:not(.type-decl) a:not(.srclink):not(.test-arrow),.docblock-short a:not(.srclink):not(.test-arrow),.stability a{color:#3873AD;}a.test-arrow{color:#f5f5f5;}.collapse-toggle{color:#999;}#crate-search{color:#555;background-color:white;border-color:#e0e0e0;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input{color:#555;background-color:white;box-shadow:0 0 0 1px #e0e0e0,0 0 0 2px transparent;}.search-input:focus{border-color:#66afe9;}.search-focus:disabled{background-color:#e6e6e6;}#crate-search+.search-input:focus{box-shadow:0 0 8px #078dd8;}.module-item .stab{color:#000;}.stab.unstable{background:#FFF5D6;border-color:#FFC600;}.stab.deprecated{background:#F3DFFF;border-color:#7F0087;}.stab.portability{background:#C4ECFF;border-color:#7BA5DB;}.stab.portability>code{color:#000;}#help>div{background:#e9e9e9;border-color:#bfbfbf;}.since{color:grey;}tr.result span.primitive::after,tr.result span.keyword::after{color:black;}.line-numbers :target{background-color:transparent;}pre.rust .kw{color:#8959A8;}pre.rust .kw-2,pre.rust .prelude-ty{color:#4271AE;}pre.rust .number,pre.rust .string{color:#718C00;}pre.rust .self,pre.rust .bool-val,pre.rust .prelude-val,pre.rust .attribute,pre.rust .attribute .ident{color:#C82829;}pre.rust .macro,pre.rust .macro-nonterminal{color:#3E999F;}pre.rust .lifetime{color:#B76514;}pre.rust .question-mark{color:#ff9011;}.example-wrap>pre.line-number{border-color:#c7c7c7;}a.test-arrow{background-color:rgba(78,139,202,0.2);}a.test-arrow:hover{background-color:#4e8bca;}.toggle-label{color:#999;}:target>code,:target>.in-band{background:#FDFFD3;border-right:3px solid #ffb44c;}pre.compile_fail{border-left:2px solid rgba(255,0,0,.5);}pre.compile_fail:hover,.information:hover+pre.compile_fail{border-left:2px solid #f00;}pre.should_panic{border-left:2px solid rgba(255,0,0,.5);}pre.should_panic:hover,.information:hover+pre.should_panic{border-left:2px solid #f00;}pre.ignore{border-left:2px solid rgba(255,142,0,.6);}pre.ignore:hover,.information:hover+pre.ignore{border-left:2px solid #ff9200;}.tooltip.compile_fail{color:rgba(255,0,0,.5);}.information>.compile_fail:hover{color:#f00;}.tooltip.should_panic{color:rgba(255,0,0,.5);}.information>.should_panic:hover{color:#f00;}.tooltip.ignore{color:rgba(255,142,0,.6);}.information>.ignore:hover{color:#ff9200;}.search-failed a{color:#0089ff;}.tooltip .tooltiptext{background-color:#000;color:#fff;}.tooltip .tooltiptext::after{border-color:transparent black transparent transparent;}.notable-traits-tooltiptext{background-color:#eee;border-color:#999;}#titles>div:not(.selected){background-color:#e6e6e6;border-top-color:#e6e6e6;}#titles>div:hover,#titles>div.selected{border-top-color:#0089ff;}#titles>div>div.count{color:#888;}@media (max-width:700px){.sidebar-menu{background-color:#F1F1F1;border-bottom-color:#e0e0e0;border-right-color:#e0e0e0;}.sidebar-elems{background-color:#F1F1F1;border-right-color:#000;}#sidebar-filler{background-color:#F1F1F1;border-bottom-color:#e0e0e0;}}kbd{color:#000;background-color:#fafbfc;border-color:#d1d5da;border-bottom-color:#c6cbd1;box-shadow-color:#c6cbd1;}#theme-picker,#settings-menu,.help-button{border-color:#e0e0e0;background-color:#fff;}#theme-picker:hover,#theme-picker:focus,#settings-menu:hover,#settings-menu:focus,.help-button:hover,.help-button:focus{border-color:#717171;}#theme-choices{border-color:#ccc;background-color:#fff;}#theme-choices>button:not(:first-child){border-top-color:#e0e0e0;}#theme-choices>button:hover,#theme-choices>button:focus{background-color:#eee;}@media (max-width:700px){#theme-picker{background:#fff;}}#all-types{background-color:#fff;}#all-types:hover{background-color:#f9f9f9;}.search-results td span.alias{color:#000;}.search-results td span.grey{color:#999;}#sidebar-toggle{background-color:#F1F1F1;}#sidebar-toggle:hover{background-color:#E0E0E0;}#source-sidebar{background-color:#F1F1F1;}#source-sidebar>.title{border-bottom-color:#ccc;}div.files>a:hover,div.name:hover{background-color:#E0E0E0;}div.files>.selected{background-color:#fff;}.setting-line>.title{border-bottom-color:#D5D5D5;} \ No newline at end of file diff --git a/src/doc/main.js b/src/doc/main.js new file mode 100644 index 0000000..612d268 --- /dev/null +++ b/src/doc/main.js @@ -0,0 +1,7 @@ +if(!String.prototype.startsWith){String.prototype.startsWith=function(searchString,position){position=position||0;return this.indexOf(searchString,position)===position}}if(!String.prototype.endsWith){String.prototype.endsWith=function(suffix,length){var l=length||this.length;return this.indexOf(suffix,l-suffix.length)!==-1}}if(!DOMTokenList.prototype.add){DOMTokenList.prototype.add=function(className){if(className&&!hasClass(this,className)){if(this.className&&this.className.length>0){this.className+=" "+className}else{this.className=className}}}}if(!DOMTokenList.prototype.remove){DOMTokenList.prototype.remove=function(className){if(className&&this.className){this.className=(" "+this.className+" ").replace(" "+className+" "," ").trim()}}}function getSearchInput(){return document.getElementsByClassName("search-input")[0]}function getSearchElement(){return document.getElementById("search")}function focusSearchBar(){getSearchInput().focus()}function defocusSearchBar(){getSearchInput().blur()}(function(){"use strict";var itemTypes=["mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","primitive","associatedtype","constant","associatedconstant","union","foreigntype","keyword","existential","attr","derive","traitalias"];var disableShortcuts=getCurrentValue("rustdoc-disable-shortcuts")==="true";var search_input=getSearchInput();var searchTimeout=null;var toggleAllDocsId="toggle-all-docs";var currentTab=0;var mouseMovedAfterSearch=true;var titleBeforeSearch=document.title;function clearInputTimeout(){if(searchTimeout!==null){clearTimeout(searchTimeout);searchTimeout=null}}function getPageId(){if(window.location.hash){var tmp=window.location.hash.replace(/^#/,"");if(tmp.length>0){return tmp}}return null}function showSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){addClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];if(sidebar){addClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(!filler){var div=document.createElement("div");div.id="sidebar-filler";sidebar.appendChild(div)}}var themePickers=document.getElementsByClassName("theme-picker");if(themePickers&&themePickers.length>0){themePickers[0].style.display="none"}}function hideSidebar(){var elems=document.getElementsByClassName("sidebar-elems")[0];if(elems){removeClass(elems,"show-it")}var sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"mobile");var filler=document.getElementById("sidebar-filler");if(filler){filler.remove()}document.getElementsByTagName("body")[0].style.marginTop="";var themePickers=document.getElementsByClassName("theme-picker");if(themePickers&&themePickers.length>0){themePickers[0].style.display=null}}function showSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(main,"hidden");removeClass(search,"hidden");mouseMovedAfterSearch=false}function hideSearchResults(search){if(search===null||typeof search==='undefined'){search=getSearchElement()}addClass(search,"hidden");removeClass(main,"hidden")}var TY_PRIMITIVE=itemTypes.indexOf("primitive");var TY_KEYWORD=itemTypes.indexOf("keyword");function getQueryStringParams(){var params={};window.location.search.substring(1).split("&").map(function(s){var pair=s.split("=");params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function isHidden(elem){return elem.offsetHeight===0}var main=document.getElementById("main");var savedHash="";function handleHashes(ev){var elem;var search=getSearchElement();if(ev!==null&&search&&!hasClass(search,"hidden")&&ev.newURL){hideSearchResults(search);var hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(hash,"","?search=#"+hash)}elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}if(savedHash!==window.location.hash){savedHash=window.location.hash;if(savedHash.length===0){return}elem=document.getElementById(savedHash.slice(1));if(!elem||!isHidden(elem)){return}var parent=elem.parentNode;if(parent&&hasClass(parent,"impl-items")){onEachLazy(parent.getElementsByClassName("collapsed"),function(e){if(e.parentNode===parent){e.click();return true}});if(isHidden(elem)){if(hasClass(parent.lastElementChild,"collapse-toggle")){parent.lastElementChild.click()}}}}}function highlightSourceLines(match,ev){if(typeof match==="undefined"){hideSidebar();match=window.location.hash.match(/^#?(\d+)(?:-(\d+))?$/)}if(!match){return}var from=parseInt(match[1],10);var to=from;if(typeof match[2]!=="undefined"){to=parseInt(match[2],10)}if(to0){collapseDocs(collapses[0],"show")}}}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!="undefined"){return ev.key}var c=ev.charCode||ev.keyCode;if(c==27){return"Escape"}return String.fromCharCode(c)}function getHelpElement(){buildHelperPopup();return document.getElementById("help")}function displayHelp(display,ev,help){help=help?help:getHelpElement();if(display===true){if(hasClass(help,"hidden")){ev.preventDefault();removeClass(help,"hidden");addClass(document.body,"blur")}}else if(hasClass(help,"hidden")===false){ev.preventDefault();addClass(help,"hidden");removeClass(document.body,"blur")}}function handleEscape(ev){var help=getHelpElement();var search=getSearchElement();if(hasClass(help,"hidden")===false){displayHelp(false,ev,help)}else if(hasClass(search,"hidden")===false){clearInputTimeout();ev.preventDefault();hideSearchResults(search);document.title=titleBeforeSearch}defocusSearchBar()}function handleShortcut(ev){if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts===true){return}if(document.activeElement.tagName==="INPUT"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":displayHelp(false,ev);ev.preventDefault();focusSearchBar();break;case"+":case"-":ev.preventDefault();toggleAllDocs();break;case"?":displayHelp(true,ev);break}}}function findParentElement(elem,tagName){do{if(elem&&elem.tagName===tagName){return elem}elem=elem.parentNode}while(elem);return null}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function resetMouseMoved(ev){mouseMovedAfterSearch=true}document.addEventListener("mousemove",resetMouseMoved);var handleSourceHighlight=(function(){var prev_line_id=0;var set_fragment=function(name){var x=window.scrollX,y=window.scrollY;if(browserSupportsHistoryApi()){history.replaceState(null,null,"#"+name);highlightSourceLines()}else{location.replace("#"+name)}window.scrollTo(x,y)};return function(ev){var cur_line_id=parseInt(ev.target.id,10);ev.preventDefault();if(ev.shiftKey&&prev_line_id){if(prev_line_id>cur_line_id){var tmp=prev_line_id;prev_line_id=cur_line_id;cur_line_id=tmp}set_fragment(prev_line_id+"-"+cur_line_id)}else{prev_line_id=cur_line_id;set_fragment(cur_line_id)}}}());document.addEventListener("click",function(ev){if(hasClass(ev.target,"help-button")){displayHelp(true,ev)}else if(hasClass(ev.target,"collapse-toggle")){collapseDocs(ev.target,"toggle")}else if(hasClass(ev.target.parentNode,"collapse-toggle")){collapseDocs(ev.target.parentNode,"toggle")}else if(ev.target.tagName==="SPAN"&&hasClass(ev.target.parentNode,"line-numbers")){handleSourceHighlight(ev)}else if(hasClass(getHelpElement(),"hidden")===false){var help=getHelpElement();var is_inside_help_popup=ev.target!==help&&help.contains(ev.target);if(is_inside_help_popup===false){addClass(help,"hidden");removeClass(document.body,"blur")}}else{var a=findParentElement(ev.target,"A");if(a&&a.hash){expandSection(a.hash.replace(/^#/,""))}}});(function(){var x=document.getElementsByClassName("version-selector");if(x.length>0){x[0].onchange=function(){var i,match,url=document.location.href,stripped="",len=rootPath.match(/\.\.\//g).length+1;for(i=0;i-1){var obj=searchIndex[results[i].id];obj.lev=results[i].lev;if(isType!==true||obj.type){var res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=obj.displayPath+obj.name;obj.fullPath+="|"+obj.ty;obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}}return out}function sortResults(results,isType){var ar=[];for(var entry in results){if(hasOwnProperty(results,entry)){ar.push(results[entry])}}results=ar;var i;var nresults=results.length;for(i=0;ib?+1:-1)}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}if((aaa.item.ty===TY_PRIMITIVE&&bbb.item.ty!==TY_KEYWORD)||(aaa.item.ty===TY_KEYWORD&&bbb.item.ty!==TY_PRIMITIVE)){return-1}if((bbb.item.ty===TY_PRIMITIVE&&aaa.item.ty!==TY_PRIMITIVE)||(bbb.item.ty===TY_KEYWORD&&aaa.item.ty!==TY_KEYWORD)){return 1}a=(aaa.item.desc==="");b=(bbb.item.desc==="");if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});var length=results.length;for(i=0;i"));return{name:val.substring(0,val.indexOf("<")),generics:values.split(/\s*,\s*/),}}return{name:val,generics:[],}}function getObjectFromId(id){if(typeof id==="number"){return searchIndex[id]}return{'name':id}}function checkGenerics(obj,val){var lev_distance=MAX_LEV_DISTANCE+1;if(val.generics.length>0){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var total=0;var done=0;var vlength=val.generics.length;for(var y=0;yGENERICS_DATA&&obj[GENERICS_DATA].length>=val.generics.length){var elems=obj[GENERICS_DATA].slice(0);var allFound=true;for(var y=0;allFound===true&&yGENERICS_DATA&&obj[GENERICS_DATA].length!==0){var tmp_lev=checkGenerics(obj,val);if(tmp_lev<=MAX_LEV_DISTANCE){return tmp_lev}}else{return 0}}if(literalSearch===true){if(obj.length>GENERICS_DATA&&obj[GENERICS_DATA].length>0){var length=obj[GENERICS_DATA].length;for(x=0;xGENERICS_DATA&&obj[GENERICS_DATA].length>0){var olength=obj[GENERICS_DATA].length;for(x=0;x0){var length=obj.type[INPUTS_DATA].length;for(var i=0;iOUTPUT_DATA){var ret=obj.type[OUTPUT_DATA];if(typeof ret[0]==="string"){ret=[ret]}for(var x=0;xlength){return MAX_LEV_DISTANCE+1}for(var i=0;ilength){break}var lev_total=0;var aborted=false;for(var x=0;xMAX_LEV_DISTANCE){aborted=true;break}lev_total+=lev}if(aborted===false){ret_lev=Math.min(ret_lev,Math.round(lev_total/clength))}}return ret_lev}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER)return true;if(filter===type)return true;var name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function generateId(ty){if(ty.parent&&ty.parent.name){return itemTypes[ty.ty]+ty.path+ty.parent.name+ty.name}return itemTypes[ty.ty]+ty.path+ty.name}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,desc:item.desc,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,}}function handleAliases(ret,query,filterCrates){var aliases=[];var crateAliases=[];var i;if(filterCrates!==undefined){if(ALIASES[filterCrates]&&ALIASES[filterCrates][query.search]){for(i=0;iMAX_RESULTS){ret.others.pop()}};onEach(aliases,pushFunc);onEach(crateAliases,pushFunc)}var nSearchWords=searchWords.length;var i;var ty;var fullId;var returned;var in_args;if((val.charAt(0)==="\""||val.charAt(0)==="'")&&val.charAt(val.length-1)===val.charAt(0)){val=extractGenerics(val.substr(1,val.length-2));for(i=0;i")>-1){var trimmer=function(s){return s.trim()};var parts=val.split("->").map(trimmer);var input=parts[0];var inputs=input.split(",").map(trimmer).sort();for(i=0;i1?paths.length-1:1);var lev;for(j=0;j1){lev=checkPath(contains,paths[paths.length-1],ty);if(lev>MAX_LEV_DISTANCE){continue}else if(lev>0){lev_add=lev/10}}returned=MAX_LEV_DISTANCE+1;in_args=MAX_LEV_DISTANCE+1;var index=-1;lev=MAX_LEV_DISTANCE+1;fullId=generateId(ty);if(searchWords[j].indexOf(split[i])>-1||searchWords[j].indexOf(val)>-1||searchWords[j].replace(/_/g,"").indexOf(val)>-1){if(typePassesFilter(typeFilter,ty.ty)&&results[fullId]===undefined){index=searchWords[j].replace(/_/g,"").indexOf(val)}}if((lev=levenshtein(searchWords[j],val))<=MAX_LEV_DISTANCE){if(typePassesFilter(typeFilter,ty.ty)===false){lev=MAX_LEV_DISTANCE+1}else{lev+=1}}in_args=findArg(ty,valGenerics,false,typeFilter);returned=checkReturned(ty,valGenerics,false,typeFilter);lev+=lev_add;if(lev>0&&val.length>3&&searchWords[j].indexOf(val)>-1){if(val.length<6){lev-=1}else{lev=0}}if(in_args<=MAX_LEV_DISTANCE){if(results_in_args[fullId]===undefined){results_in_args[fullId]={id:j,index:index,lev:in_args,}}results_in_args[fullId].lev=Math.min(results_in_args[fullId].lev,in_args)}if(returned<=MAX_LEV_DISTANCE){if(results_returned[fullId]===undefined){results_returned[fullId]={id:j,index:index,lev:returned,}}results_returned[fullId].lev=Math.min(results_returned[fullId].lev,returned)}if(index!==-1||lev<=MAX_LEV_DISTANCE){if(index!==-1&&paths.length<2){lev=0}if(results[fullId]===undefined){results[fullId]={id:j,index:index,lev:lev,}}results[fullId].lev=Math.min(results[fullId].lev,lev)}}}var ret={"in_args":sortResults(results_in_args,true),"returned":sortResults(results_returned,true),"others":sortResults(results),};handleAliases(ret,query,filterCrates);return ret}function validateResult(name,path,keys,parent){for(var i=0;i-1||path.indexOf(keys[i])>-1||(parent!==undefined&&parent.name!==undefined&&parent.name.toLowerCase().indexOf(keys[i])>-1)||levenshtein(name,keys[i])<=MAX_LEV_DISTANCE)){return false}}return true}function getQuery(raw){var matches,type,query;query=raw;matches=query.match(/^(fn|mod|struct|enum|trait|type|const|macro)\s*:\s*/i);if(matches){type=matches[1].replace(/^const$/,"constant");query=query.substring(matches[0].length)}return{raw:raw,query:query,type:type,id:query+type}}function initSearchNav(){var hoverTimeout;var click_func=function(e){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}var dst=e.target.getElementsByTagName("a");if(dst.length<1){return}dst=dst[0];if(window.location.pathname===dst.pathname){hideSearchResults();document.location.href=dst.href}};var mouseover_func=function(e){if(mouseMovedAfterSearch){var el=e.target;while(el.tagName!=="TR"){el=el.parentNode}clearTimeout(hoverTimeout);hoverTimeout=setTimeout(function(){onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){removeClass(i_e,"highlighted")})});addClass(el,"highlighted")},20)}};onEachLazy(document.getElementsByClassName("search-results"),function(e){onEachLazy(e.getElementsByClassName("result"),function(i_e){i_e.onclick=click_func;i_e.onmouseover=mouseover_func})});search_input.onkeydown=function(e){var actives=[[],[],[]];var current=0;onEachLazy(document.getElementById("results").childNodes,function(e){onEachLazy(e.getElementsByClassName("highlighted"),function(h_e){actives[current].push(h_e)});current+=1});if(e.which===38){if(!actives[currentTab].length||!actives[currentTab][0].previousElementSibling){return}addClass(actives[currentTab][0].previousElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted");e.preventDefault()}else if(e.which===40){if(!actives[currentTab].length){var results=document.getElementById("results").childNodes;if(results.length>0){var res=results[currentTab].getElementsByClassName("result");if(res.length>0){addClass(res[0],"highlighted")}}}else if(actives[currentTab][0].nextElementSibling){addClass(actives[currentTab][0].nextElementSibling,"highlighted");removeClass(actives[currentTab][0],"highlighted")}e.preventDefault()}else if(e.which===13){if(actives[currentTab].length){document.location.href=actives[currentTab][0].getElementsByTagName("a")[0].href}}else if(e.which===9){if(e.shiftKey){printTab(currentTab>0?currentTab-1:2)}else{printTab(currentTab>1?0:currentTab+1)}e.preventDefault()}else if(e.which===16){}else if(actives[currentTab].length>0){removeClass(actives[currentTab][0],"highlighted")}}}function buildHrefAndPath(item){var displayPath;var href;var type=itemTypes[item.ty];var name=item.name;var path=item.path;if(type==="mod"){displayPath=path+"::";href=rootPath+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="primitive"||type==="keyword"){displayPath="";href=rootPath+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=rootPath+name+"/index.html"}else if(item.parent!==undefined){var myparent=item.parent;var anchor="#"+type+"."+name;var parentType=itemTypes[myparent.ty];var pageType=parentType;var pageName=myparent.name;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){var splitPath=item.path.split("::");var enumName=splitPath.pop();path=splitPath.join("::");displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="#variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}href=rootPath+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html"+anchor}else{displayPath=item.path+"::";href=rootPath+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href]}function escape(content){var h1=document.createElement("h1");h1.textContent=content;return h1.innerHTML}function pathSplitter(path){var tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}function addTab(array,query,display){var extraStyle="";if(display===false){extraStyle=" style=\"display: none;\""}var output="";var duplicates={};var length=0;if(array.length>0){output="";array.forEach(function(item){var name,type;name=item.name;type=itemTypes[item.ty];if(item.is_alias!==true){if(duplicates[item.fullPath]){return}duplicates[item.fullPath]=true}length+=1;output+=""});output+="
"+""+(item.is_alias===true?(""+item.alias+"  - see "):"")+item.displayPath+""+name+""+""+""+escape(item.desc)+" 
"}else{output="
No results :(
"+"Try on DuckDuckGo?

"+"Or try looking in one of these:
"}return[output,length]}function makeTabHeader(tabNb,text,nbElems){if(currentTab===tabNb){return"
"+text+"
("+nbElems+")
"}return"
"+text+"
("+nbElems+")
"}function showResults(results){var search=getSearchElement();if(results.others.length===1&&getCurrentValue("rustdoc-go-to-only-result")==="true"&&(!search.firstChild||search.firstChild.innerText!==getSearchLoadingText())){var elem=document.createElement("a");elem.href=results.others[0].href;elem.style.display="none";document.body.appendChild(elem);elem.click();return}var query=getQuery(search_input.value);currentResults=query.id;var ret_others=addTab(results.others,query);var ret_in_args=addTab(results.in_args,query,false);var ret_returned=addTab(results.returned,query,false);var output="

Results for "+escape(query.query)+(query.type?" (type: "+escape(query.type)+")":"")+"

"+"
"+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
"+ret_others[0]+ret_in_args[0]+ret_returned[0]+"
";search.innerHTML=output;showSearchResults(search);var tds=search.getElementsByTagName("td");var td_width=0;if(tds.length>0){td_width=tds[0].offsetWidth}var width=search.offsetWidth-40-td_width;onEachLazy(search.getElementsByClassName("desc"),function(e){e.style.width=width+"px"});initSearchNav();var elems=document.getElementById("titles").childNodes;elems[0].onclick=function(){printTab(0)};elems[1].onclick=function(){printTab(1)};elems[2].onclick=function(){printTab(2)};printTab(currentTab)}function execSearch(query,searchWords,filterCrates){function getSmallest(arrays,positions,notDuplicates){var start=null;for(var it=0;itpositions[it]&&(start===null||start>arrays[it][positions[it]].lev)&&!notDuplicates[arrays[it][positions[it]].fullPath]){start=arrays[it][positions[it]].lev}}return start}function mergeArrays(arrays){var ret=[];var positions=[];var notDuplicates={};for(var x=0;xpositions[x]&&arrays[x][positions[x]].lev===smallest&&!notDuplicates[arrays[x][positions[x]].fullPath]){ret.push(arrays[x][positions[x]]);notDuplicates[arrays[x][positions[x]].fullPath]=true;positions[x]+=1}}}return ret}var queries=query.raw.split(",");var results={"in_args":[],"returned":[],"others":[],};for(var i=0;i1){return{"in_args":mergeArrays(results.in_args),"returned":mergeArrays(results.returned),"others":mergeArrays(results.others),}}return{"in_args":results.in_args[0],"returned":results.returned[0],"others":results.others[0],}}function getFilterCrates(){var elem=document.getElementById("crate-search");if(elem&&elem.value!=="All crates"&&hasOwnProperty(rawSearchIndex,elem.value)){return elem.value}return undefined}function search(e,forced){var params=getQueryStringParams();var query=getQuery(search_input.value.trim());if(e){e.preventDefault()}if(query.query.length===0){return}if(forced!==true&&query.id===currentResults){if(query.query.length>0){putBackSearch(search_input)}return}document.title="Results for "+query.query+" - Rust";if(browserSupportsHistoryApi()){if(!history.state&&!params.search){history.pushState(query,"","?search="+encodeURIComponent(query.raw))}else{history.replaceState(query,"","?search="+encodeURIComponent(query.raw))}}var filterCrates=getFilterCrates();showResults(execSearch(query,index,filterCrates))}function buildIndex(rawSearchIndex){searchIndex=[];var searchWords=[];var i;var currentIndex=0;for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}var crateSize=0;searchWords.push(crate);searchIndex.push({crate:crate,ty:1,name:crate,path:"",desc:rawSearchIndex[crate].doc,type:null,});currentIndex+=1;var items=rawSearchIndex[crate].i;var paths=rawSearchIndex[crate].p;var aliases=rawSearchIndex[crate].a;var len=paths.length;for(i=0;i0){search_input.value=params.search;search(e)}else{search_input.value="";hideSearchResults()}})}search()}index=buildIndex(rawSearchIndex);startSearch();if(rootPath==="../"||rootPath==="./"){var sidebar=document.getElementsByClassName("sidebar-elems")[0];if(sidebar){var div=document.createElement("div");div.className="block crate";div.innerHTML="

Crates

";var ul=document.createElement("ul");div.appendChild(ul);var crates=[];for(var crate in rawSearchIndex){if(!hasOwnProperty(rawSearchIndex,crate)){continue}crates.push(crate)}crates.sort();for(var i=0;i"+""+"
"+code.outerHTML+"
";list.appendChild(display)}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}function labelForToggleButton(sectionIsCollapsed){if(sectionIsCollapsed){return"+"}return"\u2212"}function onEveryMatchingChild(elem,className,func){if(elem&&className&&func){var length=elem.childNodes.length;var nodes=elem.childNodes;for(var i=0;i"+labelForToggleButton(sectionIsCollapsed)+"
]";return toggle}function createToggle(toggle,otherMessage,fontSize,extraClass,show){var span=document.createElement("span");span.className="toggle-label";if(show){span.style.display="none"}if(!otherMessage){span.innerHTML=" Expand description"}else{span.innerHTML=otherMessage}if(fontSize){span.style.fontSize=fontSize}var mainToggle=toggle.cloneNode(true);mainToggle.appendChild(span);var wrapper=document.createElement("div");wrapper.className="toggle-wrapper";if(!show){addClass(wrapper,"collapsed");var inner=mainToggle.getElementsByClassName("inner");if(inner&&inner.length>0){inner[0].innerHTML="+"}}if(extraClass){addClass(wrapper,extraClass)}wrapper.appendChild(mainToggle);return wrapper}(function(){var toggles=document.getElementById(toggleAllDocsId);if(toggles){toggles.onclick=toggleAllDocs}var toggle=createSimpleToggle(false);var hideMethodDocs=getCurrentValue("rustdoc-auto-hide-method-docs")==="true";var hideImplementors=getCurrentValue("rustdoc-auto-collapse-implementors")!=="false";var pageId=getPageId();var func=function(e){var next=e.nextElementSibling;if(!next){return}if(hasClass(next,"docblock")===true||(hasClass(next,"stability")===true&&hasClass(next.nextElementSibling,"docblock")===true)){var newToggle=toggle.cloneNode(true);insertAfter(newToggle,e.childNodes[e.childNodes.length-1]);if(hideMethodDocs===true&&hasClass(e,"method")===true){collapseDocs(newToggle,"hide",pageId)}}};var funcImpl=function(e){var next=e.nextElementSibling;if(next&&hasClass(next,"docblock")){next=next.nextElementSibling}if(!next){return}if(hasClass(e,"impl")&&(next.getElementsByClassName("method").length>0||next.getElementsByClassName("associatedconstant").length>0)){var newToggle=toggle.cloneNode(true);insertAfter(newToggle,e.childNodes[e.childNodes.length-1]);if(hideImplementors===true&&e.parentNode.id==="implementors-list"){collapseDocs(newToggle,"hide",pageId)}}};onEachLazy(document.getElementsByClassName("method"),func);onEachLazy(document.getElementsByClassName("associatedconstant"),func);onEachLazy(document.getElementsByClassName("impl"),funcImpl);var impl_call=function(){};if(hideMethodDocs===true){impl_call=function(e,newToggle){if(e.id.match(/^impl(?:-\d+)?$/)===null){if(hasClass(e,"impl")===true){collapseDocs(newToggle,"hide",pageId)}}}}var newToggle=document.createElement("a");newToggle.href="javascript:void(0)";newToggle.className="collapse-toggle hidden-default collapsed";newToggle.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items";function toggleClicked(){if(hasClass(this,"collapsed")){removeClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("hidden"),function(x){if(hasClass(x,"content")===false){removeClass(x,"hidden");addClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(false)+"] Hide undocumented items"}else{addClass(this,"collapsed");onEachLazy(this.parentNode.getElementsByClassName("x"),function(x){if(hasClass(x,"content")===false){addClass(x,"hidden");removeClass(x,"x")}},true);this.innerHTML="["+labelForToggleButton(true)+"] Show hidden undocumented items"}}onEachLazy(document.getElementsByClassName("impl-items"),function(e){onEachLazy(e.getElementsByClassName("associatedconstant"),func);var hiddenElems=e.getElementsByClassName("hidden");var needToggle=false;var hlength=hiddenElems.length;for(var i=0;i"+getSearchLoadingText()+"";showSearchResults(search)}var sidebar_menu=document.getElementsByClassName("sidebar-menu")[0];if(sidebar_menu){sidebar_menu.onclick=function(){var sidebar=document.getElementsByClassName("sidebar")[0];if(hasClass(sidebar,"mobile")===true){hideSidebar()}else{showSidebar()}}}window.onresize=function(){hideSidebar()};if(main){onEachLazy(main.getElementsByClassName("loading-content"),function(e){e.remove()});onEachLazy(main.childNodes,function(e){if(e.tagName==="H2"||e.tagName==="H3"){var nextTagName=e.nextElementSibling.tagName;if(nextTagName=="H2"||nextTagName=="H3"){e.nextElementSibling.style.display="flex"}else{e.nextElementSibling.style.display="block"}}})}function enableSearchInput(){if(search_input){search_input.removeAttribute('disabled')}}window.addSearchOptions=function(crates){var elem=document.getElementById("crate-search");if(!elem){enableSearchInput();return}var crates_text=[];if(Object.keys(crates).length>1){for(var crate in crates){if(hasOwnProperty(crates,crate)){crates_text.push(crate)}}}crates_text.sort(function(a,b){var lower_a=a.toLowerCase();var lower_b=b.toLowerCase();if(lower_alower_b){return 1}return 0});var savedCrate=getCurrentValue("rustdoc-saved-filter-crate");for(var i=0;i"
"+x[0]+"
"+x[1]+"
").join("");var div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

Keyboard Shortcuts

"+shortcuts+"
";var infos=["Prefix searches with a type followed by a colon (e.g., fn:) to \ + restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \ + enum, trait, type, macro, \ + and const.","Search functions by type signature (e.g., vec -> usize or \ + * -> vec)","Search multiple things at once by splitting your query with comma (e.g., \ + str,u8 or String,struct:Vec,test)","You can look for items with an exact name by putting double quotes around \ + your request: \"string\"","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

"+x+"

").join("");var div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

Search Tricks

"+infos;container.appendChild(div_shortcuts);container.appendChild(div_infos);popup.appendChild(container);insertAfter(popup,getSearchElement());buildHelperPopup=function(){}}onHashChange(null);window.onhashchange=onHashChange}());window.onunload=function(){} \ No newline at end of file diff --git a/src/doc/main/all.html b/src/doc/main/all.html new file mode 100644 index 0000000..fb783ed --- /dev/null +++ b/src/doc/main/all.html @@ -0,0 +1,6 @@ +List of all items in this crate + +

[] + + List of all items

\ No newline at end of file diff --git a/src/doc/main/index.html b/src/doc/main/index.html new file mode 100644 index 0000000..f7902f1 --- /dev/null +++ b/src/doc/main/index.html @@ -0,0 +1,4 @@ +main - Rust + +

[][src]Crate main

\ No newline at end of file diff --git a/src/doc/main/sidebar-items.js b/src/doc/main/sidebar-items.js new file mode 100644 index 0000000..48333d3 --- /dev/null +++ b/src/doc/main/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({}); \ No newline at end of file diff --git a/src/doc/normalize.css b/src/doc/normalize.css new file mode 100644 index 0000000..6d692b5 --- /dev/null +++ b/src/doc/normalize.css @@ -0,0 +1,2 @@ + /*! normalize.css v3.0.0 | MIT License | git.io/normalize */ +html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}audio,canvas,progress,video{display:inline-block;vertical-align:baseline}audio:not([controls]){display:none;height:0}[hidden],template{display:none}a{background:transparent}a:active,a:hover{outline:0}abbr[title]{border-bottom:1px dotted}b,strong{font-weight:bold}dfn{font-style:italic}h1{font-size:2em;margin:.67em 0}mark{background:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sup{top:-0.5em}sub{bottom:-0.25em}img{border:0}svg:not(:root){overflow:hidden}figure{margin:1em 40px}hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}pre{overflow:auto}code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}button,input,optgroup,select,textarea{color:inherit;font:inherit;margin:0}button{overflow:visible}button,select{text-transform:none}button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}button[disabled],html input[disabled]{cursor:default}button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}input{line-height:normal}input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}input[type="number"]::-webkit-inner-spin-button,input[type="number"]::-webkit-outer-spin-button{height:auto}input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}legend{border:0;padding:0}textarea{overflow:auto}optgroup{font-weight:bold}table{border-collapse:collapse;border-spacing:0}td,th{padding:0} \ No newline at end of file diff --git a/src/doc/noscript.css b/src/doc/noscript.css new file mode 100644 index 0000000..351b41c --- /dev/null +++ b/src/doc/noscript.css @@ -0,0 +1 @@ +#main>h2+div,#main>h2+h3,#main>h3+div{display:block;}.loading-content{display:none;}#main>h2+div,#main>h3+div{display:block;}#main>h2+h3{display:flex;} \ No newline at end of file diff --git a/src/doc/rust-logo.png b/src/doc/rust-logo.png new file mode 100644 index 0000000..74b4bd6 Binary files /dev/null and b/src/doc/rust-logo.png differ diff --git a/src/doc/rustdoc.css b/src/doc/rustdoc.css new file mode 100644 index 0000000..2aacd01 --- /dev/null +++ b/src/doc/rustdoc.css @@ -0,0 +1 @@ + @font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular.woff") format('woff');}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:400;src:local('Source Serif Pro'),url("SourceSerifPro-Regular.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:italic;font-weight:400;src:local('Source Serif Pro Italic'),url("SourceSerifPro-It.ttf.woff") format('woff');}@font-face {font-family:'Source Serif Pro';font-style:normal;font-weight:700;src:local('Source Serif Pro Bold'),url("SourceSerifPro-Bold.ttf.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular.woff") format('woff');}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold.woff") format('woff');}*{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;}html{content:"";}@media (prefers-color-scheme:light){html{content:"light";}}@media (prefers-color-scheme:dark){html{content:"dark";}}body{font:16px/1.4 "Source Serif Pro",serif;margin:0;position:relative;padding:10px 15px 20px 15px;-webkit-font-feature-settings:"kern","liga";-moz-font-feature-settings:"kern","liga";font-feature-settings:"kern","liga";}h1{font-size:1.5em;}h2{font-size:1.4em;}h3{font-size:1.3em;}h1,h2,h3:not(.impl):not(.method):not(.type):not(.tymethod):not(.notable),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){font-weight:500;margin:20px 0 15px 0;padding-bottom:6px;}h1.fqn{border-bottom:1px dashed;margin-top:0;}h1.fqn>.in-band>a:hover{text-decoration:underline;}h2,h3:not(.impl):not(.method):not(.type):not(.tymethod),h4:not(.method):not(.type):not(.tymethod):not(.associatedconstant){border-bottom:1px solid;}h3.impl,h3.method,h4.method,h3.type,h4.type,h4.associatedconstant{flex-basis:100%;font-weight:600;margin-top:16px;margin-bottom:10px;position:relative;}h3.impl,h3.method,h3.type{padding-left:15px;}h1,h2,h3,h4,.sidebar,a.source,.search-input,.content table :not(code)>a,.collapse-toggle,div.item-list .out-of-band,#source-sidebar,#sidebar-toggle{font-family:"Fira Sans",sans-serif;}.content ul.crate a.crate{font:16px/1.6 "Fira Sans";}ol,ul{padding-left:25px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.6em;}p{margin:0 0 .6em 0;}summary{outline:none;}code,pre,a.test-arrow{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.1em;}.docblock pre code,.docblock-short pre code,.docblock code.spotlight{padding:0;}.docblock code.spotlight :last-child{padding-bottom:0.6em;}pre{padding:14px;}.source .content pre{padding:20px;}img{max-width:100%;}li{position:relative;}.source .content{margin-top:50px;max-width:none;overflow:visible;margin-left:0px;min-width:70em;}nav.sub{font-size:16px;text-transform:uppercase;}.sidebar{width:200px;position:fixed;left:0;top:0;bottom:0;overflow:auto;}*{scrollbar-width:initial;}.sidebar{scrollbar-width:thin;}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;}.sidebar .block>ul>li{margin-right:-10px;}.content,nav{max-width:960px;}.hidden{display:none !important;}.logo-container{height:100px;width:100px;position:relative;margin:20px auto;display:block;margin-top:10px;}.logo-container>img{max-width:100px;max-height:100px;position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);display:block;}.sidebar .location{border:1px solid;font-size:17px;margin:30px 10px 20px 10px;text-align:center;word-wrap:break-word;}.sidebar .version{font-size:15px;text-align:center;border-bottom:1px solid;overflow-wrap:break-word;word-wrap:break-word;word-break:break-word;}.location:empty{border:none;}.location a:first-child{font-weight:500;}.block{padding:0;margin-bottom:14px;}.block h2,.block h3{margin-top:0;margin-bottom:8px;text-align:center;}.block ul,.block li{margin:0 10px;padding:0;list-style:none;}.block a{display:block;text-overflow:ellipsis;overflow:hidden;line-height:15px;padding:7px 5px;font-size:14px;font-weight:300;transition:border 500ms ease-out;}.sidebar-title{border-top:1px solid;border-bottom:1px solid;text-align:center;font-size:17px;margin-bottom:5px;}.sidebar-links{margin-bottom:15px;}.sidebar-links>a{padding-left:10px;width:100%;}.sidebar-menu{display:none;}.content{padding:15px 0;}.source .content pre.rust{white-space:pre;overflow:auto;padding-left:0;}.rustdoc:not(.source) .example-wrap{display:inline-flex;margin-bottom:10px;position:relative;}.example-wrap{width:100%;}.example-wrap>pre.line-number{overflow:initial;border:1px solid;border-top-left-radius:5px;border-bottom-left-radius:5px;padding:13px 8px;text-align:right;}.rustdoc:not(.source) .example-wrap>pre.rust{width:100%;overflow-x:auto;}.rustdoc:not(.source) .example-wrap>pre{margin:0;}#search{margin-left:230px;position:relative;}#results{position:absolute;right:0;left:0;overflow:auto;}#results>table{width:100%;table-layout:fixed;margin-bottom:40px;}.content pre.line-numbers{float:left;border:none;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;}.line-numbers span{cursor:pointer;}.docblock-short p{display:inline;}.docblock-short.nowrap{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;}.docblock-short p{overflow:hidden;text-overflow:ellipsis;margin:0;}.docblock code,.docblock-short code{white-space:pre-wrap;}.docblock h1,.docblock h2,.docblock h3,.docblock h4,.docblock h5{border-bottom:1px solid;}#main>.docblock h1{font-size:1.3em;}#main>.docblock h2{font-size:1.15em;}#main>.docblock h3,#main>.docblock h4,#main>.docblock h5{font-size:1em;}#main>h2+div,#main>h2+h3,#main>h3+div{display:none;flex-wrap:wrap;}.docblock h1{font-size:1em;}.docblock h2{font-size:0.95em;}.docblock h3,.docblock h4,.docblock h5{font-size:0.9em;}.docblock{margin-left:24px;position:relative;}.content .out-of-band{float:right;font-size:23px;margin:0px;padding:0px;font-weight:normal;}h3.impl>.out-of-band{font-size:21px;}h4.method>.out-of-band{font-size:19px;}h4>code,h3>code,.invisible>code{max-width:calc(100% - 41px);display:block;}.invisible{width:100%;display:inline-block;}.content .in-band{margin:0px;padding:0px;}.in-band>code{display:inline-block;}#main{position:relative;}#main>.since{top:inherit;font-family:"Fira Sans",sans-serif;}.content table:not(.table-display){border-spacing:0 5px;}.content td{vertical-align:top;}.content td:first-child{padding-right:20px;}.content td p:first-child{margin-top:0;}.content td h1,.content td h2{margin-left:0;font-size:1.1em;}.content tr:first-child td{border-top:0;}.docblock table{margin:.5em 0;width:calc(100% - 2px);border:1px dashed;}.docblock table td{padding:.5em;border:1px dashed;}.docblock table th{padding:.5em;text-align:left;border:1px solid;}.fields+table{margin-bottom:1em;}.content .item-list{list-style-type:none;padding:0;}.content .multi-column{-moz-column-count:5;-moz-column-gap:2.5em;-webkit-column-count:5;-webkit-column-gap:2.5em;column-count:5;column-gap:2.5em;}.content .multi-column li{width:100%;display:inline-block;}.content .method{font-size:1em;position:relative;}.content .method .where,.content .fn .where,.content .where.fmt-newline{display:block;font-size:0.8em;}.content .methods>div:not(.notable-traits){margin-left:40px;margin-bottom:15px;}.content .docblock>.impl-items{margin-left:20px;margin-top:-34px;}.content .docblock>.impl-items>h4{border-bottom:0;}.content .docblock>.impl-items .table-display{margin:0;}.content .docblock>.impl-items table td{padding:0;}.toggle-wrapper.marg-left>.collapse-toggle{left:-24px;}.content .docblock>.impl-items .table-display,.impl-items table td{border:none;}.content .stability code{font-size:90%;}.content .stability{position:relative;margin-left:33px;margin-top:-13px;}.sub-variant>div>.stability{margin-top:initial;}.content .stability::before{content:'⬑';font-size:25px;position:absolute;top:-6px;left:-19px;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{margin-left:20px;}.content .impl-items .docblock,.content .impl-items .stability{margin-bottom:.6em;}.content .impl-items>.stability{margin-left:40px;}.methods>.stability,.content .impl-items>.stability{margin-top:-8px;}.impl-items{flex-basis:100%;}#main>.stability{margin-top:0;}nav:not(.sidebar){border-bottom:1px solid;padding-bottom:10px;margin-bottom:10px;}nav.main{padding:20px 0;text-align:center;}nav.main .current{border-top:1px solid;border-bottom:1px solid;}nav.main .separator{border:1px solid;display:inline-block;height:23px;margin:0 20px;}nav.sum{text-align:right;}nav.sub form{display:inline;}nav.sub,.content{margin-left:230px;}a{text-decoration:none;background:transparent;}.small-section-header:hover>.anchor{display:initial;}.in-band:hover>.anchor,.impl:hover>.anchor{display:inline-block;position:absolute;}.anchor{display:none;position:absolute;left:-7px;}.anchor.field{left:-5px;}.small-section-header>.anchor{left:-28px;padding-right:10px;}.anchor:before{content:'\2002\00a7\2002';}.docblock a:not(.srclink):not(.test-arrow):hover,.docblock-short a:not(.srclink):not(.test-arrow):hover,.stability a{text-decoration:underline;}.invisible>.srclink,h4>code+.srclink{position:absolute;top:0;right:0;font-size:17px;font-weight:normal;}.block a.current.crate{font-weight:500;}.search-container{position:relative;}.search-container>div{display:inline-flex;width:calc(100% - 63px);}#crate-search{margin-top:5px;padding:6px;padding-right:19px;flex:none;border:0;border-right:0;border-radius:4px 0 0 4px;outline:none;cursor:pointer;border-right:1px solid;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;text-overflow:"";background-repeat:no-repeat;background-color:transparent;background-size:20px;background-position:calc(100% - 1px) 56%;}.search-container>.top-button{position:absolute;right:0;top:10px;}.search-input{-moz-box-sizing:border-box !important;box-sizing:border-box !important;outline:none;border:none;border-radius:1px;margin-top:5px;padding:10px 16px;font-size:17px;transition:border-color 300ms ease;transition:border-radius 300ms ease-in-out;transition:box-shadow 300ms ease-in-out;width:100%;}#crate-search+.search-input{border-radius:0 1px 1px 0;width:calc(100% - 32px);}.search-input:focus{border-radius:2px;border:0;outline:0;}.search-results .desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;display:block;}.search-results a{display:block;}.content .search-results td:first-child{padding-right:0;width:50%;}.content .search-results td:first-child a{padding-right:10px;}.content .search-results td:first-child a:after{clear:both;content:"";display:block;}.content .search-results td:first-child a span{float:left;}tr.result span.primitive::after{content:' (primitive type)';font-style:italic;}tr.result span.keyword::after{content:' (keyword)';font-style:italic;}body.blur>:not(#help){filter:blur(8px);-webkit-filter:blur(8px);opacity:.7;}#help{width:100%;height:100vh;position:fixed;top:0;left:0;display:flex;justify-content:center;align-items:center;}#help>div{flex:0 0 auto;box-shadow:0 0 6px rgba(0,0,0,.2);width:550px;height:auto;border:1px solid;}#help dt{float:left;clear:left;display:block;}#help dd{margin:5px 35px;}#help .infos{padding-left:0;}#help h1,#help h2{margin-top:0;}#help>div div{width:50%;float:left;padding:20px;padding-left:17px;}.stab{display:table;border-width:1px;border-style:solid;padding:3px;margin-bottom:5px;font-size:90%;}.stab p{display:inline;}.stab summary{display:list-item;}.stab .emoji{font-size:1.5em;}.module-item .stab{border-radius:3px;display:inline-block;font-size:80%;line-height:1.2;margin-bottom:0;margin-right:.3em;padding:2px;vertical-align:text-bottom;}.module-item.unstable{opacity:0.65;}.since{font-weight:normal;font-size:initial;position:absolute;right:0;top:0;}.impl-items .since,.impl .since{flex-grow:0;padding-left:12px;padding-right:2px;position:initial;}.impl-items .srclink,.impl .srclink{flex-grow:0;font-size:17px;font-weight:normal;}.impl-items code,.impl code{flex-grow:1;}.impl-items h4,h4.impl,h3.impl{display:flex;flex-basis:100%;font-size:16px;margin-bottom:12px;justify-content:space-between;}.variants_table{width:100%;}.variants_table tbody tr td:first-child{width:1%;}td.summary-column{width:100%;}.summary{padding-right:0px;}pre.rust .question-mark{font-weight:bold;}a.test-arrow{display:inline-block;position:absolute;padding:5px 10px 5px 10px;border-radius:5px;font-size:130%;top:5px;right:5px;z-index:1;}a.test-arrow:hover{text-decoration:none;}.section-header:hover a:before{position:absolute;left:-25px;padding-right:10px;content:'\2002\00a7\2002';}.section-header:hover a{text-decoration:none;}.section-header a{color:inherit;}.collapse-toggle{font-weight:300;position:absolute;left:-23px;top:0;}h3>.collapse-toggle,h4>.collapse-toggle{font-size:0.8em;top:5px;}.toggle-wrapper>.collapse-toggle{left:-24px;margin-top:0px;}.toggle-wrapper{position:relative;margin-top:0;}.toggle-wrapper.collapsed{height:25px;transition:height .2s;margin-bottom:.6em;}.collapse-toggle>.inner{display:inline-block;width:1.2ch;text-align:center;}.collapse-toggle.hidden-default{position:relative;margin-left:20px;}.since+.srclink{display:table-cell;padding-left:10px;}.item-spacer{width:100%;height:12px;}.out-of-band>span.since{position:initial;font-size:20px;margin-right:5px;}.toggle-wrapper>.collapse-toggle{left:0;}.variant+.toggle-wrapper+.docblock>p{margin-top:5px;}.sub-variant,.sub-variant>h3{margin-top:1px !important;}#main>.sub-variant>h3{font-size:15px;margin-left:25px;margin-bottom:5px;}.sub-variant>div{margin-left:20px;margin-bottom:10px;}.sub-variant>div>span{display:block;position:relative;}.toggle-label{display:inline-block;margin-left:4px;margin-top:3px;}.enum>.toggle-wrapper+.docblock,.struct>.toggle-wrapper+.docblock{margin-left:30px;margin-bottom:20px;margin-top:5px;}.docblock>.section-header:first-child{margin-left:15px;margin-top:0;}.docblock>.section-header:first-child:hover>a:before{left:-10px;}.enum>.collapsed,.struct>.collapsed{margin-bottom:25px;}#main>.variant,#main>.structfield{display:block;}.attributes{display:block;margin-top:0px !important;margin-right:0px;margin-bottom:0px !important;margin-left:30px;}.toggle-attributes.collapsed{margin-bottom:0;}.impl-items>.toggle-attributes{margin-left:20px;}.impl-items .attributes{font-weight:500;}:target>code{opacity:1;}.information{position:absolute;left:-25px;margin-top:7px;z-index:1;}.tooltip{position:relative;display:inline-block;cursor:pointer;}.tooltip .tooltiptext{width:120px;display:none;text-align:center;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;top:-5px;left:105%;z-index:10;font-size:16px;}.tooltip .tooltiptext::after{content:" ";position:absolute;top:50%;left:16px;margin-top:-5px;border-width:5px;border-style:solid;}.tooltip.compile_fail,.tooltip.should_panic,.tooltip.ignore{font-weight:bold;font-size:20px;}.notable-traits-tooltip{display:inline-block;cursor:pointer;}.notable-traits:hover .notable-traits-tooltiptext,.notable-traits .notable-traits-tooltiptext.force-tooltip{display:inline-block;}.notable-traits .notable-traits-tooltiptext{display:none;padding:5px 3px 3px 3px;border-radius:6px;margin-left:5px;z-index:10;font-size:16px;cursor:default;position:absolute;border:1px solid;}.notable-traits-tooltip::after{content:"\00a0\00a0\00a0";}.notable-traits .notable,.notable-traits .docblock{margin:0;}.notable-traits .docblock code.content{margin:0;padding:0;font-size:20px;}pre.rust.rust-example-rendered{position:relative;}pre.rust{tab-size:4;-moz-tab-size:4;}.search-failed{text-align:center;margin-top:20px;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#titles{height:35px;}#titles>div{float:left;width:33.3%;text-align:center;font-size:18px;cursor:pointer;border-top:2px solid;}#titles>div:not(:last-child){margin-right:1px;width:calc(33.3% - 1px);}#titles>div>div.count{display:inline-block;font-size:16px;}.notable-traits{cursor:pointer;z-index:2;margin-left:5px;}h4>.notable-traits{position:absolute;left:-44px;top:2px;}#all-types{text-align:center;border:1px solid;margin:0 10px;margin-bottom:10px;display:block;border-radius:7px;}#all-types>p{margin:5px 0;}#sidebar-toggle{position:fixed;top:30px;left:300px;z-index:10;padding:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;cursor:pointer;font-weight:bold;transition:left .5s;font-size:1.2em;border:1px solid;border-left:0;}#source-sidebar{position:fixed;top:0;bottom:0;left:0;width:300px;z-index:1;overflow:auto;transition:left .5s;border-right:1px solid;}#source-sidebar>.title{font-size:1.5em;text-align:center;border-bottom:1px solid;margin-bottom:6px;}.theme-picker{position:absolute;left:211px;top:19px;}.theme-picker button{outline:none;}#settings-menu,.help-button{position:absolute;top:10px;}#settings-menu{right:0;outline:none;}.help-button{right:30px;font-family:"Fira Sans",sans-serif;text-align:center;font-size:17px;}#theme-picker,#settings-menu,.help-button{padding:4px;width:27px;height:29px;border:1px solid;border-radius:3px;cursor:pointer;}#theme-choices{display:none;position:absolute;left:0;top:28px;border:1px solid;border-radius:3px;z-index:1;cursor:pointer;}#theme-choices>button{border:none;width:100%;padding:4px 8px;text-align:center;background:rgba(0,0,0,0);}#theme-choices>button:not(:first-child){border-top:1px solid;}@media (min-width:701px){.information:first-child>.tooltip{margin-top:16px;}}@media (max-width:700px){body{padding-top:0px;}.rustdoc>.sidebar{height:45px;min-height:40px;margin:0;margin-left:-15px;padding:0 15px;position:static;z-index:11;}.sidebar>.location{float:right;margin:0px;margin-top:2px;padding:3px 10px 1px 10px;min-height:39px;background:inherit;text-align:left;font-size:24px;}.sidebar .location:empty{padding:0;}.sidebar .logo-container{width:35px;height:35px;margin-top:5px;margin-bottom:5px;float:left;margin-left:50px;}.sidebar .logo-container>img{max-width:35px;max-height:35px;}.sidebar-menu{position:fixed;z-index:10;font-size:2rem;cursor:pointer;width:45px;left:0;text-align:center;display:block;border-bottom:1px solid;border-right:1px solid;height:45px;}.rustdoc.source>.sidebar>.sidebar-menu{display:none;}.sidebar-elems{position:fixed;z-index:1;left:0;top:45px;bottom:0;overflow-y:auto;border-right:1px solid;display:none;}.sidebar>.block.version{border-bottom:none;margin-top:12px;}nav.sub{width:calc(100% - 32px);float:right;}.content{margin-left:0px;}#main{margin-top:45px;padding:0;}.content .in-band{width:100%;}.content h4>.out-of-band{position:inherit;}.toggle-wrapper>.collapse-toggle{left:0px;}.toggle-wrapper{height:1.5em;}#search{margin-left:0;}.content .impl-items .method,.content .impl-items>.type,.impl-items>.associatedconstant{display:flex;}.anchor{display:none !important;}h1.fqn{overflow:initial;}.theme-picker{left:10px;top:54px;z-index:1;}h4>.notable-traits{position:absolute;left:-22px;top:24px;}#titles>div>div.count{float:left;width:100%;}#titles{height:50px;}.sidebar.mobile{position:fixed;width:100%;margin-left:0;background-color:rgba(0,0,0,0);height:100%;}.sidebar{width:calc(100% + 30px);}.show-it{display:block;width:246px;}.show-it>.block.items{margin:8px 0;}.show-it>.block.items>ul{margin:0;}.show-it>.block.items>ul>li{text-align:center;margin:2px 0;}.show-it>.block.items>ul>li>a{font-size:21px;}#sidebar-filler{position:fixed;left:45px;width:calc(100% - 45px);top:0;height:45px;z-index:-1;border-bottom:1px solid;}.collapse-toggle{left:-20px;}.impl>.collapse-toggle{left:-10px;}#all-types{margin:10px;}#sidebar-toggle{top:100px;width:30px;font-size:1.5rem;text-align:center;padding:0;}#source-sidebar{z-index:11;}#main>.line-numbers{margin-top:0;}.notable-traits .notable-traits-tooltiptext{left:0;top:100%;}}@media print{nav.sub,.content .out-of-band,.collapse-toggle{display:none;}}@media (max-width:416px){#titles{height:73px;}#titles>div{height:73px;}}h3.notable{margin:0;margin-bottom:13px;font-size:19px;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px;border-radius:3px;box-shadow:inset 0 -1px 0;cursor:default;}.hidden-by-impl-hider,.hidden-by-usual-hider{display:none !important;}#implementations-list>h3>span.in-band{width:100%;}.table-display{width:100%;border:0;border-collapse:collapse;border-spacing:0;font-size:16px;}.table-display tr td:first-child{padding-right:0;}.table-display tr td:last-child{float:right;}.table-display .out-of-band{position:relative;font-size:19px;display:block;}#implementors-list>.impl-items .table-display .out-of-band{font-size:17px;}.table-display td:hover .anchor{display:block;top:2px;left:-5px;}#main>ul{padding-left:10px;}#main>ul>li{list-style:none;}.non-exhaustive{margin-bottom:1em;}div.children{padding-left:27px;display:none;}div.name{cursor:pointer;position:relative;margin-left:16px;}div.files>a{display:block;padding:0 3px;}div.files>a:hover,div.name:hover{background-color:#a14b4b;}div.name.expand+.children{display:block;}div.name::before{content:"\25B6";padding-left:4px;font-size:0.7em;position:absolute;left:-16px;top:4px;}div.name.expand::before{transform:rotate(90deg);left:-15px;top:2px;}.type-decl>pre>.toggle-wrapper.toggle-attributes.top-attr{margin-left:0 !important;}.type-decl>pre>.docblock.attributes.top-attr{margin-left:1.8em !important;}.type-decl>pre>.toggle-attributes{margin-left:2.2em;}.type-decl>pre>.docblock.attributes{margin-left:4em;} \ No newline at end of file diff --git a/src/doc/search-index.js b/src/doc/search-index.js new file mode 100644 index 0000000..fd7a14d --- /dev/null +++ b/src/doc/search-index.js @@ -0,0 +1,5 @@ +var searchIndex = JSON.parse('{\ +"main":{"doc":"","i":[],"p":[]},\ +"token":{"doc":"","i":[[0,"token","token","token docs",null,null],[4,"Token","token::token","",null,null],[13,"ILLEGAL","","",0,null],[13,"EOF","","",0,null],[13,"IDENT","","",0,null],[13,"ASSIGN","","",0,null],[13,"PLUS","","",0,null],[13,"MINUS","","",0,null],[13,"ASTERISK","","",0,null],[13,"SLASH","","",0,null],[13,"EQ","","",0,null],[13,"LEQ","","",0,null],[13,"LE","","",0,null],[13,"GEQ","","",0,null],[13,"GE","","",0,null],[13,"NEQ","","",0,null],[13,"COMMA","","",0,null],[13,"SEMICOLON","","",0,null],[13,"LPAR","","",0,null],[13,"RPAR","","",0,null],[13,"LBRA","","",0,null],[13,"RBRA","","",0,null],[13,"BANG","","",0,null],[13,"FUNCTION","","",0,null],[13,"LET","","",0,null],[13,"RETURN","","",0,null],[13,"IF","","",0,null],[13,"ELIF","","",0,null],[13,"ELSE","","",0,null],[13,"INT","","",0,null],[13,"STRING","","",0,null],[13,"TRUE","","",0,null],[13,"FALSE","","",0,null],[5,"lookup_ident","","",null,[[],["token",4]]],[11,"from","","",0,[[]]],[11,"into","","",0,[[]]],[11,"to_owned","","",0,[[]]],[11,"clone_into","","",0,[[]]],[11,"borrow","","",0,[[]]],[11,"borrow_mut","","",0,[[]]],[11,"try_from","","",0,[[],["result",4]]],[11,"try_into","","",0,[[],["result",4]]],[11,"type_id","","",0,[[],["typeid",3]]],[11,"clone","","",0,[[],["token",4]]],[11,"eq","","",0,[[["token",4]]]],[11,"ne","","",0,[[["token",4]]]],[11,"fmt","","",0,[[["formatter",3]],["result",6]]]],"p":[[4,"Token"]]}\ +}'); +addSearchOptions(searchIndex);initSearch(searchIndex); \ No newline at end of file diff --git a/src/doc/settings.css b/src/doc/settings.css new file mode 100644 index 0000000..6ce7665 --- /dev/null +++ b/src/doc/settings.css @@ -0,0 +1 @@ +.setting-line{padding:5px;position:relative;}.setting-line>div{max-width:calc(100% - 74px);display:inline-block;vertical-align:top;font-size:17px;padding-top:2px;}.setting-line>.title{font-size:19px;width:100%;max-width:none;border-bottom:1px solid;}.toggle{position:relative;display:inline-block;width:45px;height:27px;margin-right:20px;}.toggle input{display:none;}.slider{position:absolute;cursor:pointer;top:0;left:0;right:0;bottom:0;background-color:#ccc;-webkit-transition:.3s;transition:.3s;}.slider:before{position:absolute;content:"";height:19px;width:19px;left:4px;bottom:4px;background-color:white;-webkit-transition:.3s;transition:.3s;}input:checked+.slider{background-color:#2196F3;}input:focus+.slider{box-shadow:0 0 1px #2196F3;}input:checked+.slider:before{-webkit-transform:translateX(19px);-ms-transform:translateX(19px);transform:translateX(19px);}.setting-line>.sub-settings{padding-left:42px;width:100%;display:block;} \ No newline at end of file diff --git a/src/doc/settings.html b/src/doc/settings.html new file mode 100644 index 0000000..87394dc --- /dev/null +++ b/src/doc/settings.html @@ -0,0 +1,5 @@ +Rustdoc settings + +

Rustdoc settings

Auto-hide item declarations
Auto-hide structs declaration
Auto-hide enums declaration
Auto-hide unions declaration
Auto-hide traits declaration
Auto-hide macros declaration
+
Auto-hide item attributes.
Auto-hide item methods' documentation
Auto-hide trait implementation documentation
Auto-hide implementors of a trait
Directly go to item in search if there is only one result
Show line numbers on code examples
Disable keyboard shortcuts
\ No newline at end of file diff --git a/src/doc/settings.js b/src/doc/settings.js new file mode 100644 index 0000000..9930309 --- /dev/null +++ b/src/doc/settings.js @@ -0,0 +1 @@ +(function(){function changeSetting(settingName,isEnabled){updateLocalStorage('rustdoc-'+settingName,isEnabled)}function getSettingValue(settingName){return getCurrentValue('rustdoc-'+settingName)}function setEvents(){var elems=document.getElementsByClassName("slider");if(!elems||elems.length===0){return}for(var i=0;i"){sidebar.style.left="";this.style.left="";child.innerText="<";updateLocalStorage("rustdoc-source-sidebar-show","true")}else{sidebar.style.left="-300px";this.style.left="0";child.innerText=">";updateLocalStorage("rustdoc-source-sidebar-show","false")}}function createSidebarToggle(){var sidebarToggle=document.createElement("div");sidebarToggle.id="sidebar-toggle";sidebarToggle.onclick=toggleSidebar;var inner1=document.createElement("div");inner1.style.position="relative";var inner2=document.createElement("div");inner2.style.paddingTop="3px";if(getCurrentValue("rustdoc-source-sidebar-show")==="true"){inner2.innerText="<"}else{inner2.innerText=">";sidebarToggle.style.left="0"}inner1.appendChild(inner2);sidebarToggle.appendChild(inner1);return sidebarToggle}function createSourceSidebar(){if(window.rootPath.endsWith("/")===false){window.rootPath+="/"}var main=document.getElementById("main");var sidebarToggle=createSidebarToggle();main.insertBefore(sidebarToggle,main.firstChild);var sidebar=document.createElement("div");sidebar.id="source-sidebar";if(getCurrentValue("rustdoc-source-sidebar-show")!=="true"){sidebar.style.left="-300px"}var currentFile=getCurrentFilePath();var hasFoundFile=false;var title=document.createElement("div");title.className="title";title.innerText="Files";sidebar.appendChild(title);Object.keys(sourcesIndex).forEach(function(key){sourcesIndex[key].name=key;hasFoundFile=createDirEntry(sourcesIndex[key],sidebar,"",currentFile,hasFoundFile)});main.insertBefore(sidebar,main.firstChild);var selected_elem=sidebar.getElementsByClassName("selected")[0];if(typeof selected_elem!=="undefined"){selected_elem.focus()}} \ No newline at end of file diff --git a/src/doc/src/main/eval/env.rs.html b/src/doc/src/main/eval/env.rs.html new file mode 100644 index 0000000..8dedb8a --- /dev/null +++ b/src/doc/src/main/eval/env.rs.html @@ -0,0 +1,50 @@ +env.rs.html -- source + +
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+
+use super::eval::Object;
+use std::collections::HashMap;
+
+pub struct Env {
+    pub env: HashMap<String, Object>,
+}
+
+impl Env {
+    pub fn new() -> Self {
+        Env {
+            env: HashMap::new(),
+        }
+    }
+
+    pub fn set(&mut self, key: String, value: Object) {
+        self.env.insert(key, value);
+    }
+
+    pub fn get(&self, key: &str) -> Option<Object> {
+        self.env.get(key).map(|val| val.clone())
+    }
+}
+
+
\ No newline at end of file diff --git a/src/doc/src/main/eval/eval.rs.html b/src/doc/src/main/eval/eval.rs.html new file mode 100644 index 0000000..0839255 --- /dev/null +++ b/src/doc/src/main/eval/eval.rs.html @@ -0,0 +1,432 @@ +eval.rs.html -- source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+
+use crate::parser::ast::Statement;
+use crate::parser::ast::Expr;
+use crate::parser::ast::Operator;
+use crate::parser::ast::Prefix;
+
+pub use super::env::Env;
+
+#[derive(Debug, PartialEq, Clone)]
+pub enum Object {
+    Null,
+    Integer(i64),
+    String(String),
+    Boolean(bool),
+    Return(Box<Object>),
+    Function {
+        parameters: Vec<String>,
+        body: Vec<Statement>,
+    },
+}
+
+fn eval_expr(expression: Expr, env: &mut Env) -> Object {
+    match expression {
+        Expr::String(string) => Object::String(string),
+        Expr::Integer(num) => Object::Integer(num),
+        Expr::Boolean(val) => Object::Boolean(val),
+        Expr::Prefix {
+            prefix: Prefix::Bang,
+            value: expr,
+        } => match eval_expr(*expr, env) {
+            Object::Boolean(val) => Object::Boolean(!val),
+            _ => panic!("! operator only valid for boolean type"),
+        },
+        Expr::Prefix {
+            prefix: Prefix::Minus,
+            value: expr,
+        } => match eval_expr(*expr, env) {
+            Object::Integer(val) => Object::Integer(-val),
+            _ => panic!("minus operator only valid for integer type"),
+        },
+        Expr::Infix {
+            left,
+            operator: Operator::Plus,
+            right,
+        } => match (eval_expr(*left, env), eval_expr(*right, env)) {
+            (Object::Integer(left), Object::Integer(right)) => Object::Integer(left + right),
+            (Object::String(left), Object::String(right)) => Object::String(left + &right),
+            _ => panic!("plus operator used on invalid types"),
+        },
+        Expr::Infix {
+            left,
+            operator: Operator::Minus,
+            right,
+        } => match (eval_expr(*left, env), eval_expr(*right, env)) {
+            (Object::Integer(left), Object::Integer(right)) => Object::Integer(left - right),
+            _ => panic!("minus operator only valid on integer types"),
+        },
+        Expr::Infix {
+            left,
+            operator: Operator::Multiply,
+            right,
+        } => match (eval_expr(*left, env), eval_expr(*right, env)) {
+            (Object::Integer(left), Object::Integer(right)) => Object::Integer(left * right),
+            _ => panic!("multiply operator only valid on integer types"),
+        },
+        Expr::Infix {
+            left,
+            operator: Operator::Divide,
+            right,
+        } => match (eval_expr(*left, env), eval_expr(*right, env)) {
+            (Object::Integer(left), Object::Integer(right)) => Object::Integer(left / right),
+            _ => panic!("divide operator only valid on integer types"),
+        },
+        Expr::Infix {
+            left,
+            operator: Operator::LessThan,
+            right,
+        } => match (eval_expr(*left, env), eval_expr(*right, env)) {
+            (Object::Integer(left), Object::Integer(right)) => Object::Boolean(left < right),
+            _ => panic!("less than operator only valid on integer types"),
+        },
+        Expr::Infix {
+            left,
+            operator: Operator::GreaterThan,
+            right,
+        } => match (eval_expr(*left, env), eval_expr(*right, env)) {
+            (Object::Integer(left), Object::Integer(right)) => Object::Boolean(left > right),
+            _ => panic!("greater than operator only valid on integer types"),
+        },
+        Expr::Infix {
+            left,
+            operator: Operator::Equals,
+            right,
+        } => match (eval_expr(*left, env), eval_expr(*right, env)) {
+            (Object::Integer(left), Object::Integer(right)) => Object::Boolean(left == right),
+            (Object::Boolean(left), Object::Boolean(right)) => Object::Boolean(left == right),
+            _ => panic!("equals operator used on invalid types"),
+        },
+        Expr::Infix {
+            left,
+            operator: Operator::NotEquals,
+            right,
+        } => match (eval_expr(*left, env), eval_expr(*right, env)) {
+            (Object::Integer(left), Object::Integer(right)) => Object::Boolean(left != right),
+            (Object::Boolean(left), Object::Boolean(right)) => Object::Boolean(left != right),
+            _ => panic!("not equals operator used on invalid types"),
+        },
+        Expr::If {
+            condition,
+            consequence,
+            alternative,
+        } => {
+            if eval_expr(*condition, env) == Object::Boolean(true) {
+                eval_statements(consequence, env)
+            } else {
+                eval_statements(alternative, env)
+            }
+        }
+        Expr::Variable(name) => env.get(&name).expect("attempted access to invalid binding"),
+        Expr::Function { parameters, body } => Object::Function { parameters, body },
+        Expr::Call {
+            function,
+            arguments,
+        } => {
+            let (parameters, body) = match *function {
+                Expr::Variable(func_name) => match env.get(&func_name) {
+                    Some(Object::Function { parameters, body }) => (parameters, body),
+                    None => {
+                        let arguments = arguments
+                            .into_iter()
+                            .map(|expr| eval_expr(expr, env))
+                            .collect();
+                        println!("{:?}", arguments);
+                        println!("{:?}", env.get(&"fn"));
+                        return eval_builtin(&func_name, arguments)
+                            .expect("error calling function");
+                    }
+                    _ => panic!("attempted to call non-function"),
+                },
+                Expr::Function { parameters, body } => (parameters, body),
+                _ => panic!("attempted to call non-function"),
+            };
+
+            // run user defined function
+            assert_eq!(
+                parameters.len(),
+                arguments.len(),
+                "called function with wrong number of parameters"
+            );
+
+            let mut env_func = Env::new();
+            for (parameter, arg_value) in parameters.into_iter().zip(arguments.into_iter()) {
+                env_func.set(parameter, eval_expr(arg_value, env));
+            }
+
+            eval_return_scope(body, &mut env_func)
+        }
+    }
+}
+
+fn eval_builtin(func_name: &str, arguments: Vec<Object>) -> Option<Object> {
+    println!("{:?}", arguments.as_slice());
+    println!("AS");
+    match (func_name, arguments.as_slice()) {
+        ("len", [Object::String(string)]) => Some(Object::Integer(string.len() as i64)),
+        _ => None,
+    }
+}
+
+fn eval_statement(statement: Statement, env: &mut Env) -> Object {
+    match statement {
+        Statement::Expression(expr) => eval_expr(expr, env),
+        Statement::Let { name, value } => {
+            let value = eval_expr(value, env);
+
+            env.set(name, value.clone());
+            value
+        },
+        Statement::Define {func_name, func} => {
+            let value = eval_expr(func,env);
+            
+            env.set(func_name, value.clone());
+            value
+
+        }
+        Statement::Return { value: expr } => Object::Return(Box::new(eval_expr(expr, env))),
+    }
+}
+
+/// similar to eval_return_scope but doesn't unwrap Return types
+/// useful for if-else blocks where the return should return from the parent scope as well
+fn eval_statements(statements: Vec<Statement>, env: &mut Env) -> Object {
+    let mut result = Object::Null;
+
+    for statement in statements {
+        result = eval_statement(statement, env);
+
+        if let &Object::Return(_) = &result {
+            return result;
+        }
+    }
+
+    result
+}
+
+pub fn eval_return_scope(statements: Vec<Statement>, env: &mut Env) -> Object {
+    let result = eval_statements(statements, env);
+
+    match result {
+        // unwrap Return type
+        Object::Return(res) => *res,
+        _ => result,
+    }
+}
+
+
\ No newline at end of file diff --git a/src/doc/src/main/eval/mod.rs.html b/src/doc/src/main/eval/mod.rs.html new file mode 100644 index 0000000..57c9cf3 --- /dev/null +++ b/src/doc/src/main/eval/mod.rs.html @@ -0,0 +1,10 @@ +mod.rs.html -- source + +
1
+2
+
+pub mod env;
+pub mod eval;
+
+
\ No newline at end of file diff --git a/src/doc/src/main/lexer/lexer.rs.html b/src/doc/src/main/lexer/lexer.rs.html new file mode 100644 index 0000000..1d2f1e2 --- /dev/null +++ b/src/doc/src/main/lexer/lexer.rs.html @@ -0,0 +1,346 @@ +lexer.rs.html -- source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+
+use crate::token::token::{Token,lookup_ident};
+use ::std::iter::Peekable;
+use std::str;
+use std::str::Chars;
+
+pub struct Lexer<'a> {
+    /*
+    Takes in a string then stores its iterator.
+    Info: <'a> indicates a speciifed lifetime.
+    */
+    pub chr_iter: Peekable<Chars<'a>>,
+}
+
+impl<'a> Lexer<'a> {
+    pub fn read_char(&mut self) -> Option<char> {
+        // Returns the next item in the iterator.
+        return self.chr_iter.next();
+    }
+
+    pub fn new(file_string: &'a str) -> Lexer<'a> {
+        return Lexer {
+            chr_iter: file_string.chars().peekable(),
+        };
+    }
+
+    pub fn skip_whitespace(&mut self) {
+        while let Some(&chr) = self.chr_iter.peek() {
+            if chr.is_whitespace() {
+                self.chr_iter.next();
+            } else {
+                break;
+            }
+        }
+    }
+
+    pub fn read_identifier(&mut self, first_letter: char) -> String {
+        let mut expression: String = String::from(first_letter);
+
+        // Peek at top element, determine if alphabetic then add.
+        while let Some(&chr) = self.chr_iter.peek() {
+            if chr.is_alphabetic() || chr == '=' {
+                expression.push(self.read_char().unwrap());
+            } else {
+                break;
+            }
+        }
+        return expression;
+    }
+
+    pub fn read_string(&mut self) -> String {
+        let mut expression: String = String::new();
+
+        // Peek at top element, determine if alphabetic then add.
+        while let Some(&chr) = self.chr_iter.peek() {
+            if chr == '"' {
+                break;
+            } else {
+                expression.push(self.read_char().unwrap());
+            }
+        }
+        return expression;
+    }
+
+    pub fn read_number(&mut self, first_chr: char) -> i64 {
+        let mut expression: String = String::from(first_chr);
+
+        while let Some(&chr) = self.chr_iter.peek() {
+            if char::is_digit(chr, 10) {
+                expression.push(self.read_char().unwrap());
+            } else {
+                break;
+            }
+        }
+
+        return expression.parse().unwrap();
+    }
+
+    pub fn next_token(&mut self) -> Token {
+        self.skip_whitespace();
+
+        match self.read_char() {
+            // = first, into ASSIGN and EQUAL
+            Some('=') => {
+                // Comparison operator
+                if self.chr_iter.peek().unwrap() == &'=' {
+                    self.read_char();
+                    return Token::EQ;
+                } else {
+                    return Token::ASSIGN;
+                }
+            }
+            Some(',') => Token::COMMA,
+            Some(';') => Token::SEMICOLON,
+            Some('+') => Token::PLUS,
+            Some('-') => Token::MINUS,
+            Some('*') => Token::ASTERISK,
+            Some('/') => Token::SLASH,
+
+            Some('(') => Token::LPAR,
+            Some(')') => Token::RPAR,
+            Some('{') => Token::LBRA,
+            Some('}') => Token::RBRA,
+
+            Some('>') => {
+                if self.chr_iter.peek().unwrap() == &'=' {
+                    self.read_char();
+                    return Token::GEQ;
+                } else {
+                    return Token::GE;
+                }
+            }
+
+            Some('<') => {
+                if self.chr_iter.peek().unwrap() == &'=' {
+                    self.read_char();
+                    return Token::LEQ;
+                } else {
+                    return Token::LE;
+                }
+            }
+
+            Some('!') => {
+                if self.chr_iter.peek().unwrap() == &'=' {
+                    self.read_char();
+                    return Token::NEQ;
+                } else {
+                    return Token::BANG;
+                }
+            }
+
+            None => Token::EOF,
+
+            Some('"') => {
+                self.read_char();
+                Token::STRING(self.read_string())
+            }
+
+            // Deal with expressions and primitives
+            Some(chr) => {
+                if chr.is_alphabetic() {
+                    // Converts to either keyword or identifier
+                    let token = self.read_identifier(chr);
+                    return lookup_ident(&token as &str);
+                }
+                // Could be an integer
+                else if char::is_digit(chr, 10) {
+                    return Token::INT(self.read_number(chr));
+                }
+                // Nope, just ignore it
+                else {
+                    return Token::ILLEGAL(String::from(chr));
+                }
+            }
+        }
+    }
+
+    pub fn lex(&mut self) -> Vec<Token> {
+        let mut token_vec: Vec<Token> = Vec::new();
+
+        loop {
+            match self.chr_iter.peek() {
+                None => break,
+                _ => token_vec.push(self.next_token()),
+            }
+        }
+        // Important, I'm reversing the list because implementation from the back is much better in terms of time complexity. Pop better than remove.
+        token_vec.reverse();
+        return token_vec;
+    }
+}
+
+
\ No newline at end of file diff --git a/src/doc/src/main/lexer/lexer_test.rs.html b/src/doc/src/main/lexer/lexer_test.rs.html new file mode 100644 index 0000000..6cb76f0 --- /dev/null +++ b/src/doc/src/main/lexer/lexer_test.rs.html @@ -0,0 +1,46 @@ +lexer_test.rs.html -- source + +
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+
+/*
+#[cfg(test)]
+mod tests {
+
+    use super::*;
+    #[test]
+    fn test_tokens()
+    {
+        let input:&str = "=+(){},;";
+        struct testing_struct {
+            token_vec: Vec<(token::token_type,&'static str)>
+        }
+
+        let tests:testing_struct = testing_struct{
+            token_vec: vec![
+                (token.ASSIGN,"=")]
+        };
+        assert!(token_vec[0][1]=="=");
+    }
+}*/
+
+
\ No newline at end of file diff --git a/src/doc/src/main/lexer/mod.rs.html b/src/doc/src/main/lexer/mod.rs.html new file mode 100644 index 0000000..92db9b0 --- /dev/null +++ b/src/doc/src/main/lexer/mod.rs.html @@ -0,0 +1,10 @@ +mod.rs.html -- source + +
1
+2
+
+pub mod lexer;
+pub mod lexer_test;
+
+
\ No newline at end of file diff --git a/src/doc/src/main/main.rs.html b/src/doc/src/main/main.rs.html new file mode 100644 index 0000000..ee137e4 --- /dev/null +++ b/src/doc/src/main/main.rs.html @@ -0,0 +1,28 @@ +main.rs.html -- source + +
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+
+mod eval;
+mod lexer;
+mod parser;
+mod repl;
+mod tests;
+mod token;
+
+fn main() {
+    println!("uwu *nuzzles* wewcome to uwucode! Is for me..? 🥺👉👈");
+    repl::repl::start();
+}
+
+
\ No newline at end of file diff --git a/src/doc/src/main/parser/ast.rs.html b/src/doc/src/main/parser/ast.rs.html new file mode 100644 index 0000000..aa58a33 --- /dev/null +++ b/src/doc/src/main/parser/ast.rs.html @@ -0,0 +1,174 @@ +ast.rs.html -- source + +
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+
+use crate::token::token:: {Token};
+
+#[derive(Debug, Clone, PartialEq)]
+pub enum Statement {
+    Let { name: String, value: Expr },
+    Define { func_name: String, func: Expr },
+    Return { value: Expr },
+    Expression(Expr),
+}
+
+#[derive(Debug, Clone, PartialEq)]
+pub enum Expr {
+    String(String),
+    Variable(String),
+    Boolean(bool),
+    Integer(i64),
+    Prefix {
+        prefix: Prefix,
+        value: Box<Expr>,
+    },
+    Infix {
+        left: Box<Expr>,
+        operator: Operator,
+        right: Box<Expr>,
+    },
+    If {
+        condition: Box<Expr>,
+        consequence: Vec<Statement>,
+        alternative: Vec<Statement>,
+    },
+    Function {
+        parameters: Vec<String>,
+        body: Vec<Statement>,
+    },
+    Call {
+        function: Box<Expr>,
+        arguments: Vec<Expr>,
+    },
+}
+
+#[derive(Debug, Clone, PartialEq)]
+pub enum Prefix {
+    Bang,
+    Minus,
+}
+
+#[derive(PartialOrd, PartialEq,Debug)]
+pub enum Precedence {
+    Lowest,
+    Equals,
+    LessGreater,
+    Sum,
+    Product,
+    Prefix,
+}
+#[derive(Debug, Clone, PartialEq)]
+pub enum Operator {
+    Plus,
+    Minus,
+    Multiply,
+    Divide,
+    GreaterThan,
+    LessThan,
+    Equals,
+    NotEquals,
+}
+
+impl Token {
+    pub fn priority(&self) -> Precedence {
+        match self {
+            Token::PLUS => Precedence::Sum,
+            Token::MINUS => Precedence::Sum,
+            Token::SLASH => Precedence::Product,
+            Token::ASTERISK => Precedence::Product,
+            Token::LEQ => Precedence::LessGreater,
+            Token::LE => Precedence::LessGreater,
+            Token::GEQ => Precedence::LessGreater,
+            Token::GE => Precedence::LessGreater,
+            Token::EQ => Precedence::Equals,
+            Token::NEQ => Precedence::Equals,
+            _ => Precedence::Lowest,
+        }
+    }
+}
+
+
\ No newline at end of file diff --git a/src/doc/src/main/parser/mod.rs.html b/src/doc/src/main/parser/mod.rs.html new file mode 100644 index 0000000..86897b2 --- /dev/null +++ b/src/doc/src/main/parser/mod.rs.html @@ -0,0 +1,10 @@ +mod.rs.html -- source + +
1
+2
+
+pub mod ast;
+pub mod parser;
+
+
\ No newline at end of file diff --git a/src/doc/src/main/parser/parser.rs.html b/src/doc/src/main/parser/parser.rs.html new file mode 100644 index 0000000..95bac9a --- /dev/null +++ b/src/doc/src/main/parser/parser.rs.html @@ -0,0 +1,542 @@ +parser.rs.html -- source + +
  1
+  2
+  3
+  4
+  5
+  6
+  7
+  8
+  9
+ 10
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ 31
+ 32
+ 33
+ 34
+ 35
+ 36
+ 37
+ 38
+ 39
+ 40
+ 41
+ 42
+ 43
+ 44
+ 45
+ 46
+ 47
+ 48
+ 49
+ 50
+ 51
+ 52
+ 53
+ 54
+ 55
+ 56
+ 57
+ 58
+ 59
+ 60
+ 61
+ 62
+ 63
+ 64
+ 65
+ 66
+ 67
+ 68
+ 69
+ 70
+ 71
+ 72
+ 73
+ 74
+ 75
+ 76
+ 77
+ 78
+ 79
+ 80
+ 81
+ 82
+ 83
+ 84
+ 85
+ 86
+ 87
+ 88
+ 89
+ 90
+ 91
+ 92
+ 93
+ 94
+ 95
+ 96
+ 97
+ 98
+ 99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112
+113
+114
+115
+116
+117
+118
+119
+120
+121
+122
+123
+124
+125
+126
+127
+128
+129
+130
+131
+132
+133
+134
+135
+136
+137
+138
+139
+140
+141
+142
+143
+144
+145
+146
+147
+148
+149
+150
+151
+152
+153
+154
+155
+156
+157
+158
+159
+160
+161
+162
+163
+164
+165
+166
+167
+168
+169
+170
+171
+172
+173
+174
+175
+176
+177
+178
+179
+180
+181
+182
+183
+184
+185
+186
+187
+188
+189
+190
+191
+192
+193
+194
+195
+196
+197
+198
+199
+200
+201
+202
+203
+204
+205
+206
+207
+208
+209
+210
+211
+212
+213
+214
+215
+216
+217
+218
+219
+220
+221
+222
+223
+224
+225
+226
+227
+228
+229
+230
+231
+232
+233
+234
+235
+236
+237
+238
+239
+240
+241
+242
+243
+244
+245
+246
+247
+248
+249
+250
+251
+252
+253
+254
+255
+256
+257
+258
+259
+260
+261
+262
+263
+264
+265
+266
+267
+268
+
+use crate::parser::ast::{Expr, Operator, Precedence, Prefix, Statement};
+use crate::token::token::Token;
+
+pub fn parse(input: &mut Vec<Token>) -> Vec<Statement> {
+    /*
+    This function should be able to parse the following:
+
+    Primitives into primitives (duh)
+    variables
+
+    */
+    let mut statements = vec![];
+
+    // Process each statement here
+    loop {
+        let top_token = match input.last() {
+            Some(token) => token,
+            None => panic!("fuck, the token vec is empty"),
+        };
+
+
+        // We need to check against six possible cases:
+        /*
+        - Let statements
+        - Function defining
+        - EOF token
+        - Expression
+        - Right braces
+        - Returns
+        */
+        match top_token {
+            Token::EOF => break, // We've reached the end of line or file
+            Token::LET => parse_let(input, &mut statements), // Define a variable
+            Token::FUNCTION => parse_function(input, &mut statements), // Define a function
+            Token::RBRA => break, // We've reached the end of an enclosing
+            Token::RETURN => parse_return(input, &mut statements),
+            _ => statements.push(Statement::Expression(parse_expression(
+                input,
+                Precedence::Lowest,
+            ))), // Deal with an expression
+        }
+
+
+        // Since the subcalls modify the vector of tokens, we should reach a semicolon at the end.
+        // THE BACK OF THE VECTOR IS THE TOP LIKE A STACK LOL
+
+        
+        assert_eq!(input.pop(), Some(Token::SEMICOLON));
+    }
+
+    return statements;
+}
+
+fn parse_let(input: &mut Vec<Token>, statements: &mut Vec<Statement>) {
+    /*
+    We need to look at our enum here. Let {name:String, value: Expr}. When we encounter a let, we need to pop it off the grill.
+    LET STRING = THING (in uwu speak, its owo STRING = THING)
+    */
+    assert_eq!(input.pop(), Some(Token::LET)); // Sanity Check duhs
+
+    // wtfs going on here lol, double enum extraction
+    let var_name: String = match input.pop() {
+        Some(Token::IDENT(var)) => var,
+        _ => panic!("Uh we don't have a string strangely"),
+    };
+
+    // We're at = stage
+    assert_eq!(input.pop(), Some(Token::ASSIGN));
+    // Now we're at the expression eval stage, leave it to parse expr
+    let value = parse_expression(input, Precedence::Lowest);
+    statements.push(Statement::Let {
+        name: var_name,
+        value,
+    });
+}
+
+fn parse_return(input: &mut Vec<Token>, statements: &mut Vec<Statement>) {
+    /*
+    Let's have a look at our Return enum now. Return {value:Expr} which means
+    we need to just parse the expression.
+    */
+    assert_eq!(input.pop(), Some(Token::RETURN));
+    // Now evaluate the expression
+    let value = parse_expression(input, Precedence::Lowest);
+    statements.push(Statement::Return { value });
+}
+
+fn parse_function(input: &mut Vec<Token>, statements: &mut Vec<Statement>) {
+    /*
+    Lets have a look at the Define enum, iu
+
+    Ideal structure looks like this:
+
+    DEFINE FUNCTIONNAME(args..) {
+        body
+    }
+    in uwu code:
+    uwu funcName(args) {
+        body
+    }
+    */
+    assert_eq!(input.pop(), Some(Token::FUNCTION));
+
+    // Next thing is the function name, add it in
+    let func_name: String = match input.pop() {
+        Some(Token::IDENT(name)) => name,
+        a => panic!("Huh, we didnt get a string, instead I got {:?}", a),
+    };
+
+    // Now we're at args, first thing is the LPAR
+    assert_eq!(input.pop(), Some(Token::LPAR));
+
+    // Arguments here
+    let mut parameters = vec![];
+
+    loop {
+        match input.pop() {
+            Some(Token::RPAR) => break,
+            Some(Token::IDENT(var)) => {
+                // Find an arg, add then proceed
+                parameters.push(var); // push to vec list
+                match input.pop() {
+                    Some(Token::RPAR) => break,
+                    Some(Token::COMMA) => continue,
+                    _ => panic!("Object after param was not comma or bracket"),
+                };
+            }
+            _ => panic!("Object after param was not comma or bracket"),
+        }
+    }
+
+    // We've reached the end of args, now parse body
+    assert_eq!(input.pop(), Some(Token::LBRA)); // {
+    let body = parse(input); // will return code of inside
+    assert_eq!(input.pop(), Some(Token::RBRA)); // }
+
+    statements.push(Statement::Define {
+        func_name,
+        func: Expr::Function { parameters, body },
+    });
+}
+
+fn parse_expression(input: &mut Vec<Token>, precedence: Precedence) -> Expr {
+    let mut left_expr = match input.pop() {
+        Some(val) => {
+
+            match val {
+                
+                // This is a Token type
+                // Primitives
+                Token::INT(value) => Expr::Integer(value),
+                Token::TRUE => Expr::Boolean(true),
+                Token::FALSE => Expr::Boolean(false),
+                Token::IDENT(value) => {
+                if input.last() == Some(&Token::LPAR)
+                {
+                    input.pop();
+                    let mut args = vec![];
+
+                    loop {
+                        match input.last() {
+                            Some(Token::RPAR) => {
+                                input.pop();
+                                break;
+                            },
+                            None => panic!("weird stuff happened"),
+                            _ => args.push(parse_expression(input, Precedence::Lowest)),
+                        }
+
+                        match input.pop() {
+                            Some(Token::RPAR) => break, 
+                            Some(Token::COMMA) => continue,
+                            _ => panic!("Unexpected parameter"),
+                        }
+                    }
+                    Expr::Call {
+                        function: Box::new(Expr::Variable(value)),
+                        arguments:args
+                    }
+                }
+                else {
+                    Expr::Variable(value)
+                }
+                
+                }
+                Token::STRING(value) => Expr::String(value),
+
+                // Prefix types [A B]
+                Token::BANG => Expr::Prefix {
+                    prefix: Prefix::Bang,
+                    value: Box::new(parse_expression(input, Precedence::Prefix)),
+                },
+
+                Token::MINUS => Expr::Prefix {
+                    prefix: Prefix::Minus,
+                    value: Box::new(parse_expression(input, Precedence::Prefix)),
+                },
+
+                // conditional
+                Token::IF => {
+                    assert_eq!(Some(Token::LPAR), input.pop());
+                    let condition = parse_expression(input, Precedence::Lowest);
+                    assert_eq!(Some(Token::RPAR), input.pop());
+
+                    // Parse body
+                    assert_eq!(Some(Token::LBRA), input.pop());
+                    let consequence = parse(input);
+                    assert_eq!(Some(Token::RBRA), input.pop());
+
+                    let alternative = if input.last() == Some(&Token::ELSE) {
+                        // ELSE CONDITION
+                        input.pop();
+                        assert_eq!(Some(Token::LBRA), input.pop());
+                        let alternative = parse(input);
+                        assert_eq!(Some(Token::RBRA), input.pop());
+                        alternative
+                    } else {
+                        Vec::new()
+                    };
+
+                    Expr::If {
+                        condition: Box::new(condition),
+                        consequence,
+                        alternative,
+                    }
+                }
+
+                // Error
+                _ => panic!("Parser error: Not recognized!"),
+            }
+        }
+        _ => panic!("The vector is empty"),
+    };
+
+    while precedence < input.last().unwrap().priority() {
+
+        left_expr = parse_infix(left_expr, input);
+    }
+
+    left_expr
+}
+
+fn parse_infix(left: Expr, input: &mut Vec<Token>) -> Expr {
+    let next_token = match input.pop() {
+        Some(value) => value,
+        None => panic!("Empty list..."),
+    };
+
+    let operator = match next_token {
+        Token::PLUS => Operator::Plus,
+        Token::MINUS => Operator::Minus,
+        Token::SLASH => Operator::Divide,
+        Token::ASTERISK => Operator::Multiply,
+        Token::LEQ => Operator::LessThan,
+        Token::LE => Operator::LessThan,
+        Token::GEQ => Operator::GreaterThan,
+        Token::GE => Operator::GreaterThan,
+        Token::EQ => Operator::Equals,
+        Token::NEQ => Operator::NotEquals,
+        _ => panic!("parse infix called on invalid operator"),
+    };
+
+    Expr::Infix {
+        left: Box::new(left),
+        operator,
+        right: Box::new(parse_expression(input, next_token.priority())),
+    }
+}
+
+
\ No newline at end of file diff --git a/src/doc/src/main/repl/mod.rs.html b/src/doc/src/main/repl/mod.rs.html new file mode 100644 index 0000000..5e2aead --- /dev/null +++ b/src/doc/src/main/repl/mod.rs.html @@ -0,0 +1,8 @@ +mod.rs.html -- source + +
1
+
+pub mod repl;
+
+
\ No newline at end of file diff --git a/src/doc/src/main/repl/repl.rs.html b/src/doc/src/main/repl/repl.rs.html new file mode 100644 index 0000000..e43f653 --- /dev/null +++ b/src/doc/src/main/repl/repl.rs.html @@ -0,0 +1,90 @@ +repl.rs.html -- source + +
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+
+use crate::eval::eval::{eval_return_scope, Env, Object};
+use crate::lexer::lexer::Lexer;
+use crate::parser::parser::{parse};
+use ::std::io::Write;
+use std::io;
+
+//use colored::*;
+
+const PROMPT: &str = "( ᴜ ω ᴜ )⭜";
+
+pub fn start() {
+    let mut env = Env::new();
+    loop {
+        print!("{}  ", PROMPT);//.truecolor(255, 69, 0));
+        std::io::stdout().flush().expect("Flushing failed");
+        let mut user_in: String = String::new();
+        io::stdin().read_line(&mut user_in).expect("Could not read");
+        let mut lexer = Lexer::new(&user_in as &str);
+        let mut token_vec = lexer.lex();
+
+        let parsed = parse(&mut token_vec);
+        //println!("{:?}",parsed);
+        display_object(eval_return_scope(parsed, &mut env));
+    }
+}
+
+fn display_object(obj: Object) {
+    match obj {
+        Object::Integer(num) => println!("{}", num),
+        Object::String(string) => println!("{}", string),
+        Object::Boolean(val) => match val { 
+            true=> println!("truwu"),
+            false=> println!("fowose"),
+        },
+        Object::Function {
+            parameters: _,
+            body: _,
+        } => println!("function"),
+        Object::Null => println!("null"),
+        Object::Return(obj) => display_object(*obj),
+    }
+}
+
+
\ No newline at end of file diff --git a/src/doc/src/main/tests.rs.html b/src/doc/src/main/tests.rs.html new file mode 100644 index 0000000..7cad14a --- /dev/null +++ b/src/doc/src/main/tests.rs.html @@ -0,0 +1,170 @@ +tests.rs.html -- source + +
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+
+
+
+
+#[cfg(test)]
+mod tests {
+    use crate::lexer;
+    use crate::token::token:: {Token};
+    #[test]
+    fn test_token_basic() {
+        let input: &str = "=+(){},;";
+        struct TestingStruct {
+            token_vec: Vec<Token>,
+        }
+        let mut test_lexer = lexer::lexer::Lexer::new(input);
+
+        let tests: TestingStruct = TestingStruct {
+            token_vec: vec![
+                Token::ASSIGN,
+                Token::PLUS,
+                Token::LPAR,
+                Token::RPAR,
+                Token::LBRA,
+                Token::RBRA,
+                Token::COMMA,
+                Token::SEMICOLON,
+            ],
+        };
+        for test in tests.token_vec.iter() {
+            let current_token = test_lexer.next_token();
+            assert_eq!(test, &current_token);
+        }
+    }
+
+    #[test]
+    fn test_token_strings() {
+        let input: &str = "owo five = 5;
+        owo ten = 10;
+        owo add = uwu(x,y) {
+            x+y;
+        };
+        ";
+        struct TestingStruct {
+            token_vec: Vec<Token>,
+        }
+        let mut test_lexer = lexer::lexer::Lexer::new(input);
+
+        let tests: TestingStruct = TestingStruct {
+            token_vec: vec![
+                Token::LET,
+                Token::IDENT(String::from("five")),
+                Token::ASSIGN,
+                Token::INT(5),
+                Token::SEMICOLON,
+                Token::LET,
+                Token::IDENT(String::from("ten")),
+                Token::ASSIGN,
+                Token::INT(10),
+                Token::SEMICOLON,
+                Token::LET,
+                Token::IDENT(String::from("add")),
+                Token::ASSIGN,
+                Token::FUNCTION,
+                Token::LPAR,
+                Token::IDENT(String::from("x")),
+                Token::COMMA,
+                Token::IDENT(String::from("y")),
+                Token::RPAR,
+                Token::LBRA,
+                Token::IDENT(String::from("x")),
+                Token::PLUS,
+                Token::IDENT(String::from("y")),
+                Token::SEMICOLON,
+                Token::RBRA,
+                Token::SEMICOLON,
+            ],
+        };
+        for test in tests.token_vec.iter() {
+            let current_token = test_lexer.next_token();
+            assert_eq!(test, &current_token);
+        }
+    }
+}
+
+
\ No newline at end of file diff --git a/src/doc/src/main/token/mod.rs.html b/src/doc/src/main/token/mod.rs.html new file mode 100644 index 0000000..0f9fd47 --- /dev/null +++ b/src/doc/src/main/token/mod.rs.html @@ -0,0 +1,8 @@ +mod.rs.html -- source + +
1
+
+pub mod token;
+
+
\ No newline at end of file diff --git a/src/doc/src/main/token/token.rs.html b/src/doc/src/main/token/token.rs.html new file mode 100644 index 0000000..5b07ad0 --- /dev/null +++ b/src/doc/src/main/token/token.rs.html @@ -0,0 +1,118 @@ +token.rs.html -- source + +
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+
+pub fn lookup_ident(ident: &str) -> Token {
+    match ident {
+        "uwu" => Token::FUNCTION,
+        "owo" => Token::LET,
+        "nuzzles" => Token::IF,
+        "dab" => Token::ELIF,
+        "rawr" => Token::ELSE,
+        "sugoi" => Token::RETURN,
+        "truwu" => Token::TRUE,
+        "fowose" => Token::FALSE,
+        _ => Token::IDENT(String::from(ident)),
+    }
+}
+
+#[derive(PartialEq, Clone, Debug)]
+pub enum Token {
+    ILLEGAL(String),
+    EOF,
+    IDENT(String),
+
+    ASSIGN,
+    PLUS,
+    MINUS,
+    ASTERISK,
+    SLASH,
+
+    EQ,
+    LEQ,
+    LE,
+    GEQ,
+    GE,
+    NEQ,
+
+    COMMA,
+    SEMICOLON,
+
+    LPAR,
+    RPAR,
+    LBRA,
+    RBRA,
+
+    BANG,
+
+    FUNCTION,
+    LET,
+    RETURN,
+
+    IF,
+    ELIF,
+    ELSE,
+
+    INT(i64),
+    STRING(String),
+    TRUE,
+    FALSE,
+}
+
+
\ No newline at end of file diff --git a/src/doc/src/token/token.rs.html b/src/doc/src/token/token.rs.html new file mode 100644 index 0000000..0f8de6d --- /dev/null +++ b/src/doc/src/token/token.rs.html @@ -0,0 +1,129 @@ +token.rs.html -- source + +
 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+
+/// token docs
+
+pub mod token {
+
+pub fn lookup_ident(ident: &str) -> Token {
+
+    match ident {
+        "uwu" => Token::FUNCTION,
+        "owo" => Token::LET,
+        "nuzzles" => Token::IF,
+        "dab" => Token::ELIF,
+        "rawr" => Token::ELSE,
+        "sugoi" => Token::RETURN,
+        "truwu" => Token::TRUE,
+        "fowose" => Token::FALSE,
+        _ => Token::IDENT(String::from(ident)),
+    }
+}
+
+#[derive(PartialEq, Clone, Debug)]
+pub enum Token {
+    ILLEGAL(String),
+    EOF,
+    IDENT(String),
+
+    ASSIGN,
+    PLUS,
+    MINUS,
+    ASTERISK,
+    SLASH,
+
+    EQ,
+    LEQ,
+    LE,
+    GEQ,
+    GE,
+    NEQ,
+
+    COMMA,
+    SEMICOLON,
+
+    LPAR,
+    RPAR,
+    LBRA,
+    RBRA,
+
+    BANG,
+
+    FUNCTION,
+    LET,
+    RETURN,
+
+    IF,
+    ELIF,
+    ELSE,
+
+    INT(i64),
+    STRING(String),
+    TRUE,
+    FALSE,
+}
+}
+
\ No newline at end of file diff --git a/src/doc/storage.js b/src/doc/storage.js new file mode 100644 index 0000000..1b52251 --- /dev/null +++ b/src/doc/storage.js @@ -0,0 +1 @@ +var resourcesSuffix="";var currentTheme=document.getElementById("themeStyle");var mainTheme=document.getElementById("mainThemeStyle");var savedHref=[];function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(!elem||!elem.classList){return}elem.classList.add(className)}function removeClass(elem,className){if(!elem||!elem.classList){return}elem.classList.remove(className)}function onEach(arr,func,reversed){if(arr&&arr.length>0&&func){var length=arr.length;var i;if(reversed!==true){for(i=0;i=0;--i){if(func(arr[i])===true){return true}}}}return false}function onEachLazy(lazyArray,func,reversed){return onEach(Array.prototype.slice.call(lazyArray),func,reversed)}function hasOwnProperty(obj,property){return Object.prototype.hasOwnProperty.call(obj,property)}function usableLocalStorage(){if(typeof Storage==="undefined"){return false}try{return window.localStorage!==null&&window.localStorage!==undefined}catch(err){return false}}function updateLocalStorage(name,value){if(usableLocalStorage()){localStorage[name]=value}else{}}function getCurrentValue(name){if(usableLocalStorage()&&localStorage[name]!==undefined){return localStorage[name]}return null}function switchTheme(styleElem,mainStyleElem,newTheme,saveTheme){var fullBasicCss="rustdoc"+resourcesSuffix+".css";var fullNewTheme=newTheme+resourcesSuffix+".css";var newHref=mainStyleElem.href.replace(fullBasicCss,fullNewTheme);if(styleElem.href===newHref){return}var found=false;if(savedHref.length===0){onEachLazy(document.getElementsByTagName("link"),function(el){savedHref.push(el.href)})}onEach(savedHref,function(el){if(el===newHref){found=true;return true}});if(found===true){styleElem.href=newHref;if(saveTheme===true){updateLocalStorage("rustdoc-theme",newTheme)}}}function getSystemValue(){var property=getComputedStyle(document.documentElement).getPropertyValue('content');return property.replace(/[\"\']/g,"")}switchTheme(currentTheme,mainTheme,getCurrentValue("rustdoc-theme")||getSystemValue()||"light",false) \ No newline at end of file diff --git a/src/doc/theme.js b/src/doc/theme.js new file mode 100644 index 0000000..3800819 --- /dev/null +++ b/src/doc/theme.js @@ -0,0 +1 @@ +var themes=document.getElementById("theme-choices");var themePicker=document.getElementById("theme-picker");function showThemeButtonState(){themes.style.display="block";themePicker.style.borderBottomRightRadius="0";themePicker.style.borderBottomLeftRadius="0"}function hideThemeButtonState(){themes.style.display="none";themePicker.style.borderBottomRightRadius="3px";themePicker.style.borderBottomLeftRadius="3px"}function switchThemeButtonState(){if(themes.style.display==="block"){hideThemeButtonState()}else{showThemeButtonState()}};function handleThemeButtonsBlur(e){var active=document.activeElement;var related=e.relatedTarget;if(active.id!=="themePicker"&&(!active.parentNode||active.parentNode.id!=="theme-choices")&&(!related||(related.id!=="themePicker"&&(!related.parentNode||related.parentNode.id!=="theme-choices")))){hideThemeButtonState()}}themePicker.onclick=switchThemeButtonState;themePicker.onblur=handleThemeButtonsBlur;["ayu","dark","light"].forEach(function(item){var but=document.createElement('button');but.textContent=item;but.onclick=function(el){switchTheme(currentTheme,mainTheme,item,true)};but.onblur=handleThemeButtonsBlur;themes.appendChild(but)}) \ No newline at end of file diff --git a/src/doc/token/all.html b/src/doc/token/all.html new file mode 100644 index 0000000..926a5c8 --- /dev/null +++ b/src/doc/token/all.html @@ -0,0 +1,6 @@ +List of all items in this crate + +

[] + + List of all items

Enums

Functions

\ No newline at end of file diff --git a/src/doc/token/index.html b/src/doc/token/index.html new file mode 100644 index 0000000..a0de345 --- /dev/null +++ b/src/doc/token/index.html @@ -0,0 +1,6 @@ +token - Rust + +

[][src]Crate token

Modules

+
token

token docs

+
\ No newline at end of file diff --git a/src/doc/token/sidebar-items.js b/src/doc/token/sidebar-items.js new file mode 100644 index 0000000..cbc1d3a --- /dev/null +++ b/src/doc/token/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"mod":[["token","token docs"]]}); \ No newline at end of file diff --git a/src/doc/token/token/enum.Token.html b/src/doc/token/token/enum.Token.html new file mode 100644 index 0000000..f4ddd5b --- /dev/null +++ b/src/doc/token/token/enum.Token.html @@ -0,0 +1,57 @@ +token::token::Token - Rust + +

[][src]Enum token::token::Token

pub enum Token {
+    ILLEGAL(String),
+    EOF,
+    IDENT(String),
+    ASSIGN,
+    PLUS,
+    MINUS,
+    ASTERISK,
+    SLASH,
+    EQ,
+    LEQ,
+    LE,
+    GEQ,
+    GE,
+    NEQ,
+    COMMA,
+    SEMICOLON,
+    LPAR,
+    RPAR,
+    LBRA,
+    RBRA,
+    BANG,
+    FUNCTION,
+    LET,
+    RETURN,
+    IF,
+    ELIF,
+    ELSE,
+    INT(i64),
+    STRING(String),
+    TRUE,
+    FALSE,
+}

+ Variants

+
ILLEGAL(String)
EOF
IDENT(String)
ASSIGN
PLUS
MINUS
ASTERISK
SLASH
EQ
LEQ
LE
GEQ
GE
NEQ
COMMA
SEMICOLON
LPAR
RPAR
LBRA
RBRA
BANG
FUNCTION
LET
RETURN
IF
ELIF
ELSE
INT(i64)
STRING(String)
TRUE
FALSE

Trait Implementations

impl Clone for Token[src]

impl Debug for Token[src]

impl PartialEq<Token> for Token[src]

impl StructuralPartialEq for Token[src]

Auto Trait Implementations

impl RefUnwindSafe for Token

impl Send for Token

impl Sync for Token

impl Unpin for Token

impl UnwindSafe for Token

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> ToOwned for T where
    T: Clone
[src]

type Owned = T

The resulting type after obtaining ownership.

+

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

+

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

+
\ No newline at end of file diff --git a/src/doc/token/token/fn.lookup_ident.html b/src/doc/token/token/fn.lookup_ident.html new file mode 100644 index 0000000..d8d137a --- /dev/null +++ b/src/doc/token/token/fn.lookup_ident.html @@ -0,0 +1,4 @@ +token::token::lookup_ident - Rust + +

[][src]Function token::token::lookup_ident

pub fn lookup_ident(ident: &str) -> Token
\ No newline at end of file diff --git a/src/doc/token/token/index.html b/src/doc/token/token/index.html new file mode 100644 index 0000000..f99cff5 --- /dev/null +++ b/src/doc/token/token/index.html @@ -0,0 +1,7 @@ +token::token - Rust + +

[][src]Module token::token

token docs

+

Enums

+
Token

Functions

+
lookup_ident
\ No newline at end of file diff --git a/src/doc/token/token/sidebar-items.js b/src/doc/token/token/sidebar-items.js new file mode 100644 index 0000000..5dfe349 --- /dev/null +++ b/src/doc/token/token/sidebar-items.js @@ -0,0 +1 @@ +initSidebarItems({"enum":[["Token",""]],"fn":[["lookup_ident",""]]}); \ No newline at end of file diff --git a/src/doc/wheel.svg b/src/doc/wheel.svg new file mode 100644 index 0000000..01da3b2 --- /dev/null +++ b/src/doc/wheel.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/eval/env.rs b/src/eval/env.rs new file mode 100644 index 0000000..849e7f2 --- /dev/null +++ b/src/eval/env.rs @@ -0,0 +1,41 @@ +//! Handles the scoping of functions and various contexts. +use crate::eval::eval::Object; +use std::collections::HashMap; + +/// Scopes contain bound variables and expressions. +#[derive(Clone)] +pub struct Env { + pub space: HashMap, + pub enclosing: Option>, // Pointer to a scope or nothing. +} + +impl Env { + /// Instantiates a new environment object with no outer scope. + pub fn new() -> Self { + Env { + space: HashMap::new(), + enclosing: None, + } + } + + /// Defines a variable/function in the current scope. + pub fn set(&mut self, key: String, value: Object) { + self.space.insert(key, value); + } + + /// Recursively attempts to get a variable/functions value. + pub fn get(&self, key: &str) -> Option { + match (self.space.get(key), &self.enclosing) { + (Some(val), _) => Some(val.clone()), // Variable found + (None, Some(enclose)) => enclose.get(key), // Query outer scope + (None, _) => None, // Variable not found at outermost scope + } + } + + // Enclosing = outer or global typically. + pub fn new_enclosing(outer: Self) -> Self { + let mut env = Self::new(); + env.enclosing = Some(Box::new(outer)); // Pointer to original object + env // Return the inner environment + } +} diff --git a/src/eval/eval.rs b/src/eval/eval.rs new file mode 100644 index 0000000..29af16c --- /dev/null +++ b/src/eval/eval.rs @@ -0,0 +1,369 @@ +use crate::parser::ast::Expr; +use crate::parser::ast::Operator; +use crate::parser::ast::Prefix; +use crate::parser::ast::Statement; + +pub use crate::eval::env::Env; +use std::fmt; + +#[derive(Debug, PartialEq, Clone)] +pub enum Object { + Null, + Integer(i64), + String(String), + Boolean(bool), + Return(Box), + Function { + parameters: Vec, + body: Vec, + }, + Terminate, + Print(Box), + While { + condition: Box, + instruction: Vec, + }, +} + +/// NOT IMPLEMENTED: Determines what action the interpreter must take. The while loop feature is not implemented as a result, and neither is the input function. +#[allow(dead_code)] +#[derive(Debug, PartialEq, Clone)] +pub enum InterpreterAction { + Print(Object), + Terminate, + Input(Object), + None(Object), + While(Object), +} + +impl fmt::Display for Object { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Object::Integer(num) => num.fmt(f), + Object::String(string) => string.fmt(f), + Object::Boolean(val) => match val { + true => "truwu".fmt(f), + false => "fowose".fmt(f), + }, + Object::Function {parameters:_,body:_} => "".fmt(f), + Object::Null => "none".fmt(f), + Object::Return(obj) => write!(f,"{}",obj), + Object::Terminate => "Nyaaa!~, t-t-thanks fow u-using uwucode?!?1 Come *boops your nose* again *huggles tightly* soon?!! 🥺".fmt(f), + Object::Print(obj) => write!(f,"{}",obj), + Object::While {condition:_,instruction:_} => "".fmt(f) + } + } +} +// Change to be an Action +/// Evaluates most expressions recursively, with base cases being recognised primitives. +fn eval_expr(expression: Expr, env: &mut Env) -> Object { + match expression { + // Match primitives into their objective form + Expr::String(string) => Object::String(string), + Expr::Integer(num) => Object::Integer(num), + Expr::Boolean(val) => Object::Boolean(val), + + /* + While {statement,body} => { + eval_expr(statement) => true,false -> break out and return blank eval + easy + } + */ + + /* + Input needs to call a stdin but print first. logic needs to be handled elsewhere. + + */ + + /* + not sure how to do elif*/ + // Call prefix notation expressions into here + Expr::Prefix { prefix, value } => eval_prefix(prefix, value, env), + + // Call infix notation here + Expr::Infix { + left, + operator, + right, + } => eval_infix(left, operator, right, env), + + Expr::If { + condition, + consequence, + alternative, + } => { + if eval_expr(*condition, env) == Object::Boolean(true) { + eval_statements(consequence, env) + } else { + eval_statements(alternative, env) + } + } + Expr::Variable(name) => env.get(&name).expect("Failed to get variable"), + Expr::Function { parameters, body } => Object::Function { parameters, body }, + + // Control flow + Expr::While { + condition, + instruction, + } => Object::While { + condition, + instruction, + }, + Expr::Builtin { + function_name, + arguments, + } => { + let mut obj_args: Vec = vec![]; + for arg in arguments.iter() { + obj_args.push(eval_expr(arg.clone(), env)); + } + eval_builtin(function_name, obj_args) + } + + // Call logic requires setting up function frames + Expr::Call { + function, + arguments, + } => { + // Prep args by evaluating and appending to vector + let mut obj_args: Vec = vec![]; + for arg in arguments.iter() { + obj_args.push(eval_expr(arg.clone(), env)); + } + + let (parameters, body) = match *function { + // Scope here, clean up logic + Expr::Variable(func_name) => { + match env.get(&func_name) { + // Found a user-defined function + Some(Object::Function { parameters, body }) => (parameters, body), + + // Try checking against inbuilt functions, not implemented + None => { + panic!("Function not found!"); + //return eval_builtin(&func_name, arguments); + } + _ => panic!("attempted to call non-function"), + } + } + Expr::Function { parameters, body } => (parameters, body), + + _ => panic!("attempted to call non-function"), + }; + + // run user defined function + eval_function(body, parameters, obj_args, env) + } + } +} + +/// Evaluates an entire body of statements. +fn eval_statements(statements: Vec, env: &mut Env) -> Object { + let mut result = Object::Null; + + for statement in statements { + result = eval_statement(statement, env); + + if let &Object::Return(_) = &result { + return result; + } + } + result +} + +/// Evaluates primitive statements which are either function declarations, variable definitions or return statements. +fn eval_statement(statement: Statement, env: &mut Env) -> Object { + match statement { + Statement::Define { func_name, func } => { + let value = eval_expr(func, env); + env.set(func_name, value.clone()); + value + } + + Statement::Let { name, value } => { + let value = eval_expr(value, env); + env.set(name, value.clone()); + value + } + + Statement::Expression(expr) => eval_expr(expr, env), + + Statement::Return { value } => Object::Return(Box::new(eval_expr(value, env))), + } +} + +/// Evaluates and unwraps return statements if found. +pub fn eval_return(statements: Vec, env: &mut Env) -> Object { + let result = eval_statements(statements, env); + + match result { + Object::Return(ret) => *ret, + _ => result, // Don't unwrap and deref + } +} + +/// Evaluates a single line. +pub fn eval_return_single(statement: &Statement, env: &mut Env) -> Object { + let result = eval_statement(statement.clone(), env); + + match result { + Object::Return(ret) => *ret, + _ => result, + } +} + +/// Binds any arguments passed in to the function scope created, returning the scope of the function. +fn bind_local_vars(args: Vec, parameters: Vec, env: &mut Env) -> Env { + // for i in .... env set in the newest env + assert_eq!(parameters.len(),args.len(), + "Function called with incorrect number of arguments, {} arguments required instead {} were found.",parameters.len(),args.len() + ); + + let mut closed_env = Env::new_enclosing(env.clone()); + for (param, arg) in parameters.iter().zip(args.iter()) { + closed_env.set(arg.clone(), param.clone()); + } + closed_env +} + +/// Sets up a function frame, binds local variables and execeutes the function. +fn eval_function( + func_body: Vec, + args: Vec, + parameters: Vec, + env: &mut Env, +) -> Object { + let mut func_env = bind_local_vars(args, parameters, env); + eval_return(func_body, &mut func_env) +} + +/// Handles unary operations such as negation or turning a number negative. +fn eval_prefix(prefix: Prefix, value: Box, env: &mut Env) -> Object { + match prefix { + // Negative numbers + Prefix::Minus => match eval_expr(*value, env) { + Object::Integer(val) => Object::Integer(-val), + _ => panic!("non numeric type found, - does not support this operation"), + }, + // Logical negation + Prefix::Bang => match eval_expr(*value, env) { + Object::Boolean(val) => Object::Boolean(!val), + _ => panic!("Logical negation op performed on non boolean type"), + }, + //_ => panic!("Prefix type not recognized"), + } +} + +/// Evaluates binary expressions via infix notation. This can include basic arithmetic or comparisons. +fn eval_infix(left: Box, operator: Operator, right: Box, env: &mut Env) -> Object { + match operator { + // Arithmetic group + Operator::Plus + | Operator::Minus + | Operator::Multiply + | Operator::Divide + | Operator::Modulo => eval_infix_op(left, operator, right, env), + // Comparison group + Operator::LessThan + | Operator::GreaterThan + | Operator::Equals + | Operator::LessThanEqual + | Operator::GreaterThanEqual => eval_infix_comp(left, operator, right, env), + _ => panic!("Operator not recognized!"), + } +} + +/// Evaluates arithmetic operations that are of the infix notation. +fn eval_infix_op(left: Box, operator: Operator, right: Box, env: &mut Env) -> Object { + match operator { + // Inner workings, eval left side and right side then check if both are numbers (or similar type) + Operator::Plus => match (eval_expr(*left, env), eval_expr(*right, env)) { + (Object::Integer(left), Object::Integer(right)) => Object::Integer(left + right), + _ => panic!("Unsupported operation between two expressions"), + }, + Operator::Minus => match (eval_expr(*left, env), eval_expr(*right, env)) { + (Object::Integer(left), Object::Integer(right)) => Object::Integer(left - right), + _ => panic!("Unsupported operation between two expressions"), + }, + Operator::Multiply => match (eval_expr(*left, env), eval_expr(*right, env)) { + (Object::Integer(left), Object::Integer(right)) => Object::Integer(left * right), + _ => panic!("Unsupported operation between two expressions"), + }, + Operator::Divide => match (eval_expr(*left, env), eval_expr(*right, env)) { + (Object::Integer(left), Object::Integer(right)) => Object::Integer(left / right), + _ => panic!("Unsupported operation between two expressions"), + }, + + Operator::Modulo => match (eval_expr(*left, env), eval_expr(*right, env)) { + (Object::Integer(left), Object::Integer(right)) => Object::Integer(left % right), + _ => panic!("Unsupported operation between two expressions"), + }, + + _ => panic!("Unsupported arithmetic operator found "), + } +} + +/// Evaluates comparisons that are of the infix notation. +fn eval_infix_comp(left: Box, operator: Operator, right: Box, env: &mut Env) -> Object { + match operator { + Operator::Equals => match (eval_expr(*left, env), eval_expr(*right, env)) { + (Object::Integer(left), Object::Integer(right)) => Object::Boolean(left == right), + (Object::String(left), Object::String(right)) => Object::Boolean(left == right), + _ => panic!("Unsupported operation between two expressions"), + }, + Operator::LessThan => match (eval_expr(*left, env), eval_expr(*right, env)) { + (Object::Integer(left), Object::Integer(right)) => Object::Boolean(left < right), + _ => panic!("Unsupported operation between two expressions"), + }, + Operator::GreaterThan => match (eval_expr(*left, env), eval_expr(*right, env)) { + (Object::Integer(left), Object::Integer(right)) => Object::Boolean(left > right), + _ => panic!("Unsupported operation between two expressions"), + }, + Operator::GreaterThanEqual => match (eval_expr(*left, env), eval_expr(*right, env)) { + (Object::Integer(left), Object::Integer(right)) => Object::Boolean(left >= right), + _ => panic!("Unsupported operation between two expressions"), + }, + Operator::LessThanEqual => match (eval_expr(*left, env), eval_expr(*right, env)) { + (Object::Integer(left), Object::Integer(right)) => Object::Boolean(left <= right), + _ => panic!("Unsupported operation between two expressions"), + }, + Operator::NotEquals => match (eval_expr(*left, env), eval_expr(*right, env)) { + (Object::Integer(left), Object::Integer(right)) => Object::Boolean(left != right), + (Object::String(left), Object::String(right)) => Object::Boolean(left != right), + _ => panic!("Unsupported operation between two expressions"), + }, + + _ => panic!("Unsupported comparison operator encountered"), + } +} + +/// Evaluates builtins that come from the Builtin call. +/// +/// # Current Builtins +/// - len (prints the length of strings) +/// - quwuit (terminates the program) +/// - dprint (prints a statement) +fn eval_builtin(func_name: String, args: Vec) -> Object { + match &func_name as &str { + "len" => len(args), + "quwuit" => Object::Terminate, + "dprint" => dprint(args), + _ => panic!("inbuilt not found!"), + } +} + +/// BUILTIN - len +fn len(args: Vec) -> Object { + match args.as_slice() { + [Object::String(string)] => Object::Integer(string.len() as i64), + _ => panic!("Non measurable type given"), + } +} + +/// BUILTIN - dprint +fn dprint(args: Vec) -> Object { + match args.as_slice() { + [obj] => Object::Print(Box::new(obj.clone())), + _ => panic!("Incorrect args supplied"), + } +} diff --git a/src/eval/mod.rs b/src/eval/mod.rs new file mode 100644 index 0000000..2137c7f --- /dev/null +++ b/src/eval/mod.rs @@ -0,0 +1,5 @@ +//! The eval module evaluates parsed statements and returns object enums. +//! + +pub mod env; +pub mod eval; diff --git a/src/lexer/lexer.rs b/src/lexer/lexer.rs new file mode 100644 index 0000000..624ab63 --- /dev/null +++ b/src/lexer/lexer.rs @@ -0,0 +1,231 @@ +use crate::token::token::{lookup_ident, Token}; +use ::std::iter::Peekable; +use std::str; +use std::str::Chars; + +pub struct Lexer<'a> { + /* + Takes in a string then stores its iterator. + Info: <'a> indicates a speciifed lifetime. + */ + pub chr_iter: Peekable>, +} + +/// Initializes an instance of a lexer which returns a vector of tokens on a string. +/// +/// # Examples +/// +/// Initialize a lexer as follows: +/// ``` +/// let mut lexer = Lexer::new("owo five = 5;"); +/// ``` +impl<'a> Lexer<'a> { + /// Calls next on the char iterator. + pub fn read_char(&mut self) -> Option { + // Returns the next item in the iterator. + self.chr_iter.next() + } + + pub fn peek_char(&mut self) -> Option<&char> { + self.chr_iter.peek() + } + + /// Instantiates a new lexer instance with a char iterator. + pub fn new(file_string: &'a str) -> Lexer<'a> { + Lexer { + chr_iter: file_string.chars().peekable(), + } + } + + /// Consumes all whitespace characters by peaking, making the language independent of whitespace. + pub fn skip_whitespace(&mut self) { + // While not perfect, it's better to use Some over unwrap to avoid None issues. + while let Some(&chr) = self.peek_char() { + if chr.is_whitespace() { + self.read_char(); + } else { + break; + } + } + } + + /// Reads in keywords, variables and function names. + pub fn read_identifier(&mut self, first_letter: char) -> String { + let mut expression: String = String::from(first_letter); + + // Peek at top element, determine if alphabetic then add. + while let Some(&chr) = self.peek_char() { + if chr.is_alphabetic() || chr == '_' { + expression.push(self.read_char().unwrap()); + } else { + break; + } + } + expression + } + + /// Reads in a string which has a specific terminator. + pub fn read_string(&mut self) -> String { + let mut expression: String = String::new(); + + // Peek at top element, determine if alphabetic then add. + while let Some(&chr) = self.peek_char() { + if chr == '"' { + self.read_char(); + break; + } else { + expression.push(self.read_char().unwrap()); + } + } + expression + } + + /// Reads in a sequence of integers and returns an integer. + pub fn read_number(&mut self, first_chr: char) -> i64 { + // TODO: Prefix notation, i.e 0x, 0b, 0o, 0f + let mut expression: String = String::from(first_chr); + + while let Some(&chr) = self.peek_char() { + if char::is_digit(chr, 10) { + expression.push(self.read_char().unwrap()); + } else { + break; + } + } + + expression.parse().unwrap() + } + + /// Reads from the iterator to create the next token. + pub fn next_token(&mut self) -> Token { + self.skip_whitespace(); + + /* + Matching process: + For single character tokens, immediately process. + However for multi-leter tokens, use peak to determine if the next character links up. + */ + match self.read_char() { + // = first, into ASSIGN and EQUAL + Some('=') => { + // Comparison operator + if self.peek_char().unwrap() == &'=' { + self.read_char(); + Token::EQ + } else { + Token::ASSIGN + } + } + Some(',') => Token::COMMA, + Some(';') => Token::SEMICOLON, + + // Alternative (or soon to be default) line end :3 + Some(':') => { + if self.peek_char().unwrap() == &'3' { + self.read_char(); + Token::SEMICOLON + } else { + Token::ILLEGAL(String::from(":")) + } + } + + Some('+') => Token::PLUS, + Some('-') => Token::MINUS, + Some('%') => Token::MOD, + + // TODO: implement power + Some('*') => Token::ASTERISK, + // TODO: implement integer division, comments + Some('/') => { + if self.peek_char().unwrap() == &'*' { + // comments + self.read_char(); + loop { + if self.peek_char().unwrap() == &'*' { + self.read_char(); + if self.peek_char().unwrap() == &'/' { + self.read_char(); + return self.next_token(); + } + } + self.read_char(); + } + } else { + Token::SLASH + } + } + + Some('(') => Token::LPAR, + Some(')') => Token::RPAR, + Some('{') => Token::LBRA, + Some('}') => Token::RBRA, + + Some('>') => { + if self.peek_char().unwrap() == &'=' { + self.read_char(); + Token::GEQ + } else { + Token::GR + } + } + + Some('<') => { + if self.peek_char().unwrap() == &'=' { + self.read_char(); + Token::LEQ + } else { + Token::LE + } + } + + Some('!') => { + if self.peek_char().unwrap() == &'=' { + self.read_char(); + Token::NEQ + } else { + Token::BANG + } + } + + None => Token::EOF, + + Some('"') => Token::STRING(self.read_string()), + + // Deal with expressions and primitives + Some(chr) => { + if chr.is_alphabetic() { + // Converts to either keyword or identifier + let token = self.read_identifier(chr); + lookup_ident(&token as &str) + } + // Could be an integer + else if char::is_digit(chr, 10) { + Token::INT(self.read_number(chr)) + } + // Nothing recognized, spit illegal. + else { + Token::ILLEGAL(String::from(chr)) + } + } + } + } + + /// Returns the vector of tokens from an input. + pub fn lex(&mut self) -> Vec { + let mut token_vec: Vec = Vec::new(); + + loop { + match self.chr_iter.peek() { + None => break, + _ => token_vec.push(self.next_token()), + } + } + if token_vec.last() != Some(&Token::EOF) { + token_vec.push(Token::EOF); + } + // Important, I'm reversing the list because implementation from the back is much better in terms of time complexity. Pop better than remove. + // Potential TODO: Change to stack? + token_vec.reverse(); + token_vec + } +} diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs new file mode 100644 index 0000000..a6929e6 --- /dev/null +++ b/src/lexer/mod.rs @@ -0,0 +1,2 @@ +//! The lexer module turns input into a vector of tokens. +pub mod lexer; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..3637e2a --- /dev/null +++ b/src/main.rs @@ -0,0 +1,33 @@ +//! # What is uwucode? +//! uwucode is an atrocity. In all seriousness, uwucode is a satirical programming language that incorporates egirl slang to make it nearly unreadable. Take for example the following: +//! ``` +//! owo hehexd = 1; +//! uwu nya(lel) {nuzzles (lel==hehexd) {sugoi hehexd;} rawr {sugoi lel*nya(lel-hehexd);};}; +//! nya(5); // -> 120 +//! ``` +//! Of course, one may recognize this is a recursive implementation of the factorial function, however it looks like a mess to anyone else. + +mod eval; +mod lexer; +mod parser; +mod repl; +mod tests; +mod token; +use std::env; + +/// uwucode takes in the following arguments: +/// repl | open +/// # repl +/// Opens a REPl to evaluate uwucode. Takes in no additional arguments. +/// +/// # open +/// Takes in one argument, which is the filepath. +fn main() { + let args: Vec = env::args().collect(); + match args[1].as_ref() { + "repl" => repl::repl::start(), + "open" => repl::interpreter::file_interpret(args[2].as_ref()), + + val => panic!("{} is not a recognized argument", val), + } +} diff --git a/src/parser/ast.rs b/src/parser/ast.rs new file mode 100644 index 0000000..1b7cae3 --- /dev/null +++ b/src/parser/ast.rs @@ -0,0 +1,120 @@ +//! The abstract syntax tree is built of enums within enums. For instance, a let statement, for example: +//! ```no_run +//! let three = 3; +//! ``` +//! This would turn into the tree: +//! ```no_run +//! Let(three,Expr(3)) +//! ``` +//! +//! The complexity of these trees grow, especially when dealing with function calls. +use crate::token::token::Token; + +// TODO: Implement fmt methods for the statements. + +/// Statement enums effectively compose the structure of a line of code. +/// These could be considered the roots of an AST, typically with Expr being the children. +#[derive(Debug, Clone, PartialEq)] +pub enum Statement { + Let { name: String, value: Expr }, + Define { func_name: String, func: Expr }, + Return { value: Expr }, + Expression(Expr), +} + +/// Expressions typically consist of other expressions, and can be considered the children of statements. Any expression type that involves other expressions stores a smart pointer to them. +#[derive(Debug, Clone, PartialEq)] +pub enum Expr { + String(String), + Variable(String), + Boolean(bool), + Integer(i64), + Prefix { + prefix: Prefix, + value: Box, + }, + Infix { + left: Box, + operator: Operator, + right: Box, + }, + If { + condition: Box, + consequence: Vec, + alternative: Vec, + }, + While { + condition: Box, + instruction: Vec, + }, + Function { + parameters: Vec, + body: Vec, + }, + Call { + function: Box, // Function name + arguments: Vec, + }, + + Builtin { + function_name: String, + arguments: Vec, + }, +} + +#[derive(Debug, Clone, PartialEq, Copy)] +pub enum Prefix { + Bang, + Minus, +} + +#[derive(PartialOrd, PartialEq, Debug, Clone, Copy)] +pub enum Precedence { + Lowest, + Equals, + LessGreater, + Sum, + Product, + Prefix, +} +#[derive(Debug, Clone, PartialEq, Copy)] +pub enum Operator { + Plus, + Minus, + Multiply, + Divide, + Modulo, + GreaterThan, + GreaterThanEqual, + LessThan, + LessThanEqual, + Equals, + NotEquals, +} + +pub fn is_builtin(func_name: &str) -> bool { + match func_name { + "len" | "quwuit" | "dprint" => true, + _ => false, + } +} + +impl Token { + /// The priority system determines whether an expression is evaluated as Infix or Prefix. + pub fn priority(&self) -> Precedence { + match self { + Token::PLUS => Precedence::Sum, + Token::MINUS => Precedence::Sum, + Token::SLASH => Precedence::Product, + Token::ASTERISK => Precedence::Product, + Token::MOD => Precedence::Product, + Token::LEQ => Precedence::LessGreater, + Token::LE => Precedence::LessGreater, + Token::GEQ => Precedence::LessGreater, + Token::GR => Precedence::LessGreater, + Token::EQ => Precedence::Equals, + Token::NEQ => Precedence::Equals, + _ => Precedence::Lowest, + } + } +} diff --git a/src/parser/mod.rs b/src/parser/mod.rs new file mode 100644 index 0000000..5d088a0 --- /dev/null +++ b/src/parser/mod.rs @@ -0,0 +1,5 @@ +//! The parser joins together tokens to create statements that consist of expressions. +//! + +pub mod ast; +pub mod parser; diff --git a/src/parser/parser.rs b/src/parser/parser.rs new file mode 100644 index 0000000..16f2b42 --- /dev/null +++ b/src/parser/parser.rs @@ -0,0 +1,288 @@ +//! Handles the parsing of tokens that come from the lexer. +use crate::parser::ast::{is_builtin, Expr, Operator, Precedence, Prefix, Statement}; +use crate::token::token::Token; + +/// The parse function turns a vector of tokens into a vector of statements. This is done by grouping them into one of several categories. +/// +/// # Parse categories +/// - Let (define) +/// - Function (define) +/// - Right brace (end body) +/// - Return (return statement) +/// - EOF (end of file) +/// - Expressions (everything else) +pub fn parse(input: &mut Vec) -> Vec { + let mut statements = vec![]; + + // Process each statement here + loop { + let top_token = match input.last() { + Some(token) => token, + None => panic!("Vec list found empty."), + }; + + match top_token { + Token::EOF => break, // We've reached the end of line or file + Token::LET => parse_let(input, &mut statements), // Define a variable + Token::FUNCTION => parse_function(input, &mut statements), // Define a function + Token::RBRA => break, // We've reached the end of an enclosing + Token::RETURN => parse_return(input, &mut statements), // We've hit a return statement + _ => statements.push(Statement::Expression(parse_expression( + input, + Precedence::Lowest, + ))), // Deal with an expression + } + + // Since the subcalls modify the vector of tokens, we should reach a semicolon at the end. + assert_eq!(input.pop(), Some(Token::SEMICOLON)); + } + + return statements; +} + +/// Parses let statement by resolving an identifier name and an expression. +/// +/// # Technical information +/// The function effectively transforms a line with a let statement into a let expression. +fn parse_let(input: &mut Vec, statements: &mut Vec) { + assert_eq!(input.pop(), Some(Token::LET)); // Sanity check + + // wtfs going on here lol, double enum extraction + let var_name: String = match input.pop() { + Some(Token::IDENT(var)) => var, + _ => panic!("String type not found for variable name."), + }; + + // We're at = stage + assert_eq!(input.pop(), Some(Token::ASSIGN)); + // Now we're at the expression eval stage, leave it to parse expr + let value = parse_expression(input, Precedence::Lowest); + statements.push(Statement::Let { + name: var_name, + value, + }); +} + +fn parse_return(input: &mut Vec, statements: &mut Vec) { + /* + Let's have a look at our Return enum now. Return {value:Expr} which means + we need to just parse the expression. + */ + assert_eq!(input.pop(), Some(Token::RETURN)); + // Now evaluate the expression + let value = parse_expression(input, Precedence::Lowest); + statements.push(Statement::Return { value }); +} + +/// Parses a function definition, which consists of statements from the other categories. +/// +/// # Technical Information +/// The ideal structure of a function takes the following form: +/// DEFINE function_name(args..) { +/// body +/// } +/// This means that each argument and the body have to be individually parsed. +/// +fn parse_function(input: &mut Vec, statements: &mut Vec) { + assert_eq!(input.pop(), Some(Token::FUNCTION)); + + // Next thing is the function name, add it in + let func_name: String = match input.pop() { + Some(Token::IDENT(name)) => name, + a => panic!( + "String not found for the function name, instead found {:?}", + a + ), + }; + + // Now we're at args, first thing is the LPAR + assert_eq!(input.pop(), Some(Token::LPAR)); + + // Read arguments + let mut parameters = vec![]; + + loop { + match input.pop() { + Some(Token::RPAR) => break, + Some(Token::IDENT(var)) => { + // Find an arg, add then proceed + parameters.push(var); // push to vec list + // Either separate the argument, finish reading or panic. + match input.pop() { + Some(Token::RPAR) => break, + Some(Token::COMMA) => continue, + _ => panic!("Object after parameter was not comma or bracket"), + }; + } + _ => panic!("Object after param was not comma or bracket"), + } + } + + // Parse the body + assert_eq!(input.pop(), Some(Token::LBRA)); // { + let body = parse(input); // will return code of inside + assert_eq!(input.pop(), Some(Token::RBRA)); // } + + statements.push(Statement::Define { + func_name, + func: Expr::Function { parameters, body }, + }); +} + +/// Parses most expressions that involve primitives, operators or basic conditionals. +/// +/// # Technical Information +/// +fn parse_expression(input: &mut Vec, precedence: Precedence) -> Expr { + let mut left_expr = match input.pop() { + Some(val) => { + match val { + // This is a Token type + // Primitives + Token::INT(value) => Expr::Integer(value), + Token::TRUE => Expr::Boolean(true), + Token::FALSE => Expr::Boolean(false), + Token::IDENT(value) => { + // for implementing builtin, do a logic check here + if input.last() == Some(&Token::LPAR) { + input.pop(); + let mut args = vec![]; + + loop { + match input.last() { + Some(Token::RPAR) => { + input.pop(); + break; + } + None => panic!("weird stuff happened"), + _ => args.push(parse_expression(input, Precedence::Lowest)), + } + + match input.pop() { + Some(Token::RPAR) => break, + Some(Token::COMMA) => continue, + _ => panic!("Unexpected parameter"), + } + } + if is_builtin(&value as &str) { + Expr::Builtin { + function_name: value, + arguments: args, + } + } else { + Expr::Call { + function: Box::new(Expr::Variable(value)), + arguments: args, + } + } + } else { + Expr::Variable(value) + } + } + Token::STRING(value) => Expr::String(value), + + // Prefix types [A B] + Token::BANG => Expr::Prefix { + prefix: Prefix::Bang, + value: Box::new(parse_expression(input, Precedence::Prefix)), + }, + + Token::MINUS => Expr::Prefix { + prefix: Prefix::Minus, + value: Box::new(parse_expression(input, Precedence::Prefix)), + }, + + // conditional + Token::IF => { + assert_eq!(Some(Token::LPAR), input.pop()); + let condition = parse_expression(input, Precedence::Lowest); + assert_eq!(Some(Token::RPAR), input.pop()); + + // Parse body + assert_eq!(Some(Token::LBRA), input.pop()); + let consequence = parse(input); + assert_eq!(Some(Token::RBRA), input.pop()); + + let alternative = if input.last() == Some(&Token::ELSE) { + // ELSE CONDITION + input.pop(); + assert_eq!(Some(Token::LBRA), input.pop()); + let alternative = parse(input); + assert_eq!(Some(Token::RBRA), input.pop()); + alternative + } else { + // No alternative + Vec::new() + }; + + Expr::If { + condition: Box::new(condition), + consequence, + alternative, + } + } + + // while, control flow 1 + Token::WHILE => { + // While (THING) { do thing} + assert_eq!(Some(Token::LPAR), input.pop()); + let condition = parse_expression(input, Precedence::Lowest); + assert_eq!(Some(Token::RPAR), input.pop()); + + // Parse body + assert_eq!(Some(Token::LBRA), input.pop()); + let instruction = parse(input); + assert_eq!(Some(Token::RBRA), input.pop()); + + Expr::While { + condition: Box::new(condition), + instruction, + } + } + + // Error + _ => panic!("Parser error: Not recognized!"), + } + } + _ => panic!("The vector is empty"), + }; + + // Depending on whether we have a prefix/infix expression, we need to modify evaluation order. + while precedence < input.last().unwrap().priority() { + left_expr = parse_infix(left_expr, input); + } + + left_expr +} + +/// Parses expressions involving an operator in the middle, for instance a OP b. +/// +/// # Technical Information +/// The left token is passed in, then the right token is popped, which results in a new infix expression, with pointers to the left and right expressions. +fn parse_infix(left: Expr, input: &mut Vec) -> Expr { + let next_token = match input.pop() { + Some(value) => value, + None => panic!("Empty list..."), + }; + + let operator = match next_token { + Token::PLUS => Operator::Plus, + Token::MINUS => Operator::Minus, + Token::SLASH => Operator::Divide, + Token::MOD => Operator::Modulo, + Token::ASTERISK => Operator::Multiply, + Token::LEQ => Operator::LessThanEqual, + Token::LE => Operator::LessThan, + Token::GEQ => Operator::GreaterThanEqual, + Token::GR => Operator::GreaterThan, + Token::EQ => Operator::Equals, + Token::NEQ => Operator::NotEquals, + _ => panic!("parse infix called on invalid operator"), + }; + + Expr::Infix { + left: Box::new(left), + operator, + right: Box::new(parse_expression(input, next_token.priority())), + } +} diff --git a/src/repl/interpreter.rs b/src/repl/interpreter.rs new file mode 100644 index 0000000..32de39d --- /dev/null +++ b/src/repl/interpreter.rs @@ -0,0 +1,35 @@ +use crate::eval::eval::{eval_return_single, Env, Object}; +use crate::lexer::lexer::Lexer; +use crate::parser::parser::parse; +use std::fs; +use std::process; + +pub fn file_interpret(file_name: &str) { + println!("uwu *nuzzles* wewcome to uwucode! Is for me..? 🥺👉👈"); + let mut env = Env::new(); + + let file_str = match fs::read_to_string(file_name) { + Ok(val) => val, + Err(_) => panic!("File not found, or unreadable"), + }; + + let mut lexer = Lexer::new(&file_str); + let mut token_vec = lexer.lex(); + + let parsed = parse(&mut token_vec); + /* + Match action, i.e Print, Terminate, or Exit + */ + for parsed_expr in parsed.iter() { + match eval_return_single(parsed_expr, &mut env) { + Object::Terminate => { + println!("{}", Object::Terminate); + process::exit(69); + } + Object::Print(value) => { + println!("{}", value); + } + _ => print!(""), + }; + } +} diff --git a/src/repl/mod.rs b/src/repl/mod.rs new file mode 100644 index 0000000..1ccc3e6 --- /dev/null +++ b/src/repl/mod.rs @@ -0,0 +1,4 @@ +//! The REPL module contains the code that creates a REPL or evaluates a file. + +pub mod interpreter; +pub mod repl; diff --git a/src/repl/repl.rs b/src/repl/repl.rs new file mode 100644 index 0000000..dbd1542 --- /dev/null +++ b/src/repl/repl.rs @@ -0,0 +1,34 @@ +use crate::eval::eval::{eval_return, Env, Object}; +use crate::lexer::lexer::Lexer; +use crate::parser::parser::parse; +use ::std::io::Write; +use std::io; +use std::process; + +use colored::*; + +const PROMPT: &str = "( ᴜ ω ᴜ )⭜"; + +pub fn start() { + println!("uwu *nuzzles* wewcome to uwucode! Is for me..? 🥺👉👈"); + let mut env = Env::new(); + loop { + print!("{} ", PROMPT.truecolor(255, 69, 0)); + std::io::stdout().flush().expect("Flushing failed"); + let mut user_in: String = String::new(); + io::stdin().read_line(&mut user_in).expect("Could not read"); + let mut lexer = Lexer::new(&user_in as &str); + let mut token_vec = lexer.lex(); + + let parsed = parse(&mut token_vec); + + let evaluated = match eval_return(parsed, &mut env) { + Object::Terminate => { + println!("{}", Object::Terminate); + process::exit(69); + } + val => val, + }; + println!("{}", evaluated); + } +} diff --git a/src/tests/lexer_test.rs b/src/tests/lexer_test.rs new file mode 100644 index 0000000..8488eb9 --- /dev/null +++ b/src/tests/lexer_test.rs @@ -0,0 +1,103 @@ +#[cfg(test)] +mod tests { + use crate::lexer; + use crate::token::token::Token; + struct TestingStruct { + token_vec: Vec, + } + #[test] + fn test_token_basic() { + let input: &str = "=+(){},;"; + + let mut test_lexer = lexer::lexer::Lexer::new(input); + + let tests: TestingStruct = TestingStruct { + token_vec: vec![ + Token::ASSIGN, + Token::PLUS, + Token::LPAR, + Token::RPAR, + Token::LBRA, + Token::RBRA, + Token::COMMA, + Token::SEMICOLON, + ], + }; + for test in tests.token_vec.iter() { + let current_token = test_lexer.next_token(); + assert_eq!(test, ¤t_token); + } + } + // Note: The structure below need not follow the syntax of uwucode. + #[test] + fn test_token_strings() { + let input: &str = "owo five = 5; + owo ten = 10; + owo add = uwu(x,y) { + x+y; + }; + "; + + let mut test_lexer = lexer::lexer::Lexer::new(input); + + let tests: TestingStruct = TestingStruct { + token_vec: vec![ + Token::LET, + Token::IDENT(String::from("five")), + Token::ASSIGN, + Token::INT(5), + Token::SEMICOLON, + Token::LET, + Token::IDENT(String::from("ten")), + Token::ASSIGN, + Token::INT(10), + Token::SEMICOLON, + Token::LET, + Token::IDENT(String::from("add")), + Token::ASSIGN, + Token::FUNCTION, + Token::LPAR, + Token::IDENT(String::from("x")), + Token::COMMA, + Token::IDENT(String::from("y")), + Token::RPAR, + Token::LBRA, + Token::IDENT(String::from("x")), + Token::PLUS, + Token::IDENT(String::from("y")), + Token::SEMICOLON, + Token::RBRA, + Token::SEMICOLON, + ], + }; + for test in tests.token_vec.iter() { + let current_token = test_lexer.next_token(); + assert_eq!(test, ¤t_token); + } + } + + #[test] + fn test_keywords() { + let input: &str = "owo uwu nuzzles dab rawr sugoi truwu fowose"; + + let mut test_lexer = lexer::lexer::Lexer::new(input); + let mut tests: TestingStruct = TestingStruct { + token_vec: vec![ + Token::LET, + Token::FUNCTION, + Token::IF, + Token::ELIF, + Token::ELSE, + Token::RETURN, + Token::TRUE, + Token::FALSE, + Token::EOF, + ], + }; + tests.token_vec.reverse(); + + for (test, token) in tests.token_vec.iter().zip(test_lexer.lex().iter()) { + assert_eq!(test, token); + } + } +} diff --git a/src/tests/mod.rs b/src/tests/mod.rs new file mode 100644 index 0000000..323c47c --- /dev/null +++ b/src/tests/mod.rs @@ -0,0 +1,3 @@ +//! Self explanatory. +mod lexer_test; +mod token_test; diff --git a/src/tests/token_test.rs b/src/tests/token_test.rs new file mode 100644 index 0000000..ff80dba --- /dev/null +++ b/src/tests/token_test.rs @@ -0,0 +1,34 @@ +#[cfg(test)] +mod tests { + use crate::token::token::*; + + #[test] + fn test_lookup_ident() { + struct TestingStruct { + token_vec: Vec, + } + let inputs: Vec<&str> = vec![ + "uwu", "owo", "nuzzles", "dab", "rawr", "sugoi", "truwu", "fowose", "Hello!", + ]; + + let tests: TestingStruct = TestingStruct { + token_vec: vec![ + Token::FUNCTION, + Token::LET, + Token::IF, + Token::ELIF, + Token::ELSE, + Token::RETURN, + Token::TRUE, + Token::FALSE, + Token::IDENT(String::from("Hello!")), + ], + }; + // You may ask, what the hell is the resultant iterator here?? Tbh, I'm not sure as well... + // In all seriousness,unlike Python, zip is a method for tying iterators, where the argument (not self!) is the second element. + // Diagram: A.iter().zip(B.iter()) -> iter(a,b). + for (input, test) in inputs.iter().zip(tests.token_vec.iter()) { + assert_eq!(&lookup_ident(input), test); + } + } +} diff --git a/src/token/mod.rs b/src/token/mod.rs new file mode 100644 index 0000000..61de94f --- /dev/null +++ b/src/token/mod.rs @@ -0,0 +1,5 @@ +//! +//! The token module stores the atomic elements require to interpret user input. That means keywords, primitives and everything else is stored in some form of a token. +//! + +pub mod token; diff --git a/src/token/token.rs b/src/token/token.rs new file mode 100644 index 0000000..9907e88 --- /dev/null +++ b/src/token/token.rs @@ -0,0 +1,80 @@ +/// +/// Maps an identifier to a keyword or a variable/function. +/// # Examples +/// +/// Various keywords are mapped to a respective action. +/// ``` +/// let result = lookup_ident("uwu"); // Returns Token::FUNCTION +/// assert_eq!(Token::FUNCTION,result); +/// ``` +/// +/// If the keyword is not recognized, it gets mapped to an identifier. +/// ``` +/// let result = lookup_ident("random_thing"); +/// assert_eq!(Token::IDENT(String::from("random_thing")),result); +/// ``` +/// +/// +pub fn lookup_ident(ident: &str) -> Token { + match ident { + "uwu" => Token::FUNCTION, + "owo" => Token::LET, + "nuzzles" => Token::IF, + "dab" => Token::ELIF, + "rawr" => Token::ELSE, + "sugoi" => Token::RETURN, + "truwu" => Token::TRUE, + "fowose" => Token::FALSE, + "nyaa" => Token::WHILE, + _ => Token::IDENT(String::from(ident)), + } +} + +/// The Token enum is used in the parsing process. It could be called the atomic element of a programming language. +/// +#[derive(PartialEq, Clone, Debug)] +pub enum Token { + ILLEGAL(String), + EOF, + + IDENT(String), + + ASSIGN, + PLUS, + MINUS, + ASTERISK, + SLASH, + MOD, + + EQ, + LEQ, + LE, + GEQ, + GR, + NEQ, + + COMMA, + SEMICOLON, + + LPAR, + RPAR, + LBRA, + RBRA, + + BANG, + + FUNCTION, + LET, + RETURN, + + IF, + ELIF, + ELSE, + + WHILE, + + INT(i64), + STRING(String), + TRUE, + FALSE, +}