Start work on mdbook.
This commit is contained in:
parent
88487a911e
commit
7d7626809d
1
dm-book/.gitignore
vendored
Normal file
1
dm-book/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
book
|
||||||
4
dm-book/book.toml
Normal file
4
dm-book/book.toml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
[book]
|
||||||
|
title = "Deimos Lang"
|
||||||
|
authors = ["Jesse Brault"]
|
||||||
|
language = "en"
|
||||||
43
dm-book/src/README.md
Normal file
43
dm-book/src/README.md
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
# Introduction
|
||||||
|
|
||||||
|
Greetings! This is the manual for **Deimos Lang**, a programming language created by Jesse Brault. Deimos has the
|
||||||
|
planned following features:
|
||||||
|
|
||||||
|
- Basic object-oriented features and semantics, including interfaces, classes, and records.
|
||||||
|
- Enumerated (union) types like Rust/OCaml.
|
||||||
|
- Traits, which function similar to Rust traits or Haskell type-classes.
|
||||||
|
- Closures, including those with delegates like Groovy or Kotlin.
|
||||||
|
- Compile-time metaprogramming with template-like constructs.
|
||||||
|
- The usual imperative constructs: if/else, for/while loops, etc.
|
||||||
|
- Functional features, borrowed from languages such as OCaml, Rust, Haskell:
|
||||||
|
pattern matching, persistent data structures, and tail recursion.
|
||||||
|
- Static name-resolution and type-checking, with compiler type-inference as much as possible.
|
||||||
|
- Optional fully-dynamic dispatch via `dyn` keyword, providing runtime method/property lookup like Groovy or Ruby.
|
||||||
|
- A fast foreign-function interface FFI for calling native Rust functions.
|
||||||
|
|
||||||
|
Deimos is compiled for the **Deimos Virtual Machine** (DVM), a VM like those of Java and Lua in spirit but with a Rust
|
||||||
|
implementation and access to the rest of the Rust (and C, via Rust) ecosystem. The ultimate goal is to be able to run
|
||||||
|
Deimos and Lua side-by-side on the DVM, allowing applications both a statically typed language like Deimos to function
|
||||||
|
alongside and interface with a much more relaxed language like Lua.
|
||||||
|
|
||||||
|
## Hello, World!
|
||||||
|
|
||||||
|
Since it's standard practice to offer the classic Hello World program, let's get started!
|
||||||
|
|
||||||
|
```deimos
|
||||||
|
fn main()
|
||||||
|
println("Hello, World!")
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Sometimes we just need to dump a string to the terminal, so `println` is available by default in all scopes. Indeed, all
|
||||||
|
items in the `std::core` module are imported by default to each file/module. In this case, the fully-qualified name of
|
||||||
|
`println` is `std::core::println`, and is located in the `print.dm` file under `std/core`:
|
||||||
|
|
||||||
|
```deimos
|
||||||
|
pub extern fn println(message: Any) -> Void
|
||||||
|
```
|
||||||
|
|
||||||
|
Here, `println` is declared as an `extern` function, meaning its implementation is provided by a native function at
|
||||||
|
runtime. We can also see that it takes one parameter of type `Any`—where `Any` is the catchall super-type of all types
|
||||||
|
in the language. `Void` takes its usual meaning.
|
||||||
6
dm-book/src/SUMMARY.md
Normal file
6
dm-book/src/SUMMARY.md
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# Summary
|
||||||
|
|
||||||
|
[Introduction](README.md)
|
||||||
|
|
||||||
|
- [Getting Started](getting_started.md)
|
||||||
|
- [Implementing Array List](./impl_array_list.md)
|
||||||
159
dm-book/src/getting_started.md
Normal file
159
dm-book/src/getting_started.md
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
# Chapter 1: Getting Started
|
||||||
|
|
||||||
|
Deimos can be run both interactively via a read-eval-print loop (REPL) or by compiling and running a given source file.
|
||||||
|
|
||||||
|
## REPL
|
||||||
|
|
||||||
|
The REPL allows interactive programming similar to classic functional languages as well as Ruby. To start the REPL, run:
|
||||||
|
|
||||||
|
```
|
||||||
|
dm repl
|
||||||
|
```
|
||||||
|
|
||||||
|
### Basics
|
||||||
|
|
||||||
|
All statements and expressions in the REPL are scoped under a synthetic function; in other words, variables persist
|
||||||
|
through each input:
|
||||||
|
|
||||||
|
```
|
||||||
|
> let x = 2
|
||||||
|
> x
|
||||||
|
2
|
||||||
|
> let y = 3
|
||||||
|
> x + y
|
||||||
|
5
|
||||||
|
```
|
||||||
|
|
||||||
|
In addition to statements and expressions, functions can be defined in scope:
|
||||||
|
|
||||||
|
```
|
||||||
|
> fn double(x: Int) x * 2 end
|
||||||
|
> double(4)
|
||||||
|
8
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that variables in the "top" scope are not available inside defined functions:
|
||||||
|
|
||||||
|
```
|
||||||
|
> let x = 7
|
||||||
|
> fn doubleX() x * 2 end
|
||||||
|
Error: Symbol x could not be found.
|
||||||
|
```
|
||||||
|
|
||||||
|
This requires the use of closures, which can "capture" variables in their containing scope:
|
||||||
|
|
||||||
|
```
|
||||||
|
> let x = 42
|
||||||
|
> let doubleX = { x * 2 }
|
||||||
|
> doubleX()
|
||||||
|
84
|
||||||
|
```
|
||||||
|
|
||||||
|
Note the difference in syntax between function declarations and closure declarations. As we will later see, closures are
|
||||||
|
powerful constructs.
|
||||||
|
|
||||||
|
### Introduction to Classes
|
||||||
|
|
||||||
|
Classes can also be defined in the REPL:
|
||||||
|
|
||||||
|
```
|
||||||
|
> class Dog \
|
||||||
|
pub name: String \
|
||||||
|
pub ctor(name: String) \
|
||||||
|
self.name = name \
|
||||||
|
end \
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
A few things are going on here. First, note the use the backslash to indicate that we are not done with our input
|
||||||
|
(normally, a newline without a preceding backslash will cause the interpreter to consume everything input so far). Next,
|
||||||
|
note our syntax for declaring a class, with hints of Rust and Ruby:
|
||||||
|
|
||||||
|
- `class` keyword: the usual meaning
|
||||||
|
- `pub` keyword: makes a property or method available outside the class (i.e., non-private)
|
||||||
|
- `: Type` annotations: indicates the type of a property, parameter, or variable.
|
||||||
|
- `ctor` keyword: marks a constructor. *Note: Classes can only have **one** constructor*.
|
||||||
|
- `self` keyword, followed by property name: like the usual construct in OOP languages.
|
||||||
|
|
||||||
|
Once we've defined our class, we can use it:
|
||||||
|
|
||||||
|
```
|
||||||
|
> let bear = Dog("Bear")
|
||||||
|
> let skye = Dog("Skye")
|
||||||
|
> bear.name
|
||||||
|
Bear
|
||||||
|
> skye.name
|
||||||
|
Skye
|
||||||
|
```
|
||||||
|
|
||||||
|
Note above how we construct instances of the class by "calling" the class, exactly like we do in Kotlin.
|
||||||
|
|
||||||
|
#### Class Declaration Short Form
|
||||||
|
|
||||||
|
The above class example is a bit verbose; Deimos offers the following equivalent, inspired by Kotlin:
|
||||||
|
|
||||||
|
```
|
||||||
|
class Dog(pub name: String) end
|
||||||
|
```
|
||||||
|
|
||||||
|
This is especially useful in the REPL, where we may just want to declare a data type for doing some data processing.
|
||||||
|
|
||||||
|
```
|
||||||
|
> class Point(pub x: Int, pub y: Int) end
|
||||||
|
> fn double(p: Point) Point(p.x * 2, p.y * 2) end
|
||||||
|
> let a = Point(3, 4)
|
||||||
|
> double(a)
|
||||||
|
Point(6, 8)
|
||||||
|
> let b = Point(5, 6)
|
||||||
|
> double(double(b))
|
||||||
|
Point(20, 24)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Compiling and Running Files
|
||||||
|
|
||||||
|
To compile and run a file, do:
|
||||||
|
|
||||||
|
```
|
||||||
|
dm run <your file name here>.dm
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that the `.dm` extension is required in the command name (unlike `java`).
|
||||||
|
|
||||||
|
The above command will compile and immediately run the file. In order for a Deimos file to be executable, it must
|
||||||
|
contain a `main` function like the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
fn main()
|
||||||
|
println("Hello, Deimos!")
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
Unlike the REPL, statements and expressions are not allowed in the top-level scope; they must be contained in a function
|
||||||
|
or method:
|
||||||
|
|
||||||
|
```
|
||||||
|
let x = 10 // ERROR! Will not parse.
|
||||||
|
```
|
||||||
|
|
||||||
|
However, functions, classes, and other top-level constructs are allowed:
|
||||||
|
|
||||||
|
```
|
||||||
|
fn double(p: Point) -> Point
|
||||||
|
Point(p.x * 2, p.y * 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
class Point(x: Int, y: Int) end
|
||||||
|
|
||||||
|
fn main()
|
||||||
|
let a = Point(1, 2)
|
||||||
|
let b = Point(3, 4)
|
||||||
|
println(double(a)) // Point(2, 4)
|
||||||
|
println(double(b)) // Point(6, 8)
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
let f = { a, b -> a + b } << 4
|
||||||
|
let x = f(5)
|
||||||
|
println(x) // 9
|
||||||
|
```
|
||||||
296
dm-book/src/impl_array_list.md
Normal file
296
dm-book/src/impl_array_list.md
Normal file
@ -0,0 +1,296 @@
|
|||||||
|
# Implementing Array List
|
||||||
|
|
||||||
|
```
|
||||||
|
trait Map<T>
|
||||||
|
fn <U> map(f: fn (T) -> U) -> Self<U>
|
||||||
|
end
|
||||||
|
|
||||||
|
trait Index<I>
|
||||||
|
type Output
|
||||||
|
|
||||||
|
op fn [] (index: I) -> Self::Output
|
||||||
|
end
|
||||||
|
|
||||||
|
trait Cons<T>
|
||||||
|
fn cons(t: T) -> Self<T>
|
||||||
|
fn head() -> Option<T>
|
||||||
|
fn tail() -> Self<T>
|
||||||
|
end
|
||||||
|
|
||||||
|
trait Default
|
||||||
|
static fn default() -> Self
|
||||||
|
end
|
||||||
|
|
||||||
|
int Iterable<T>
|
||||||
|
fn iter() -> Iterator<T>
|
||||||
|
|
||||||
|
def fn each(f: fn (T) -> Void)
|
||||||
|
for t in self
|
||||||
|
f(t)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
int Iterator<T>
|
||||||
|
fn next() -> Option<T>
|
||||||
|
end
|
||||||
|
|
||||||
|
#[intrinsic]
|
||||||
|
class Array<T> : Iterable<T>
|
||||||
|
pub extern static fn <T: Default> sized(size: Size) -> Array<T>
|
||||||
|
|
||||||
|
#[intrinsic]
|
||||||
|
pub fn len() -> Size end
|
||||||
|
|
||||||
|
#[intrinsic]
|
||||||
|
pub fn getAt(index: Size) -> T end
|
||||||
|
|
||||||
|
pub fn iter()
|
||||||
|
let mut i = 0
|
||||||
|
let iterator = {
|
||||||
|
if i < len() then
|
||||||
|
let next = Some(getAt(i))
|
||||||
|
i++
|
||||||
|
next
|
||||||
|
else
|
||||||
|
None
|
||||||
|
end
|
||||||
|
}
|
||||||
|
iterator
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
record Range<T>(start: T, end: T) end
|
||||||
|
|
||||||
|
impl<T> Index<Size> for Array<T>
|
||||||
|
type Output = T
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
op fn [] (index) = getAt(index)
|
||||||
|
end
|
||||||
|
|
||||||
|
impl<T> Index<Range<Size>> for Array<T>
|
||||||
|
type Output = Self<T>
|
||||||
|
|
||||||
|
op fn [] (range)
|
||||||
|
let ts = Self(range.end() - range.start())
|
||||||
|
for i in range do
|
||||||
|
ts[i] = self[i]
|
||||||
|
end
|
||||||
|
ts
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
impl<T: Default> Cons<T> for Array<T>
|
||||||
|
fn cons(t)
|
||||||
|
let ts = Array::<T>(len() + 1)
|
||||||
|
ts[0] = t
|
||||||
|
for i in 0..len() do
|
||||||
|
ts[i + 1] = self[i]
|
||||||
|
end
|
||||||
|
ts
|
||||||
|
end
|
||||||
|
|
||||||
|
fn head(t)
|
||||||
|
if len() > 0 then
|
||||||
|
self[0]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
fn tail()
|
||||||
|
if len() > 0 then
|
||||||
|
self[1..]
|
||||||
|
else
|
||||||
|
[]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
int List<T> : Iterable<T>
|
||||||
|
fn len() -> Size
|
||||||
|
fn getAt(index: Size) -> Option<T>
|
||||||
|
fn slice(range: Range<Size>) -> Self<T>
|
||||||
|
|
||||||
|
mut fn add(t: T) -> Void
|
||||||
|
mut fn addAll(ts: Iterable<T>) -> Void
|
||||||
|
|
||||||
|
def mut op fn << (t: T) -> Void = add(t)
|
||||||
|
def mut op fn << (ts: Iterable<T>) -> Void = addAll(ts)
|
||||||
|
|
||||||
|
mut fn insert(t: T, index: Size) -> Void
|
||||||
|
|
||||||
|
def fn iter()
|
||||||
|
let mut i = 0
|
||||||
|
let iterator = {
|
||||||
|
if i < len() then
|
||||||
|
let next = getAt(i)
|
||||||
|
i++
|
||||||
|
next
|
||||||
|
else
|
||||||
|
None
|
||||||
|
end
|
||||||
|
}
|
||||||
|
iterator
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
impl<T> Map<T> for List<T>
|
||||||
|
fn map(f) = match self
|
||||||
|
[] => [],
|
||||||
|
head :: tail => f(head) :: tail.map(f)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
impl<T> Cons<T> for List<T>
|
||||||
|
fn cons(t)
|
||||||
|
let l = ArrayList(self.len() + 1)
|
||||||
|
l << t
|
||||||
|
l += self
|
||||||
|
l
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
impl<T> Index<Size> for List<T>
|
||||||
|
type Output = Option<T>
|
||||||
|
|
||||||
|
op fn [] (index) = getAt(index)
|
||||||
|
end
|
||||||
|
|
||||||
|
impl<T> Index<Range<Size>> for List<T>
|
||||||
|
type Output = Self<T>
|
||||||
|
|
||||||
|
op fn [] (range) = slice(range)
|
||||||
|
end
|
||||||
|
|
||||||
|
int UnsafeIterable<T>
|
||||||
|
fn iter() -> UnsafeIterator<T>
|
||||||
|
end
|
||||||
|
|
||||||
|
int UnsafeIterator<T>
|
||||||
|
unsafe fn next() -> Option<T> throws NullPointerException
|
||||||
|
|
||||||
|
def fn tryNext() -> Result<Option<T>, NullPointerException>
|
||||||
|
try
|
||||||
|
Ok(next())
|
||||||
|
catch e: NullPointerException
|
||||||
|
Err(e)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
#[intrinsic]
|
||||||
|
class MaybeUninitArray<T> : UnsafeIterable<T>
|
||||||
|
pub extern static fn <T> sized(size: Size) -> Self<T>
|
||||||
|
|
||||||
|
#[intrinsic]
|
||||||
|
pub fn len() -> Size end
|
||||||
|
|
||||||
|
#[intrinsic]
|
||||||
|
pub unsafe fn getAt(index: Size) -> T throws NullPointerException end
|
||||||
|
|
||||||
|
class MaybeUninitIterator<T>(parent: MaybeUninitArray<T>) : UnsafeIterator<T>
|
||||||
|
mut i: Size = 0
|
||||||
|
|
||||||
|
pub unsafe fn next() -> Option<T> throws NullPointerException
|
||||||
|
if i < parent.len()
|
||||||
|
let next = parent.getAt(i)
|
||||||
|
i++
|
||||||
|
next
|
||||||
|
else
|
||||||
|
None
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
pub unsafe fn iter()
|
||||||
|
MaybeUninitIterator(self)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class ArrayList<T> : List<T>
|
||||||
|
#[get]
|
||||||
|
mut len: Size = 0
|
||||||
|
|
||||||
|
mut ts = {% if T has Default then %}
|
||||||
|
Array<T>
|
||||||
|
{% else %}
|
||||||
|
MaybeUninitArray<T>
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
pub ctor(capacity: Size)
|
||||||
|
ts = {% if T has Default then %}
|
||||||
|
Array::sized::<T>(capacity)
|
||||||
|
%{ else %}
|
||||||
|
MaybeUninitArray::sized::<T>(capacity)
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
|
||||||
|
pub fn getAt(index)
|
||||||
|
{% if T has Default then %}
|
||||||
|
index < len ? Some(ts[index]) : None
|
||||||
|
{% else %}
|
||||||
|
if index < len then
|
||||||
|
try
|
||||||
|
Some(ts[index])
|
||||||
|
catch e: NullPointerException
|
||||||
|
None
|
||||||
|
end
|
||||||
|
else
|
||||||
|
None
|
||||||
|
end
|
||||||
|
{% end %}
|
||||||
|
end
|
||||||
|
|
||||||
|
pub fn slice(range)
|
||||||
|
/* some implementation */
|
||||||
|
end
|
||||||
|
|
||||||
|
mut fn maybeGrow()
|
||||||
|
if len + 1 == ts.len() then
|
||||||
|
let newSize = len * 2 // or whatever factor
|
||||||
|
|
||||||
|
let newTs = {% if T has Default then %}
|
||||||
|
Array::sized::<T>(newSize)
|
||||||
|
{% else %}
|
||||||
|
MaybeUninitArray::sized::<T>(newSize)
|
||||||
|
{% end %}
|
||||||
|
|
||||||
|
for i in 0..ts.len() do
|
||||||
|
newTs[i] = ts[i]
|
||||||
|
end
|
||||||
|
ts = newTs
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
pub mut fn add(t)
|
||||||
|
maybeGrow()
|
||||||
|
ts[len] = t
|
||||||
|
len++
|
||||||
|
end
|
||||||
|
|
||||||
|
pub mut fn addAll(ts)
|
||||||
|
ts.each { add(it) }
|
||||||
|
end
|
||||||
|
|
||||||
|
pub mut fn insert(t, i)
|
||||||
|
maybeGrow()
|
||||||
|
let mut previous = None
|
||||||
|
for i in i..len() do
|
||||||
|
match previous with
|
||||||
|
Some(p) => do
|
||||||
|
let cur = ts[i]
|
||||||
|
ts[i] = p
|
||||||
|
previous = Some(cur)
|
||||||
|
end
|
||||||
|
None => do
|
||||||
|
previous = Some(ts[i])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
ts[i] = t
|
||||||
|
len++
|
||||||
|
end
|
||||||
|
end
|
||||||
|
```
|
||||||
Loading…
Reference in New Issue
Block a user