Skip to content

Commit

Permalink
Auto docs
Browse files Browse the repository at this point in the history
  • Loading branch information
Seggan committed Oct 20, 2023
1 parent 478d421 commit d768dbe
Show file tree
Hide file tree
Showing 5 changed files with 359 additions and 3 deletions.
49 changes: 49 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
name: Generate Docs
on: push
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install Papyri
uses: actions-rs/toolchain@v1
with:
toolchain: stable
run: cargo install papyri-rs

- name: Generate KDoc
run: ./gradlew dokkaHtml

- name: Compile Metis
run: ./gradlew shadowJar

- name: Run the doc generator
uses: actions/setup-python@v4
with:
python-version: 3.11
run: python3 docs/gen.py

- name: Fix permissions
run: |
chmod -c -R +rX "gendocs/" | while read line; do
echo "::warning title=Invalid file permissions automatically fixed::$line"
done
- name: Upload Pages artifact
uses: actions/upload-pages-artifact@v2
deploy:
needs: build

permissions:
pages: write
id-token: write

environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
295 changes: 293 additions & 2 deletions docs/lang/index.papyri
Original file line number Diff line number Diff line change
@@ -1,5 +1,296 @@
@include `metis.lib`

@page(`The Language`)
@page(`The Language`)...

@h1 { The Language }
@h1 { The Language }

@info { This is a quick overview of the language. I do not feel like writing a full tutorial or
language reference, but this is a good place to start. }

@info { Metis is heavily based off of Lua and Python, so I will be comparing Metis with them often. }

@h2 Variables

Local variables are declared with `let`:

@metis `let x = 5`

Global variables are declared with `let global`:

@metis `let global x = 5`

The difference is that local variables are only visible in the current scope, while global variables can
be accessed from anywhere. Global variables are also stored in a global table, so they can be accessed
from other files.

@h2 Functions

Functions are declared with `fn`:

@metis `fn add(a, b) return a + b end`

Short, single expression functions can be declared with `=`:

@metis `fn add(a, b) = a + b`

Functions can be called with `()`:

@metis `add(1, 2)`

Functions can be declared global by prepending `global`:

@metis `global fn add(a, b) return a + b end`

They follow the same scoping rules as variables.

@h2 { Anonymous Functions }

The syntax above is actually syntax sugar for assigning an anonymous function to a variable. Anonymous
functions are declared with `fn`, but without a name:

@metis `fn(a, b) return a + b end`
@metis `fn(a, b) = a + b`

Functions are first class values, so they can be assigned to variables:

@metis `let add = fn(a, b) = a + b`

@h2 { Data Types }

Metis has the following data types: `null`, `boolean`, `number`, `string`, `list`, `table`, `callable`,
`native`, `bytes`, `error`, and `coroutine`. You can use the `type` function to get the type of a value:

@metis `type(5) // "number"`

Data types may also have metatables, which are tables that are used to look up missing keys. Metatables
may also have metamethods, which are functions that are called when certain operations are performed on
a value. For example, the `+` operator is actually a metamethod called `__plus__` that is called when the
`+` operator is used on a value.

@h3 Null

The `null` type has a single value, `null`. It is used to represent the absence of a value. It cannot be called,
indexed, or iterated over. It is similar to `nil` in Lua. Due to the fact that it has a single instance,
it is clearer (and faster) to use `is`/`is not` instead of `==`/`!=` to check for `null`:

@metis ```
let x = null
if x is null
print("x is null")
end
```

@h3 Booleans

The `boolean` type has two values, `true` and `false`. Its principal use is inside conditional expressions.
Unlike other literals, `true`, `false`, and `null` are global variables; they @i can be reassigned, but
this is not recommended.

@h3 Numbers

The `number` type represents a double precision floating point number. It is similar to `number` in Lua. There
is no integer type, but you can use the `math.floor` function to convert a number to an integer. There are
multiple ways to write numbers:

@metis ```
let x = 5
let y = 5.0
let z = 5e0
```

@h3 Strings

The `string` type represents a sequence of characters. Strings are immutable, so you cannot change them
after they are created. String literals are enclosed in double quotes:

@metis `let x = "hello"`

The following escape sequences are supported:

@table [
[@code `\n`, `newline`],
[@code `\r`, `carriage return`],
[@code `\t`, `tab`],
[@code `\b`, `backspace`],
[@code `\f`, `form feed`],
[@code `\\`, `backslash`],
[@code `\"`, `double quote`],
[@code `\xnn`, `hexadecimal escape`],
[@code `\unnnn`, `unicode escape`]
]

@h3 Lists

The `list` type represents a sequence of values. Lists are mutable, so you can change them after they are
created. List literals are enclosed in square brackets:

@metis `let x = [1, 2, 3]`

Lists can be indexed with `[]`:

@metis `x[0] // 1`

Lists can be iterated over with `for`:

@metis ```
for v in x
print(v)
end
```

@h3 Tables

The `table` type represents a mapping from keys to values. They are also called "maps" or "dictionaries" in
other languages. Tables are mutable, so you can change them after they are created. Table literals are
enclosed in curly braces:

@metis `let x = { "a" = 1, "b" = 2 }`

Tables can be indexed with `[]`:

@metis `x["a"] // 1`

Alternatively, you can use the `.` operator:

@metis `x.a // 1`

