mirror of
https://github.com/hi-language/hi-language.github.io.git
synced 2026-01-14 00:28:05 +00:00
410 lines
16 KiB
HTML
410 lines
16 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 Programming Language</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" 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-center">
|
|
<button class="hi-button text-2xl font-bold text-gray-900 px-6 py-2 rounded-lg cursor-default transition-all duration-300 hover:bg-gray-100">
|
|
Hi
|
|
</button>
|
|
</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 corely symbolic language
|
|
|
|
**Hi** is a programming language inspired by JavaScript, designed with a symbolic core to be more universal, AI-friendly, and conducive to code golfing. The syntax prioritizes symbols over keywords.
|
|
|
|
The underscore \`_\` is the global output function.
|
|
|
|
\`\`\`javascript
|
|
_("Hi world")
|
|
\`\`\`
|
|
|
|
## Declaration and Assignment
|
|
|
|
Variable lifecycle is split into two distinct symbolic operations.
|
|
|
|
- \`:\` **Declaration**: Binds a name in the current scope.
|
|
- \`=\` **Assignment**: Reassigns the value of an existing name.
|
|
|
|
\`\`\`javascript
|
|
version: 1.0 // Declaration and initialization
|
|
version = 1.1 // Assignment
|
|
\`\`\`
|
|
|
|
## The Block: A Unified Structure
|
|
|
|
The \`{}\` syntax creates a **Block**, the foundational structure in Hi. A Block is a container for both properties (state) and executable code (behavior), functioning simultaneously as a callable object and a stateful function.
|
|
|
|
### Function Block
|
|
A Block with only executable code is a function.
|
|
|
|
\`\`\`javascript
|
|
sayHi: { _("Hi") }
|
|
sayHi() // Invokes the block
|
|
\`\`\`
|
|
|
|
### Object Block
|
|
A Block with named properties is an object. A \`#\` prefix denotes a private property, inaccessible from outside the block's scope.
|
|
|
|
\`\`\`javascript
|
|
player: {
|
|
name: "Orion" // Public property
|
|
#hp: 100 // Private property
|
|
}
|
|
_(player.name) // "Orion"
|
|
\`\`\`
|
|
|
|
### Hybrid Block
|
|
Blocks can contain both state and methods. Inner blocks lexically inherit the scope of their parent, allowing them to access and mutate the parent's private state. This provides true encapsulation without classes.
|
|
|
|
\`\`\`javascript
|
|
counter: {
|
|
#value: 0
|
|
inc: { value = value + 1 }
|
|
get: { value }
|
|
}
|
|
|
|
counter.inc()
|
|
_(counter.get()) // Prints 1
|
|
\`\`\`
|
|
|
|
### Blocks with Parameters
|
|
|
|
\`\`\`javascript
|
|
greet: (name) { _("Hi, " + name) }
|
|
greet("Orion")
|
|
\`\`\`
|
|
|
|
## Arrow Expressions
|
|
|
|
For concise single-expression functions, Hi provides the \`=>\` arrow syntax, inspired by JavaScript. It serves as a shorthand for a Block that immediately returns an expression, making it ideal for callbacks and functional patterns.
|
|
|
|
It's a direct replacement for \`(params) { ^ expression }\`.
|
|
|
|
\`\`\`javascript
|
|
// Standard block
|
|
add: (a, b) { ^ a + b }
|
|
|
|
// Equivalent Arrow Expression
|
|
add: (a, b) => a + b
|
|
|
|
// Useful for functional helpers
|
|
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 for truthiness.
|
|
|
|
- \`0\` is **falsy** (the canonical false).
|
|
- \`!0\` is **truthy** (the canonical true, representing a logical NOT 0).
|
|
- \`-0\` represents null/undefined values.
|
|
- All other numbers, and any non-empty string, block, or array are "truthy".
|
|
- The \`==\` operator performs strict equality comparison (equivalent to JavaScript's \`===\`).
|
|
|
|
## Conditional Expressions
|
|
|
|
All conditional logic is handled by a single ternary expression structure, which always returns a value.
|
|
|
|
\`\`\`javascript
|
|
// if
|
|
(1 < 2) ? { _("True") }
|
|
|
|
// if / else
|
|
result: (1 > 2) ? { "A" } : { "B" } // result is "B"
|
|
|
|
// if / else if / else
|
|
score: 75
|
|
grade: (score >= 90) ? { "A" }
|
|
: (score >= 80) ? { "B" }
|
|
: (score >= 70) ? { "C" }
|
|
: { "D" } // The final else case
|
|
|
|
_(grade) // Prints "C"
|
|
\`\`\`
|
|
|
|
## Data Structures
|
|
|
|
### Arrays
|
|
Arrays are 0-indexed lists of values. They support random access via \`[]\` and are iterable.
|
|
|
|
\`\`\`javascript
|
|
primes: [2, 3, 5, 7]
|
|
_(primes[0]) // Random access: 2
|
|
primes[0] = 1
|
|
_(primes) // Mutation: [1, 3, 5, 7]
|
|
\`\`\`
|
|
|
|
### Strings
|
|
Strings are sequences of characters. They are immutable but support random access and iteration.
|
|
|
|
\`\`\`javascript
|
|
greeting: "Hi"
|
|
_(greeting[1]) // "i"
|
|
\`\`\`
|
|
|
|
## Destructuring
|
|
|
|
Destructuring provides an expressive way to extract data from Blocks and Arrays. The extraction operator \`->\` is used to unpack values, mirroring its use in module imports.
|
|
|
|
- \`source -> { pattern }\`: Extracts properties from a Block.
|
|
- \`source -> [ pattern ]\`: Extracts elements from an Array.
|
|
- \`prop -> alias\`: The same operator is used within the pattern for aliasing.
|
|
|
|
\`\`\`javascript
|
|
// Setup
|
|
user: { name: "Zeta"; role: "Admin"; id: 101 }
|
|
coords: [10, -5, 8]
|
|
|
|
// Extract 'name' and 'role' from the user block
|
|
user -> { name, role }
|
|
_(name) // "Zeta"
|
|
|
|
// Extract 'id' and alias it to 'userID'
|
|
user -> { id -> userID }
|
|
_(userID) // 101
|
|
|
|
// Extract first two elements from the array
|
|
coords -> [x, y]
|
|
_(y) // -5
|
|
\`\`\`
|
|
|
|
## Repetition
|
|
|
|
Repetition is handled by a unified iteration protocol: \`(source -> pattern) * { ... }\`. This single, concise syntax adapts to iterate over any collection type.
|
|
|
|
### Iterating Collections
|
|
The \`->\` operator extracts elements from a source into a pattern.
|
|
|
|
\`\`\`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) }
|
|
|
|
// Iterate over a String's characters
|
|
("Hi" -> char) * { _(char) }
|
|
|
|
// 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
|
|
// A range from 0 up to (but not including) 3
|
|
(0..3 -> i) * {
|
|
_("Iteration: " + i) // Prints 0, 1, 2
|
|
}
|
|
\`\`\`
|
|
|
|
### Loop Control
|
|
Control flow within loops is managed by distinct symbols:
|
|
- \`.\`: **Break**. Immediately terminates the loop.
|
|
- \`>>\`: **Continue**. Skips to the next iteration.
|
|
- \`^\`: **Return**. Exits the parent block, not just the loop.
|
|
|
|
\`\`\`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
|
|
|
|
Modules are imported using the \`+\` and \`->\` operators. This allows for destructuring and aliasing of imported members. Placing the module source first allows development tools to provide immediate, context-aware autocompletion for the members being imported—a direct ergonomic improvement over JavaScript's syntax.
|
|
|
|
\`\`\`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")
|
|
\`\`\`
|
|
|
|
## Method Chaining
|
|
|
|
A Block's return behavior is designed for fluency. It implicitly returns the value of its last expression. If the last expression does not yield a value (such as an assignment), the Block returns itself (\`this\`) by default, enabling method chaining. The \`^\` symbol is used for an explicit or early return from any point in the Block.
|
|
|
|
\`\`\`javascript
|
|
calculator: {
|
|
#total: 0
|
|
add: (n) { total = total + n } // Implicitly returns 'this'
|
|
sub: (n) { total = total - n } // Implicitly returns 'this'
|
|
get: { ^ total } // Explicitly returns the total
|
|
}
|
|
|
|
// .add() and .sub() return the calculator, allowing the chain
|
|
result: calculator.add(10).sub(4).get()
|
|
|
|
_(result) // Prints 6
|
|
\`\`\`
|
|
|
|
## Core Language Blueprint
|
|
|
|
To create the initial Hi-to-JS transpiler, the following primitives and built-in functionalities must be defined. This serves as the blueprint for the core standard library.
|
|
|
|
### Built-in Definitions Table
|
|
|
|
| Type | Name / Symbol | Description | Example |
|
|
| :--- | :--- | :--- | :--- |
|
|
| **Global** | \`_\` | The global output function. Transpiles to \`console.log\`. | \`_("hello")\` |
|
|
| **Global** | \`Math\` | A global block containing mathematical constants and functions. | \`_(Math.PI)\` |
|
|
| | | | |
|
|
| **Number** | \`.str()\` | Converts the number to its string representation. | \`age: 21; _(age.str())\` |
|
|
| **Number** | \`.fix(d)\` | Formats a number using fixed-point notation. | \`n: 3.14159; _(n.fix(2)) // "3.14"\` |
|
|
| | | | |
|
|
| **String** | \`.len\` | **Property**: Returns the number of characters in the string. | \`"hi".len // 2\` |
|
|
| **String** | \`.num()\` | Parses the string, returning a number. | \`"42".num() // 42\` |
|
|
| **String** | \`.upper()\` | Returns the string converted to uppercase. | \`"hi".upper() // "HI"\` |
|
|
| **String** | \`.lower()\` | Returns the string converted to lowercase. | \`"HI".lower() // "hi"\` |
|
|
| **String** | \`.trim()\` | Removes whitespace from both ends of a string. | \`" hi ".trim() // "hi"\` |
|
|
| **String** | \`.split(d)\` | Divides a string into an ordered list of substrings. | \`"a-b-c".split("-") // ["a","b","c"]\` |
|
|
| **String** | \`.slice(s,e)\`| Extracts a section of a string and returns it as a new string. | \`"hello".slice(1,3) // "el"\` |
|
|
| **String** | \`.has(sub)\`| Determines whether a string contains a given substring. | \`"hi".has("i") // !0 (true)\` |
|
|
| **String** | \`.replace(f,r)\` | Replaces the first occurrence of a substring. | \`"hi hi".replace("i","o") // "ho hi"\` |
|
|
| **String** | \`.replaceAll(f,r)\` | Replaces all occurrences of a substring. | \`"hi hi".replaceAll("i","o") // "ho ho"\` |
|
|
| | | | |
|
|
| **Array** | \`.len\` | **Property**: Returns the number of elements in the array. | \`[1,2].len // 2\` |
|
|
| **Array** | \`.add(v)\` | Adds one or more elements to the end of an array. | \`a:[1]; a.add(2) // a is now [1,2]\` |
|
|
| **Array** | \`.pop()\` | Removes the last element from an array and returns it. | \`a:[1,2]; a.pop() // returns 2\` |
|
|
| **Array** | \`.pre(v)\` | Adds one or more elements to the beginning of an array. | \`a:[2]; a.pre(1) // a is now [1,2]\` |
|
|
| **Array** | \`.shift()\` | Removes the first element from an array and returns it. | \`a:[1,2]; a.shift() // returns 1\` |
|
|
| **Array** | \`.each(fn)\` | Executes a provided function once for each array element. | \`[1,2].each((n)=>{_(n)})\` |
|
|
| **Array** | \`.map(fn)\` | Creates a new array with the results of calling a function on every element. | \`[1,2].map((n)=>n*2) // [2,4]\` |
|
|
| **Array** | \`.filter(fn)\` | Creates a new array with all elements that pass the test implemented by the provided function. | \`[1,2,3].filter((n)=>n>1) // [2,3]\` |
|
|
| **Array** | \`.reduce(fn,iv)\`| Executes a reducer function on each element, resulting in a single output value. | \`[1,2,3].reduce((a,c)=>a+c, 0) // 6\` |
|
|
| **Array** | \`.find(fn)\` | Returns the first element in the array that satisfies the provided testing function. | \`[1,2].find((n)=>n>1) // 2\` |
|
|
| **Array** | \`.has(v)\` | Determines whether an array includes a certain value. | \`[1,2].has(2) // !0 (true)\` |
|
|
| **Array** | \`.join(d)\` | Joins all elements of an array into a string. | \`["a","b"].join("-") // "a-b"\` |
|
|
| **Array** | \`.slice(s,e)\`| Returns a shallow copy of a portion of an array into a new array object. | \`[1,2,3].slice(1) // [2,3]\` |
|
|
| **Array** | \`.reverse()\`| Reverses an array in place. | \`a:[1,2]; a.reverse() // a is [2,1]\` |
|
|
| **Array** | \`.sort(fn)\` | Sorts the elements of an array in place. | \`[3,1,2].sort() // [1,2,3]\` |
|
|
| | | | |
|
|
| **Block** | \`.keys()\` | Returns an array of a given block's own property names. | \`{a:1}.keys() // ["a"]\` |
|
|
| **Block** | \`.values()\` | Returns an array of a given block's own property values. | \`{a:1}.values() // [1]\` |
|
|
| **Block** | \`.has(key)\` | Checks if a block has a specified property as its own. | \`{a:1}.has("a") // !0 (true)\` |
|
|
| | | | |
|
|
| **Math** | \`.PI\` | **Property**: Ratio of a circle's circumference to its diameter. | \`Math.PI // 3.14159...\` |
|
|
| **Math** | \`.abs(n)\` | Returns the absolute value of a number. | \`Math.abs(-5) // 5\` |
|
|
| **Math** | \`.floor(n)\` | Returns the largest integer less than or equal to a number. | \`Math.floor(5.9) // 5\` |
|
|
| **Math** | \`.ceil(n)\` | Returns the smallest integer greater than or equal to a number. | \`Math.ceil(5.1) // 6\` |
|
|
| **Math** | \`.round(n)\` | Returns the value of a number rounded to the nearest integer. | \`Math.round(5.5) // 6\` |
|
|
| **Math** | \`.max(a,b,..)\`| Returns the largest of the given numbers. | \`Math.max(1,5,2) // 5\` |
|
|
| **Math** | \`.min(a,b,..)\`| Returns the smallest of the given numbers. | \`Math.min(1,5,2) // 1\` |
|
|
| **Math** | \`.pow(b,e)\` | Returns base to the exponent power. | \`Math.pow(2,3) // 8\` |
|
|
| **Math** | \`.sqrt(n)\` | Returns the square root of a number. | \`Math.sqrt(9) // 3\` |
|
|
| **Math** | \`.rand()\` | Returns a pseudo-random number between 0 and 1. | \`Math.rand() // e.g., 0.123...\` |
|
|
|
|
|
|
---
|
|
|
|
<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>
|
|
|