Updated Application overview (markdown)
@@ -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.
|
||||
Reference in New Issue
Block a user