diff --git a/app/src/main/kotlin/io/smnp/evaluation/evaluator/StaffEvaluator.kt b/app/src/main/kotlin/io/smnp/evaluation/evaluator/StaffEvaluator.kt index 4142a5b..3a6e3a8 100644 --- a/app/src/main/kotlin/io/smnp/evaluation/evaluator/StaffEvaluator.kt +++ b/app/src/main/kotlin/io/smnp/evaluation/evaluator/StaffEvaluator.kt @@ -21,34 +21,21 @@ class StaffEvaluator : Evaluator() { var currentSignature: Fraction? = null val list = measures.map { it as MeasureNode }.flatMap { measure -> - val evaluatedMeasure = measure.items.mapNotNull { + val evaluatedMeasure = measure.items.mapIndexedNotNull { index, it -> when (it) { is TimeSignatureNode -> { + assertTimeSignaturePosition(index, environment, it) currentSignature = Fraction( (it.numerator as IntegerLiteralNode).token.value as Int, (it.denominator as IntegerLiteralNode).token.value as Int ) - null } - else -> evaluator.evaluate(it, environment).value } } - val evaluatedSignature = calculateTimeSignature(evaluatedMeasure) - - currentSignature?.let { - if (evaluatedSignature != it) { - val simplified = evaluatedSignature.simplified - throw PositionException( - EnvironmentException( - EvaluationException("Invalid time signature: expected ${it.numerator}/${it.denominator}, got ${simplified.numerator}/${simplified.denominator}"), - environment - ), measure.position - ) - } - } + assertTimeSignature(evaluatedMeasure, currentSignature, environment, measure) evaluatedMeasure } @@ -56,6 +43,42 @@ class StaffEvaluator : Evaluator() { return EvaluatorOutput.value(Value.list(list)) } + private fun assertTimeSignaturePosition( + index: Int, + environment: Environment, + it: Node + ) { + if (index != 0) { + throw PositionException( + EnvironmentException( + EvaluationException("Time signature can be placed only at the beginning of measure"), + environment + ), it.position + ) + } + } + + private fun assertTimeSignature( + evaluatedMeasure: List, + currentSignature: Fraction?, + environment: Environment, + measure: MeasureNode + ) { + val evaluatedSignature = calculateTimeSignature(evaluatedMeasure) + + currentSignature?.let { + if (evaluatedSignature != it) { + val simplified = evaluatedSignature.simplified + throw PositionException( + EnvironmentException( + EvaluationException("Invalid time signature: expected ${it.numerator}/${it.denominator}, got ${simplified.numerator}/${simplified.denominator}"), + environment + ), measure.position + ) + } + } + } + private fun calculateTimeSignature(values: List): Fraction { return values.fold(Fraction(0, 1)) { acc, value -> acc + when (value.type) {