Start adding documentation to the language
This commit is contained in:
parent
5991a75d32
commit
6f5bb51e3b
264
documentation/README.md
Normal file
264
documentation/README.md
Normal file
@ -0,0 +1,264 @@
|
||||
# Reid Language
|
||||
|
||||
This is where the documentation for this language will go, describing the
|
||||
features, syntax and standard library of the language as best as I have time and
|
||||
motivation to write.
|
||||
|
||||
Documentation is presented in a formal grammar and an example,
|
||||
syntax-highlighted with Rust, because it's close enough.
|
||||
|
||||
## Syntax
|
||||
|
||||
Syntax for Reid is very much inspired by rust, and examples of the language can
|
||||
be found in the [examples](../examples/)-folder.
|
||||
|
||||
In Reid **modules** (or files) on the top-level are comprised of imports, type
|
||||
definitions, binop-definitions and functions.
|
||||
|
||||
In formal grammar
|
||||
```bnf
|
||||
<module> :: (<import> | <type-definition> | <binop-definition> | <function>)*
|
||||
```
|
||||
|
||||
Table of Contents:
|
||||
- [Common tokens](#common-tokens)
|
||||
- [Imports](#imports)
|
||||
- [Type definitions](#type-definitions)
|
||||
- [Struct types](#struct-types)
|
||||
- [Binary operation Definitions](#binary-operation-definitions)
|
||||
- [Function definitions](#function-definition)
|
||||
- [Statement](#statement)
|
||||
- [Expression](#expression)
|
||||
|
||||
### Common tokens
|
||||
|
||||
Common token used throughout this document to express parts of grammar include:
|
||||
```bnf
|
||||
<ident> :: [a-Z]([_a-Z0-9])*
|
||||
|
||||
<literal> :: <integer> | <real> | <char> | <string> | <bool>
|
||||
<integer> :: <decimal> | <hexadecimal> | <octal> | <binary>
|
||||
<real> :: [0-9]+ "." [0-9]+
|
||||
<char> :: "'" <any-character> "'"
|
||||
<string> :: "\"" <any-character>* "\""
|
||||
<bool> :: "true" | "false"
|
||||
|
||||
// Any character (except "), or any character escaped
|
||||
<any-character> :: [.] | "\" [.]
|
||||
|
||||
<decimal> :: [0-9]+
|
||||
<hexadecimal> :: "0x" [0-9a-f]+
|
||||
<octal> :: "0o" [0-7]+
|
||||
<binary> :: "0b" [01]+
|
||||
|
||||
|
||||
<type> :: <primitive-type>
|
||||
| "[" <type> ";" <integer>] "]"
|
||||
| "*" <type>
|
||||
| "&" [ "mut" ] <type>
|
||||
|
||||
<primitive-type> ::
|
||||
"char" | "bool" |
|
||||
"u8" | "u16" | "u32" | "u64" | "u128" |
|
||||
"i8" | "i16" | "i32" | "i64" | "i128" |
|
||||
"f16" | "f32" | "f32b" | "f64" | "f80" | "f128" | "f128ppc"
|
||||
|
||||
<binop> :: "+" | "-" | "*" | "/" | "%" | "&&" | <cmp>
|
||||
<cmp> :: "<" | "<=" | "==" | "!=" | ">=" | >"
|
||||
<unary> :: "+" | "-" | "!"
|
||||
```
|
||||
|
||||
### Imports
|
||||
|
||||
Imports are used to import functions and types from other modules. In formal
|
||||
grammar the syntax for imports is
|
||||
```bnf
|
||||
<import> :: "import" <ident> "::" <ident> ";"
|
||||
```
|
||||
|
||||
An example importing the `print`-function from `std` would be
|
||||
``` rust
|
||||
import std::print;
|
||||
```
|
||||
|
||||
### Type Definitions
|
||||
|
||||
Type definitions are used to define new types. Currently this only supports
|
||||
struct-types. In formal grammar:
|
||||
```bnf
|
||||
<type-definition> :: <struct-definition>
|
||||
```
|
||||
|
||||
#### Struct types
|
||||
|
||||
Struct (or Structure) types are aggregate types containing other types within
|
||||
struct fields. In formal grammar:
|
||||
```bnf
|
||||
<struct-definition> :: "struct" <ident> "{" [ <field-def> ( "," <field-def> )* [ "," ] ] "}"
|
||||
<field-def> :: <ident> ":" <type>
|
||||
```
|
||||
|
||||
An example of a struct `Test` containing two fields `first` and `second` of
|
||||
integer types.
|
||||
```rust
|
||||
struct Test {
|
||||
first: u32,
|
||||
second: u64,
|
||||
}
|
||||
```
|
||||
|
||||
### Binary Operation Definitions
|
||||
|
||||
Reid has a feature where custom binary operations can be defined with a
|
||||
specialized syntas. Only pre-defined operators are allowed however. In formal
|
||||
grammar:
|
||||
|
||||
```bnf
|
||||
<binop-definition>: "impl" "binop" <param> <binop> <param> "-> " <type> <block>
|
||||
<param> :: "(" <ident> ":" <type> ")"
|
||||
```
|
||||
|
||||
(Block-syntax is defined formally with functions)
|
||||
|
||||
An example of a custom binary operator `+` between type `u16` and `u32` could be:
|
||||
```rust
|
||||
impl binop (lhs: u16) + (rhs: u32) -> u32 {
|
||||
return (lhs as u32) + rhs;
|
||||
}
|
||||
```
|
||||
|
||||
### Function Definition
|
||||
|
||||
Rust syntax for defining functions is similar to rust. There are two types of functions:
|
||||
1. `extern` functions which are defined in another module, used to define functions from outside modules such as `libc`.
|
||||
2. `local` functions which are defined locally in the module in Reid. Their
|
||||
definition is contained within a `block` which contains a list of
|
||||
`statement`s.
|
||||
|
||||
In formal grammar:
|
||||
```bnf
|
||||
<function-definition> :: <extern-function> | <local-function>
|
||||
<extern-function> :: "extern" "fn" <signature> ";"
|
||||
<local-function> :: [ "pub" ] "fn" <signature> <block>
|
||||
|
||||
<signature> :: <ident> "(" [ <params> ] ")" [ "->" <type> ]
|
||||
<params> <param> ( "," <param> )*
|
||||
<param> :: <ident> ":" <type>
|
||||
<block> :: "{" <statement>* "}"
|
||||
```
|
||||
|
||||
An example of a simple `extern` and `local` function definition would be:
|
||||
```rust
|
||||
extern fn puts(message: *char) -> i32;
|
||||
|
||||
fn main() -> u8 {
|
||||
return 7;
|
||||
}
|
||||
```
|
||||
|
||||
### Statement
|
||||
|
||||
Statements in Reid is how you tell the program to do anything. Currently supported statements include:
|
||||
- Let-statement to declare new variables
|
||||
- Let-statements declare immutable variables by-default, but can declare
|
||||
mutable variables with the `mut` keyword similar to Rust.
|
||||
- Set-statement to re-set previously declared (mutable) variables to new values.
|
||||
- Statements can also be simply expressions without intent to store the result.
|
||||
- Return-statements to return values out of blocks or functions.
|
||||
- For-loops to loop over a certain range of numbers
|
||||
- While-loops to loop until a certain condition is no longer met.
|
||||
|
||||
In formal grammar:
|
||||
```bnf
|
||||
<statement> :: <let> | <set> | <return> | <for> | <while> | <expr-statement>
|
||||
<let> :: "let" [ "mut" ] <ident> "=" <expression> ";"
|
||||
<set> :: <ident> "=" <expression> ";"
|
||||
<expr-statement> :: <expression> ";"
|
||||
<for> :: "for" <ident> "in" <expression> ".." <expression> <block>
|
||||
<while> :: "while" <expression> <block>
|
||||
<return> :: ( "return" <expression> ";" ) | <expression>
|
||||
```
|
||||
|
||||
An example of each statement type would be:
|
||||
```rust
|
||||
let mut value = 5;
|
||||
value = 6;
|
||||
for i in 0..5 { }
|
||||
while value < 5 { }
|
||||
|
||||
// "hard" return
|
||||
return value;
|
||||
|
||||
// "soft" return
|
||||
value
|
||||
```
|
||||
|
||||
### Expression
|
||||
|
||||
Expressions in Reid are anything that can return a value, such as function
|
||||
calls, literals, or if-expressions. Types of supported expressions include:
|
||||
- **Variable name reference**, to reference a value in a variable
|
||||
- **Borrow**, which works similar to Rust but with a little less safety. In simple
|
||||
terms it creates a safer pointer-type than a regular pointer.
|
||||
- **Deref**, which extracts the value out of a borrow.
|
||||
- **Literal**, which is just some direct value, such as a number.
|
||||
- **Array-value**, to declare a new array with a static length
|
||||
- **Struct-value**, to declare a new value for a struct that has been defined
|
||||
earlier.
|
||||
- Shorter way to declare arrays with a single initialized value.
|
||||
- **Indexing** into an array-value
|
||||
- **Accessing a field** in a struct-value
|
||||
- **Binary operations** (such as add/sub/mult)
|
||||
- **Unary operations** (such as !value or -value)
|
||||
- **Function calls**, to invoke a predefined function with given parameters
|
||||
- **Block-expressions**, which can return a value to the higher-level expression
|
||||
if they have a statement with a soft-return. Otherwise they return void.
|
||||
- **If-expressions**, which can execute one of two expressions depending on the
|
||||
given condition.
|
||||
- **Casts** to explicitly cast a value to another type.
|
||||
|
||||
Expressions can also always be surrounded by (paranthesis).
|
||||
|
||||
In formal grammar:
|
||||
```bnf
|
||||
<expression> ::
|
||||
<variable> | <borrow> |
|
||||
<deref> | <literal> |
|
||||
<array> | <struct> |
|
||||
<indexing> | <accessing> |
|
||||
<binary-exp> | <unary-exp> |
|
||||
<function-call> | <block> |
|
||||
<if-expr> | <cast> |
|
||||
( "(" <expression> ")" )
|
||||
|
||||
<variable> :: <ident>
|
||||
<borrow> :: "&" [ "mut" ] <ident>
|
||||
<deref> :: "*" <ident>
|
||||
<array> :: "[" <expression>* "]"
|
||||
<struct> :: <ident> "{" [ <field> ( "," <field> )* [ "," ] ]
|
||||
<field> :: <ident> ":" <expression>
|
||||
<indexing> :: <expression> "[" <integer> "]"
|
||||
<accessing> :: <expression> "." <ident>
|
||||
<binary-exp> :: <expression> <binop> <expression>
|
||||
<unary-exp> :: <unary> <expression>
|
||||
<function-call> :: <expression> "(" [ <expression> ( "," <expression> )* ] ")"
|
||||
<if-expr> :: "if" <expression> <expression> [ "else" <expression> ]
|
||||
<cast> :: <expression> "as" <type>
|
||||
```
|
||||
|
||||
An example of each expression in-order is:
|
||||
```rust
|
||||
varname // Variable
|
||||
&varname // Borrow
|
||||
*borrowed_varname // Deref
|
||||
[ varname, 5, 7 ] // Array
|
||||
Test { first: 4, second: 15 } // Struct
|
||||
array[0] // Indexing
|
||||
test.first // Accessing
|
||||
7 + value // Binop
|
||||
!bool_value // Unary
|
||||
func(value, 14) // Function call
|
||||
if varname {} else {} // If-expression
|
||||
value as u32 // cast
|
||||
(value + 2) // Binop within parenthesis
|
||||
```
|
Loading…
Reference in New Issue
Block a user