Updated Application overview (markdown)

Bartłomiej Przemysław Pluta
2020-03-30 18:54:27 +02:00
parent 08e561a626
commit cfd0135fb7

@@ -224,3 +224,59 @@ RootNode 1:16
└─BoolLiteralNode 1:37
└ (bool, »false«, 1:37)
```
All parsers-related code is located in `io.smnp.dsl.ast` package.
## Evaluator
Evaluator is the last stage of SMNP language processing pipeline and also is the heart
of entire SMNP tool, which takes AST as an input and performs programmed operations.
Similar to implemented parser, evaluator works *recursively* because of processing tree-like
structure.
Evaluator's architecture is similar to parser's one. Evaluator consists of
smaller evaluators which are able to evaluate small part of AST's node types.
Similar to parsers, the evaluators also uses a helper method (like `oneOf()`) to improve readability and decrease
the complexity along with the code repeatability.
Because evaluator introduces as *runtime* term, it also works on special object
called *environment*. The *environment* object contains some runtime information,
like loaded modules (with included functions and methods), call stack with included scopes and some meta information. This object is passed through all evaluators along with AST and its
subtrees.
Following listening shows the example evaluator which is `if` statement evaluator:
```kotlin
class ConditionEvaluator : Evaluator() {
private val expressionEvaluator = ExpressionEvaluator()
private val defaultEvaluator = DefaultEvaluator()
override fun supportedNodes() = listOf(ConditionNode::class)
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
val (conditionNode, trueBranchNode, falseBranchNode) = (node as ConditionNode)
val condition = expressionEvaluator.evaluate(conditionNode, environment).value
if (condition.type != DataType.BOOL) {
throw contextEvaluationException(
"Condition should be of bool type, found '${condition.value}'",
conditionNode.position,
environment
)
}
if (condition.value as Boolean) {
return defaultEvaluator.evaluate(trueBranchNode, environment)
} else if (falseBranchNode !is NoneNode) {
return defaultEvaluator.evaluate(falseBranchNode, environment)
}
return EvaluatorOutput.ok()
}
}
```
The code above defines list of supported node, which in this case is a list with single element: `ConditionNode`. The `ConditionNode` is product of `ConditionParser`'s work which handles the `if` statements.
The `tryToEvaluate()` method contains the actually logic of evaluation, and in this case it:
1. evaluates the condition using `ExpressionEvaluator` (it always returns a value)
2. asserts the value to be of `bool` type - if it's other than `bool`, an exception is begin thrown
3. evaluates the `trueBranchNode` if the value is evaluated to `true`
4. if the condition is evaluated to `false`, it checks if `falseBranchNode` (that comes from `else` clause) is present. If so, it's being evaluated.
All evaluator-related code is located in `io.smnp.evaluation` package.