1use std::sync::LazyLock;
11
12use crate::ui::pages::contact::claims::learn_figures;
13use crate::ui::pages::contact::content::{free_answer, ASSISTANT_GUIDE_URL, INSTALL_UNIX, INSTALL_WINDOWS, SOURCE_URL};
14use crate::ui::pages::studio_workbench::Shelf;
15use crate::ui::router::studio_file_url;
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq)]
19pub enum Install {
20 Unix,
21 Windows,
22}
23
24impl Install {
25 pub const ALL: &'static [Install] = &[Install::Unix, Install::Windows];
26
27 pub fn name(self) -> &'static str {
29 match self {
30 Install::Unix => "unix",
31 Install::Windows => "windows",
32 }
33 }
34
35 pub fn from_name(name: &str) -> Option<Install> {
36 Install::ALL.iter().copied().find(|install| install.name() == name)
37 }
38
39 pub fn switch_label(self) -> &'static str {
41 match self {
42 Install::Unix => "Using Windows?",
43 Install::Windows => "Using macOS or Linux?",
44 }
45 }
46
47 pub fn other(self) -> Install {
49 match self {
50 Install::Unix => Install::Windows,
51 Install::Windows => Install::Unix,
52 }
53 }
54}
55
56pub const AGENT_GUIDE_URL: &str = "https://logicaffeine.com/agent.txt";
59
60pub const SERVE_URL: &str = "http://localhost:8080";
62
63pub const CRATES_URL: &str = "https://logicaffeine.com/crates";
65
66pub const SYNTAX_MATRIX: &[&str] = &[
72 "The language on one page. Every statement is one English sentence.",
73 "Blocks: ## Main is the program. ## To add (a: Int, b: Int) -> Int: is a function.",
74 "## A Point has: with An x: Int. below is a struct. ## A Shape is one of: is an enum.",
75 "## Page /path is a web page. ## Route GET /api/x -> Seq of Todo: is an API route.",
76 "## Test: name is a test of a page. ## Theorem: name is a theorem for the prover.",
77 "Bind: Let x be 5. Let mutable n be 0. Let x: Int be 5. Change: Set n to n + 1.",
78 "Also: Increase n by 1. Decrease n by 1. Set p's x to 5. Set item i of xs to v.",
79 "Types: Int, Float, Text, Bool, Seq of Int, Map of Text to Int, Set of Int, some 30, none.",
80 "Make: a new Seq of Int, [1, 2, 3], a new Map of Text to Int, {1, 2, 3}, a new Point.",
81 "Read: item 1 of xs is the first item, length of xs, xs contains v, p's x, p.x.",
82 "Slice: items 2 through 4 of xs. Change a list or set: Push v to xs. Pop from xs into y.",
83 "Add v to s. Remove v from s. Arithmetic: x + y, x - y, x * y, x / y, x % y.",
84 "Text: \"Hi, {name}!\" fills the hole with name, a combined with b joins two Texts.",
85 "Compare: is equal to or ==, is not or !=, is less than or <, is greater than or >.",
86 "Also: is at most or <=, is at least or >=, is between lo and hi, is divisible by n.",
87 "Logic in a test: and, or, not. Choose: If c: then Otherwise If d: then Otherwise:.",
88 "A block is the lines indented four spaces under the colon.",
89 "Repeat: While c:, Repeat for x in xs:, Repeat for i from 1 to n:, Break.",
90 "Match: Inspect t: then When V (a): and Otherwise:. Options: some 30, none.",
91 "Filter: Let small be every n in xs where n is less than 4.",
92 "In place: Remove every t from todos where t's done.",
93 "Call: add(3, 7), or xs.f(a) for f(xs, a). A closure: (x: Int) -> x + 1. Return x.",
94 "Show x. prints x. Contracts: Let x: Int where x > 0 be 5. Assert that x is equal to 42.",
95 "Check that b is at least a. stops the program when it is not.",
96 "Time: 500ms, 2s, 5min, 1h, 2026-05-20, 9am, 2 weeks, 2026-05-20 at 4pm.",
97 "A page: State: holds Let draft be \"\". Actions: holds To add: and its steps.",
98 "View: is HTML. {draft} is a hole, on-click={add}, bind={draft}, {if c:}...{else:}...{end}.",
99 "Lists in a View: {for each t in todos, keyed by t's id:}...{end}. Style: is CSS, scoped.",
100 "Derived state: Let left always be length of todos. It recomputes after every turn.",
101 "A page test: Click \"#add\". Expect that the text of \"#n\" is equal to \"1\".",
102 "Logic mode: one sentence per line. Every dog barks. Some cat sleeps. No cat barks.",
103 "A theorem: Given: Every man is mortal. Given: Socrates is a man. Prove: He is mortal.",
104 "Then Proof: Auto. and the kernel certifies it.",
105];
106
107pub const CLONE_SOURCE: &str = "git clone https://github.com/Brahmastra-Labs/logicaffeine";
109
110pub fn prompt(install: Install) -> &'static [Line] {
114 static PROMPTS: LazyLock<[Vec<Line>; 2]> = LazyLock::new(|| [Install::Unix, Install::Windows].map(prompt_lines));
115 &PROMPTS[install as usize]
116}
117
118fn prompt_lines(install: Install) -> Vec<Line> {
119 use Line::*;
120 let (how, command) = match install {
121 Install::Unix => ("Install largo, the LOGOS command line tool, easy to install and lightweight:", INSTALL_UNIX),
122 Install::Windows => ("Install largo, the LOGOS command line tool, easy to install, lightweight, in PowerShell:", INSTALL_WINDOWS),
123 };
124 vec![
125 Say(agreed("LOGOS programmer instructions, for any coding agent (bring your own).")),
126 Say(agreed(format!("Source, examples and docs: {SOURCE_URL}"))),
127 Say(agreed(how)),
128 Run(command),
129 Say(agreed(format!("Then follow {AGENT_GUIDE_URL}, every step. It ends with a site running."))),
130 ]
131}
132
133pub fn prompt_text(install: Install) -> &'static str {
135 static TEXTS: LazyLock<[String; 2]> =
136 LazyLock::new(|| [Install::Unix, Install::Windows].map(|install| prompt(install).iter().map(Line::text).collect::<Vec<_>>().join("\n")));
137 &TEXTS[install as usize]
138}
139
140pub fn how() -> &'static Claim {
143 static HOW: LazyLock<Claim> = LazyLock::new(|| {
144 proven("Copy the prompt for your system into your coding agent. It installs largo and puts a LOGOS website on your screen.", &["landing_page", "llms_lock"])
145 });
146 &HOW
147}
148
149#[derive(Clone, Copy, Debug, PartialEq, Eq)]
152pub enum System {
153 MacOs,
154 Linux,
155 Windows,
156}
157
158impl System {
159 pub const ALL: [System; 3] = [System::MacOs, System::Linux, System::Windows];
160
161 pub fn name(self) -> &'static str {
162 match self {
163 System::MacOs => "macOS",
164 System::Linux => "Linux",
165 System::Windows => "Windows",
166 }
167 }
168
169 pub fn slug(self) -> &'static str {
171 match self {
172 System::MacOs => "macos",
173 System::Linux => "linux",
174 System::Windows => "windows",
175 }
176 }
177
178 pub fn install(self) -> Install {
180 match self {
181 System::Windows => Install::Windows,
182 System::MacOs | System::Linux => Install::Unix,
183 }
184 }
185
186 pub fn copy_label(self) -> String {
188 format!("{COPY_LABEL} for {}", self.name())
189 }
190
191 pub fn mark(self) -> &'static str {
194 match self {
195 System::MacOs => APPLE_MARK,
196 System::Linux => UBUNTU_MARK,
197 System::Windows => WINDOWS_MARK,
198 }
199 }
200}
201
202const APPLE_MARK: &str = "M12.152 6.896c-.948 0-2.415-1.078-3.96-1.04-2.04.027-3.91 1.183-4.961 3.014-2.117 3.675-.546 9.103 1.519 12.09 1.013 1.454 2.208 3.09 3.792 3.039 1.52-.065 2.09-.987 3.935-.987 1.831 0 2.35.987 3.96.948 1.637-.026 2.676-1.48 3.676-2.948 1.156-1.688 1.636-3.325 1.662-3.415-.039-.013-3.182-1.221-3.22-4.857-.026-3.04 2.48-4.494 2.597-4.559-1.429-2.09-3.623-2.324-4.39-2.376-2-.156-3.675 1.09-4.61 1.09zM15.53 3.83c.843-1.012 1.4-2.427 1.245-3.83-1.207.052-2.662.805-3.532 1.818-.78.896-1.454 2.338-1.273 3.714 1.338.104 2.715-.688 3.559-1.701";
203const UBUNTU_MARK: &str = "M17.61.455a3.41 3.41 0 0 0-3.41 3.41 3.41 3.41 0 0 0 3.41 3.41 3.41 3.41 0 0 0 3.41-3.41 3.41 3.41 0 0 0-3.41-3.41zM12.92.8C8.923.777 5.137 2.941 3.148 6.451a4.5 4.5 0 0 1 .26-.007 4.92 4.92 0 0 1 2.585.737A8.316 8.316 0 0 1 12.688 3.6 4.944 4.944 0 0 1 13.723.834 11.008 11.008 0 0 0 12.92.8zm9.226 4.994a4.915 4.915 0 0 1-1.918 2.246 8.36 8.36 0 0 1-.273 8.303 4.89 4.89 0 0 1 1.632 2.54 11.156 11.156 0 0 0 .559-13.089zM3.41 7.932A3.41 3.41 0 0 0 0 11.342a3.41 3.41 0 0 0 3.41 3.409 3.41 3.41 0 0 0 3.41-3.41 3.41 3.41 0 0 0-3.41-3.41zm2.027 7.866a4.908 4.908 0 0 1-2.915.358 11.1 11.1 0 0 0 7.991 6.698 11.234 11.234 0 0 0 2.422.249 4.879 4.879 0 0 1-.999-2.85 8.484 8.484 0 0 1-.836-.136 8.304 8.304 0 0 1-5.663-4.32zm11.405.928a3.41 3.41 0 0 0-3.41 3.41 3.41 3.41 0 0 0 3.41 3.41 3.41 3.41 0 0 0 3.41-3.41 3.41 3.41 0 0 0-3.41-3.41z";
204const WINDOWS_MARK: &str = "M3 3h8.5v8.5H3zM12.5 3H21v8.5h-8.5zM3 12.5h8.5V21H3zM12.5 12.5H21V21h-8.5z";
205
206pub const INSTALL_HEADING: &str = "Install largo yourself";
209
210pub fn install_commands() -> [(&'static str, &'static str); 2] {
211 [("macOS and Linux", INSTALL_UNIX), ("Windows", INSTALL_WINDOWS)]
212}
213
214pub const HEADING: [&str; 3] = ["Code we can all read.", "Logic and mathematics built in.", "Bring your own agent."];
216
217pub const COPY_LABEL: &str = "Copy agent instructions";
219
220pub const INSTRUCTIONS_ID: &str = "agent-instructions";
222
223pub mod said {
225 pub const COPIED: &str = "Copied";
227 pub const COPIED_STATUS: &str = "Copied the agent instructions.";
229 pub const COPY_REFUSED: &str = "This browser blocked copying. The instructions are selected, so press Ctrl+C or Command+C.";
231 pub const COMMAND_COPIED: &str = "Copied";
233
234 pub fn all() -> Vec<(&'static str, &'static str)> {
236 vec![
237 ("the copy button once pressed", COPIED),
238 ("the copy status", COPIED_STATUS),
239 ("the copy status when the browser refuses", COPY_REFUSED),
240 ("an install command's copy button once pressed", COMMAND_COPIED),
241 ]
242 }
243}
244
245pub enum Evidence {
247 Suites(&'static [&'static str]),
249 Agreement,
251}
252
253pub struct Claim {
255 pub text: String,
256 pub evidence: Evidence,
257}
258
259fn proven(text: impl Into<String>, suites: &'static [&'static str]) -> Claim {
260 Claim { text: text.into(), evidence: Evidence::Suites(suites) }
261}
262
263fn agreed(text: impl Into<String>) -> Claim {
264 Claim { text: text.into(), evidence: Evidence::Agreement }
265}
266
267pub enum Line {
269 Step(&'static str),
271 Say(Claim),
273 Rule(Claim),
275 Agree(&'static str),
277 Run(&'static str),
279 Open(String),
281 Blank,
282}
283
284const INDENT: &str = " ";
287
288impl Line {
289 pub fn text(&self) -> String {
291 match self {
292 Line::Step(title) => title.to_string(),
293 Line::Say(claim) => claim.text.clone(),
294 Line::Rule(claim) => format!("- {}", claim.text),
295 Line::Agree(text) => format!("- {text}"),
296 Line::Run(command) => format!("{INDENT}{command}"),
297 Line::Open(url) => format!("{INDENT}{url}"),
298 Line::Blank => String::new(),
299 }
300 }
301}
302
303fn studio_address(example: &str) -> String {
305 format!("https://logicaffeine.com{}", studio_file_url(example))
306}
307
308pub fn instructions() -> &'static [Line] {
314 static LINES: LazyLock<Vec<Line>> = LazyLock::new(|| {
315 use Line::*;
316 vec![
317 Say(proven("LOGOS programmer instructions, for any coding agent (bring your own).", &["landing_page", "llms_lock"])),
318 Say(proven("LOGOS is the English programming language from logicaffeine.com.", &["doc_examples", "code_examples_all_tiers"])),
319 Say(proven("LOGOS is lightweight and modular, and largo, its command line tool, is easy to install.", &["installer_docs_lock", "landing_page"])),
320 Blank,
321 Step("1. Get the source"),
322 Say(agreed("Source, examples and docs are on GitHub. Clone it, and read it when a question comes up:")),
323 Run(CLONE_SOURCE),
324 Say(proven(format!("Its crates, one per part of the language, are listed at {CRATES_URL}."), &["crates_page_lock", "landing_page"])),
325 Blank,
326 Step("2. Install largo, the LOGOS command line tool"),
327 Say(agreed("On macOS and Linux:")),
328 Run(INSTALL_UNIX),
329 Say(agreed("On Windows, in PowerShell:")),
330 Run(INSTALL_WINDOWS),
331 Say(proven("If the shell can't find largo, open a new terminal or add its folder to PATH.", &["installer_docs_lock"])),
332 Say(agreed("Then check the install:")),
333 Run("largo --version"),
334 Run("largo doctor"),
335 Blank,
336 Step("3. Start a website"),
337 Run("largo new mysite --site"),
338 Run("cd mysite"),
339 Run("largo test"),
340 Run("largo serve"),
341 Say(proven("The front page is pages/app.lg: a counter with a button, written in English.", &["landing_page"])),
342 Say(proven("largo test ran the ## Test at the end of the page: it clicks the button and counts.", &["landing_page"])),
343 Say(proven("largo serve keeps running, so run it in a second terminal or in the background.", &["landing_page"])),
344 Say(proven(format!("The site is at {SERVE_URL}. Each save rebuilds the page and reloads it."), &["landing_page"])),
345 Say(agreed("Report that the site is up before changing anything.")),
346 Blank,
347 Step("4. Learn the language before you write it"),
348 Say(proven(format!("Read {ASSISTANT_GUIDE_URL}, every LOGOS guide in one file."), &["llms_lock"])),
349 Say(proven("largo new also wrote AGENTS.md in the project, the language taught to an agent. Read it.", &["landing_page"])),
350 Say(proven("Use a command only if largo --help lists it, and say so when one is missing.", &["landing_page"])),
351 Say(agreed("Four rules to start with:")),
352 Rule(proven("A statement is one English sentence, as in Let x be 5.", &["doc_examples", "landing_page"])),
353 Rule(proven("Let names a value and Set changes it, as in Set x to 6.", &["phase_interpret_mode", "landing_page"])),
354 Rule(proven("Lists count from 1: item 1 of xs is the first item.", &["phase22_index", "landing_page"])),
355 Rule(proven("Compare with is equal to, as in If name is equal to \"Ada\":", &["correctness_is_equality", "landing_page"])),
356 Blank,
357 Say(agreed("The language on one page:")),
358 Say(proven("Blocks: ## Main is the program. ## To add (a: Int, b: Int) -> Int: is a function.", &["teach_parity", "doc_examples"])),
359 Say(proven("## A Point has: with An x: Int. below is a struct. ## A Shape is one of: is an enum.", &["teach_parity", "doc_examples"])),
360 Say(proven("## Page /path is a web page. ## Route GET /api/x -> Seq of Todo: is an API route.", &["teach_parity", "doc_examples"])),
361 Say(proven("## Test: name is a test of a page. ## Theorem: name is a theorem for the prover.", &["teach_parity", "doc_examples"])),
362 Say(proven("Bind: Let x be 5. Let mutable n be 0. Let x: Int be 5. Change: Set n to n + 1.", &["teach_parity", "doc_examples"])),
363 Say(proven("Also: Increase n by 1. Decrease n by 1. Set p's x to 5. Set item i of xs to v.", &["teach_parity", "doc_examples"])),
364 Say(proven("Types: Int, Float, Text, Bool, Seq of Int, Map of Text to Int, Set of Int, some 30, none.", &["teach_parity", "doc_examples"])),
365 Say(proven("Make: a new Seq of Int, [1, 2, 3], a new Map of Text to Int, {1, 2, 3}, a new Point.", &["teach_parity", "doc_examples"])),
366 Say(proven("Read: item 1 of xs is the first item, length of xs, xs contains v, p's x, p.x.", &["teach_parity", "doc_examples"])),
367 Say(proven("Slice: items 2 through 4 of xs. Change a list or set: Push v to xs. Pop from xs into y.", &["teach_parity", "doc_examples"])),
368 Say(proven("Add v to s. Remove v from s. Arithmetic: x + y, x - y, x * y, x / y, x % y.", &["teach_parity", "doc_examples"])),
369 Say(proven("Text: \"Hi, {name}!\" fills the hole with name, a combined with b joins two Texts.", &["teach_parity", "doc_examples"])),
370 Say(proven("Compare: is equal to or ==, is not or !=, is less than or <, is greater than or >.", &["teach_parity", "doc_examples"])),
371 Say(proven("Also: is at most or <=, is at least or >=, is between lo and hi, is divisible by n.", &["teach_parity", "doc_examples"])),
372 Say(proven("Logic in a test: and, or, not. Choose: If c: then Otherwise If d: then Otherwise:.", &["teach_parity", "doc_examples"])),
373 Say(proven("A block is the lines indented four spaces under the colon.", &["teach_parity", "doc_examples"])),
374 Say(proven("Repeat: While c:, Repeat for x in xs:, Repeat for i from 1 to n:, Break.", &["teach_parity", "doc_examples"])),
375 Say(proven("Match: Inspect t: then When V (a): and Otherwise:. Options: some 30, none.", &["teach_parity", "doc_examples"])),
376 Say(proven("Filter: Let small be every n in xs where n is less than 4.", &["teach_parity", "doc_examples"])),
377 Say(proven("In place: Remove every t from todos where t's done.", &["teach_parity", "doc_examples"])),
378 Say(proven("Call: add(3, 7), or xs.f(a) for f(xs, a). A closure: (x: Int) -> x + 1. Return x.", &["teach_parity", "doc_examples"])),
379 Say(proven("Show x. prints x. Contracts: Let x: Int where x > 0 be 5. Assert that x is equal to 42.", &["teach_parity", "doc_examples"])),
380 Say(proven("Check that b is at least a. stops the program when it is not.", &["teach_parity", "doc_examples"])),
381 Say(proven("Time: 500ms, 2s, 5min, 1h, 2026-05-20, 9am, 2 weeks, 2026-05-20 at 4pm.", &["teach_parity", "doc_examples"])),
382 Say(proven("A page: State: holds Let draft be \"\". Actions: holds To add: and its steps.", &["teach_parity", "doc_examples"])),
383 Say(proven("View: is HTML. {draft} is a hole, on-click={add}, bind={draft}, {if c:}...{else:}...{end}.", &["teach_parity", "doc_examples"])),
384 Say(proven("Lists in a View: {for each t in todos, keyed by t's id:}...{end}. Style: is CSS, scoped.", &["teach_parity", "doc_examples"])),
385 Say(proven("Derived state: Let left always be length of todos. It recomputes after every turn.", &["teach_parity", "doc_examples"])),
386 Say(proven("A page test: Click \"#add\". Expect that the text of \"#n\" is equal to \"1\".", &["teach_parity", "doc_examples"])),
387 Say(proven("Logic mode: one sentence per line. Every dog barks. Some cat sleeps. No cat barks.", &["teach_parity", "doc_examples"])),
388 Say(proven("A theorem: Given: Every man is mortal. Given: Socrates is a man. Prove: He is mortal.", &["teach_parity", "doc_examples"])),
389 Say(proven("Then Proof: Auto. and the kernel certifies it.", &["teach_parity", "doc_examples"])),
390 Blank,
391 Step("5. Build the site"),
392 Say(agreed("Change pages/app.lg one thing at a time. After every change, run:")),
393 Run("largo check"),
394 Run("largo test"),
395 Say(proven("largo check explains each mistake it finds in plain English, with its line.", &["check_json", "diagnostic_surfaces_lock", "landing_page"])),
396 Say(proven("largo fmt sets the source in the standard layout.", &["fmt"])),
397 Say(proven("A page is its State, its Actions, its View in HTML with {holes}, and its Style in CSS.", &["landing_page"])),
398 Say(proven("For a backend of ## Route blocks under the pages, scaffold with largo new mysite --web.", &["landing_page"])),
399 Blank,
400 Step("6. Programs"),
401 Run("largo new hello"),
402 Run("cd hello"),
403 Run("largo run --interpret"),
404 Say(proven("It prints Hello, world! The program is src/main.lg and the manifest is Largo.toml.", &["landing_page", "phase_interpret_mode"])),
405 Say(proven("--interpret runs it in the interpreter, which needs no Rust toolchain.", &["landing_page", "phase_interpret_mode"])),
406 Say(proven("largo new also wrote a .gitignore, so git init makes the folder a repository.", &["landing_page"])),
407 Blank,
408 Step("7. Logic"),
409 Run("largo logic \"Every student read a book.\" --all-readings"),
410 Say(proven("prints every reading of the sentence in first-order logic.", &["logic", "phase12_ambiguity", "landing_page"])),
411 Say(proven("largo prove proves each ## Theorem block in a file (Given, Prove and Proof lines),", &["prove", "landing_page"])),
412 Say(proven("and the type theory kernel certifies every proof it reports:", &["prove", "phase69_kernel_coc"])),
413 Run("largo prove theorem.lg"),
414 Blank,
415 Step("8. Math"),
416 Say(proven("largo prove also proves the theorems of a ## Theory block from its axioms.", &["prove", "landing_page"])),
417 Say(proven("Inductive types, Definition, Check and Eval run in the Studio's Math mode:", &["e2e_studio_examples", "studio_example_contract"])),
418 Open(studio_address("/examples/math/natural-numbers.logos")),
419 Blank,
420 Step("9. Hardware"),
421 Say(proven("The Studio's Hardware mode turns an English spec into a SystemVerilog assertion", &["hardware_examples", "phase_hw_sva_2023"])),
422 Say(proven("and checks that the assertion matches the spec:", &["hardware_examples", "landing_page"])),
423 Open(studio_address("/examples/hardware/handshake.hw")),
424 Say(proven("The command line release has no hardware command yet.", &["landing_page"])),
425 Blank,
426 Step("10. Working with the user"),
427 Agree("Take small steps. Change one thing, run it, and report the output."),
428 Agree("Never report that something works before running it."),
429 Agree("Show the LOGOS written. The user reads it as English, so keep it plain."),
430 Agree("When a sentence can mean two things, ask which one is meant."),
431 Agree("Commit each step that runs, so there is always a way back."),
432 ]
433 });
434 &LINES
435}
436
437pub fn instructions_text() -> &'static str {
439 static TEXT: LazyLock<String> = LazyLock::new(|| instructions().iter().map(Line::text).collect::<Vec<_>>().join("\n"));
440 &TEXT
441}
442
443pub fn shelf() -> &'static Shelf {
448 static SHELF: Shelf = Shelf {
449 opens: "/examples/code/web/website.logos",
450 files: &[
451 "/examples/code/web/website.logos",
452 "/examples/code/basics/control-flow.logos",
453 "/examples/code/verification/refinement.logos",
454 "/examples/code/distributed/merge.logos",
455 "/examples/logic/prover-demo.logic",
456 "/examples/math/auto-tactic.logos",
457 "/examples/hardware/handshake.hw",
458 ],
459 };
460 &SHELF
461}
462
463pub struct Usually {
466 pub name: &'static str,
467 pub source: &'static str,
468}
469
470#[derive(Clone, Copy, Debug, PartialEq, Eq)]
473pub enum Status {
474 Ships,
475 InTheStudio,
476 Partial,
477 NextRelease,
478}
479
480impl Status {
481 pub fn label(self) -> &'static str {
482 match self {
483 Status::Ships => "In largo",
484 Status::InTheStudio => "In the Studio",
485 Status::Partial => "In part",
486 Status::NextRelease => "Next release",
487 }
488 }
489}
490
491#[derive(Clone, Copy, Debug, PartialEq, Eq)]
493pub enum Uses {
494 Command(&'static str),
495 Emit(&'static str),
496}
497
498pub struct Card {
500 pub kind: &'static str,
501 pub usually: &'static [Usually],
502 pub logos: Claim,
503 pub tags: &'static [Status],
504 pub uses: &'static [Uses],
505 pub try_it: Option<&'static str>,
507}
508
509impl Card {
510 pub fn usually_names(&self) -> String {
512 self.usually.iter().map(|tool| tool.name).collect::<Vec<_>>().join(", ")
513 }
514}
515
516pub const COMPARE_HEADING: &str = "How LOGOS compares";
517
518pub fn compare_lead() -> &'static Claim {
520 static LEAD: LazyLock<Claim> =
521 LazyLock::new(|| proven("Eight kinds of work, what each usually takes, and what LOGOS does there.", &["landing_page"]));
522 &LEAD
523}
524
525const PYTHON: Usually = Usually { name: "Python", source: "https://docs.python.org/3/" };
526const RUST: Usually = Usually { name: "Rust", source: "https://www.rust-lang.org/" };
527const C: Usually = Usually { name: "C", source: "https://www.open-std.org/jtc1/sc22/wg14/" };
528const LEAN: Usually = Usually { name: "Lean 4", source: "https://lean-lang.org/" };
529const ROCQ: Usually = Usually { name: "Rocq", source: "https://rocq-prover.org/" };
530const DAFNY: Usually = Usually { name: "Dafny", source: "https://dafny.org/" };
531const TLA: Usually = Usually { name: "TLA+", source: "https://lamport.azurewebsites.net/tla/tla.html" };
532const PROLOG: Usually = Usually { name: "Prolog", source: "https://www.iso.org/standard/21413.html" };
533const ACE: Usually = Usually { name: "Attempto Controlled English", source: "https://attempto.ifi.uzh.ch/site/" };
534const SYSTEMVERILOG: Usually = Usually { name: "SystemVerilog", source: "https://standards.ieee.org/ieee/1800/7743/" };
535const CHISEL: Usually = Usually { name: "Chisel", source: "https://www.chisel-lang.org/" };
536const CUDA: Usually = Usually { name: "CUDA", source: "https://docs.nvidia.com/cuda/" };
537const TYPESCRIPT: Usually = Usually { name: "TypeScript", source: "https://www.typescriptlang.org/" };
538const JAVASCRIPT: Usually = Usually { name: "JavaScript", source: "https://tc39.es/ecma262/" };
539const ELIXIR: Usually = Usually { name: "Elixir", source: "https://elixir-lang.org/" };
540const ERLANG: Usually = Usually { name: "Erlang", source: "https://www.erlang.org/" };
541const AUTOMERGE: Usually = Usually { name: "Automerge", source: "https://automerge.org/" };
542
543pub fn compare() -> &'static [Card] {
548 static CARDS: LazyLock<Vec<Card>> = LazyLock::new(|| {
549 vec![
550 Card {
551 kind: "General purpose",
552 usually: &[PYTHON, RUST, C],
553 logos: proven(
554 "English programs, checked before they run, built through Rust, C or WebAssembly.",
555 &["code_examples_all_tiers", "benchmark_logos_tiers_lock", "largo_build_emit_c"],
556 ),
557 tags: &[Status::Ships],
558 uses: &[Uses::Command("build"), Uses::Emit("c"), Uses::Emit("wasm")],
559 try_it: Some("/examples/code/basics/control-flow.logos"),
560 },
561 Card {
562 kind: "Proof assistants",
563 usually: &[LEAN, ROCQ],
564 logos: proven(
565 "Theorems in English, checked by a kernel whose integers are Lean's.",
566 &["dag_dual_agreement", "axiom_footprint_lean_parity", "definition_kernel"],
567 ),
568 tags: &[Status::InTheStudio],
569 uses: &[Uses::Command("lean")],
570 try_it: Some("/examples/math/auto-tactic.logos"),
571 },
572 Card {
573 kind: "Verification",
574 usually: &[DAFNY, TLA],
575 logos: proven(
576 "Refinements and assertions checked as the program is built.",
577 &["e2e_refinement", "phase25_assertions", "phase43_refinement"],
578 ),
579 tags: &[Status::Ships],
580 uses: &[Uses::Command("check"), Uses::Command("verify")],
581 try_it: Some("/examples/code/verification/refinement.logos"),
582 },
583 Card {
584 kind: "Logic and controlled English",
585 usually: &[PROLOG, ACE],
586 logos: proven(
587 "Sentences become first-order logic, with scope and every reading.",
588 &["logic", "logic_determiner_readings", "modal_scope_tests"],
589 ),
590 tags: &[Status::InTheStudio],
591 uses: &[Uses::Command("logic")],
592 try_it: Some("/examples/logic/prover-demo.logic"),
593 },
594 Card {
595 kind: "Hardware",
596 usually: &[SYSTEMVERILOG, CHISEL],
597 logos: proven(
598 "English specs become SystemVerilog assertions, programs become circuits.",
599 &["phase_hw_fol_to_sva", "phase_hw_sva_roundtrip", "caravel_signoff_lock", "sky130_deep_signoff_lock"],
600 ),
601 tags: &[Status::InTheStudio],
602 uses: &[Uses::Command("bringup")],
603 try_it: Some("/examples/hardware/handshake.hw"),
604 },
605 Card {
606 kind: "GPU",
607 usually: &[CUDA],
608 logos: proven(
609 "Transformers written as tensor sentences, lowered to CUDA, FPGAs and Tenstorrent.",
610 &["cuda_aot_lock", "cuda_attention_gqa_lock", "int8_decode_lock", "decode_board_lock"],
611 ),
612 tags: &[Status::Ships],
613 uses: &[Uses::Emit("cuda"), Uses::Emit("tenstorrent")],
614 try_it: None,
615 },
616 Card {
617 kind: "Web",
618 usually: &[TYPESCRIPT, JAVASCRIPT],
619 logos: proven(
620 "Pages, components and typed routes in English, tested where they run.",
621 &["lgx_check_lock", "lgx_constructs_lock", "serve_fullstack"],
622 ),
623 tags: &[Status::InTheStudio],
624 uses: &[Uses::Command("serve"), Uses::Command("test")],
625 try_it: Some("/examples/code/web/website.logos"),
626 },
627 Card {
628 kind: "Concurrency and distributed",
629 usually: &[ELIXIR, ERLANG, AUTOMERGE],
630 logos: proven(
631 "Tasks and channels in English, collections that merge without conflict.",
632 &["concurrency_aot", "e2e_crdt", "converge_crdt_lock"],
633 ),
634 tags: &[Status::Ships],
635 uses: &[Uses::Command("run")],
636 try_it: Some("/examples/code/distributed/merge.logos"),
637 },
638 ]
639 });
640 &CARDS
641}
642
643pub const LIBRARY_HEADING: &str = "What comes with LOGOS";
644
645pub struct LibraryFigures {
649 pub modules: usize,
650 pub green: usize,
651 pub in_scope: usize,
652}
653
654const PARITY_LEDGER: &str = include_str!("../../../../../../benchmarks/parity/PARITY_LEDGER.md");
655
656pub fn library_figures() -> LibraryFigures {
657 let parity = PARITY_LEDGER.lines().find(|line| line.contains("**Correctness parity:**")).expect("the ledger states its correctness parity");
658 let inner = &parity[parity.find('(').unwrap() + 1..parity.find(')').unwrap()];
659 let numbers: Vec<usize> = inner.split(|c: char| !c.is_ascii_digit()).filter(|w| !w.is_empty()).filter_map(|w| w.parse().ok()).collect();
660 LibraryFigures { modules: logicaffeine_compile::loader::prelude_module_sources().len(), green: numbers[0], in_scope: numbers[1] }
661}
662
663
664pub fn library() -> &'static [Claim] {
666 static LINES: LazyLock<Vec<Claim>> = LazyLock::new(|| {
667 let figures = library_figures();
668 vec![
669 proven(
670 format!("{} modules written in LOGOS, auto-imported as a program uses them.", figures.modules),
671 &["import_scan_lock", "phase36_modules", "crypto_stdlib"],
672 ),
673 proven(
674 format!(
675 "{} of {} capabilities of the C, Python, Rust, Go and Java standard libraries, checked against their sources.",
676 figures.green, figures.in_scope
677 ),
678 &["blas_stdlib", "crypto_stdlib", "http_stdlib"],
679 ),
680 ]
681 });
682 &LINES
683}
684
685pub fn features() -> &'static [Claim] {
687 static LINES: LazyLock<Vec<Claim>> = LazyLock::new(|| {
688 vec![
689 proven("Tests, properties and replays, written in the language.", &["property_test_lock", "tests_index_lock", "replay_lock"]),
690 proven("A failing run replays, and the debugger steps backward.", &["replay_lock", "e2e_deterministic_replay"]),
691 proven("Import joins files. The type checker runs on every join.", &["import_hygiene", "phase36_modules", "lgx_check_lock"]),
692 proven("Infinitesimals, hyperreals and exact reals, compiled to Rust.", &["hyperreal_closure", "hyperreal_functions", "exact_by_context"]),
693 proven("Theorems check in a kernel whose integers are Lean's.", &["dag_dual_agreement", "axiom_footprint_lean_parity"]),
694 proven("HTTP served natively, with verified TLS.", &["http_lifecycle_lock", "tcp_tls_lock"]),
695 proven("One scheduler runs tasks on C, RISC-V and GPU.", &["c_family_scheduler_conformance_lock", "c_concurrency_scheduler_lock"]),
696 ]
697 });
698 &LINES
699}
700
701pub struct Faq {
703 pub question: &'static str,
704 pub answer: Claim,
705 pub link: Option<(&'static str, &'static str)>,
707}
708
709pub fn faq() -> &'static [Faq] {
710 static FAQ: LazyLock<Vec<Faq>> = LazyLock::new(|| {
711 let learn = learn_figures();
712 vec![
713 Faq { question: "Is it really free?", answer: proven(free_answer(), &["contact_page", "version_lock"]), link: None },
714 Faq {
715 question: "Do I need to know logic already?",
716 answer: proven(
717 format!(
718 "No. Learn teaches it step by step, in {} modules and {} exercises, free in the browser.",
719 learn.modules, learn.exercises
720 ),
721 &["learn_curriculum"],
722 ),
723 link: None,
724 },
725 Faq {
726 question: "Which coding agents can use the instructions?",
727 answer: agreed(
728 "Any agent that can read a web page and run commands in a terminal, such as Claude Code, Cursor or \
729 Codex. The instructions are plain text, so they paste into any of them.",
730 ),
731 link: None,
732 },
733 Faq {
734 question: "Where is the source?",
735 answer: agreed("On GitHub: github.com/Brahmastra-Labs/logicaffeine"),
736 link: Some(("github.com/Brahmastra-Labs/logicaffeine", SOURCE_URL)),
737 },
738 ]
739 });
740 &FAQ
741}
742
743pub fn every_claim() -> Vec<(String, &'static Evidence)> {
747 let lines = instructions().iter().filter_map(|line| match line {
748 Line::Say(claim) | Line::Rule(claim) => Some(claim),
749 _ => None,
750 });
751 let hows = std::iter::once(how());
752 let cards = std::iter::once(compare_lead()).chain(compare().iter().map(|card| &card.logos));
753 let library = library().iter().chain(features().iter());
754 let answers = faq().iter().map(|faq| &faq.answer);
755 lines.chain(hows).chain(cards).chain(library).chain(answers).map(|claim| (claim.text.clone(), &claim.evidence)).collect()
756}