docs/optimizer.md

Summary

Maintainability
Test Coverage
# Optimizer

uGO has a builtin simple optimizer to improve bytecode execution performance.
Optimizer is loosely coupled in compiler which enables to disable optimizer
before compilation. If your script has many constants and arithmetic operations,
optimizer may save some cpu cycles.

As of now optimizer works on Abstract Syntax Tree (AST) like compiler but it
replaces expressions, if applicable, with constant literals. Optimizer uses two
techniques to modify AST, constant folding and dynamically evaluating
expressions, which has no side effect. Optimizer greedily tries to modify AST
until the given limit is reached. Constant propagation will be implemented in
the future which may improve execution performance more than current
implementation.

Following example shows how the optimizer works:

If optimizer is not enabled, for a basic binary operation, at least 3
instructions, 2 constants are emitted by compiler in bytecode as can be seen in
the comments (ignore SETLOCAL and RETURN opcodes for the example).

``` go
a := 1 << 4
```

```console
Bytecode
Modules:0
Constants:
   0: 1|int
   1: 4|int
Params:1 Variadic:false Locals:1
Instructions:
0000 CONSTANT        0
0003 CONSTANT        1
0006 BINARYOP        20
0008 SETLOCAL        0
0010 RETURN          0
SourceMap:map[0:6 3:11 6:6 8:1 10:0]
```

If optimizer is enabled, 1 instruction is emitted by the compiler as below. We
saved 2 instructions, 1 constant and a few source map entries.

``` go
a := 1 << 4
```

```console
Bytecode
Modules:0
Constants:
   0: 16|int
Params:1 Variadic:false Locals:1
Instructions:
0000 CONSTANT        0
0003 SETLOCAL        0
0005 RETURN          0
SourceMap:map[0:6 3:1 5:0]
```

Of course user can directly write constant value instead of writing `1 << 4` but
for readibility purposes and cases where verbosity matters, it may be useful.

Another advantage of using optimizer is to get some builtin function results at
compile time.

```go
a := uint("0b0101")   // a == 5
```

As be seen in generated bytecode below, builtin function is not called.

```console
Bytecode
Modules:0
Constants:
   0: 0x5|uint
Params:1 Variadic:false Locals:1
Instructions:
0000 CONSTANT        0
0003 SETLOCAL        0
0005 RETURN          0
SourceMap:map[0:6 3:1 5:0]
```

> uGO's terminal application enables you to see the generated bytecode for the
> last executed code. To see the bytecode, type `.bytecode` command in terminal.

To see unoptimized bytecode start application like this

```sh
./ugo -no-optimizer
```

uGO's terminal application provides trace output for parser, optimizer and
compiler that can help you to learn, test or debug. To enable traces see usage
of the application like below.

```console
./ugo -h

Usage of ugo:
  -no-optimizer
        disable optimization
  -trace string
        comma separated units: -trace parser,optimizer,compiler
```

The options to configure the optimizer are passed by compiler options. Optimizer
is enabled by default in default compiler options.

Please don't expect much from the optimizer, but it is going to be smarter!