diff --git a/core/src/main/kotlin/ch/kleis/lcaac/core/lang/evaluator/Evaluator.kt b/core/src/main/kotlin/ch/kleis/lcaac/core/lang/evaluator/Evaluator.kt index f47e46bf..07ad1528 100644 --- a/core/src/main/kotlin/ch/kleis/lcaac/core/lang/evaluator/Evaluator.kt +++ b/core/src/main/kotlin/ch/kleis/lcaac/core/lang/evaluator/Evaluator.kt @@ -1,9 +1,10 @@ package ch.kleis.lcaac.core.lang.evaluator import ch.kleis.lcaac.core.lang.SymbolTable -import ch.kleis.lcaac.core.lang.evaluator.protocol.Oracle import ch.kleis.lcaac.core.lang.evaluator.protocol.Learner +import ch.kleis.lcaac.core.lang.evaluator.protocol.Oracle import ch.kleis.lcaac.core.lang.expression.* +import ch.kleis.lcaac.core.lang.register.ProcessKey import ch.kleis.lcaac.core.math.QuantityOperations import org.slf4j.LoggerFactory @@ -32,9 +33,23 @@ class Evaluator( } } - fun trace(template: EProcessTemplate, arguments: Map> = emptyMap()): EvaluationTrace { - return prepareRequests(template, arguments) - .let(this::trace) + fun with(template: EProcessTemplate): Evaluator { + val processKey = ProcessKey(template.body.name) + if (symbolTable.processTemplates[processKey] != null) throw IllegalStateException("Process ${template.body.name} already exists") + val st = this.symbolTable.copy( + processTemplates = this.symbolTable.processTemplates.plus( + mapOf(processKey to template) + ) + ) + return Evaluator(st, ops) + } + + fun trace( + template: EProcessTemplate, + arguments: Map> = emptyMap() + ): EvaluationTrace { + val requests = prepareRequests(template, arguments) + return trace(requests) } private fun prepareRequests( diff --git a/core/src/test/kotlin/ch/kleis/lcaac/core/lang/evaluator/EvaluatorTest.kt b/core/src/test/kotlin/ch/kleis/lcaac/core/lang/evaluator/EvaluatorTest.kt index b4e48924..f24610a6 100644 --- a/core/src/test/kotlin/ch/kleis/lcaac/core/lang/evaluator/EvaluatorTest.kt +++ b/core/src/test/kotlin/ch/kleis/lcaac/core/lang/evaluator/EvaluatorTest.kt @@ -13,6 +13,7 @@ import ch.kleis.lcaac.core.math.basic.BasicNumber import ch.kleis.lcaac.core.math.basic.BasicOperations import org.junit.jupiter.api.Test import org.junit.jupiter.api.Timeout +import org.junit.jupiter.api.assertThrows import kotlin.test.assertEquals import kotlin.test.assertFailsWith import kotlin.test.assertNotEquals @@ -20,6 +21,60 @@ import kotlin.test.assertNotEquals class EvaluatorTest { private val ops = BasicOperations + @Test + fun with_whenNewTemplate() { + // given + val template = EProcessTemplate( + body = EProcess( + name = "eProcess", + products = listOf( + ETechnoExchange(QuantityFixture.oneKilogram, ProductFixture.carrot) + ), + impacts = listOf( + ImpactFixture.oneClimateChange + ), + ) + ) + val evaluator = Evaluator(SymbolTable.empty(), BasicOperations) + .with(template) + val expected = ImpactValue( + QuantityValueFixture.oneKilogram, + IndicatorValueFixture.climateChange, + ) + + // when + val actual = evaluator.trace(template).getEntryPoint().impacts.first() + + // then + assertEquals(expected, actual) + } + + @Test + fun with_whenNameCollision_shouldThrow() { + // given + val template = EProcessTemplate( + body = EProcess( + name = "eProcess", + products = listOf( + ETechnoExchange(QuantityFixture.oneKilogram, ProductFixture.carrot) + ), + impacts = listOf( + ImpactFixture.oneClimateChange + ), + ) + ) + val symbolTable = SymbolTable( + processTemplates = ProcessTemplateRegister.from(mapOf( + ProcessKey("eProcess") to template + )) + ) + val evaluator = Evaluator(symbolTable, BasicOperations) + + // when/then + val e = assertThrows { evaluator.with(template) } + assertEquals("Process eProcess already exists", e.message) + } + @Test fun eval_processWithImpacts_shouldReduceImpacts() { // given