From 6d2102e7251dcc2c8d89f4f0b3e8b6286ca46597 Mon Sep 17 00:00:00 2001 From: crc Date: Mon, 21 Sep 2020 13:48:13 +0000 Subject: [PATCH] retro-book: update scripting chapter to reflect namespace changes FossilOrigin-Name: 8128973ed2d7918c7a86255af0736e9a4ae92c355bd6e642ee8cafcaefce8a05 --- doc/RETRO-Book.md | 4653 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 4653 insertions(+) diff --git a/doc/RETRO-Book.md b/doc/RETRO-Book.md index e69de29..0e9cce3 100644 --- a/doc/RETRO-Book.md +++ b/doc/RETRO-Book.md @@ -0,0 +1,4653 @@ +# RETRO: a Modern, Pragmatic Forth + +Welcome to RETRO, my personal take on the Forth language. This +is a modern system primarily targetting desktop, mobile, and +servers, though it can also be used on some larger (ARM, MIPS32) +embedded systems. + +The language is Forth. It is untyped, uses a stack to pass data +between functions called words, and a dictionary which tracks +the word names and data structures. + +But it's not a traditional Forth. RETRO draws influences from +many sources and takes a unique approach to the language. + +RETRO has a large vocabulary of words. Keeping a copy of the +Glossary on hand is highly recommended as you learn to use RETRO. + +This book will hopefully help you develop a better understanding +of RETRO and how it works. + +The text in these files is Copyright (c) 2018-2020 by +Charles Childers. + +To the extent possible under law, Charles Childers has +waived all copyright and related or neighboring rights +to the RETRO Documentation. This work is published from: +United States. + +The historical papers are Copyright (c) 1999-2000 by +Tom Novelli. + +## Legal Text + +See https://creativecommons.org/publicdomain/zero/1.0/legalcode + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work +of authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without +fear of later claims of infringement build upon, modify, incorporate in +other works, reuse and redistribute as freely as possible in any form +whatsoever and for any purposes, including without limitation commercial +purposes. These owners may contribute to the Commons to promote the +ideal of a free culture and the further production of creative, cultural +and scientific works, or to gain reputation or greater distribution for +their Work in part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or +she is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under +its terms, with knowledge of his or her Copyright and Related Rights in +the Work and the meaning and intended legal effect of CC0 on those +rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + +- the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; +- moral rights retained by the original author(s) and/or performer(s); +- publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; +- rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; +- rights protecting the extraction, dissemination, use and reuse of data + in a Work; +- database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation thereof, + including any amended or successor version of such directive); and +- other similar, equivalent or corresponding rights throughout the world + based on applicable law or treaty, and any national implementations + thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or +future medium and for any number of copies, and (iv) for any purpose +whatsoever, including without limitation commercial, advertising or +promotional purposes (the "Waiver"). Affirmer makes the Waiver for the +benefit of each member of the public at large and to the detriment of +Affirmer's heirs and successors, fully intending that such Waiver shall +not be subject to revocation, rescission, cancellation, termination, or +any other legal or equitable action to disrupt the quiet enjoyment of +the Work by the public as contemplated by Affirmer's express Statement +of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non +exclusive, irrevocable and unconditional license to exercise Affirmer's +Copyright and Related Rights in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or +future medium and for any number of copies, and (iv) for any purpose +whatsoever, including without limitation commercial, advertising or +promotional purposes (the "License"). The License shall be deemed +effective as of the date CC0 was applied by Affirmer to the Work. Should +any part of the License for any reason be judged legally invalid or +ineffective under applicable law, such partial invalidity or +ineffectiveness shall not invalidate the remainder of the License, and +in such case Affirmer hereby affirms that he or she will not (i) +exercise any of his or her remaining Copyright and Related Rights in the +Work or (ii) assert any associated claims and causes of action with +respect to the Work, in either case contrary to Affirmer's express +Statement of Purpose. + +4. Limitations and Disclaimers. + +No trademark or patent rights held by Affirmer are waived, abandoned, +surrendered, licensed or otherwise affected by this document. + +Affirmer offers the Work as-is and makes no representations or +warranties of any kind concerning the Work, express, implied, statutory +or otherwise, including without limitation warranties of title, +merchantability, fitness for a particular purpose, non infringement, or +the absence of latent or other defects, accuracy, or the present or +absence of errors, whether or not discoverable, all to the greatest +extent permissible under applicable law. + +Affirmer disclaims responsibility for clearing rights of other persons +that may apply to the Work or any use thereof, including without +limitation any person's Copyright and Related Rights in the Work. +Further, Affirmer disclaims responsibility for obtaining any necessary +consents, permissions or other rights required for any use of the Work. + +Affirmer understands and acknowledges that Creative Commons is not a +party to this document and has no duty or obligation with respect to +this CC0 or use of the Work. + +---- + +The Code It Yourself Manifesto is Copyright (c) 2016 by +Christian Kellermann and is used under the +Attribution-ShareAlike 3.0 Unported (CC BY-SA 3.0) license. + +This license reads: + +THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE +COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY +COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS +AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED. + +BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE +TO BE BOUND BY THE TERMS OF THIS LICENSE. TO THE EXTENT THIS LICENSE MAY +BE CONSIDERED TO BE A CONTRACT, THE LICENSOR GRANTS YOU THE RIGHTS +CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND +CONDITIONS. + +1. Definitions + +"Adaptation" means a work based upon the Work, or upon the Work and +other pre-existing works, such as a translation, adaptation, derivative +work, arrangement of music or other alterations of a literary or +artistic work, or phonogram or performance and includes cinematographic +adaptations or any other form in which the Work may be recast, +transformed, or adapted including in any form recognizably derived from +the original, except that a work that constitutes a Collection will not +be considered an Adaptation for the purpose of this License. For the +avoidance of doubt, where the Work is a musical work, performance or +phonogram, the synchronization of the Work in timed-relation with a +moving image ("synching") will be considered an Adaptation for the +purpose of this License. + +"Collection" means a collection of literary or artistic works, such as +encyclopedias and anthologies, or performances, phonograms or +broadcasts, or other works or subject matter other than works listed in +Section 1(f) below, which, by reason of the selection and arrangement of +their contents, constitute intellectual creations, in which the Work is +included in its entirety in unmodified form along with one or more other +contributions, each constituting separate and independent works in +themselves, which together are assembled into a collective whole. A work +that constitutes a Collection will not be considered an Adaptation (as +defined below) for the purposes of this License. + +"Creative Commons Compatible License" means a license that is listed at +https://creativecommons.org/compatiblelicenses that has been approved by +Creative Commons as being essentially equivalent to this License, +including, at a minimum, because that license: (i) contains terms that +have the same purpose, meaning and effect as the License Elements of +this License; and, (ii) explicitly permits the relicensing of +adaptations of works made available under that license under this +License or a Creative Commons jurisdiction license with the same License +Elements as this License. + +"Distribute" means to make available to the public the original and +copies of the Work or Adaptation, as appropriate, through sale or other +transfer of ownership. + +"License Elements" means the following high-level license attributes as +selected by Licensor and indicated in the title of this License: +Attribution, ShareAlike. + +"Licensor" means the individual, individuals, entity or entities that +offer(s) the Work under the terms of this License. + +"Original Author" means, in the case of a literary or artistic work, the +individual, individuals, entity or entities who created the Work or if +no individual or entity can be identified, the publisher; and in +addition (i) in the case of a performance the actors, singers, +musicians, dancers, and other persons who act, sing, deliver, declaim, +play in, interpret or otherwise perform literary or artistic works or +expressions of folklore; (ii) in the case of a phonogram the producer +being the person or legal entity who first fixes the sounds of a +performance or other sounds; and, (iii) in the case of broadcasts, the +organization that transmits the broadcast. + +"Work" means the literary and/or artistic work offered under the terms +of this License including without limitation any production in the +literary, scientific and artistic domain, whatever may be the mode or +form of its expression including digital form, such as a book, pamphlet +and other writing; a lecture, address, sermon or other work of the same +nature; a dramatic or dramatico-musical work; a choreographic work or +entertainment in dumb show; a musical composition with or without words; +a cinematographic work to which are assimilated works expressed by a +process analogous to cinematography; a work of drawing, painting, +architecture, sculpture, engraving or lithography; a photographic work +to which are assimilated works expressed by a process analogous to +photography; a work of applied art; an illustration, map, plan, sketch +or three-dimensional work relative to geography, topography, +architecture or science; a performance; a broadcast; a phonogram; a +compilation of data to the extent it is protected as a copyrightable +work; or a work performed by a variety or circus performer to the extent +it is not otherwise considered a literary or artistic work. + +"You" means an individual or entity exercising rights under this License +who has not previously violated the terms of this License with respect +to the Work, or who has received express permission from the Licensor to +exercise rights under this License despite a previous violation. + +"Publicly Perform" means to perform public recitations of the Work and +to communicate to the public those public recitations, by any means or +process, including by wire or wireless means or public digital +performances; to make available to the public Works in such a way that +members of the public may access these Works from a place and at a place +individually chosen by them; to perform the Work to the public by any +means or process and the communication to the public of the performances +of the Work, including by public digital performance; to broadcast and +rebroadcast the Work by any means including signs, sounds or images. + +"Reproduce" means to make copies of the Work by any means including +without limitation by sound or visual recordings and the right of +fixation and reproducing fixations of the Work, including storage of a +protected performance or phonogram in digital form or other electronic +medium. + +2. Fair Dealing Rights. Nothing in this License is intended to reduce, +limit, or restrict any uses free from copyright or rights arising from +limitations or exceptions that are provided for in connection with the +copyright protection under copyright law or other applicable laws. + +3. License Grant. Subject to the terms and conditions of this License, +Licensor hereby grants You a worldwide, royalty-free, non-exclusive, +perpetual (for the duration of the applicable copyright) license to +exercise the rights in the Work as stated below: + +- to Reproduce the Work, to incorporate the Work into one or more + Collections, and to Reproduce the Work as incorporated in the + Collections; + +- to create and Reproduce Adaptations provided that any such Adaptation, + including any translation in any medium, takes reasonable steps to + clearly label, demarcate or otherwise identify that changes were made to + the original Work. For example, a translation could be marked "The + original work was translated from English to Spanish," or a modification + could indicate "The original work has been modified."; + +- to Distribute and Publicly Perform the Work including as incorporated in + Collections; and, + +- to Distribute and Publicly Perform Adaptations. + +For the avoidance of doubt: + +Non-waivable Compulsory License Schemes. In those jurisdictions in which +the right to collect royalties through any statutory or compulsory +licensing scheme cannot be waived, the Licensor reserves the exclusive +right to collect such royalties for any exercise by You of the rights +granted under this License; + +Waivable Compulsory License Schemes. In those jurisdictions in which the +right to collect royalties through any statutory or compulsory licensing +scheme can be waived, the Licensor waives the exclusive right to collect +such royalties for any exercise by You of the rights granted under this +License; and, + +Voluntary License Schemes. The Licensor waives the right to collect +royalties, whether individually or, in the event that the Licensor is a +member of a collecting society that administers voluntary licensing +schemes, via that society, from any exercise by You of the rights +granted under this License. + +The above rights may be exercised in all media and formats whether now +known or hereafter devised. The above rights include the right to make +such modifications as are technically necessary to exercise the rights +in other media and formats. Subject to Section 8(f), all rights not +expressly granted by Licensor are hereby reserved. + +4. Restrictions. The license granted in Section 3 above is expressly +made subject to and limited by the following restrictions: + +You may Distribute or Publicly Perform the Work only under the terms of +this License. You must include a copy of, or the Uniform Resource +Identifier (URI) for, this License with every copy of the Work You +Distribute or Publicly Perform. You may not offer or impose any terms on +the Work that restrict the terms of this License or the ability of the +recipient of the Work to exercise the rights granted to that recipient +under the terms of the License. You may not sublicense the Work. You +must keep intact all notices that refer to this License and to the +disclaimer of warranties with every copy of the Work You Distribute or +Publicly Perform. When You Distribute or Publicly Perform the Work, You +may not impose any effective technological measures on the Work that +restrict the ability of a recipient of the Work from You to exercise the +rights granted to that recipient under the terms of the License. This +Section 4(a) applies to the Work as incorporated in a Collection, but +this does not require the Collection apart from the Work itself to be +made subject to the terms of this License. If You create a Collection, +upon notice from any Licensor You must, to the extent practicable, +remove from the Collection any credit as required by Section 4(c), as +requested. If You create an Adaptation, upon notice from any Licensor +You must, to the extent practicable, remove from the Adaptation any +credit as required by Section 4(c), as requested. + +You may Distribute or Publicly Perform an Adaptation only under the +terms of: (i) this License; (ii) a later version of this License with +the same License Elements as this License; (iii) a Creative Commons +jurisdiction license (either this or a later license version) that +contains the same License Elements as this License (e.g., +Attribution-ShareAlike 3.0 US)); (iv) a Creative Commons Compatible +License. If you license the Adaptation under one of the licenses +mentioned in (iv), you must comply with the terms of that license. If +you license the Adaptation under the terms of any of the licenses +mentioned in (i), (ii) or (iii) (the "Applicable License"), you must +comply with the terms of the Applicable License generally and the +following provisions: (I) You must include a copy of, or the URI for, +the Applicable License with every copy of each Adaptation You Distribute +or Publicly Perform; (II) You may not offer or impose any terms on the +Adaptation that restrict the terms of the Applicable License or the +ability of the recipient of the Adaptation to exercise the rights +granted to that recipient under the terms of the Applicable License; +(III) You must keep intact all notices that refer to the Applicable +License and to the disclaimer of warranties with every copy of the Work +as included in the Adaptation You Distribute or Publicly Perform; (IV) +when You Distribute or Publicly Perform the Adaptation, You may not +impose any effective technological measures on the Adaptation that +restrict the ability of a recipient of the Adaptation from You to +exercise the rights granted to that recipient under the terms of the +Applicable License. This Section 4(b) applies to the Adaptation as +incorporated in a Collection, but this does not require the Collection +apart from the Adaptation itself to be made subject to the terms of the +Applicable License. + +If You Distribute, or Publicly Perform the Work or any Adaptations or +Collections, You must, unless a request has been made pursuant to +Section 4(a), keep intact all copyright notices for the Work and +provide, reasonable to the medium or means You are utilizing: (i) the +name of the Original Author (or pseudonym, if applicable) if supplied, +and/or if the Original Author and/or Licensor designate another party or +parties (e.g., a sponsor institute, publishing entity, journal) for +attribution ("Attribution Parties") in Licensor's copyright notice, +terms of service or by other reasonable means, the name of such party or +parties; (ii) the title of the Work if supplied; (iii) to the extent +reasonably practicable, the URI, if any, that Licensor specifies to be +associated with the Work, unless such URI does not refer to the +copyright notice or licensing information for the Work; and (iv) , +consistent with Ssection 3(b), in the case of an Adaptation, a credit +identifying the use of the Work in the Adaptation (e.g., "French +translation of the Work by Original Author," or "Screenplay based on +original Work by Original Author"). The credit required by this Section +4(c) may be implemented in any reasonable manner; provided, however, +that in the case of a Adaptation or Collection, at a minimum such credit +will appear, if a credit for all contributing authors of the Adaptation +or Collection appears, then as part of these credits and in a manner at +least as prominent as the credits for the other contributing authors. +For the avoidance of doubt, You may only use the credit required by this +Section for the purpose of attribution in the manner set out above and, +by exercising Your rights under this License, You may not implicitly or +explicitly assert or imply any connection with, sponsorship or +endorsement by the Original Author, Licensor and/or Attribution Parties, +as appropriate, of You or Your use of the Work, without the separate, +express prior written permission of the Original Author, Licensor and/or +Attribution Parties. + +Except as otherwise agreed in writing by the Licensor or as may be +otherwise permitted by applicable law, if You Reproduce, Distribute or +Publicly Perform the Work either by itself or as part of any Adaptations +or Collections, You must not distort, mutilate, modify or take other +derogatory action in relation to the Work which would be prejudicial to +the Original Author's honor or reputation. Licensor agrees that in those +jurisdictions (e.g. Japan), in which any exercise of the right granted +in Section 3(b) of this License (the right to make Adaptations) would be +deemed to be a distortion, mutilation, modification or other derogatory +action prejudicial to the Original Author's honor and reputation, the +Licensor will waive or not assert, as appropriate, this Section, to the +fullest extent permitted by the applicable national law, to enable You +to reasonably exercise Your right under Section 3(b) of this License +(right to make Adaptations) but not otherwise. + +5. Representations, Warranties and Disclaimer + +UNLESS OTHERWISE MUTUALLY AGREED TO BY THE PARTIES IN WRITING, LICENSOR +OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY +KIND CONCERNING THE WORK, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, +INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, +FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF +LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, +WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE +EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU. + +6. Limitation on Liability. EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE +LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR +ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES +ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS +BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. Termination + +This License and the rights granted hereunder will terminate +automatically upon any breach by You of the terms of this License. +Individuals or entities who have received Adaptations or Collections +from You under this License, however, will not have their licenses +terminated provided such individuals or entities remain in full +compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will +survive any termination of this License. Subject to the above terms and +conditions, the license granted here is perpetual (for the duration of +the applicable copyright in the Work). Notwithstanding the above, +Licensor reserves the right to release the Work under different license +terms or to stop distributing the Work at any time; provided, however +that any such election will not serve to withdraw this License (or any +other license that has been, or is required to be, granted under the +terms of this License), and this License will continue in full force and +effect unless terminated as stated above. 8. Miscellaneous + +Each time You Distribute or Publicly Perform the Work or a Collection, +the Licensor offers to the recipient a license to the Work on the same +terms and conditions as the license granted to You under this License. + +Each time You Distribute or Publicly Perform an Adaptation, Licensor +offers to the recipient a license to the original Work on the same terms +and conditions as the license granted to You under this License. + +If any provision of this License is invalid or unenforceable under +applicable law, it shall not affect the validity or enforceability of +the remainder of the terms of this License, and without further action +by the parties to this agreement, such provision shall be reformed to +the minimum extent necessary to make such provision valid and +enforceable. + +No term or provision of this License shall be deemed waived and no +breach consented to unless such waiver or consent shall be in writing +and signed by the party to be charged with such waiver or consent. + +This License constitutes the entire agreement between the parties with +respect to the Work licensed here. There are no understandings, +agreements or representations with respect to the Work not specified +here. Licensor shall not be bound by any additional provisions that may +appear in any communication from You. This License may not be modified +without the mutual written agreement of the Licensor and You. + +The rights granted under, and the subject matter referenced, in this +License were drafted utilizing the terminology of the Berne Convention +for the Protection of Literary and Artistic Works (as amended on +September 28, 1979), the Rome Convention of 1961, the WIPO Copyright +Treaty of 1996, the WIPO Performances and Phonograms Treaty of 1996 and +the Universal Copyright Convention (as revised on July 24, 1971). These +rights and subject matter take effect in the relevant jurisdiction in +which the License terms are sought to be enforced according to the +corresponding provisions of the implementation of those treaty +provisions in the applicable national law. If the standard suite of +rights granted under applicable copyright law includes additional rights +not granted under this License, such additional rights are deemed to be +included in the License; this License is not intended to restrict the +license of any rights under applicable law. + +# Obtaining RETRO + +## Stable Releases + +I periodically make stable releases. This will typically happen +two to four times per year. These are good for those needing a +solid base that doesn't change frequently. + +- http://forthworks.com/retro +- http://forth.works + +## Snapshots + +A lot of development happens between releases. I make snapshots +of my working source tree nightly (and often more often). + +This is what I personally recommend for most users. It reflects +my latest system and is normally reliable as it's used daily in +production. + +The latest snapshot can be downloaded from the following stable +URLs: + +* http://forthworks.com/retro/r/latest.tar.gz +* gopher://forthworks.com/9/retro/r/latest.tar.gz + +## Repository + +I use a Fossil repository to manage development. To obtain a +copy of the repository install Fossil and: + + fossil clone http://forthworks.com:8000 retro.fossil + mkdir retro + cd retro + fossil open /path/to/retro.fossil + +See the Fossil documentation for details on using Fossil to +keep your local copy of the repository current. + +This will let you stay current with my latest changes faster +than the snapshots, but you may occasionally encounter bigger +problems as some commits may be in a partially broken state. + +If you have problems, check the version of Fossil you are +using. I am currently using Fossil 2.10, you may experience +issues checking out or cloning if using older versions. + +# Building on BSD, Linux, macOS, and outher Inix Targets + +RETRO is well supported on BSD (tested on FreeBSD, NetBSD, +OpenBSD), Linux, and macOS systems. It should build on any +of these without issue. + +## Requirements + +- c compiler & linker +- standard headers +- make + +## Process + +For a standard 32-bit system: + +Run `make` + +For a 64-bit system: + +Run `make OPTIONS=-DBIT64` + +This will build the toolchain and then the main `retro` +executable. + +## Executables + +In the `bin/` directory: + + retro + retro-unu + retro-muri + retro-extend + retro-embedimage + retro-describe + +## Platform Specific Notes + +In addition to the 64-bit build, it is possible to override the +image size, address stack depth, and data stack depth by defining +the appropriate elements. + +E.g., for a 64-bit build with: + + 4,000,000 cells of memory + 4,000 item limit on data stack + 500 item limit on address stack + +Run `make OPTIONS="-DBIT64 -DIMAGE_SIZE=4000000 -DSTACK_DEPTH=4000 -DADDRESSES=500"` + + +### Haiku + +To build on Haiku, you need to link with the *network* library. +E.g.: + + make LDFLAGS=-lnetwork + +## Issues + +If you run into any build issues, please send details to +crc@forth.works so I can work on addressing them as quickly +as possible. + +# Building RETRO on Windows + +It is possible to build RETRO on Windows, though a few of the +extensions are not supported: + +- no `unix:` words +- no `gopher:` words + +This is currently more difficult than on a Unix host. If you have +Windows 10 and WSL, it may be better to build under that (using +the Unix instructions). + +## Setup Build Environment + +RETRO on Windows is built with TCC. + +Go to http://download.savannah.gnu.org/releases/tinycc/ + +Download the *winapi-full* and *tcc-xxxx-bin* packages for your +system. Decompress them, copy the headers from the winapi +package into the tcc directory. + +## Prepare Source + +Copy the `source/interfaces/retro-windows.c` and the +`source/interfaces/retro-windows.c` to the directory you setup +tcc into. + +## Build + +Building will require use of the command line. Assuming that +tcc.exe is in the current directory along with the RETRO sources: + + tcc retro-windows.c -o retro.exe + +# Building Alternative Systems + +In addition to the C implementation, there are a few other +interfaces that can be built. + +## Requirements + +- c compiler (tested: clang, tcc, gcc) +- make +- standard unix shell + +## retro-repl + +A basic interactive system can be built by using: + + make bin/retro-repl + +This requires a copy of `ngaImage` to be in the current +directory. + +## Barebones + +This is a minimal version of the `retro-repl`. It keeps the C +portion as short as possible, making it a useful starting point +for new interfaces. + +To build: + + make bin/retro-barebones + +## retro-compiler + +This is a turnkey compiler. It can compile a new executable +bundling a Retro VM and image. + +Requirements: + +- BSD or Linux +- objcopy in $PATH + +To build: + + make bin/retro-compiler + +Example use: + +1. Given a source file like "Hello.forth": + + ~~~ + :hello 'hello_world! s:put nl ; + ~~~ + +2. Use: + + ./bin/retro-compiler Hello.forth hello + +The first argument is the source file, the second is the +word to run on startup. + +3. Run the generated `a.out` + +Limits: + +This only supports the core words ('all' interface) and the +file i/o words. Support for other I/O extensions will be +added in the future. + +## Pascal + +There is a Pascal version of `retro-repl`. + +Dependencies: + +- freepascal + +Building: + + cd vm/nga-pascal + fpc listener.lpr + +This will require a copy of the `ngaImage` in the +current directory. + +## Python: retro.py + +This is an implementation of `retro-repl` in Python. As +with `retro-repl` it requires the `ngaImage` in the current +directory when starting. + +## C#: retro.cs + +This is an implementation of `retro-repl` in C#. As with +`retro-repl` it requires the `ngaImage` in the current +directory when starting. + +Building: + + cd vm\nga-csharp + csc retro.cs + +You'll need to make sure your path has the CSC.EXE in it, +or provide a full path to it. Something like this should +reveal the path to use: + + dir /s %WINDIR%\CSC.EXE + +I've only tested building this using Microsoft's .NET tools. +It should also build and run under Mono. + +# Advanced Builds + +## Custom Image + +For users of BSD, Linux, macOS, you can customize the image at +build time. + +In the top level directory is a `package` directory containing +a file named `list.forth`. You can add files to compile into +your system by adding them to the `list.forth` and rebuilding. + +Example: + +If you have wanted to include the NumbersWithoutPrefixes.forth +example, add: + + ~~~ + 'example/NumbersWithoutPrefixes.forth include + ~~~ + +To the start of the `list.forth` file and then run `make` again. +The newly built `bin/retro` will now include your additions. + +# Starting RETRO + +RETRO can be run for scripting or interactive use. + +## Interactive + +To start it interactively, run: `retro` without any command line +arguments, or with `-i`, `-s`, or `-i,c`. + +Starting the interactive system: + +``` +retro +``` + +Or: + +``` +retro -i +``` + +This should be sufficient for most uses. + +Starting the interactive system (without displaying the +startup banner): + +``` +retro -s +``` + +## Using In a Pipe + +If using a Unix shell and piping input between processes, you +will probably want to use `-s` to supress the startup messages +and `Ok` prompt that normally appear. + +E.g., + +``` +echo "'lol s:put nl" | retro -s +``` + +## Running A Program In A File + +You can run code in a file very easily. This is simply: + +``` +retro filename +``` + +You can follow the filename with any arguments that it may need. +These will be accessible to the program via the `sys:argc` and +`sys:argv` words. + +Source files must be written in Unu format. + +## Scripting + +You can use RETRO to write scripts. Add a shebang: + +``` +#!/usr/bin/env retro +``` + +And make the file executable. + +Source files must be written in Unu format. + +## Command Line Arguments + +For a summary of the full command line arguments available: + + Scripting Usage: + + retro filename [script arguments...] + + Interactive Usage: + + retro [-h] [-i] [-c] [-s] [-f filename] [-t] + + -h Display this help text + -i Interactive mode (line buffered) + -s Suppress the startup text + -f filename Run the contents of the specified file + -t Run tests (in ``` blocks) in any loaded files + +# Basic Interactions + +Start RETRO in interactive mode: + +``` +retro -i +``` + +You should see something similar to this: + + RETRO 12 (rx-2019.6) + 8388608 MAX, TIB @ 1025, Heap @ 9374 + +At this point you are at the *listener*, which reads and +processes your input. You are now set to begin exploring +RETRO. + +To exit, run `bye`: + +``` +bye +``` + +# Unu: Simple, Literate Source Files + +RETRO is written in a literate style. Most of the sources +are in a format called Unu. This allows easy mixing of +commentary and code blocks, making it simple to document +the code. + +As an example, + + # Determine The Average Word Name Length + + To determine the average length of a word name two values + are needed. First, the total length of all names in the + Dictionary: + + ~~~ + #0 [ d:name s:length + ] d:for-each + ~~~ + + And then the number of words in the Dictionary: + + ~~~ + #0 [ drop n:inc ] d:for-each + ~~~ + + With these, a simple division is all that's left. + + ~~~ + / + ~~~ + + Finally, display the results: + + + ~~~ + 'Average_name_length:_%n\n s:format s:put + ~~~ + +This illustrates the format. Only code in the fenced blocks +(between \~~~ pairs) get extracted and run. + +(Note: this only applies to *source files*; fences are not used +when entering code interactively). + +## On The Name + +The name Unu comes from the Maori language, where it means: + + (verb) (-hia) pull out, withdraw, draw out, extract. + Taken from https://maoridictionary.co.nz/ + +# A Quick Tutorial + +Programming in RETRO is all about creating words to solve +the problem at hand. Words operate on data, which can be +kept in memory or on the stack. + +Let's look at this by solving a small problem: writing a +word to determine if a string is a palindrome. + +A palindrome is a phrase which reads the same backward +and forward. + +We first need a string to look at. Starting with something +easy: + +``` +'anna +``` + +Looking in the Glossary, there is a `s:reverse` word for +reversing a string. We can find `dup` to copy a value, and +`s:eq?` to compare two strings. So testing: + +``` +'anna dup s:reverse s:eq? +``` + +This yields -1 (`TRUE`) as expected. So we can easily +name it: + +``` +:palindrome? dup s:reverse s:eq? ; +``` + +Naming uses the `:` prefix to add a new word to the dictionary. +The words that make up the definition are then placed, with a +final word (`;`) ending the definition. We can then use this: + +``` +'anna palindrome? +``` + +Once defined there is no difference between our new word and +any of the words already provided by the RETRO system. + +# Syntax + +RETRO has more syntax than a traditional Forth due to ideas +borrowed from ColorForth and some design decisions. This has +some useful traits, and helps to make the language more +consistent. + +## Tokens + +Input is divided into a series of whitespace delimited tokens. +Each of these is then processed individually. There are no +parsing words in RETRO. + +Tokens may have a single character *prefix*, which RETRO will +use to decide how to process the token. + +## Prefixes + +Prefixes are single characters added to the start of a token +to guide the compiler. The use of these is a major way in +which RETRO differs from traditional Forth. + +When a token is passed to `interpret`, RETRO first takes the +intitial character and looks to see if there is a word that +matches this. If so, it will pass the rest of the token to +that word to handle. + +In a traditional Forth, the interpret process is something +like: + + get token + is token in the dictionary? + yes: + is it immediate? + yes: call the word. + no: are we interpreting? + yes: call the word + no: compile a call to the word + no: + is it a number? + yes: are we interpreting? + yes: push the number to the stack + no: compile the number as a literal + no: report an error ("not found") + +In RETRO, the interpret process is basically: + + get token + does the first character match a `prefix:` word? + yes: pass the token to the prefix handler + no: is token a word in the dictionary? + yes: push the XT to the stack and call the + class handler + no: report an error ("not found") + +All of the actual logic for how to deal with tokens is moved +to the individual prefix handlers, and the logic for handling +words is moved to word class handlers. + +This means that prefixes are used for a lot of things. Numbers? +Handled by a `#` prefix. Strings? Use the `'` prefix. Comments? +Use `(`. Making a new word? Use the `:` prefix. + +The major prefixes are: + + | Prefix | Used For | + | ------ | ----------------------------- | + | @ | Fetch from variable | + | ! | Store into variable | + | & | Pointer to named item | + | # | Numbers | + | $ | ASCII characters | + | ' | Strings | + | ( | Comments | + | : | Define a word | + +The individual prefixes will be covered in more detail in the +later chapters on working with different data types. + +## Word Classes + +Word classes are words which take a pointer and do something +with it. These are covered in detail in their own chapter, +but essentially they decide *how* to execute or compile specific +types of words. + + +# Additional Tools + +In addition to the core `retro` binary, the `bin` directory +will contain a few other tools. + +## retro + +This is the main RETRO binary. + +## retro-describe + +This is a program that looks up entries in the Glossary. + +At the command line, you can use it like: + + retro-describe s:for-each + +You can pass multiple word names to it: + + retro-describe s:for-each nl d:words + +## retro-embedimage + +This is a program which generates a C file with the ngaImage +contents. It's used when building `retro`. + + retro-embedimage ngaImage + +The output is written to stdout; redirect it as needed. + +## retro-extend + +This is a program which compiles code into the ngaImage. +It's used when building `retro` and when you want to make a +standalone image with custom additions. + +Example command line: + + retro-extend ngaImage example/rot13.forth + +Pass the image name as the first argument, and then file names +as susequent ones. Do *not* use this for things relying on I/O +apart from the basic console output as it doesn't emulate other +devices. If you need to load in things that rely on using the +optional I/O devices, see the **Advanced Builds** chapter. + +## retro-muri + +This is the assembler for Nga. It's used to build the initial +RETRO kernel and can be used by other tools as well. + + retro-muri rx.muri + +## retro-tags and retro-locate + +These tools are intended to be used together. The first tool, +`retro-tags`, will recursively scan the current directory for +RETRO source files and extract the locations of words defined +in them. These will be written to disk in a `tags` file, using +the standard ctags format. + +`retro-locate` takes a word name, and returns the location(s) +where it is defined. This requires a `tags` file to be present. + +Create the `tags` file: + + retro-tags + +Locate a word: + + retro-locate n:square + +## retro-unu + +This is the literate source extraction tool for RETRO. It +is used in building `retro`. + +Example usage: + + retro-unu literate/RetroForth.md + +Output is written to stdout; redirect as neeeded. + +# The Optional Retro Compiler + +In addition to the base system, users of RETRO on Unix hosts +with ELF executables can build and use the `retro-compiler` +to generate turnkey executables. + +## Requirements + +- Unix host +- ELF executable support +- `objcpy` in the $PATH + +## Building + +BSD users: + + make bin/retro-compiler + +Linux users: + + make -f Makefile.linux bin/retro-compiler + +## Installing + +Copy `bin/retro-compiler` to somewhere in your $PATH. + +## Using + +`retro-compiler` takes two arguments: the source file to +compile and the name of the word to use as the main entry +point. + +Example: + +Given a `hello.forth`: + + ~~~ + :hello 'Hello_World! s:put nl ; + ~~~ + +Use: + + retro-compiler hello.forth hello + +The compiler will generate an `a.out` file which you can +then rename. + +## Known Limitations + +This does not provide the scripting support for command line +arguments that the standard `retro` interface offers. + +A copy of `objcopy` needs to be in the path for compilation +to work. + +The current working directory must be writable. + +This only supports hosts using ELF executables. + +The output file name is fixed to `a.out`. + +RETRO(1) General Commands Manual RETRO(1) + +RETRO + retro - a modern, pragmatic forth development system + +SYNOPSIS + retro [-h] [-i] [-t] [-f filename] [-u filename] [-r filename] + [filename script-args] + +DESCRIPTION + RETRO is a modern, pragmatic Forth drawing influences from many sources. + It's clean, elegant, tiny, and easy to grasp and adapt to various uses. + + retro is the main interface for interacting with Retro. It provides both + an interactive and a scripting model. + +OPTIONS + -h Display a help screen. + + -i Start Retro in interactive mode. + + -s Start Retro in interactive mode and supress the startup message. + + -t Run any test blocks in the loaded files. + + -f filename + Run any code blocks in the specified file. + + -u filename + Load and use the specified image file rather than the integral + one. + + -r filename + Load and run the code in the specified image file rather than + the integral one. + + filename script-args + Run code blocks in a single file. Pass script-args to the code + being run. + +AUTHORS + Charles Childers + +OpenBSD 6.4 Setember 2019 OpenBSD 6.4 + +RETRO-DESCRIBE(1) General Commands Manual RETRO-DESCRIBE(1) + +RETRO-DESCRIBE + retro-describe - a modern, pragmatic forth development system + +SYNOPSIS + retro-describe wordname [additional wordnames] + +DESCRIPTION + RETRO is a modern, pragmatic Forth drawing influences from many sources. + It's clean, elegant, tiny, and easy to grasp and adapt to various uses. + + retro-describe is a tool for looking up the description and stack + comments for words in the core language and extensions. It will write + output to stdout. + +AUTHORS + Charles Childers + +OpenBSD 6.4 May 2019 OpenBSD 6.4 + +RETRO-DOCUMENT(1) General Commands Manual RETRO-DOCUMENT(1) + +RETRO-DOCUMENT + retro-document - a modern, pragmatic forth development system + +SYNOPSIS + retro-document filename + +DESCRIPTION + RETRO is a modern, pragmatic Forth drawing influences from many sources. + It's clean, elegant, tiny, and easy to grasp and adapt to various uses. + + retro-document is a tool for generating a listing of the descriptions and + stack comments for all standard word used in a source file. It will write + output to stdout. + +AUTHORS + Charles Childers + +OpenBSD 6.4 May 2019 OpenBSD 6.4 + +RETRO-EMBEDIMAGE(1) General Commands Manual RETRO-EMBEDIMAGE(1) + +RETRO-EMBEDIMAGE + retro-embedimage - a modern, pragmatic forth development system + +SYNOPSIS + retro-embedimage [filename] + +DESCRIPTION + RETRO is a modern, pragmatic Forth drawing influences from many sources. + It's clean, elegant, tiny, and easy to grasp and adapt to various uses. + + retro-embedimage loads the specified image (or `ngaImage` from the + current directory if none is specified). It converts this into C code + that can be compiled for inclusion in a RETRO executable. It will write + the output to stdout. + +AUTHORS + Charles Childers + +OpenBSD 6.4 February 2019 OpenBSD 6.4 + +RETRO-EXTEND(1) General Commands Manual RETRO-EXTEND(1) + +RETRO-EXTEND + retro-extend - a modern, pragmatic forth development system + +SYNOPSIS + retro-extend image filename [filenames] + +DESCRIPTION + RETRO is a modern, pragmatic Forth drawing influences from many sources. + It's clean, elegant, tiny, and easy to grasp and adapt to various uses. + + retro-extend is a tool to load additional code into an image file. It + takes the name of an image file and one or more source files to load into + the image. After completion the image file will be updated with the + changes. + + +CAVETS + retro-extend only emulates the minimal console output device. If the + source files require additional I/O to be present, the extend process + will likely fail to work correctly. + + +AUTHORS + Charles Childers + +OpenBSD 6.4 February 2019 OpenBSD 6.4 + +RETRO-LOCATE(1) General Commands Manual RETRO-LOCATE(1) + +RETRO-LOCATE + retro-locate - a modern, pragmatic forth development system + +SYNOPSIS + retro-locate wordname + +DESCRIPTION + RETRO is a modern, pragmatic Forth drawing influences from many sources. + It's clean, elegant, tiny, and easy to grasp and adapt to various uses. + + retro-locate searches the tags file generated by retro-tags for the + desired word name. Any matches are displayed, along with the line number. + +AUTHORS + Charles Childers + +OpenBSD 6.6 January 2020 OpenBSD 6.6 + +RETRO-MURI(1) General Commands Manual RETRO-MURI(1) + +RETRO-MURI + retro-muri - a modern, pragmatic forth development system + +SYNOPSIS + retro-muri filename + +DESCRIPTION + RETRO is a modern, pragmatic Forth drawing influences from many sources. + It's clean, elegant, tiny, and easy to grasp and adapt to various uses. + + retro-muri is an assembler for Nga, the virtual machine at the heart of + Retro. It is used to build the image file containing the actual Retro + language. + + This will extract the code blocks in the specified file and generate an + image file named `ngaImage`. + +AUTHORS + Charles Childers + +OpenBSD 6.4 February 2019 OpenBSD 6.4 + +RETRO-TAGS(1) General Commands Manual RETRO-TAGS(1) + +RETRO-TAGS + retro-tags - a modern, pragmatic forth development system + +SYNOPSIS + retro-tags + +DESCRIPTION + RETRO is a modern, pragmatic Forth drawing influences from many sources. + It's clean, elegant, tiny, and easy to grasp and adapt to various uses. + + retro-tags is a tool for extracting code from fenced blocks in literate + sources and generating a tags file compatible with ctags. + +AUTHORS + Charles Childers + +OpenBSD 6.4 August 2019 OpenBSD 6.4 + +# Naming Conventions + +Word names in RETRO generally follow the following conventions. + +## General Guidelines + +* Readability is important +* Be consistent +* Don't use a prefix as the first character of a name +* Don't use underscores in word names +* Use short names for indices +* Word names start with a `-` for "not" +* Words returning a flag end in ? + +## Typical Format + +The word names will generally follow a form like: + + [namespace:]name + +The `namespace:` is optional, but recommended for consistency +with the rest of the system and to make it easier to identify +related words. + +## Case + +Word names are lowercase, with a dash (-) for compound names. + + hello + drop-pair + s:for-each + +Variables use TitleCase, with no dash between compound names. + + Base + Heap + StringBuffers + +Constants are UPPERCASE, with a dash (-) for compound names. + + TRUE + FALSE + f:PI + MAX-STRING-LENGTH + +## Namespaces + +Words are grouped into broad namespaces by attaching a short +prefix string to the start of a name. + +The common namespaces are: + + | Prefix | Contains | + | ------- | ------------------------------------------------------ | + | a: | Words operating on simple arrays | + | ASCII: | ASCII character constants for control characters | + | buffer: | Words for operating on a simple linear LIFO buffer | + | c: | Words for operating on ASCII character data | + | class: | Contains class handlers for words | + | d: | Words operating on the Dictionary | + | err: | Words for handling errors | + | io: | General I/O words | + | n: | Words operating on numeric data | + | prefix: | Contains prefix handlers | + | s: | Words operating on string data | + | v: | Words operating on variables | + | file: | File I/O words | + | f: | Floating Point words | + | unix: | Unix system call words | + +## Tips + +### Don't Start Names With Prefix Characters + +Avoid using a prefix as the first character of a word name. RETRO +will look for prefixes first, this will prevent direct use of +the work in question. + +To find a list of prefix characters, do: + + 'prefix: d:words-with + +### Don't Use Underscores + +Underscores in strings are replaced by spaces. This is problematic, +especially with variables. Consider: + + 'test_name var + #188 !test_name + +In this, the string for the name is converted to "test name". The +store in the second line will not add the space, so resolves to an +incorrect address. + +I personally recommend avoiding the use of underscores in any word +names. + +# The Return Stack + +RETRO has two stacks. The primary one is used to pass data +beween words. The second one primarily holds return addresses. + +Each time a word is called, the next address is pushed to +the return stack. + +# Stack Diagrams + +Most words in RETRO have a stack comment. These look like: + + (-) + (nn-n) + +As with all comments, a stack comment begins with `(` and +should end with a `)`. There are two parts to the comment. +On the left side of the `-` is what the word *consumes*. On +the right is what it *leaves*. + +RETRO uses a short notation, with one character per value +taken or left. In general, the following symbols represent +certain types of values. + + | Notation | Represents | + | ------------------- | ----------------------- | + | b, n, m, o, x, y, z | generic numeric values | + | s | string | + | v | variable | + | p, a | pointers | + | q | quotation | + | d | dictionary header | + | f | `TRUE` or `FALSE` flag. | + +In the case of something like `(xyz-m)`, RETRO expects z to be +on the top of the stack, with y below it and x below the y +value. And after execution, a single value (m) will be left on +the stack. + +Words with no stack effect have a comment of (-) + +# Working With Arrays + +RETRO offers a number of words for operating on statically sized +arrays. + +## Namespace + +The words operating on arrays are kept in an `a:` namespace. + +## Creating Arrays + +The easiest way to create an array is to wrap the values in a +`{` and `}` pair: + +``` +{ #1 #2 #3 #4 } +{ 'this 'is 'an 'array 'of 'strings } +{ 'this 'is 'a 'mixed 'array #1 #2 #3 } +``` + +You can also make an array from a quotation which returns +values and the number of values to store in the a: + +``` +[ #1 #2 #3 #3 ] a:counted-results +[ #1 #2 #3 #3 ] a:make +``` + +## Accessing Elements + +You can access a specific value with `a:th` and `fetch` or +`store`: + +``` +{ #1 #2 #3 #4 } #3 a:th fetch +``` + +## Find The Length + +Use `a:length` to find the size of the array. + +``` +{ #1 #2 #3 #4 } a:length +``` + +## Duplicate + +Use `a:dup` to make a copy of an a: + +``` +{ #1 #2 #3 #4 } a:dup +``` + +## Filtering + +RETRO provides `a:filter` which extracts matching values +from an array. This is used like: + +``` +{ #1 #2 #3 #4 #5 #6 #7 #8 } [ n:even? ] a:filter +``` + +The quote will be passed each value in the array and should +return TRUE or FALSE. Values that lead to TRUE will be collected +into a new array. + +## Mapping + +`a:map` applies a quotation to each item in an array and +constructs a new array from the returned values. + +Example: + +``` +{ #1 #2 #3 } [ #10 * ] a:map +``` + +## Reduce + +`a:reduce` takes an array, a starting value, and a quote. It +executes the quote once for each item in the array, passing the +item and the value to the quote. The quote should consume both +and return a new value. + +``` +{ #1 #2 #3 } #0 [ + ] a:reduce +``` + +## Search + +RETRO provides `a:contains?` and `a:contains-string?` +to search an array for a value (either a number or string) and +return either TRUE or FALSE. + +``` +#100 { #1 #2 #3 } a:contains? +'test { 'abc 'def 'test 'ghi } a:contains-string? +``` + +## Implementation + +In memory, an array is a count followed by the values. As an +example, if you have an array: + + { #10 #20 #30 } + +In memory this would be setup as: + + | Offset | Value | + | ------ | ----- | + | 000 | 3 | + | 001 | 10 | + | 002 | 20 | + | 003 | 30 | + +You can construct one on the fly by keeping a pointer to +`here` and using `,` to place the values. E.g., + + here [ #3 , #10 , #20 , #30 , ] dip + +An example of this can be seen in this excerpt from an example +(*example/Primes.forth*): + + :create-set (-a) + here #3000 , #2 #3002 [ dup , n:inc ] times drop ; + +# Working With Assembly Language + +RETRO runs on a virtual machine called Nga. It provides a +standard assembler for this called *Muri*. + +Muri is a simple, multipass model that's not fancy, but +suffices for RETRO's needs. + +## Assembling A Standalone File + +A small example (*test.muri*) + + ~~~ + i liju.... + r main + : c:put + i liiire.. + i 0 + : main + i lilica.. + d 97 + i liju.... + r main + ~~~ + +Assembling it: + + retro-muri test.muri + +So breaking down: Muri extracts the assembly code blocks to +assemble, then proceeds to do the assembly. Each source line +starts with a directive, followed by a space, and then ending +with a value. + +The directives are: + + : value is a label + i value is an instruction bundle + d value is a numeric value + r value is a reference + s value is a string to inline + +Instructions for Nga are provided as bundles. Each memory +location can store up to four instructions. And each instruction +gets a two character identifier. + +From the list of instructions: + + 0 nop 5 push 10 ret 15 fetch 20 div 25 zret + 1 lit 6 pop 11 eq 16 store 21 and 26 halt + 2 dup 7 jump 12 neq 17 add 22 or 27 ienum + 3 drop 8 call 13 lt 18 sub 23 xor 28 iquery + 4 swap 9 ccall 14 gt 19 mul 24 shift 29 iinvoke + +This reduces to: + + 0 .. 5 pu 10 re 15 fe 20 di 25 zr + 1 li 6 po 11 eq 16 st 21 an 26 ha + 2 du 7 ju 12 ne 17 ad 22 or 27 ie + 3 dr 8 ca 13 lt 18 su 23 xo 28 iq + 4 sw 9 cc 14 gt 19 mu 24 sh 29 ii + +Most are just the first two letters of the instruction name. I +use `..` instead of `no` for `NOP`, and the first letter of +each I/O instruction name. So a bundle may look like: + + dumure.. + +(This would correspond to `dup multiply return nop`). + +## Runtime Assembler + +RETRO also has a runtime variation of Muri that can be used +when you need to generate more optimal code. So one can write: + + :n:square dup * ; + +Or: + + :n:square \dumure.. ; + +The second one will be faster, as the entire definition is one +bundle, which reduces memory reads and decoding by 2/3. + +Doing this is less readable, so I only recommend doing so after +you have finalized working RETRO level code and determined the +best places to optimize. + +The runtime assembler has the following directives: + + i value is an instruction bundle + d value is a numeric value + r value is a reference + +Additionally, in the runtime assembler, these are reversed: + + 'dudumu.. i + +Instead of: + + i dudumu.. + +The runtime assembler also provides three prefixes for use in +inlining machine code into a definition. These are: + + \ Treat token as an assembly sequence + ` Treat token as a numeric value + ^ Treat token as a reference + +E.g., instead of doing something like: + + :n:square as{ 'dumu.... i }as ; + :test as{ 'lilica.... i #22 d 'n:square r }as ; + +Just write: + + :n:square \dumu.... ; + :test \lilica.. `22 ^n:square ; + +# Working With a Buffer + +RETRO provides words for operating on a linear memory area. +This can be useful in building strings or custom data +structures. + +## Namespace + +Words operating on the buffer are kept in the `buffer:` +namespace. + +## Implementation + +A buffer is a linear sequence of memory. The buffer words +provide a means of incrementally storing and retrieving +values from it. + +The buffer words keep track of the start and end of the +buffer. They also ensure that an `ASCII:NULL` is written +after the last value, which make using them for string +data easy. + +## Limitations + +Only one buffer can be active at a time. RETRO provides a +`buffer:preserve` combinator to allow using a second one +before returning to the prior one. + +## Set The Active Buffer + +To set a buffer as the active one use `buffer:set`. This takes +an address. + +The buffer will be assumed to be empty. The inital value will +be set to ASCII:NULL. + +## Add Value + +Use `buffer:add` to append a value to the buffer. This takes +a single value and will also add an ASCII:NULL after the end +of the buffer. + +## Fetch Last Value + +To return the last value in the buffer you can use `buffer:get`. +This removes the value and sets an ASCII:NULL in the memory +location the returned value occupied. + +## Get Data About The Buffer + +RETRO provides `buffer:start` to get the initial address in +the buffer, `buffer:end` to get the last address (ignoring the +ASCII:NULL), and `buffer:size` to return the number of values +in the buffer. + +## Reset + +You can reset a buffer to the empty state using `buffer:empty`. + +## Example + +To begin, create a memory region to use as a buffer. + +``` +'Test d:create #1025 allot +``` + +Then you can set this as the current buffer: + +``` +&Test buffer:set +``` + +When a buffer is set, the vocabulary sets an internal +index to the first address in it. This will be +incremented when you add data and decremented when you +remove data. + +Let's add some stuff using `buffer:add`: + +``` +#100 buffer:add +#200 buffer:add +#300 buffer:add +``` + +And then retreive the values: + +``` +buffer:get n:put nl +buffer:get n:put nl +buffer:get n:put nl +``` + +You can remove all values using `buffer:empty`: + +``` +#100 buffer:add +#200 buffer:add +#300 buffer:add +buffer:empty +``` + +And ask the buffer how many items it contains: + +``` +buffer:size n:put nl +#100 buffer:add +#200 buffer:add +#300 buffer:add +buffer:size n:put nl +buffer:empty +``` + +The other functions are `buffer:start`, which returns +the address of the buffer, `buffer:end`, which returns +the address of the last value, and `buffer:preserve`. +The first is easy to demo: + +``` +buffer:start Test eq? n:put nl +``` + +The last one is useful. Only one buffer is ever active +at a given time. The `buffer:preserve` combinator lets +you execute a word, saving and restoring the current +buffer indexes. So the word could assign and use a new +buffer and this will reset the previous one after +control returns. + +There are a few notes that need to be considered. The +preserve combinator saves the start and current index +but *not* the contents. If the word you call uses the +same buffer, the contents will remain altered. + +Finally, the buffer words have one interesting trait: +they store an ASCII NULL after adding each item to the +buffer. This lets one use them to build strings easily. + +``` +Test buffer:set +$h buffer:add +$e buffer:add +$l buffer:add +$l buffer:add +$o buffer:add +$, buffer:add +#32 buffer:add +$w buffer:add +$o buffer:add +$r buffer:add +$l buffer:add +$d buffer:add +buffer:start s:put nl +``` + +# Working With Characters + +RETRO provides words for working with ASCII characters. + +## Prefix + +Character constants are returned using the `$` prefix. + +## Namespace + +Words operating on characters are in the `c:` namespace. + +## Classification + +RETRO provides a number of words to determine if a character +fits into predefined groups. + +The primary words for this are: + +* `c:consonant?` +* `c:digit?` +* `c:letter?` +* `c:lowercase?` +* `c:uppercase?` +* `c:visible?` +* `c:vowel?` +* `c:whitespace?` + +There are also corresponding "not" forms: + +* `c:-consonant?` +* `c:-digit?` +* `c:-lowercase?` +* `c:-uppercase?` +* `c:-visible?` +* `c:-vowel?` +* `c:-whitespace?` + +All of these take a character and return either a `TRUE` or +`FALSE` flag. + +## Conversions + +A few words are provided to convert case. Each takes a character +and returns the modified character. + +* `c:to-lower` +* `c:to-number` +* `c:to-upper` +* `c:toggle-case` + +RETRO also has `c:to-string`, which takes a character and +creates a new temporary string with the character. + +## I/O + +Characters can be displayed using `c:put`. + +``` +$a c:put +``` + +With the default system on BSD, Linux, and macOS (and other +Unix style hosts), `c:get` is provided to read input. This +may be buffered, depending on the host. + +# Defining Words + +Words are named functions. To start a word, preceed it's name +with a colon. Follow this by the definition, and end with a +semicolon. + +E.g., + + :do-nothing ; + :square dup * ; + +# Working With The Dictionary + +The Dictionary is a linked list containing the dictionary +headers. + +## Namespace + +Words operating on the dictionary are in the `d:` namespace. + +## Variables + +`Dictionary` is a variable holding a pointer to the most recent +header. + +## Header Structure + +Each entry follows the following structure: + + Offset Contains + ------ --------------------------- + 0000 Link to Prior Header + 0001 Link to XT + 0002 Link to Class Handler + 0003+ Word name (null terminated) + +RETRO provides words for accessing the fields in a portable +manner. It's recommended to use these to allow for future +revision of the header structure. + +## Accessing Fields + +Given a pointer to a header, you can use `d:xt`, `d:class`, +and `d:name` to access the address of each specific field. +There is no `d:link`, as the link will always be the first +field. + +## Shortcuts For The Latest Header + +RETRO provides several words for operating on the most recent +header. + +`d:last` returns a pointer to the latest header. `d:last` +will give the contents of the `d:xt` field for the latest +header. There are also `d:last` and `d:last`. + +## Adding Headers + +Two words exist for making new headers. The easy one is +`d:create`. This takes a string for the name and makes a +new header with the class set to `class:data` and the XT +field pointing to `here`. + +Example: + +``` +'Base d:create +``` + +The other is `d:add-header`. This takes a string, a pointer +to the class handler, and a pointer for the XT field and +builds a new header using these. + +Example: + +``` +'Base &class:data #10000 d:add-header +``` + +## Searching + +RETRO provides two words for searching the dictionary. + +`d:lookup` takes a string and tries to find it in the +dictionary. It will return a pointer to the dictionary header +or a value of zero if the word was not found. + +`d:lookup-xt` takes a pointer and will return the dictionary +header that has this as the `d:xt` field, or zero if no match +is found. + +## Iteration + +You can use the `d:for-each` combinator to iterate over all +entries in the dictionary. For instance, to display the names +of all words: + +``` +[ d:name s:put sp ] d:for-each +``` + +For each entry, this combinator will push a pointer to the +entry to the stack and call the quotation. + +## Listing Words + +Most Forth systems provide WORDS for listing the names of all +words in the dictionary. RETRO does as well, but this is named +`d:words`. + +This isn't super useful as looking through several hundred +names is annoying. RETRO also provides `d:words-with` to help +in filtering the results. + +Example: + +``` +'class: d:words-with +``` + + +# Working With Floating Point + +Some RETRO systems include support for floating point numbers. +When present, this is built over the system `libm` using the +C `double` type. + +Floating point values are typically 64 bit IEEE 754 double +precision (1 bit for the sign, 11 bits for the exponent, and +the remaining 52 bits for the value), i.e. 15 decimal digits +of precision. + +## Prefix + +Floating point numbers start with a `.` + +Examples: + + Token Value + .1 1.0 + .0.5 0.5 + .-.4 -0.4 + .1.3 1.3 + +## Namespace + +Floating point words are in the `f:` namespace. There is also +a related `e:` namespace for *encoded values*, which allows +storing of floats in standard memory. + +## Operation + +Floating point values exist on a separate stack, and are bigger +than the standard memory cells, so can not be directly stored +and fetched from memory. + +The floating point system also provides an alternate stack that +can be used to temporarily store values. + +The following words exist for arranging values on the floating +point stack. These are direct analogs to the non-prefiexd words +for dealing with the data stack. + +- `f:nip` +- `f:over` +- `f:depth` +- `f:drop` +- `f:drop-pair` +- `f:dup` +- `f:dup-pair` +- `f:dump-stack` +- `f:tuck` +- `f:swap` +- `f:rot` + +For the secondary floating point stack, the following words are +provided: + +- `f:push` +- `f:pop` +- `f:adepth` +- `f:dump-astack` + +## Constants + + | Name | Returns | + | -------- | ----------------- | + | `f:E` | Euler's number | + | `f:-INF` | Negative infinity | + | `f:INF` | Positive infinity | + | `f:NAN` | Not a Number | + | `f:PI` | PI | + +## Comparisons + +The basic set of comparators are the same as those for +operating on integers. These are: + +- `f:-eq?` +- `f:between?` +- `f:eq?` +- `f:gt?` +- `f:lt?` +- `f:negative?` +- `f:positive?` +- `f:case` + +There are also a few additions for comparing to special values +like infinity and NaN. + +- `f:-inf?` +- `f:inf?` +- `f:nan?` + +## Basic Math + +- `f:*` +- `f:+` +- `f:-` +- `f:/` +- `f:abs` +- `f:floor` +- `f:inc` +- `f:limit` +- `f:max` +- `f:min` +- `f:negate` +- `f:power` +- `f:ceiling` +- `f:dec` +- `f:log` +- `f:sqrt` +- `f:square` +- `f:round` +- `f:sign` +- `f:signed-sqrt` +- `f:signed-square` + +## Geometry + +RETRO provides a small number of words for doing geometric +related calculations. + +| Word | Returns | +| -------- | ------------ | +| `f:acos` | arc cosine | +| `f:asin` | arc sine | +| `f:atan` | arc tangent | +| `f:cos` | cosine | +| `f:sin` | sine | +| `f:tan` | tangent | + +## Storage and Retrieval + +By leveraging the encoded value functions, RETRO is able to +allow storage of floating point values in memory. This does +have a tradeoff in accuracy as the memory cells are considerably +smaller than a full floating point size. + +You can use `f:fetch` to fetch a floating point value and +`f:store` to store one. + +If you need more precision, try Kiyoshi Yoneda's FloatVar +example (`example/FloatVar.forth`), which includes words to +store and retrieve values using multiple cells. + +- `f:to-number` +- `f:to-string` + +## I/O + +The floating point vocabulary has a single I/O word, `f:put`, +for the display of floating point numbers. + +## Encoded Values + +RETRO provides a means of encoding and decoding floating point +values into standard integer cells. This is based on the paper +"Encoding floating point values to shorter integers" by Kiyoshi +Yoneda and Charles Childers. + +- `f:E1` +- `f:to-e` +- `e:-INF` +- `e:-inf?` +- `e:INF` +- `e:MAX` +- `e:MIN` +- `e:NAN` +- `e:clip` +- `e:inf?` +- `e:max?` +- `e:min?` +- `e:n?` +- `e:nan?` +- `e:put` +- `e:to-f` +- `e:zero?` + +# Working With Files + +On Unix and Windows systems RETRO provides a set of words for +working with files. As a pragmatic choice these are mostly +modeled after the file functions in libc. + +The file words are in the `file:` namespace. + +## File Access Modes + +You can open a file for various operations. The functionality +allowed depends on the file access mode. Valid modes in RETRO +are: + + file:A Open for appending; file pointer set to end of file + file:R Open for reading; file pointer set to start of file + file:R+ Open for reading and writing + file:W Open for writing + +## Opening A File + +To open a file, pass the file name and a file mode to `file:open`. + + '/etc/motd file:R file:open + +On a successful open this will return a file handle greater than +zero. + +Additionally, RETRO provides a few other forms for opening files. + +To open a file for reading: + + '/etc/motd file:open + +This will return the size of the file (as NOS) and the file handle +(as TOS). + +To open a file for writing: + + '/tmp/test file:open + +This returns the file handle. + +To open a file for append operations: + + '/tmp/test file:open + +As with `file:open`, this returns both the size of +the file and the file handle. + +## Closing A File + +To close a file, pass the file handle to `file:close`. + + '/etc/motd file:A file:open file:close + +## Reading From A File + +To read a byte from an open file, pass the file handle to the +`file:read` word. + + @FID file:read n:put + +To read a line from a file, pass the file handle to the word +`file:read-line`. + + @FID file:read-line s:put + +The line is read into a temporary string buffer. Move the +text to a safe place if you aren't using it quickly or if +the length of the line is bigger than the size of a temporary +string. + +## Writing To A File + +To write a byte to a file, pass it and the file handle to +`file:write`. + + $h @FID file:write + $e @FID file:write + $l @FID file:write + $l @FID file:write + $o @FID file:write + +Though cells are 32 or 64 bits in size, only the byte value will +be written to the file. + +## Deleting Files + +You can delete a file by passing the file name to `file:delete`. + + /tmp/test file:delete + +## Check For File Existance + +Use `file:exists?` to detect the existance of a file. Pass it a +file name and it will return `TRUE` if existing or `FALSE` if +it does not. + + '/etc/motd file:exists? + +This will also return `TRUE` if the filename is a directory. + +## Flush Caches + +Use `file:flush` to flush the system caches for a file. Pass a +file handle to this. + + @FID file:flush + +## Seek A Position Within A File + +You can use `file:seek` to move the internal file pointer +for a given file. Pass this the new location and a file. + + #100 @FID file:seek + +The location for the file pointer is a fixed offset from the +start of the file, not a relative offset. + +## Get The Current Position Within A File + +To find the current value of the file pointer within a file +just pass the file handle to `file:tell`. + + @FID file:tell + +This returns a number that is the number of bytes into the file +that the file pointer is currently at. + +## Determine The Size Of A File + +Use `file:size` to return the size of a file. Pass this a file +handle and it will return the size of a file, or 0 if empty. If +the file is a directory, it returns -1. + + @FID file:size + +## Reading An Entire File + +If you want to read an entire file into memory you can use +`file:slurp`. This takes the starting address of a memory +region and the name of the file. + + here '/etc/motd file:slurp + +Take care that the memory buffer is large enough for the file +being read or you will run into problems. + +## Writing A String To A File + +If you have a string that you want to write to a file, replacing +any existing contents, you can use `file:spew`. This takes the +string to write and a file name. + + 'hello_world '/tmp/test.txt file:spew + +## Iterating Over A File, Line By Line + +You can easily iterate over each line in a file using the word +`file:for-each-line`. This will take a file name and a quote, +read each line into a temporary string, then pass this string to +the quote. + + '/etc/motd [ s:put nl ] file:for-each-line + +# Loops + +RETRO provides several words for creating loops. + +## Unconditional Loops + +An unconditional loop begins with `repeat` and ends with `again`. + + :test repeat #1 n:put sp again ; + test + +Unconditional loops must be inside a definition or quote. To exit +one of these, use `0;`, `-if;` or `if;`. + + :test #100 repeat 0; dup n:put sp n:dec again ; + test + + :test #100 repeat dup #50 eq? [ 'done! s:put nl ] if; n:dec again ; + test + +You can also achieve this via recursion: + + :test 0; dup n:put sp n:dec test ; + #100 test + +Be careful with recursion as the virtual machine will have a limited +amount of space for the address stack and recursing too many times +can cause a stack overflow. + +## Conditional Loops + +There are two conditional looping combinators: `while` and `until`. +Both take a quote and execute it, checking a returned flag to decide +when to stop running. + + #0 [ dup n:put sp n:inc dup #10 eq? ] until + #10 [ dup n:put sp n:dec dup n:-zero? ] while + +## Counted Loops + +There are two combinators for counted loops. These are `times` and +`times`. + + #0 #10 [ dup n:put sp n:inc ] times nl + #10 [ I n:put sp ] times + +The `times` provides an index via the `I`, `J`, and +`K` words. `I` will be the index of the current loop, with `J` and +`K` being the indexes of the next two older loops. + +The loop indexes can be accessed outside the loop body: + + :display I n:square n:put sp ; + :squares [ display ] times nl ; + #100 squares + +## Tradeoffs + +The unconditional loop form is more efficient as it's just a +simple jump operation. The `times` counted loops are a little +slower, but can be cleaner and more readable in many cases. The +`times` form is significantly slower than the other +two forms. + +# Working With Numbers + +Numbers in RETRO are signed integers. + +## Token Prefix + +All numbers start with a `#` prefix. + +## Namespace + +Most words operating on numbers are in the `n:` namespace. + +## Range of Values + +A default RETRO system with 32 bit cells provides a range of +-2,147,483,648 to 2,147,483,647. For 64 bit systems, the range +will be -9,223,372,036,854,775,807 to 9,223,372,036,854,775,806. + +You can check the range your VM and image support using: + + n:MIN + n:MAX + +These will return the limits for your system. + +## Comparisons + +RETRO provides a number of comparison words for numeric values. + +The basic comparators are: + + -eq? + eq? + lt? + lteq? + gt? + gteq? + +Additionally RETRO also provides: + + n:-zero? + n:between? + n:even? + n:negative? + n:odd? + n:positive? + n:strictly-positive? + n:zero? + +## Basic Operations + + + + - + * + / + mod + /mod + n:abs + n:dec + n:inc + n:limit + n:max + n:min + n:negate + n:pow + n:sqrt + n:square + +## Conversions + +You can convert a number to a string with `n:to-string` or +to a floating point value with `n:to-float`. + + #123 n:to-float f:put + + #123 n:to-string s:put + +## Display + +To display a number, use `n:put`. + + #123 n:put + +# Working With Pointers + +## Prefix + +Pointers are returned by the `&` prefix. + +## Examples + +``` +'Base var +&Base fetch +#10 &Base store + +#10 &n:inc call +``` + +## Notes + +The use of `&` to get a pointer to a data structure (with a +word class of `class:data`) is not required. I like to use it +anyway as it makes my intent a little clearer. + +Pointers are useful with combinators. Consider: + +``` +:abs dup n:negative? [ n:negate ] if ; +``` + +Since the target quote body is a single word, it is more +efficient to use a pointer instead: + +``` +:abs dup n:negative? &n:negate if ; +``` + +The advantages are speed (saves a level of call/return by +avoiding the quotation) and size (for the same reason). +This may be less readable though, so consider the balance +of performance to readability when using this approach. + +# Quotations + +Quotes are anonymous functions. RETRO uses these as the basis for +executable flow control and combinatorial logic. + +## Using Quotations + +To make a quotation, surround the code with square brackets. E.g., + + #1 #2 eq? [ 'No_match s:put nl ] -if + +Quotes can be nested: + + [ #3 [ #4 ] dip ] call + +After creation, a pointer to the quotation is left on the stack +(or is compiled into the current definition). + +## Combinators + +Words operating on quotations are called combinators; these are +discussed in *Using Combinators*. + +## Implementation + +A quotation is compiled as: + + ... code before quotation ... + i liju.... (if_compiling_only) + d address after quotation (if_compiling_only) + ... code for quotation + i re...... (this_is_where_the_quote_ends) + i li...... + d address of code for quotation + ... code after quotation .... + +## Other Notes + +Quotations are used heavily in RETRO. They give the source a +feel that's different from traditional Forth, and allow for +a more consistent syntax. + +For instance, in a traditional Forth, you might have some +conditionals: + + IF ... THEN + IF ... ELSE ... THEN + IF ... EXIT THEN + +RETRO uses conditional combinators for these: + + [ ... ] if + [ ... ] [ ... ] choose + [ ... ] if; + +Or loops: + + FOR ... NEXT + +Is replaced by: + + [ ... ] times + +This can also extend to stack flow. Sequences like: + + >R ... >R + DUP >R ... >R + +Become: + + [ ... ] dip + [ ... ] sip + +And forms like: + + 1 2 3 * swap 3 * swap + +Can be replaced with a combinator like: + + #1 #2 [ #3 * ] bi@ + +While there is a different set of words to learn, I find that +overall there's less noise from low level stack shuffling words +and the added consistency with regards to overall syntax has +been nice as I was never fond of the multiple forms that existed +in traditional Forth. + +# Sockets + +On Unix hosts, RETRO provides an optional set of words for using +network sockets. + +## Create a Socket + +To create a new socket, just run: + + socket:create + +This will return a socket handle. + +## Bind To A Port + +To bind to a port, pass the port number and socket handle +to `socket:bind`. The port should be a string. This will return +0 if successful, -1 if not successful, and an error code. + + '9998 @Sock socket:bind + +## Configure To Allow Incoming Connections + +To prepare a socket for incoming connections use socket:listen. This +will take a backlog count and a socket handle. It returns a flag +(0 success, -1 failed) and an error code. + + #3 @Sock socket:listen + +## Accept Connections + +To accept connections pass the socket handle to `socket:accept`. +This returns a new socket for the connection and an error code. + + @Sock socket:accept + +## Make A Connection + +To connect to a server using the socket: + + 'forth.works '70 socket:configure + @Sock socket:connect + +`socket:connect` will return a status code and an error code. + +## Writing To A Socket + +To write a string to a socket, use `socket:send`. This will +take a string and a socket handle and will return the number +of bytes sent and an error code. + + 'test @Sock socket:send + +## Reading From A Socket + +To read data from a socket pass an address, a maximum number of +bytes, and the socket handle to `socket:recv`. This will return +the number of bytes received and an error code. The bytes will +be stored in memory starting at the specified address. + + here #1024 @Sock socket:recv + +## Close a Socket + +To close a socket, pass the socket handle to `socket:close`. + + @Socket socket:close + +# Unix Scripting + +RETRO on Unix hosts is designed to play well with scripting. + +## Shebang + +To run an entire program directly, start the file with the +standard shebang and make the file executable: + + #!/usr/bin/env retro + +This requires the `retro` binary to be in your path. + +## Arguments + +RETRO provides several words in the `script:` namespace for accessing +command line arguments. + +The number of arguments can be accessed via `script:arguments`. This +will return a number with the arguments, other than the script +name. + + script:arguments '%n_arguments_passed\n s:format s:put + +To retreive an argument, pass the argument number to `script:get-argument`: + + script:arguments [ I script:get-argument s:put nl ] indexed-times + +And to get the name of the script, use `script:name`. + + script:name s:put + +## Mixing + +With use of the Unu literate format, it's possible to mix both +shell and RETRO code into a single script. As an example, this +is a bit of shell that runs itself via retro for each .retro +file in the current directory tree: + + #!/bin/sh + + # shell part + find . -name '*.retro' -print0 | xargs -0 -n 1 retro $0 + exit + + # retro part + + This will scan a source file and do something with it: + + ~~~ + ... do stuff ... + ~~~ + +# Working With Strings + +Strings in RETRO are NULL terminated sequences of values +representing characters. Being NULL terminated, they can't +contain a NULL (ASCII 0). + +The character words in RETRO are built around ASCII, but +strings can contain UTF8 encoded data if the host platform +allows. Words like `s:length` will return the number of bytes, +not the number of logical characters in this case. + +## Prefix + +Strings begin with a single `'`. + + 'Hello + 'This_is_a_string + 'This_is_a_much_longer_string_12345_67890_!!! + +RETRO will replace spaces with underscores. If you need both +spaces and underscores in a string, escape the underscores and +use `s:format`: + + 'This_has_spaces_and_under\_scored_words. s:format + +## Namespace + +Words operating on strings are in the `s:` namespace. + +## Lifetime + +At the interpreter, strings get allocated in a rotating buffer. +This is used by the words operating on strings, so if you need +to keep them around, use `s:keep` or `s:copy` to move them to +more permanent storage. + +In a definition, the string is compiled inline and so is in +permanent memory. + +You can manually manage the string lifetime by using `s:keep` +to place it into permanent memory or `s:temp` to copy it to +the rotating buffer. + +## Mutability + +Strings are mutable. If you need to ensure that a string is +not altered, make a copy before operating on it or see the +individual glossary entries for notes on words that may do +this automatically. + +## Searching + +RETRO provides four words for searching within a string. + +* `s:contains-char?` +* `s:contains-string?` +* `s:index-of` +* `s:index-of-string` + +## Comparisons + +* `s:eq?` +* `s:case` + +## Extraction + +To obtain a new string containing the first `n` characters from +a source string, use `s:left`: + + 'Hello_World #5 s:left + +To obtain a new string containing the last `n` characters from +a source string, use `s:right`: + + 'Hello_World #5 s:right + +If you need to extract data from the middle of the string, use +`s:substr`. This takes a string, the offset of the first +character, and the number of characters to extract. + + 'Hello_World #3 #5 s:substr + +## Joining + +You can use `s:append` or `s:prepend` to merge two strings. + + 'First 'Second s:append + 'Second 'First s:prepend + +## Tokenization + +* `s:tokenize` +* `s:tokenize-on-string` +* `s:split` +* `s:split-on-string` + +## Conversions + +To convert the case of a string, RETRO provides `s:to-lower` +and `s:to-upper`. + +`s:to-number` is provided to convert a string to an integer +value. This has a few limitations: + +- only supports decimal +- non-numeric characters will result in incorrect values + +## Cleanup + +RETRO provides a handful of words for cleaning up strings. + +`s:chop` will remove the last character from a string. This +is done by replacing it with an ASCII:NULL. + +`s:trim` removes leading and trailing whitespace from a string. +For more control, there is also `s:trim-left` and `s:trim-right` +which let you trim just the leading or trailing end as desired. + +## Combinators + +* `s:for-each` +* `s:filter` +* `s:map` + +## Other + +* `s:evaluate` +* `s:copy` +* `s:reverse` +* `s:hash` +* `s:length` +* `s:replace` +* `s:format` +* `s:empty` + +## Controlling The Temporary Buffers + +As dicussed in the Lifetime subsection, temporary strings are +allocated in a rotating buffer. The details of this can be +altered by updating two variables. + + | Variable | Holds | + | ------------- | ---------------------------------------- | + | TempStrings | The number of temporary strings | + | TempStringMax | The maximum length of a temporary string | + +For example, to increase the number of temporary strings to +48: + + #48 !TempStrings + +The defaults are: + + | Variable | Default | + | ------------- | ------- | + | TempStrings | 32 | + | TempStringMax | 512 | + +It's also important to note that altering these will affect +the memory map for all temporary buffers. Do not use anything +already in the buffers after updating these or you will risk +data corruption and possible crashes. + +# Using Combinators + +A combinator is a function that consumes functions as input. +They are used heavily by the RETRO system. + +## Types of Combinators + +Combinators are divided into three primary types: compositional, +execution flow, and data flow. + +## Compositional + +A compositional combinator takes elements from the stack and +returns a new quote. + +`curry` takes a value and a quote and returns a new quote +applying the specified quote to the specified value. As an +example, + +``` +:acc (n-) here swap , [ dup v:inc fetch ] curry ; +``` + +This would create an accumulator function, which takes an +initial value and returns a quote that will increase the +accumulator by 1 each time it is invoked. It will also return +the latest value. So: + +``` +#10 acc +dup call n:put +dup call n:put +dup call n:put +``` + +## Execution Flow + +Combinators of this type execute other functions. + +### Fundamental + +`call` takes a quote and executes it immediately. + +``` +[ #1 n:put ] call +&words call +``` + +### Conditionals + +RETRO provides three primary combinators for use with +conditional execution of quotes. These are `choose`, `if`, +and `-if`. + +`choose` takes a flag and two quotes from the stack. If the +flag is true, the first quote is executed. If false, the +second quote is executed. + +``` +#-1 [ 'true s:put ] [ 'false s:put ] choose + #0 [ 'true s:put ] [ 'false s:put ] choose +``` + +`if` takes a flag and one quote from the stack. If the flag is +true, the quote is executed. If false, the quote is discarded. + +``` +#-1 [ 'true s:put ] if + #0 [ 'true s:put ] if +``` + +`-if` takes a flag and one quote from the stack. If the flag is +false, the quote is executed. If true, the quote is discarded. + +``` +#-1 [ 'false s:put ] -if + #0 [ 'false s:put ] -if +``` + +RETRO also provides `case` and `s:case` for use when you have +multiple values to check against. This is similar to a `switch` +in C. + +`case` takes two numbers and a quote. The initial value is +compared to the second one. If they match, the quote is +executed. If false, the quote is discarded and the initial +value is left on the stack. + +Additionally, if the first value was matched, `case` will exit +the calling function, but if false, it returns to the calling +function. + +`s:case` works the same way, but for strings instead of simple +values. + +``` +:test (n-) + #1 [ 'Yes s:put ] case + #2 [ 'No s:put ] case + drop 'No idea s:put ; +``` + +### Looping + +Several combinators are available for handling various looping +constructs. + +`while` takes a quote from the stack and executes it repeatedly +as long as the quote returns a true flag on the stack. This flag +must be well formed and equal -1 or 0. + +``` +#10 [ dup n:put sp n:dec dup 0 -eq? ] while +``` + +`times` takes a count and quote from the stack. The quote will +be executed the number of times specified. No indexes are pushed +to the stack. + +``` +#1 #10 [ dup n:put sp n:inc ] times drop +``` + +There is also a `times` variation that provides +access to the loop index (via `I`) and parent loop indexes +(via `J` and `K`). + +``` +#10 [ I n:put sp ] times +``` + +## Data Flow + +These combinators exist to simplify stack usage in various +circumstances. + +### Preserving + +Preserving combinators execute code while preserving portions +of the data stack. + +`dip` takes a value and a quote, moves the value off the main +stack temporarily, executes the quote, and then restores the +value. + +``` +#10 #20 [ n:inc ] dip +``` + +Would yield the following on the stack: + +``` +11 20 +``` + +`sip` is similar to `dip`, but leaves a copy of the original +value on the stack during execution of the quote. So: + +``` +#10 [ n:inc ] sip +``` + +Leaves us with: + +``` +11 10 +``` + +### Cleave + +Cleave combinators apply multiple quotations to a single value +or set of values. + +`bi` takes a value and two quotes, it then applies each quote to +a copy of the value. + +``` +#100 [ n:inc ] [ n:dec ] bi +``` + +`tri` takes a value and three quotes. It then applies each quote +to a copy of the value. + +``` +#100 [ n:inc ] [ n:dec ] [ dup * ] tri +``` + +### Spread + +Spread combinators apply multiple quotations to multiple values. +The asterisk suffixed to these function names signifies that +they are spread combinators. + +`bi*` takes two values and two quotes. It applies the first +quote to the first value and the second quote to the second +value. + +``` +#1 #2 [ n:inc ] [ #2 * ] bi* +``` + +`tri*` takes three values and three quotes, applying the +first quote to the first value, the second quote to the +second value, and the third quote to the third value. + +``` +#1 #2 #3 [ n:inc ] [ #2 * ] [ n:dec ] tri* +``` + +### Apply + +Apply combinators apply a single quotation to multiple values. +The @ sign suffixed to these function names signifies that they +are apply combinators. + +`bi@` takes two values and a quote. It then applies the quote to +each value. + +``` +#1 #2 [ n:inc ] bi@ +``` + +`tri@` takes three values and a quote. It then applies the quote +to each value. + +``` +#1 #2 #3 [ n:inc ] tri@ +``` + +RETRO also provides `for-each` combinators for various data +structures. The exact usage of these varies; consult the +Glossary and relevant chapters for more details on these. + +# Word Classes + +Word classes are one of the two elements at the heart of +RETRO's interpreter. + +There are different types of words in a Forth system. At a +minimum there are data words, regular words, and immediate +words. There are numerous approaches to dealing with this. + +In RETRO I define special words which receive a pointer and +decide how to deal with it. These are grouped into a `class:` +namespace. + +## How It Works + +When a word is found in the dictionary, RETRO will push a +pointer to the definition (the `d:xt` field) to the stack +and then call the word specified by the `d:class` field. + +The word called is responsible for processing the pointer +passed to it. + +As a simple case, let's look at `immediate` words. These are +words which will always be called when encountered. A common +strategy is to have an immediacy bit which the interpreter +will look at, but RETRO uses a class for this. The class is +defined: + +``` +:class:immediate (a-) call ; +``` + +Or a normal word. These should be called at interpret time +or compiled into definitions. The handler for this can look +like: + +``` +:class:word (a-) compiling? [ compile:call ] [ call ] choose ; +``` + +## Using Classes + +The ability to add new classes is useful. If I wanted to add +a category of word that preserves an input value, I could do +it with a class: + +``` +:class:duplicating (a-) + compiling? [ &dup compile:call ] [ &dup dip ] choose + class:word ; + +:duplicating &class:duplicating reclass ; + +:. n:put nl ; duplicating +#100 . . . +``` + +# Checking The Version + +RETRO releases add and change things. You can use the `Version` +variable to determine the version in use and react accordingly. + +``` +@Version #201906 eq? [ 'Needs_2019.6! s:put nl bye ] if +``` + +This can be also be used to conditionally load compatibility files: + +``` +(If_newer_than_2016.6,_load_aliases_for_renamed_words) +@Version #201906 gt? [ 'Renamed_2019.6.forth include ] if +``` + +## Version Number Format + +The version is a six digit number encoding the year and month of +the release. So: + + 201901 is 2019.1 + 201906 is 2019.6 + 201911 is 2019.11 + +A `#100 /mod` will suffice to split these if needed. + +# Errors + +RETRO does only minimal error checking. + +## Non-Fatal + +A non-fatal error will be reported on *word not found* during +interactive or compile time. Note that this only applies to +calls: if you try to get a pointer to an undefined word, the +returned pointer will be zero. + +## Fatal + +A number of conditions are known to cause fatal errors. The +main ones are stack overflow, stack underflow, and division +by zero. + +On these, RETRO will generally exit. For stack depth issues, +the VM will attempt to display an error prior to exiting. + +In some cases, the VM may get stuck in an endless loop. If this +occurs, try using CTRL+C to kill the process, or kill it using +whatever means your host system provides. + +## Rationale + +Error checks are useful, but slow - especially on a minimal +system like RETRO. The overhead of doing depth or other checks +adds up quickly. + +As an example, adding a depth check to `drop` increases the +time to use it 250,000 times in a loop from 0.16 seconds to +1.69 seconds. + + +# Lexical Scope + +RETRO has a single dictionary, but does provide a means of using +lexical scope to keep this dictionary clean. + +## Example + +``` +{{ + 'A var + :++A &A v:inc ; +---reveal--- + :B ++A ++A @A n:put nl ; +}} +``` + +In this example, the lexical namespace is created with `{{`. A +variable (`A`) and word (`++A`) are defined. Then a marker is +set with `---reveal---`. Another word (`B`) is defined, and the +lexical area is closed with `}}`. + +The headers between `{{` and `---reveal---` are then hidden from +the dictionary, leaving only the headers between `---reveal---` +and `}}` exposed. + +## Notes + +This only affects word visibility within the scoped area. As an +example: + +``` +:a #1 ; + +{{ + :a #2 ; +---reveal--- + :b 'a s:evaluate n:put ; +}} +``` + +In this, after `}}` closes the area, the `:a #2 ;` is hidden and +the `s:evaluate` will find the `:a #1 ;` when `b` is run. + +# The Stacks + +The stacks are a defining feature of Forth. They are are used +to pass data between words and to track return addresses for +function calls. + +RETRO always has two stacks, and optionally (if built with +floating point support) a third. + +## Data Stack + +This is the primary stack. Values are placed here, passed to +words which consume them and then return results. When I +refer to "the stack", this is the one I mean. Learning to use +the stack is a crucial part to making effective use of RETRO. + +### Placing Values On The Stack + +Values can be placed on the stack directly. + + | Example | Action | + | -------------- | ---------------------------------------- | + | `#300123` | Push the number `300123` to the stack | + | `$h` | Push the ASCII code for `h` to the stack | + | `'hello_world` | Push a pointer to a string to the stack | + | `&fetch` | Push the address of `fetch` to the stack | + +### Reordering The Stack + +RETRO provides a number of *shufflers* for reordering items +on the stack. + +Some of the most common ones are: + + | Word | Before | After | + | ------- |--------- | -------- | + | dup | #1 | #1 #1 | + | drop | #1 #2 | #1 | + | swap | #1 #2 | #2 #1 | + | over | #1 #2 | #1 #2 #1 | + | tuck | #1 #2 | #2 #1 #2 | + | nip | #1 #2 | #2 | + | rot | #1 #2 #3 | #3 #1 #2 | + +You can use `push` and `pop` to move values to and from the +address stack. Make sure you `pop` them back before the word +ends or RETRO will crash. These two words can not be used +at the interpreter. + +There is also a special one, `reorder`, which allows for big +stack restructuring. This is slow but can be very useful. + +As an example, let's say we have four values: + + #1 #2 #3 #4 + +And we want them to become: + + #4 #3 #2 #1 + +Doing this with the basic shufflers is difficult. You could end +up with something similar to: + + swap rot push rot pop swap + +But with `reorder`, you can just express the before and after +states: + + 'abcd 'dcba reorder + +### Resetting The Stack + +If you need to quickly empty the stack, use `reset`. + +### Get The Stack Depth + +To find out how many items are on the stack, use `depth`. + +### Displaying The Stack + +You can display the stack by running `dump-stack`. + +### Data Flow Combinators + +RETRO provides *combinators* for working with data order on +the stack. These are covered in a later chapter and are worth +learning to use as they can help provide a cleaner, more +structured means of working. + +### Tips + +The stack is *not* an array in addressable memory. Don't try +to treat it like one. + +## Address Stack + +This stack primarily holds return addresses for function calls. +You normally won't need to directly interact with this stack, +but you can use `push` and `pop` to move values between the +data stack and this. + +## Floating Point Stack + +If you are using a build with floating point support a third +stack will be present. Floating point values are kept and +passed between words using this. + +See the Floating Point chapter for more details on this. + +## Tips + +I recommend keeping the data stack shallow. Don't try to juggle +too much; it's better to factor definitions into shorter ones +that deal with simpler parts of the stack values than to have +a big definition with a lot of complex shuffling. + +## Notes + +The standard system is configured with a very deep data stack +(around 2,000 items) and an address stack that is 3x deeper. +In actual use, your programs are unlikely to ever need this, +but if you do, keep the limits in mind. + +# Internals: Nga Virtual Machine + +## Overview + +At the heart of RETRO is a simple MISC (minimal instruction +set computer) processor for a dual stack architecture. + +This is a very simple and straightforward system. There are +30 instructions. The memory is a linear array of signed 32 +bit values. And there are two stacks: one for data and one +for return addresses. + +## Instruction Table + +| Opcode | Muri | Full Name | Data Stack | Address Stack | +| ------ | ---- | ------------------ | ---------- | ------------- | +| 0 | .. | nop | - | - | +| 1 | li | lit | -n | - | +| 2 | du | dup | n-nn | - | +| 3 | dr | drop | n- | - | +| 4 | sw | swap | xy-yx | - | +| 5 | pu | push | n- | -n | +| 6 | po | pop | -n | n- | +| 7 | ju | jump | a- | - | +| 8 | ca | call | a- | -A | +| 9 | cc | conditional call | af- | -A | +| 10 | re | return | - | A- | +| 11 | eq | equality | xy-f | - | +| 12 | ne | inequality | xy-f | - | +| 13 | lt | less than | xy-f | - | +| 14 | gt | greater than | xy-f | - | +| 15 | fe | fetch | a-n | - | +| 16 | st | store | na- | - | +| 17 | ad | addition | xy-n | - | +| 18 | su | subtraction | xy-n | - | +| 19 | mu | multiplication | xy-n | - | +| 20 | di | divide & remainder | xy-rq | - | +| 21 | an | bitwise and | xy-n | - | +| 22 | or | bitwise or | xy-n | - | +| 23 | xo | bitwise xor | xy-n | - | +| 24 | sh | shift | xy-n | - | +| 25 | zr | zero return | n-? | - | +| 26 | ha | halt | - | - | +| 27 | ie | i/o enumerate | -n | - | +| 28 | iq | i/o query | n-xy | - | +| 29 | ii | i/o invoke | ...n- | - | + +## Encoding + +Up to four instructions can be packed into each memory cell. + +As an example, + + Opcode 4 Opcode 3 Opcode 2 Opcode 1 + 00000000:00000000:00000000:00000000 + +If we have a bundle of `duliswst`, it would look like: + + st sw li du + 00010000:00000100:00000001:00000010 + +Each `li` should have a value in the following cell(s). These +values will be pushed to the stack. E.g., `lili....` and +1, 2: + + 00000000:00000000:00000001:00000001 + 00000000 00000000 00000000 00000001 (1) + 00000000 00000000 00000000 00000010 (2) + +## Shifts + +`sh` performs a bitwise arithmetic shift operation. + +This takes two values: + + xy + +And returns a single one: + + z + +If y is positive, this shifts `x` right by `y` bits. If negative, +it shifts left. + +## Queries: Memory, Stacks + +The `fe` instruction allows queries of some data related to +the Nga VM state. These are returned by reading from negative +addresses: + +| Address | Returns | +| ------- | ---------------------- | +| -1 | Data stack depth | +| -2 | Address stack depth | +| -3 | Maximum Image Size | +| -4 | Minimum Integer Value | +| -5 | Maximum Integer Value | + +## I/O Devices + +Nga provides three instructions for interacting with I/O devices. +These are: + + ie i/o enumerate returns the number of attached devices + iq i/o query returns information about a device + ii i/o interact invokes an interaction with a device + +As an example, with an implementation providing an output source, +a block storage system, and keyboard: + + ie will return `3` since there are three i/o devices + 0 iq will return 0 0, since the first device is a screen (0) + with a version of 0 + 1 iq will return 1 3, since the second device is a block + storage (3), with a version of 1 + 2 iq will return 0 1, since the third device is a keyboard + (1), with a version of 0 + +In this case, some interactions can be defined: + + : c:put + i liiire.. + d 0 + + : c:get + i liiire.. + d 2 + +Setup the stack, push the device ID to the stack, and then use +`ii` to invoke the interaction. + +A RETRO system requires one I/O device (a generic output for a +single character). This must be the first device, and must have +a device ID of 0. + +All other devices are optional and can be specified in any order. + +The currently supported and reserved device identifiers are: + +| ID | Device Type | Notes | +| ---- | ---------------- | -------------------------- | +| 0000 | Generic Output | Always present as device 0 | +| 0001 | Keyboard | | +| 0002 | Floating Point | | +| 0003 | Block Storage | Raw, 1024 cell blocks | +| 0004 | Filesystem | Unix-style Files | +| 0005 | Network: Gopher | Make gopher requests | +| 0006 | Network: HTTP | Make HTTP requests | +| 0007 | Network: Sockets | | +| 0008 | Syscalls: Unix | | +| 0009 | Scripting Hooks | | +| 0010 | Random Number | | + +This list may be revised in the future. The only guaranteed +stable indentifier is 0000 for generic output. + +# Internals: Interface Layers + +Nga provides a virtual processor and an extensible way of adding +I/O devices, but does not provide any I/O itself. Adding I/O is +the responsability of the *interface layer*. + +An interface layer will wrap Nga, providing at least one I/O +device (a generic output target), and a means of interacting +with the *retro image*. + +It's expected that this layer will be host specific, adding any +system interactions that are needed via the I/O instructions. +The image will typically be extended with words to use these. + + + +# Internals: I/O + +RETRO provides three words for interacting with I/O. These are: + + io:enumerate returns the number of attached devices + io:query returns information about a device + io:invoke invokes an interaction with a device + +As an example, with an implementation providing an output source, +a block storage system, and keyboard: + + io:enumerate will return `3` since there are three + i/o devices + #0 io:query will return 0 0, since the first device + is a screen (type 0) with a version of 0 + #1 io:query will return 1 3, since the second device is + block storage (type 3), with a version of 1 + #2 io:query will return 0 1, since the last device is a + keyboard (type 1), with a version of 0 + +In this case, some interactions can be defined: + + :c:put #0 io:invoke ; + :c:get #2 io:invoke ; + +Setup the stack, push the device ID, and then use `io:invoke` +to invoke the interaction. + +A RETRO system requires one I/O device (a generic output for a +single character). This must be the first device, and must have +a device ID of 0. + +All other devices are optional and can be specified in any +order. + + +# Internals: The Retro Image + +The actual RETRO language is stored as a memory image for Nga. + +## Format + +The image file is a flat, linear sequence of signed 32-bit +values. Each value is stored in little endian format. The +size is not fixed. An interface should check when loading to +ensure that the physical image is not larger than the emulated +memory. + +## Header + +The image will start with two cells. The first is a liju.... +instruction, the second is the target address for the jump. +This serves to skip over the rest of the data and reach the +actual entry point. + +This is followed by a pointer to the most recent dictionary +header, a pointer to the next free address in memory, and +then the RETRO version number. + + | Offset | Contains | + | ------ | --------------------------- | + | 0 | lit call nop nop | + | 1 | Pointer to main entry point | + | 2 | Dictionary | + | 3 | Heap | + | 4 | RETRO version | + +The actual code starts after this header. + +The version number is the year and month. As an example, +the 12.2019.6 release will have a version number of +`201906`. + +## Layout + +Assuming an Nga built with 524287 cells of memory: + + | RANGE | CONTAINS | + | --------------- | ---------------------------- | + | 0 - 1024 | rx kernel | + | 1025 - 1535 | token input buffer | + | 1536 + | start of heap space | + | ............... | free memory for your use | + | 506879 | buffer for string evaluate | + | 507904 | temporary strings (32 * 512) | + | 524287 | end of memory | + +The buffers at the end of memory will resize when specific +variables related to them are altered. + +# Using The Glossary + +The Glossary is a valuable resource. It provides information +on the RETRO words. + +## Example Entry + + f:+ + + Data: - + Addr: - + Float: FF-F + + Add two floating point numbers, returning the result. + + Class: class:word | Namespace: f | Interface Layer: rre + + Example #1: + + .3.1 .22 f:+ + +## Reading The Entry + +An entry starts with the word name. + +This is followed by the stack effect for each stack. All RETRO +systems have Data and Address stacks, some also include a +floating point stack). + +The stack effect diagrams are followed by a short description +of the word. + +After the description is a line providing some useful data. This +includes the class handler, namespace prefix, and the interface +layer that provides the word. + +Words in all systems will be listed as `all`. Some words (like +the `pb:` words) are only on specific systems like iOS. These +can be identified by looking at the interface layer field. + +At the end of the entry may be an example or two. + +## Access Online + +The latest Glossary can be browsed at http://forthworks.com:9999 +or gopher://forthworks.com:9999 + +# Historical Papers and Notes + +## On the Naming of RETRO + +Taken from http://lists.tunes.org/archives/tunes-lll/1999-July/000121.html + +On Fri, Jul 30, 1999 at 07:43:54PM -0400, Paul Dufresne wrote: + +> My brother did found it funny that Retro is called like that. +> For him retro means going back (generally in time) so this +> does not looks like a name of a OS to come. So he'd like to +> know from where the name came. + +Heheh, here's the story: When I started playing with OS stuff +last year (not seriously), I was reading about some old things +like FORTH and ITS, dating back to the 1960's and 70's. The +past few years in America, there's been a revival of disco +music (along with bell bottoms, platform shoes, and all that +crap) and they call it "retro". Now, my OS was named by +musicians.. I was telling a fellow musician about my ideas, +how it would be cool to have a small OS that isn't bloated and +unmanageable like Windows... go back to the 70's and resurrect +a line of software that died out. He goes "hmm.. sounds kinda +retro.." + +I think it sounds kinda rebellious, which is a Good Thing now +that everybody hates the M$ empire. :) It seems like other +people are as sick of the future as I am. Look at TUNES, the +idea there isn't to make some great new invention, just take +some decades-old ideas and combine them in one OS. The first +time I saw Knuth's "Art of Computer Programming" in the library +I thought "god that looks old.. 1973!!! nevermind.." Now it's +my programming bible. Find me something better published in +the 90's.. if such a thing exists, it'll be like a needle in a +haystack. "Newer" doesn't necessarily mean "better". + + New cars = flimsier + New farming methods = more devastating + New version of Netscape = more bloat, more bullshit + +One thing is better now: computer hardware. Give me 70's +software on 90's and 00's hardware :) + +- Tom Novelli + + +## The Design Philosophy of RETRO Native Forth + +Computer software is a technology in its infancy, a mere fifty years +old. The last 25 years in particular have seen an explosion in the +software business. However, software has seen little innovation while +hardware technology has improved phenomenally (notwithstanding the advent +of lousy slave-made parts). Proven software techniques of forty years ago +have yet to reach widespread use, in deference to the "latest and +greatest" proprietary solutions of dubious value. Thanks to agressive +marketing, we make huge investments in these dead-end technologies +(through our businesses and governments, if not personally) and we end up +with a reliance on a heap of complicated, error-prone, poorly understood +junk software. + +Complexity will dominate the software industry for the foreseeable +future. The Retro philosophy is a simple alternative for those willing to +make a clean break with legacy software. A Retro system can communicate +with other systems, but it won't run much legacy software, especially +proprietary software without source code. An emulation layer could be +added, but doing so would defeat the purpose of a simple operating system. +I think TCP/IP support is all the compatibility that's needed. + +At first Retro will appeal to computer hobbyists and electronic +engineers. Once the rough edges are smoothed out, it could catch on with +ordinary folks who don't like waiting five minutes just to check their +email (not to mention the long hours of setup and maintenance). Game +programmers who take their craft seriously may also be interested. +Businesses might even see a use for it, if the managers decide it's more +cost-effective to carefully design software for specific needs, rather +than buying off-the-shelf crap and spending countless manhours working +around the bugs. Since it's not practical for businesses to make a clean +break, my advice is to run Retro (and its ilk) on separate machines +connected by a network. Retro is efficient enough to run on older +machines that would otherwise sit idle, being too slow for the latest +Microsoft bloatware (or Linux, for that matter). + +I strive to avoid the extraneous. That applies even to proven +technologies, if I don't need them. If my computer isn't set up for +people to log in over the network, I don't want security features; they +just get in the way. If I'm only running programs I wrote, I should be +able to run them with full access to the hardware; I don't need protection +from viruses. If I download something I don't trust, then I can run it in +an isolated process, which is customary with Unix and kin. But that's not +core functionality. All that's needed is the flexibility to add things +like security, graphical interfaces, and distributed processing - if the +need ever arises. + +In programming languagues, I was misled. It's the Tower of Babel all +over again. The thousands of languages in existence all fall into a +handful of archetypes: Assembler, LISP, FORTRAN and FORTH represent the +earliest descendants of nearly all languages. I hesitate to name a +definitive "object-oriented" language, and here's why: Object-Oriented +programming is just a technique, and any language will suffice, even +Assembler. The complexites of fancy languages like Ada and C++ are a +departure from reality -- the reality of the actual physical machine. +When it all boils down, even LISP, FORTRAN and FORTH are only extensions +of the machine. + +I chose FORTH as the "native tongue" of Retro. LISP, FORTRAN, and +other languages can be efficiently implemented as extensions of FORTH, but +the reverse isn't so efficient. Theoretically all languages are +equivalent, but when design time, compilation time, and complexity are +accounted for, FORTH is most efficient. FORTH also translates most +directly to the hardware. (In fact, FORTH has been implemented in +hardware; these "stack machines" are extremely efficient.) FORTH is also +the easiest language to implement from scratch - a major concern when +you're trying to make a clean break. So with simplicity in mind, FORTH +was the obvious choice. + +I'm perfectly happy working with text only, and I go to great lengths +to avoid using the standard graphical environments, which have major +problems: windows, pulldown menus, and mice. Windows can't share the +screen nicely; that idea is hopeless. Pulldowns are tedious. Mice get in +the way of typing without reducing the need for it; all they give me is +tendonitis. Their main use is for drawing. + +Some of my favorite interfaces: Telix, Telegard BBS, Pine, Pico, Lynx, +and ScreamTracker. All "hotkey" interfaces where you press a key or two +to perform an action. Usually the important commands are listed at the +bottom of the screen, or at least on a help screen. The same principles +apply to graphical interfaces: use the full screen, except for a status +and menu area on one edge. Resist the temptation to clutter up the +screen. + +As for switching between programs, the Windows methods suck; the only +thing worse is Unix job control (jobs, fg, and such). The Linux method is +tolerable: Alt-Arrows, Alt-F1, Alt-F2, etc. Still, things could be +better: F11 and F12 cycle back and forth through all open programs; Alt-F1 +assigns the currently selected program to F1, and likewise for the other +function keys. Programs just won't use function keys - Control and Alt +combinations are less awkward and easier to remember, besides. I'll also +want a "last channel" key and a "task list" key; maybe I'll borrow those +stupid Win95 keys. The Pause key will do like it says - pause the current +program - and Ctrl-Pause (Break) will kill it. + +One more thing: consistency. I like programs to look different so I +can tell them apart, but the keys should be the same as much as possible. +Keys should be configured in one place, for all programs. Finally, +remember the most consistent interface, one of the few constants +throughout the history of computing - the text screen and keyboard, and +the teletypewriter before that. Don't overlook it. + +More to come, maybe... :) + +"If it's on line, it's a work in progress." + +Tom Novelli, 3/4/2000 + +## Metacompilation and Assembly + +RETRO 10 and 11 were written in themselves using a metacompiler. +I had been fascinated by this idea for a long time and was able +to explore it heavily. While I still find it to be a good idea, +the way I ended up doing it was problematic. + +The biggest issue I faced was that I wanted to do this in one +step, where loading the RETRO source would create a new image +in place of the old one, switch to the new one, and then load +the higher level parts of the language over this. In retrospect, +this was a really bad idea. + +My earlier design for RETRO was very flexible. I allowed almost +everything to be swapped out or extended at any time. This made +it extremely easy to customize the language and environment, but +made it crucial to keep track of what was in memory and what had +been patched so that the metacompiler wouldn't refer to anything +in the old image during the relocation and control change. It +was far too easy to make a mistake, discover that elements of +the new image were broken, and then have to go and revert many +changes to try to figure out what went wrong. + +This was also complicated by the fact that I built new images +as I worked, and, while a new image could be built from the last +built one, it wasn't always possible to build a new image from +the prior release version. (Actually, it was often worse - I +failed to check in every change as I went, so often even the +prior commits couldn't rebuild the latest images). + +For RETRO 12 I wanted to avoid this problem, so I decided to go +back to writing the kernel ("Rx") in assembly. I actually wrote +a Machine Forth dialect to generate the initial assembly, before +eventually hand tuning the final results to its current state. + +I could (and likely will eventually) write the assembler in +RETRO, but the current one is in C, and is built as part of the +standard toolchain. + +My VM actually has two assemblers. The older one is Naje. This +was intended to be fairly friendly to work with, and handles +many of the details of packing instructions for the user. Here +is an example of a small program in it: + + :square + dup + mul + ret + :main + lit 35 + lit &square + call + end + +The other assembler is Muri. This is a far more minimalistic +assembler, but I've actually grown to prefer it. The above +example in Muri would become: + + i liju.... + r main + : square + i dumure.. + : main + i lilica.. + d 35 + r square + i en...... + +In Muri, each instruction is reduced to two characters, and the +bundlings are listed as part of an instruction bundle (lines +starting with `i`). This is less readable if you aren't very +familiar with Nga's assembly and packing rules, but allows a +very quick, efficient way of writing assembly for those who are. + +I eventually rewrote the kernel in the Muri style as it's what +I prefer, and since there's not much need to make changes in it. + +## The Path to Self Hosting + +RETRO is an image based Forth system running on a lightweight +virtual machine. This is the story of how that image is made. + +The first RETRO to use an image based approach was RETRO 10. +The earliest images were built using a compiler written in +Toka, an earlier experimental stack language I had written. +It didn't take long to want to drop the dependency on Toka, +so I rewrote the image compiler in RETRO and then began +development at a faster pace. + +RETRO 11 was built using the last RETRO 10 image and an +evolved version of the metacompiler. This worked well, but +I eventually found it to be problematic. + +One of the issues I faced was the inability to make a new +image from the prior stable release. Since I develop and +test changes incrementally, I reached a point where the +current metacompiler and image required each other. This +wasn't a fatal flaw, but it was annoying. + +Perhaps more critical was the fragility of the system. In +R11 small mistakes could result in a corrupt image. The test +suite helped identify some of these, but there were a few +times I was forced to dig back through the version control +history to recover a working image. + +The fragile nature was amplified by some design decisions. +In R11, after the initial kernel was built, it would be +moved to memory address 0, then control would jump into the +new kernel to finish building the higher level parts. + +Handling this was a tricky task. In R11 almost everything +could be revectored, so the metacompiler had to ensure that +it didn't rely on anything in the old image during the move. +This caused a large number of issues over R11's life. + +So on to RETRO 12. I decided that this would be different. +First, the kernel would be assembly, with an external tool +to generate the core image. The kernel is in `Rx.md` and the +assembler is `Muri`. To load the standard library, I wrote a +second tool, `retro-extend`. This separation has allowed me +many fewer headaches as I can make changes more easily and +rebuild from scratch when necessary. + +But I miss self-hosting. So last fall I decided to resolve +this. And today I'm pleased to say that it is now done. + +There are a few parts to this. + +**Unu**. I use a Markdown variation with fenced code blocks. +The tool I wrote in C to extract these is called `unu`. For +a self hosting RETRO, I rewrote this as a combinator that +reads in a file and runs another word against each line in the +file. So I could display the code block contents by doing: + + 'filename [ s:put nl ] unu + +This made it easier to implement the other tools. + +**Muri**. This is my assembler. It's minimalistic, fast, and +works really well for my purposes. RETRO includes a runtime +version of this (using `as{`, `}as`, `i`, `d`, and `r`), so +all I needed for this was to write a few words to parse the +lines and run the corresponding runtime words. As with the C +version, this is a two pass assembler. + +Muri generates a new `ngaImage` with the kernel. To create a +full image I needed a way to load in the standard library and +I/O extensions. + +This is handled by **retro-extend**. This is where it gets +more complex. I implemented the Nga virtual machine in RETRO +to allow this to run the new image in isolation from the +host image. The new ngaImage is loaded, the interpreter is +located, and each token is passed to the interpreter. Once +done, the new image is written to disk. + +So at this point I'm pleased to say that I can now develop +RETRO using only an existing copy of RETRO (VM+image) and +tools (unu, muri, retro-extend, and a line oriented text +editor) written in RETRO. + +This project has delivered some additional side benefits. +During the testing I was able to use it to identify a few +bugs in the I/O extensions, and the Nga-in-RETRO will replace +the older attempt at this in the debugger, allowing a safer +testing environment. + +What issues remain? + +The extend process is *slow*. On my main development server +(Linode 1024, OpenBSD 6.4, 64-bit) it takes a bit over five +minutes to complete loading the standard library, and a few +additional depending on the I/O drivers selected. + +Most of the performance issues come from running Nga-in-RETRO +to isolate the new image from the host one. It'd be possible +to do something a bit more clever (e.g., running a RETRO +instance using the new image via a subprocess and piping in +the source, or doing relocations of the data), but this is +less error prone and will work on all systems that I plan to +support (including, with a few minor adjustments, the native +hardware versions [assuming the existance of mass storage]). + +Sources: + +**Unu** + +- http://forth.works/c8820f85e0c52d32c7f9f64c28f435c0 +- gopher://forth.works/0/c8820f85e0c52d32c7f9f64c28f435c0 + +**Muri** + +- http://forth.works/09d6c4f3f8ab484a31107dca780058e3 +- gopher://forth.works/0/09d6c4f3f8ab484a31107dca780058e3 + +**retro-extend** + +- http://forth.works/c812416f397af11db58e97388a3238f2 +- gopher://forth.works/0/c812416f397af11db58e97388a3238f2 + +## Prefixes as a Language Element + +A big change in RETRO 12 was the elimination of the traditional +parser from the language. This was a sacrifice due to the lack +of an I/O model. RETRO has no way to know *how* input is given +to the `interpret` word, or whether anything else will ever be +passed into it. + +And so `interpret` operates only on the current token. The core +language does not track what came before or attempt to guess at +what might come in the future. + +This leads into the prefixes. RETRO 11 had a complicated system +for prefixes, with different types of prefixes for words that +parsed ahead (e.g., strings) and words that operated on the +current token (e.g., `@`). RETRO 12 eliminates all of these in +favor of just having a single prefix model. + +The first thing `interpret` does is look to see if the first +character in a token matches a `prefix:` word. If it does, it +passes the rest of the token as a string pointer to the prefix +specific handler to deal with. If there is no valid prefix +found, it tries to find it in the dictionary. Assuming that it +finds the words, it passes the `d:xt` field to the handler that +`d:class` points to. Otherwise it calls `err:notfound`. + +This has an important implication: *words can not reliably +have names that start with a prefix character.* + +It also simplifies things. Anything that would normally parse +becomes a prefix handler. So creating a new word? Use the `:` +prefix. Strings? Use `'`. Pointers? Try `&`. And so on. E.g., + + In ANS | In RETRO + : foo ... ; | :foo ... ; + ' foo | &foo + : bar ... ['] foo ; | :bar ... &foo ; + s" hello world!" | 'hello_world! + +If you are familiar with ColorForth, prefixes are a similar +idea to colors, but can be defined by the user as normal words. + +After doing this for quite a while I rather like it. I can see +why Chuck Moore eventually went towards ColorForth as using +color (or prefixes in my case) does simplify the implementation +in many ways. + +## On The Kernel Wordset + +In implementing the RETRO 12 kernel (called Rx) I had to decide +on what functionality would be needed. It was important to me +that this be kept clean and minimalistic, as I didn't want to +spend a lot of time changing it as time progressed. It's far +nicer to code at the higher level, where the RETRO language is +functional, as opposed to writing more assembly code. + +So what made it in? + +Primitives + +These are words that map directly to Nga instructions. + + dup drop swap call eq? -eq? lt? gt? + fetch store + - * /mod and or + xor shift push pop 0; + +Memory + + fetch-next store-next , s, + +Strings + + s:to-number s:eq? s:length + +Flow Control + + choose if -if repeat again + +Compiler & Interpreter + + Compiler Heap ; [ ] Dictionary + d:link d:class d:xt d:name d:add-header + class:word class:primitive class:data class:macro + prefix:: prefix:# prefix:& prefix:$ + interpret d:lookup err:notfound + +Assembler + + i d r + +I *could* slightly reduce this. The $ prefix could be defined in +higher level code, and I don't strictly *need* to expose the +`fetch-next` and `store-next` here. But since the are already +implemented as dependencies of the words in the kernel, it would +be a bit wasteful to redefine them later in higher level code. + +A recent change was the addition of the assembler into the +kernel. This allows the higher levels to use assembly as needed, +which gives more flexibility and allows for more optimal code +in the standard library. + +With these words the rest of the language can be built up. Note +that the Rx kernel does not provide any I/O words. It's assumed +that the RETRO interfaces will add these as best suited for the +systems they run on. + +There is another small bit. All images start with a few key +pointers in fixed offsets of memory. These are: + + | Offset | Contains | + | ------ | --------------------------- | + | 0 | lit call nop nop | + | 1 | Pointer to main entry point | + | 2 | Dictionary | + | 3 | Heap | + | 4 | RETRO version identifier | + +An interface can use the dictionary pointer and knowledge of the +dictionary format for a specific RETRO version to identify the +location of essential words like `interpret` and `err:notfound` +when implementing the user facing interface. + +## On The Evolution Of Ngaro Into Nga + +When I decided to begin work on what became RETRO 12, I knew +the process would involve updating Ngaro, the virtual machine +that RETRO 10 and 11 ran on. + +Ngaro rose out of an earlier experimental virtual machine I had +written back in 2005-2006. This earlier VM, called Maunga, was +very close to what Ngaro ended up being, though it had a very +different approach to I/O. (All I/O in Maunga was intended to be +memory mapped; Ngaro adopted a port based I/O system). + +Ngaro itself evolved along with RETRO, gaining features like +automated skipping of NOPs and a LOOP opcode to help improve +performance. But the I/O model proved to be a problem. When I +created Ngaro, I had the idea that I would always be able to +assume a console/terminal style environment. The assumption was +that all code would be entered via the keyboard (or maybe a +block editor), and that proved to be the fundamental flaw as +time went on. + +As RETRO grew it was evident that the model had some serious +problems. Need to load code from a file? The VM and language had +functionality to pretend it was being typed in. Want to run on +something like a browser, Android, or iOS? The VM would need to +be implemented in a way that simulates input being typed into +the VM via a simulated keyboard. And RETRO was built around this. +I couldn't change it because of a promise to maintain, as much +as possible, source compatibility for a period of at least five +years. + +When the time came to fix this, I decided at the start to keep +the I/O model separate from the core VM. I also decided that the +core RETRO language would provide some means of interpreting +code without requiring an assumption that a traditional terminal +was being used. + +So Nga began. I took the opportunity to simplify the instruction +set to just 26 essential instructions, add support for packing +multiple instructions per memory location (allowing a long due +reduction in memory footprint), and to generally just make a far +simpler design. + +I've been pleased with Nga. On its own it really isn't useful +though. So with RETRO I embed it into a larger framework that +adds some basic I/O functionality. The *interfaces* handle the +details of passing tokens into the language and capturing any +output. They are free to do this in whatever model makes most +sense on a given platform. + +So far I've implemented: + + - a scripting interface, reading input from a file and + offering file i/o, gopher, and reading from stdin, and + sending output to stdout. + - an interactive interface, built around ncurses, reading + input from stdin, and displaying output to a scrolling + buffer. + - an iOS interface, built around a text editor, directing + output to a separate interface pane. + - an interactive block editor, using a gopher-based block + data store. Output is displayed to stdout, and input is + done via the blocks being evaluated or by reading from + stdin. + +In all cases, the only common I/O word that has to map to an +exposed instruction is `putc`, to display a single character to +some output device. There is no requirement for a traditional +keyboard input model. + +By doing this I was able to solve the biggest portability issue +with the RETRO 10/11 model, and make a much simpler, cleaner +language in the end. + +## RETRO 11 (2011 - 2019): A Look Back + +So it's now been about five years since the last release of RETRO +11. While I still see some people obtaining and using it, I've +moved on to the twelth generation of RETRO. It's time for me to +finally retire RETRO 11. + +As I prepare to do so, I thought I'd take a brief look back. + +RETRO 11 began life in 2011. It grew out of RETRO 10, which was +the first version of RETRO to not be written in x86 assembly +language. For R10 and R11, I wrote a portable virtual machine +(with numerous implementations) and the Forth dialect was kept +in an image file which ran on the VM. + +RETRO 10 worked, but was always a bit too sloppy and changed +drastically between releases. The major goal of RETRO 11 was to +provide a stable base for a five year period. In retrospect, +this was mostly achieved. Code from earlier releases normally +needed only minor adjustments to run on later releases, though +newer releases added significantly to the language. + +There were seven releases. + +- Release 11.0: 2011, July +- Release 11.1: 2011, November +- Release 11.2: 2012, January +- Release 11.3: 2012, March +- Release 11.4: 2012, July +- Release 11.5: 2013, March +- Release 11.6: 2014, August + +Development was fast until 11.4. This was the point at which I +had to slow down due to RSI problems. It was also the point +which I started experiencing some problems with the metacompiler +(as discussed previously). + +RETRO 11 was flexible. All colon definitions were setup as hooks, +allowing new functionality to be layered in easily. This allowed +the later releases to add things like vocabularies, search order, +tab completion, and keyboard remapping. This all came at a cost +though: later things could use the hooks to alter behavior of +existing words, so it was necessary to use a lot of caution to +ensure that the layers didn't break the earlier code. + +The biggest issue was the I/O model. RETRO 11 and the Ngaro VM +assumed the existence of a console environment. All input was +required to be input at the keyboard, and all output was to be +shown on screen. This caused some problems. Including code from +a file required some tricks, temporarily rewriting the keyboard +input function to read from the file. It also became a major +issue when I wrote the iOS version. The need to simulate the +keyboard and console complicated everything and I had to spend +a considerable amount of effort to deal with battery performance +resulting from the I/O polling and wait states. + +But on the whole it worked well. I used RETRO 11.6 until I started +work on RETRO 12 in late 2016, and continued running some tools +written in R11 until the first quarter of last year. + +The final image file was 23,137 cells (92,548 bytes). This was +bloated by keeping some documentation (stack comments and short +descriptions) in the image, which started in 11.4. This contained +269 words. + +I used RETRO 11 for a wide variety of tasks. A small selection of +things that were written includes: + +- a pastebin +- front end to ii (irc client) +- small explorations of interactive fiction +- irc log viewer +- tool to create html from templates +- tool to automate creation of an SVCD from a set of photos +- tools to generate reports from data sets for my employer + +In the end, I'm happy with how RETRO 11 turned out. I made some +mistakes in embracing too much complexity, but despite this it +was a successful system for many years. + +# Security Concerns + +The standard RETRO is not a good choice for applications +needing to be highly secure. + +## Runtime Checks + +The RETRO system performs only minimal checks. It will not +load an image larger than the max set at build time. And +stack over/underflow are checked for as code executes. + +The system does not attempt to validate anything else, it's +quite easy to crash. + +## Isolation + +The VM itself and the core code is self contained. Nga does +not make use of malloc/free, and uses only standard system +libraries. It's possible for buffer overruns within the image +(overwriting Nga code), but the RETRO image shouldn't leak +into the C portions. + +I/O presents a bigger issue. Anything involving I/O, especially +with the `unix:` words, may be a vector for attacks. + +## Future Direction + +I'm not planning to add anything to the *image* side as, for me, +the performance hit due to added checks is bigger than the +benefits. + +The story is different on the VM side. I've already begun taking +steps to address some of the issues, using functions that check +for overruns with strings and doing some minor testing for these +conditions. I will be gradually addressing the various I/O +related extensions, though it's unlikely to ever be fully guarded +against attacks. + +## Rationale + +RETRO is, primarily, a personal system. I'm running code I wrote +to solve problems I face. On the occasions where I run code sent +to me by others, I read it carefully first and then run inside a +sandboxed environment if I'm worried about anything in it. + +### On The Use Of Underscores In Word Names + +In brief: don't use underscores in word names. + +There is a good reason for this, and it has to do with how RETRO +processes strings. By default, underscores in strings are replaced +by spaces. This is problematic when dealing with words like `var`, +`const`, and `d:create` which take word names as strings. + +Consider: + + :hello_msg 'hello_user ; + 'test_name var + #188 !test_name + +In the first case, the `:` prefix handles the token, so the +underscore is not remapped to a space, creating a word name as +`hello_msg`. But in the second, the `'` prefix remaps the +underscore to a space, giving a variable name of `test name`. +In the third line, the name lookup will fail as `test_name` is +not defined, so the store will be done to an incorrect address. + +Because of this, it's best to avoid underscores in names. + +Having covered this, if you do need to use them for some reason, +you can replace `d:add-header` with a version that remaps spaces +back to underscores before creating the header. The following +will allow for this. + + ~~~ + {{ + :fields @Dictionary , (link) , (xt) , (class) ; + :invalid-name? dup ASCII:SPACE s:contains-char? ; + :rewrite [ ASCII:SPACE [ $_ ] case ] s:map ; + :entry here &call dip !Dictionary ; + [ [ fields invalid-name? &rewrite if s, (name) ] entry ] + }} + + #1793 &d:add-header store + &d:add-header n:inc store + ~~~ + +Additional Note: + +Some version of RETRO have included the above patch. The last +release that will include this by default is 2020.4 as it is +not needed by the majority of users. If you want to keep it in +your system, you will need to load it yourself or add it to +your `package/list.forth` (for Unix users) before building. + +# The Code It Yourself Manifesto + +We use software for our everyday needs because we want to get +something done. We have goals to achieve and things to do. + +The software we use is coded by brave programmers that have +their own goals. Most of the time there is an overlap between +their goals and ours. + +Over time these will diverge. + +This means that the tools we depend on grow features we don't +use or understand. There will be bugs in these code parts which +will prevent us from reaching our goals. + +So we are at a fork in the road: + +- We have the choice of trying to understand the code and + fix it. +- We have the choice of trying another program, whose + creator's goals are closer to ours. +- We also have the choice of coding the software ourself. + +All but the last path mean endless seeking, evaluating and +further deviation from our goals. Therefore we replace programs +we do not understand fully with our own implementation. + +The followers of the Code It Yourself Manifesto believe in +these things: + +- We implement it according to our own goals. +- We make mistakes and learn from them. +- We learn how our tools we depend on need to work. +- We gain a deep understanding of our problem domain. +- We still embrace sharing of ideas and code. + +Sharing is only possible if we are excellent developers to +each other. The next developer reading our code will be us +in a not so distant future. Coding It Ourselves means we will +document our code, clearly stating the goal of the software +we write. + +Together we enjoy the diversity of implementations and ideas. + +We encourage our colleagues to + +**Code It Yourself.** + +---- + +Written by Christian Kellermann on 2016-01-12, licensed under +a CreativeCommonsAttribution-ShareAlike3.0UnportedLicense. + +Original text taken from +http://pestilenz.org/~ckeen/blog/posts/ciy-manifesto.html + +# Deprecation Policy + +As RETRO evolves, some words will become obsolete and no longer +be needed. In each release, these will be marked as deprecated +in the glossary. Any deprecated words will be removed in the +next quarterly release. + +E.g., if 2020.1 had deprecated words, these would be removed in +the 2020.4 release. Any words made deprecated in between 2020.1 +and 2020.4 would be removed in the 2020.7 release. +