## Overview

> **Q**: Good to see you Mr Bond, things have been awfully dull around
> here...Now you're on this, I hope we're going to have some gratuitous
> sex and violence!  
> **James Bond**: I certainly hope so too.

007 is a small language. It has been designed with the purpose of
exploring ASTs, macros, the compiler-runtime barrier, and program
structure introspection.

In terms of language features, it's perhaps easiest to think of 007 as
the secret love child of Perl 6 and Python.

| feature                  | Perl 6   | 007   | Python   |
| ------------------------ | -------- | ----- | -------- |
| braces                   | yes      | yes   | no       |
| user-defined operators   | yes      | yes   | no       |
| variable declarations    | yes      | yes   | no       |
| macros                   | yes      | yes   | no       |
| implicit typecasts       | yes      | no    | no       |
| sigils                   | yes      | no    | no       |
| multis                   | yes      | no    | no       |
| implicit returns         | yes      | no    | no       |

## Values

A small number of values in 007 can be expressed using literal syntax.

    123                 Q::Literal::Int
    "Bond."             Q::Literal::Str
    None                Q::Literal::None
    [0, 0, 7]           Q::Term::Array
    { name: "Bond" }    Q::Term::Object

Only double quotes are allowed. Strings don't have any form of
interpolation.

The `None` value is a singleton. It's the value of unassigned variables
and subroutines that don't `return` anything.

## Expressions

> **James Bond**: A gun and a radio. It's not exactly Christmas, is it?  
> **Q**: Were you expecting an exploding pen? We don't really go in for
> that anymore.

You can add integers together, and negate them.

    40 + 2              Q::Infix::Addition
    -42                 Q::Prefix::Minus

Strings can be concatenated.

    "Bo" ~ "nd."        Q::Infix::Concat

Arrays can be indexed. (Strings can't, but there's a builtin for that.)

    ar[3]               Q::Postfix::Index

There's an assignment operator, and a comparison operator. These work on
all types.

    name = "Bond"       Q::Infix::Assignment
    42 == 40 + 2        Q::Infix::Eq

There is no boolean type; comparison yields `1` and `0`. Comparison is
strict, in the sense that `7` and `"7"` are not considered equal under
`==`, and an array is never equal to an int, not even the length of the
array.

