{"action":"created","issue":{"url":"https://api.github.com/repos/masak/007/issues/30","repository_url":"https://api.github.com/repos/masak/007","labels_url":"https://api.github.com/repos/masak/007/issues/30/labels{/name}","comments_url":"https://api.github.com/repos/masak/007/issues/30/comments","events_url":"https://api.github.com/repos/masak/007/issues/30/events","html_url":"https://github.com/masak/007/issues/30","id":110789623,"number":30,"title":"Implement quasi unquotes","user":{"login":"masak","id":20627,"avatar_url":"https://avatars.githubusercontent.com/u/20627?v=3","gravatar_id":"","url":"https://api.github.com/users/masak","html_url":"https://github.com/masak","followers_url":"https://api.github.com/users/masak/followers","following_url":"https://api.github.com/users/masak/following{/other_user}","gists_url":"https://api.github.com/users/masak/gists{/gist_id}","starred_url":"https://api.github.com/users/masak/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/masak/subscriptions","organizations_url":"https://api.github.com/users/masak/orgs","repos_url":"https://api.github.com/users/masak/repos","events_url":"https://api.github.com/users/masak/events{/privacy}","received_events_url":"https://api.github.com/users/masak/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":31,"created_at":"2015-10-10T11:45:24Z","updated_at":"2016-08-12T21:22:48Z","closed_at":null,"body":"[Hacker News wants unquotes](https://news.ycombinator.com/item?id=10326221). We happily oblige.\r\n\r\n## Unquotes in expressions\r\n\r\nWhenever the parser is ready to parse a term, it should also expect an unquote.\r\n\r\n    quasi { say(\"Mr Bond!\") }\r\n    quasi { say({{{greeting_ast}}}) }\r\n\r\nTechnically, I don't see why we shouldn't expect the same for operators. But we get into the interesting issue of what syntactic category it is.\r\n\r\nScrew it, I'm tired of theorizing. Let's just steal the colon for this.\r\n\r\n    quasi { 2 + 2 }\r\n    quasi { 2 {{{infix: my_op}}} 2 }\r\n\r\n    quasi { -14 }\r\n    quasi { {{{prefix: my_op}}}14 }\r\n\r\n    quasi { array_potter[5] }\r\n    quasi { array_potter{{{postfix: my_op}}} }\r\n\r\nBackporting this solution to terms, you could mark up a quasi as `term` if you want, but it's the default so you don't have to:\r\n\r\n    quasi { say(\"Mr Bond!\") }\r\n    quasi { say({{{term: greeting_ast}}}) }\r\n\r\nAt the time of evaluating the quasi (usually macro application time), we'll have the type of the unquoted Qtree. The runtime dies if you try to stick a square Qtree into a round unquote.\r\n\r\nBut the parser can sometimes reject things early on, too. For example, this shouldn't even parse:\r\n\r\n    quasi { sub {{{prefix: op}}}(n) { } }\r\n\r\n(That slot doesn't hold an operator, it holds an identifier.)\r\n\r\n## Unquotes for identifiers\r\n\r\n007 currently has 5 major places in the grammar where it expects an identifier:\r\n\r\n* *Usages*\r\n    * Terms in expressions (but that's handled by the previous section)\r\n    * `is <ident>` traits\r\n* *Declarations*\r\n    * `my` and `constant`\r\n    * `sub` and `macro`\r\n    * parameters in parameter lists (in subs and pointy blocks)\r\n\r\nThe traits one is kind of uninteresting right now, because we have four trait types. Someone who really wanted to play around with dynamic traits could write a case expression over those four. So let's skip traits &mdash; might reconsider this if we user-expose the traits more.\r\n\r\nThe three declaration cases are the really interesting ones. Notice that each of those has a *side effect*: introducing whatever name you give it into the surrounding lexical scope. (Handling that correctly is likely part of the #5 thing with Qtree strengthening.)\r\n\r\nI would be fine with the `{{{identifier: id}}}` unquote accepting both `Q::Identifier` nodes and `Str` values. `Q::Identifier` is basically the only node type where I think this automatic coercion would make sense.\r\n\r\n## Unquotes in other places\r\n\r\nThese are the remaining things I can think of where an unquote would make sense:\r\n\r\n* Sequence of statements (`Q::Statements`)\r\n* Parameter list (`Q::Parameters`)\r\n* Argument list\r\n* Standalone block (`Q::Block`)\r\n* Trait (`Q::Trait`) &mdash; *note: we should probably have a `Q::Traits` container, just like we do for statements and parameters*\r\n* Individual statement (`Q::Statement`) &mdash; *not sure what this one'll give us over sequence of statements, but it's possible it might be useful*\r\n* Lambda &mdash; *interesting; this one is in the grammar but not reified among the `Q` nodes*\r\n* \"Expr block\" &mdash; *ditto*\r\n* Unquote (`Q::Unquote`) &mdash; [*mind explosion*](https://www.youtube.com/watch?v=9CS7j5I6aOc) &mdash; note that this is only allowed inside a `Q::Quasi`"},"comment":{"url":"https://api.github.com/repos/masak/007/issues/comments/239563102","html_url":"https://github.com/masak/007/issues/30#issuecomment-239563102","issue_url":"https://api.github.com/repos/masak/007/issues/30","id":239563102,"user":{"login":"vendethiel","id":199499,"avatar_url":"https://avatars.githubusercontent.com/u/199499?v=3","gravatar_id":"","url":"https://api.github.com/users/vendethiel","html_url":"https://github.com/vendethiel","followers_url":"https://api.github.com/users/vendethiel/followers","following_url":"https://api.github.com/users/vendethiel/following{/other_user}","gists_url":"https://api.github.com/users/vendethiel/gists{/gist_id}","starred_url":"https://api.github.com/users/vendethiel/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vendethiel/subscriptions","organizations_url":"https://api.github.com/users/vendethiel/orgs","repos_url":"https://api.github.com/users/vendethiel/repos","events_url":"https://api.github.com/users/vendethiel/events{/privacy}","received_events_url":"https://api.github.com/users/vendethiel/received_events","type":"User","site_admin":false},"created_at":"2016-08-12T21:22:47Z","updated_at":"2016-08-12T21:22:47Z","body":"Er, there's actually a way around this, but this one is a case where the cure is poisonous... `quasi` could delay parsing and consider `{}` always match..."}}
{"actor":{"display_login":"vendethiel"}}