96 lines
3.1 KiB
Rust
96 lines
3.1 KiB
Rust
use dever::{
|
|
compiler::{build, check, model::Program},
|
|
syntax::{diagnostic::Diagnostic, source::Source},
|
|
};
|
|
|
|
fn linked(text: &str) -> Result<Program, Diagnostic> {
|
|
let inputs = [
|
|
("main", text),
|
|
("dever.time", include_str!("../../../lib/dever/time.dever")),
|
|
(
|
|
"dever.time",
|
|
include_str!("../../../lib/dever/time/calendar.dever"),
|
|
),
|
|
(
|
|
"dever.time",
|
|
include_str!("../../../lib/dever/time/operations.dever"),
|
|
),
|
|
(
|
|
"dever.time",
|
|
include_str!("../../../lib/dever/time/clock.dever"),
|
|
),
|
|
];
|
|
let modules = inputs
|
|
.iter()
|
|
.enumerate()
|
|
.map(|(index, (_, text))| {
|
|
dever::syntax::parse(&Source::new(
|
|
index,
|
|
if index == 0 {
|
|
"main.dever".into()
|
|
} else {
|
|
format!("library{index}.dever")
|
|
},
|
|
(*text).into(),
|
|
))
|
|
})
|
|
.collect::<Result<Vec<_>, _>>()?;
|
|
check::check(
|
|
modules,
|
|
&inputs
|
|
.iter()
|
|
.map(|(package, _)| (*package).into())
|
|
.collect::<Vec<_>>(),
|
|
)
|
|
}
|
|
|
|
#[test]
|
|
fn calendar_types_are_distinct_and_only_clock_reads_have_effects() {
|
|
let program = linked("main() (answer: Text) pure { instant = dever.time.parseDatetime(\"1970-01-01T00:00:00Z\")\n answer = dever.time.formatDatetime(dever.time.add(instant, dever.time.duration(1))) }").unwrap();
|
|
let main = program
|
|
.functions
|
|
.iter()
|
|
.position(|function| function.signature.name == "main")
|
|
.unwrap();
|
|
assert_eq!(
|
|
program.functions[main].signature.effects,
|
|
Default::default()
|
|
);
|
|
assert_eq!(
|
|
build::runtime_features(&program, &program.reachable([main])),
|
|
["calendar"]
|
|
);
|
|
let clocks = linked("main() (value: Int) { value = dever.time.unixMillis() }").unwrap();
|
|
let main = clocks
|
|
.functions
|
|
.iter()
|
|
.position(|function| function.signature.name == "main")
|
|
.unwrap();
|
|
assert!(clocks.functions[main].signature.effects.clock);
|
|
assert!(!clocks.functions[main].signature.effects.timer);
|
|
assert!(!clocks.functions[main].signature.effects.suspend);
|
|
assert!(build::runtime_features(&clocks, &clocks.reachable([main])).is_empty());
|
|
for (source, code) in [
|
|
("main() (value: DateTime) { value = 0 }", "C005"),
|
|
(
|
|
"main(value: DateTime) (answer: DateTime) { answer = dever.time.add(value, 1) }",
|
|
"C005",
|
|
),
|
|
(
|
|
"main(value: DateTime) (answer: Bool) { answer = value < value }",
|
|
"C005",
|
|
),
|
|
(
|
|
"main() (value: DateTime) pure { value = dever.time.now() }",
|
|
"C013",
|
|
),
|
|
("main() () { value = dever.system.timeDuration(1) }", "C006"),
|
|
(
|
|
"main() () { lost = result(dever.time.parseDate(\"bad\")) }",
|
|
"C012",
|
|
),
|
|
] {
|
|
assert_eq!(linked(source).unwrap_err().code, code, "{source}");
|
|
}
|
|
}
|