From 1714d7ee767010fda65cee42b891f08f934d53a9 Mon Sep 17 00:00:00 2001 From: Araozu Date: Thu, 20 Jun 2024 17:29:30 -0500 Subject: [PATCH] Add landpage components --- public/css/global.css | 3 + src/components/CodeEditor.astro | 11 ++ src/components/InteractiveCode.astro | 70 +---------- src/components/utils.ts | 70 +++++++++++ src/lexer/identifier_lexer.ts | 2 +- src/pages/index.astro | 170 +++++++++++++++++---------- tailwind.config.mjs | 1 + 7 files changed, 197 insertions(+), 130 deletions(-) create mode 100644 src/components/CodeEditor.astro create mode 100644 src/components/utils.ts diff --git a/public/css/global.css b/public/css/global.css index 031131d..2e8b152 100644 --- a/public/css/global.css +++ b/public/css/global.css @@ -17,6 +17,9 @@ src: url('/Iosevka/Bold.woff2') format('woff2'); } +:root { + --c-thp: #f472b6; +} :root { --c-bg: #121212; diff --git a/src/components/CodeEditor.astro b/src/components/CodeEditor.astro new file mode 100644 index 0000000..0874cec --- /dev/null +++ b/src/components/CodeEditor.astro @@ -0,0 +1,11 @@ +--- +import { trimAndDedent } from "./utils"; + +const {thpcode} = Astro.props; +--- + +
+
+
{trimAndDedent(thpcode).join("\n")}
+
+
diff --git a/src/components/InteractiveCode.astro b/src/components/InteractiveCode.astro index 4d650ae..3b62e89 100644 --- a/src/components/InteractiveCode.astro +++ b/src/components/InteractiveCode.astro @@ -2,77 +2,9 @@ import { lex } from "../lexer/lexer"; import type { Instruction } from "../thp_machine/machine_parser"; import { parse_str } from "../thp_machine/machine_parser"; +import { trimAndDedent } from "./utils"; const {code, steps} = Astro.props; -/** - * Performs the following: - * - Removes the first & last line, if they are empty - * - Picks the indentation level from the first non-white line - * - Dedents the following lines -*/ -function trimAndDedent(input: string): Array { - let lines = input.split("\n"); - - // Remove empty lines at the start - while (lines[0] === "") { - lines = lines.slice(1); - } - - // Get indentation level - let indentationLevel = 0; - for (const char of lines[0]!) { - if (char === " ") { - indentationLevel += 1; - } else { - break; - } - } - - // Enforce indentation, or trim - for (let i = 0; i < lines.length; i += 1) { - // If the line is empty, continue - const characters = lines[i]!.split(""); - if (characters.length === 0) { - continue; - } - - // If all characters are whitespace, append just a newline - const nonWhitespace = characters.find((x) => x !== " "); - if (nonWhitespace === undefined) { - lines[i] = ""; - continue; - } - - // Enforce indentation - if (characters.length < indentationLevel) { - throw new Error("Invalid indentation while parsing THP code: " + lines[i]); - } - let currentIndentation = 0; - for (const c of characters) { - if (c === " ") { currentIndentation += 1 } - else {break;} - } - if (currentIndentation < indentationLevel) { - throw new Error("Invalid indentation while parsing THP code: " + lines[i]); - } - - lines[i] = characters.slice(4).join(""); - } - - - // Remove empty lines at the end - let endPosition = lines.length - 1; - while (true) { - if (lines[endPosition] === "") { - lines = lines.slice(0, -1); - endPosition -= 1; - } else { - break; - } - } - - return lines; -} function highlightCode(lines: Array): string { let outLines: Array = []; diff --git a/src/components/utils.ts b/src/components/utils.ts new file mode 100644 index 0000000..d7548f7 --- /dev/null +++ b/src/components/utils.ts @@ -0,0 +1,70 @@ + +/** + * Performs the following: + * - Removes the first & last line, if they are empty + * - Picks the indentation level from the first non-white line + * - Dedents the following lines +*/ +export function trimAndDedent(input: string): Array { + let lines = input.split("\n"); + + // Remove empty lines at the start + while (lines[0] === "") { + lines = lines.slice(1); + } + + // Get indentation level + let indentationLevel = 0; + for (const char of lines[0]!) { + if (char === " ") { + indentationLevel += 1; + } else { + break; + } + } + + // Enforce indentation, or trim + for (let i = 0; i < lines.length; i += 1) { + // If the line is empty, continue + const characters = lines[i]!.split(""); + if (characters.length === 0) { + continue; + } + + // If all characters are whitespace, append just a newline + const nonWhitespace = characters.find((x) => x !== " "); + if (nonWhitespace === undefined) { + lines[i] = ""; + continue; + } + + // Enforce indentation + if (characters.length < indentationLevel) { + throw new Error("Invalid indentation while parsing THP code: " + lines[i]); + } + let currentIndentation = 0; + for (const c of characters) { + if (c === " ") { currentIndentation += 1 } + else {break;} + } + if (currentIndentation < indentationLevel) { + throw new Error("Invalid indentation while parsing THP code: " + lines[i]); + } + + lines[i] = characters.slice(4).join(""); + } + + + // Remove empty lines at the end + let endPosition = lines.length - 1; + while (true) { + if (lines[endPosition] === "") { + lines = lines.slice(0, -1); + endPosition -= 1; + } else { + break; + } + } + + return lines; +} \ No newline at end of file diff --git a/src/lexer/identifier_lexer.ts b/src/lexer/identifier_lexer.ts index 773e9d4..a531c52 100644 --- a/src/lexer/identifier_lexer.ts +++ b/src/lexer/identifier_lexer.ts @@ -34,7 +34,7 @@ export function scan_identifier(input: string, starting_position: number, is_dat } function check_keyword(value: string): string { - const keywords = ["throws", "extends", "constructor", "case", "static", "const", "enum", "union", "loop", "use", "break", "catch", "continue", "do", "else", "finally", "for", "fun", "if", "in", "fn", "nil", "return", "throw", "try", "while", "type", "match", "with", "of", "abstract", "class", "interface", "private", "pub", "override", "open", "init", "val", "var", "mut", "clone"]; + const keywords = ["throws", "extends", "constructor", "case", "static", "const", "enum", "union", "loop", "use", "break", "catch", "continue", "as", "do", "else", "finally", "for", "fun", "if", "in", "fn", "nil", "return", "throw", "try", "while", "type", "match", "with", "of", "abstract", "class", "interface", "private", "pub", "override", "open", "init", "val", "var", "mut", "clone"]; if (keywords.includes(value)) { return "keyword"; diff --git a/src/pages/index.astro b/src/pages/index.astro index 7fe69e9..3a55630 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -1,13 +1,14 @@ --- import BaseLayout from "../layouts/BaseLayout.astro"; import Navbar from "../components/Navbar.astro"; +import CodeEditor from "../components/CodeEditor.astro"; ---
@@ -21,7 +22,7 @@ import Navbar from "../components/Navbar.astro"; compiled to PHP

- Inspired by Rust, Zig and Swift, THP has a modern syntax, + Inspired by Rust, Zig and Kotlin, THP has a modern syntax, semantics, type system and stdlib.


@@ -46,49 +47,99 @@ import Navbar from "../components/Navbar.astro";
-
- +
+
+
+ - - - - - - - -
-
+ + + + + + + +
+
+
+
+
+
+ +
+
+

+ THP is actually typed +

+
+ +
+
+
+ THP enforces type safety at compile time and, at the programmer's + request, at runtime. +
+
+ Everything has a type. + There are generics. + No implicit type conversions. No mixed. + No client Any .Type inference included. +
+
+ All possible checks are made at compile time. Runtime checks + have a small performance penalty. +
+
+
+ Any { ... } + + // Compile error: Cannot use \`Any\` without an explicit cast + val result = mock() + // Ok + val result = mock() as String + `} /> +
@@ -100,29 +151,28 @@ import Navbar from "../components/Navbar.astro"; }); jar.updateCode( - `// Sum types -enum Animal { + `union Animal { Dog(String), Cat(String, Int), } -// Null safety -val cat_name = Post::get("cat_name") ?? "Michi" -val cat1 = Animal::Cat(cat_name, 9) +val cat_name = Post::get("cat_name") ?? "Michifu" +val my_cat = Animal::Cat(cat_name, 9) -// Errors as values, easy handling -val cat2 = try clone_cat(cat) else die("Not a cat") +try change_fur_color(cat) else die("Not a cat") -// Pattern matching match random_animal() -case Dog(name) { print("{name} has 1 live ") } -case Cat(name, lives) { print("{name} has {lives}") } - -// First class HTML-like templates & components - - welcome, {person.name} - -// And more!`, +case Dog(name) +{ + print("{name} has 1 live ") +} +case Cat(name, lives) { + print("{name} has {lives}") +}`, ); + diff --git a/tailwind.config.mjs b/tailwind.config.mjs index e21bfa2..8100db5 100644 --- a/tailwind.config.mjs +++ b/tailwind.config.mjs @@ -4,6 +4,7 @@ export default { theme: { extend: { colors: { + "c-thp": "var(--c-thp)", "c-bg": "var(--c-bg)", "c-text": "var(--c-text)", "c-text-2": "var(--c-text-2)",