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

+88
View File
@@ -0,0 +1,88 @@
use super::checked;
use dever::{
compiler::{build, emit},
syntax::source::Source,
};
#[test]
fn emission_keeps_only_called_ownership_versions() {
let text = "decorate(value: Text, loud: true) (answer: Text) { answer = value + \"!\" }\ndecorate(value: Text, loud: false) (answer: Text) { answer = value + \".\" }\nmain(value: Text, loud: Bool) (answer: Text) { answer = decorate(value + \"hello\", loud) }";
let program = checked(text).unwrap();
let source = Source::new(0, "case.dever", text.into());
let main = program
.functions
.iter()
.position(|function| function.signature.name == "main")
.unwrap();
let decorate = program
.functions
.iter()
.position(|function| function.signature.name == "decorate")
.unwrap();
let generated = emit::generate(&program, &[source], &[main].into());
assert!(generated.contains(&format!("fn function{decorate}_own0(")));
assert!(!generated.contains(&format!("fn function{decorate}(")));
}
#[test]
fn final_record_fields_keep_ownership_across_calls() {
let text = "type Packet { path: Text\n values: List<Int> }\nselected(path: \"/echo\", values: List<Int>) (answer: List<Int>) { answer = values }\nselected(path: other, values: List<Int>) (answer: List<Int>) { answer = [] }\nroute(packet: Packet) (answer: List<Int>) { answer = selected(packet.path, packet.values) }\nmain() (answer: List<Int>) { packet = Packet { path = \"/echo\", values = [1, 2, 3] }\n answer = route(packet) }";
let program = checked(text).unwrap();
let source = Source::new(0, "case.dever", text.into());
let index = |name| {
program
.functions
.iter()
.position(|function| function.signature.name == name)
.unwrap()
};
let generated = emit::generate(&program, &[source], &[index("main")].into());
let selected = index("selected");
assert!(generated.contains(&format!("fn function{selected}_own0_own1(")));
assert!(!generated.contains(&format!("fn function{selected}(")));
}
#[test]
fn emitted_types_follow_entry_variables_errors_and_nested_fields() {
let text = "type Leaf { value: Channel<Int>? }\ntype Box { leaves: List<Leaf> }\ntype Unused { value: AsyncStream<Int> }\nmake() (value: Box) { value = Box { leaves = [] } }\nmain() () { value = make() }\nplain() (answer: Int) { answer = 42 }";
let program = checked(text).unwrap();
let source = Source::new(0, "case.dever", text.into());
for (entry, required) in [("main", true), ("plain", false)] {
let index = program
.functions
.iter()
.position(|function| function.signature.name == entry)
.unwrap();
let functions = program.reachable([index]);
assert_eq!(
build::runtime_features(&program, &functions).contains(&"task"),
required
);
let generated = emit::generate(&program, std::slice::from_ref(&source), &functions);
for (index, definition) in program.definitions.iter().enumerate() {
let wanted = required && matches!(definition.name.as_str(), "Leaf" | "Box");
assert_eq!(
generated.contains(&format!("pub struct Type{index} {{")),
wanted,
"{entry}: {}",
definition.name
);
}
}
}
#[test]
fn unused_types_are_still_validated_before_emission() {
assert_eq!(
checked("type Unused { values: Channel<Stream<Int>> }\nmain() () {}")
.unwrap_err()
.code,
"C013"
);
assert_eq!(
checked("type Unused { next: Unused? }\nmain() () {}")
.unwrap_err()
.code,
"C007"
);
}