Spezifikationsabgleich und Regressionsnachweise abschließen

This commit is contained in:
2026-09-06 10:31:16 +02:00
parent c8b92f0619
commit 024336e29c
39 changed files with 2485 additions and 120 deletions

View File

@@ -265,7 +265,8 @@ fn builtin_fn(name: &str) -> Option<(u8, u8, &'static [ArgK], RetK)> {
(5, 5, &[N, N, N, N, N], Db)
}
"IPMT" | "IPMT#" | "PPMT" | "PPMT#" | "RATE" | "RATE#" => (6, 6, &[N, N, N, N, N, N], Db),
"NPV" | "NPV#" | "IRR" | "IRR#" => (2, 2, &[N, A], Db),
"NPV" | "NPV#" => (2, 2, &[N, A], Db),
"IRR" | "IRR#" => (2, 2, &[A, N], Db),
"MIRR" | "MIRR#" => (3, 3, &[A, N, N], Db),
"SLN" | "SLN#" => (3, 3, &[N, N, N], Db),
"SYD" | "SYD#" | "DDB" | "DDB#" => (4, 4, &[N, N, N, N], Db),
@@ -278,6 +279,7 @@ fn builtin_fn(name: &str) -> Option<(u8, u8, &'static [ArgK], RetK)> {
"CVD" | "CVDMBF" => (1, 1, &[S], Db),
"CVC" => (1, 1, &[S], Cu),
// Dateisystem und System
"SHELL" => (1, 1, &[S], L),
"CURDIR$" => (0, 1, &[S], St),
"DIR$" => (0, 1, &[S], St),
"LPOS" => (1, 1, &[N], I),
@@ -2861,7 +2863,7 @@ impl Sema {
} => {
let Some(art) = trap_art(device) else {
// COM/PEN/PLAY/STRIG sind Non-Feature — namentlich.
self.err(*pos, "Feature unavailable");
self.err(*pos, format!("Feature unavailable: {device}"));
return;
};
// Wertebereich prüfen, soweit die Kennung konstant ist.
@@ -2908,7 +2910,7 @@ impl Sema {
} => {
match device.as_str() {
"TIMER" | "KEY" | "UEVENT" | "SIGNAL" | "EVENT" => {}
_ => self.err(*pos, "Feature unavailable"),
_ => self.err(*pos, format!("Feature unavailable: {device}")),
}
if let Some(i) = index {
self.want_num(i, scope);
@@ -2939,7 +2941,7 @@ impl Sema {
return;
}
let Some(art) = trap_art(device) else {
self.err(*pos, "Feature unavailable");
self.err(*pos, format!("Feature unavailable: {device}"));
return;
};
if let Some(i) = index {
@@ -3566,7 +3568,7 @@ impl Sema {
for a in args {
self.lower_expr(a, scope);
}
self.err(pos, "Feature unavailable");
self.err(pos, format!("Feature unavailable: {name}"));
return;
}
self.err(pos, "Subprogram not defined");
@@ -4147,7 +4149,7 @@ impl Sema {
fn reject_com_device(&mut self, file: &Expr, pos: SourcePos) {
if let Expr::StrLit(s, _) = file {
if ist_com_geraet(s) {
self.err(pos, "Feature unavailable");
self.err(pos, format!("Feature unavailable: {s}"));
}
}
}
@@ -4922,7 +4924,7 @@ impl Sema {
for a in idx {
self.lower_expr(a, scope);
}
self.err(pos, "Feature unavailable");
self.err(pos, format!("Feature unavailable: {full_name}"));
return (HExpr::Int(0), Ty::Unknown);
}
// 4. Builtin-Funktion
@@ -4982,7 +4984,7 @@ impl Sema {
.is_some_and(|v| suffix.is_none_or(|s| v.ty == suffix_ty(s)));
if !declared {
if banned_feature(&full_name) {
self.err(pos, "Feature unavailable");
self.err(pos, format!("Feature unavailable: {full_name}"));
return (HExpr::Int(0), Ty::Unknown);
}
if let Some((0, _, _, _)) = builtin_fn(&full_name) {
@@ -5628,13 +5630,13 @@ mod tests {
#[test]
fn hardware_features_zur_compilezeit_abgelehnt() {
assert!(diags("POKE 100, 1").contains(&"Feature unavailable".to_string()));
assert!(diags("x = PEEK(100)").contains(&"Feature unavailable".to_string()));
assert!(diags("p = VARPTR(a%)").contains(&"Feature unavailable".to_string()));
assert!(diags("SOUND 440, 10").contains(&"Feature unavailable".to_string()));
assert!(diags("CHAIN \"prog\"").contains(&"Feature unavailable".to_string()));
assert!(diags("PLAY \"cde\"").contains(&"Feature unavailable".to_string()));
assert!(diags("CIRCLE 1, 2").contains(&"Feature unavailable".to_string()));
assert!(diags("POKE 100, 1").contains(&"Feature unavailable: POKE".to_string()));
assert!(diags("x = PEEK(100)").contains(&"Feature unavailable: PEEK".to_string()));
assert!(diags("p = VARPTR(a%)").contains(&"Feature unavailable: VARPTR".to_string()));
assert!(diags("SOUND 440, 10").contains(&"Feature unavailable: SOUND".to_string()));
assert!(diags("CHAIN \"prog\"").contains(&"Feature unavailable: CHAIN".to_string()));
assert!(diags("PLAY \"cde\"").contains(&"Feature unavailable: PLAY".to_string()));
assert!(diags("CIRCLE 1, 2").contains(&"Feature unavailable: CIRCLE".to_string()));
}
#[test]
@@ -5726,7 +5728,7 @@ mod tests {
fn datei_ea_und_events() {
let src = "OPEN \"test.dat\" FOR RANDOM AS #1 LEN = 64\nCLOSE #1\nOPEN \"o\", #2, \"f.txt\"\nCLOSE\nTIMER ON\nKEY(5) OFF";
assert!(diags(src).is_empty(), "{:?}", diags(src));
assert!(diags("PEN ON").contains(&"Feature unavailable".to_string()));
assert!(diags("PEN ON").contains(&"Feature unavailable: PEN".to_string()));
}
fn form_catalog() -> FormCatalog {