From 1958cda6bcbdf3f06063252acb53f28464c55f47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Przemys=C5=82aw=20Pluta?= Date: Mon, 30 Mar 2020 19:09:56 +0200 Subject: [PATCH] Updated Application overview (markdown) --- Application-overview.md | 74 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) diff --git a/Application-overview.md b/Application-overview.md index 1badebe..f5e4c5c 100644 --- a/Application-overview.md +++ b/Application-overview.md @@ -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. \ No newline at end of file +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, "", 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, + 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. \ No newline at end of file