use dever::{ compiler::{build, check, model::Program}, syntax::{diagnostic::Diagnostic, source::Source}, }; fn linked(text: &str) -> Result { 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::, _>>()?; check::check( modules, &inputs .iter() .map(|(package, _)| (*package).into()) .collect::>(), ) } #[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}"); } }