Initial Dever 0.0.1

This commit is contained in:
Codex committed 2026-11-03 03:32:07 +00:00
commit 81233d098c
1479 files changed
+163782

No files matched your search

+179
View File
@@ -0,0 +1,179 @@
use super::checked;
const HANDLERS: &str = "double(value: Int) (answer: Int) { answer = value * 2 }\npositive(value: Int) (answer: Bool) { answer = value > 0 }\nadd(value: Int, state: Int) (next: Int) { next = value + state }\nstop(value: Int, state: Int) (next: Int, stop: Bool) { next = value + state\n stop = next >= 3 }\n";
const ERRORS: &str = "type Result { Ready(value: Int)\n error Failed(message: Text) }\nidentity(value: Result) (answer: Result) { answer = value }\nhandled(value: Result) (answer: Bool) recover(\"optional probe failure is explicitly discarded\") { answer = true }\ncontext(value: Int, state: Result) () recover(\"optional context probe is discarded\") {}\nkeep(value: Int, state: Result) (next: Result) { next = state }\nconsume(value: Result, state: Int) (next: Int) recover(\"count failed probes\") { next = state + 1 }\npartial(value: Result, state: Int) (next: Int, stop: Bool) recover(\"count failed probes\") { next = state + 1\n stop = true }\n";
#[test]
fn checks_collection_handler_types_and_cycles() {
for body in [
"main() (answer: List<Int>) { answer = each(double, []) }",
"main() (answer: List<Int>) { answer = filter(positive, [1, -1]) }",
"main() (answer: Int?) { answer = find(positive, []) }",
"main() (answer: Int) { answer = sum(double, []) }",
"main() (answer: Float) { answer = sum([]) }",
"main() (answer: Decimal?) { answer = sum([]) }",
"main() (answer: Int) { answer = reduce(add, [], 10) }",
"main() (answer: Int) { answer = reduceUntil(stop, [1, 2, 3], 0) }",
] {
let result = checked(&(HANDLERS.to_owned() + body));
assert!(result.is_ok(), "{body}: {result:?}");
}
for body in [
"main() (answer: List<Int>) { answer = each(positive, [1]) }",
"main() (answer: List<Int>) { answer = filter(double, [1]) }",
"main() (answer: Int?) { answer = find(positive, [\"one\"]) }",
"main() (answer: Int) { answer = sum(positive, [1]) }",
"main() (answer: Int) { answer = reduce(add, [1], true) }",
"main() (answer: Int) { answer = reduceUntil(add, [1], 0) }",
"main() (answer: Int) { answer = reduce(add, [1], 0, 1) }",
"main() (answer: List<Int>) { double = 2\n answer = each(double, [1]) }",
"main() () { handler = double }",
] {
assert!(checked(&(HANDLERS.to_owned() + body)).is_err(), "{body}");
}
assert_eq!(
checked("cycle(value: Int) (answer: Int) { answer = sum(cycle, [value]) }")
.unwrap_err()
.code,
"C007"
);
assert_eq!(checked("first(value: Int) (answer: Int) { answer = sum(second, [value]) }\nsecond(value: Int) (answer: Int) { answer = first(value) }").unwrap_err().code, "C007");
}
#[test]
fn collections_preserve_error_obligations() {
for body in [
"main(values: List<Result>) (answer: Int) { copies = each(identity, values)\n answer = length(copies) }",
"main(values: List<Result>) (answer: Result?) { answer = find(handled, values) }",
"main(values: List<Result>) (answer: Int) { answer = reduceUntil(partial, values, 0) }",
"main() (answer: Int) { answer = reduceUntil(partial, [Result.Failed(\"one\"), Result.Failed(\"two\")], 0) }",
"main(state: Result) () { each(context, [], state) }",
"main(values: List<Int>, state: Result) () { each(context, values, state) }",
"main(state: Result) (answer: Int) { kept = reduce(keep, [], state)\n answer = 1 }",
"main() (answer: List<Result>) { lost = Result.Failed(\"lost\")\n answer = each(identity, []) }",
] {
let result = checked(&(ERRORS.to_owned() + body));
assert_eq!(result.unwrap_err().code, "C012", "{body}");
}
for body in [
"main(values: List<Result>) (answer: List<Result>) { answer = each(identity, values) }",
"main(values: List<Result>) (answer: Int) { answer = reduce(consume, values, 0) }",
"main(state: Result) () { each(context, [1], state) }",
"main() (answer: Result?) { answer = find(handled, [Result.Failed(\"one\")]) }",
"main() (answer: Int) { answer = reduceUntil(partial, [Result.Failed(\"one\")], 0) }",
"main(state: Result) (answer: Result) { answer = reduce(keep, [], state) }",
] {
let result = checked(&(ERRORS.to_owned() + body));
assert!(result.is_ok(), "{body}: {result:?}");
}
}
#[test]
fn collection_error_summaries_survive_calls_and_repeated_state() {
let prefix = ERRORS.to_owned()
+ "copy(values: List<Result>) (answer: List<Result>) { answer = each(identity, values) }\nreplace(value: Result, state: Result) (next: Result) recover(\"last probe replaces previous probe\") { next = value }\n";
for body in [
"main(values: List<Result>) (answer: Int) { copies = copy(values)\n answer = length(copies) }",
"main(values: List<Result>, state: Result) (answer: Int) { last = reduce(replace, values, state)\n answer = 1 }",
"main(state: Result) () { copies = copy([])\n count = length(copies) }",
] {
assert_eq!(
checked(&(prefix.clone() + body)).unwrap_err().code,
"C012",
"{body}"
);
}
let source = prefix
+ "main(values: List<Result>, state: Result) (answer: Result) { answer = reduce(replace, values, state) }";
assert!(checked(&source).is_ok());
}
#[test]
fn optional_traversal_cannot_transfer_unvisited_obligations() {
let prefix = ERRORS.to_owned()
+ "takeContext(value: Int, context: Result) (answer: Result) { answer = context }\nfirst(value: Result, state: Result) (next: Result, stop: Bool) recover(\"replace previous state\") { next = value\n stop = true }\n";
for body in [
"main(values: List<Int>, state: Result) (answer: List<Result>) { answer = each(takeContext, values, state) }",
"main(values: List<Result>) (answer: Result) { answer = reduceUntil(first, values, Result.Ready(0)) }",
] {
assert_eq!(
checked(&(prefix.clone() + body)).unwrap_err().code,
"C012",
"{body}"
);
}
assert!(checked(&(prefix + "main(state: Result) (answer: List<Result>) { answer = each(takeContext, [1], state) }")).is_ok());
}
#[test]
fn replacing_record_fields_still_checks_discarded_failures() {
let source = ERRORS.to_owned()
+ "type Row { result: Result\n count: Int }\nreplace(value: Row) (answer: Row) { answer = value\n answer.result = Result.Ready(1)\n answer.count = 0 }";
assert_eq!(checked(&source).unwrap_err().code, "C012");
}
#[test]
fn known_length_map_builds_reserve_once_and_update_in_place() {
for (kind, item, value, sequence) in [
("Bytes", "Int", "value", "values"),
("List<Int>", "Int", "value", "values"),
(
"Map<Int, Int>",
"MapEntry<Int, Int>",
"value.value",
"entries(values)",
),
] {
let text = format!(
"insert(value: {item}, state: Map<Int, Int>) (next: Map<Int, Int>) {{ next = put(state, length(state), {value}) }}\nmain(values: {kind}) (answer: Map<Int, Int>) {{ answer = reduce(insert, {sequence}, {{}}) }}"
);
let source = dever::syntax::source::Source::new(0, "case.dever", text);
let program = checked(&source.text).unwrap();
let generated = dever::compiler::emit::generate(&program, &[source], &[1].into());
let main = generated.split("pub fn function1(").nth(1).unwrap();
let main = main.split("pub fn ").next().unwrap();
assert!(
main.contains("Map::with_capacity(sequence.len())"),
"{main}"
);
assert!(main.contains("state.insert("), "{main}");
assert!(!main.contains("state.clone()"), "{main}");
assert!(!main.contains(".to_owned()"), "{main}");
}
}
#[test]
fn record_reductions_keep_a_single_growing_buffer() {
let text = "type State { values: List<Int>\n count: Int }\nstep(value: Int, state: State) (next: State) { values = append(state.values, value)\n next = State { values = values\n count = state.count + 1 } }\nmain(input: Bytes) (answer: State) { answer = reduce(step, input, State { values = []\n count = 0 }) }";
let source = dever::syntax::source::Source::new(0, "case.dever", text.into());
let program = checked(text).unwrap();
let generated = dever::compiler::emit::generate(&program, &[source], &[1].into());
let main = generated.split("pub fn function1(").nth(1).unwrap();
let main = main.split("\npub ").next().unwrap();
assert!(!main.contains(".clone()"), "{main}");
let iteration = main.split("for byte in sequence").nth(1).unwrap();
let iteration = iteration.split("Type0 {").next().unwrap();
assert!(!iteration.contains(".reserve("), "{main}");
assert!(iteration.contains(".push(element)"), "{main}");
}
#[test]
fn map_selection_copies_only_matching_entries() {
for (operation, result) in [
("filter", "List<MapEntry<Text, Text>>"),
("find", "MapEntry<Text, Text>?"),
] {
let text = format!(
"matches(entry: MapEntry<Text, Text>, target: Text) (answer: Bool) {{ answer = entry.value == target }}\nmain(values: Map<Text, Text>, target: Text) (answer: {result}) {{ answer = {operation}(matches, entries(values), target) }}"
);
let source = dever::syntax::source::Source::new(0, "case.dever", text.clone());
let program = checked(&text).unwrap();
let generated = dever::compiler::emit::generate(&program, &[source], &[1].into());
let main = generated.split("pub fn function1(").nth(1).unwrap();
let main = main.split("\npub ").next().unwrap();
let iteration = main.split("for (key, value) in sequence").nth(1).unwrap();
let (inspection, selected) = iteration.split_once("if ").unwrap();
assert!(!inspection.contains(".clone()"), "{main}");
assert!(selected.contains("(key.clone(), value.clone())"), "{main}");
}
}