use dever::compiler::{check, model::Program}; use dever::syntax::{diagnostic::Diagnostic, source::Source}; fn linked(text: &str) -> Result { let sources = [ Source::new(0, "main.dever", text.into()), Source::new( 1, "lib/dever/id.dever", include_str!("../../../lib/dever/id.dever").into(), ), ]; let modules = sources .iter() .map(dever::syntax::parse) .collect::, _>>()?; check::check(modules, &["main".into(), "dever.id".into()]) } #[test] fn ids_are_opaque_and_distinct_from_text() { for source in [ "main(text: Text) (answer: Id) { answer = text }", "main(id: Id) (answer: Text) { answer = id }", "main(id: Id) (answer: Int) { answer = length(id) }", "main(id: Id) (answer: Bool) { answer = id == \"x\" }", "main(id: Id) (answer: Bool) { answer = id < id }", "main(id: Id) (answer: Id) { answer = id + id }", "main(id: Id) (answer: Text) { answer = id.value }", "main() (answer: Id) { answer = Id { value = \"x\" } }", "main(id: Id) () { value = dever.id.fromText(id) }", "main() () { value = dever.id.toText(\"x\") }", ] { assert!(linked(source).is_err(), "{source}"); } assert_eq!( linked("main() (answer: Id) { answer = dever.system.idFromText(\"x\") }") .unwrap_err() .code, "C006" ); } #[test] fn ids_can_be_keys_and_nullable_values_without_implicit_conversion() { for source in [ "main(id: Id) (answer: Map) { answer = { id = 1 } }", "main(id: Id, values: Map) (answer: Text?) { answer = get(values, id) }", "main(id: Id, values: Map) (answer: Id?) { answer = get(values, id) }", "main(values: List) (answer: List) { answer = each(dever.id.fromText, values) }", "main(id: Id?) (answer: Id?) { answer = id }", ] { let result = linked(source); assert!(result.is_ok(), "{result:?}"); } assert_eq!( linked("main(id: Id) () { alias = id\n value = { id = 1\n alias = 2 } }") .unwrap_err() .code, "C002" ); assert!(linked("main(values: Map) () { found = get(values, \"x\") }").is_err()); }