Package org.ek9lang.compiler.phase5
At this point, before the compiler builds the intermediate representation it complete some more basic checks.
PreIntermediateRepresentationChecks
is the main entry point for this phase.
Most of the processing is delegated to PreIRListener
.
This now follows the same pattern as most of the other Listeners, using
SymbolsAndScopes
for handling scope traversals and locating recorded
symbols and scopes.
There is a 'complexity' calculator built into this phase, it is quite tolerant of high complexity. It does emit compiler errors if a single method/function has complexity at level 50 or higher or if an aggregate has a total complexity of 500 or higher. The rules for calculating complexity are based on a modified McCabe region algorithm. It is quite simple in it's approach, as code elements are encountered a level of complexity is incremented.
There are additional checks around simple evaluation of whether variables have been initialised or not. In some cases properties on aggregates may need to be defined in uninitialised for i.e.
prop1 as String?
In such cases the EK9 compiler will mandate that the EK9 developer create all necessary coded constructors, it will not mandate that that 'prop1' is then initialised - it will leave that to the Ek9 developer to 'take the risk' and understand what may or may not go wrong in their code.
Ideally, all properties and variables are always declared in initialised form (even if the value is 'un-set'). But this cannot always be mandated, so the EK9 compiler has some tolerance for these uninitialised variables.
-
ClassDescriptionEmit error if there are too many arguments.Looks for the complexity value in the complexityCounter and adds the value to the appropriate symbol.Check the assignment to a variable can be a single assignment or a deep copy type assignment.Designed to give a broad indication of complexity, this is not true pure Cyclometric Complexity.Deals with handling any returning values in a dynamic function.Just checks if the expression as defined by the ANTLR AST is simple enough to be assessed to make any Result/Optional get()/ok()/error() method calls safe.When looking to calculate complexity of methods/functions it is important to work out if parts of an expression are in some way conditional.Checks the for structure via the code analysers.Typically checks any returning values to see if they have now been initialised on a function.Extracts the guard variable if there is a guard expression.Given an identifier, this consumer checks if it is a property of some aggregate.Emits an error if an identifier (typically a variable) has been used before being initialised.Does basic checks on the if condition to see if a Result/Optional access has been made safe.Deals with checking if all paths through if/else/else-if/else result in variables meeting criteria.A bit of a catch 22, need to issue errors and the like when traversing an identifier in some circumstances.Once an expression has been assesed as being simple enough to process, this consumer is called to mark the appropriate symbol(s) used in the expression as safe if the appropriate methods are called.Typically checks any returning values to see if they have now been initialised on a method.In the case of specific variables of type like 'Result' and 'Optional' it is important to check if the method being called needs a previous call to isOk or isError or just '?' before accessing specific methods.Typically checks any returning values to see if they have now been initialised on an operator.Used as a base for a range of constructs that can be expressions.At this point all templates should be present and all symbols resolved.Designed to do additional logic checks once everything has been resolved.Deals with handling any returning values in a dynamic function.Checks on a guard expression and marks the identifier variable as initialised.Checks if return variables are initialised.Marks specific types of variable of specific types (generic Result/Option) in a manner that enables the compiler to check if access to certain methods is safe.Typically checks any returning values to see if they have now been initialised on a service operation.Used with aggregates to check that is they have any properties that are not initialised at declaration there are no default or implicit constructors being used.Deals with checking if all paths through switch/case/default (return) result in variables meeting criteria.Similar to the if block check, but this is focused on the true part of the ternary expression.Checks the try/catch/finally structure via the code analysers.Accepts a variable only declaration and ensures the variable is recorded if appropriate, for transient flow checks.Does checks on the control part of a while loop to see if Optional/Result/Iterator are now safe via method access.Checks the while statement via the code analysers.