1use crate::messages::Refusal;
24
25pub use vla_lang::projection::{Projection, Window};
26
27#[derive(Clone, Copy, Debug, PartialEq, Eq)]
29pub struct Seam {
30 pub name: &'static str,
32 pub entrance: &'static str,
35 pub oracle: &'static str,
37 pub implementations: &'static [&'static str],
40 pub deferred_to: &'static str,
42}
43
44pub const SEAMS: [Seam; 6] = [
46 Seam {
47 name: "sentences",
48 entrance: "a phrasebook file (.vla) with its test: proofs, loaded through api::vocab_gate",
49 oracle: "frazaro prove passes every proof; the translate and refusal goldens hold",
50 implementations: &["the phrasebooks a door loads, english.vla first"],
51 deferred_to: "",
52 },
53 Seam {
54 name: "paragraphs",
55 entrance: "a library of sentences with named slots, imported by a Use sentence",
56 oracle: "the build golden, and the stamp hashing every file used",
57 implementations: &[],
58 deferred_to: "G-USE",
59 },
60 Seam {
61 name: "engines",
62 entrance: "an implementation of kernel::Engine under a head-table symbol",
63 oracle: "a proof file of its kind, with clingo beside it where it applies",
64 implementations: &[],
65 deferred_to: "PORT.9",
66 },
67 Seam {
68 name: "formats and hosts",
69 entrance: "an implementation of reflect::Source to read, a writer beside it, and a kernel::HostProfile per door",
70 oracle: "the reflect, diff and audit goldens for a reader; the build golden for a writer",
71 implementations: &["xlsx (OOXML), read and written", "ods (OpenDocument), read"],
72 deferred_to: "",
73 },
74 Seam {
75 name: "projections",
76 entrance: "an implementation of vla_lang::projection::Projection",
77 oracle: "a view golden per projection",
78 implementations: &["grid, the view record of one window (view::Grid)"],
79 deferred_to: "",
80 },
81 Seam {
82 name: "functions",
83 entrance: "a function registered into vla_lang::calc::Library, with the fixture a host saved that shows it (excel::library)",
84 oracle: "the recalc golden: the fixture's cached values agree (check_recalc_golden.ps1)",
85 implementations: &[
86 "the language's fourteen day-one functions (vla_lang::calc::library)",
87 "Excel's library, the declared subset by measurement (excel::SUBSET)",
88 ],
89 deferred_to: "",
90 },
91];
92
93pub fn seams() -> &'static [Seam] {
95 &SEAMS
96}
97
98#[derive(Clone, Copy, Debug, PartialEq, Eq)]
100pub struct Format {
101 pub name: &'static str,
102 pub extension: &'static str,
103 pub reads: bool,
104 pub writes: bool,
105}
106
107pub const FORMATS: [Format; 2] = [
110 Format {
111 name: "OOXML",
112 extension: "xlsx",
113 reads: true,
114 writes: true,
115 },
116 Format {
117 name: "OpenDocument",
118 extension: "ods",
119 reads: true,
120 writes: false,
121 },
122];
123
124pub trait Engine {
130 type Table;
132 fn head(&self) -> &str;
134 fn proof_kind(&self) -> &str;
136 fn run(&self, tables: &[Self::Table]) -> Result<Self::Table, Refusal>;
138}
139
140#[derive(Clone, Copy, Debug, PartialEq, Eq)]
143pub struct HostProfile {
144 pub door: &'static str,
145 pub forms: &'static [&'static str],
147 pub scaffold: &'static [&'static str],
149 pub refuses_with: &'static str,
151}
152
153pub const FILE_DOOR: HostProfile = HostProfile {
159 door: "file",
160 forms: &[
161 "at-line",
162 "begin",
163 "dim",
164 "on-error",
165 "label",
166 "exit-sub",
167 "exit-function",
168 "set!",
169 "if",
170 ".",
171 ],
172 scaffold: &["vla-report-error", "vlaensuresheet"],
173 refuses_with: "build-not-representable",
174};
175
176pub const HOST_PROFILES: [HostProfile; 1] = [FILE_DOOR];
180
181#[cfg(test)]
182mod tests {
183 use super::*;
184 use crate::headtable;
185 use crate::reflect;
186
187 const FIXTURE_XLSX: &[u8] = include_bytes!("../../scripts/reflect/fixture.xlsx");
188 const FIXTURE_ODS: &[u8] = include_bytes!("../../scripts/reflect/opendocument.ods");
189
190 #[test]
191 fn six_seams_each_with_an_entrance_and_an_oracle() {
192 assert_eq!(seams().len(), 6);
193 let names: Vec<&str> = seams().iter().map(|s| s.name).collect();
194 assert_eq!(
195 names,
196 [
197 "sentences",
198 "paragraphs",
199 "engines",
200 "formats and hosts",
201 "projections",
202 "functions"
203 ]
204 );
205 for s in seams() {
206 assert!(!s.entrance.is_empty(), "{} names no entrance", s.name);
207 assert!(!s.oracle.is_empty(), "{} names no oracle", s.name);
208 assert!(
209 !s.implementations.is_empty() || !s.deferred_to.is_empty(),
210 "{} has neither an implementation nor the item that lands one",
211 s.name
212 );
213 }
214 }
215
216 #[test]
217 fn the_engines_seam_is_empty_today_and_the_projections_seam_has_its_grid() {
218 let engines = seams().iter().find(|s| s.name == "engines").unwrap();
219 assert!(engines.implementations.is_empty());
220 assert_eq!(engines.deferred_to, "PORT.9");
221 let projections = seams().iter().find(|s| s.name == "projections").unwrap();
222 assert_eq!(projections.implementations.len(), 1);
223 assert_eq!(projections.deferred_to, "");
224 assert_eq!(crate::view::Grid::default().name(), "grid");
225 assert!(projections.implementations[0].starts_with("grid"));
226 let paragraphs = seams().iter().find(|s| s.name == "paragraphs").unwrap();
227 assert_eq!(paragraphs.deferred_to, "G-USE");
228 }
229
230 #[test]
231 fn the_formats_registry_matches_the_readers_and_the_writer() {
232 assert_eq!(FORMATS.len(), 2);
233 assert!(reflect::open(FIXTURE_XLSX, "fixture.xlsx").is_ok());
234 assert!(reflect::open(FIXTURE_ODS, "opendocument.ods").is_ok());
235 let readers: Vec<&str> = FORMATS
236 .iter()
237 .filter(|f| f.reads)
238 .map(|f| f.extension)
239 .collect();
240 assert_eq!(readers, ["xlsx", "ods"]);
241 let writers: Vec<&str> = FORMATS
242 .iter()
243 .filter(|f| f.writes)
244 .map(|f| f.extension)
245 .collect();
246 assert_eq!(writers, ["xlsx"], "the one writer is the OOXML writer");
247 let formats = seams()
248 .iter()
249 .find(|s| s.name == "formats and hosts")
250 .unwrap();
251 assert_eq!(formats.implementations.len(), FORMATS.len());
252 }
253
254 #[test]
255 fn the_file_door_holds_only_core_forms_and_refuses_from_the_catalogue() {
256 assert_eq!(HOST_PROFILES.len(), 1);
257 assert_eq!(FILE_DOOR.door, "file");
258 for sym in FILE_DOOR.forms {
259 let canonical = headtable::resolve_head_alias(sym);
260 assert!(
261 headtable::row(&canonical).is_some(),
262 "{sym} is not a form of the head table"
263 );
264 }
265 for call in FILE_DOOR.scaffold {
266 assert!(
267 headtable::row(call).is_none(),
268 "{call} is a scaffold call, not a core form"
269 );
270 }
271 assert_eq!(FILE_DOOR.refuses_with, "build-not-representable");
272 }
273
274 #[test]
275 fn the_projection_trait_is_the_language_s() {
276 let w: vla_lang::projection::Window = Window {
278 sheet: "Model".to_string(),
279 range: crate::sheet::parse_a1_range("A1:F20").unwrap(),
280 };
281 assert_eq!(w.range.cells(), 120);
282 }
283}