Files
hi-language.github.io/index.html

458 lines
15 KiB
HTML

<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hi: A Symbolic Syntax for JavaScript</title>
<!-- Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Google Fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;600&family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet">
<!-- Markdown & Highlighting Styles -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/github-markdown-css@5.8.1/github-markdown-light.min.css"/>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/styles/github.min.css"/>
<!-- Lucide Icons -->
<script src="https://unpkg.com/lucide@latest"></script>
<!-- Markdown-it and Highlight.js -->
<script src="https://cdn.jsdelivr.net/npm/markdown-it@14.1.0/dist/markdown-it.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/highlightjs/cdn-release@11.9.0/build/highlight.min.js"></script>
<style>
body {
font-family: 'Poppins', sans-serif;
background-color: #f9fafb; /* bg-gray-50 */
}
.markdown-body {
font-size: 14px;
line-height: 1.7;
background-color: transparent;
}
.markdown-body h1, .markdown-body h2, .markdown-body h3 {
font-family: 'Poppins', sans-serif;
font-weight: 600;
border-bottom-color: #e5e7eb; /* border-gray-200 */
}
.markdown-body pre {
background-color: #ffffff;
border: 1px solid #e5e7eb;
border-radius: 0.75rem;
padding: 1rem;
overflow-x: auto;
}
.markdown-body code {
font-family: 'JetBrains Mono', monospace;
font-size: 13px;
font-variant-ligatures: none;
}
:not(pre) > code {
font-size: 85%;
padding: .2em .4em;
margin: 0;
border-radius: 6px;
background-color: rgba(175, 184, 193, 0.2);
}
.hi-button {
font-family: 'JetBrains Mono', monospace;
}
</style>
</head>
<body class="text-gray-900 selection:bg-cyan-400/20">
<header class="sticky top-0 z-20 bg-white/80 backdrop-blur-sm border-b border-gray-200">
<div class="mx-auto w-full max-w-4xl px-4 py-3 flex items-center justify-between">
<button class="hi-button text-2xl font-bold text-gray-900 px-4 py-2 rounded-lg cursor-default transition-all duration-300 hover:bg-gray-100">
Hi
</button>
<a href="https://github.com/hi-language" target="_blank" rel="noopener noreferrer" title="View GitHub Organization" class="text-gray-600 hover:text-gray-900 transition-colors p-2 rounded-lg hover:bg-gray-100">
<i data-lucide="github" class="h-5 w-5"></i>
</a>
</div>
</header>
<main class="w-full min-h-screen flex flex-col items-center p-4 sm:p-8">
<div id="content" class="markdown-body w-full max-w-4xl">
<!-- Markdown content will be rendered here -->
</div>
</main>
<script>
const markdownContent = `
# A Symbolic Syntax for JavaScript
**Hi** is a symbolic frontend for JavaScript, designed for code golfing and improved AI interaction. It transpiles to standard JS, providing full access to its powerful engine and the entire NPM ecosystem, but with a syntax that prioritizes symbols over keywords.
The underscore \`_\` is the global output function, transpiling to \`console.log\`.
\`\`\`javascript
_("Hi world")
\`\`\`
## Declaration and Assignment
Variable lifecycle is split into two distinct symbolic operations, providing a more concise alternative to \`let\`/\`const\` and subsequent assignment.
- \`:\` **Declaration**: Binds a name in the current scope (like \`let\`).
- \`=\` **Assignment**: Reassigns the value of an existing name.
\`\`\`javascript
version: 1.0 // Declaration and initialization
version = 1.1 // Assignment
\`\`\`
## The Block: Unifying Objects and Functions
The **Block** (\`{}\`) is Hi's foundational structure, unifying data objects and executable functions into a single concept. It is a sequence of expressions that can be invoked with \`()\`.
### As a Data Structure (Object)
A block can hold \`key: value\` pairs, transpiling to a standard JavaScript object. A \`#\` prefix denotes a private property.
\`\`\`javascript
player: {
name: "Orion"
#hp: 100
}
_(player.name) // "Orion"
_(player.hp) // -0 (null) because #hp is private
\`\`\`
### As Executable Code (Function)
Invoking a block with \`()\` executes its expressions. The value of the last expression is implicitly returned. This transpiles to a JavaScript function.
\`\`\`javascript
// Simple invocation
sayHi: { _("Hi") }
sayHi() // Prints "Hi"
// With parameters and return value
add: (a, b) { a + b }
_(add(2, 3)) // Prints 5
\`\`\`
### As a Hybrid (Factory/Class)
A block containing both data and logic acts as a natural factory. The context symbol \`@\` (representing JS \`this\`) can be used to return the newly created instance.
\`\`\`javascript
createPlayer: (name) {
name: name,
hp: 100
@ // Return the new block instance
}
player1: createPlayer("Orion")
_(player1.name) // "Orion"
_(player1.hp) // 100
\`\`\`
### Expression Separators
Newlines act as implicit separators. Commas (\`,\`) or semicolons (\`;\`) are required for single-line blocks.
\`\`\`javascript
// Multi-line
point: {
x: 10
y: 20
}
// Single-line
point: { x: 10, y: 20 }
\`\`\`
## Arrow Expressions
To maintain familiarity and leverage powerful JS idioms, Hi directly adopts the arrow function syntax. It serves as a shorthand for a Block that immediately returns an expression.
It's a direct replacement for \`(params) { ^ expression }\`.
\`\`\`javascript
// Standard block
add: (a, b) { ^ a + b }
// Equivalent Arrow Expression
add: (a, b) => a + b
// Directly uses JS array methods
numbers: [1, 2, 3]
doubled: numbers.map((n) => n * 2)
_(doubled) // [2, 4, 6]
\`\`\`
## Booleans and Equality
Hi dispenses with boolean keywords in favor of canonical numeric values, which map directly to JavaScript's truthiness model.
- \`0\` is **falsy** (transpiles to \`false\`).
- \`!0\` is **truthy** (transpiles to \`true\`).
- \`-0\` represents null/undefined values.
- All other non-zero numbers, and any non-empty string, block, or array are "truthy", consistent with JS behavior.
- The \`==\` operator performs strict equality comparison (transpiles to JavaScript's \`===\`).
## Conditional Expressions
Hi uses a single ternary-like expression for all conditional logic, which transpiles to JS \`if/else\` statements or ternary operators.
\`\`\`javascript
// A simple 'if' to execute code conditionally
status: "active"
(status == "active") ? { _("User is active.") }
\`\`\`
You can provide an \`else\` branch using the colon (\`:\`) symbol.
\`\`\`javascript
// if / else
isOnline: !0
(isOnline == !0) ? { _("Online") } : { _("Offline") } // Prints "Online"
\`\`\`
This structure is an *expression* that always evaluates to a value, allowing the result to be directly assigned.
\`\`\`javascript
// if / else returning a value
result: (1 > 2) ? { "A" } : { "B" } // result is "B"
\`\`\`
Expressions can be chained for \`if / else if / else\` logic.
\`\`\`javascript
// if / else if / else
score: 75
grade: (score >= 90) ? { "A" }
: (score >= 80) ? { "B" }
: (score >= 70) ? { "C" }
: { "D" }
_(grade) // Prints "C"
\`\`\`
If a condition is false and no \`else\` branch is provided, the expression evaluates to \`-0\` (null).
## Data Structures
Hi provides a concise syntax for working with JavaScript's native data structures.
### Arrays
Hi arrays are JavaScript arrays. They are 0-indexed lists supporting all standard JS Array methods.
\`\`\`javascript
primes: [2, 3, 5, 7]
_(primes[0]) // Random access: 2
primes[0] = 1
_(primes) // Mutation: [1, 3, 5, 7]
\`\`\`
### Strings
Hi strings are JavaScript strings. They are immutable sequences of characters supporting all standard JS String methods.
\`\`\`javascript
greeting: "Hi"
_(greeting[1]) // "i"
\`\`\`
## Destructuring
Destructuring provides an expressive way to extract data. The extraction operator \`->\` offers a clearer, more tool-friendly alternative to JavaScript's syntax.
- \`source -> { pattern }\`: Extracts properties from an Object.
- \`source -> [ pattern ]\`: Extracts elements from an Array.
- \`prop -> alias\`: Used within the pattern for aliasing.
\`\`\`javascript
// Setup
user: { name: "Zeta", role: "Admin", id: 101 }
coords: [10, -5, 8]
// Extract 'name' and 'role'
user -> { name, role }
_(name) // "Zeta"
// Extract 'id' and alias it to 'userID'
user -> { id -> userID }
_(userID) // 101
// Extract array elements
coords -> [x, y]
_(y) // -5
\`\`\`
## Repetition
Hi unifies iteration with a single syntax: \`(source -> pattern) * { ... }\`. This transpiles to the most appropriate JavaScript loop (\`for...of\`, \`for...in\`, etc.) based on the source type.
### Iterating Collections
\`\`\`javascript
// Iterate over an Array's values
(["a", "b"] -> item) * { _(item) }
// Iterate over an Array with index and value
(["a", "b"] -> [i, item]) * { _(i + ": " + item) }
// Iterate over a Block's key-value pairs
({ id: 1 } -> [k, v]) * { _(k + " is " + v) }
// Destructure directly in the loop signature
users: [{ name: "Orion" }]
(users -> { name }) * { _("User: " + name) }
\`\`\`
### Numeric Ranges
The \`..\` operator creates an iterable numeric range for concise, traditional loops.
\`\`\`javascript
(0..3 -> i) * {
_("Iteration: " + i) // Prints 0, 1, 2
}
\`\`\`
### Loop Control
Control flow symbols map directly to their JS counterparts.
- \`><\`: **Break** (\`break\`).
- \`>>\`: **Continue** (\`continue\`).
- \`^\`: **Return** (\`return\`). Exits the parent function.
\`\`\`javascript
(0..10 -> i) * {
(i == 2) ? { >> } // Skip 2
(i == 5) ? { >< } // Break at 5
_("i is " + i)
}
// Prints: i is 0, i is 1, i is 3, i is 4
\`\`\`
## Imports
Hi streamlines JavaScript's module system with the \`+\` and \`->\` operators. This syntax improves tooling by placing the module source first, enabling immediate, context-aware autocompletion for the members being imported.
\`\`\`javascript
// Import 'block1' and 'block2' (as 'alias2') from a module
+ "npm://hi-lang@0.1/path/file.hi" -> { block1, block2 -> alias2 }
block1()
alias2("some value")
\`\`\`
## Context Reference: @
The \`@\` symbol is a direct, one-character replacement for \`this\` in JavaScript, providing a reference to the current execution context.
\`\`\`javascript
// This block is a portable method.
loggable: {
logId: { _("ID is: " + @id) }
}
user: { id: 101, log: loggable.logId }
item: { id: "abc-789", log: loggable.logId }
user.log() // Prints "ID is: 101" (@ is 'user')
item.log() // Prints "ID is: abc-789" (@ is 'item')
\`\`\`
## Expression Blocks and Fluent Chaining
Hi adopts an expression-oriented design. Every **Block** is an expression that yields a value, transpiling to a JS IIFE or function body.
- The value of the *last expression* in a Block is implicitly returned.
- To return early or explicitly, use the return symbol \`^\`.
\`\`\`javascript
// The last expression, \`a + b\`, is returned.
add: (a, b) {
_("adding...")
a + b
}
result: add(2, 3) // result is 5
\`\`\`
### Fluent Chaining
To enable fluent method chaining (e.g., \`obj.method1().method2()\`), if the last expression in a block produces no value (like an assignment), the block returns its own context (\`@\`) by default. This transpiles to returning \`this\`.
\`\`\`javascript
calculator: {
#total: 0
add: (n) { total = total + n } // Assignment has no value, returns '@'
sub: (n) { total = total - n } // Also returns '@'
get: { ^ total } // Explicitly returns the final value
}
result: calculator.add(10).sub(4).get()
_(result) // Prints 6
\`\`\`
## Direct JavaScript Interoperability
Hi does not create its own standard library or aliases for built-in methods. Instead, it provides **direct access** to the complete JavaScript standard library. All properties (\`.length\`) and methods (\`.toUpperCase()\`, \`.map()\`) are used with their standard JavaScript names.
This ensures zero learning curve for existing JS functionality and guarantees full compatibility.
### Common JavaScript Built-ins
| Type | Name / Property / Method | Example |
| :--- | :--- | :--- |
| **Global** | \`_\` | \`_("hello") // console.log\` |
| **Global** | \`Math\` | \`_(Math.PI)\` |
| **Global** | \`Object\` | \`Object.keys({a:1}) // ["a"]\` |
| | | |
| **Number** | \`.toFixed(digits)\` | \`n: 3.14159; _(n.toFixed(2)) // "3.14"\` |
| **Number** | \`.toString()\` | \`age: 21; _(age.toString())\` |
| | | |
| **String** | \`.length\` | \`"hi".length // 2\` |
| **String** | \`.toUpperCase()\` | \`"hi".toUpperCase() // "HI"\` |
| **String** | \`.toLowerCase()\` | \`"HI".toLowerCase() // "hi"\` |
| **String** | \`.trim()\` | \`" hi ".trim() // "hi"\` |
| **String** | \`.split(separator)\` | \`"a-b-c".split("-") // ["a","b","c"]\` |
| **String** | \`.slice(start, end)\`| \`"hello".slice(1,3) // "el"\` |
| **String** | \`.includes(substr)\`| \`"hi".includes("i") // !0 (true)\` |
| **String** | \`.replaceAll(find,r)\` | \`"hi hi".replaceAll("i","o") // "ho ho"\` |
| | | |
| **Array** | \`.length\` | \`[1,2].length // 2\` |
| **Array** | \`.push(value)\` | \`a:[1]; a.push(2) // a is now [1,2]\` |
| **Array** | \`.pop()\` | \`a:[1,2]; a.pop() // returns 2\` |
| **Array** | \`.forEach(fn)\` | \`[1,2].forEach((n)=>{_(n)})\` |
| **Array** | \`.map(fn)\` | \`[1,2].map((n)=>n*2) // [2,4]\` |
| **Array** | \`.filter(fn)\` | \`[1,2,3].filter((n)=>n>1) // [2,3]\` |
| **Array** | \`.reduce(fn, init)\`| \`[1,2,3].reduce((a,c)=>a+c, 0) // 6\` |
| **Array** | \`.find(fn)\` | \`[1,2].find((n)=>n>1) // 2\` |
| **Array** | \`.includes(value)\` | \`[1,2].includes(2) // !0 (true)\` |
| **Array** | \`.join(separator)\` | \`["a","b"].join("-") // "a-b"\` |
| **Array** | \`.sort()\` | \`[3,1,2].sort() // [1,2,3]\` |
| | | |
| **Object** | \`.hasOwnProperty(key)\` | \`{a:1}.hasOwnProperty("a") // !0 (true)\` |
---
<p class="text-sm text-gray-600">Hi is in early development. The syntax and features are subject to change.</p>
`;
document.addEventListener('DOMContentLoaded', () => {
const md = window.markdownit({
html: true,
linkify: true,
typographer: true,
highlight: (str, lang) => {
if (lang && hljs.getLanguage(lang)) {
try {
return `<pre class="hljs"><code>${hljs.highlight(str, { language: lang, ignoreIllegals: true }).value}</code></pre>`;
} catch (__) {}
}
return `<pre class="hljs"><code>${md.utils.escapeHtml(str)}</code></pre>`;
}
});
document.getElementById('content').innerHTML = md.render(markdownContent);
lucide.createIcons();
});
</script>
</body>
</html>