Adds:
- UnaryOperator: AST node for unary operators -, ++, --, and so forth
- UnaryOperatorOptimizer: optimizes a unary operator with its operand
- now integer and float negation, and integer inversion
- later x[y]++ to a single instruction
Also:
- automatically include basic.em, which includes some parameter defaults like -1.
This allows the compiler to generate output for a hello, world script with the exact same .ecl output as the legacy compiler.
Adds support for var statements at the global level.
Adds:
- analyzer/Variables: keeps track of the variables in scope (either local or global).
- ast/Identifier: AST node for an identifier.
- The optimizer will replace constant identifiers with their constant value (in a later commit).
- The semantic analyzer will set the variable field for local or global variable identifiers.
- ast/VarStatement: AST node for a var statement.
- A single var statement will generate one VarStatement per variable declared.
- model/Variable: Describes a variable, including its index within its scope.
Adds:
- ast/Argument: AST node for an argument passed to a function.
- ast/FunctionCall: AST node for a function call.
- codegen/ModuleDeclarationRegistrar: The code generator registers module function declarations with this in order to determine module indexes and function indexes for instructions.
- model/FunctionLink: this is a reference either:
- from: a FunctionCall or a FunctionReference
- to: a ModuleFunctionDeclaration or a UserFunction
- optimizer/ReferencedFunctionGatherer: a visitor that determines which module functions and user functions are referenced, by looking at function calls and function references.
Also:
- CodeGenerator registers module functions
- InstructionGenerator generates code for function calls
- InstructionEmitter generates TOK_FUNC instructions
- StoredTokenDecoder decodes TOK_FUNC instructions
After all of this, the compiler can compile print("hello, world");
Adds enough to build the AST nodes for the module function declarations in a .em file.
Adds:
- Function: base class for module function declarations and user functions
- FunctionParameterDeclaration: declaration for a function parameter, as well as its default value if any
- FunctionParameterList: just a holder for function parameter declarations
- ModuleFunctionDeclaration: for function declarations in .em files
- FunctionResolver: hooks up function calls to module functions or user functions
- ModuleProcessor: a visitor for processing const declarations and module function declarations (const declarations are yet to come from the main branch)
* Add codegen/InstructionEmitter
* Add codegen/InstructionGenerator
* CodeGenerator: emit progend
Checkpoint: compiler can compile an empty file
* Comment reason for having both emit and emitter.
The Disambiguator will correct the AST based on context.
At present, it needs to handle ambiguities in the grammar between
case group selectors and named break/continue labels.
Build antlr as external project inside of lib/antlr.
Cache in Ci the antlr folder to speed up compilation times.
* replace ERROR with ANTLR_ERROR, fix clang build
* added missing define needed to link on windows
* different lib name with clang on windows
Add astbuilder/BuilderWorkspace:
- Temporary workspace used while building the AST (which goes in the CompilerWorkspace)
Add astbuilder/CompilerWorkspaceBuilder:
- Builds a CompilerWorkspace for a script
Add model/CompilerWorkspace:
- Holds AST
- Holds some intermediate data used by semantic analyzer, optimizer, code generator
* Add compiler/Profile
* Add compiler/Report
* From CR notes: add newline on caught exception.
Also added comments that messages should have a newline at the end.
* Add SourceFileIdentifier, SourceLocation, formatfwd
* Add formatfwd.h to clib make sources
* Note to not keep a SourceFileLocation after the lifetime of the SourceFileIdentifiers.
* Add -G / CompareCompilerOutput ecompile mode that runs old and new compiler and compares output.
Add LegacyFunctionOrder because parity needs to know how the old compiler ordered functions.
* Fix class/struct mixup, add to cmake sources
optimize_token() is meant to return true only if it performs an optimization.
By returning true when it did not, it makes the optimizer stop trying.
A script like this can trigger the condition:
var i := 3;
var ii;
ii := 1 - (--i);
print(i);
print(ii);
Notice that line 4 does not optimize to an 'assign-consume' and therefore does not optimize to 'assign global`
Listfile before (see instructions 6-12):
/vagrant/testsuite/escript/opt/opt005-stopped-optimizing-early.src, Line 1
var i := 3;
0: decl global #0
1: 3L
2: :=
3: #
var ii;
4: decl global #1
5: #
ii := 1 - (--i);
6: global #1
7: 1L
8: global #0
9: unary --
10: -
11: :=
12: #
print(i);
13: global #0
14: Func(1,0): Print
15: #
print(ii);
16: global #1
17: Func(1,0): Print
18: #
19: progend
Listfile after (see instructions 6-10):
/vagrant/testsuite/escript/opt/opt005-stopped-optimizing-early.src, Line 1
var i := 3;
0: decl global #0
1: 3L
2: :=
3: #
var ii;
4: decl global #1
5: #
ii := 1 - (--i);
6: 1L
7: global #0
8: unary --
9: -
10: global1 :=
print(i);
11: global #0
12: Func(1,0): Print
13: #
print(ii);
14: global #1
15: Func(1,0): Print
16: #
17: progend
The RSV_LOCAL offset should be the the local variable, not of the local variable within the block
Notice though, that the executor doesn't even use it.
There is more detail in the attached script.
listfile before:
/vagrant/testsuite/escript/bug/bug013-local-variable-index.src, Line 7
program foo()
var a; // should be 0
0: decl local #0
1: #
if ( a )
2: local #0
3: if false goto 17
var b; // should be 1 actually emitted 0
4: decl local #0
5: #
var c; // should be 2 actually emitted 1
6: decl local #1
7: #
if ( b )
8: local #1
9: if false goto 16
var d; // should be 3 actually emitted 0
10: decl local #0
11: #
print(d);
12: local #3
13: Func(1,0): Print
14: #
15: leave block(1)
16: leave block(2)
17: leave block(1)
18: progend
listfile after:
/vagrant/testsuite/escript/bug/bug013-local-variable-index.src, Line 7
program foo()
var a; // should be 0
0: decl local #0
1: #
if ( a )
2: local #0
3: if false goto 17
var b; // should be 1 actually emitted 0
4: decl local #1
5: #
var c; // should be 2 actually emitted 1
6: decl local #2
7: #
if ( b )
8: local #1
9: if false goto 16
var d; // should be 3 actually emitted 0
10: decl local #3
11: #
print(d);
12: local #3
13: Func(1,0): Print
14: #
15: leave block(1)
16: leave block(2)
17: leave block(1)
18: progend