Tables cannot be iterated over directly, but you can iterate over their keys or values:

@metis ```
for k in x:keys()
print(k)
end
```

@metis ```
for v in x:values()
print(v)
end
```

@h3 Callables

The `callable` type represents a function or a native function. It is similar to `function` in Lua. Callables
can be called with `()`:

@metis ```
let x = fn(a, b) = a + b
x(1, 2) // 3
```

@h3 Natives

Natives are values which are backed by an object not written in Metis. They are similar to `userdata` in Lua.
The object returned by `string.builder` is an example of a native (it is backed by a `java.lang.StringBuilder` object).

@h3 Bytes

The `bytes` type represents a sequence of bytes. Bytes are mutable, so you can change them after they are
created. Byte literals are enclosed in single quotes:

@metis `let x = 'hello'`

Bytes can be indexed with `[]`:

@metis `x[0] // 104`

Bytes can be iterated over with `for`:

@metis ```
for v in x
print(v)
end
```

Bytes can be converted to strings using `decode`, and strings can be converted to bytes using `encode`:

@metis ```
let x = 'hello'
let y = x:decode() // "hello"
let z = y:encode() // 'hello'
```

@h3 Errors

The `error` type represents an error. Errors have a type, a message, and an optional "companion table".
Errors are created with the keyword `error`:

@metis `let err = error TheTypeOfTheError("a message") : { "key" = "value" }`

Errors can be thrown with `raise`:

@metis `raise err`

Errors can be caught with `try`:

@metis ```
try
raise err
catch err = TheTypeOfTheError
print("caught " + str(err))
print(err.message)
print(err.key)
end
```

@h3 Coroutines

The `coroutine` type represents a coroutine. It is similar to `thread` in Lua. Coroutines can be created
with `coroutine.create`:

@metis ```
let x = coroutine.create(fn()
print("hello")
end)
```

Coroutines can be run with `coroutine.run`:

@metis `x:run() // "hello"`

@h2 { Operators }

Metis has a set of operators that may or may not be overloaded. They are listed in order of decreasing precedence:

`[]`, `()`, `.`, and `:`; these are used to index tables and call callables. There is no way to overload
calling, but as `.` and `:` are various forms of syntax sugar for `[]`, they can be overloaded using
the metamethod `__index__`.

`not` and unary `-`; these are used to negate booleans and numbers. Only `-` can be overloaded using
`__neg__`.

`*`, `/`, and `%`; these are used to multiply, divide, and modulo numbers. They can be overloaded using
`__times__`, `__div__`, and `__mod__`.

`+` and `-`; these are used to add and subtract numbers. `+` is also used for concatenating strings and
adding to lists and tables. They can be overloaded using `__plus__` and `__minus__`.

`..<` and `..=`; exclusive and inclusive range. Can be overloaded with `__range__` and `__inclrange__`.

`?:`, also known as the elvis operator, is used to provide a default value in case a value is null.
For example, `x ?: 1` will return `1` is `x` is null, and `x` otherwise. It cannot be overloaded.

`in`, `not in`, `is`, and `is not`; these are used to check if a value is in a list or table, or if
two values are the same exact object. `in` and `not in` can be overloaded using `__contains__`.

`<`, `<=`, `>`, and `>=`; these are used to compare values. They all use the same metamethod for overloading:
`__cmp__`. The metamethod should return a negative number if the left value is less than the right value,
a positive number if the left value is greater than the right value, and zero if the left value is equal
to the right value.

`==` and `!=`; these are used to check if two values are equal or not. They can be overloaded using
`__eq__`.

`and`; returns `true` if both values are true, and `false` otherwise. It cannot be overloaded. It also
short circuits, so if the left value is false, the right value is not evaluated.

`or`; returns `true` if either value is true, and `false` otherwise. It cannot be overloaded. It also
short circuits, so if the left value is true, the right value is not evaluated.

`? else` is the ternary operator. It is used as a shorter form of `if`:

@metis `x ? 1 else 2`

The above code returns `1` if `x` is true, and `2` otherwise. It cannot be overloaded.

@h1 TODO
12 changes: 12 additions & 0 deletions docs/metis.lib.papyri
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,18 @@
@code_block(language=.) $v
}

@fn tbl_row $row: inline list -> @match $row {
[$a, *$tail] -> { <td>$a</> @tbl_row $tail },
[] -> {},
}

@fn tbl_rows $rows: inline list list -> @match $rows {
[$a, *$tail] -> { <tr> @tbl_row $a </tr> @tbl_rows $tail },
[] -> {},
}

@export @fn table $tbl: inline list list -> { <table> @tbl_rows $tbl </> }



@fn get_headings $content: html -> @match $content {
Expand Down
4 changes: 4 additions & 0 deletions docs/static/metis.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,8 @@

.highlight {
font-family: "Fira Code", monospace;
}

table, tr, td {
border: black 1px;
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ class Lexer(private val source: CodeSource) {
}

init {
regex("//.*\\n", Token.Type.COMMENT)
regex("//.*(?:\\n|$)", Token.Type.COMMENT)
text("(", Token.Type.OPEN_PAREN)
text(")", Token.Type.CLOSE_PAREN)
text("{", Token.Type.OPEN_BRACE)
Expand Down

0 comments on commit d768dbe

Please sign in to comment.