# Syntactic sugar

We will define some additional syntax to facilitate entry of some common expressions. Recall that we already allow the user to enter

```(A B C)
```
```(A . (B . (C . NIL)))
```

## Quoting

In order to include a literal symbol or list in an expression, we need to use the `QUOTE` operator. As a shortcut, we will define

```'EXPR
```
to be equivalent to
```(QUOTE EXPR)
```

So for example the following forms are equivalent:
Abbreviation Canonical form Evaluates to
`'FOO` `(QUOTE FOO)` `FOO`
`'(+ 1 2)` `(QUOTE (+ 1 2))` `(+ 1 2)`
`'(A . B)` `(QUOTE (A . B))` `(A . B)`

The lexer needs to know that the quote mark is a prefix (i.e., it can appear immediately before another token but is not necessarily a delimeter).

```int lex(const char *str, const char **start, const char **end)
{
const char *ws = " \t\n";
const char *delim = "() \t\n";
const char *prefix = "()\'";
.
.
.
}
```

Also `read_expr` must convert it to the correct list expresssion.

```int read_expr(const char *input, const char **end, Atom *result)
{
const char *token;
Error err;

err = lex(input, &token, end);
if (err)
return err;

if (token[0] == '(') {
} else if (token[0] == ')') {
return Error_Syntax;
} else if (token[0] == '\'') {
*result = cons(make_sym("QUOTE"), cons(nil, nil));
} else {
return parse_simple(token, *end, result);
}
}
```

#### Testing

```> (define x '(a b c))
X
> x
(A B C)
> 'x
X
> (define foo 'bar)
FOO
> foo
BAR
> ''()
(QUOTE NIL)
```

## Function definitions

It is cumbersome to have to type a lambda expression every time we wish to define a function, so we will modify the `DEFINE` operator to avoid this.

```(DEFINE (name args...) body...)
```
is equivalent to
```(DEFINE name (LAMBDA (args...) body...))
```

Here's how:

```int eval_expr(Atom expr, Atom env, Atom *result)
{
.
.
.
if (op.type == AtomType_Symbol) {
if (strcmp(op.value.symbol, "QUOTE") == 0) {
.
.
.
} else if (strcmp(op.value.symbol, "DEFINE") == 0) {
Atom sym, val;

if (nilp(args) || nilp(cdr(args)))
return Error_Args;

sym = car(args);
if (sym.type == AtomType_Pair) {
err = make_closure(env, cdr(sym), cdr(args), &val);
sym = car(sym);
if (sym.type != AtomType_Symbol)
return Error_Type;
} else if (sym.type == AtomType_Symbol) {
if (!nilp(cdr(cdr(args))))
return Error_Args;
err = eval_expr(car(cdr(args)), env, &val);
} else {
return Error_Type;
}

if (err)
return err;

*result = sym;
return env_set(env, sym, val);
} else if (strcmp(op.value.symbol, "LAMBDA") == 0) {
.
.
.
}
}
.
.
.
}
```

#### Testing

```> (define (square x) (* x x))
SQUARE
> (square 3)
9
```

Sweet!