aboutsummaryrefslogtreecommitdiff
path: root/docs/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'docs/index.html')
-rw-r--r--docs/index.html117
1 files changed, 69 insertions, 48 deletions
diff --git a/docs/index.html b/docs/index.html
index 02df44f..01b238a 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -7,7 +7,7 @@
<!-- Custom HTML head -->
-
+
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff">
@@ -176,39 +176,55 @@
<h1 id="-puck---an-experimental-programming-language"><a class="header" href="#-puck---an-experimental-programming-language"><span style="font-family: 'Noto Color Emoji'">🧚</span> Puck - A Programming Language</a></h1>
<p>A place where I can make some bad decisions.</p>
<p>Puck is an experimental, memory safe, structurally typed, interface-first, imperative programming language.
-It aims to be clean and succinct while performant: inspired by the syntax and metaprogramming of <a href="https://nim-lang.org/">Nim</a>, the error handling of <a href="https://www.swift.org/">Swift</a>, the performance and safety guarantees of <a href="https://www.rust-lang.org/">Rust</a>, the async/await and comptime of <a href="https://ziglang.org/">Zig</a>, and the module system of <a href="https://ocaml.org/">OCaml</a>.</p>
+It aims to be consistent and succinct while performant: inspired by the syntax and metaprogramming of <a href="https://nim-lang.org/">Nim</a>, the error handling of <a href="https://www.swift.org/">Swift</a>, the memory management of <a href="https://www.rust-lang.org/">Rust</a> and <a href="https://koka-lang.github.io/">Koka</a>, the async/await and comptime of <a href="https://ziglang.org/">Zig</a>, and the module system of <a href="https://ocaml.org/">OCaml</a>.</p>
<details>
-<summary><b>Example: Interfaces</b></summary>
-<pre><code class="language-nim"># Note: These declarations are adapted from the standard prelude.
+<summary><b>Example: Type Classes</b></summary>
+<pre><code class="language-puck"># Note: These declarations are adapted from the standard prelude.
## The Result type. Represents either success or failure.
pub type Result[T, E] = union
Okay(T)
Error(E)
-## The Err interface. Useful for dynamically dispatching errors.
-pub type Err = interface
+## The Err class. Useful for dynamically dispatching errors.
+pub type Err = class
str(Self): str
dbg(Self): str
## A Result type that uses dynamically dispatched errors.
-## The Error may be any type implementing Err.
+## The Error may be any type implementing the Err class.
pub type Result[T] = Result[T, ref Err]
-## Implements the dbg function for strings.
-## As the str function is already defined for strings,
+## Implements the `dbg` function for strings.
+## As the `str` function is already defined for strings,
## this in turn means strings now implicitly implement Err.
-pub func dbg(self: str) = &quot;\&quot;&quot; &amp; self &amp; &quot;\&quot;&quot;
+pub func dbg(self: str) = "\"" &amp; self &amp; "\""
+</code></pre>
+</details>
+<details>
+<summary><b>Example: Metaprogramming</b></summary>
+<pre><code class="language-puck"># Note: These declarations are adapted from the standard prelude.
+
+## Syntactic sugar for dynamic result type declarations.
+pub macro !(T: type) =
+ quote Result[`T`]
+
+## Indirect access. Propagates `Error`.
+pub macro ?[T, E](self: Result[T, E]) =
+ quote
+ match `self`
+ of Okay(x) then x
+ of Error(e) then return Error(e)
</code></pre>
</details>
<details open>
<summary><b>Example: Pattern Matching</b></summary>
-<pre><code class="language-nim">## Opens the std.tables module for unqualified use.
+<pre><code class="language-puck">## Opens the std.tables module for unqualified use.
use std.tables
-pub type Value = string
-pub type Ident = string
-pub type Expr = ref union
+pub type Value = str
+pub type Ident = str
+pub type Expr = ref union # tagged, algebraic unions
Literal(Value)
Variable(Ident)
Abstraction(param: Ident, body: Expr)
@@ -217,29 +233,50 @@ pub type Expr = ref union
then_branch: Expr, else_branch: Expr)
## Evaluate an Expr down to a Value, or return an Error.
-pub func eval(context: mut HashTable[Ident, Value], expr: Expr): Result[Value]
- match expr
- of Literal(value): Okay(value)
- of Variable(ident):
- context.get(ident)
- .err(&quot;Could not find variable {} in context!&quot;.fmt(ident))
- of Application(body, arg):
- if body of Abstraction(param, body as inner_body):
+pub func eval(context: mut Table[Ident, Value], expr: lent Expr): Value! =
+ match expr # structural pattern matching and guards are supported but not shown
+ of Literal(value) then
+ Okay(value.clone) # ownership necessitates we explicitly clone
+ of Variable(ident) then
+ context.get(ident) # whitespace is significant but flexible
+ .err("Could not find variable {} in context!"
+ .fmt(ident)) # uniform function call syntax allows arbitrary piping/chaining
+ of Application(body, arg) then
+ if body of Abstraction(param, body as inner_body) then # compact matching with if
context.set(param, context.clone.eval(arg)?)
- context.eval(inner_body)
- else:
- Error(&quot;Expected Abstraction, found body {} and argument {}&quot;.fmt(body, arg))
- of Conditional(condition, then_branch, else_branch):
- if context.clone.eval(condition)? == &quot;true&quot;:
+ context.eval(inner_body) # all values must be handled: returns are implicit
+ else
+ Error("Expected Abstraction, found body {} and arg {}".fmt(body.clone, arg.clone))
+ of Conditional(condition, then_branch, else_branch) then
+ if context.clone.eval(condition)? == "true" then
context.eval(then_case)
- else:
+ else
context.eval(else_case)
- of _: Error(&quot;Invalid expression {}&quot;.fmt(expr))
+ of _ then Error("Invalid expression {}".fmt(expr))
</code></pre>
</details>
<details>
<summary><b>Example: Modules</b></summary>
-<pre><code class="language-nim">...
+<pre><code class="language-puck"># The top-level module declaration can be elided if the file shares the same name.
+pub mod tables =
+ ## The Table class. Any sort of table - no matter the underlying
+ ## representation - must implement these methods.
+ pub type Table[K, V] = class
+ get(lent Self, lent K): lent V?
+ get(mut Self, lent K): mut V?
+ set(mut Self, lent K, V): V?
+ pop(mut Self, lent K): V?
+ clear(mut Self)
+ size(lent Self): uint
+ init(varargs (K, V)): Self
+
+ ...
+
+ pub mod hashtable =
+ use std.hashes
+
+ pub type HashTable[K, V] = struct
+ ...
</code></pre>
</details>
<h2 id="why-puck"><a class="header" href="#why-puck">Why Puck?</a></h2>
@@ -248,8 +285,8 @@ Don't use it. Everything is unimplemented and it will break underneath your feet
<p>That said: in the future, once somewhat stabilized, reasons why you <em>would</em> use it would be for:</p>
<ul>
<li>The <strong>syntax</strong>, aiming to be flexible, predictable, and succinct, through the use of <em>uniform function call syntax</em> and significant whitespace</li>
-<li>The <strong>type system</strong>, being modern and powerful with a strong emphasis on safety, optional and result types, algebraic data types, interfaces, and modules</li>
-<li>The <strong>memory management system</strong>, implementing a model of strict ownership while allowing individual fallbacks to reference counts if so desired</li>
+<li>The <strong>type system</strong>, being modern and powerful with a strong emphasis on safety, algebraic data types, optional and result types, first-class functions, generics, interfaces, and modules</li>
+<li>The <strong>memory management system</strong>, implementing a model of strict ownership with an optimized reference counting escape hatch</li>
<li>The <strong>metaprogramming</strong>, providing integrated macros capable of rewriting the abstract syntax tree before or after typechecking</li>
<li>The <strong>interop system</strong>, allowing foreign functions to be usable with native semantics from a bevy of languages</li>
</ul>
@@ -300,22 +337,6 @@ Don't use it. Everything is unimplemented and it will break underneath your feet
</div>
- <!-- Livereload script (if served using the cli tool) -->
- <script>
- const wsProtocol = location.protocol === 'https:' ? 'wss:' : 'ws:';
- const wsAddress = wsProtocol + "//" + location.host + "/" + "__livereload";
- const socket = new WebSocket(wsAddress);
- socket.onmessage = function (event) {
- if (event.data === "reload") {
- socket.close();
- location.reload();
- }
- };
-
- window.onbeforeunload = function() {
- socket.close();
- }
- </script>