diff --git a/documentation/README.md b/documentation/README.md index d5101ea..8243ff1 100644 --- a/documentation/README.md +++ b/documentation/README.md @@ -12,6 +12,12 @@ syntax-highlighted with Rust, because it's close enough. Reid has a standard library that is referred to as `std` in code. Documentation about importable types and functions can be found [here](./standard_library.md). +## Book + +A collection of documentation and examples to get you going can be found at [the +Book of Reid](./book.md). It is recommended you read through the chapter about +Syntax first though to familiarize yourself with the basic concepts of Reid. + ## Syntax and general information Syntax for Reid is very much inspired by rust, and examples of the language can diff --git a/documentation/book.md b/documentation/book.md new file mode 100644 index 0000000..4fdc0cd --- /dev/null +++ b/documentation/book.md @@ -0,0 +1,122 @@ +# Book of Reid + +Welcome to the Book of Reid, a learning resource for Reid programming language. +This is neither just documentation or a tutorial, but something in between, +trying to establish basic concepts and philosophies. + +Before reading this book, it is recommended you familiarize yourself with [the +Syntax of Reid](./README.md#syntax-and-general-information). After you're +familiar with that, you can continue here. + +The best way to think about Reid is to think about how a combination of Rust's +Syntax and C's closeness to hardware would manifest itself in a language. Reid +is a very grounded language with not many safety features in reality, while +still trying to have some. Reid also has error raporting vastly superior to that +of C, similar to Rust. + +Reid also, similarly to Rust, has a powerful typechecker that can infer types +automatically quite well. When this does not pan out, you can often coerce types +either in literals by adding a type after it (e.g. `5u32`), similarly to rust, +or simply casting the value (e.g. `5 as u32`). + +## Table of Contents: +- [Hello World](#hello-world) +- [Borrowing and Pointers](#borrowing-and-pointers) + +### Hello World + +A hello world in Reid looks something like this: + +```rust +import std::print; +import std::from_str; +import std::free_string; + +fn main() { + let message = from_str("hello world"); + print(message); + free_string(&message); +} +``` + +Let's go through this example line-by-line: + +```rust +import std::print; +import std::from_str; +import std::free_string; +``` + +Tthe first 3 lines are simply imports from the [Standard +Library](./standard_library.md) to functions `print`, `from_str` and +`free_string`, which are used later in this example. + +```rust +fn main() { + ... +} +``` + +Then we declare our `main`-function. The function that gets executed after +compilation is always called `main`, and it can return a value, although it does +not necessarily have to. The return code of the program ends up being the return +value of `main`, and without a return value it may be unpredictable. In this +example we don't declare a return value for `main`. + +```rust + let message = from_str("hello world"); +``` + +Then we create our printable message with `from_str` and store it in variable +`message`. While this value could be passed to `print` directly, it is necessary +to store the value first in order to free it. Let's come back to that. + + +```rust + print(message); +``` + +Here we actually print out the message we just created, very simple. + +```rust + free_string(&message); +``` + +Finally we free the string. Like mentioned before, it is necessary to store the +value in a variable so that the memory allocated for the message can be free. +While freeing the memory is not strictly necessary, it is recommended, +especially if the program runs for longer than this example. + +That's the Hello World of Reid! It is not a oneliner, but at least I'd say it is quite simple in the end! + +### Borrowing and Pointers + +In Reid, all **variables** can be borrowed, and borrows can be dereferenced. +Borrows act like pointers, except that borrows do not have the same implicit +safety-problem as pointers, because Borrows are not implicitly unsized. With +pointers, the size of the allocated memory is unknown at compile time, which +makes them unsafe in comparisons. + +Note though how **variables** were bolded; You can not make borrows out of just any expressions, they must first be stored in variables. A simple example using borrows would be: +```rust +fn main() -> u32 { + // Create a value to be mutated + let mut value = [4, 3, 2]; + + // Pass a mutable borrow of the value + mutate(&mut value); + + // Retrieve the now-mutated value + return value[1]; +} + +fn mutate(value: &mut [u32; 3]) { + // Dereference the borrow to mutate it + *value[1] = 17; +} +``` + +This example will always return `17`. Notice also, how a **mutable** borrow was +passed to `mutate`-function. While borrows do not always need to be mutable, +this example would not work without the `mut`-keyword. Try it out for yourself +to see why! \ No newline at end of file diff --git a/examples/borrow.reid b/examples/borrow.reid index 861caa8..6afb9b1 100644 --- a/examples/borrow.reid +++ b/examples/borrow.reid @@ -1,11 +1,15 @@ -// Arithmetic, function calls and imports! - - fn main() -> u32 { - let mut value = [4, 3, 2]; + // Create a value to be mutated + let mut value = [4, 3, 2]; - let mut borrow = &mut value; - (*borrow)[1] = 17; + // Pass a mutable borrow of the value + mutate(&mut value); - return value[1]; + // Retrieve the now-mutated value + return value[1]; } + +fn mutate(value: &mut [u32; 3]) { + // Dereference the borrow to mutate it + *value[1] = 17; +} \ No newline at end of file diff --git a/examples/hello_world.reid b/examples/hello_world.reid index c9abe1e..30cca49 100644 --- a/examples/hello_world.reid +++ b/examples/hello_world.reid @@ -1,25 +1,9 @@ import std::print; import std::from_str; -import std::add_char; -import std::set_char; import std::free_string; -import std::new_string; -import std::add_num_to_str; -import std::concat_strings; fn main() { - let mut test = from_str("hello"); - - concat_strings(&mut test, from_str(" world")); - - add_char(&mut test, '!'); - add_char(&mut test, '\n'); - - add_num_to_str(&mut test, 175); - - print(test); - - free_string(&test); - - return; -} + let message = from_str("hello world"); + print(message); + free_string(&message); +} \ No newline at end of file diff --git a/examples/hello_world_harder.reid b/examples/hello_world_harder.reid new file mode 100644 index 0000000..c9abe1e --- /dev/null +++ b/examples/hello_world_harder.reid @@ -0,0 +1,25 @@ +import std::print; +import std::from_str; +import std::add_char; +import std::set_char; +import std::free_string; +import std::new_string; +import std::add_num_to_str; +import std::concat_strings; + +fn main() { + let mut test = from_str("hello"); + + concat_strings(&mut test, from_str(" world")); + + add_char(&mut test, '!'); + add_char(&mut test, '\n'); + + add_num_to_str(&mut test, 175); + + print(test); + + free_string(&test); + + return; +} diff --git a/reid/tests/e2e.rs b/reid/tests/e2e.rs index c029c36..0439ff7 100644 --- a/reid/tests/e2e.rs +++ b/reid/tests/e2e.rs @@ -101,6 +101,10 @@ fn hello_world_compiles_well() { test(include_str!("../../examples/hello_world.reid"), "test", None); } #[test] +fn hello_world_harder_compiles_well() { + test(include_str!("../../examples/hello_world_harder.reid"), "test", None); +} +#[test] fn mutable_compiles_well() { test(include_str!("../../examples/mutable.reid"), "test", Some(21)); }