Compare commits
No commits in common. "ab04411c93cde698199099cba0aa9ea1271811c5" and "e7716d038e7f6d46c6c4f1410676121351669106" have entirely different histories.
ab04411c93
...
e7716d038e
11 changed files with 82 additions and 400 deletions
28
Cargo.lock
generated
28
Cargo.lock
generated
|
@ -31,9 +31,9 @@ checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bumpalo"
|
name = "bumpalo"
|
||||||
version = "3.17.0"
|
version = "3.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
|
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "byteorder"
|
name = "byteorder"
|
||||||
|
@ -55,9 +55,9 @@ checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.28"
|
version = "4.5.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff"
|
checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
|
@ -65,9 +65,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.27"
|
version = "4.5.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7"
|
checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstyle",
|
"anstyle",
|
||||||
"clap_lex",
|
"clap_lex",
|
||||||
|
@ -75,9 +75,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.5.28"
|
version = "4.5.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed"
|
checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
|
@ -410,9 +410,9 @@ checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.44"
|
version = "0.38.43"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"errno",
|
"errno",
|
||||||
|
@ -457,9 +457,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.98"
|
version = "2.0.96"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
|
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
@ -519,9 +519,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.16"
|
version = "1.0.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
|
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-segmentation"
|
name = "unicode-segmentation"
|
||||||
|
|
31
default.nix
31
default.nix
|
@ -1,31 +0,0 @@
|
||||||
{ pkgs ? import <nixpkgs> { }
|
|
||||||
, stdenv ? pkgs.stdenv
|
|
||||||
, lib ? stdenv.lib
|
|
||||||
, rustPlatform ? pkgs.rustPlatform
|
|
||||||
, fetchFromGitea ? pkgs.fetchFromGitea
|
|
||||||
}:
|
|
||||||
|
|
||||||
rustPlatform.buildRustPackage rec {
|
|
||||||
pname = "talc";
|
|
||||||
version = "0.2.2";
|
|
||||||
|
|
||||||
src = fetchFromGitea {
|
|
||||||
domain = "g.trimill.xyz";
|
|
||||||
owner = "trimill";
|
|
||||||
repo = "talc";
|
|
||||||
rev = "v${version}";
|
|
||||||
hash = "sha256-QhZzSbCmawHOKRNDb0RAGX6qvRNbW0bnznA4o61+/7U=";
|
|
||||||
};
|
|
||||||
|
|
||||||
cargoHash = "sha256-yJEUmOEo2BkLyi6A+89itBMjvgXBLjwY72k6YL80ooM=";
|
|
||||||
|
|
||||||
meta = with lib; {
|
|
||||||
description = "magnesium silicate-based programming language and terminal calculator";
|
|
||||||
homepage = "https://talc.trimill.xyz/";
|
|
||||||
license = licenses.lgpl3Plus;
|
|
||||||
maintainers = [{
|
|
||||||
name = "Freya Murphy";
|
|
||||||
email = "contact@freyacat.org";
|
|
||||||
}];
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -10,6 +10,7 @@
|
||||||
|
|
||||||
- [Arithmetic](./lang/arithmetic.md)
|
- [Arithmetic](./lang/arithmetic.md)
|
||||||
- [Bitwise operators](./lang/bitwise.md)
|
- [Bitwise operators](./lang/bitwise.md)
|
||||||
|
- [Operators reference](./lang/operators.md)
|
||||||
- [Variables and scope](./lang/variables.md)
|
- [Variables and scope](./lang/variables.md)
|
||||||
- [Functions](./lang/functions.md)
|
- [Functions](./lang/functions.md)
|
||||||
- [Partial functions and pipes](./lang/partial.md)
|
- [Partial functions and pipes](./lang/partial.md)
|
||||||
|
@ -20,8 +21,5 @@
|
||||||
- [Iterators](./lang/iterators.md)
|
- [Iterators](./lang/iterators.md)
|
||||||
- [Ranges](./lang/ranges.md)
|
- [Ranges](./lang/ranges.md)
|
||||||
- [Exceptions](./lang/exceptions.md)
|
- [Exceptions](./lang/exceptions.md)
|
||||||
- [Language reference](./lang/reference.md)
|
|
||||||
- [Grammar](./lang/grammar.md)
|
|
||||||
- [Operators reference](./lang/operators.md)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,95 +0,0 @@
|
||||||
# Grammar
|
|
||||||
|
|
||||||
Some additional restrictions, such as the precedence of operators or the kinds
|
|
||||||
of expressions that are valid to assign to, are not represented here. See the
|
|
||||||
[operators reference](operators.md) for a description of operator precedence.
|
|
||||||
|
|
||||||
```grammar
|
|
||||||
program := block EOF
|
|
||||||
|
|
||||||
# LINESEP: either a semicolon or newline
|
|
||||||
block := LINESEP* (expr LINESEP+)* expr?
|
|
||||||
|
|
||||||
expr := assign
|
|
||||||
| return assign?
|
|
||||||
| break assign?
|
|
||||||
| continue
|
|
||||||
|
|
||||||
assign := pipeline | pipeline assign_op assign
|
|
||||||
|
|
||||||
assign_op := "=" | "++=" | "&=" | "#|=" | "#^=" | "#&=" | "<<=" | ">>=" | "+="
|
|
||||||
| "-=" | "*=" | "/=" | "//=" | "%=" | "^="
|
|
||||||
|
|
||||||
pipeline := lambda | pipeline "|" lambda
|
|
||||||
|
|
||||||
lambda := prec_expr
|
|
||||||
| "\" ident_list "->" lambda
|
|
||||||
| "&" lambda
|
|
||||||
|
|
||||||
# See the operators reference
|
|
||||||
prec_expr := access
|
|
||||||
| prec_expr infix_op prec_expr
|
|
||||||
| prec_expr postfix_op
|
|
||||||
| prefix_op prec_expr
|
|
||||||
|
|
||||||
infix_op := "==" | "!=" | ">" | ">=" | "<" | "<=" | "++" | "&" | ".." | "..="
|
|
||||||
| "#|" | "#^" | "#&" | "<<" | ">>" | "+" | "-" | "*" | "/" | "//"
|
|
||||||
| "%" | "^" | "and" | "or"
|
|
||||||
|
|
||||||
prefix_op := "-" | "!" | "~" | "*.." | "*..="
|
|
||||||
|
|
||||||
postfix_op := "..*"
|
|
||||||
|
|
||||||
access := term access_op*
|
|
||||||
access_op := "(" expr_list ")"
|
|
||||||
| "[" expr "]"
|
|
||||||
| "." IDENT
|
|
||||||
| "->" IDENT "(" expr_list ")"
|
|
||||||
|
|
||||||
var := term
|
|
||||||
| "global" IDENT
|
|
||||||
| "var" IDENT
|
|
||||||
| fn_decl
|
|
||||||
fn_decl := "fn" IDENT? "(" ident_list ")" fn_body
|
|
||||||
fn_body := "do" block "end"
|
|
||||||
| "=" expr
|
|
||||||
|
|
||||||
term := IDENT
|
|
||||||
| "(" expr ")"
|
|
||||||
| "[" list_items "]"
|
|
||||||
| "{" table_items "}"
|
|
||||||
| "$"
|
|
||||||
| "do" block "end"
|
|
||||||
| "if" if_stmt_chain
|
|
||||||
| "while" expr "do" block "end"
|
|
||||||
| "for" IDENT "in" expr "do" block "end"
|
|
||||||
| "try" block catch_block* "end"
|
|
||||||
| INTEGER
|
|
||||||
| FLOAT
|
|
||||||
| IMAGINARY
|
|
||||||
| STRING
|
|
||||||
| SYMBOL
|
|
||||||
| "true"
|
|
||||||
| "false"
|
|
||||||
| "nil"
|
|
||||||
| "*..*"
|
|
||||||
|
|
||||||
if_stmt_chain := expr "then" block if_stmt_end
|
|
||||||
if_stmt_end := "elif" if_stmt_chain
|
|
||||||
| "else" block "end"
|
|
||||||
| "end"
|
|
||||||
|
|
||||||
catch_block := "catch" ("*" | symbol_list) ("in" IDENT)? "do" block
|
|
||||||
symbol_list := (SYMBOL ",")* SYMBOL?
|
|
||||||
|
|
||||||
ident_list := (IDENT ",")* IDENT?
|
|
||||||
|
|
||||||
expr_list := (expr ",")* expr?
|
|
||||||
|
|
||||||
list_items := (list_item ",")* list_item?
|
|
||||||
list_item := ".."? expr
|
|
||||||
|
|
||||||
table_items := (table_item ",")* table_item?
|
|
||||||
table_item := ".." expr
|
|
||||||
| term "=" expr
|
|
||||||
```
|
|
|
@ -4,8 +4,7 @@ Lists in Talc are written as comma-separated items between square brackets.
|
||||||
Lists may be *heterogeneous* (contain items of different types). Similarly to
|
Lists may be *heterogeneous* (contain items of different types). Similarly to
|
||||||
strings, lists may be concatenated using `++`. Lists can be indexed by writing
|
strings, lists may be concatenated using `++`. Lists can be indexed by writing
|
||||||
the index in square brackets after the list. The first element of the list is
|
the index in square brackets after the list. The first element of the list is
|
||||||
at index zero. The `&` operator will add a single element to the end of a list,
|
at index zero.
|
||||||
returning a new list.
|
|
||||||
|
|
||||||
```talc
|
```talc
|
||||||
>> numbers = [1, 5, 6, 4, 2, 3]
|
>> numbers = [1, 5, 6, 4, 2, 3]
|
||||||
|
@ -14,15 +13,6 @@ returning a new list.
|
||||||
4
|
4
|
||||||
>> numbers ++ [8, 9]
|
>> numbers ++ [8, 9]
|
||||||
[1, 5, 6, 4, 2, 3, 8, 9]
|
[1, 5, 6, 4, 2, 3, 8, 9]
|
||||||
>> numbers & 7
|
|
||||||
[1, 5, 6, 4, 2, 3, 7]
|
|
||||||
```
|
|
||||||
|
|
||||||
Lists are heterogeneous, so they may contain values of different types.
|
|
||||||
|
|
||||||
```talc
|
|
||||||
>> things = [1, 2.0, "three", 4/1, :five]
|
|
||||||
[1, 2.0, "three", 4/1, :five]
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Lists are *mutable* and their elements can be assigned to or modified.
|
Lists are *mutable* and their elements can be assigned to or modified.
|
||||||
|
@ -56,69 +46,3 @@ ranges further in their own chapter.
|
||||||
>> squares[*..-3]
|
>> squares[*..-3]
|
||||||
[0, 1, 4, 9, 16]
|
[0, 1, 4, 9, 16]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Interpolation
|
|
||||||
|
|
||||||
Using the `..` operator, a list can be created by combining the elements from
|
|
||||||
multiple different collections
|
|
||||||
|
|
||||||
```talc
|
|
||||||
>> even = [2, 4, 6, 8]
|
|
||||||
[2, 4, 6, 8]
|
|
||||||
>> odd = [1, 3, 5, 7, ..even]
|
|
||||||
[1, 3, 5, 7, 2, 4, 6, 8]
|
|
||||||
>> n = [1, ..[2, 3, 4], 5, ..[6, ..[7, 8]], ..[9]]
|
|
||||||
[1, 2, 3, 4, 5, 6, 7, 8, 9]
|
|
||||||
```
|
|
||||||
|
|
||||||
Any iterator or iterable value can be used
|
|
||||||
|
|
||||||
```talc
|
|
||||||
>> squares = [..(0..10 | map(\x -> x*x))]
|
|
||||||
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
|
|
||||||
```
|
|
||||||
|
|
||||||
## Destructuring
|
|
||||||
|
|
||||||
A list can be destructured in an assignment expression as follows:
|
|
||||||
|
|
||||||
```talc
|
|
||||||
>> vals = [6, 2, 8]
|
|
||||||
[6, 2, 8]
|
|
||||||
>> [a, b, c] = vals
|
|
||||||
[6, 2, 8]
|
|
||||||
>> a
|
|
||||||
6
|
|
||||||
>> b
|
|
||||||
2
|
|
||||||
>> c
|
|
||||||
8
|
|
||||||
```
|
|
||||||
|
|
||||||
If the number of elements in the list does not match the number in the
|
|
||||||
destructure, an error is thrown.
|
|
||||||
|
|
||||||
A single interpolation may also be used to collect all remaining values. The
|
|
||||||
interpolation may occur in the beginning, middle, or end of the assignment.
|
|
||||||
|
|
||||||
```talc
|
|
||||||
>> ns = [1, 2, 3, 4, 5]
|
|
||||||
[1, 2, 3, 4, 5]
|
|
||||||
>> [a, b, ..rest] = ns
|
|
||||||
[1, 2, 3, 4, 5]
|
|
||||||
>> a
|
|
||||||
1
|
|
||||||
>> b
|
|
||||||
2
|
|
||||||
>> rest
|
|
||||||
[3, 4, 5]
|
|
||||||
>> [a, ..middle, z] = ns
|
|
||||||
[1, 2, 3, 4, 5]
|
|
||||||
>> a
|
|
||||||
1
|
|
||||||
>> middle
|
|
||||||
[2, 3, 4]
|
|
||||||
>> rest
|
|
||||||
5
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ In increasing order of precedence:
|
||||||
| `..*` | Suffix | Range from |
|
| `..*` | Suffix | Range from |
|
||||||
| `#\|` | Left | Bitwise OR |
|
| `#\|` | Left | Bitwise OR |
|
||||||
| `#^` | Left | Bitwise XOR |
|
| `#^` | Left | Bitwise XOR |
|
||||||
| `#&` | Left | Bitwise AND |
|
| `#&` | Left | Bitwise AND |
|
||||||
| `<< >>` | Left | Shift left and right |
|
| `<< >>` | Left | Shift left and right |
|
||||||
| `+ -` | Left | Add and subtract |
|
| `+ -` | Left | Add and subtract |
|
||||||
| `* / // %` | Left | Multiply, divide, integer divide, modulo |
|
| `* / // %` | Left | Multiply, divide, integer divide, modulo |
|
||||||
|
|
|
@ -1,4 +0,0 @@
|
||||||
# Language reference
|
|
||||||
|
|
||||||
These pages present a more thorough (and less guided) description of the
|
|
||||||
Talc language.
|
|
32
docs/theme/highlight.js
vendored
32
docs/theme/highlight.js
vendored
|
@ -105,35 +105,3 @@ hljs.registerLanguage('talc', function() {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
hljs.registerLanguage('grammar', function() {
|
|
||||||
const STR_RE = "'[^']*'|\"[^\"]*\"";
|
|
||||||
const TERMINAL_RE = "\\b[A-Z_]+\\b"
|
|
||||||
const OP_RE = ":=|\\||\\+|\\*|\\?|\\(|\\)"
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: "Grammar",
|
|
||||||
contains: [
|
|
||||||
{
|
|
||||||
className: 'string',
|
|
||||||
begin: STR_RE,
|
|
||||||
relevance: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
className: 'variable',
|
|
||||||
begin: TERMINAL_RE,
|
|
||||||
relevance: 0
|
|
||||||
},
|
|
||||||
{
|
|
||||||
className: 'literal',
|
|
||||||
begin: OP_RE,
|
|
||||||
relevance: 0
|
|
||||||
},
|
|
||||||
hljs.COMMENT(
|
|
||||||
'#', // begin
|
|
||||||
'\n', // end
|
|
||||||
{}
|
|
||||||
)
|
|
||||||
]
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
61
flake.lock
generated
61
flake.lock
generated
|
@ -1,61 +0,0 @@
|
||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"flake-utils": {
|
|
||||||
"inputs": {
|
|
||||||
"systems": "systems"
|
|
||||||
},
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1731533236,
|
|
||||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "numtide",
|
|
||||||
"repo": "flake-utils",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1738782063,
|
|
||||||
"narHash": "sha256-vN1z7l7DvnIPNO/iQZ3sMq5yqKX+ztNJp+aYRK40WXo=",
|
|
||||||
"owner": "nixos",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "cf574db30e0c4a23e79ea8e6d0eb160f89b49af9",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nixos",
|
|
||||||
"ref": "master",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"flake-utils": "flake-utils",
|
|
||||||
"nixpkgs": "nixpkgs"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"systems": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1681028828,
|
|
||||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "nix-systems",
|
|
||||||
"repo": "default",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
17
flake.nix
17
flake.nix
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
description = "magnesium silicate-based programming language and terminal calculator";
|
|
||||||
|
|
||||||
inputs = {
|
|
||||||
nixpkgs.url = "github:nixos/nixpkgs/master";
|
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs = { nixpkgs, flake-utils, ... }@inputs:
|
|
||||||
flake-utils.lib.eachSystem [ "x86_64-linux" "i686-linux" "aarch64-linux" ] (system: let
|
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
|
||||||
in rec {
|
|
||||||
packages.talc = pkgs.callPackage ./default.nix {};
|
|
||||||
legacyPackages = packages;
|
|
||||||
defaultPackage = packages.talc;
|
|
||||||
});
|
|
||||||
}
|
|
|
@ -272,15 +272,8 @@ impl<'s> Parser<'s> {
|
||||||
let ext = self.parse_expr()?;
|
let ext = self.parse_expr()?;
|
||||||
items.push(TableItem::Interpolate(b(ext)));
|
items.push(TableItem::Interpolate(b(ext)));
|
||||||
}
|
}
|
||||||
T::True
|
k if k.expr_first() => {
|
||||||
| T::False
|
let key = self.parse_term_not_ident()?;
|
||||||
| T::Nil
|
|
||||||
| T::Dollar
|
|
||||||
| T::Integer
|
|
||||||
| T::String
|
|
||||||
| T::Symbol
|
|
||||||
| T::LParen => {
|
|
||||||
let key = self.parse_term()?;
|
|
||||||
expect!(self, T::Equal);
|
expect!(self, T::Equal);
|
||||||
let value = self.parse_expr()?;
|
let value = self.parse_expr()?;
|
||||||
items.push(TableItem::Pair(b(key), b(value)));
|
items.push(TableItem::Pair(b(key), b(value)));
|
||||||
|
@ -406,10 +399,9 @@ impl<'s> Parser<'s> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_term(&mut self) -> Result<Expr> {
|
fn parse_term_not_ident(&mut self) -> Result<Expr> {
|
||||||
let tok = self.next()?;
|
let tok = self.next()?;
|
||||||
match tok.kind {
|
match tok.kind {
|
||||||
T::Identifier => Ok(E::Ident(Symbol::get(tok.content)).span(tok.span)),
|
|
||||||
T::LParen => {
|
T::LParen => {
|
||||||
let e = self.parse_expr()?;
|
let e = self.parse_expr()?;
|
||||||
expect!(self, T::RParen);
|
expect!(self, T::RParen);
|
||||||
|
@ -493,46 +485,26 @@ impl<'s> Parser<'s> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_fn_decl(&mut self) -> Result<Expr> {
|
fn parse_term(&mut self) -> Result<Expr> {
|
||||||
let tok_fn = expect!(self, T::Fn);
|
let Some(tok) = try_next!(self, T::Identifier | T::Var | T::Global) else {
|
||||||
let name = try_next!(self, T::Identifier).map(|t| Symbol::get(t.content));
|
return self.parse_term_not_ident()
|
||||||
expect!(self, T::LParen);
|
};
|
||||||
let args = self.parse_ident_list()?;
|
match tok.kind {
|
||||||
expect!(self, T::RParen);
|
T::Identifier => Ok(E::Ident(Symbol::get(tok.content)).span(tok.span)),
|
||||||
match expect!(self, T::Do | T::Equal).kind {
|
|
||||||
T::Do => {
|
|
||||||
let content = self.parse_block()?;
|
|
||||||
let end = expect!(self, T::End);
|
|
||||||
Ok(E::FnDef(name, args, b(content)).span(tok_fn.span + end.span))
|
|
||||||
}
|
|
||||||
T::Equal => {
|
|
||||||
let content = self.parse_expr()?;
|
|
||||||
let span = tok_fn.span + content.span;
|
|
||||||
Ok(E::FnDef(name, args, b(content)).span(span))
|
|
||||||
}
|
|
||||||
_ => unreachable!("parse_fn_decl: guaranteed by try_next!"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_var(&mut self) -> Result<Expr> {
|
|
||||||
match self.peek()?.kind {
|
|
||||||
T::Global => {
|
T::Global => {
|
||||||
let tok = self.next()?;
|
|
||||||
let ident = expect!(self, T::Identifier);
|
let ident = expect!(self, T::Identifier);
|
||||||
Ok(E::Global(Symbol::get(ident.content)).span(tok.span + ident.span))
|
Ok(E::Global(Symbol::get(ident.content)).span(tok.span + ident.span))
|
||||||
}
|
}
|
||||||
T::Var => {
|
T::Var => {
|
||||||
let tok = self.next()?;
|
|
||||||
let ident = expect!(self, T::Identifier);
|
let ident = expect!(self, T::Identifier);
|
||||||
Ok(E::Var(Symbol::get(ident.content)).span(tok.span + ident.span))
|
Ok(E::Var(Symbol::get(ident.content)).span(tok.span + ident.span))
|
||||||
}
|
}
|
||||||
T::Fn => self.parse_fn_decl(),
|
_ => unreachable!("guarenteed by try_next"),
|
||||||
_ => self.parse_term(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_access(&mut self) -> Result<Expr> {
|
fn parse_access(&mut self) -> Result<Expr> {
|
||||||
let mut lhs = self.parse_var()?;
|
let mut lhs = self.parse_term()?;
|
||||||
loop {
|
loop {
|
||||||
let tok = try_next!(self, T::LParen | T::LBrack | T::Arrow | T::Dot);
|
let tok = try_next!(self, T::LParen | T::LBrack | T::Arrow | T::Dot);
|
||||||
match tok.map(|t| t.kind) {
|
match tok.map(|t| t.kind) {
|
||||||
|
@ -679,7 +651,7 @@ impl<'s> Parser<'s> {
|
||||||
if let Some(op) = self.peek()?.kind.assign_op() {
|
if let Some(op) = self.peek()?.kind.assign_op() {
|
||||||
let lval = LValue::from_expr(lhs)?;
|
let lval = LValue::from_expr(lhs)?;
|
||||||
self.next()?;
|
self.next()?;
|
||||||
let rhs = self.parse_assign()?;
|
let rhs = self.parse_decl()?;
|
||||||
let rhs_span = rhs.span;
|
let rhs_span = rhs.span;
|
||||||
Ok(E::Assign(op, b(lval), b(rhs)).span(lhs_span + rhs_span))
|
Ok(E::Assign(op, b(lval), b(rhs)).span(lhs_span + rhs_span))
|
||||||
} else {
|
} else {
|
||||||
|
@ -687,36 +659,64 @@ impl<'s> Parser<'s> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expr(&mut self) -> Result<Expr> {
|
fn parse_fn_decl(&mut self) -> Result<Expr> {
|
||||||
|
let tok_fn = expect!(self, T::Fn);
|
||||||
|
let name = try_next!(self, T::Identifier).map(|t| Symbol::get(t.content));
|
||||||
|
expect!(self, T::LParen);
|
||||||
|
let args = self.parse_ident_list()?;
|
||||||
|
expect!(self, T::RParen);
|
||||||
|
match expect!(self, T::Do | T::Equal).kind {
|
||||||
|
T::Do => {
|
||||||
|
let content = self.parse_block()?;
|
||||||
|
let end = expect!(self, T::End);
|
||||||
|
Ok(E::FnDef(name, args, b(content)).span(tok_fn.span + end.span))
|
||||||
|
}
|
||||||
|
T::Equal => {
|
||||||
|
let content = self.parse_expr()?;
|
||||||
|
let span = tok_fn.span + content.span;
|
||||||
|
Ok(E::FnDef(name, args, b(content)).span(span))
|
||||||
|
}
|
||||||
|
_ => unreachable!("parse_fn_decl: guaranteed by try_next!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_decl(&mut self) -> Result<Expr> {
|
||||||
match self.peek()?.kind {
|
match self.peek()?.kind {
|
||||||
T::Return => {
|
T::Fn => self.parse_fn_decl(),
|
||||||
let tok = self.next()?;
|
|
||||||
if self.peek()?.kind.expr_first() {
|
|
||||||
let expr = self.parse_assign()?;
|
|
||||||
let span = expr.span;
|
|
||||||
Ok(E::Return(Some(b(expr))).span(tok.span + span))
|
|
||||||
} else {
|
|
||||||
Ok(E::Return(None).span(tok.span))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
T::Break => {
|
|
||||||
let tok = self.next()?;
|
|
||||||
if self.peek()?.kind.expr_first() {
|
|
||||||
let expr = self.parse_assign()?;
|
|
||||||
let span = expr.span;
|
|
||||||
Ok(E::Break(Some(b(expr))).span(tok.span + span))
|
|
||||||
} else {
|
|
||||||
Ok(E::Break(None).span(tok.span))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
T::Continue => {
|
|
||||||
let tok = self.next()?;
|
|
||||||
Ok(E::Continue.span(tok.span))
|
|
||||||
}
|
|
||||||
_ => self.parse_assign(),
|
_ => self.parse_assign(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parse_expr(&mut self) -> Result<Expr> {
|
||||||
|
let tok = try_next!(self, T::Return | T::Break | T::Continue);
|
||||||
|
if let Some(tok) = tok {
|
||||||
|
match tok.kind {
|
||||||
|
T::Return => {
|
||||||
|
if self.peek()?.kind.expr_first() {
|
||||||
|
let expr = self.parse_decl()?;
|
||||||
|
let span = expr.span;
|
||||||
|
Ok(E::Return(Some(b(expr))).span(tok.span + span))
|
||||||
|
} else {
|
||||||
|
Ok(E::Return(None).span(tok.span))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
T::Break => {
|
||||||
|
if self.peek()?.kind.expr_first() {
|
||||||
|
let expr = self.parse_decl()?;
|
||||||
|
let span = expr.span;
|
||||||
|
Ok(E::Break(Some(b(expr))).span(tok.span + span))
|
||||||
|
} else {
|
||||||
|
Ok(E::Break(None).span(tok.span))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
T::Continue => Ok(E::Continue.span(tok.span)),
|
||||||
|
_ => unreachable!("parse_expr: guaranteed by try_next!"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.parse_decl()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn parse_block(&mut self) -> Result<Expr> {
|
fn parse_block(&mut self) -> Result<Expr> {
|
||||||
while try_next!(self, T::LineSeparator).is_some() {}
|
while try_next!(self, T::LineSeparator).is_some() {}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue