{"id":13761129,"url":"https://github.com/richardhundt/shine","last_synced_at":"2025-05-10T12:31:04.846Z","repository":{"id":9518486,"uuid":"11416194","full_name":"richardhundt/shine","owner":"richardhundt","description":"A Shiny Lua Dialect","archived":false,"fork":false,"pushed_at":"2021-04-22T10:21:02.000Z","size":580,"stargazers_count":231,"open_issues_count":15,"forks_count":18,"subscribers_count":17,"default_branch":"master","last_synced_at":"2024-08-03T13:06:05.929Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/richardhundt.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-07-15T06:17:25.000Z","updated_at":"2024-07-28T22:16:44.000Z","dependencies_parsed_at":"2022-09-18T12:30:56.644Z","dependency_job_id":null,"html_url":"https://github.com/richardhundt/shine","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardhundt%2Fshine","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardhundt%2Fshine/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardhundt%2Fshine/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/richardhundt%2Fshine/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/richardhundt","download_url":"https://codeload.github.com/richardhundt/shine/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224957965,"owners_count":17398494,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-03T13:01:39.587Z","updated_at":"2024-11-16T18:32:06.491Z","avatar_url":"https://github.com/richardhundt.png","language":"Lua","funding_links":[],"categories":["Lua","Resources"],"sub_categories":["Lua 5.1"],"readme":"\n```Lua\n-- taken from a real world web app which talks to elasticsearch\n\nimport JSON        from \"codec.json\"\nimport Presenter   from \"swarm.app\"\nimport HTTPStatic  from \"swarm.static\"\n\nimport ESClient, ESIndex from \"app.es.client\"\n\n-- this presenter is a singleton, so we use `module` here\nmodule Features include Presenter\n\n   local client  = ESClient('localhost', 9200)\n   local storage = ESIndex(client, 'features')\n   local static  = HTTPStatic(\"./public/admin\")\n\n   @self.route('GET', '/admin')\n   admin(req, path, query)\n      if #path == 0 then\n         path[#path + 1] = 'index.html'\n      end\n      return static.handler(req, path, query)\n   end\n\n   @self.route('GET', '/features/feature/:id')\n   fetch(req, args, query)\n      resp = storage.lookup('feature', args['id'])\n      hdrs = { }\n      hdrs['Content-Type'] = 'application/json'\n      if resp.exists then\n         return { 200, hdrs, { JSON.encode(resp) } }\n      else\n         return { 404, hdrs, { JSON.encode(resp) } }\n      end\n   end\n\nend\n```\n\n# Shine Reference\n\nThis document aims to be a fairly concise, but broad reference.\n\nTo help get you started, though, have a look at the [wiki](https://github.com/richardhundt/shine/wiki)\nwhich has a growing collection of tutorials.\n\n* [Introduction](#introduction)\n* [Philosophy](#philosophy)\n* [Getting Started](#getting-started)\n* [Language Basics](#language-basics)\n  * [Comments](#comments)\n  * [Identifiers](#identifiers)\n  * [Scoping](#scoping)\n  * [Builtin Types](#builtin-types)\n    * [Booleans](#booleans)\n    * [Numbers](#numbers)\n    * [`nil` and `null`](#nil-and-null)\n    * [Strings](#strings)\n    * [Ranges](#ranges)\n    * [Tables](#tables)\n    * [Arrays](#arrays)\n    * [Patterns](#patterns)\n  * [Expressions](#expressions)\n    * [Operators](#operators)\n    * [Call Expressions](#call-expressions)\n    * [Member Expressions](#member-expressions)\n    * [Assignment](#assignment)\n    * [Destructuring](#destructuring)\n    * [Comprehensions](#comprehensions)\n    * [Lambda Expressions](#lambda-expressions)\n  * [Statements](#statements)\n    * [Do Statement](#do-statement)\n    * [If Statement](#if-statement)\n    * [Given Statement](#given-statement)\n    * [While Statement](#while-statement)\n    * [Numeric For Loop](#numeric-for-loop)\n    * [Generic For Loop](#generic-for-loop)\n    * [Try Statement](#try-statement)\n    * [Import Statement](#import-statement)\n    * [Export Statement](#export-statement)\n  * [Guards](#guards)\n  * [Functions](#functions)\n  * [Generators](#generators)\n  * [Modules](#modules)\n  * [Classes](#classes)\n    * [Methods](#methods)\n    * [Properties](#properties)\n    * [Constructor](#constructor)\n    * [Inheritance](#inheritance)\n    * [Module Mixins](#module-mixins)\n  * [Grammars](#grammars)\n  * [Decorators](#decorators)\n  * [Macros](#macros)\n* [Standard Libraries](#standard-libraries)\n  * [Concurrency](#concurrency)\n    * [Fibers](#fibers)\n    * [Threads](#threads)\n  * [Serialization](#serialization)\n\n## \u003ca name=\"introduction\"\u003e\u003c/a\u003eIntroduction\n\nShine is a general purpose, dynamic, multi-paradigm programming\nlanguage which is based on, and extends, Lua with features geared\nmore to programming in the large. For maximum performance it uses\na [modified](https://github.com/fperrad/tvmjit) version of the\n[LuaJIT](http://luajit.org) virtual machine, which is known for its\nsmall footprint and impressive performance which rivals that of C.\n\nMost of the language features are those of the underlying LuaJIT\nVM, and the extensions are implemented in terms of lower level\nconstructs already present in LuaJIT, so anyone familiar with\nLua and LuaJIT should quickly feel right at home with Shine.\n\nMoreover, vanilla Lua libraries can be loaded and run unmodified,\nand although compilation of Lua code is slower than with LuaJIT or\nPuC Lua, there is no additional runtime penalty, and since they\nshare the same bytecode, this means that Shine users can leverage\nall of the existing Lua libraries out there without writing wrappers\nor additional bindings. You can, of course, call seamlessly into\nShine code from Lua too, as long as Lua is running within the\nShine runtime.\n\nAnother goal of Shine, is that the standard libraries which are\nincluded are focused on providing\n[CSP](http://en.wikipedia.org/wiki/Communicating_sequential_processes)\nstyle concurrency, so although the language itself has no concurrency\nprimitives, the fibers, channels, threads, pipes and I/O libraries\nare all centered around building highly scalable, low-footprint,\nnetwork oriented concurrent applications.\n\n## \u003ca name=\"philosophy\"\u003e\u003c/a\u003ePhilosophy\n\nShine strives for a pragmatic balance between safety and syntactic\nand semantic flexibility.\n\nSummary of safety features:\n\n* Static local variable name resolution.\n* Default declaration scope is localized.\n* Function and method parameter guards.\n* Scoped variable guards.\n* Self-type assertions in methods.\n\nSummary of flexibility features:\n\n* Operator meta-methods as in Lua with Shine specific extensions.\n* Deep introspection into nominal types.\n* Lambda expressions (short function syntax).\n* Optional parentheses.\n* Property getters and setters with fallback.\n* User-only operators.\n* Procedural Macros\n* Decorators\n\nAdditionally, all constructs can be nested. Classes can be declared\ninside other classes and even inside functions, which allows for\nrun-time construction of classes, modules and grammars.\n\nOther notable extensions to Lua:\n\n* Bitwise operators.\n* Standard libraries.\n* Tight LPeg integration.\n* Classes and modules .\n* `continue` statement.\n* `try`, `catch`, `finally`\n* Destructuring assignment.\n* Pattern matching.\n* Default function parameters.\n* Parameter and variable guards.\n* Richer type system.\n* Concurrency primitives\n* OS Threads\n\n## \u003ca name=\"getting-started\"\u003e\u003c/a\u003eGetting Started\n\nShine ships with all its dependencies, so simply clone the git\nrepository and run `make \u0026\u0026 sudo make install`:\n\n```\n$ git clone --recursive https://github.com/richardhundt/shine.git\n$ make \u0026\u0026 sudo make install\n```\n\nStandard `package.path` and `package.cpath` values set up by virtual machine\ncould be customized with passing `TVMJIT_PREFIX` and `TVMJIT_MULTILIB`\nparameters to `make`. It could be useful for accessing Lua libraries installed\nby standard Linux distro way. For example, on Debian following parameter\nvalues could be used:\n\n```\n$ make TVMJIT_PREFIX=/usr TVMJIT_MULTILIB=\"lib/$(gcc -print-multiarch)\" \u0026\u0026 sudo make install\n```\n\nThis will install two executables `shinec` and `shine` (along with standard\nlibrary).  The `shinec` executable is just the compiler and has the following\nusage:\n\n```\nusage: shinec [options]... input output.\nAvailable options are:\n  -t type   Output file format.\n  -b        List formatted bytecode.\n  -n name   Provide a chunk name.\n  -g        Keep debug info.\n  -p        Print the parse tree.\n  -o        Print the opcode tree.\n```\n\nThe main executable and runtime is `shine`, which includes\nall the functionality of `shinec` via the `-c` option and\nhas the following usage:\n\n```\nusage: shine [options]... [script [args]...].\nAvailable options are:\n  -e chunk  Execute string 'chunk'.\n  -c ...    Compile or list bytecode.\n  -i        Enter interactive mode after executing 'script'.\n  -v        Show version information.\n  --        Stop handling options. \n  -         Execute stdin and stop handling options.\n```\n\nThe `script` file argument extension is significant in that\nfiles with a `.lua` extension are passed to the built-in Lua\ncompiler, whereas files with a `.shn` extension are compiled\nas Shine source.\n\nShine has been tested on Linux and Mac OS X, and support for\nWindows is in progress.\n\n## \u003ca name=\"language-basics\"\u003e\u003c/a\u003eLanguage Basics\n\nShine is a line-oriented language. Statements are generally seperated\nby a line terminator. If several statements appear on the same line, they\nmust be may be separated by a semicolon `;`.\n\nLong expressions with infix operators may be wrapped with the operator\nleading after the line break, however for function and method calls, the\nargument list must start on the same line as the callee:\n\n```\na = 40\n  + 2 -- OK\n\nfoo\n  .bar() -- OK\n\nprint \"answer:\", 42 -- OK [means: print(\"answer:\", 42)]\n\nprint(\n  \"answer:\", 42 -- OK\n)\n\nprint\n  \"answer:\", 42 -- BAD [syntax error]\n```\n\nA bare word by itself is parsed as a function call:\n\n```\nif waiting then\n   yield -- compiles as yield()\nend\n```\n\n### \u003ca name=\"comments\"\u003e\u003c/a\u003eComments\n\nComments come in 3 forms:\n\n* Lua-style line comments starting with `--`\n* Lua-style block comments of the form `--[=*[ ... ]=*]`\n* Shine block comments of the form `--:\u003ctoken\u003e([^)]*)?: ... :\u003ctoken\u003e:`\n\nThe last form is designed to allow Shine sources to be annotated\nfor processing by external tools such as documentation generators:\n\n```\n-- a line comment\n\n--[[\na familiar Lua-style\nblock comment\n]]\n\n--::\nsimple Shine block comment\n::\n\n--:md(github-flavored):\nperhaps this is extracted by a markdown processor\n:md:\n```\n\n### \u003ca name=\"identifiers\"\u003e\u003c/a\u003eIdentifiers\n\nIdentifiers must start with `[a-zA-Z_$?]` (alphabetical characters\nor `_` or `$` or `?`) which may be followed by zero or more\n`[a-zA-Z_$!?0-9]` characters (alphanumeric or `_` or `$` or `!` or `?`).\n\n```\n$this_is_valid\nso_is_$this\nthis_is_valid_too!\nunusual?_but_still_valid\n```\n\n### \u003ca name=\"scoping\"\u003e\u003c/a\u003eScoping\n\nShine scoping rules are similar to Lua's with the addition of the concept\nof a default storage if `local` is not specified when introducing a new\ndeclaration.\n\nThe default storage for variables is always `local`. For other\ndeclarations, it depends on the enclosing scope:\n\n* If at the top level of a compilation unit, the default is package\n  scoped for all non-variable declarations.\n* Inside class and module bodies, the default is scoped to the body\n  environment.\n* Everwhere else (i.e. functions and blocks) it is `local`.\n\nDeclarations can always be lexically scoped by declaring them as `local`.\n\nIn short, what this means is that most of the time you can simply leave out\nthe `local` keyword without worrying about creating globals or leaking out\ndeclarations to the surrounding environment.\n\nThere are cases where a `local` is useful for reusing a variable name in\na nested scope when the inner scope should shadow the variable in the outer\nscope.\n\n### \u003ca name=\"builtin-types\"\u003e\u003c/a\u003eBuiltin Types\n\nShine includes all of LuaJIT's builtin types:\n\n* `nil`\n* `boolean`\n* `number`\n* `string`\n* `table`\n* `function`\n* `thread` (coroutine)\n* `userdata`\n* `cdata`\n\nAll other extensions are built primarily using `table`s and `cdata`.\n\nThese include:\n\nPrimitive meta types:\n\n* `Nil`\n* `Boolean`\n* `Number`\n* `String`\n* `Table`\n* `Function`\n* `Coroutine`\n* `UserData`\n* `CData`\n\nAdditional builtins:\n\n* `null` (CData meta type)\n* `Array`\n* `Range`\n* `Error`\n\nNominal meta types:\n\n* `Class`\n* `Module`\n* `Grammar`\n\nPattern matching meta types:\n\n* `Pattern`\n* `ArrayPattern`\n* `TablePattern`\n* `ApplyPattern`\n\nThe meta meta type:\n\n* `Meta`\n\n#### \u003ca name=\"booleans\"\u003e\u003c/a\u003eBooleans\n\nThe constants `true` and `false`. The only values which are logically\nfalse are `false` and `nil`. Everything else evaluates to `true` in a\nboolean context.\n\n#### \u003ca name=\"numbers\"\u003e\u003c/a\u003eNumbers\n\nThe Shine parser recognizes LuaJIT `cdata` long integers as well as\nLua numbers. This is extended with octals.\n\nThe following are represented as Lua `number` type:\n\n* `123`\n* `123.45`\n* `1.2e3`\n* `0x42` - heximal\n* `0o644` - octal\n\nThese are LuaJIT extensions enabled by default in Shine:\n\n* `42LL` - LuaJIT long integer `cdata`\n* `42ULL` - LuaJIT unsigned long integer `cdata`\n\n#### \u003ca name=\"nil-and-null\"\u003e\u003c/a\u003e`nil` and `null`\n\nThe constant `nil` has exactly the same meaning as in Lua.\n\nThe constant `null` is exactly the cdata `NULL` value. It compares\nto `nil` as true, however, unlike in C, in a boolean context also\nevaluates to true. That is, although `null == nil` holds, `if null\nthen print 42 end` will print \"42\".\n\n#### \u003ca name=\"strings\"\u003e\u003c/a\u003eStrings\n\nAs in Lua, strings are 8-bit clean, immutable and interned. The\nextensions added by Shine relate to delimiters, escape sequences\nand expression interpolation.\n\nThere are two types of strings:\n\n* Single quoted\n* Double quoted\n\nSingle quoted strings are verbatim strings. The only escape sequences\nwhich they recognise are `\\'` and `\\\\`. All other bytes are passed\nthrough as is.\n\nDouble quoted strings allow the common C-style escape sequences, including\nunicode escapes. These are all valid strings:\n\n```\n\"text\"\n\"tab\\t\"\n\"quote\\\"\"\n\"\\x3A\"      -- hexadecimal 8-bits character\n\"\\u20AC\"    -- unicode char UTF-8 encoded\n\"\nmultiline\nstring\n\"\n```\n\nAdditionally, double quoted strings interpolate expressions inside\n`%{` and `}` marks. When constructing strings programmatically it\nis encouraged to use this form as the fragments produced are\nconcatenated in a single VM instruction without creating short-lived\ntemporary strings.\n\n```\n\"answer = %{40 + 2}\" -- interpolated\n```\n\nBoth types of strings can be delimited with single and triple\ndelimiters. This is just a convenience to save escaping quotation\nmarks:\n\n```\n\"a quoted string\"\n\"\"\"a triple quoted string\"\"\"\n'a verbatim string'\n'''a triple quoted verbatim string'''\n```\n\n##### \u003ca name=\"string-operations\"\u003e\u003c/a\u003eString Operations\n\nStrings have a metatable with all the methods supported by Lua,\nnamely: `len`, `match`, `uppper`, `sub`, `char`, `rep`, `lower`,\n`dump`, `gmatch`, `reverse`, `byte`, `gsub`, `format` and `find`.\n\nShine adds a `split` method with the following signature:\n\n* `str.split(sep = '%s+', max = math::huge, raw = false)`\n\nSplits `str` on `sep`, which is interpreted as a Lua match pattern\nunless `raw` is `true`. The default value for `sep` is `%s+`. If\n`max` is given, then this is the maximum number of fragments returned.\nIf the pattern is not found, the `split` returns the entire string.\nThe `split` method is only available as a method, and is not defined\nin the `string` library.\n\nStrings can additionally be subscripted with numbers and ranges.\nBoth subscripts have the effect of calling `string.sub()` internally.\nIf a number is passed then a single character is returned at that\noffset, otherwise the two extremes of the range are passed to\n`string.sub`.  Negative offsets may be used.\n\n#### \u003ca name=\"ranges\"\u003e\u003c/a\u003eRanges\n\nRanges are objects which represent numeric spans and are constructed with\n`\u003cexpr\u003e .. \u003cexpr\u003e`. They can be used for slicing strings, or for looping\nconstructs.\n\n#### \u003ca name=\"tables\"\u003e\u003c/a\u003eTables\n\nTables work just as in Lua with the addition that line-breaks serve as\nseparators, in addition to `,` and `;`\n\n```\n-- these are equivalent\nt = { answer = 42, 1, 'b' }\nt = {\n    answer = 42\n    1\n    'b'\n}\n```\n\n#### \u003ca name=\"arrays\"\u003e\u003c/a\u003eArrays\n\nArrays are zero-based, numerically indexed lists of values, based on Lua\ntables, with the difference being that they track their length, and so\nmay contain `nil` values.\n\nArrays have a literal syntax delimited by `[` and `]` as in languages\nsuch as Perl, JavaScript or Ruby, but may also be constructed by\ncalling `Array(...)`.\n\n```\na = [ 1, 'two', 33 ]\na = Array(1, 'two', 33) -- same thing\n```\n\nThe array type defines the following methods:\n\n* `join(sep = '')`\n\n* `push(val)`\n\n* `pop()`\n\n* `shift()`\n\n* `unshift(val)`\n\n* `slice(offset, count)`\n\n  Returns a new array with `count` elements, starting at `offset`.\n\n* `reverse()`\n\n  Returns a new array with elements in reverse order.\n\n* `sort(cmp = less, len = #self)`\n\n  Sorts the array in place using the comparison function `cmp` if given\n  and limits the number of items sorted to `len` if provided.\n\n#### \u003ca name=\"patterns\"\u003e\u003c/a\u003ePatterns\n\nShine integrates Parsing Expression Grammars into the language as\na first-class type, thanks to the excellent\n[LPeg](http://www.inf.puc-rio.br/~roberto/lpeg/) library.\n\nPatterns are delimited by a starting and ending `/`, which borrows from\ncommonly used regular expression quotation. However, Shine's patterns\nare very different and far more powerful than regular expressions.\n\nSyntax borrows heavily from the [re.lua](luahttp://www.inf.puc-rio.br/~roberto/lpeg/re.html) module.  Notable differences are that `|` replaces re's `/` as an\nalternation separator, `%pos` replaces `{}` as a position capture, and `+\u003e`\nreplaces `=\u003e` as a match-time capture. Fold captures are added using `~\u003e`.\n\nUnlike the `re.lua` module, grammars aren't represented as strings,\nbut are compiled to LPeg API calls directly, so production rules\nfor `-\u003e`, `~\u003e` and `+\u003e` captures can be any term or postfix expression\nsupported by the language itself.\n\nWhich means you can say `rule \u003c- %digit -\u003e function(c) ... end`\nwith functions inlined directly in the grammar.\n\nIt also means that patterns can be composed using the standard Lua\noperators as with the LPeg library:\n\n```\nword = / { %alnum+ } /\npatt = / %s+ / * word + function()\n   error \"d'oh!\"\nend\n```\n\n### \u003ca name=\"expressions\"\u003e\u003c/a\u003eExpressions\n\nExpressions are much the same as in Lua, with a few changes and some\nadditions, notable C-style bitwise operators.\n\nString concatenation is done using `~` instead of `..` as the latter\nis reserved for ranges. The `**` operator replaces `^` as exponentiation\n(`^` is bitwise xor instead).\n\nMoreover, methods can be called directly on literals without the need to\nsurround them in parentheses. So whereas in Lua one would say:\n\n```\nlocal quote = (\"%q\"):format(val)\n```\n\nin Shine it's simply:\n\n```\nlocal quote = \"%q\".format(val)\n```\n\n#### \u003ca name=\"operators\"\u003e\u003c/a\u003eOperators\n\nThe following table lists Shine's operators in order of increasing\nprecedence. Operators marked with a trailing `_` are unary operators.\n\n| Operator | Precedence | Associativity | Comment |\n|----------|------------|---------------|---------|\n| `..._`   | 1          | right         | unpack |\n| `or`     | 1          | left          | logical or |\n| `and`    | 2          | left          | logical and |\n| `==`     | 3          | left          | equality |\n| `!=`     | 3          | left          | inequality |\n| `~~`     | 3          | left          | matches |\n| `!~`     | 3          | left          | does not match |\n| `is`     | 4          | left          | type equality |\n| `as`     | 4          | left          | type coercion |\n| `\u003e=`     | 5          | left          | greater than or equal to |\n| `\u003c=`     | 5          | left          | less than or equal to |\n| `\u003e`      | 5          | left          | greater than |\n| `\u003c`      | 5          | left          | less than |\n| \u0026#124;   | 6          | left          | bitwise or |\n| `^`      | 7          | left          | bitwise exclusive or |\n| `\u0026`      | 8          | left          | bitwise and |\n| `\u003c\u003c`     | 9          | left          | bitwise left shift |\n| `\u003e\u003e`     | 9          | left          | bitwise right shift |\n| `\u003e\u003e\u003e`    | 9          | left          | bitwise arithmetic right shift |\n| `~`      | 10         | left          | concatenation |\n| `+`      | 10         | left          | addition |\n| `-`      | 10         | left          | subtraction |\n| `..`     | 10         | right         | range |\n| `*`      | 11         | left          | multiplication |\n| `/`      | 11         | left          | division |\n| `%`      | 11         | left          | remainder (modulo) |\n| `~_`     | 12         | right         | bitwise not |\n| `!_`     | 12         | right         | logical not |\n| `not_`   | 12         | right         | logical not |\n| `**`     | 13         | right         | exponentiation |\n| `#_`     | 14         | right         | length of |\n\nMany infix operators are also available in update, or assigment, form:\n\n| Operator  | Comment |\n|-----------|---------|\n| `+=`      | add assign |\n| `-=`      | subtract assign |\n| `~=`      | concatenate assign |\n| `*=`      | multiply assign |\n| `/=`      | divide assign |\n| `%=`      | modulo assign |\n| `**=`     | exponentiation assign |\n| `and=`    | logical and assign |\n| `or=`     | logical or assign |\n| `\u0026=`      | bitwise and assign |\n| \u0026#124;=   | bitwise or assign |\n| `^=`      | bitwise xor assign |\n| `\u003c\u003c=`     | bitwise left shift assign |\n| `\u003e\u003e=`     | bitwise right shift assign |\n| `\u003e\u003e\u003e=`    | bitwise arithmetic right shift assign |\n\nThe following operators are used in [patterns](#patterns):\n\n| Operator | Precedence | Associativity | Comment |\n|----------|------------|---------------|---------|\n| `~\u003e`     | 1          | left          | fold capture |\n| `-\u003e`     | 1          | left          | production capture |\n| `+\u003e`     | 1          | left          | match-time capture |\n| \u0026#124;   | 2          | left          | ordered choice |\n| `\u0026_`     | 3          | right         | lookahead assertion |\n| `!_`     | 3          | right         | negative lookahead assertion |\n| `+`      | 3          | left          | one or more repetitions |\n| `*`      | 3          | left          | zero or more repetitions |\n| `?`      | 3          | left          | zero or one |\n| `^+`\u003cN\u003e  | 4          | right         | at least `N` repetitions |\n| `^-`\u003cN\u003e  | 4          | right         | at most `N` repetitions |\n\nNot listed above are the common `(` and `)` for grouping, and\npostcircumfix `()` and `[]` operators for function/method calls and\nsubscripting respectively.\n\nIn addition to the built-in operators, Shine exposes a full suite\nof user-definable operators, which share precedence with their\nbuilt-in counterparts, but have no intrinsic meaning to the language.\n\nShine will simply try to call the corresponding meta-method as with\nthe built-in operators. The full listing is:\n\n| Operator | Precedence | Associativity | Meta-Method |\n|----------|------------|---------------|-------------|\n|`:!`      | 3          | left          | `__ubang`   |\n|`:?`      | 3          | left          | `__uques`   |\n|`:=`      | 5          | left          | `__ueq`     |\n|`:\u003e`      | 5          | left          | `__ugt`     |\n|`:\u003c`      | 5          | left          | `__ult`     |\n|:\u0026#124;   | 6          | left          | `__upipe`   |\n|`:^`      | 7          | left          | `__ucar`    |\n|`:\u0026`      | 8          | left          | `__uamp`    |\n|`:~`      | 10         | left          | `__utilde`  |\n|`:+`      | 10         | left          | `__uadd`    |\n|`:-`      | 10         | left          | `__usub`    |\n|`:*`      | 11         | left          | `__umul`    |\n|`:/`      | 11         | left          | `__udiv`    |\n|`:%`      | 11         | left          | `__umod`    |\n\n#### \u003ca name=\"call-expressions\"\u003e\u003c/a\u003eCall Expressions\n\nWhen calling a function, method, or other callable, parenthesis\nmay be omitted provided there is either at least one argument.\nThe following are all valid:\n\n```\nfido.bark(loudness)\nfido.move x, y          -- fido.move(x, y)\n```\n\nAs a special case, if the callee is a single word as a statement\non its own, then no parentheses or arguments are required:\n\n```\nyield                   -- OK yield()\nfido.greet              -- BAD (not a word)\nprint yield             -- BAD (yield not a statement)\n```\n\n#### \u003ca name=\"member-expressions\"\u003e\u003c/a\u003eMember Expressions\n\nMember expressions have three lexical forms:\n\n* method call\n* property call\n* property access\n\nShine deviates from Lua in that the `.` operator when followed by\na call expression is a method call, whereas Lua uses `:`. To call\na property without passing an implicit receiver, use `::` instead:\n\n```\ns.format(...)          -- method call (self is implicit)\nstring::format(s, ...) -- property call\n```\n\nFor property access, either `::` or `.` may be used with identical\nsemantics. By convention, one may prefer `::` for indicating namespace\naccess such as `async::io::StreamReader`, whereas `.` may be used to\naccess instance members.\n\n#### \u003ca name=\"assignment\"\u003e\u003c/a\u003eAssignment\n\nAssignment expressions are based on Lua allowing multiple left and\nright hand sides. If an identifier on the left is previously\nundefined, then a new local variable is automatically introduced\nthe fist time it is assigned.  This prevents global namespace\npollution. Examples:\n\n```\na, b = 1, 2             -- implicit locals a, b\no.x, y = y, o.x         -- implicit local y \nlocal o, p = f()        -- explicit\na[42] = 'answer'\n```\n\n#### \u003ca name=\"destructuring\"\u003e\u003c/a\u003eDestructuring\n\nShine also supports destructuring of tables, arrays and application\npatterns. This can be used during assignment as well as pattern\nmatching in [given](#given-statement) statements.\n\nFor tables and arrays, Shine knows how to extract values for you:\n\n```\na = ['foo', { bar = 42 }, 'baz']\n[x, { bar = y }, z] = a\nprint x, y, z           -- prints: foo  42  baz\n```\n\nHowever, with objects you have to implement an `__unapply` hook to make\nit work. The hook is expected to return an iterator which would be valid\nfor use in a generic for loop. Here's an example:\n\n```\nclass Point\n   self(x = 0, y = 0)\n      self.x = x\n      self.y = y\n   end\n   function self.__unapply(o)\n      return ipairs{ o.x, o.y }\n   end\nend\n\np = Point(42, 69)\nPoint(x, y) = p\nprint x, y              -- prints: 42   69\n```\n\n[Patterns](#patterns) already implement the relevant hooks, so the following\nworks as expected:\n\n```\nSplit2 = / { [a-z]+ } %s+ { [a-z]+ } /\nstr = \"two words\"\n\nSplit2(a, b) = str\n\nassert a == 'two' and b == 'words'\n```\n\n#### \u003ca name=\"comprehensions\"\u003e\u003c/a\u003eComprehensions\n\nComprehensions are an experimental feature only implemented for\narrays currently. They are also _not_ lazy generators. They should\nlook familiar to Python programmers. Here are two examples:\n\n```\na1 = [ i * 2 for i in 1..10 if i % 2 == 0 ]\na2 = [ i * j for i in 1..5 for j in 1..5 ]\n```\n\n#### \u003ca name=\"lambda-expressions\"\u003e\u003c/a\u003eLambda Expressions\n\nShine has a syntactic short-hand form for creating functions:\n\n`(\u003cparam_list\u003e)? =\u003e \u003cfunc_body\u003e \u003cend\u003e`\n\nThe parameter list is optional.\n\n```\n-- these two are identical\nf1 = (x) =\u003e\n   return x * 2\nend\nfunction f1(x)\n    return x * 2\nend\n```\n\nAdditionally, if the function body contains a single expression\nand appears on one line, then an implicit `return` is inserted\nand the `end` token is omitted:\n\n```\nb = a.map((x) =\u003e x * 2)\n\n-- shorter still\nb = a.map (x) =\u003e x * 2\n```\n\nMeans:\n\n```\nb = a.map((x) =\u003e\n   return x * 2\nend)\n```\n\n### \u003ca name=\"statements\"\u003e\u003c/a\u003eStatements\n\n#### \u003ca name=\"do-statement\"\u003e\u003c/a\u003eDo Statement\n\n`do \u003cchunk\u003e end`\n\nSame as in Lua.\n\n#### \u003ca name=\"if-statement\"\u003e\u003c/a\u003eIf Statement\n\n`if \u003cexpr\u003e then \u003cchunk\u003e (elseif \u003cexpr\u003e then \u003cchunk\u003e)* (else \u003cchunk\u003e)? end`\n\nSame as in Lua.\n\n#### \u003ca name=\"given-statement\"\u003e\u003c/a\u003eGiven Statement\n\n`given \u003cexpr\u003e (case \u003cbind_expr\u003e then \u003cchunk\u003e)* (else \u003cchunk\u003e)? end`\n\nThis is analogous to C's `switch` statement, however, the discriminant\nis not simply compared for equality. Instead, Shine provides pattern\nand smart matching capabilities.\n\nIf `\u003cbind_expr\u003e` is not an extractor used for destructuring:\n\n* If the `\u003cbind_expr\u003e` evaluates to an object which implements a\n  `__match` metamethod, then this is used to determine of the\n  discriminant given by `\u003cexpr\u003e` matches.\n\n* Otherwise the `is` operator is used for comparison.\n\nIf `\u003cbind_expr\u003e` is a destructuring expression, then the extractor\nis bound and evaluated.\n\nExample:\n\n```\nfunction match(disc)\n   given disc\n      case \"Hello World!\" then\n         print \"a greeting\"\n      case String then\n         print \"a string\"\n      case { answer = A } then\n         print \"%{A} is the answer\"\n      else\n         print \"something else\"\n   end\nend\nmatch \"Hello World!\"    -- prints: \"a greeting\"\nmatch \"cheese\"          -- prints: \"a string\"\nmatch { answer = 42 }   -- prints: \"42 is the answer\"\nmatch 42                -- prints: \"something else\"\n```\n\n#### \u003ca name=\"while-statement\"\u003e\u003c/a\u003eWhile Statement\n\n`while \u003cexpr\u003e do \u003cchunk\u003e end`\n\nSame as in Lua.\n\n#### \u003ca name=\"repeat-statement\"\u003e\u003c/a\u003eRepeat Statement\n\n`repeat \u003cchunk\u003e until \u003cexpr\u003e`\n\nSame as in Lua.\n\n#### \u003ca name=\"numeric-for-loop\"\u003e\u003c/a\u003eNumeric For Loop\n\n`for \u003cident\u003e=\u003cinit\u003e,\u003climit\u003e,\u003cstep\u003e do \u003cchunk\u003e end`\n\nSame as in Lua.\n\n#### \u003ca name=\"generic-for-loop\"\u003e\u003c/a\u003eGeneric For Loop\n\n`for \u003cname_list\u003e in \u003cexpr_list\u003e do \u003cchunk\u003e end`\n\nGenerally works as in Lua, except that you don't need to use `pairs`\nas it is called implicitly (via a builtin called `__each__`), if\nthe first argument in `\u003cexpr_list\u003e` is not a function.\n\nThe builtin `__each__` also calls a meta-method hook `__each`. This\nallows objects to differentiate `pairs`, `ipairs` iterators which\nreturn pairs, from the notion of a /default/ iterator, which may\nreturn an arbitrary number of values.\n\n#### \u003ca name=\"try-statement\"\u003e\u003c/a\u003eTry Statement\n\n`try \u003cchunk\u003e (catch \u003cident\u003e (if \u003cexpr\u003e)? then \u003cchunk\u003e)* (finally \u003cchunk\u003e)? end`\n\nDoes an `xpcall` internally, however it ensures that the `finally` clause is\nrun, even if `return` is used in the `try` block or one of the `catch`\nbodies.\n\n```\nfunction foo()\n   try\n      throw Error(\"cheese\")\n      return 42\n   catch e if e is Error then\n      print(\"caught:\", e)\n      return 69\n   catch e then\n      print(\"something else\")\n   finally\n      print('cleanup')\n   end\nend\n\nprint(\"GOT:\", foo())\n\n--:output:\n\ncaught:  cheese\ncleanup\nGOT:    69\n\n--:output:\n```\n\nJust bear in mind that this still creates up to three closures\ninline, so it's best to place loops inside the try block and not\naround it.\n\n#### \u003ca name=\"import-statement\"\u003e\u003c/a\u003eImport Statement\n\n`import macro? (\u003calias\u003e = )? \u003csymbol\u003e (, (\u003calias\u003e = )? \u003csymbol\u003e)* from \u003cexpr\u003e`\n\nCalls `require(expr)` and then extracts and assigns the named symbols\nto `local` variables. May be used anywhere.\n\n`import macro ...` doesn't assign the named symbols to `local` variables, but\nintroduces them as [macros](#macros) in current scope. `import macro ..` is a\ncompile time statement evaluated in translating phase.\n\nAlternative syntaxes:\n```\nimport macro? \u003cmodule_path\u003e.\u003csymbol\u003e\nimport macro? \u003cmodule_path\u003e.{(\u003calias\u003e = )? \u003csymbol\u003e (, (\u003calias\u003e = )? \u003csymbol\u003e)*}\n```\n\n`import a.b.{x = m, y = n}` is equivalent to `import x = m, y = n from \"a.b\"`\n\n#### \u003ca name=\"export-statement\"\u003e\u003c/a\u003eExport Statement\n\n`export \u003cident\u003e (, \u003cident\u003e)*`\n\nCopies the values refered to by the identifiers into a table which is\nreturned by the compilation unit. By default, the `_M` table is visible\nalong with all non-local declarations being available for import or\npublic access. By using an explicit `export`, only the symbols declared\nare exported and the compilation unit's namespace is essentially sealed.\n\nThe `export` statement may not precede the declarations which are being\nexported.\n\n### \u003ca name=\"guards\"\u003e\u003c/a\u003eGuards\n\nVariables and function parameters can have guards associated with them.\nThe Shine compiler inserts checks which are executed at runtime each\ntime the variable is updated, or in the case of parameters, on\nfunction entry.\n\nA variable guard is introduced by using the `is` keyword in a\ndeclaration:\n\n```\nlocal a is Number = 42\n\n-- or simply\nb is Number = 101\n\n-- works for destructuring too:\n{ x is Number = X, y is Number = Y } = point\n```\n\nThe mechanics are simple: The right hand side of a guard expression\ncan be any object which implements an `__is` hook. If the hook\nreturns a non-true value, an error is raised.\n\nThe builtin types such as `Number`, as well as classes and modules\nalready have the `__is` hook implemented, so these should \"just work\".\n\nGuards are lexically bound, static entities. That is, the value of\nthe variable does not carry around additional run-time meta-data\nwith it, so passing it to a different scope (or returning it) does\nnot guarantee that its type remains constrained:\n\n```\nfunction random()\n   local x is Number = math::random()\n   return x\nend\n\nx = random()\nx = \"cheese\"        -- no error here\n```\n\nHowever, in practice, functions and methods can enforce a contract:\n\n```\nfunction addone(x is Number)\n   return x + 1\nend\naddone \"cheese\"     -- Error: bad argument #1 to 'addone'...\n```\n\n### \u003ca name=\"functions\"\u003e\u003c/a\u003eFunctions\n\nFunctions are closures with all the same semantics as in Lua, however\nShine extends function declarations with _default parameter expressions_,\n_parameter guards_, and _rest arguments_.\n\nDefault parameter expressions can be any valid Shine expression and are\nscoped to the body of the function. That is, they are evaluate at the top\nof the function body.\n\n```\nfunction greet(whom = \"World\")\n   print \"Hello %{whom}!\"\nend\ngreet()             -- prints: \"Hello World!\"\ngreet(\"romix\")      -- prints: \"Hello romix!\"\n```\n\nSince defaults can be any expression, they can be used to enforce a\ncontract:\n\n```\nfunction addone(n = assert(type(n) == 'number') and n)\n   return n + 1\nend\n```\n\nHowever, this can be better achieved using _parameter guards_. Guards\nare checked against by using the `is` operator, and if they evaluate\nto `false`, an error is raised.\n\n```\nfunction addone(n is Number)\n   return n + 1\nend\n\naddone(40)          -- OK\naddone(\"cheese\")    -- bad argument #1 to 'addone' (Number expected got String)\n```\n\nLike in Lua, functions can be declared on tables. However, the `.` notation\ndefines a method with an implicit `self`, whereas the `::` notation does not.\nTherefore the `.` is the equivalent of Lua's `:`, and `::` is the equivalent\nof Lua's `.`. For example:\n\n```\no = { }\nfunction o.greet()\n   print \"Hi, I'm %{self}\"      -- implicit self parameter\nend\nfunction o::greet()\n   print self                   -- Error: self is undefined\nend\n```\n\nCalling functions attached to tables follows the same conventions,\nwith `.` passing the receiver, whereas `::` does not.\n\nLastly, although the Lua-style `...` notation may be used for\n\"vararg\" functions as the last parameter. Shine extends this by\nadding `...\u003cident\u003e` syntax. This has the effect of collecting the\nremaining arguments and packing them into an array:\n\n```\n-- the Lua way\nfunction luaesque(...)\n   for i=1, select('#', ...) do\n      a = select(i, ...)\n      print \"arg: %{i} is %{a}\"\n   end\n   return ...\nend\n\n-- the Shine way\nfunction shiny(...args)\n   for i, v in args do\n      print \"arg: %{i} is %{v}\"\n   end\n   return ...args   -- unpack\nend\n```\n\nOf course, the Lua way may often be preferred, especially for\nperformance sensitive code which passes `...` along to avoid\nallocating arrays at each invocation.\n\n### \u003ca name=\"generators\"\u003e\u003c/a\u003eGenerators\n\nGenerators are special functions which return a wrapped coroutine\nup invocation. Generators are declared as functions decorated with\na `*`. The position of the asterisk depends on whether the generator\nis declared using long or short syntax.\n\nThe long syntax takes the form:\n\n`function* '(' \u003cparam_list\u003e ')' \u003cchunk\u003e end`\n\nExample:\n\n```\nfunction* seq(x)\n   -- inside the coroutine\n   for i in 1..x do\n      yield i       -- i.e. coroutine::yield(i)\n   end\nend\ngen = seq(3)\n\nprint gen()         -- prints: 1\nprint gen()         -- prints: 2\nprint gen()         -- prints: 3\n```\n\nThe short syntax takes the form:\n\n`*'(' \u003cparam_list\u003e ')' =\u003e (\u003cnl\u003e \u003cchunk\u003e end) | \u003cexpr\u003e`\n\nExample:\n\n```\nseq = *(x) =\u003e\n   -- inside the coroutine\n   for i in 1..x do\n      yield i       -- i.e. coroutine::yield(i)\n   end\nend\ngen = seq(3)\n\nprint gen()         -- prints: 1\nprint gen()         -- prints: 2\nprint gen()         -- prints: 3\n```\n\nGenerators can also be defined as [class members](#methods)\n\n\n### \u003ca name=\"classes\"\u003e\u003c/a\u003eClasses\n\nClasses are Lua tables used as constructors and metatables for their\ninstances. A class is declared using the `class` keyword, which has\nthe following form.\n\n`class \u003cident\u003e (extends \u003cexpr\u003e)? \u003cchunk\u003e end`\n\nClasses support single inheritance with implementation sharing via module\nmixins. Much like Ruby.\n\nClass bodies are closures internally, so all the ordinary scoping rules for\nfunctions apply. Two parameters `self` and `super` are passed to the class\nbody, where `super` either references the base class, or the builtin `Object`\nif no base class is specified.\n\nThe behaviour expressed by a class is contained in three special\ntables attached to the class as properties: `__members__`, `__getters__`\nand `__setters__`.\n\nShine overloads the `__index` and `__newindex` metamethods to\ndelegate to these tables - as well as two fallbacks: `__getindex`,\nand `__setindex` - according to the following rules:\n\n* if the access is a read access (`__index` hook)\n  * if `__getters__` contains the key, then call `__getters__[key](obj)`\n  * otherwise if `__members__` defines the key, return `__members__[key]`\n  * otherwise if `class.__getindex` is defined, call `__getindex(obj, key)`\n  * otherwise return `nil`\n\n* if the access is a write access (`__newindex` hook)\n  * if `__setters__` contains the key, then call `__setters__[key](obj, val)`\n  * otherwise, if `class.__setindex` is defined, call `__setindex(obj, key, val)`\n  * otherwise call `rawset(obj, key, val)`\n\n#### \u003ca name=\"methods\"\u003e\u003c/a\u003eMethods\n\nMethods are shared by all instances, and attached to the class's\n`__members__` property, keyed on their name, who's value is an\nordinary function, with an implicit `self` parameter.\n\nMethods are introduced with an identifier followed by the parameters\nand the body:\n\n`\u003cident\u003e '( \u003cparam_list\u003e ')' \u003cchunk\u003e end`\n\nThe `function` keyword is omitted. This allows functions local to\nthe class body to be distinguised from instance methods. Here is\nthe canonical `Point` class in Shine, with comments to illustrate:\n\n```\nclass Point\n   -- constructor\n   self(x = 0, y = 0)\n      self.x = x    -- property 'x'\n      self.y = y    -- property 'y'\n   end\n\n   -- instance method\n   move(dx, dy)\n      self.x = delta(self.x, dx)\n      self.y = delta(self.y, dy)\n   end\n\n   -- class-scoped function\n   function delta(v, dv)\n      return v + dv\n   end\nend\n```\n\nAs a special case, generators may also be declared as methods, if\nthey are prefixed with a `*`:\n\n```\nclass Bomb\n   *ticker()\n      while true do\n         yield \"tick\"\n      end\n   end\nend\nb = Bomb()\ng = b.ticker()\nprint g()       -- prints: \"tick\"\n```\n\n#### \u003ca name=\"properties\"\u003e\u003c/a\u003eProperties\n\nProperties are typically not part of the class model, and can be\nsimply set inside the constructor, or externally as needed.\n\nFor cases where more control is needed, however, classes may also\ndefine /getters/ and /setters/, which are method declarations\nprefixed with `get` or `set` respectively. These special methods\nbehave like properties in that they can be read from or assigned\nto as with ordinary properties by users of the objects, but they\nare invoked by the runtime as methods on the object. The following\nillustrates:\n\n```\nclass Point\n   set x(x)\n      self._x = x\n   end\n   get x()\n      return self._x\n   end\n\n   set y(v)\n      self._y = y\n   end\n   get y()\n      return self._y\n   end\nend\n\np = Point()\np.x = 42            -- means: Point::__setters__::x(p, 42)\nprint p.x           -- means: print(Point::__getters__::y(p, 42))\n```\n\nThis allows for lazy construction of default property values,\nread-only or write-only properties,  enforcing type constraints,\nor coercing to and from `cdata` values.\n\n#### \u003ca name\"constructors\"\u003e\u003c/a\u003eConstructors\n\nThe constructor of a class is a an ordinary method called `self`.\nClasses overload the `__apply` hook, which is called from the `Class`\nmetatype's `__call` metamethod, and so are callable directly.  This\nis used to create instances of the class. Arguments are passed\nthrough to the constructor.\n\nHowever, this is largely a convention. An instance can also be created\nby using Lua's `setmetatable`:\n\n```\np = setmetatable({ x = 0, y = 0}, Point)\n```\n\nA more concise form is supported by Shine using `as`:\n\n```\np = { x = 0, y = 0 } as Point\n```\n\nThe default `__apply` implementation calls `self` on the class, passing\nin a table with the metatable already set to that of the receiving class.\nIn some cases - especially when creating metatypes for FFI bindings - this\nis undesirable, since FFI bindings construct `cdata` types and not insances\nbased on tables.\n\nIn this case a custom `__apply` method should be used. The following\nillustates:\n\n```\nimport ffi from \"sys.ffi\"\nclass Buffer\n   local ctype = ffi::typeof('struct { char* ptr; size_t len; };')\n   function self.__apply(str)\n      return ctype(str, #str)\n   end\n   -- make this class the metatype\n   ffi::metatype(ctype, self)\nend\n\nbuf = Buffer(\"Hello World!\")\n```\n\n#### \u003ca name=\"inheritance\"\u003e\u003c/a\u003eInheritance\n\nInheritance uses the `extends \u003cexpr\u003e` clause. The following illustrates:\n\n```\nclass Point3D extends Point\n   self(x, y, z = 0)\n      super(x, y)           -- super refers to Point::__members__\n      self.z = z\n   end\n   move(dx, dy, dz)\n      super.move(dx, dy)    -- compiles to super::move(self, dx, dy)\n      self.z += dz\n   end\nend\n```\n\nThe argument to `extends` can be any valid expression, so even literal\ntables, and call expressions are allowed, which can be powerful tools for\nconstructing parameterized class hierarchies at runtime.\n\n```\nfunction DBRecord(table)\n   dbh = DB.connection()\n   class base\n      fetch()\n         dbh.with(table) (handle) =\u003e\n            -- do something\n         end\n      end\n   end\n   return base\nend\nclass DBUser extends DBRecord(\"user_table\")\n   -- whatever\nend\n```\n\nThe above also shows that all declarations - including class\ndeclarations - can be nested.\n\n### \u003ca name=\"modules\"\u003e\u003c/a\u003eModules\n\nShine's modules are not to be confused with Lua's modules.\n\nIn Shine modules are almost identical to classes in every way,\nexcept that they are without a constructor and don't inherit. Modules\nare often used as singletons, or namespaces to contain related\npieces of code. Their real power, however, comes from the fact that\nthey can be composed into classes and even other modules using\n`include \u003cexpr_list\u003e`.\n\nThis example shows similarities with classes, and how modules may be\nused as namespaces:\n\n```\nmodule armory\n   local ANSWER = 42\n\n   -- they can have getters/setters\n   get answer()\n      return ANSWER\n   end\n   set answer(v)\n      ANSWER = v\n   end\n\n   -- they can contain other classes\n   class PlasmaRifle\n      trigger()\n         print \"pew pew\"\n      end\n   end\n\n   class BootKnife\n      unsheath()\n         print \"snick\"\n      end\n   end\nend\n\ngun = armory::PlasmaRifle()\n\n```\n\nThe following shows composing a module into a class using the `include`\nstatement:\n\n```\nmodule Explosive\n   ignite()\n      throw \"BOOM!\"\n   end\nend\n\nclass Grenade\n   include Explosive\nend\n\ng = Grenade()\ng.ignite() -- crashes your program\n```\n\nModules are also callable, which lets you parametrize them during mixin:\n\n```\nmodule Explosive\n   message = ...\n   ignite()\n      throw message\n   end\nend\n\nclass Grenade\n   include Explosive \"BOOM!\"\nend\n\ng = Grenade()\ng.ignite() -- also crashes your program\n\n```\n\n### \u003ca name=\"grammars\"\u003e\u003c/a\u003eGrammars\n\nShine grammars are a special kind of [module](#modules) which can\ncontain [patterns](#patterns) as well as module body declarations\nsuch as methods, properties and statements. Grammar bodies have\na lexical scope, just as with classes and modules.\n\nGrammars are composable via `include` statements.\n\nGrammars override the `__call` metamethod for matching.\n\n\n```\ngrammar Macro\n   function fail(err)\n      return (s, i) =\u003e\n         local msg = (#s \u003c i + 20) and s.sub(i)\n         msg = \"error %{err} near '%s'\".format(msg)\n         error(msg, 2)\n      end\n   end\n\n   function expect(tok)\n      return / \u003c{tok}\u003e | \u003c{fail(\"'%{tok}' expected\")}\u003e /\n   end\n\n   text  \u003c- {~ \u003citem\u003e* ~}\n   item  \u003c- \u003cmacro\u003e | [^()] | '(' \u003citem\u003e* \u003c{expect(')')}\u003e\n   arg   \u003c- ' '* {~ (!',' \u003citem\u003e)* ~}\n   args  \u003c- '(' \u003carg\u003e (',' \u003carg\u003e)* ')'\n   macro \u003c- (\n        ('apply' \u003cargs\u003e) -\u003e '%1(%2)'\n      | ('add'   \u003cargs\u003e) -\u003e '%1 + %2'\n      | ('mul'   \u003cargs\u003e) -\u003e '%1 * %2'\n   )\nend\n\nlocal s = \"add(mul(a,b),apply(f,x))\"\nprint(Macro(s))\n```\n\n### \u003ca name=\"decorators\"\u003e\u003c/a\u003eDecorators\n\nDecorators are annotations associated with class, module, grammar,\nfunction or local declarations.\n\n```\n@classdeco(whatever)\nclass Foo\n\n   @methdeco({ doc = \"does something\" }, 42)\n   munge(...)\n      ---\n   end\n\nend\n\n@funcdeco\nfunction bar()\n   --\nend\n\n@localdeco\nlocal a, b = 40, 2\n```\n\nThe semantics are simple. A decorator is a function or other callable\nwhich is passed the decorated object as a first argument, followed\nby any remaining arguments declared in the annotation. The exception\nbeing local variable declarations, in which case the decorator\nfunction is passed the right-hand side of the assignment as a list.\n\nA decorator is expected to return a value to be used as the value\nof the declaration. The transormation inserted by the compiler has\nthe following pattern:\n\n```\n@deco1(42)\n@deco2({ answer = 0 })\nfunction greet()\n   print \"Hello World!\"\nend\n\n@deco3(\"cheese\")\nlocal a, b = 1, 2\n```\n\nbecomes:\n\n```\nfunction greet()\n   print \"Hello World!\"\nend\ngreet = deco1(deco2(greet, { answer = 0 }), 42)\n\nlocal a, b = deco3(1, 2, \"cheese\")\n```\n\nThat's it. Simple.\n\n### \u003ca name=\"macros\"\u003e\u003c/a\u003eMacros\n\nShine currently has experimental support for procedural macros.\nMacros are functions run at compile time, which receive the compiler\ncontext and abstract syntax tree (AST) nodes as arguments.\n\nA macro is expected to transform the AST nodes into opcode tree\nfragments exactly as is done by the Shine\n[translator](./src/lang/translator.lua). This is a powerful\nfeature, but also allows one to produce invalid code, so\nnot for the faint of heart.\n\nThe following macro does a compile-time string concatenation and\ninserts `print \"Hello World!\"`.\n\n```\n-- file: hello.shn\nmacro hello!(ctx, expr)\n   util = require(\"shine.lang.util\")\n   mesg = util::unquote(ctx.get(expr))\n   return ctx.op{'!call', 'print', ctx.op\"Hello %{mesg}\"}\nend\n\nhello!(\"World!\")\n```\n\nRunning the above with `shinec -o` to print the opcode tree, yields:\n\n```\n$ shinec -o hello.shn \n;TvmJIT opcode tree:\n\n(!line \"@hello.shn\" 1)(!define __magic__ (!index (!call1 require \"core\") \"__magic__\"))(!call (!index _G \"module\") !vararg (!index __magic__ \"environ\"))\n(!line 2) \n(!line 8) (!call print \"Hello World!\")\n```\n\nThe first line is the standard Shine prelude which loads the runtime\nenvironment. The interesting part comes next. We see the constant\nstring passed to `print` is pre-computed as we expected.\n\nNote that the macro itself is a compile-time entity and is not\npresent in the output.\n\nOf course, defining macros only within a given compilation unit limits\ntheir usefulness, so macro definitions have an alternative syntax:\n\n```\nmacro \u003cname\u003e '=' \u003cident\u003e\n```\n\nWhere `\u003cident\u003e` is either a locally declared function, or an imported\nsymbol. The following illustrates:\n\n```\n-- file: macros.shn\n\nfunction hello(ctx, expr)\n   util = require(\"shine.lang.util\")\n   mesg = util::unquote(ctx.get(expr))\n   return ctx.op{'!call', 'print', ctx.op\"Hello %{mesg}\"}\nend\n\nexport hello\n```\n\n```\n-- file: hello.shn\nimport hello from \"macros\"\n\nmacro hello! = hello\n\nhello!(\"World!\")\n```\n\nRunning `hello.shn` with `shinec -o` now shows:\n\n```\n$ shinec -o hello.shn \n;TvmJIT opcode tree:\n\n(!line \"@hello.shn\" 1)(!define __magic__ (!index (!call1 require \"core\") \"__magic__\"))(!call (!index _G \"module\") !vararg (!index __magic__ \"environ\"))\n(!line 1) (!define (hello) ((!call import \"macros\" \"hello\")))\n(!line 3) \n(!line 5) (!call print \"Hello World!\")\n```\n\nThis comes with a couple of caveats. First, the compiler needs to\nload and evaluate the module at compile time, so if the module's\ncode has side effects (such as sending an email), then this will\nhappen when the code is *compiled*. This is the only case (along with\n`import macro ...` statement) where the compiler does any sort of early\nlinking or binding.\n\nSecondly, if the function to be used as the macro implementation is\ndeclared in the same compilation unit, then it must be declared in\nits canonical form: i.e. `function \u003cname\u003e \u003cparams\u003e \u003cbody\u003e end`. It\ncannot be a property or expression or any other computed form.\n\nLastly, macro functions are run early, so generally need to import\nwhat they need locally.\n\nSome tips:\n\n* Macros could be imported with shorthand syntax:\n```\n-- file: hello.shn\nimport macro hello from \"macros\"\n\nhello(\"World!\")\n```\n* To implement macros, one needs to know the structure of the\n  AST, so `shinec -p` will print it out.\n* The \"shine.lang.util\" module has a `dump` function which pretty\n  prints AST nodes.\n* The best reference is the Shine [translator](./src/lang/translator.lua) itself.\n\n## \u003ca name=\"standard-libaries\"\u003e\u003c/a\u003eStandard Libraries\n\nSee [./lib](./lib)\n\n### \u003ca name=\"concurrency\"\u003e\u003c/a\u003eConcurrency\n\nThe standard libraries have a strong focus on concurrency using\nscheduled coroutines, wrapped as the class `Fiber`, which cooperate\nwith (but not scheduled by) an event loop.\n\nThis gives a clean linear flow to writing concurrent applications\nwithout the need for inverting everything using callbacks.\n\nHere is the canonical TCP echo server example:\n\n```\nimport async, yield from \"async\"\nimport TCPServer from \"async.io\"\n\nserver = TCPServer()\nserver.reuseaddr(true)\nserver.bind(\"localhost\", 1976)\nserver.listen(128)\n\nasync =\u003e\n   while true do\n      client = server.accept()\n      async =\u003e\n         while true do\n            got = client.read()\n            if got == nil then\n               client.close()\n               break\n            end\n            client.write(\"you said %{got}\")\n         end\n      end\n   end\nend\n\nyield\n```\n\n#### \u003ca name=\"fibers\"\u003e\u003c/a\u003eFibers\n\nSee [./lib/async/fiber.shn](./lib/async/fiber.shn),\n[./lib/async/util.shn](./lib/async/util.shn)\n\n#### \u003ca name=\"threads\"\u003e\u003c/a\u003eThreads\n\nSee [./lib/sys/thread.shn](./lib/sys/thread.shn) and the\n[czmq bindings](https://github.com/richardhundt/shine-zsys).\n\n### \u003ca name=\"serialization\"\u003e\u003c/a\u003eSerialization\n\nSee [./lib/codec/serializer.shn](./lib/codec/serializer.shn)\n\nBig TODO here.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichardhundt%2Fshine","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frichardhundt%2Fshine","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frichardhundt%2Fshine/lists"}