From e04af86491d97b297406cc4cd0d77fbbfc3a94c4 Mon Sep 17 00:00:00 2001 From: JJ Date: Thu, 16 May 2024 17:40:34 -0700 Subject: docs: update website --- docs/index.html | 117 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 69 insertions(+), 48 deletions(-) (limited to 'docs/index.html') 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 @@ - + @@ -176,39 +176,55 @@

🧚 Puck - A Programming Language

A place where I can make some bad decisions.

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 Nim, the error handling of Swift, the performance and safety guarantees of Rust, the async/await and comptime of Zig, and the module system of OCaml.

+It aims to be consistent and succinct while performant: inspired by the syntax and metaprogramming of Nim, the error handling of Swift, the memory management of Rust and Koka, the async/await and comptime of Zig, and the module system of OCaml.

-Example: Interfaces -
# Note: These declarations are adapted from the standard prelude.
+Example: Type Classes
+
# 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 & "\""
+
+
+
+Example: Metaprogramming +
# 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)
 
Example: Pattern Matching -
## Opens the std.tables module for unqualified use.
+
## 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))
 
Example: Modules -
...
+
# 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
+      ...
 

Why Puck?

@@ -248,8 +285,8 @@ Don't use it. Everything is unimplemented and it will break underneath your feet

That said: in the future, once somewhat stabilized, reasons why you would use it would be for:

  • The syntax, aiming to be flexible, predictable, and succinct, through the use of uniform function call syntax and significant whitespace
  • -
  • The type system, being modern and powerful with a strong emphasis on safety, optional and result types, algebraic data types, interfaces, and modules
  • -
  • The memory management system, implementing a model of strict ownership while allowing individual fallbacks to reference counts if so desired
  • +
  • The type system, being modern and powerful with a strong emphasis on safety, algebraic data types, optional and result types, first-class functions, generics, interfaces, and modules
  • +
  • The memory management system, implementing a model of strict ownership with an optimized reference counting escape hatch
  • The metaprogramming, providing integrated macros capable of rewriting the abstract syntax tree before or after typechecking
  • The interop system, allowing foreign functions to be usable with native semantics from a bevy of languages
@@ -300,22 +337,6 @@ Don't use it. Everything is unimplemented and it will break underneath your feet - - -- cgit v1.2.3-70-g09d2