Updated Application overview (markdown)

Bartłomiej Przemysław Pluta
2020-03-30 19:09:56 +02:00
parent cfd0135fb7
commit 1958cda6bc

@@ -279,4 +279,76 @@ The `tryToEvaluate()` method contains the actually logic of evaluation, and in t
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.
All evaluator-related code is located in `io.smnp.evaluation` package.
## Interpreter
`Interpreter` actually isn't an another language processing
stage, rather it is a facade that composes each stage into single pipeline,
accepting a raw SMNP code as an input.
It also accepts additional parameters, like `printTokens`, `printAst` and `dryRun`.
So far, SMNP provides two types of interpreters:
* `LanguageModuleInterpreter` (with its implementation: `DefaultLanguageModuleInterpreter`) and is used only by _Language Module Providers_ and _Hybrid Module Providers_.
* `DefaultInterpreter` which is the standard interpreter that is used for user's input (in form of both scripts and inline code snippets).
The difference between these two interpreters is the `LanguageModuleInterpreter` does support only definitions of functions and methods at the top level of script (technically, in `RootNode`), whereas the `DefaultInterpreter` allows you to have each available statement at the top level of script.
Following snippets shows the code of `DefaultInterpreter`:
```kotlin
class DefaultInterpreter {
private val tokenizer = DefaultTokenizer()
private val parser = RootParser()
private val evaluator = RootEvaluator()
fun run(
code: String,
environment: Environment = DefaultEnvironment(),
printTokens: Boolean = false,
printAst: Boolean = false,
dryRun: Boolean = false
): Environment {
val lines = code.split("\n")
return run(lines, "<inline>", environment, printTokens, printAst, dryRun)
}
fun run(
file: File,
environment: Environment = DefaultEnvironment(),
printTokens: Boolean = false,
printAst: Boolean = false,
dryRun: Boolean = false
): Environment {
val lines = file.readLines()
return run(lines, file.canonicalPath, environment, printTokens, printAst, dryRun)
}
private fun run(
lines: List<String>,
source: String,
environment: Environment,
printTokens: Boolean,
printAst: Boolean,
dryRun: Boolean
): Environment {
environment.loadModule("smnp.lang")
val tokens = tokenizer.tokenize(lines, source)
if (printTokens) println(tokens)
val ast = parser.parse(tokens)
if (printAst) ast.node.pretty()
if (!dryRun) {
val result = evaluator.evaluate(ast.node, environment)
if (result.result == EvaluationResult.FAILED) {
throw RuntimeException("Evaluation failed")
}
}
return environment
}
}
```
You can think of `DefaultInterpreter` as an endpoint for `core` module that is ready to be used by `app` module or any other application willing to make use of SMNP.