A statically typed, functional language inspired by Haskell, ML, and Rust. This language is effectively a rewrite and redesign of all the prior languages I've (incompletely) implemented, but with an emphasis on modular (and ideally non-monolithic) code.
The Wysk language aims to eventually branch away from its admittedly Haskell-heavy influence, and currently touts the following features (either complete or as goals):
- algebraic data types
- static type inference via Hindley-Milner
- systematic overloading and polymorphism via type classes
- a flexible module system
- robust concurrency afforded by lazy semantics and a run-time system written purely in Rust
- leveraging the low-level power of Rust with the high-level semantics of Haskell
I am still fairly inexperienced when it comes to compiler development, so it follows that this project -- and its documentation -- is very much a work in progress.
Additionally, this compiler aims to use as little dependencies as possible.
The common exceptions to this are the lazy_static, serde and toml crates;
aside from these two, the lack of external dependencies allows for a greater
amount of flexibility and control over specific functions and implementations
used within the compiler, as well as proving to be a wonderful exercise in
learning how to truly appreciate what the Rust standard library has to offer.
With that being said, additional dependencies will likely be added on an
as-needed basis as the compiler itself matures -- but that'll have to wait until
I get tired of handrolling my own Rust :).
The entry point to every program, the function main operates within IO. The
actual return type of main is generally irrelevant, but must be contained
within the IO type.
fn main :: IO ()
= printLine "Hello world!"Wysk does not have traditional loops; instead it relies on recursion to
achieve the same effect. With tail-call optimization, this generally allows
for fearless recursion (assuming convergent tail recursion). This can be
exploited along with case-like syntax at the function definition level,
allowing for branches to be predicated upon from a function's top-most scope.
fn factorial :: Int -> Int
| n if n < 2 = 1
| n = n * factorial (n - 1)Functions may be matched on with either case or match expressions, where
match expressions correspond to function in OCaml or \case in Haskell,
i.e., are sugar for \x -> match x { ... }. Wysk additionally supports
(nested) or-patterns, allowing for pattern matching to be written as concisely as
necessary without repeated code.
fn fibs :: Int -> Int
= match
| (0 | 1) -> 1
| n -> fibs (n - 1) + fibs (n - 2)The following may not necessarily be directly involved within the development of this compiler, but have proven nonetheless to be valuable sources of information.
- [1987] Simon Peton Jones. The Implementation of Functional Programming Languages
- [1992] Simon Peyton Jones. Implementing lazy functional languages on stock hardware: the Spineless Tagless G-machine
- [1997] Simon Peyton Jones, Jones & Meijer. Type classes: an exploration of the design space
- [1999] Simon Peyton Jones, Simon Marlow. Secrets of the Glasgow Haskell Compiler inliner
- [2000] Mark P. Jones, Typing Haskell in Haskell
- [2002] Paul Graham, The Roots of Lisp
- [2004] Luca Cardelli, Type Systems
- [2005] Daan Leijen. Extensible records with scoped labels
- [2010] The Haskell Community. The Haskell 2010 report
- [2011] Vytiniotis et al. OutsideIn(X): Modular type inference with local assumptions
- [2013] Susan B. Horwitz. UW CS704 notes
- [2013] Dunfield and Krishnaswami. Complete and easy bidirectional typechecking for higher-rank polymorphism
- [2015] Stephen Diehl. Write you a Haskell
- [2020] Serrano, Have, Jones & Vytiniotis. A Quick Look at Impredicativity
- [2022] Gonglin Li. An Affine Type System with Hindley-Milner Style Type Inference