diff options
Diffstat (limited to 'docs/index.html')
-rw-r--r-- | docs/index.html | 117 |
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) = "\"" & self & "\"" +pub func dbg(self: str) = "\"" & self & "\"" +</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("Could not find variable {} in context!".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("Expected Abstraction, found body {} and argument {}".fmt(body, arg)) - of Conditional(condition, then_branch, else_branch): - if context.clone.eval(condition)? == "true": + 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("Invalid expression {}".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> |