Compare commits

...

1 commit

Author SHA1 Message Date
Alex Bethel ed4e98891c Move project to gkgoat 2022-09-16 14:41:13 -06:00

133
README.md
View file

@ -1,134 +1,3 @@
<!--
Please keep this document correctly word-wrapped at 70 columns and
with no trailing whitespace or blank lines at the end! Merge requests
with modifications to this document will be not be accepted until it
is formatted correctly! ~~abb
-->
# Drim
Drim is a programming language designed to have the very high-level
ergonomics and provable correctness of a purely functional language,
while maintaining speed using strictly-controlled, deterministic
memory management. The language is capable of compiling to C (and
possibly other languages in the future), allowing for maximum
portability without having to write a new backend for the compiler for
every possible target; also, the compiler and tooling will eventually
be rewritten in Drim to allow for maximum portability.
Syntactically, the language primarily resembles a mixture between
standard ML and Rust; the language always ignores whitespace.
Drim is licensed under the GNU General Public License, version 3 or
later. See the `LICENSE` file for details.
## Example
```
// Calculates the nth fibonacci number.
def fibonacci (n: U32) : U32 = match n {
0 => 0,
1 => 1,
n => fibonacci (n - 2) + fibonacci (n - 1),
};
// Prompts the user for a number n, and prints the Fibonacci numbers up
// to n.
def fibPrompt = do {
print "Enter a number: ";
num <- read <$> getLine;
sequence_ (print . fibonacci <$> (0 .. num));
};
// Program entry point.
def main : IO ()
= fibPrompt;
```
Note that type annotations are always optional; here they're given for
`fibonacci` and `main` for illustrative purposes, but omitted for
`fibPrompt` (for which the compiler infers the return type `IO ()`).
## Tools
This repository contains the following tools:
- `drimc-rs`, the Stage-1 Drim compiler, written in Rust. This can be
used as a binary with a fairly standard compiler CLI, or as a
library for use in other Rust programs.
The following tools do not exist yet, but are planned:
- `drimc`, the main Drim compiler written in Drim. This program
supports a superset of the behavior of `drimc-rs`, and exposes a
library that can be used by other Drim programs in addition to a the
compiler CLI.
- `drim`, the interactive Drim interpreter, a wrapper around `drimc`.
- `drimd`, the Language Server Protocol (LSP) server for Drim code
support in editors, supporting definition peeking and lookup,
renaming variables and modules, etc.
- `drimfmt`, the standard formatter for Drim code; all Drim code used
in this repository must be formatted with `drimfmt`, and its use is
recommended for other projects.
- `drimdoc`, the documentation generator.
- `drim-mode`, an Emacs mode for editing Drim code, supporting syntax
highlighting, automatic indentation, some basic keybindings for
common tasks, Emacs-side LSP integration for communicating with
`drimd`, and a collection of `yasnippet` snippets for inserting
common Drim constructs.
- `drim-vsc`, Visual Studio Code plugins and tools for editing
AlexScript code.
- `drim-vim`, tools and configuration files for optimizing Vim
and Neovim for editing Drim code.
## Language features
The language is mostly influenced by Rust and Haskell: it has strict
safety requirements and borrow-checked memory management like that of
Rust, but its syntax and type system are similar to those of Haskell.
Some features the language will most likely have:
- All functions are pure by default; side effects are chained together
using an `IO` monad.
- Despite the language's purity, expressions will be strictly
evaluated to provide more programmer control.
- Different monads represent different levels of safety, and can be
converted using functions marked as `UNSAFE`. The intention is that
code can be audited by manually checking that all the `UNSAFE`
transformations are sound, and code that contains no `UNSAFE`
function calls are guaranteed to satisfy varying definitions of
soundness:
- The `IO` monad represents computations that might have side
effects on the real world. If a computation of type `IO` is known
by the programmer to not have side effects on the real world, then
it can be converted to a pure computation using the standard
library function `UNSAFE_assertPure : IO a -> a`.
- The `MemoryUnsafe` monad represents computations that might read
from or write to memory that is not allocated correctly: for
example, `readPtr`, which reads from a raw pointer, is of type
`MemoryUnsafe a` because the pointer is not known to be valid. If
a computation has been confirmed to be safe by the programmer, it
can be converted to an `IO` computation using
`UNSAFE_assertMemorySafe : MemoryUnsafe a -> IO a`.
- Further safety monads may be added in the future.
- The language achieves good performance by guaranteeing a number of
optimizations:
- Since the language uses a linear type system, garbage collection
is not done; instead, values are stored on the stack unless
explicitly declared to be on the heap, and heap-stored values are
cleaned up at deterministic points as calculated at compile time.
- Functions of type `Fn t -> t` are optimized into functions that
operate on pointers to `t`, i.e., notionally, `Fn (*mut t) -> ()`,
where `*mut t` is a mutable pointer to a type `t`.
- Types that contain an optional, non-null pointer like `Option (Box
a)`, `Option (Ref a)`, etc., are optimized into nullable pointers.
- Since the language has no loops, the compiler guarantees
optimization of tail-call recursion to loops on all functions, as
is standard in functional languages.
## Compilation
When invoked with no flags, Drim by default compiles source code
directly to code that is valid C and C++, then calls the system C
compiler to generate an object file, then calls the system linker to
generate an executable file.
Drim is now hosted at [[https://codeberg.org/gkgoat/drim]].