diff options
-rw-r--r-- | README.md | 33 | ||||
-rw-r--r-- | docs/ASYNC.md (renamed from ASYNC.md) | 0 | ||||
-rw-r--r-- | docs/BASIC.md (renamed from BASIC.md) | 14 | ||||
-rw-r--r-- | docs/ERRORS.md (renamed from ERRORS.md) | 0 | ||||
-rw-r--r-- | docs/TYPES.md (renamed from TYPES.md) | 30 |
5 files changed, 45 insertions, 32 deletions
@@ -3,10 +3,13 @@ A place where I can make some bad decisions. Puck is an experimental, memory safe, strongly typed, multi-paradigm programming language. -It aims to be clean and succinct while performant: having the ease of use of [Python](https://www.python.org/) with the performance/safety guarantees of [Rust](https://www.rust-lang.org/) and the flexibility/metaprogramming of [Nim](https://nim-lang.org/). +It aims to be clean and succinct while performant: having the flexibility/metaprogramming of [Nim](https://nim-lang.org/) with the performance/safety guarantees of [Rust](https://www.rust-lang.org/) and the error handling of [Swift](https://www.swift.org/). You may judge for yourself if Puck meets these ideals. +```puck +``` + ## Why Puck? Puck is primarily a testing ground and should not be used in any important capacity. @@ -20,23 +23,25 @@ That said: in the future, once somewhat stabilized, reasons why you *would* use - The **interop system**, allowing foreign functions to be usable with native semantics from a bevy of popular languages <!-- - The **effect system**, being one of few languages with a proper effects system based on handlers --> +This is the language I keep in my head. It sprung from a series of unstructured notes I kept on language design, that finally became something more comprehensive in early 2023. The overarching goal is to provide a language capable of elegantly expressing any problem, and explore ownership and interop along the way. + ## How do I learn more? -- The [basic usage](BASIC.md) document lays out the fundamental grammar of Puck. -- The [syntax](SYNTAX.md) document provides a deeper and formal look into the syntax choices made. -- The [type system](TYPES.md) document gives an in-depth analysis of Puck's extensive type system. <!-- and its relationship to classes and other abstractions. --> -- The [memory management](MEMORY_MANAGEMENT.md) document gives an overview of Puck's memory model. <!-- which is considered a mashup of the models pioneered by Lobster, Rust, and Nim. --> -- The [metaprogramming](METAPROGRAMMING.md) document explains how using metaprogramming to extend the language works. <!-- and write more powerful code works. --> -- The [asynchronous](ASYNC.md) document gives an overview of the intertwining of Puck's asynchronous support with other language features. -- The [effect system](EFFECTS.md) document gives a description of how Puck's effect handler system works. -- The [interop](INTEROP.md) document gives an overview of how the first-class language interop system works. -- The [modules](MODULES.md) document provides a more detailed look at imports and how they relate to the type system. -- The [standard library](STDLIB.md) document provides an overview and examples of usage of the standard library. -- The [roadmap](ROADMAP.md) provides a clear view of the current state and future plans of the language's development. +- The [basic usage](docs/BASIC.md) document lays out the fundamental grammar of Puck. +- The [syntax](docs/SYNTAX.md) document provides a deeper and formal look into the syntax choices made. +- The [type system](docs/TYPES.md) document gives an in-depth analysis of Puck's extensive type system. <!-- and its relationship to classes and other abstractions. --> +- The [memory management](docs/MEMORY_MANAGEMENT.md) document gives an overview of Puck's memory model. <!-- which is considered a mashup of the models pioneered by Lobster, Rust, and Nim. --> +- The [metaprogramming](docs/METAPROGRAMMING.md) document explains how using metaprogramming to extend the language works. <!-- and write more powerful code works. --> +- The [asynchronous](docs/ASYNC.md) document gives an overview of the intertwining of Puck's asynchronous support with other language features. +- The [interop](docs/INTEROP.md) document gives an overview of how the first-class language interop system works. +- The [modules](docs/MODULES.md) document provides a more detailed look at imports and how they relate to the type system. +<!-- - The [effect system](docs/EFFECTS.md) document gives a description of how Puck's effect handler system works. --> +- The [standard library](docs/STDLIB.md) document provides an overview and examples of usage of the standard library. +- The [roadmap](docs/ROADMAP.md) provides a clear view of the current state and future plans of the language's development. These are best read in order. -Note that all of these documents (and parts of this README) are written as if everything already exists. Nothing already exists! You can see the [roadmap](ROADMAP.md) for an actual sense as to the state of the language. I simply found writing in the present tense to be an easier way to collect my thoughts. +Note that all of these documents (and parts of this README) are written as if everything already exists. Nothing already exists! You can see the [roadmap](docs/ROADMAP.md) for an actual sense as to the state of the language. I simply found writing in the present tense to be an easier way to collect my thoughts. ## Acknowledgements @@ -44,4 +49,4 @@ First and foremost, this language is *heavily* inspired by Nim. Many ideas - gen The error handling model, and purity system, were essentially directly lifted from Swift (and to an extent, Nim). The underlying type system is mostly copied from Rust, with significant changes to the interface (trait) and module system. The memory model is based upon similar successful models in Lobster, Nim, and Rust. Performance annotations are somewhat inspired by Nim. -The effects system is unique, with inspiration from the few languages successfully implementing effects systems, namely Koka and Unison. +<!-- The effects system is unique, with inspiration from the few languages successfully implementing effects systems, namely Koka and Unison. --> @@ -80,13 +80,15 @@ All forms of control flow ultimately desugar to continuations: https://github.co ```puck ``` -Exhaustive structural pattern matching is available, particularly useful for tagged unions, and discussed in detail in the [types document](TYPES.md). This is frequently a better alternative to a series of `if` statements. +Exhaustive structural pattern matching is available and particularly useful for tagged unions. This is frequently a better alternative to a series of `if` statements. ```puck ``` I am undecided on how the import/module system will work and particularly how it will play into the type system. UFCS *will* be supported. todo +More details may be found in the [modules document](MODULES.md). + ```puck ``` @@ -94,16 +96,13 @@ Compile-time programming may be done via the previously-mentioned `const` keywor Compile-time programming may also be intertwined in the codebase with the use of the `when` statement. It functions similarly to `if`, but may only take a static operation as its parameter, and will directly replace code accordingly at compile-time. The `else` statement is overloaded to complement this. -```puck -``` - -Metaprogramming is done via compile-time introspection on the abstract syntax tree. +Further compile-time programming may be done via metaprogramming: compile-time introspection on the abstract syntax tree. Two distinct language constructs of differing complexity are provided: templates for raw substitution, and macros for direct manipulation of the abstract syntax tree. These are complex, and more details may be found in the [metaprogramming document](METAPROGRAMMING.md). ```puck ``` -Error handling is typically done via explicitly matching upon Optional and Result values (with the help of the `?` operator), but such functions can be made to explicitly throw exceptions (which may then be caught via `try`/`catch`/`finally` or thrown with `raise`) with the help of the `!` operator. This is complex and necessarily verbose, although a bevy of helper functions and syntactic sugar are available to ease the pain. More details may be found in [error handling overview](ERRORS.md). +Error handling is typically done via explicitly matching upon Optional and Result values (with the help of the `?` operator), but such functions can be made to explicitly throw exceptions (which may then be caught via `try`/`catch`/`finally` or thrown with `raise`) with the help of the `!` operator. This is complex and necessarily verbose, although a bevy of helper functions and syntactic sugar are available to ease usage. More details may be found in [error handling overview](ERRORS.md). ```puck ``` @@ -117,4 +116,5 @@ Effects are complex and relegated to external libraries (with native syntax via ```puck ``` -Details on memory safety, references and pointers, and deep optimizations may be found in the [memory management overview](MEMORY_MANAGEMENT.md). This intertwines deeply with the [type system](TYPES.md). +Details on memory safety, references and pointers, and deep optimizations may be found in the [memory management overview](MEMORY_MANAGEMENT.md). +The memory model intertwines deeply with the type system. diff --git a/ERRORS.md b/docs/ERRORS.md index 4a4b206..4a4b206 100644 --- a/ERRORS.md +++ b/docs/ERRORS.md @@ -16,8 +16,9 @@ Basic types can be one-of: - `rune`: a Unicode character. - `str`: a string type. mutable. internally a char-array? must also support unicode. - `void`: an internal type designating the absence of a value. - - possibly, the empty tuple. then would `empty` be better? -- `never`: a type that denotes functions that do not return. distinct from returning nothing. + - possibly, the empty tuple. then would `empty` be better? or `unit`? +- `never`: a type that denotes functions that do not return. + - distinct from returning nothing. - the bottom type. `bool`, `int`/`uint` and siblings, `float` and siblings, `char`, and `rune` are all considered **primitive types** and are _always_ [[copied]] (unless passed as `var`). @@ -28,13 +29,14 @@ Basic types as a whole include the primitive types, as well as `str`, `void`, an - textual types: `char`, `rune`, `str` - funky types: `void`, `never` -Funky types will rarely be referenced by name: instead, the absence of a type typically implicitly denotes one or the other. Still, having a name is helpful in some situations: like with [[concepts]]. +Funky types will rarely be referenced by name: instead, the absence of a type typically implicitly denotes one or the other. Still, having a name is helpful in some situations. ## Function types Functions can also be types. - `func(T, U): V`: denotes a type that is a function taking arguments of type T and U and returning a value of type V. - - The syntactical sugar `(T, U) -> (V)` is available, to consolidate type declarations and disambiguate when dealing with many `:`s. Is this a good idea? should i universally use `:` or `->`? + - The syntactical sugar `(T, U) -> (V)` is available, to consolidate type declarations and disambiguate when dealing with many `:`s. + - purity of functions? ## Container types @@ -53,9 +55,11 @@ Iterable types can be one-of: - `str`: Strings. Contain the `rune` type or alternatively `char`s or `bytes`?? {undecided} All of these above types are some sort of sequence: and so have a length, and so can be _iterated_. -For convenience, a special `iterable` generic type is defined for use in parameters: that abstracts over all of the container types. This `iterable` type is also extended to any collection with a length of a single type (and also tuples). It is functionally equivalent to the `openarray` type in Nim: but hopefully a bit more powerful? +For convenience, a special `iterable` generic type is defined for use in parameters: that abstracts over all of the container types. This `iterable` type is also extended to any collection with a length of a single type (and also tuples). It is functionally equivalent to the `openarray` type in Nim. +- Under the hood, this is an interface. - Aside: how do we implement this? rust-style (impl `iter()`), or monomorphize the hell out of it? i think compiler magic is the way to go for specifically this... -- Aside: `iterable` may need a better name. it implies iterators right now which it is distinctly Unrelated to. unless i don't have iterators? that may be the way to go... +- Aside: does `slice` fill this role? +- todo. many questions abound. Elements of container types can be accessed by the `container[index]` syntax. Slices of container types can be accessed by the `container[lowerbound..upperbound]` syntax. Slices of non-consecutive elements can be accessed by the `container[a,b,c..d]` syntax, and indeed, the previous example expands to these. They can also be combined: `container[a,b,c..d]`. - Aside: take inspiration from Rust here? they make it really safe if a _little_ inconvenient @@ -113,7 +117,7 @@ Constrained generics have two syntaxes: the constraint can be directly on a para ## Reference types -Types are typically constructed as value on the stack. That is, without any level of indirection: and so type declarations that recursively refer to one another would not be allowed. However, Puck provides two avenues for indirection. +Types are typically constructed by value on the stack. That is, without any level of indirection: and so type declarations that recursively refer to one another would not be allowed. However, Puck provides two avenues for indirection. Reference types can be one-of: - `ref T`: An automatically-managed reference to type `T`. @@ -137,15 +141,19 @@ type BinaryTree = ref struct The compiler abstracts over `ref` types to provide optimization for reference counts: and so neither a distinction between `Rc`/`Arc`/`Box`, nor a `*` dereference operator is needed. Much care has been given to make references efficient and safe, and so `ptr` should be avoided if at all possible. The compiler will yell at you if you use it (or any other unsafe features). + These types are delved into in further detail in the section on memory management. +The indirection that `ref` types provide is explored a little further in the section in this document on interfaces. ## Advanced Types -The `type` keyword is used to declare custom types. +The `type` keyword is used to declare custom data types. These are *algebraic*: they function by composition. -Custom types can be one-of: +Algebraic data types can be one-of: - `tuple`: An ordered collection of types. Optionally named. - `struct`: An unordered, named collection of types. May have default values. -- `enum`: Powerful algebraic data types a la Rust. -- `concept`: typeclasses. they have some unique syntax +- `enum`: Ordinal labels, that may hold values. Their default values are their ordinality. +- `union`: Powerful matchable tagged unions a la Rust. Sum types. +- `interface`: Usage-based typeclasses. User-defined duck typing. - `distinct`: a type that must be explicitly converted +- type aliases, declared as `type Identifier = Alias` |