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

+125
View File
@@ -0,0 +1,125 @@
use super::linked;
#[test]
fn async_streams_support_typed_sequential_consumers_and_infer_suspension() {
let source = "add(value: Int, state: Int) (next: Int) pure { next = value + state }\n main() (answer: Int) { answer = reduce(add, stream([1, 2]), 0) }";
let program = linked(source).unwrap();
let main = program
.functions
.iter()
.find(|function| function.signature.name == "main")
.unwrap();
assert!(main.signature.effects.suspend);
assert!(main.signature.effects.async_stream);
for source in [
"main() (values: AsyncStream<Int>) { values = stream([]) }",
"main() (values: AsyncStream<Int>) { values = dever.task.ticks(1) }",
"main(values: AsyncStream<Int>) () { close(values) }",
] {
let program = linked(source).unwrap();
let main = program
.functions
.iter()
.find(|function| function.signature.name == "main")
.unwrap();
assert!(!main.signature.effects.suspend);
}
}
#[test]
fn async_streams_reject_wrong_handlers_nontransferable_values_and_private_intrinsics() {
for (source, code) in [
(
"main(values: List<Stream<Int>>) () { close(stream(values)) }",
"C013",
),
(
"main(values: AsyncStream<Stream<Int>>) () { close(values) }",
"C013",
),
("main() () pure { close(stream([1])) }", "C013"),
("main() () { close(dever.system.taskTicks(1)) }", "C006"),
(
"copy(value: Int) (next: Int) { next = value }\nmain() () { each(copy, stream([1])) }",
"C005",
),
(
"consume(value: Int, state: Stream<Int>) () { close(state) }\nmain(state: Stream<Int>) () { each(consume, stream([1]), state) }",
"C013",
),
("main() () { close(stream(1)) }", "C005"),
] {
assert_eq!(linked(source).unwrap_err().code, code, "{source}");
}
}
#[test]
fn streams_preserve_existing_error_obligations() {
let prefix = "type Result { Done\n error Failed(message: Text) }\nhandle(value: Result) () recover(\"handles stream errors\") {}\n";
assert!(
linked(&format!(
"{prefix}main() () {{ each(handle, stream([Result.Failed(\"reason\")])) }}"
))
.is_ok()
);
for body in [
"values = stream([Result.Failed(\"reason\")])\n close(values)",
"values = stream([Result.Failed(\"reason\")])",
] {
assert_eq!(
linked(&format!("{prefix}main() () {{ {body} }}"))
.unwrap_err()
.code,
"C012"
);
}
assert!(linked(&format!("{prefix}main() (values: AsyncStream<Result>) {{ values = stream([Result.Failed(\"reason\")]) }}")).is_ok());
}
#[test]
fn closed_stream_aliases_cannot_discharge_unread_error_values() {
let prefix = "type Result { Done\n error Failed(message: Text) }\nhandle(value: Result) () recover(\"handles errors\") {}\nforward(values: AsyncStream<Result>) (output: AsyncStream<Result>) { output = values }\ntype Box { values: AsyncStream<Result> }\n";
for body in [
"values = stream([Result.Failed(\"reason\")])\n alias = values\n close(alias)\n each(handle, values)",
"values = stream([Result.Failed(\"reason\")])\n alias = forward(values)\n close(alias)\n each(handle, values)",
"values = stream([Result.Failed(\"reason\")])\n box = Box { values = values }\n close(box.values)\n each(handle, values)",
] {
assert_eq!(
linked(&format!("{prefix}main() () {{ {body} }}"))
.unwrap_err()
.code,
"C012",
"{body}"
);
}
assert_eq!(linked(&format!("{prefix}main() (output: AsyncStream<Result>) {{ values = stream([Result.Failed(\"reason\")])\n close(values)\n output = values }}")).unwrap_err().code, "C012");
assert!(linked(&format!("{prefix}main() () {{ original = [Result.Failed(\"reason\")]\n close(stream(original))\n each(handle, original) }}")).is_ok());
assert!(linked(&format!("{prefix}main() () {{ original = [Result.Failed(\"reason\")]\n first = stream(original)\n second = stream(original)\n close(first)\n each(handle, second) }}")).is_ok());
}
#[test]
fn forwarding_a_lazy_stream_keeps_future_item_error_obligations() {
let prefix = "type Result { Done\n error Failed(message: Text) }\nforward(values: AsyncStream<Result>) (output: AsyncStream<Result>) { output = values }\ncollect(value: Result, state: List<Result>) (next: List<Result>) { next = append(state, value) }\n";
for input in [
"stream(values)",
"forward(stream(values))",
"forward(forward(stream(values)))",
] {
assert_eq!(
linked(&format!(
"{prefix}main(values: Channel<Result>) () {{ lost = reduce(collect, {input}, []) }}"
))
.unwrap_err()
.code,
"C012",
"{input}"
);
assert!(linked(&format!("{prefix}main(values: Channel<Result>) (output: List<Result>) {{ output = reduce(collect, {input}, []) }}")).is_ok());
}
assert!(
linked(&format!(
"{prefix}main(values: Channel<Result>) () {{ close(forward(stream(values))) }}"
))
.is_ok()
);
}