You can assign to individual variables, like `name`, or long strings
of postfix operators, like `employee[n - 1].boss.name`. There's no
autovivification like in Perl &mdash; in the previous example,
`employee[n - 1].boss` needs to already exist (though its `.name`
property doesn't need to exist).

Operands don't need to be simple values. Arbitrarily large expressions
can be built. Parentheses can be used to explicitly show evaluation
order.

    10 + -(2 + int("3" ~ "4"))

## Variables

In order to be able to read and write a variable, you must first declare
it.

    my name;            Q::Statement::My

As part of the declaration, you can also do an assignment.

    my name = "Bond";

Variables are only visible for the rest of the scope they are declared
in. All scopes are delimited by braces, except for the scope delimiting
the whole program.

    {
        my drink = "Dry Martini";
        say(drink);     # works
    }
    say(drink);         # fails, no longer visible

It's fine for a variable in an inner scope to have the same name as one
in an outer scope. The inner variable will then "shadow" the outer until
it's no longer visible.

    my x = 1;
    {
        my x = 2;
        say(x);         # 2
    }
    say(x);             # 1

## Statements

> **Q**: It is to be handled with special care!  
> **Bond**: Everything you give me...  
> **Q**: ...is treated with equal contempt. Yes, I know.

We've seen two types of statement already: variable declarations, and
expression statements.

    my name = "Bond";   Q::Statement::My
    say(2 + 2);         Q::Statement::Expr

Expression statements are generally used for their side effects, so they
tend to either call some routine or assign to some variable. However,
this is not a requirement, and an expression statement can contain any
valid expression.

Besides these simple statements, there are also a few compound
statements for conditionals and loops.

    if 2 + 2 == 4 {}    Q::Statement::If
    for xs -> x {}      Q::Statement::For
    while agent {}      Q::Statement::While

There is also an immediate block statement. Immediate blocks run
unconditionally, as if they were an `if 1 {}` statement.

    { say("hi") }       Q::Statement::Block

## Subroutines

Subroutines are similar to blocks, but they are declared with a name and
a (non-optional) parameter list.

    sub f(x) {}         Q::Statement::Sub

When calling a subroutine, the number of arguments must equal the number
of parameters.

The parentheses in the call are mandatory. There is no `g "Mr. Bond";`
listop form.

Subroutines can return values.

    return 42;          Q::Statement::Return

## `BEGIN` and constants

`BEGIN` blocks are blocks of code that run as soon as the parser has
parsed the ending brace (`}`) of the block.

    BEGIN {}            Q::Statement::BEGIN

There is no statement form of `BEGIN`: you must put in the braces.

There's also a `constant` declaration statement:

    constant pi = 3;    Q::Statement::Constant

The right-hand side of the `constant` declaration is evaluated at parse
time, making it functionally similar to using a BEGIN block to do the
assignment:

    my pi;
    BEGIN {
        pi = 3;
    }

Constants cannot be assigned to after their declaration. Because of
this, the assignment in the `constant` declaration is mandatory.

## Setting

There's a scope outside the program scope, containing a utility
subroutines. These should be fairly self-explanatory.

    say(any)
    type(any)
    str(any)
    int(any)
    min(a, b)
    max(a, b)

## Objects

Object terms are delimited by braces, and contain property declarations
separated by commas:

    { name: "Bond", agency: "MI6" }

Property keys can be quoted, for example when they aren't simple identifiers:

    { "no, Mr Bond": "I expect you to die" }

There's also syntactic sugar for defining properties with function values,
making these two forms more or less equivalent:

    { quip() { say("I'd say one of their aircraft is missing") } }

    sub quip() { say("I'd say one of their aircraft is missing") }
    { quip: quip }

## Methods on built-in types

The following built-in types have methods associated with them:

### `Int`

    .abs()
    .chr()

### `Str`

    .ord()
    .chars()
    .uc()
    .lc()
    .trim()
    .split(sep)
    .index(substr)
    .charat(pos)
    .substr(pos, chars)
    .prefix(pos)
    .suffix(pos)

### `Array`

    .elems()
    .reverse()
    .sort()
    .join(sep)
    .map(fn)
    .filter(fn)

## Q objects

All the different Q types can be created by specifying the type before an
object term:

    my q = Q::Statement::My {
        identifier: Q::Identifier { name: "name" },
        expr: Q::Literal::Str { value: "Bond" }
    };

## Macros

> **Q**: Now, look...  
> **Bond**: So where is this cutting edge stuff?  
> **Q**: I'm trying to get to it!

Macros are a form of routine, just like subs.

    macro m(q) {}       Q::Statement::Macro

When a call to a macro is seen in the source code, the compiler will
call the macro, and then install whatever code the macro said to return.

    macro greet() {
        return Q::Postfix::Call {
            expr: Q::Identifier { name: "say" },
            argumentlist: Q::ArgumentList {
                [Q::Literal::Str { value: "Mr Bond!" }]
            }
        };
    }

    greet();    # prints "Mr Bond!" when run

## Quasis

> **Q**: Right. Now pay attention, 007. I want you to take great care of
> this equipment. There are one or two rather special accessories...  
> **James Bond**: Q, have I ever let you down?  
> **Q**: Frequently.

It's sometimes convenient to express code as Qtree constructors, like
above, and sometimes convenient to express it as code. Quasis are for
the latter case.

    macro greet() {
        return quasi {
            say("Mr Bond!");
        }
    }

    greet();

Quasis can contain *unquotes*, where we momentarily jump back from
code to Qtrees. Mixing code and Qtrees like that is the main point of
quasis. For instance, instead of specifying the string directly as
above, we can construct the Q node for it, and inject it:

    constant greeting_ast = Q::Literal::Str { value: "Mr Bond!" };

    macro greet() {
        return quasi {
            say({{{greeting_ast}}});
        }
    }

    greet();

Note the need for `constant` in the mainline, because the macro
`greet` runs very early. If we moved `greeting_ast` into the macro
body, we could use `my`.
