Migrate import evaluator to Kotlin

This commit is contained in:
2020-03-11 22:58:28 +01:00
parent a256db117e
commit 10a7dc8823
6 changed files with 64 additions and 15 deletions

View File

@@ -24,7 +24,7 @@ data class CallStackFrame(
} }
fun getVariable(name: String): Value { fun getVariable(name: String): Value {
return scopes.lastOrNull { it.containsKey(name) }?.get(name) ?: throw RuntimeException("Variable `$name` not found") return scopes.lastOrNull { it.containsKey(name) }?.get(name) ?: throw RuntimeException("Undefined variable `$name`")
} }
fun prettyScope() { fun prettyScope() {

View File

@@ -9,8 +9,7 @@ class ImportParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput { override fun tryToParse(input: TokenList): ParserOutput {
val pathParser = oneOf( val pathParser = oneOf(
UnitParser(), UnitParser(),
SimpleIdentifierParser(), SimpleIdentifierParser()
StringLiteralParser()
) )
return allOf( return allOf(

View File

@@ -3,12 +3,13 @@ package io.smnp.dsl.ast.parser
import io.smnp.dsl.ast.model.entity.ParserOutput import io.smnp.dsl.ast.model.entity.ParserOutput
import io.smnp.dsl.ast.model.node.RootNode import io.smnp.dsl.ast.model.node.RootNode
import io.smnp.dsl.token.model.entity.TokenList import io.smnp.dsl.token.model.entity.TokenList
import io.smnp.dsl.token.model.enumeration.TokenType
class RootParser : Parser() { class RootParser : Parser() {
override fun tryToParse(input: TokenList): ParserOutput { override fun tryToParse(input: TokenList): ParserOutput {
return repeat( return repeat(
oneOf( oneOf(
ImportParser(), allOf(ImportParser(), optional(terminal(TokenType.SEMICOLON))) { (import, _) -> import },
FunctionDefinitionParser(), FunctionDefinitionParser(),
ExtendParser(), ExtendParser(),
StatementParser() StatementParser()

View File

@@ -0,0 +1,39 @@
package io.smnp.evaluation.evaluator
import io.smnp.dsl.ast.model.node.AccessOperatorNode
import io.smnp.dsl.ast.model.node.IdentifierNode
import io.smnp.dsl.ast.model.node.ImportNode
import io.smnp.dsl.ast.model.node.Node
import io.smnp.environment.Environment
import io.smnp.error.ShouldNeverReachThisLineException
import io.smnp.evaluation.model.entity.EvaluatorOutput
class ImportEvaluator : Evaluator() {
override fun supportedNodes() = listOf(ImportNode::class)
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
val path = when (val pathNode = (node as ImportNode).path) {
is AccessOperatorNode -> complexPath(pathNode).joinToString(".")
is IdentifierNode -> pathNode.token.rawValue
else -> throw ShouldNeverReachThisLineException()
}
environment.loadModule(path)
return EvaluatorOutput.ok()
}
private fun complexPath(segment: AccessOperatorNode): List<String> {
val segments = mutableListOf<String>()
val (lhs, _, rhs) = segment
segments.add((rhs as IdentifierNode).token.rawValue)
when(lhs) {
is AccessOperatorNode -> segments.addAll(complexPath(lhs))
is IdentifierNode -> segments.add(lhs.token.rawValue)
}
return segments.reversed()
}
}

View File

@@ -11,8 +11,10 @@ class RootEvaluator : Evaluator() {
override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput { override fun tryToEvaluate(node: Node, environment: Environment): EvaluatorOutput {
val evaluator = oneOf( val evaluator = oneOf(
ImportEvaluator(),
ExpressionEvaluator(), ExpressionEvaluator(),
FunctionDefinitionEvaluator() FunctionDefinitionEvaluator(),
DefaultEvaluator()
) )
for(child in node.children) { for(child in node.children) {

View File

@@ -2,30 +2,38 @@ package io.smnp.interpreter
import io.smnp.dsl.ast.parser.RootParser import io.smnp.dsl.ast.parser.RootParser
import io.smnp.dsl.token.tokenizer.DefaultTokenizer import io.smnp.dsl.token.tokenizer.DefaultTokenizer
import io.smnp.environment.DefaultEnvironment
import io.smnp.environment.Environment
import io.smnp.evaluation.evaluator.RootEvaluator
import java.io.File import java.io.File
class Interpreter { class Interpreter {
fun run(code: String) { private val tokenizer = DefaultTokenizer()
val tokenizer = DefaultTokenizer() private val parser = RootParser()
val parser = RootParser() private val evaluator = RootEvaluator()
fun run(code: String) {
val lines = code.split("\n") val lines = code.split("\n")
val tokens = tokenizer.tokenize(lines) val tokens = tokenizer.tokenize(lines)
val ast = parser.parse(tokens) val ast = parser.parse(tokens)
ast.node.pretty() val environment = createEnvironment()
println(tokens) evaluator.evaluate(ast.node, environment)
}
private fun createEnvironment(): Environment {
val environment = DefaultEnvironment()
environment.loadModule("smnp.lang")
return environment
} }
fun run(file: File) { fun run(file: File) {
val tokenizer = DefaultTokenizer()
val parser = RootParser()
val lines = file.readLines() val lines = file.readLines()
val tokens = tokenizer.tokenize(lines) val tokens = tokenizer.tokenize(lines)
val ast = parser.parse(tokens) val ast = parser.parse(tokens)
ast.node.pretty() val environment = createEnvironment()
println(tokens) evaluator.evaluate(ast.node, environment)
} }
} }