Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement simple syntax macros #80

Open
masak opened this issue Nov 12, 2015 · 6 comments
Open

Implement simple syntax macros #80

masak opened this issue Nov 12, 2015 · 6 comments

Comments

@masak
Copy link
Owner

masak commented Nov 12, 2015

Let's try to make a dent in syntax macros as envisioned here. By implementing this bit, 007 would have something macro-wise that Perl 6 definitely doesn't have yet!

I was struck today by how most of the common control statement forms — if, for, while — are all of the same form: <sym> <EXPR> <pblock>. So let's make that the default form (for now), until we figure out what we want is parsed to be.

Mandatory example:

macro statement:<unless>(expr, pblock) {
    return quasi @ Q::Statement {
        if !{{{expr}}} {{{pblock @ Q::Block}}}
    }
}

If we can make that work, then that's a pretty sweet start.

Immediate remarks, though:

  • It'd be far more common to want to inflict a new statement form on a "module caller", so we should think about how to combine this with the ideas of Implement module imports #53.
  • I am not sure the @ Q::Statement qualifier is absolutely necessary there. But I put it in because I am not sure.
@raiph
Copy link

raiph commented Nov 19, 2015

"In general, each node (tuple) above follows the following format:"

{ tuple | atom, list, list | atom }
  • The first element of the tuple is an atom or another tuple in the same representation;
  • The second element of the tuple is an list of metadata, it may hold information like the node line number;
  • The third element of the tuple is either a list of arguments for the function call or an atom. When an atom, it means the tuple represents a variable.

Besides the node defined above, there are also five Elixir literals that when quoted return themselves (and not a tuple). They are:

:sum         #=> Atoms
1.0          #=> Numbers
[1,2]        #=> Lists
"binaries"   #=> Strings
{key, value} #=> Tuples with two elements

With those basic structures in mind, we are ready to define our own macro.

@vendethiel
Copy link
Collaborator

Though Elixir has several constructs that are not definable with a macro. (like if)

@masak
Copy link
Owner Author

masak commented Nov 21, 2015

Yes, the "three" here seems mostly coincidental. 007's three in this case are

(keyword, expression, pblock)

whereas Elixir's three are something more like

(function name, imports/context, arguments)

Elixir's message seems to be "this is the internal representation of expression nodes (which is essential to know about if you get into the macro game", whereas this issue is aiming for "we recognize that people tend to want to implement special forms (such as unless) in a very constrained way, so we're going to provide that way as the default, until we figure out how to do it in general".

@vendethiel
Copy link
Collaborator

Well, the thing is that elixir will parse the dos very naturally – our TTIAR would be much harder.

@masak
Copy link
Owner Author

masak commented Aug 18, 2016

I was struck today by how most of the common control statement forms — if, for, while — are all of the same form: <sym> <EXPR> <pblock>. So let's make that the default form (for now), until we figure out what we want is parsed to be.

I no longer believe this to be a good idea. It'd end up being a "wrong default" that we would then have to painstakingly major-version away. Instead, I've started believing that is parsed is within reach, without too much excruciating implementation pain along the way. To think, our little 007 baby is growing up.

So, blocking this one on #177 for now.

@masak
Copy link
Owner Author

masak commented Jan 18, 2021

I no longer believe this to be a good idea.

Well, in a sort of graceful multi-year oscillation, I no longer believe this to be a bad idea. 😄

But maybe the syntax should be modified slightly:

macro keyword:<unless>(expr, pblock) {
    return quasi @ Q::Statement {
        if !{{{expr}}} {
            {{{pblock}}}();
        }
    }
}

I changed two things from the OP, by the way:

  • The grammatical category is keyword. (And we can make sure to document this one as all forms of conjectural/automatically deprecated/playground if we want; the main thing is to get it to play with soon.)
  • I changed the way we consume the pblock to the much-simpler method of invoking its runtime value, instead of exotically unquoting it (something that we still don't have, and that's blocking on a similarly exotic parser). Both methods ought to work, in the fullness of time, but this one has the advantage of working sooner.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants