feat(charka): EVALUATE TRUE y rangos WHEN ... THRU
Completa el EVALUATE con sus dos formas que faltaban. - IR: la rama WhenBranch pasa de values: Vec<Operand> a tests: Vec<WhenTest>, donde WhenTest es Value (igualdad), Range (WHEN lo THRU hi) o Cond (EVALUATE TRUE WHEN cond). - Parser: detecta EVALUATE TRUE y entonces cada WHEN parsea una condición; en modo valor reconoce WHEN lo THRU hi. - Codegen y shadow: una prueba Range se traduce a lo <= s <= hi; una Cond, a la condición directa. - Corpus: programa nuevo 14-clasifica (clasifica notas con rangos THRU y un EVALUATE TRUE). Verificado: intérprete sombra y crate compilado dan la misma salida. Tests: charka-ir 27, charka-codegen 21, charka-shadow 19. fmt + clippy limpios. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@ use std::collections::HashMap;
|
||||
|
||||
use charka_ir::{
|
||||
BinOp, CmpOp, Cond, ConditionName, Expr, Figurative, InspectOp, Ir, Operand, Perform,
|
||||
PerformControl, PerformTarget, Stmt,
|
||||
PerformControl, PerformTarget, Stmt, WhenTest,
|
||||
};
|
||||
use charka_runtime::{cobol_text_cmp, Decimal, Rounding};
|
||||
|
||||
@@ -237,11 +237,7 @@ impl<'a> Machine<'a> {
|
||||
other,
|
||||
} => {
|
||||
for branch in whens {
|
||||
if branch
|
||||
.values
|
||||
.iter()
|
||||
.any(|v| self.operands_equal(subject, v))
|
||||
{
|
||||
if branch.tests.iter().any(|t| self.when_test(subject, t)) {
|
||||
return self.exec_block(&branch.body);
|
||||
}
|
||||
}
|
||||
@@ -582,6 +578,18 @@ impl<'a> Machine<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// ¿Se cumple una prueba `WHEN` para el sujeto dado?
|
||||
fn when_test(&self, subject: &Operand, test: &WhenTest) -> bool {
|
||||
match test {
|
||||
WhenTest::Value(v) => self.operands_equal(subject, v),
|
||||
WhenTest::Range(lo, hi) => {
|
||||
let s = self.eval_decimal(subject);
|
||||
s >= self.eval_decimal(lo) && s <= self.eval_decimal(hi)
|
||||
}
|
||||
WhenTest::Cond(cond) => self.eval_cond(cond),
|
||||
}
|
||||
}
|
||||
|
||||
/// ¿Son iguales dos operandos? (Para las ramas `WHEN` del `EVALUATE`.)
|
||||
fn operands_equal(&self, a: &Operand, b: &Operand) -> bool {
|
||||
if self.is_text(a) || self.is_text(b) {
|
||||
|
||||
@@ -122,6 +122,7 @@ mod tests {
|
||||
corpus_test!(corpus_11_tabla, "11-tabla");
|
||||
corpus_test!(corpus_12_cadenas, "12-cadenas");
|
||||
corpus_test!(corpus_13_inspeccion, "13-inspeccion");
|
||||
corpus_test!(corpus_14_clasifica, "14-clasifica");
|
||||
|
||||
#[test]
|
||||
fn empty_source_runs_clean() {
|
||||
|
||||
Reference in New Issue
Block a user