mirror of
https://github.com/erg-lang/erg.git
synced 2025-09-29 20:34:44 +00:00
Merge branch 'main' into dict
This commit is contained in:
commit
c784ba261e
53 changed files with 1336 additions and 818 deletions
|
@ -12,6 +12,14 @@ cmp = "run -- --mode compile"
|
||||||
ex = "run -- --mode exec"
|
ex = "run -- --mode exec"
|
||||||
read = "run -- --mode read"
|
read = "run -- --mode read"
|
||||||
|
|
||||||
|
dlex = "run --features debug -- --mode lex"
|
||||||
|
dprs = "run --features debug -- --mode parse"
|
||||||
|
dlwr = "run --features debug -- --mode lower"
|
||||||
|
dchk = "run --features debug -- --mode check"
|
||||||
|
dcmp = "run --features debug -- --mode compile"
|
||||||
|
dex = "run --features debug -- --mode exec"
|
||||||
|
dread = "run --features debug -- --mode read"
|
||||||
|
|
||||||
rd = "run --features debug"
|
rd = "run --features debug"
|
||||||
rd_ja = "run --features debug --features japanese"
|
rd_ja = "run --features debug --features japanese"
|
||||||
rd_zh_cn = "run --features debug --features simplified_chinese"
|
rd_zh_cn = "run --features debug --features simplified_chinese"
|
||||||
|
|
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -1,29 +0,0 @@
|
||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Create a report to help us improve
|
|
||||||
title: ''
|
|
||||||
labels: bug
|
|
||||||
assignees: ''
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**Reproducible code**
|
|
||||||
Or steps to reproduce the behavior:
|
|
||||||
|
|
||||||
**Expected behavior**
|
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
|
||||||
**Result**
|
|
||||||
|
|
||||||
**Screenshots (optional)**
|
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
|
||||||
**OS**
|
|
||||||
e.g. Windows 11 (WSL2)
|
|
||||||
If it is an obvious environment-independent bug (e.g. type inference bug), it is not necessary
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context about the problem here.
|
|
58
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
58
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
name: 🐛 Bug report
|
||||||
|
description: Create a report to help us improve
|
||||||
|
labels:
|
||||||
|
- bug
|
||||||
|
body:
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Describe the bug?
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Reproducible code
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Expected result
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Actual result
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
attributes:
|
||||||
|
label: Additional context
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: Erg version
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: input
|
||||||
|
attributes:
|
||||||
|
label: Python version
|
||||||
|
validations:
|
||||||
|
required: false
|
||||||
|
|
||||||
|
- type: dropdown
|
||||||
|
attributes:
|
||||||
|
label: os
|
||||||
|
options:
|
||||||
|
- Windows 10
|
||||||
|
- Windows 11
|
||||||
|
- MacOS 12 (Monterey)
|
||||||
|
- MacOS 11 (Big Sur)
|
||||||
|
- Ubuntu
|
||||||
|
- Linux(other distro)
|
||||||
|
- Other (write in `Additional context`)
|
25
Cargo.lock
generated
25
Cargo.lock
generated
|
@ -2,20 +2,9 @@
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "atty"
|
|
||||||
version = "0.2.14"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg"
|
name = "erg"
|
||||||
version = "0.5.7"
|
version = "0.5.9-nightly.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_compiler",
|
"erg_compiler",
|
||||||
|
@ -25,14 +14,16 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_common"
|
name = "erg_common"
|
||||||
version = "0.5.7"
|
version = "0.5.9-nightly.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"atty",
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_compiler"
|
name = "erg_compiler"
|
||||||
version = "0.5.7"
|
version = "0.5.9-nightly.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_parser",
|
"erg_parser",
|
||||||
|
@ -41,14 +32,14 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_parser"
|
name = "erg_parser"
|
||||||
version = "0.5.7"
|
version = "0.5.9-nightly.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "erg_type"
|
name = "erg_type"
|
||||||
version = "0.5.7"
|
version = "0.5.9-nightly.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"erg_common",
|
"erg_common",
|
||||||
"erg_parser",
|
"erg_parser",
|
||||||
|
|
18
Cargo.toml
18
Cargo.toml
|
@ -1,6 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "erg"
|
name = "erg"
|
||||||
version = "0.5.7"
|
version = "0.5.9-nightly.0"
|
||||||
description = "The Erg programming language"
|
description = "The Erg programming language"
|
||||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
|
@ -18,6 +18,14 @@ members = [
|
||||||
"compiler/erg_type",
|
"compiler/erg_type",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[workspace.package]
|
||||||
|
version = "0.5.9-nightly.0"
|
||||||
|
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
edition = "2021"
|
||||||
|
repository = "https://github.com/erg-lang/erg"
|
||||||
|
homepage = "https://erg-lang.org/"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# when "debug" feature is turned on, that of the following crates will also be turned on.
|
# when "debug" feature is turned on, that of the following crates will also be turned on.
|
||||||
debug = [
|
debug = [
|
||||||
|
@ -47,10 +55,10 @@ traditional_chinese = [
|
||||||
pre-commit = []
|
pre-commit = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erg_common = { version = "0.5.7", path = "./compiler/erg_common" }
|
erg_common = { version = "0.5.9-nightly.0", path = "./compiler/erg_common" }
|
||||||
erg_parser = { version = "0.5.7", path = "./compiler/erg_parser" }
|
erg_parser = { version = "0.5.9-nightly.0", path = "./compiler/erg_parser" }
|
||||||
erg_compiler = { version = "0.5.7", path = "./compiler/erg_compiler" }
|
erg_compiler = { version = "0.5.9-nightly.0", path = "./compiler/erg_compiler" }
|
||||||
erg_type = { version = "0.5.7", path = "./compiler/erg_type" }
|
erg_type = { version = "0.5.9-nightly.0", path = "./compiler/erg_type" }
|
||||||
|
|
||||||
# [workspace]
|
# [workspace]
|
||||||
# member = ["cm", "dyne"]
|
# member = ["cm", "dyne"]
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<img width="500" src="./assets/erg_logo_with_slogan.svg">
|
<img width="500" src="./assets/erg_logo_with_slogan.svg">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>This is the main source code repository for [Erg](https://erg-lang.github.io/). This contains the compiler and documentation.
|
<br>This is the main source code repository for [Erg](https://erg-lang.org/). This contains the compiler and documentation.
|
||||||
|
|
||||||
<p align='center'>
|
<p align='center'>
|
||||||
<a href="https://github.com/erg-lang/erg/releases"><img alt="Build status" src="https://img.shields.io/github/v/release/erg-lang/erg.svg"></a>
|
<a href="https://github.com/erg-lang/erg/releases"><img alt="Build status" src="https://img.shields.io/github/v/release/erg-lang/erg.svg"></a>
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<img width="500" src="./assets/erg_logo_with_slogan.svg">
|
<img width="500" src="./assets/erg_logo_with_slogan.svg">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>こちらは[Erg](https://mtshiba.github.io/TheErgBook)のメインリポジトリです。コンパイラとドキュメントが置かれています。
|
<br>こちらは[Erg](https://erg-lang.org/)のメインリポジトリです。コンパイラとドキュメントが置かれています。
|
||||||
|
|
||||||
<p align='center'>
|
<p align='center'>
|
||||||
<a href="https://github.com/erg-lang/erg/releases"><img alt="Build status" src="https://img.shields.io/github/v/release/erg-lang/erg.svg"></a>
|
<a href="https://github.com/erg-lang/erg/releases"><img alt="Build status" src="https://img.shields.io/github/v/release/erg-lang/erg.svg"></a>
|
||||||
|
@ -12,8 +12,8 @@
|
||||||
<br>
|
<br>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
[
|
[
|
||||||
](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=README.md&commit_hash=f2118ff45d9e46ca8fa44242363223be43b046dd)
|
](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=README.md&commit_hash=1a66848fd63479093d0d7995712571e3fdc6bd92)
|
||||||
|
|
||||||
## Ergはこんな人におすすめです:
|
## Ergはこんな人におすすめです:
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<img width="500" src="./assets/erg_logo_with_slogan.svg">
|
<img width="500" src="./assets/erg_logo_with_slogan.svg">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>这是[Erg](https://erg-lang.github.io/)的主要源代码库。它包含编译器和文档。
|
<br>这是[Erg](https://erg-lang.org/)的主要源代码库。它包含编译器和文档。
|
||||||
|
|
||||||
<p align='center'>
|
<p align='center'>
|
||||||
<a href="https://github.com/erg-lang/erg/releases"><img alt="Build status" src="https://img.shields.io/github/v/release/erg-lang/erg.svg"></a>
|
<a href="https://github.com/erg-lang/erg/releases"><img alt="Build status" src="https://img.shields.io/github/v/release/erg-lang/erg.svg"></a>
|
||||||
|
@ -12,8 +12,8 @@
|
||||||
<br>
|
<br>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
[
|
[
|
||||||
](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=README.md&commit_hash=f2118ff45d9e46ca8fa44242363223be43b046dd)
|
](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=README.md&commit_hash=1a66848fd63479093d0d7995712571e3fdc6bd92)
|
||||||
|
|
||||||
## Erg可以推荐给以下人员:
|
## Erg可以推荐给以下人员:
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
<img width="500" src="./assets/erg_logo_with_slogan.svg">
|
<img width="500" src="./assets/erg_logo_with_slogan.svg">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>這是[Erg](https://erg-lang.github.io/)的主要源代碼庫。它包含編譯器和文檔。
|
<br>這是[Erg](https://erg-lang.org/)的主要源代碼庫。它包含編譯器和文檔。
|
||||||
|
|
||||||
<p align='center'>
|
<p align='center'>
|
||||||
<a href="https://github.com/erg-lang/erg/releases"><img alt="Build status" src="https://img.shields.io/github/v/release/erg-lang/erg.svg"></a>
|
<a href="https://github.com/erg-lang/erg/releases"><img alt="Build status" src="https://img.shields.io/github/v/release/erg-lang/erg.svg"></a>
|
||||||
|
@ -12,8 +12,8 @@
|
||||||
<br>
|
<br>
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
[
|
[
|
||||||
](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=README.md&commit_hash=f2118ff45d9e46ca8fa44242363223be43b046dd)
|
](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=README.md&commit_hash=1a66848fd63479093d0d7995712571e3fdc6bd92)
|
||||||
|
|
||||||
## Erg可以推薦給以下人員:
|
## Erg可以推薦給以下人員:
|
||||||
|
|
||||||
|
|
|
@ -14,36 +14,35 @@ cargo license --json | \
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
## `atty`
|
## `crossterm`
|
||||||
|
|
||||||
* Source code is available at [https://github.com/softprops/atty](https://github.com/softprops/atty)
|
* Source code is available at [https://github.com/crossterm-rs/crossterm](https://github.com/crossterm-rs/crossterm)
|
||||||
* license: MIT
|
* license: MIT
|
||||||
|
|
||||||
### `atty`'s license text
|
### `crossterm`'s license text
|
||||||
|
|
||||||
MIT from from [https://raw.githubusercontent.com/softprops/atty/0.2.14/LICENSE](https://raw.githubusercontent.com/softprops/atty/0.2.14/LICENSE):
|
|
||||||
|
|
||||||
```text
|
```text
|
||||||
Copyright (c) 2015-2019 Doug Tangren
|
MIT License
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
Copyright (c) 2019 Timon
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
included in all copies or substantial portions of the Software.
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
The above copyright notice and this permission notice shall be included in all
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
copies or substantial portions of the Software.
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
```
|
```
|
||||||
|
|
||||||
## `hermit-abi`
|
## `hermit-abi`
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
[package]
|
[package]
|
||||||
name = "erg_common"
|
name = "erg_common"
|
||||||
version = "0.5.7"
|
|
||||||
description = "A common components library of Erg"
|
description = "A common components library of Erg"
|
||||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
documentation = "http://docs.rs/erg_common"
|
||||||
license = "MIT OR Apache-2.0"
|
version.workspace = true
|
||||||
edition = "2021"
|
authors.workspace = true
|
||||||
repository = "https://github.com/erg-lang/erg/tree/main/src/erg_common"
|
license.workspace = true
|
||||||
documentation = "https://docs.rs/erg_common"
|
edition.workspace = true
|
||||||
homepage = "https://erg-lang.github.io/"
|
repository.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
@ -17,8 +17,13 @@ japanese = []
|
||||||
simplified_chinese = []
|
simplified_chinese = []
|
||||||
traditional_chinese = []
|
traditional_chinese = []
|
||||||
|
|
||||||
[dependencies]
|
[target.'cfg(unix)'.dependencies]
|
||||||
atty = "0.2.14"
|
libc = { version = "0.2", default-features = false }
|
||||||
|
[target.'cfg(target_os = "hermit")'.dependencies]
|
||||||
|
hermit-abi = "0.1.6"
|
||||||
|
[target.'cfg(windows)'.dependencies.winapi]
|
||||||
|
version = "0.3"
|
||||||
|
features = ["consoleapi"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
|
@ -211,48 +211,70 @@ impl ErgConfig {
|
||||||
let mut cfg = Self::default();
|
let mut cfg = Self::default();
|
||||||
// ループ内でnextするのでforにしないこと
|
// ループ内でnextするのでforにしないこと
|
||||||
while let Some(arg) = args.next() {
|
while let Some(arg) = args.next() {
|
||||||
let next_arg = args.next();
|
|
||||||
match &arg[..] {
|
match &arg[..] {
|
||||||
"-c" if next_arg.is_some() => {
|
"-c" | "--code" => {
|
||||||
cfg.input = Input::Str(next_arg.unwrap());
|
cfg.input = Input::Str(args.next().expect("the value of `-c` is not passed"));
|
||||||
}
|
}
|
||||||
"--dump-as-pyc" => {
|
"--dump-as-pyc" => {
|
||||||
cfg.dump_as_pyc = true;
|
cfg.dump_as_pyc = true;
|
||||||
}
|
}
|
||||||
"-?" | "-h" | "--help" => {
|
"-?" | "-h" | "--help" => {
|
||||||
// TODO:
|
|
||||||
println!("{}", command_message());
|
println!("{}", command_message());
|
||||||
|
if let "--mode" = args.next().as_ref().map(|s| &s[..]).unwrap_or("") {
|
||||||
|
println!("{}", mode_message());
|
||||||
|
}
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
"-m" if next_arg.is_some() => {
|
"-m" | "--module" => {
|
||||||
cfg.module = Box::leak(next_arg.unwrap().into_boxed_str());
|
let module = args
|
||||||
|
.next()
|
||||||
|
.expect("the value of `-m` is not passed")
|
||||||
|
.into_boxed_str();
|
||||||
|
cfg.module = Box::leak(module);
|
||||||
}
|
}
|
||||||
"--mode" if next_arg.is_some() => {
|
"--mode" => {
|
||||||
let mode = next_arg.unwrap();
|
let mode = args.next().expect("the value of `--mode` is not passed");
|
||||||
if let "-?" | "-h" | "--help" = &mode[..] {
|
if let "-?" | "-h" | "--help" = &mode[..] {
|
||||||
println!("{}", mode_message());
|
println!("{}", mode_message());
|
||||||
process::exit(0);
|
process::exit(0);
|
||||||
}
|
}
|
||||||
cfg.mode = Box::leak(mode.into_boxed_str());
|
cfg.mode = Box::leak(mode.into_boxed_str());
|
||||||
}
|
}
|
||||||
"--ps1" if next_arg.is_some() => {
|
"--ps1" => {
|
||||||
cfg.ps1 = Box::leak(next_arg.unwrap().into_boxed_str());
|
let ps1 = args
|
||||||
|
.next()
|
||||||
|
.expect("the value of `--ps1` is not passed")
|
||||||
|
.into_boxed_str();
|
||||||
|
cfg.ps1 = Box::leak(ps1);
|
||||||
}
|
}
|
||||||
"--ps2" if next_arg.is_some() => {
|
"--ps2" => {
|
||||||
cfg.ps2 = Box::leak(next_arg.unwrap().into_boxed_str());
|
let ps2 = args
|
||||||
|
.next()
|
||||||
|
.expect("the value of `--ps2` is not passed")
|
||||||
|
.into_boxed_str();
|
||||||
|
cfg.ps2 = Box::leak(ps2);
|
||||||
}
|
}
|
||||||
"-o" | "--opt-level" | "--optimization-level" if next_arg.is_some() => {
|
"-o" | "--opt-level" | "--optimization-level" => {
|
||||||
cfg.opt_level = next_arg.unwrap().parse::<u8>().unwrap();
|
cfg.opt_level = args
|
||||||
|
.next()
|
||||||
|
.expect("the value of `-o` is not passed")
|
||||||
|
.parse::<u8>()
|
||||||
|
.expect("the value of `-o` is not a number");
|
||||||
}
|
}
|
||||||
"-p" | "--py-ver" | "--python-version" if next_arg.is_some() => {
|
"-p" | "--py-ver" | "--python-version" => {
|
||||||
if let Ok(ver) = next_arg.unwrap().parse::<u32>() {
|
let py_ver = args
|
||||||
cfg.python_ver = Some(ver)
|
.next()
|
||||||
}
|
.expect("the value of `-p` is not passed")
|
||||||
|
.parse::<u32>()
|
||||||
|
.expect("the value of `-p` is not a number");
|
||||||
|
cfg.python_ver = Some(py_ver);
|
||||||
}
|
}
|
||||||
"--py-server-timeout" if next_arg.is_some() => {
|
"--py-server-timeout" => {
|
||||||
if let Ok(time) = next_arg.unwrap().parse::<u64>() {
|
cfg.py_server_timeout = args
|
||||||
cfg.py_server_timeout = time;
|
.next()
|
||||||
}
|
.expect("the value of `--py-server-timeout` is not passed")
|
||||||
|
.parse::<u64>()
|
||||||
|
.expect("the value of `--py-server-timeout` is not a number");
|
||||||
}
|
}
|
||||||
"--quiet-startup" => {
|
"--quiet-startup" => {
|
||||||
cfg.quiet_startup = true;
|
cfg.quiet_startup = true;
|
||||||
|
@ -260,10 +282,12 @@ impl ErgConfig {
|
||||||
"-t" | "--show-type" => {
|
"-t" | "--show-type" => {
|
||||||
cfg.show_type = true;
|
cfg.show_type = true;
|
||||||
}
|
}
|
||||||
"--verbose" if next_arg.is_some() => {
|
"--verbose" => {
|
||||||
if let Ok(vr) = next_arg.unwrap().parse::<u8>() {
|
cfg.verbose = args
|
||||||
cfg.verbose = vr;
|
.next()
|
||||||
}
|
.expect("the value of `--verbose` is not passed")
|
||||||
|
.parse::<u8>()
|
||||||
|
.expect("the value of `--verbose` is not a number");
|
||||||
}
|
}
|
||||||
"-V" | "--version" => {
|
"-V" | "--version" => {
|
||||||
println!("Erg {}", env!("CARGO_PKG_VERSION"));
|
println!("Erg {}", env!("CARGO_PKG_VERSION"));
|
||||||
|
@ -282,7 +306,8 @@ impl ErgConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if cfg.input == Input::REPL {
|
if cfg.input == Input::REPL {
|
||||||
let is_stdin_piped = atty::isnt(atty::Stream::Stdin);
|
use crate::tty::IsTty;
|
||||||
|
let is_stdin_piped = !stdin().is_tty();
|
||||||
let input = if is_stdin_piped {
|
let input = if is_stdin_piped {
|
||||||
let mut buffer = String::new();
|
let mut buffer = String::new();
|
||||||
stdin().read_to_string(&mut buffer).unwrap();
|
stdin().read_to_string(&mut buffer).unwrap();
|
||||||
|
|
|
@ -20,7 +20,7 @@ OPTIONS
|
||||||
--python-version/-p (uint 32 number) Pythonバージョンを指定
|
--python-version/-p (uint 32 number) Pythonバージョンを指定
|
||||||
--py-server-timeout (uint 64 number) PythonのREPLサーバーのタイムアウト時間を指定
|
--py-server-timeout (uint 64 number) PythonのREPLサーバーのタイムアウト時間を指定
|
||||||
--dump-as-pyc .pycファイルにダンプ
|
--dump-as-pyc .pycファイルにダンプ
|
||||||
--mode lex|parse|compile|exec 指定モードで実行
|
--mode lex|parse|compile|exec 指定モードで実行(詳細は--mode --helpを参照)
|
||||||
|
|
||||||
SUBCOMMAND
|
SUBCOMMAND
|
||||||
-c cmd : 文字列をプログラムに譲渡
|
-c cmd : 文字列をプログラムに譲渡
|
||||||
|
@ -43,7 +43,7 @@ OPTIONS
|
||||||
--python-version/-p (uint 32 number) Python 版本
|
--python-version/-p (uint 32 number) Python 版本
|
||||||
--py-server-timeout (uint 64 number) Python REPL 服务器超时
|
--py-server-timeout (uint 64 number) Python REPL 服务器超时
|
||||||
--dump-as-pyc 转储为 .pyc 文件
|
--dump-as-pyc 转储为 .pyc 文件
|
||||||
--mode lex|parse|compile|exec 执行模式
|
--mode lex|parse|compile|exec 执行模式 (更多信息见`--mode --help`)
|
||||||
|
|
||||||
SUBCOMMAND
|
SUBCOMMAND
|
||||||
-c cmd : 作为字符串传入程序
|
-c cmd : 作为字符串传入程序
|
||||||
|
@ -66,7 +66,7 @@ OPTIONS
|
||||||
--python-version/-p (uint 32 number) Python 版本
|
--python-version/-p (uint 32 number) Python 版本
|
||||||
--py-server-timeout (uint 64 number) Python REPL 服務器超時
|
--py-server-timeout (uint 64 number) Python REPL 服務器超時
|
||||||
--dump-as-pyc 轉儲為 .pyc 文件
|
--dump-as-pyc 轉儲為 .pyc 文件
|
||||||
--mode lex|parse|compile|exec 執行模式
|
--mode lex|parse|compile|exec 執行模式 (更多信息見`--mode --help`)
|
||||||
|
|
||||||
SUBCOMMAND
|
SUBCOMMAND
|
||||||
-c cmd : 作為字串傳入程式
|
-c cmd : 作為字串傳入程式
|
||||||
|
@ -89,7 +89,7 @@ OPTIONS
|
||||||
--python-version/-p (uint 32 number) Python version
|
--python-version/-p (uint 32 number) Python version
|
||||||
--py-server-timeout (uint 64 number) timeout for the Python REPL server
|
--py-server-timeout (uint 64 number) timeout for the Python REPL server
|
||||||
--dump-as-pyc dump as .pyc file
|
--dump-as-pyc dump as .pyc file
|
||||||
--mode lex|parse|compile|exec execution mode
|
--mode lex|parse|compile|exec execution mode (See `--mode --help` for details)
|
||||||
|
|
||||||
SUBCOMMAND
|
SUBCOMMAND
|
||||||
-c cmd : program passed in as string
|
-c cmd : program passed in as string
|
||||||
|
|
|
@ -21,6 +21,7 @@ pub mod stdin;
|
||||||
pub mod str;
|
pub mod str;
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
pub mod tsort;
|
pub mod tsort;
|
||||||
|
pub mod tty;
|
||||||
pub mod vis;
|
pub mod vis;
|
||||||
|
|
||||||
use crate::set::Set;
|
use crate::set::Set;
|
||||||
|
|
63
compiler/erg_common/tty.rs
Normal file
63
compiler/erg_common/tty.rs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
//! Copied and modified from the [crossterm](https://github.com/crossterm-rs/crossterm).
|
||||||
|
//! Making it a little more convenient and safe to query whether
|
||||||
|
//! something is a terminal teletype or not.
|
||||||
|
//! This module defines the IsTty trait and the is_tty method to
|
||||||
|
//! return true if the item represents a terminal.
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
use std::os::unix::io::AsRawFd;
|
||||||
|
#[cfg(windows)]
|
||||||
|
use std::os::windows::io::AsRawHandle;
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
|
use winapi::um::consoleapi::GetConsoleMode;
|
||||||
|
|
||||||
|
/// Adds the `is_tty` method to types that might represent a terminal
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use std::io::stdout;
|
||||||
|
/// use erg_common::tty::IsTty;
|
||||||
|
///
|
||||||
|
/// let is_tty: bool = stdout().is_tty();
|
||||||
|
/// ```
|
||||||
|
pub trait IsTty {
|
||||||
|
/// Returns true when an instance is a terminal teletype, otherwise false.
|
||||||
|
fn is_tty(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// On UNIX, the `isatty()` function returns true if a file
|
||||||
|
/// descriptor is a terminal.
|
||||||
|
#[cfg(unix)]
|
||||||
|
impl<S: AsRawFd> IsTty for S {
|
||||||
|
fn is_tty(&self) -> bool {
|
||||||
|
let fd = self.as_raw_fd();
|
||||||
|
unsafe { libc::isatty(fd) == 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "hermit")]
|
||||||
|
impl<S: AsRawFd> IsTty for S {
|
||||||
|
fn is_tty(&self) -> bool {
|
||||||
|
let fd = self.as_raw_fd();
|
||||||
|
hermit_abi::isatty(fd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// returns true if this is a tty
|
||||||
|
#[cfg(any(target_arch = "wasm32", target_env = "sgx"))]
|
||||||
|
impl<S: AsRawFd> IsTty for S {
|
||||||
|
fn is_tty(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// On windows, `GetConsoleMode` will return true if we are in a terminal.
|
||||||
|
/// Otherwise false.
|
||||||
|
#[cfg(windows)]
|
||||||
|
impl<S: AsRawHandle> IsTty for S {
|
||||||
|
fn is_tty(&self) -> bool {
|
||||||
|
let mut mode = 0;
|
||||||
|
let ok = unsafe { GetConsoleMode(self.as_raw_handle() as *mut _, &mut mode) };
|
||||||
|
ok == 1
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,25 +1,34 @@
|
||||||
[package]
|
[package]
|
||||||
name = "erg_compiler"
|
name = "erg_compiler"
|
||||||
version = "0.5.7"
|
|
||||||
description = "Centimetre: the Erg compiler"
|
description = "Centimetre: the Erg compiler"
|
||||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
documentation = "http://docs.rs/erg_compiler"
|
||||||
license = "MIT OR Apache-2.0"
|
build = "build.rs"
|
||||||
edition = "2021"
|
version.workspace = true
|
||||||
repository = "https://github.com/erg-lang/erg/tree/main/src/compiler/erg_compiler"
|
authors.workspace = true
|
||||||
documentation = "https://docs.rs/erg_compiler"
|
license.workspace = true
|
||||||
homepage = "https://erg-lang.github.io/"
|
edition.workspace = true
|
||||||
|
repository.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# when "debug" feature is turned on, that of parser will also be turned on.
|
# when "debug" feature is turned on, that of parser will also be turned on.
|
||||||
debug = [ "erg_common/debug", "erg_parser/debug", "erg_type/debug" ]
|
debug = ["erg_common/debug", "erg_parser/debug", "erg_type/debug"]
|
||||||
japanese = [ "erg_common/japanese", "erg_parser/japanese", "erg_type/japanese" ]
|
japanese = ["erg_common/japanese", "erg_parser/japanese", "erg_type/japanese"]
|
||||||
simplified_chinese = [ "erg_common/simplified_chinese", "erg_parser/simplified_chinese", "erg_type/simplified_chinese" ]
|
simplified_chinese = [
|
||||||
traditional_chinese = [ "erg_common/traditional_chinese", "erg_parser/traditional_chinese", "erg_type/traditional_chinese" ]
|
"erg_common/simplified_chinese",
|
||||||
|
"erg_parser/simplified_chinese",
|
||||||
|
"erg_type/simplified_chinese",
|
||||||
|
]
|
||||||
|
traditional_chinese = [
|
||||||
|
"erg_common/traditional_chinese",
|
||||||
|
"erg_parser/traditional_chinese",
|
||||||
|
"erg_type/traditional_chinese",
|
||||||
|
]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erg_common = { version = "0.5.7", path = "../erg_common" }
|
erg_common = { version = "0.5.9-nightly.0", path = "../erg_common" }
|
||||||
erg_parser = { version = "0.5.7", path = "../erg_parser" }
|
erg_parser = { version = "0.5.9-nightly.0", path = "../erg_parser" }
|
||||||
erg_type = { version = "0.5.7", path = "../erg_type" }
|
erg_type = { version = "0.5.9-nightly.0", path = "../erg_type" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
33
compiler/erg_compiler/build.rs
Normal file
33
compiler/erg_compiler/build.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
#![allow(deprecated)]
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::fs;
|
||||||
|
use std::path;
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
// Create a ".erg" directory
|
||||||
|
let erg_path = env::home_dir()
|
||||||
|
.expect("failed to get the location of the home dir")
|
||||||
|
.to_str()
|
||||||
|
.expect("invalid encoding of the home dir name")
|
||||||
|
.to_string()
|
||||||
|
+ "/.erg";
|
||||||
|
if !path::Path::new(&erg_path).exists() {
|
||||||
|
fs::create_dir(&erg_path)?;
|
||||||
|
fs::create_dir(format!("{erg_path}/std"))?;
|
||||||
|
}
|
||||||
|
println!("cargo:rustc-env=ERG_PATH={erg_path}");
|
||||||
|
println!("cargo:rustc-env=ERG_STD_PATH={erg_path}/std");
|
||||||
|
// create a std library in ".erg"
|
||||||
|
for res in fs::read_dir("std")? {
|
||||||
|
let entry = res?;
|
||||||
|
let path = entry.path();
|
||||||
|
let filename = path
|
||||||
|
.file_name()
|
||||||
|
.expect("this is not a file")
|
||||||
|
.to_str()
|
||||||
|
.unwrap();
|
||||||
|
fs::copy(&path, format!("{erg_path}/std/{filename}"))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -29,7 +29,7 @@ use erg_type::value::ValueObj;
|
||||||
use erg_type::{HasType, Type, TypeCode, TypePair};
|
use erg_type::{HasType, Type, TypeCode, TypePair};
|
||||||
|
|
||||||
use crate::compile::{AccessKind, Name, StoreLoadKind};
|
use crate::compile::{AccessKind, Name, StoreLoadKind};
|
||||||
use crate::context::eval::eval_lit;
|
use crate::context::eval::type_from_token_kind;
|
||||||
use crate::error::CompileError;
|
use crate::error::CompileError;
|
||||||
use crate::hir::{
|
use crate::hir::{
|
||||||
Accessor, Args, Array, AttrDef, Attribute, BinOp, Block, Call, ClassDef, Def, DefBody, Expr,
|
Accessor, Args, Array, AttrDef, Attribute, BinOp, Block, Call, ClassDef, Def, DefBody, Expr,
|
||||||
|
@ -867,7 +867,7 @@ impl CodeGenerator {
|
||||||
self.write_instr(MAKE_FUNCTION);
|
self.write_instr(MAKE_FUNCTION);
|
||||||
self.write_arg(0);
|
self.write_arg(0);
|
||||||
self.emit_load_const(def.sig.ident().inspect().clone());
|
self.emit_load_const(def.sig.ident().inspect().clone());
|
||||||
self.emit_load_name_instr(Identifier::private(Str::ever("#ABCMeta")));
|
self.emit_load_name_instr(Identifier::private("#ABCMeta"));
|
||||||
self.emit_load_const(vec![ValueObj::from("metaclass")]);
|
self.emit_load_const(vec![ValueObj::from("metaclass")]);
|
||||||
let subclasses_len = 1;
|
let subclasses_len = 1;
|
||||||
self.write_instr(Opcode::CALL_FUNCTION_KW);
|
self.write_instr(Opcode::CALL_FUNCTION_KW);
|
||||||
|
@ -917,7 +917,7 @@ impl CodeGenerator {
|
||||||
self.emit_empty_func(
|
self.emit_empty_func(
|
||||||
Some(sig.ident().inspect()),
|
Some(sig.ident().inspect()),
|
||||||
def.sig.into_ident(),
|
def.sig.into_ident(),
|
||||||
Some(Identifier::private(Str::ever("#abstractmethod"))),
|
Some(Identifier::private("#abstractmethod")),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
self.emit_load_const(ValueObj::None);
|
self.emit_load_const(ValueObj::None);
|
||||||
|
@ -1129,7 +1129,7 @@ impl CodeGenerator {
|
||||||
CompileError::feature_error(
|
CompileError::feature_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
unary.op.loc(),
|
unary.op.loc(),
|
||||||
"",
|
&unary.op.inspect().clone(),
|
||||||
AtomicStr::from(unary.op.content),
|
AtomicStr::from(unary.op.content),
|
||||||
)
|
)
|
||||||
.write_to_stderr();
|
.write_to_stderr();
|
||||||
|
@ -1150,6 +1150,9 @@ impl CodeGenerator {
|
||||||
self.emit_load_name_instr(Identifier::public("range"));
|
self.emit_load_name_instr(Identifier::public("range"));
|
||||||
}
|
}
|
||||||
TokenKind::LeftOpen | TokenKind::Closed | TokenKind::Open => todo!(),
|
TokenKind::LeftOpen | TokenKind::Closed | TokenKind::Open => todo!(),
|
||||||
|
TokenKind::InOp => {
|
||||||
|
self.emit_load_name_instr(Identifier::private("#in_operator"));
|
||||||
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
let type_pair = TypePair::new(bin.lhs_t(), bin.rhs_t());
|
let type_pair = TypePair::new(bin.lhs_t(), bin.rhs_t());
|
||||||
|
@ -1170,14 +1173,16 @@ impl CodeGenerator {
|
||||||
| TokenKind::NotEq
|
| TokenKind::NotEq
|
||||||
| TokenKind::Gre
|
| TokenKind::Gre
|
||||||
| TokenKind::GreEq => COMPARE_OP,
|
| TokenKind::GreEq => COMPARE_OP,
|
||||||
TokenKind::LeftOpen | TokenKind::RightOpen | TokenKind::Closed | TokenKind::Open => {
|
TokenKind::LeftOpen
|
||||||
CALL_FUNCTION
|
| TokenKind::RightOpen
|
||||||
} // ERG_BINARY_RANGE,
|
| TokenKind::Closed
|
||||||
|
| TokenKind::Open
|
||||||
|
| TokenKind::InOp => CALL_FUNCTION, // ERG_BINARY_RANGE,
|
||||||
_ => {
|
_ => {
|
||||||
CompileError::feature_error(
|
CompileError::feature_error(
|
||||||
self.cfg.input.clone(),
|
self.cfg.input.clone(),
|
||||||
bin.op.loc(),
|
bin.op.loc(),
|
||||||
"",
|
&bin.op.inspect().clone(),
|
||||||
AtomicStr::from(bin.op.content),
|
AtomicStr::from(bin.op.content),
|
||||||
)
|
)
|
||||||
.write_to_stderr();
|
.write_to_stderr();
|
||||||
|
@ -1191,14 +1196,22 @@ impl CodeGenerator {
|
||||||
TokenKind::NotEq => 3,
|
TokenKind::NotEq => 3,
|
||||||
TokenKind::Gre => 4,
|
TokenKind::Gre => 4,
|
||||||
TokenKind::GreEq => 5,
|
TokenKind::GreEq => 5,
|
||||||
TokenKind::LeftOpen | TokenKind::RightOpen | TokenKind::Closed | TokenKind::Open => 2,
|
TokenKind::LeftOpen
|
||||||
|
| TokenKind::RightOpen
|
||||||
|
| TokenKind::Closed
|
||||||
|
| TokenKind::Open
|
||||||
|
| TokenKind::InOp => 2,
|
||||||
_ => type_pair as u8,
|
_ => type_pair as u8,
|
||||||
};
|
};
|
||||||
self.write_instr(instr);
|
self.write_instr(instr);
|
||||||
self.write_arg(arg);
|
self.write_arg(arg);
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
match &bin.op.kind {
|
match &bin.op.kind {
|
||||||
TokenKind::LeftOpen | TokenKind::RightOpen | TokenKind::Open | TokenKind::Closed => {
|
TokenKind::LeftOpen
|
||||||
|
| TokenKind::RightOpen
|
||||||
|
| TokenKind::Open
|
||||||
|
| TokenKind::Closed
|
||||||
|
| TokenKind::InOp => {
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
@ -1339,7 +1352,11 @@ impl CodeGenerator {
|
||||||
self.emit_store_instr(ident, AccessKind::Name);
|
self.emit_store_instr(ident, AccessKind::Name);
|
||||||
}
|
}
|
||||||
ParamPattern::Lit(lit) => {
|
ParamPattern::Lit(lit) => {
|
||||||
self.emit_load_const(eval_lit(&lit));
|
let value = {
|
||||||
|
let t = type_from_token_kind(lit.token.kind);
|
||||||
|
ValueObj::from_str(t, lit.token.content).unwrap()
|
||||||
|
};
|
||||||
|
self.emit_load_const(value);
|
||||||
self.write_instr(Opcode::COMPARE_OP);
|
self.write_instr(Opcode::COMPARE_OP);
|
||||||
self.write_arg(2); // ==
|
self.write_arg(2); // ==
|
||||||
self.stack_dec();
|
self.stack_dec();
|
||||||
|
@ -1597,7 +1614,7 @@ impl CodeGenerator {
|
||||||
log!(info "entered {} ({rec})", fn_name!());
|
log!(info "entered {} ({rec})", fn_name!());
|
||||||
let attrs_len = rec.attrs.len();
|
let attrs_len = rec.attrs.len();
|
||||||
// making record type
|
// making record type
|
||||||
let ident = Identifier::private(Str::ever("#NamedTuple"));
|
let ident = Identifier::private("#NamedTuple");
|
||||||
self.emit_load_name_instr(ident);
|
self.emit_load_name_instr(ident);
|
||||||
// record name, let it be anonymous
|
// record name, let it be anonymous
|
||||||
self.emit_load_const("Record");
|
self.emit_load_const("Record");
|
||||||
|
@ -1615,10 +1632,10 @@ impl CodeGenerator {
|
||||||
self.write_arg(2);
|
self.write_arg(2);
|
||||||
// (1 (subroutine) + argc + kwsc) input objects -> 1 return object
|
// (1 (subroutine) + argc + kwsc) input objects -> 1 return object
|
||||||
self.stack_dec_n((1 + 2 + 0) - 1);
|
self.stack_dec_n((1 + 2 + 0) - 1);
|
||||||
let ident = Identifier::private(Str::ever("#rec"));
|
let ident = Identifier::private("#rec");
|
||||||
self.emit_store_instr(ident, Name);
|
self.emit_store_instr(ident, Name);
|
||||||
// making record instance
|
// making record instance
|
||||||
let ident = Identifier::private(Str::ever("#rec"));
|
let ident = Identifier::private("#rec");
|
||||||
self.emit_load_name_instr(ident);
|
self.emit_load_name_instr(ident);
|
||||||
for field in rec.attrs.into_iter() {
|
for field in rec.attrs.into_iter() {
|
||||||
self.emit_frameless_block(field.body.block, vec![]);
|
self.emit_frameless_block(field.body.block, vec![]);
|
||||||
|
@ -1687,6 +1704,15 @@ impl CodeGenerator {
|
||||||
self.stack_dec_n(len - 1);
|
self.stack_dec_n(len - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Array::WithLength(arr) => {
|
||||||
|
self.emit_expr(*arr.elem);
|
||||||
|
self.write_instr(BUILD_LIST);
|
||||||
|
self.write_arg(1u8);
|
||||||
|
self.emit_expr(*arr.len);
|
||||||
|
self.write_instr(BINARY_MULTIPLY);
|
||||||
|
self.write_arg(0);
|
||||||
|
self.stack_dec();
|
||||||
|
}
|
||||||
other => todo!("{other}"),
|
other => todo!("{other}"),
|
||||||
},
|
},
|
||||||
// TODO: tuple comprehension
|
// TODO: tuple comprehension
|
||||||
|
@ -1720,7 +1746,11 @@ impl CodeGenerator {
|
||||||
self.stack_dec_n(len - 1);
|
self.stack_dec_n(len - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
crate::hir::Set::WithLength(_) => todo!(),
|
crate::hir::Set::WithLength(st) => {
|
||||||
|
self.emit_expr(*st.elem);
|
||||||
|
self.write_instr(BUILD_SET);
|
||||||
|
self.write_arg(1u8);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Expr::Record(rec) => self.emit_record(rec),
|
Expr::Record(rec) => self.emit_record(rec),
|
||||||
Expr::Code(code) => {
|
Expr::Code(code) => {
|
||||||
|
@ -1739,7 +1769,7 @@ impl CodeGenerator {
|
||||||
}
|
}
|
||||||
// Dict,
|
// Dict,
|
||||||
other => {
|
other => {
|
||||||
CompileError::feature_error(self.cfg.input.clone(), other.loc(), "???", "".into())
|
CompileError::feature_error(self.cfg.input.clone(), other.loc(), "Dict", "".into())
|
||||||
.write_to_stderr();
|
.write_to_stderr();
|
||||||
self.crash("cannot compile this expression at this time");
|
self.crash("cannot compile this expression at this time");
|
||||||
}
|
}
|
||||||
|
@ -1894,7 +1924,7 @@ impl CodeGenerator {
|
||||||
attrs.push(Expr::AttrDef(attr_def));
|
attrs.push(Expr::AttrDef(attr_def));
|
||||||
}
|
}
|
||||||
let none = Token::new(TokenKind::NoneLit, "None", line, 0);
|
let none = Token::new(TokenKind::NoneLit, "None", line, 0);
|
||||||
attrs.push(Expr::Lit(Literal::from(none)));
|
attrs.push(Expr::Lit(Literal::try_from(none).unwrap()));
|
||||||
}
|
}
|
||||||
other => todo!("{other}"),
|
other => todo!("{other}"),
|
||||||
}
|
}
|
||||||
|
@ -2007,15 +2037,40 @@ impl CodeGenerator {
|
||||||
|
|
||||||
fn load_prelude(&mut self) {
|
fn load_prelude(&mut self) {
|
||||||
self.load_record_type();
|
self.load_record_type();
|
||||||
|
self.load_prelude_py();
|
||||||
self.record_type_loaded = true;
|
self.record_type_loaded = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_prelude_py(&mut self) {
|
||||||
|
self.emit_global_import_items(
|
||||||
|
Identifier::public("sys"),
|
||||||
|
vec![(
|
||||||
|
Identifier::public("path"),
|
||||||
|
Some(Identifier::private("#path")),
|
||||||
|
)],
|
||||||
|
);
|
||||||
|
self.emit_load_name_instr(Identifier::private("#path"));
|
||||||
|
self.emit_load_method_instr("Array!", None, Identifier::public("push!"));
|
||||||
|
self.emit_load_const(env!("ERG_STD_PATH"));
|
||||||
|
self.write_instr(CALL_METHOD);
|
||||||
|
self.write_arg(1u8);
|
||||||
|
self.stack_dec();
|
||||||
|
self.emit_pop_top();
|
||||||
|
self.emit_global_import_items(
|
||||||
|
Identifier::public("_erg_std_prelude"),
|
||||||
|
vec![(
|
||||||
|
Identifier::public("in_operator"),
|
||||||
|
Some(Identifier::private("#in_operator")),
|
||||||
|
)],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn load_record_type(&mut self) {
|
fn load_record_type(&mut self) {
|
||||||
self.emit_global_import_items(
|
self.emit_global_import_items(
|
||||||
Identifier::public("collections"),
|
Identifier::public("collections"),
|
||||||
vec![(
|
vec![(
|
||||||
Identifier::public("namedtuple"),
|
Identifier::public("namedtuple"),
|
||||||
Some(Identifier::private(Str::ever("#NamedTuple"))),
|
Some(Identifier::private("#NamedTuple")),
|
||||||
)],
|
)],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -2026,11 +2081,11 @@ impl CodeGenerator {
|
||||||
vec![
|
vec![
|
||||||
(
|
(
|
||||||
Identifier::public("ABCMeta"),
|
Identifier::public("ABCMeta"),
|
||||||
Some(Identifier::private(Str::ever("#ABCMeta"))),
|
Some(Identifier::private("#ABCMeta")),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
Identifier::public("abstractmethod"),
|
Identifier::public("abstractmethod"),
|
||||||
Some(Identifier::private(Str::ever("#abstractmethod"))),
|
Some(Identifier::private("#abstractmethod")),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
@ -2041,7 +2096,7 @@ impl CodeGenerator {
|
||||||
Identifier::public("types"),
|
Identifier::public("types"),
|
||||||
vec![(
|
vec![(
|
||||||
Identifier::public("ModuleType"),
|
Identifier::public("ModuleType"),
|
||||||
Some(Identifier::private(Str::ever("#ModuleType"))),
|
Some(Identifier::private("#ModuleType")),
|
||||||
)],
|
)],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -681,25 +681,26 @@ impl Context {
|
||||||
pub(crate) fn cyclic_supertype_of(&self, lhs: &FreeTyVar, rhs: &Type) -> bool {
|
pub(crate) fn cyclic_supertype_of(&self, lhs: &FreeTyVar, rhs: &Type) -> bool {
|
||||||
let subst_ctx = SubstContext::new(rhs, self, Location::Unknown);
|
let subst_ctx = SubstContext::new(rhs, self, Location::Unknown);
|
||||||
if let Some(super_traits) = self.get_nominal_type_ctx(rhs).map(|ctx| &ctx.super_traits) {
|
if let Some(super_traits) = self.get_nominal_type_ctx(rhs).map(|ctx| &ctx.super_traits) {
|
||||||
for sup_trait in super_traits {
|
for super_trait in super_traits {
|
||||||
let sup_trait = if sup_trait.has_qvar() {
|
let sup_trait = if super_trait.has_qvar() {
|
||||||
subst_ctx.substitute(sup_trait.clone()).unwrap()
|
subst_ctx.substitute(super_trait.clone()).unwrap()
|
||||||
} else {
|
} else {
|
||||||
sup_trait.clone()
|
super_trait.clone()
|
||||||
};
|
};
|
||||||
if self.sup_conforms(lhs, rhs, &sup_trait) {
|
if self.sup_conforms(lhs, rhs, &sup_trait) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(sup_classes) = self.get_nominal_type_ctx(rhs).map(|ctx| &ctx.super_classes) {
|
if let Some(super_classes) = self.get_super_classes(rhs) {
|
||||||
for sup_class in sup_classes {
|
for super_class in super_classes {
|
||||||
let sup_class = if sup_class.has_qvar() {
|
let sup_class = if super_class.has_qvar() {
|
||||||
subst_ctx.substitute(sup_class.clone()).unwrap()
|
subst_ctx.substitute(super_class).unwrap()
|
||||||
} else {
|
} else {
|
||||||
sup_class.clone()
|
super_class
|
||||||
};
|
};
|
||||||
if self.cyclic_supertype_of(lhs, &sup_class) {
|
if self.cyclic_supertype_of(lhs, &sup_class) {
|
||||||
|
log!(err "引っかかった: {lhs}, {sup_class}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -849,6 +850,9 @@ impl Context {
|
||||||
|
|
||||||
/// returns union of two types (A or B)
|
/// returns union of two types (A or B)
|
||||||
pub(crate) fn union(&self, lhs: &Type, rhs: &Type) -> Type {
|
pub(crate) fn union(&self, lhs: &Type, rhs: &Type) -> Type {
|
||||||
|
if lhs == rhs {
|
||||||
|
return lhs.clone();
|
||||||
|
}
|
||||||
// `?T or ?U` will not be unified
|
// `?T or ?U` will not be unified
|
||||||
// `Set!(?T, 3) or Set(?T, 3)` wii be unified to Set(?T, 3)
|
// `Set!(?T, 3) or Set(?T, 3)` wii be unified to Set(?T, 3)
|
||||||
if !lhs.is_unbound_var() && !rhs.is_unbound_var() {
|
if !lhs.is_unbound_var() && !rhs.is_unbound_var() {
|
||||||
|
@ -888,6 +892,9 @@ impl Context {
|
||||||
|
|
||||||
/// returns intersection of two types (A and B)
|
/// returns intersection of two types (A and B)
|
||||||
pub(crate) fn intersection(&self, lhs: &Type, rhs: &Type) -> Type {
|
pub(crate) fn intersection(&self, lhs: &Type, rhs: &Type) -> Type {
|
||||||
|
if lhs == rhs {
|
||||||
|
return lhs.clone();
|
||||||
|
}
|
||||||
// ?T and ?U will not be unified
|
// ?T and ?U will not be unified
|
||||||
if !lhs.is_unbound_var() && !rhs.is_unbound_var() {
|
if !lhs.is_unbound_var() && !rhs.is_unbound_var() {
|
||||||
match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) {
|
match (self.supertype_of(lhs, rhs), self.subtype_of(lhs, rhs)) {
|
||||||
|
|
|
@ -100,12 +100,6 @@ fn op_to_name(op: OpKind) -> &'static str {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub(crate) fn eval_lit(lit: &Literal) -> ValueObj {
|
|
||||||
let t = type_from_token_kind(lit.token.kind);
|
|
||||||
ValueObj::from_str(t, lit.token.content.clone())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Instantiate the polymorphic type from the quantified state.
|
/// Instantiate the polymorphic type from the quantified state.
|
||||||
///
|
///
|
||||||
/// e.g.
|
/// e.g.
|
||||||
|
@ -577,13 +571,26 @@ impl Context {
|
||||||
Ok(ValueObj::Subr(subr))
|
Ok(ValueObj::Subr(subr))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn eval_lit(&self, lit: &Literal) -> EvalResult<ValueObj> {
|
||||||
|
let t = type_from_token_kind(lit.token.kind);
|
||||||
|
ValueObj::from_str(t, lit.token.content.clone()).ok_or_else(|| {
|
||||||
|
EvalError::invalid_literal(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
lit.token.loc(),
|
||||||
|
self.caused_by(),
|
||||||
|
)
|
||||||
|
.into()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn eval_const_expr(
|
pub(crate) fn eval_const_expr(
|
||||||
&self,
|
&self,
|
||||||
expr: &Expr,
|
expr: &Expr,
|
||||||
__name__: Option<&Str>,
|
__name__: Option<&Str>,
|
||||||
) -> EvalResult<ValueObj> {
|
) -> EvalResult<ValueObj> {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Lit(lit) => Ok(eval_lit(lit)),
|
Expr::Lit(lit) => self.eval_lit(lit),
|
||||||
Expr::Accessor(acc) => self.eval_const_acc(acc),
|
Expr::Accessor(acc) => self.eval_const_acc(acc),
|
||||||
Expr::BinOp(bin) => self.eval_const_bin(bin),
|
Expr::BinOp(bin) => self.eval_const_bin(bin),
|
||||||
Expr::UnaryOp(unary) => self.eval_const_unary(unary),
|
Expr::UnaryOp(unary) => self.eval_const_unary(unary),
|
||||||
|
@ -603,7 +610,7 @@ impl Context {
|
||||||
__name__: Option<&Str>,
|
__name__: Option<&Str>,
|
||||||
) -> EvalResult<ValueObj> {
|
) -> EvalResult<ValueObj> {
|
||||||
match expr {
|
match expr {
|
||||||
Expr::Lit(lit) => Ok(eval_lit(lit)),
|
Expr::Lit(lit) => self.eval_lit(lit),
|
||||||
Expr::Accessor(acc) => self.eval_const_acc(acc),
|
Expr::Accessor(acc) => self.eval_const_acc(acc),
|
||||||
Expr::BinOp(bin) => self.eval_const_bin(bin),
|
Expr::BinOp(bin) => self.eval_const_bin(bin),
|
||||||
Expr::UnaryOp(unary) => self.eval_const_unary(unary),
|
Expr::UnaryOp(unary) => self.eval_const_unary(unary),
|
||||||
|
|
|
@ -109,9 +109,14 @@ impl Context {
|
||||||
panic!("{} has already been registered as const", t.name());
|
panic!("{} has already been registered as const", t.name());
|
||||||
} else {
|
} else {
|
||||||
let name = VarName::from_str(t.name());
|
let name = VarName::from_str(t.name());
|
||||||
|
let meta_t = match ctx.kind {
|
||||||
|
ContextKind::Class => Type::ClassType,
|
||||||
|
ContextKind::Trait => Type::TraitType,
|
||||||
|
_ => Type::Type,
|
||||||
|
};
|
||||||
self.locals.insert(
|
self.locals.insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
VarInfo::new(Type, muty, Private, Builtin, None),
|
VarInfo::new(meta_t, muty, Private, Builtin, None),
|
||||||
);
|
);
|
||||||
self.consts
|
self.consts
|
||||||
.insert(name.clone(), ValueObj::builtin_t(t.clone()));
|
.insert(name.clone(), ValueObj::builtin_t(t.clone()));
|
||||||
|
@ -156,9 +161,14 @@ impl Context {
|
||||||
root_ctx.methods_list.push((ClassDefType::Simple(t), ctx));
|
root_ctx.methods_list.push((ClassDefType::Simple(t), ctx));
|
||||||
} else {
|
} else {
|
||||||
let name = VarName::from_str(t.name());
|
let name = VarName::from_str(t.name());
|
||||||
|
let meta_t = match ctx.kind {
|
||||||
|
ContextKind::Class => Type::ClassType,
|
||||||
|
ContextKind::Trait => Type::TraitType,
|
||||||
|
_ => Type::Type,
|
||||||
|
};
|
||||||
self.locals.insert(
|
self.locals.insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
VarInfo::new(Type, muty, Private, Builtin, None),
|
VarInfo::new(meta_t, muty, Private, Builtin, None),
|
||||||
);
|
);
|
||||||
self.consts
|
self.consts
|
||||||
.insert(name.clone(), ValueObj::builtin_t(t.clone()));
|
.insert(name.clone(), ValueObj::builtin_t(t.clone()));
|
||||||
|
@ -203,7 +213,7 @@ impl Context {
|
||||||
let name = VarName::from_static(name);
|
let name = VarName::from_static(name);
|
||||||
self.locals.insert(
|
self.locals.insert(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
VarInfo::new(Type, muty, Private, Builtin, None),
|
VarInfo::new(Patch, muty, Private, Builtin, None),
|
||||||
);
|
);
|
||||||
for method_name in ctx.locals.keys() {
|
for method_name in ctx.locals.keys() {
|
||||||
if let Some(patches) = self.method_impl_patches.get_mut(method_name) {
|
if let Some(patches) = self.method_impl_patches.get_mut(method_name) {
|
||||||
|
@ -454,7 +464,7 @@ impl Context {
|
||||||
/* Obj */
|
/* Obj */
|
||||||
let mut obj = Self::builtin_mono_class("Obj", 2);
|
let mut obj = Self::builtin_mono_class("Obj", 2);
|
||||||
let t = fn0_met(mono_q("Self"), mono_q("Self"));
|
let t = fn0_met(mono_q("Self"), mono_q("Self"));
|
||||||
let t = quant(t, set! {subtypeof(mono_q("Self"), builtin_mono("Obj"))});
|
let t = quant(t, set! {subtypeof(mono_q("Self"), Obj)});
|
||||||
obj.register_builtin_impl("clone", t, Const, Public);
|
obj.register_builtin_impl("clone", t, Const, Public);
|
||||||
obj.register_builtin_impl("__module__", Str, Const, Public);
|
obj.register_builtin_impl("__module__", Str, Const, Public);
|
||||||
obj.register_builtin_impl("__sizeof__", fn0_met(Obj, Nat), Const, Public);
|
obj.register_builtin_impl("__sizeof__", fn0_met(Obj, Nat), Const, Public);
|
||||||
|
@ -469,10 +479,11 @@ impl Context {
|
||||||
);
|
);
|
||||||
let mut obj_in = Self::builtin_methods("In", 2);
|
let mut obj_in = Self::builtin_methods("In", 2);
|
||||||
obj_in.register_builtin_impl("__in__", fn1_met(Obj, Type, Bool), Const, Public);
|
obj_in.register_builtin_impl("__in__", fn1_met(Obj, Type, Bool), Const, Public);
|
||||||
obj.register_trait(Obj, builtin_poly("Eq", vec![ty_tp(Type)]), obj_in);
|
obj.register_trait(Obj, builtin_poly("In", vec![ty_tp(Type)]), obj_in);
|
||||||
let mut obj_mutizable = Self::builtin_methods("Mutizable", 1);
|
let mut obj_mutizable = Self::builtin_methods("Mutizable", 1);
|
||||||
obj_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Obj!")));
|
obj_mutizable.register_builtin_const("MutType!", ValueObj::builtin_t(builtin_mono("Obj!")));
|
||||||
obj.register_trait(Obj, builtin_mono("Mutizable"), obj_mutizable);
|
obj.register_trait(Obj, builtin_mono("Mutizable"), obj_mutizable);
|
||||||
|
// Obj does not implement Eq
|
||||||
|
|
||||||
/* Float */
|
/* Float */
|
||||||
let mut float = Self::builtin_mono_class("Float", 2);
|
let mut float = Self::builtin_mono_class("Float", 2);
|
||||||
|
@ -760,6 +771,24 @@ impl Context {
|
||||||
let mut str_show = Self::builtin_methods("Show", 1);
|
let mut str_show = Self::builtin_methods("Show", 1);
|
||||||
str_show.register_builtin_impl("to_str", fn0_met(Str, Str), Immutable, Public);
|
str_show.register_builtin_impl("to_str", fn0_met(Str, Str), Immutable, Public);
|
||||||
str_.register_trait(Str, builtin_mono("Show"), str_show);
|
str_.register_trait(Str, builtin_mono("Show"), str_show);
|
||||||
|
/* NoneType */
|
||||||
|
let mut nonetype = Self::builtin_mono_class("NoneType", 10);
|
||||||
|
nonetype.register_superclass(Obj, &obj);
|
||||||
|
let mut nonetype_eq = Self::builtin_methods("Eq", 2);
|
||||||
|
nonetype_eq.register_builtin_impl(
|
||||||
|
"__eq__",
|
||||||
|
fn1_met(NoneType, NoneType, Bool),
|
||||||
|
Const,
|
||||||
|
Public,
|
||||||
|
);
|
||||||
|
nonetype.register_trait(
|
||||||
|
NoneType,
|
||||||
|
builtin_poly("Eq", vec![ty_tp(NoneType)]),
|
||||||
|
nonetype_eq,
|
||||||
|
);
|
||||||
|
let mut nonetype_show = Self::builtin_methods("Show", 1);
|
||||||
|
nonetype_show.register_builtin_impl("to_str", fn0_met(NoneType, Str), Immutable, Public);
|
||||||
|
nonetype.register_trait(NoneType, builtin_mono("Show"), nonetype_show);
|
||||||
/* Type */
|
/* Type */
|
||||||
let mut type_ = Self::builtin_mono_class("Type", 2);
|
let mut type_ = Self::builtin_mono_class("Type", 2);
|
||||||
type_.register_superclass(Obj, &obj);
|
type_.register_superclass(Obj, &obj);
|
||||||
|
@ -783,6 +812,21 @@ impl Context {
|
||||||
builtin_poly("Eq", vec![ty_tp(ClassType)]),
|
builtin_poly("Eq", vec![ty_tp(ClassType)]),
|
||||||
class_eq,
|
class_eq,
|
||||||
);
|
);
|
||||||
|
let mut trait_type = Self::builtin_mono_class("TraitType", 2);
|
||||||
|
trait_type.register_superclass(Type, &type_);
|
||||||
|
trait_type.register_marker_trait(builtin_mono("Named"));
|
||||||
|
let mut trait_eq = Self::builtin_methods("Eq", 2);
|
||||||
|
trait_eq.register_builtin_impl(
|
||||||
|
"__eq__",
|
||||||
|
fn1_met(TraitType, TraitType, Bool),
|
||||||
|
Const,
|
||||||
|
Public,
|
||||||
|
);
|
||||||
|
trait_type.register_trait(
|
||||||
|
TraitType,
|
||||||
|
builtin_poly("Eq", vec![ty_tp(TraitType)]),
|
||||||
|
trait_eq,
|
||||||
|
);
|
||||||
let g_module_t = builtin_mono("GenericModule");
|
let g_module_t = builtin_mono("GenericModule");
|
||||||
let mut generic_module = Self::builtin_mono_class("GenericModule", 2);
|
let mut generic_module = Self::builtin_mono_class("GenericModule", 2);
|
||||||
generic_module.register_superclass(Obj, &obj);
|
generic_module.register_superclass(Obj, &obj);
|
||||||
|
@ -849,7 +893,15 @@ impl Context {
|
||||||
Immutable,
|
Immutable,
|
||||||
Public,
|
Public,
|
||||||
);
|
);
|
||||||
array_.register_trait(array_t, builtin_mono("Show"), array_show);
|
array_.register_trait(array_t.clone(), builtin_mono("Show"), array_show);
|
||||||
|
let array_type_t = builtin_poly("ArrayType", vec![mono_q_tp("T"), mono_q_tp("N")]);
|
||||||
|
let mut array_type = Self::builtin_poly_class(
|
||||||
|
"ArrayType",
|
||||||
|
vec![PS::named_nd("T", Type), PS::named_nd("N", Nat)],
|
||||||
|
2,
|
||||||
|
);
|
||||||
|
array_type.register_superclass(array_t.clone(), &array_);
|
||||||
|
array_type.register_superclass(Type, &type_);
|
||||||
/* Set */
|
/* Set */
|
||||||
let mut set_ =
|
let mut set_ =
|
||||||
Self::builtin_poly_class("Set", vec![PS::t_nd("T"), PS::named_nd("N", Nat)], 10);
|
Self::builtin_poly_class("Set", vec![PS::t_nd("T"), PS::named_nd("N", Nat)], 10);
|
||||||
|
@ -892,6 +944,14 @@ impl Context {
|
||||||
let mut set_show = Self::builtin_methods("Show", 1);
|
let mut set_show = Self::builtin_methods("Show", 1);
|
||||||
set_show.register_builtin_impl("to_str", fn0_met(set_t.clone(), Str), Immutable, Public);
|
set_show.register_builtin_impl("to_str", fn0_met(set_t.clone(), Str), Immutable, Public);
|
||||||
set_.register_trait(set_t.clone(), builtin_mono("Show"), set_show);
|
set_.register_trait(set_t.clone(), builtin_mono("Show"), set_show);
|
||||||
|
let set_type_t = builtin_poly("SetType", vec![mono_q_tp("T"), mono_q_tp("N")]);
|
||||||
|
let mut set_type = Self::builtin_poly_class(
|
||||||
|
"SetType",
|
||||||
|
vec![PS::named_nd("T", Type), PS::named_nd("N", Nat)],
|
||||||
|
2,
|
||||||
|
);
|
||||||
|
set_type.register_superclass(set_t.clone(), &set_);
|
||||||
|
set_type.register_superclass(Type, &type_);
|
||||||
/* Bytes */
|
/* Bytes */
|
||||||
let mut bytes = Self::builtin_mono_class("Bytes", 2);
|
let mut bytes = Self::builtin_mono_class("Bytes", 2);
|
||||||
bytes.register_superclass(Obj, &obj);
|
bytes.register_superclass(Obj, &obj);
|
||||||
|
@ -1117,243 +1177,16 @@ impl Context {
|
||||||
),
|
),
|
||||||
tuple5_eq,
|
tuple5_eq,
|
||||||
);
|
);
|
||||||
let mut tuple6 = Self::builtin_poly_class(
|
|
||||||
"Tuple6",
|
|
||||||
vec![
|
|
||||||
PS::t_nd("A"),
|
|
||||||
PS::t_nd("B"),
|
|
||||||
PS::t_nd("C"),
|
|
||||||
PS::t_nd("D"),
|
|
||||||
PS::t_nd("E"),
|
|
||||||
PS::t_nd("F"),
|
|
||||||
],
|
|
||||||
2,
|
|
||||||
);
|
|
||||||
tuple6.register_superclass(builtin_mono("Tuple"), &tuple_);
|
|
||||||
let mut tuple6_eq = Self::builtin_methods("Eq", 2);
|
|
||||||
tuple6_eq.register_builtin_impl(
|
|
||||||
"__eq__",
|
|
||||||
fn1_met(
|
|
||||||
builtin_poly(
|
|
||||||
"Tuple6",
|
|
||||||
vec![
|
|
||||||
ty_tp(mono_q("A")),
|
|
||||||
ty_tp(mono_q("B")),
|
|
||||||
ty_tp(mono_q("C")),
|
|
||||||
ty_tp(mono_q("D")),
|
|
||||||
ty_tp(mono_q("E")),
|
|
||||||
ty_tp(mono_q("F")),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
builtin_poly(
|
|
||||||
"Tuple6",
|
|
||||||
vec![
|
|
||||||
ty_tp(mono_q("A")),
|
|
||||||
ty_tp(mono_q("B")),
|
|
||||||
ty_tp(mono_q("C")),
|
|
||||||
ty_tp(mono_q("D")),
|
|
||||||
ty_tp(mono_q("E")),
|
|
||||||
ty_tp(mono_q("F")),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Bool,
|
|
||||||
),
|
|
||||||
Const,
|
|
||||||
Public,
|
|
||||||
);
|
|
||||||
tuple6.register_trait(
|
|
||||||
builtin_poly(
|
|
||||||
"Tuple6",
|
|
||||||
vec![
|
|
||||||
ty_tp(mono_q("A")),
|
|
||||||
ty_tp(mono_q("B")),
|
|
||||||
ty_tp(mono_q("C")),
|
|
||||||
ty_tp(mono_q("D")),
|
|
||||||
ty_tp(mono_q("E")),
|
|
||||||
ty_tp(mono_q("F")),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
builtin_poly(
|
|
||||||
"Eq",
|
|
||||||
vec![ty_tp(builtin_poly(
|
|
||||||
"Tuple6",
|
|
||||||
vec![
|
|
||||||
ty_tp(mono_q("A")),
|
|
||||||
ty_tp(mono_q("B")),
|
|
||||||
ty_tp(mono_q("C")),
|
|
||||||
ty_tp(mono_q("D")),
|
|
||||||
ty_tp(mono_q("E")),
|
|
||||||
ty_tp(mono_q("F")),
|
|
||||||
],
|
|
||||||
))],
|
|
||||||
),
|
|
||||||
tuple6_eq,
|
|
||||||
);
|
|
||||||
let mut tuple7 = Self::builtin_poly_class(
|
|
||||||
"Tuple7",
|
|
||||||
vec![
|
|
||||||
PS::t_nd("A"),
|
|
||||||
PS::t_nd("B"),
|
|
||||||
PS::t_nd("C"),
|
|
||||||
PS::t_nd("D"),
|
|
||||||
PS::t_nd("E"),
|
|
||||||
PS::t_nd("F"),
|
|
||||||
PS::t_nd("G"),
|
|
||||||
],
|
|
||||||
2,
|
|
||||||
);
|
|
||||||
tuple7.register_superclass(builtin_mono("Tuple"), &tuple_);
|
|
||||||
let mut tuple7_eq = Self::builtin_methods("Eq", 2);
|
|
||||||
tuple7_eq.register_builtin_impl(
|
|
||||||
"__eq__",
|
|
||||||
fn1_met(
|
|
||||||
builtin_poly(
|
|
||||||
"Tuple7",
|
|
||||||
vec![
|
|
||||||
ty_tp(mono_q("A")),
|
|
||||||
ty_tp(mono_q("B")),
|
|
||||||
ty_tp(mono_q("C")),
|
|
||||||
ty_tp(mono_q("D")),
|
|
||||||
ty_tp(mono_q("E")),
|
|
||||||
ty_tp(mono_q("F")),
|
|
||||||
ty_tp(mono_q("G")),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
builtin_poly(
|
|
||||||
"Tuple7",
|
|
||||||
vec![
|
|
||||||
ty_tp(mono_q("A")),
|
|
||||||
ty_tp(mono_q("B")),
|
|
||||||
ty_tp(mono_q("C")),
|
|
||||||
ty_tp(mono_q("D")),
|
|
||||||
ty_tp(mono_q("E")),
|
|
||||||
ty_tp(mono_q("F")),
|
|
||||||
ty_tp(mono_q("G")),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Bool,
|
|
||||||
),
|
|
||||||
Const,
|
|
||||||
Public,
|
|
||||||
);
|
|
||||||
tuple7.register_trait(
|
|
||||||
builtin_poly(
|
|
||||||
"Tuple7",
|
|
||||||
vec![
|
|
||||||
ty_tp(mono_q("A")),
|
|
||||||
ty_tp(mono_q("B")),
|
|
||||||
ty_tp(mono_q("C")),
|
|
||||||
ty_tp(mono_q("D")),
|
|
||||||
ty_tp(mono_q("E")),
|
|
||||||
ty_tp(mono_q("F")),
|
|
||||||
ty_tp(mono_q("G")),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
builtin_poly(
|
|
||||||
"Eq",
|
|
||||||
vec![ty_tp(builtin_poly(
|
|
||||||
"Tuple7",
|
|
||||||
vec![
|
|
||||||
ty_tp(mono_q("A")),
|
|
||||||
ty_tp(mono_q("B")),
|
|
||||||
ty_tp(mono_q("C")),
|
|
||||||
ty_tp(mono_q("D")),
|
|
||||||
ty_tp(mono_q("E")),
|
|
||||||
ty_tp(mono_q("F")),
|
|
||||||
ty_tp(mono_q("G")),
|
|
||||||
],
|
|
||||||
))],
|
|
||||||
),
|
|
||||||
tuple7_eq,
|
|
||||||
);
|
|
||||||
let mut tuple8 = Self::builtin_poly_class(
|
|
||||||
"Tuple8",
|
|
||||||
vec![
|
|
||||||
PS::t_nd("A"),
|
|
||||||
PS::t_nd("B"),
|
|
||||||
PS::t_nd("C"),
|
|
||||||
PS::t_nd("D"),
|
|
||||||
PS::t_nd("E"),
|
|
||||||
PS::t_nd("F"),
|
|
||||||
PS::t_nd("G"),
|
|
||||||
PS::t_nd("H"),
|
|
||||||
],
|
|
||||||
2,
|
|
||||||
);
|
|
||||||
tuple8.register_superclass(builtin_mono("Tuple"), &tuple_);
|
|
||||||
let mut tuple8_eq = Self::builtin_methods("Eq", 2);
|
|
||||||
tuple8_eq.register_builtin_impl(
|
|
||||||
"__eq__",
|
|
||||||
fn1_met(
|
|
||||||
builtin_poly(
|
|
||||||
"Tuple8",
|
|
||||||
vec![
|
|
||||||
ty_tp(mono_q("A")),
|
|
||||||
ty_tp(mono_q("B")),
|
|
||||||
ty_tp(mono_q("C")),
|
|
||||||
ty_tp(mono_q("D")),
|
|
||||||
ty_tp(mono_q("E")),
|
|
||||||
ty_tp(mono_q("F")),
|
|
||||||
ty_tp(mono_q("G")),
|
|
||||||
ty_tp(mono_q("H")),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
builtin_poly(
|
|
||||||
"Tuple8",
|
|
||||||
vec![
|
|
||||||
ty_tp(mono_q("A")),
|
|
||||||
ty_tp(mono_q("B")),
|
|
||||||
ty_tp(mono_q("C")),
|
|
||||||
ty_tp(mono_q("D")),
|
|
||||||
ty_tp(mono_q("E")),
|
|
||||||
ty_tp(mono_q("F")),
|
|
||||||
ty_tp(mono_q("G")),
|
|
||||||
ty_tp(mono_q("H")),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Bool,
|
|
||||||
),
|
|
||||||
Const,
|
|
||||||
Public,
|
|
||||||
);
|
|
||||||
tuple8.register_trait(
|
|
||||||
builtin_poly(
|
|
||||||
"Tuple8",
|
|
||||||
vec![
|
|
||||||
ty_tp(mono_q("A")),
|
|
||||||
ty_tp(mono_q("B")),
|
|
||||||
ty_tp(mono_q("C")),
|
|
||||||
ty_tp(mono_q("D")),
|
|
||||||
ty_tp(mono_q("E")),
|
|
||||||
ty_tp(mono_q("F")),
|
|
||||||
ty_tp(mono_q("G")),
|
|
||||||
ty_tp(mono_q("H")),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
builtin_poly(
|
|
||||||
"Eq",
|
|
||||||
vec![ty_tp(builtin_poly(
|
|
||||||
"Tuple8",
|
|
||||||
vec![
|
|
||||||
ty_tp(mono_q("A")),
|
|
||||||
ty_tp(mono_q("B")),
|
|
||||||
ty_tp(mono_q("C")),
|
|
||||||
ty_tp(mono_q("D")),
|
|
||||||
ty_tp(mono_q("E")),
|
|
||||||
ty_tp(mono_q("F")),
|
|
||||||
ty_tp(mono_q("G")),
|
|
||||||
ty_tp(mono_q("H")),
|
|
||||||
],
|
|
||||||
))],
|
|
||||||
),
|
|
||||||
tuple8_eq,
|
|
||||||
);
|
|
||||||
/* record */
|
/* record */
|
||||||
let mut record = Self::builtin_mono_class("Record", 2);
|
let mut record = Self::builtin_mono_class("Record", 2);
|
||||||
record.register_superclass(Obj, &obj);
|
record.register_superclass(Obj, &obj);
|
||||||
let mut record_type = Self::builtin_mono_class("RecordType", 2);
|
let mut record_type = Self::builtin_mono_class("RecordType", 2);
|
||||||
record_type.register_superclass(builtin_mono("Record"), &record);
|
record_type.register_superclass(builtin_mono("Record"), &record);
|
||||||
record_type.register_superclass(builtin_mono("Type"), &type_);
|
record_type.register_superclass(Type, &type_);
|
||||||
|
/* Or (true or type) */
|
||||||
|
let or_t = builtin_poly("Or", vec![ty_tp(mono_q("L")), ty_tp(mono_q("R"))]);
|
||||||
|
let mut or = Self::builtin_poly_class("Or", vec![PS::t_nd("L"), PS::t_nd("R")], 2);
|
||||||
|
or.register_superclass(Obj, &obj);
|
||||||
/* Float_mut */
|
/* Float_mut */
|
||||||
let mut float_mut = Self::builtin_mono_class("Float!", 2);
|
let mut float_mut = Self::builtin_mono_class("Float!", 2);
|
||||||
float_mut.register_superclass(Float, &float);
|
float_mut.register_superclass(Float, &float);
|
||||||
|
@ -1378,15 +1211,7 @@ impl Context {
|
||||||
ratio_mut.register_superclass(Ratio, &ratio);
|
ratio_mut.register_superclass(Ratio, &ratio);
|
||||||
let mut ratio_mut_mutable = Self::builtin_methods("Mutable", 2);
|
let mut ratio_mut_mutable = Self::builtin_methods("Mutable", 2);
|
||||||
ratio_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Ratio));
|
ratio_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Ratio));
|
||||||
let f_t = kw(
|
let f_t = kw("f", func(vec![kw("old", Ratio)], None, vec![], Ratio));
|
||||||
"f",
|
|
||||||
func(
|
|
||||||
vec![kw("old", builtin_mono("Ratio"))],
|
|
||||||
None,
|
|
||||||
vec![],
|
|
||||||
builtin_mono("Ratio"),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
let t = pr_met(
|
let t = pr_met(
|
||||||
ref_mut(builtin_mono("Ratio!"), None),
|
ref_mut(builtin_mono("Ratio!"), None),
|
||||||
vec![f_t],
|
vec![f_t],
|
||||||
|
@ -1462,7 +1287,7 @@ impl Context {
|
||||||
);
|
);
|
||||||
/* Str_mut */
|
/* Str_mut */
|
||||||
let mut str_mut = Self::builtin_mono_class("Str!", 2);
|
let mut str_mut = Self::builtin_mono_class("Str!", 2);
|
||||||
str_mut.register_superclass(Str, &str_);
|
str_mut.register_superclass(Str, &nonetype);
|
||||||
let mut str_mut_mutable = Self::builtin_methods("Mutable", 2);
|
let mut str_mut_mutable = Self::builtin_methods("Mutable", 2);
|
||||||
str_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Str));
|
str_mut_mutable.register_builtin_const("ImmutType", ValueObj::builtin_t(Str));
|
||||||
let f_t = kw("f", func(vec![kw("old", Str)], None, vec![], Str));
|
let f_t = kw("f", func(vec![kw("old", Str)], None, vec![], Str));
|
||||||
|
@ -1500,7 +1325,6 @@ impl Context {
|
||||||
file_mut_readable,
|
file_mut_readable,
|
||||||
);
|
);
|
||||||
/* Array_mut */
|
/* Array_mut */
|
||||||
let array_t = builtin_poly("Array", vec![ty_tp(mono_q("T")), mono_q_tp("N")]);
|
|
||||||
let array_mut_t = builtin_poly("Array!", vec![ty_tp(mono_q("T")), mono_q_tp("N")]);
|
let array_mut_t = builtin_poly("Array!", vec![ty_tp(mono_q("T")), mono_q_tp("N")]);
|
||||||
let mut array_mut_ = Self::builtin_poly_class(
|
let mut array_mut_ = Self::builtin_poly_class(
|
||||||
"Array!",
|
"Array!",
|
||||||
|
@ -1617,7 +1441,8 @@ impl Context {
|
||||||
/* Range */
|
/* Range */
|
||||||
let range_t = builtin_poly("Range", vec![TyParam::t(mono_q("T"))]);
|
let range_t = builtin_poly("Range", vec![TyParam::t(mono_q("T"))]);
|
||||||
let mut range = Self::builtin_poly_class("Range", vec![PS::t_nd("T")], 2);
|
let mut range = Self::builtin_poly_class("Range", vec![PS::t_nd("T")], 2);
|
||||||
range.register_superclass(Obj, &obj);
|
// range.register_superclass(Obj, &obj);
|
||||||
|
range.register_superclass(Type, &type_);
|
||||||
range.register_marker_trait(builtin_poly("Output", vec![ty_tp(mono_q("T"))]));
|
range.register_marker_trait(builtin_poly("Output", vec![ty_tp(mono_q("T"))]));
|
||||||
let mut range_eq = Self::builtin_methods("Eq", 2);
|
let mut range_eq = Self::builtin_methods("Eq", 2);
|
||||||
range_eq.register_builtin_impl(
|
range_eq.register_builtin_impl(
|
||||||
|
@ -1653,12 +1478,16 @@ impl Context {
|
||||||
self.register_builtin_type(Ratio, ratio, Const);
|
self.register_builtin_type(Ratio, ratio, Const);
|
||||||
self.register_builtin_type(Bool, bool_, Const);
|
self.register_builtin_type(Bool, bool_, Const);
|
||||||
self.register_builtin_type(Str, str_, Const);
|
self.register_builtin_type(Str, str_, Const);
|
||||||
|
self.register_builtin_type(NoneType, nonetype, Const);
|
||||||
self.register_builtin_type(Type, type_, Const);
|
self.register_builtin_type(Type, type_, Const);
|
||||||
self.register_builtin_type(ClassType, class_type, Const);
|
self.register_builtin_type(ClassType, class_type, Const);
|
||||||
|
self.register_builtin_type(TraitType, trait_type, Const);
|
||||||
self.register_builtin_type(g_module_t, generic_module, Const);
|
self.register_builtin_type(g_module_t, generic_module, Const);
|
||||||
self.register_builtin_type(module_t, module, Const);
|
self.register_builtin_type(module_t, module, Const);
|
||||||
self.register_builtin_type(array_t, array_, Const);
|
self.register_builtin_type(array_t, array_, Const);
|
||||||
|
self.register_builtin_type(array_type_t, array_type, Const);
|
||||||
self.register_builtin_type(set_t, set_, Const);
|
self.register_builtin_type(set_t, set_, Const);
|
||||||
|
self.register_builtin_type(set_type_t, set_type, Const);
|
||||||
self.register_builtin_type(builtin_mono("Bytes"), bytes, Const);
|
self.register_builtin_type(builtin_mono("Bytes"), bytes, Const);
|
||||||
self.register_builtin_type(tuple(vec![mono_q("A")]), tuple1, Const);
|
self.register_builtin_type(tuple(vec![mono_q("A")]), tuple1, Const);
|
||||||
self.register_builtin_type(tuple(vec![mono_q("A"), mono_q("B")]), tuple2, Const);
|
self.register_builtin_type(tuple(vec![mono_q("A"), mono_q("B")]), tuple2, Const);
|
||||||
|
@ -1683,47 +1512,9 @@ impl Context {
|
||||||
tuple5,
|
tuple5,
|
||||||
Const,
|
Const,
|
||||||
);
|
);
|
||||||
self.register_builtin_type(
|
|
||||||
tuple(vec![
|
|
||||||
mono_q("A"),
|
|
||||||
mono_q("B"),
|
|
||||||
mono_q("C"),
|
|
||||||
mono_q("D"),
|
|
||||||
mono_q("E"),
|
|
||||||
mono_q("F"),
|
|
||||||
]),
|
|
||||||
tuple6,
|
|
||||||
Const,
|
|
||||||
);
|
|
||||||
self.register_builtin_type(
|
|
||||||
tuple(vec![
|
|
||||||
mono_q("A"),
|
|
||||||
mono_q("B"),
|
|
||||||
mono_q("C"),
|
|
||||||
mono_q("D"),
|
|
||||||
mono_q("E"),
|
|
||||||
mono_q("F"),
|
|
||||||
mono_q("G"),
|
|
||||||
]),
|
|
||||||
tuple7,
|
|
||||||
Const,
|
|
||||||
);
|
|
||||||
self.register_builtin_type(
|
|
||||||
tuple(vec![
|
|
||||||
mono_q("A"),
|
|
||||||
mono_q("B"),
|
|
||||||
mono_q("C"),
|
|
||||||
mono_q("D"),
|
|
||||||
mono_q("E"),
|
|
||||||
mono_q("F"),
|
|
||||||
mono_q("G"),
|
|
||||||
mono_q("H"),
|
|
||||||
]),
|
|
||||||
tuple8,
|
|
||||||
Const,
|
|
||||||
);
|
|
||||||
self.register_builtin_type(builtin_mono("Record"), record, Const);
|
self.register_builtin_type(builtin_mono("Record"), record, Const);
|
||||||
self.register_builtin_type(builtin_mono("RecordType"), record_type, Const);
|
self.register_builtin_type(builtin_mono("RecordType"), record_type, Const);
|
||||||
|
self.register_builtin_type(or_t, or, Const);
|
||||||
self.register_builtin_type(builtin_mono("Int!"), int_mut, Const);
|
self.register_builtin_type(builtin_mono("Int!"), int_mut, Const);
|
||||||
self.register_builtin_type(builtin_mono("Nat!"), nat_mut, Const);
|
self.register_builtin_type(builtin_mono("Nat!"), nat_mut, Const);
|
||||||
self.register_builtin_type(builtin_mono("Float!"), float_mut, Const);
|
self.register_builtin_type(builtin_mono("Float!"), float_mut, Const);
|
||||||
|
@ -1744,12 +1535,19 @@ impl Context {
|
||||||
|
|
||||||
fn init_builtin_funcs(&mut self) {
|
fn init_builtin_funcs(&mut self) {
|
||||||
let t_abs = nd_func(vec![kw("n", builtin_mono("Num"))], None, Nat);
|
let t_abs = nd_func(vec![kw("n", builtin_mono("Num"))], None, Nat);
|
||||||
|
let t_ascii = nd_func(vec![kw("object", Obj)], None, Str);
|
||||||
let t_assert = func(
|
let t_assert = func(
|
||||||
vec![kw("condition", Bool)],
|
vec![kw("condition", Bool)],
|
||||||
None,
|
None,
|
||||||
vec![kw("err_message", Str)],
|
vec![kw("err_message", Str)],
|
||||||
NoneType,
|
NoneType,
|
||||||
);
|
);
|
||||||
|
let t_bin = nd_func(vec![kw("n", Int)], None, Str);
|
||||||
|
let t_chr = nd_func(
|
||||||
|
vec![kw("i", Type::from(value(0usize)..=value(1_114_111usize)))],
|
||||||
|
None,
|
||||||
|
Str,
|
||||||
|
);
|
||||||
let t_classof = nd_func(vec![kw("old", Obj)], None, ClassType);
|
let t_classof = nd_func(vec![kw("old", Obj)], None, ClassType);
|
||||||
let t_compile = nd_func(vec![kw("src", Str)], None, Code);
|
let t_compile = nd_func(vec![kw("src", Str)], None, Code);
|
||||||
let t_cond = nd_func(
|
let t_cond = nd_func(
|
||||||
|
@ -1786,6 +1584,27 @@ impl Context {
|
||||||
module(mono_q_tp("Path")),
|
module(mono_q_tp("Path")),
|
||||||
);
|
);
|
||||||
let t_import = quant(t_import, set! {static_instance("Path", Str)});
|
let t_import = quant(t_import, set! {static_instance("Path", Str)});
|
||||||
|
let t_isinstance = nd_func(
|
||||||
|
vec![
|
||||||
|
kw("object", Obj),
|
||||||
|
kw("classinfo", ClassType), // TODO: => ClassInfo
|
||||||
|
],
|
||||||
|
None,
|
||||||
|
Bool,
|
||||||
|
);
|
||||||
|
let t_issubclass = nd_func(
|
||||||
|
vec![
|
||||||
|
kw("subclass", ClassType),
|
||||||
|
kw("classinfo", ClassType), // TODO: => ClassInfo
|
||||||
|
],
|
||||||
|
None,
|
||||||
|
Bool,
|
||||||
|
);
|
||||||
|
let t_len = nd_func(
|
||||||
|
vec![kw("s", builtin_poly("Seq", vec![TyParam::erased(Type)]))],
|
||||||
|
None,
|
||||||
|
Nat,
|
||||||
|
);
|
||||||
let t_log = func(
|
let t_log = func(
|
||||||
vec![],
|
vec![],
|
||||||
Some(kw("objects", ref_(Obj))),
|
Some(kw("objects", ref_(Obj))),
|
||||||
|
@ -1797,31 +1616,57 @@ impl Context {
|
||||||
],
|
],
|
||||||
NoneType,
|
NoneType,
|
||||||
);
|
);
|
||||||
|
let t_oct = nd_func(vec![kw("x", Int)], None, Str);
|
||||||
|
let t_ord = nd_func(vec![kw("c", Str)], None, Nat);
|
||||||
|
let t_panic = nd_func(vec![kw("err_message", Str)], None, Never);
|
||||||
|
let m = mono_q("M");
|
||||||
|
// TODO: mod
|
||||||
|
let t_pow = nd_func(
|
||||||
|
vec![kw("base", m.clone()), kw("exp", m.clone())],
|
||||||
|
None,
|
||||||
|
m.clone(),
|
||||||
|
);
|
||||||
|
let t_pow = quant(
|
||||||
|
t_pow,
|
||||||
|
set! {static_instance("M", builtin_poly("Mul", vec![ty_tp(m)]))},
|
||||||
|
);
|
||||||
let t_pyimport = nd_func(
|
let t_pyimport = nd_func(
|
||||||
vec![anon(tp_enum(Str, set! {mono_q_tp("Path")}))],
|
vec![anon(tp_enum(Str, set! {mono_q_tp("Path")}))],
|
||||||
None,
|
None,
|
||||||
module(mono_q_tp("Path")),
|
module(mono_q_tp("Path")),
|
||||||
);
|
);
|
||||||
let t_panic = nd_func(vec![kw("err_message", Str)], None, NoneType);
|
|
||||||
let t_pyimport = quant(t_pyimport, set! {static_instance("Path", Str)});
|
let t_pyimport = quant(t_pyimport, set! {static_instance("Path", Str)});
|
||||||
let t_quit = func(vec![], None, vec![kw("code", Int)], NoneType);
|
let t_quit = func(vec![], None, vec![kw("code", Int)], NoneType);
|
||||||
let t_exit = t_quit.clone();
|
let t_exit = t_quit.clone();
|
||||||
|
let t_repr = nd_func(vec![kw("object", Obj)], None, Str);
|
||||||
|
let t_round = nd_func(vec![kw("number", Float)], None, Int);
|
||||||
self.register_builtin_impl("abs", t_abs, Immutable, Private);
|
self.register_builtin_impl("abs", t_abs, Immutable, Private);
|
||||||
|
self.register_builtin_impl("ascii", t_ascii, Immutable, Private);
|
||||||
self.register_builtin_impl("assert", t_assert, Const, Private); // assert casting に悪影響が出る可能性があるため、Constとしておく
|
self.register_builtin_impl("assert", t_assert, Const, Private); // assert casting に悪影響が出る可能性があるため、Constとしておく
|
||||||
|
self.register_builtin_impl("bin", t_bin, Immutable, Private);
|
||||||
|
self.register_builtin_impl("chr", t_chr, Immutable, Private);
|
||||||
self.register_builtin_impl("classof", t_classof, Immutable, Private);
|
self.register_builtin_impl("classof", t_classof, Immutable, Private);
|
||||||
self.register_builtin_impl("compile", t_compile, Immutable, Private);
|
self.register_builtin_impl("compile", t_compile, Immutable, Private);
|
||||||
self.register_builtin_impl("cond", t_cond, Immutable, Private);
|
self.register_builtin_impl("cond", t_cond, Immutable, Private);
|
||||||
self.register_builtin_impl("discard", t_discard, Immutable, Private);
|
self.register_builtin_impl("discard", t_discard, Immutable, Private);
|
||||||
self.register_builtin_impl("exit", t_exit, Immutable, Private);
|
self.register_builtin_impl("exit", t_exit, Immutable, Private);
|
||||||
self.register_builtin_impl("if", t_if, Immutable, Private);
|
self.register_builtin_impl("if", t_if, Immutable, Private);
|
||||||
self.register_builtin_impl("log", t_log, Immutable, Private);
|
|
||||||
self.register_builtin_impl("import", t_import, Immutable, Private);
|
self.register_builtin_impl("import", t_import, Immutable, Private);
|
||||||
|
self.register_builtin_impl("isinstance", t_isinstance, Immutable, Private);
|
||||||
|
self.register_builtin_impl("issubclass", t_issubclass, Immutable, Private);
|
||||||
|
self.register_builtin_impl("len", t_len, Immutable, Private);
|
||||||
|
self.register_builtin_impl("log", t_log, Immutable, Private);
|
||||||
|
self.register_builtin_impl("oct", t_oct, Immutable, Private);
|
||||||
|
self.register_builtin_impl("ord", t_ord, Immutable, Private);
|
||||||
self.register_builtin_impl("panic", t_panic, Immutable, Private);
|
self.register_builtin_impl("panic", t_panic, Immutable, Private);
|
||||||
|
self.register_builtin_impl("pow", t_pow, Immutable, Private);
|
||||||
if cfg!(feature = "debug") {
|
if cfg!(feature = "debug") {
|
||||||
self.register_builtin_impl("py", t_pyimport.clone(), Immutable, Private);
|
self.register_builtin_impl("py", t_pyimport.clone(), Immutable, Private);
|
||||||
}
|
}
|
||||||
self.register_builtin_impl("pyimport", t_pyimport, Immutable, Private);
|
self.register_builtin_impl("pyimport", t_pyimport, Immutable, Private);
|
||||||
self.register_builtin_impl("quit", t_quit, Immutable, Private);
|
self.register_builtin_impl("quit", t_quit, Immutable, Private);
|
||||||
|
self.register_builtin_impl("repr", t_repr, Immutable, Private);
|
||||||
|
self.register_builtin_impl("round", t_round, Immutable, Private);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_builtin_const_funcs(&mut self) {
|
fn init_builtin_const_funcs(&mut self) {
|
||||||
|
@ -2051,7 +1896,7 @@ impl Context {
|
||||||
self.register_builtin_decl("__rorng__", op_t.clone(), Private);
|
self.register_builtin_decl("__rorng__", op_t.clone(), Private);
|
||||||
self.register_builtin_decl("__orng__", op_t, Private);
|
self.register_builtin_decl("__orng__", op_t, Private);
|
||||||
// TODO: use existential type: |T: Type| (T, In(T)) -> Bool
|
// TODO: use existential type: |T: Type| (T, In(T)) -> Bool
|
||||||
let op_t = bin_op(mono_q("T"), mono_q("I"), Bool);
|
let op_t = bin_op(mono_q("I"), mono_q("T"), Bool);
|
||||||
let op_t = quant(
|
let op_t = quant(
|
||||||
op_t,
|
op_t,
|
||||||
set! { static_instance("T", Type), subtypeof(mono_q("I"), builtin_poly("In", vec![ty_tp(mono_q("T"))])) },
|
set! { static_instance("T", Type), subtypeof(mono_q("I"), builtin_poly("In", vec![ty_tp(mono_q("T"))])) },
|
||||||
|
|
|
@ -17,7 +17,7 @@ use erg_parser::ast::{self, Identifier};
|
||||||
use erg_parser::token::Token;
|
use erg_parser::token::Token;
|
||||||
|
|
||||||
use erg_type::constructors::{
|
use erg_type::constructors::{
|
||||||
anon, builtin_mono, free_var, func, module, mono_proj, subr_t, v_enum,
|
anon, builtin_mono, builtin_poly, free_var, func, module, mono_proj, subr_t, v_enum,
|
||||||
};
|
};
|
||||||
use erg_type::free::Constraint;
|
use erg_type::free::Constraint;
|
||||||
use erg_type::typaram::TyParam;
|
use erg_type::typaram::TyParam;
|
||||||
|
@ -87,6 +87,31 @@ impl Context {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn get_mut_current_scope_var(&mut self, name: &str) -> Option<&mut VarInfo> {
|
||||||
|
self.locals
|
||||||
|
.get_mut(name)
|
||||||
|
.or_else(|| self.decls.get_mut(name))
|
||||||
|
.or_else(|| {
|
||||||
|
self.params
|
||||||
|
.iter_mut()
|
||||||
|
.find(|(opt_name, _)| {
|
||||||
|
opt_name
|
||||||
|
.as_ref()
|
||||||
|
.map(|n| &n.inspect()[..] == name)
|
||||||
|
.unwrap_or(false)
|
||||||
|
})
|
||||||
|
.map(|(_, vi)| vi)
|
||||||
|
})
|
||||||
|
.or_else(|| {
|
||||||
|
for (_, methods) in self.methods_list.iter_mut() {
|
||||||
|
if let Some(vi) = methods.get_mut_current_scope_var(name) {
|
||||||
|
return Some(vi);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn get_local_kv(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
|
pub(crate) fn get_local_kv(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
|
||||||
self.locals.get_key_value(name)
|
self.locals.get_key_value(name)
|
||||||
}
|
}
|
||||||
|
@ -1160,8 +1185,19 @@ impl Context {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_similar_name(&self, name: &str) -> Option<&str> {
|
pub(crate) fn get_similar_name(&self, name: &str) -> Option<&str> {
|
||||||
|
match name {
|
||||||
|
"true" => return Some("True"),
|
||||||
|
"false" => return Some("False"),
|
||||||
|
"Null" | "Nil" | "null" | "nil" | "none" => return Some("None"),
|
||||||
|
"del" => return Some("Del"),
|
||||||
|
"int" => return Some("Int"),
|
||||||
|
"nat" => return Some("Nat"),
|
||||||
|
"str" => return Some("Str"),
|
||||||
|
"bool" => return Some("Bool"),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
let name = readable_name(name);
|
let name = readable_name(name);
|
||||||
// TODO: add decls
|
// REVIEW: add decls?
|
||||||
get_similar_name(
|
get_similar_name(
|
||||||
self.params
|
self.params
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -1298,35 +1334,6 @@ impl Context {
|
||||||
concatenated
|
concatenated
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn _get_nominal_super_trait_ctxs<'a>(
|
|
||||||
&'a self,
|
|
||||||
t: &Type,
|
|
||||||
) -> Option<impl Iterator<Item = &'a Context>> {
|
|
||||||
let ctx = self.get_nominal_type_ctx(t)?;
|
|
||||||
Some(ctx.super_traits.iter().map(|sup| {
|
|
||||||
let sup_ctx = self
|
|
||||||
.get_nominal_type_ctx(sup)
|
|
||||||
.unwrap_or_else(|| todo!("{} not found", sup));
|
|
||||||
sup_ctx
|
|
||||||
}))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn _get_nominal_super_class_ctxs<'a>(
|
|
||||||
&'a self,
|
|
||||||
t: &Type,
|
|
||||||
) -> Option<impl Iterator<Item = &'a Context>> {
|
|
||||||
// if `t` is {S: Str | ...}, `ctx_t` will be Str
|
|
||||||
// else if `t` is Array(Int, 10), `ctx_t` will be Array(T, N) (if Array(Int, 10) is not specialized)
|
|
||||||
let ctx = self.get_nominal_type_ctx(t)?;
|
|
||||||
// t: {S: Str | ...} => ctx.super_traits: [Eq(Str), Mul(Nat), ...]
|
|
||||||
// => return: [(Str, Eq(Str)), (Str, Mul(Nat)), ...] (the content of &'a Type isn't {S: Str | ...})
|
|
||||||
Some(
|
|
||||||
ctx.super_classes
|
|
||||||
.iter()
|
|
||||||
.map(|sup| self.get_nominal_type_ctx(sup).unwrap()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn get_nominal_super_type_ctxs<'a>(&'a self, t: &Type) -> Option<Vec<&'a Context>> {
|
pub(crate) fn get_nominal_super_type_ctxs<'a>(&'a self, t: &Type) -> Option<Vec<&'a Context>> {
|
||||||
match t {
|
match t {
|
||||||
Type::FreeVar(fv) if fv.is_linked() => self.get_nominal_super_type_ctxs(&fv.crack()),
|
Type::FreeVar(fv) if fv.is_linked() => self.get_nominal_super_type_ctxs(&fv.crack()),
|
||||||
|
@ -1364,6 +1371,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// include `t` itself
|
||||||
fn get_simple_nominal_super_type_ctxs<'a>(
|
fn get_simple_nominal_super_type_ctxs<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
t: &Type,
|
t: &Type,
|
||||||
|
@ -1377,6 +1385,19 @@ impl Context {
|
||||||
Some(vec![ctx].into_iter().chain(sups))
|
Some(vec![ctx].into_iter().chain(sups))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// if `typ` is a refinement type, include the base type (refine.t)
|
||||||
|
pub(crate) fn get_super_classes(&self, typ: &Type) -> Option<impl Iterator<Item = Type>> {
|
||||||
|
self.get_nominal_type_ctx(typ).map(|ctx| {
|
||||||
|
let super_classes = ctx.super_classes.clone();
|
||||||
|
let derefined = typ.derefine();
|
||||||
|
if typ != &derefined {
|
||||||
|
vec![derefined].into_iter().chain(super_classes)
|
||||||
|
} else {
|
||||||
|
vec![].into_iter().chain(super_classes)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Never
|
// TODO: Never
|
||||||
pub(crate) fn get_nominal_type_ctx<'a>(&'a self, typ: &Type) -> Option<&'a Context> {
|
pub(crate) fn get_nominal_type_ctx<'a>(&'a self, typ: &Type) -> Option<&'a Context> {
|
||||||
match typ {
|
match typ {
|
||||||
|
@ -1433,7 +1454,7 @@ impl Context {
|
||||||
}
|
}
|
||||||
Type::Poly { path, name, .. } => {
|
Type::Poly { path, name, .. } => {
|
||||||
if self.path() == path {
|
if self.path() == path {
|
||||||
if let Some((_, ctx)) = self.rec_get_mono_type(name) {
|
if let Some((_, ctx)) = self.rec_get_poly_type(name) {
|
||||||
return Some(ctx);
|
return Some(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1448,7 +1469,7 @@ impl Context {
|
||||||
.and_then(|cache| cache.ref_ctx(path.as_path()))
|
.and_then(|cache| cache.ref_ctx(path.as_path()))
|
||||||
})
|
})
|
||||||
{
|
{
|
||||||
if let Some((_, ctx)) = ctx.rec_get_mono_type(name) {
|
if let Some((_, ctx)) = ctx.rec_get_poly_type(name) {
|
||||||
return Some(ctx);
|
return Some(ctx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1495,16 +1516,10 @@ impl Context {
|
||||||
return Some(res);
|
return Some(res);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Or(l, r) => {
|
Type::Or(_l, _r) => {
|
||||||
let lctx = self.get_nominal_type_ctx(l)?;
|
if let Some(ctx) = self.get_nominal_type_ctx(&builtin_poly("Or", vec![])) {
|
||||||
let rctx = self.get_nominal_type_ctx(r)?;
|
return Some(ctx);
|
||||||
// use smaller context
|
}
|
||||||
return match (self.supertype_of(l, r), self.supertype_of(r, l)) {
|
|
||||||
(true, true) => Some(lctx),
|
|
||||||
(true, false) => Some(rctx),
|
|
||||||
(false, true) => Some(lctx),
|
|
||||||
(false, false) => None,
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
// FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる
|
// FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる
|
||||||
other if other.is_monomorphic() => {
|
other if other.is_monomorphic() => {
|
||||||
|
|
|
@ -26,7 +26,6 @@ use erg_type::{HasType, ParamTy, Predicate, SubrKind, TyBound, Type};
|
||||||
use TyParamOrdering::*;
|
use TyParamOrdering::*;
|
||||||
use Type::*;
|
use Type::*;
|
||||||
|
|
||||||
use crate::context::eval::eval_lit;
|
|
||||||
use crate::context::{Context, RegistrationMode};
|
use crate::context::{Context, RegistrationMode};
|
||||||
use crate::error::{SingleTyCheckResult, TyCheckError, TyCheckErrors, TyCheckResult};
|
use crate::error::{SingleTyCheckResult, TyCheckError, TyCheckErrors, TyCheckResult};
|
||||||
use crate::hir;
|
use crate::hir;
|
||||||
|
@ -577,7 +576,7 @@ impl Context {
|
||||||
self.instantiate_typespec(&spec_with_op.t_spec, opt_decl_t, tmp_tv_ctx, mode)?
|
self.instantiate_typespec(&spec_with_op.t_spec, opt_decl_t, tmp_tv_ctx, mode)?
|
||||||
} else {
|
} else {
|
||||||
match &sig.pat {
|
match &sig.pat {
|
||||||
ast::ParamPattern::Lit(lit) => v_enum(set![eval_lit(lit)]),
|
ast::ParamPattern::Lit(lit) => v_enum(set![self.eval_lit(lit)?]),
|
||||||
// TODO: Array<Lit>
|
// TODO: Array<Lit>
|
||||||
_ => {
|
_ => {
|
||||||
let level = if mode == PreRegister {
|
let level = if mode == PreRegister {
|
||||||
|
@ -613,7 +612,7 @@ impl Context {
|
||||||
let t = self.instantiate_param_sig_t(sig, opt_decl_t, tmp_tv_ctx, mode)?;
|
let t = self.instantiate_param_sig_t(sig, opt_decl_t, tmp_tv_ctx, mode)?;
|
||||||
match (sig.inspect(), &sig.opt_default_val) {
|
match (sig.inspect(), &sig.opt_default_val) {
|
||||||
(Some(name), Some(default)) => {
|
(Some(name), Some(default)) => {
|
||||||
let default = self.instantiate_const_expr(default);
|
let default = self.instantiate_const_expr(default)?;
|
||||||
Ok(ParamTy::kw_default(
|
Ok(ParamTy::kw_default(
|
||||||
name.clone(),
|
name.clone(),
|
||||||
t,
|
t,
|
||||||
|
@ -665,7 +664,7 @@ impl Context {
|
||||||
if let Some(first) = args.next() {
|
if let Some(first) = args.next() {
|
||||||
let t = self.instantiate_const_expr_as_type(&first.expr)?;
|
let t = self.instantiate_const_expr_as_type(&first.expr)?;
|
||||||
let len = args.next().unwrap();
|
let len = args.next().unwrap();
|
||||||
let len = self.instantiate_const_expr(&len.expr);
|
let len = self.instantiate_const_expr(&len.expr)?;
|
||||||
Ok(array(t, len))
|
Ok(array(t, len))
|
||||||
} else {
|
} else {
|
||||||
Ok(builtin_mono("GenericArray"))
|
Ok(builtin_mono("GenericArray"))
|
||||||
|
@ -707,23 +706,28 @@ impl Context {
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
// FIXME: kw args
|
// FIXME: kw args
|
||||||
let params = simple.args.pos_args().map(|arg| match &arg.expr {
|
let mut new_params = vec![];
|
||||||
ast::ConstExpr::Lit(lit) => TyParam::Value(eval_lit(lit)),
|
for arg in simple.args.pos_args() {
|
||||||
_ => {
|
match &arg.expr {
|
||||||
todo!()
|
ast::ConstExpr::Lit(lit) => {
|
||||||
|
new_params.push(TyParam::Value(self.eval_lit(lit)?));
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
// FIXME: non-builtin
|
// FIXME: non-builtin
|
||||||
Ok(builtin_poly(Str::rc(other), params.collect()))
|
Ok(builtin_poly(Str::rc(other), new_params))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn instantiate_const_expr(&self, expr: &ast::ConstExpr) -> TyParam {
|
pub(crate) fn instantiate_const_expr(&self, expr: &ast::ConstExpr) -> TyCheckResult<TyParam> {
|
||||||
match expr {
|
match expr {
|
||||||
ast::ConstExpr::Lit(lit) => TyParam::Value(eval_lit(lit)),
|
ast::ConstExpr::Lit(lit) => Ok(TyParam::Value(self.eval_lit(lit)?)),
|
||||||
ast::ConstExpr::Accessor(ast::ConstAccessor::Local(name)) => {
|
ast::ConstExpr::Accessor(ast::ConstAccessor::Local(name)) => {
|
||||||
TyParam::Mono(name.inspect().clone())
|
Ok(TyParam::Mono(name.inspect().clone()))
|
||||||
}
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
}
|
}
|
||||||
|
@ -780,13 +784,13 @@ impl Context {
|
||||||
)),
|
)),
|
||||||
TypeSpec::Array(arr) => {
|
TypeSpec::Array(arr) => {
|
||||||
let elem_t = self.instantiate_typespec(&arr.ty, opt_decl_t, tmp_tv_ctx, mode)?;
|
let elem_t = self.instantiate_typespec(&arr.ty, opt_decl_t, tmp_tv_ctx, mode)?;
|
||||||
let len = self.instantiate_const_expr(&arr.len);
|
let len = self.instantiate_const_expr(&arr.len)?;
|
||||||
Ok(array(elem_t, len))
|
Ok(builtin_poly("ArrayType", vec![ty_tp(elem_t), len]))
|
||||||
}
|
}
|
||||||
TypeSpec::Set(set) => {
|
TypeSpec::Set(set) => {
|
||||||
let elem_t = self.instantiate_typespec(&set.ty, opt_decl_t, tmp_tv_ctx, mode)?;
|
let elem_t = self.instantiate_typespec(&set.ty, opt_decl_t, tmp_tv_ctx, mode)?;
|
||||||
let len = self.instantiate_const_expr(&set.len);
|
let len = self.instantiate_const_expr(&set.len)?;
|
||||||
Ok(erg_type::constructors::set(elem_t, len))
|
Ok(builtin_poly("SetType", vec![ty_tp(elem_t), len]))
|
||||||
}
|
}
|
||||||
// FIXME: unwrap
|
// FIXME: unwrap
|
||||||
TypeSpec::Tuple(tys) => Ok(tuple(
|
TypeSpec::Tuple(tys) => Ok(tuple(
|
||||||
|
@ -797,18 +801,18 @@ impl Context {
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
)),
|
)),
|
||||||
// TODO: エラー処理(リテラルでない、ダブりがある)はパーサーにやらせる
|
// TODO: エラー処理(リテラルでない)はパーサーにやらせる
|
||||||
TypeSpec::Enum(set) => Ok(v_enum(
|
TypeSpec::Enum(set) => {
|
||||||
set.pos_args()
|
let mut new_set = set! {};
|
||||||
.map(|arg| {
|
for arg in set.pos_args() {
|
||||||
if let ast::ConstExpr::Lit(lit) = &arg.expr {
|
if let ast::ConstExpr::Lit(lit) = &arg.expr {
|
||||||
eval_lit(lit)
|
new_set.insert(self.eval_lit(lit)?);
|
||||||
} else {
|
} else {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
.collect::<Set<_>>(),
|
Ok(v_enum(new_set))
|
||||||
)),
|
}
|
||||||
TypeSpec::Interval { op, lhs, rhs } => {
|
TypeSpec::Interval { op, lhs, rhs } => {
|
||||||
let op = match op.kind {
|
let op = match op.kind {
|
||||||
TokenKind::Closed => IntervalOp::Closed,
|
TokenKind::Closed => IntervalOp::Closed,
|
||||||
|
@ -817,9 +821,9 @@ impl Context {
|
||||||
TokenKind::Open => IntervalOp::Open,
|
TokenKind::Open => IntervalOp::Open,
|
||||||
_ => assume_unreachable!(),
|
_ => assume_unreachable!(),
|
||||||
};
|
};
|
||||||
let l = self.instantiate_const_expr(lhs);
|
let l = self.instantiate_const_expr(lhs)?;
|
||||||
let l = self.eval_tp(&l)?;
|
let l = self.eval_tp(&l)?;
|
||||||
let r = self.instantiate_const_expr(rhs);
|
let r = self.instantiate_const_expr(rhs)?;
|
||||||
let r = self.eval_tp(&r)?;
|
let r = self.eval_tp(&r)?;
|
||||||
if let Some(Greater) = self.try_cmp(&l, &r) {
|
if let Some(Greater) = self.try_cmp(&l, &r) {
|
||||||
panic!("{l}..{r} is not a valid interval type (should be lhs <= rhs)")
|
panic!("{l}..{r} is not a valid interval type (should be lhs <= rhs)")
|
||||||
|
|
|
@ -281,6 +281,7 @@ pub enum OperationKind {
|
||||||
Import,
|
Import,
|
||||||
PyImport,
|
PyImport,
|
||||||
Del,
|
Del,
|
||||||
|
AssertCast,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl OperationKind {
|
impl OperationKind {
|
||||||
|
|
|
@ -14,8 +14,9 @@ use ast::{DefId, Identifier, VarName};
|
||||||
use erg_parser::ast;
|
use erg_parser::ast;
|
||||||
|
|
||||||
use erg_type::constructors::{func, func1, proc, ref_, ref_mut, v_enum};
|
use erg_type::constructors::{func, func1, proc, ref_, ref_mut, v_enum};
|
||||||
|
use erg_type::free::{Constraint, Cyclicity, FreeKind};
|
||||||
use erg_type::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
|
use erg_type::value::{GenTypeObj, TypeKind, TypeObj, ValueObj};
|
||||||
use erg_type::{ParamTy, SubrType, Type};
|
use erg_type::{HasType, ParamTy, SubrType, Type};
|
||||||
|
|
||||||
use crate::build_hir::HIRBuilder;
|
use crate::build_hir::HIRBuilder;
|
||||||
use crate::context::{
|
use crate::context::{
|
||||||
|
@ -1076,4 +1077,75 @@ impl Context {
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn cast(
|
||||||
|
&mut self,
|
||||||
|
type_spec: ast::TypeSpec,
|
||||||
|
call: &mut hir::Call,
|
||||||
|
) -> TyCheckResult<()> {
|
||||||
|
let cast_to =
|
||||||
|
self.instantiate_typespec(&type_spec, None, None, RegistrationMode::Normal)?;
|
||||||
|
let lhs = enum_unwrap!(
|
||||||
|
call.args.get_mut_left_or_key("pred").unwrap(),
|
||||||
|
hir::Expr::BinOp
|
||||||
|
)
|
||||||
|
.lhs
|
||||||
|
.as_mut();
|
||||||
|
match (
|
||||||
|
self.supertype_of(lhs.ref_t(), &cast_to),
|
||||||
|
self.subtype_of(lhs.ref_t(), &cast_to),
|
||||||
|
) {
|
||||||
|
// assert 1 in {1}
|
||||||
|
(true, true) => Ok(()),
|
||||||
|
// assert x in Int (x: Nat)
|
||||||
|
(false, true) => Ok(()), // TODO: warn (needless)
|
||||||
|
// assert x in Nat (x: Int)
|
||||||
|
(true, false) => {
|
||||||
|
if let hir::Expr::Accessor(ref acc) = lhs {
|
||||||
|
self.change_var_type(acc, cast_to.clone())?;
|
||||||
|
}
|
||||||
|
match lhs.ref_t() {
|
||||||
|
Type::FreeVar(fv) if fv.is_linked() => {
|
||||||
|
let constraint = Constraint::new_subtype_of(cast_to, Cyclicity::Not);
|
||||||
|
fv.replace(FreeKind::new_unbound(self.level, constraint));
|
||||||
|
}
|
||||||
|
Type::FreeVar(fv) => {
|
||||||
|
let new_constraint = Constraint::new_subtype_of(cast_to, Cyclicity::Not);
|
||||||
|
fv.update_constraint(new_constraint);
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
*lhs.ref_mut_t() = cast_to;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
// assert x in Str (x: Int)
|
||||||
|
(false, false) => Err(TyCheckErrors::from(TyCheckError::invalid_type_cast_error(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
lhs.loc(),
|
||||||
|
self.caused_by(),
|
||||||
|
&lhs.to_string(),
|
||||||
|
&cast_to,
|
||||||
|
None,
|
||||||
|
))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change_var_type(&mut self, acc: &hir::Accessor, t: Type) -> TyCheckResult<()> {
|
||||||
|
#[allow(clippy::single_match)]
|
||||||
|
match acc {
|
||||||
|
hir::Accessor::Ident(ident) => {
|
||||||
|
if let Some(vi) = self.get_mut_current_scope_var(ident.inspect()) {
|
||||||
|
vi.t = t;
|
||||||
|
} else {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// TODO: support other accessors
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -671,6 +671,13 @@ impl Context {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
hir::Array::WithLength(arr) => {
|
||||||
|
let loc = arr.loc();
|
||||||
|
arr.t = self.deref_tyvar(mem::take(&mut arr.t), Covariant, loc)?;
|
||||||
|
self.resolve_expr_t(&mut arr.elem)?;
|
||||||
|
self.resolve_expr_t(&mut arr.len)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
},
|
},
|
||||||
hir::Expr::Tuple(tuple) => match tuple {
|
hir::Expr::Tuple(tuple) => match tuple {
|
||||||
|
@ -683,12 +690,20 @@ impl Context {
|
||||||
},
|
},
|
||||||
hir::Expr::Set(set) => match set {
|
hir::Expr::Set(set) => match set {
|
||||||
hir::Set::Normal(st) => {
|
hir::Set::Normal(st) => {
|
||||||
|
let loc = st.loc();
|
||||||
|
st.t = self.deref_tyvar(mem::take(&mut st.t), Covariant, loc)?;
|
||||||
for elem in st.elems.pos_args.iter_mut() {
|
for elem in st.elems.pos_args.iter_mut() {
|
||||||
self.resolve_expr_t(&mut elem.expr)?;
|
self.resolve_expr_t(&mut elem.expr)?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
hir::Set::WithLength(_) => todo!(),
|
hir::Set::WithLength(st) => {
|
||||||
|
let loc = st.loc();
|
||||||
|
st.t = self.deref_tyvar(mem::take(&mut st.t), Covariant, loc)?;
|
||||||
|
self.resolve_expr_t(&mut st.elem)?;
|
||||||
|
self.resolve_expr_t(&mut st.len)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
},
|
},
|
||||||
hir::Expr::Dict(_dict) => {
|
hir::Expr::Dict(_dict) => {
|
||||||
todo!()
|
todo!()
|
||||||
|
|
|
@ -990,6 +990,30 @@ impl EvalError {
|
||||||
caused_by,
|
caused_by,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn invalid_literal(
|
||||||
|
input: Input,
|
||||||
|
errno: usize,
|
||||||
|
loc: Location,
|
||||||
|
caused_by: AtomicStr,
|
||||||
|
) -> Self {
|
||||||
|
Self::new(
|
||||||
|
ErrorCore::new(
|
||||||
|
errno,
|
||||||
|
SyntaxError,
|
||||||
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => "リテラルが不正です",
|
||||||
|
"simplified_chinese" => "字面量不合法",
|
||||||
|
"traditional_chinese" => "字面量不合法",
|
||||||
|
"english" => "invalid literal",
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
),
|
||||||
|
input,
|
||||||
|
caused_by,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type EffectError = TyCheckError;
|
pub type EffectError = TyCheckError;
|
||||||
|
@ -1568,6 +1592,34 @@ impl LowerError {
|
||||||
caused_by,
|
caused_by,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub fn invalid_type_cast_error(
|
||||||
|
input: Input,
|
||||||
|
errno: usize,
|
||||||
|
loc: Location,
|
||||||
|
caused_by: AtomicStr,
|
||||||
|
name: &str,
|
||||||
|
cast_to: &Type,
|
||||||
|
hint: Option<AtomicStr>,
|
||||||
|
) -> Self {
|
||||||
|
Self::new(
|
||||||
|
ErrorCore::new(
|
||||||
|
errno,
|
||||||
|
TypeError,
|
||||||
|
loc,
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("{YELLOW}{name}{RESET}の型を{RED}{cast_to}{RESET}にキャストすることはできません"),
|
||||||
|
"simplified_chinese" => format!("{YELLOW}{name}{RESET}的类型无法转换为{RED}{cast_to}{RESET}"),
|
||||||
|
"traditional_chinese" => format!("{YELLOW}{name}{RESET}的類型無法轉換為{RED}{cast_to}{RESET}"),
|
||||||
|
"english" => format!("the type of {YELLOW}{name}{RESET} cannot be cast to {RED}{cast_to}{RESET}"),
|
||||||
|
),
|
||||||
|
hint,
|
||||||
|
),
|
||||||
|
input,
|
||||||
|
caused_by,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
|
|
@ -47,14 +47,16 @@ impl Locational for Literal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Token> for Literal {
|
impl TryFrom<Token> for Literal {
|
||||||
fn from(token: Token) -> Self {
|
type Error = ();
|
||||||
let data = ValueObj::from_str(type_from_token_kind(token.kind), token.content.clone());
|
fn try_from(token: Token) -> Result<Self, ()> {
|
||||||
Self {
|
let data =
|
||||||
|
ValueObj::from_str(type_from_token_kind(token.kind), token.content.clone()).ok_or(())?;
|
||||||
|
Ok(Self {
|
||||||
t: data.t(),
|
t: data.t(),
|
||||||
value: data,
|
value: data,
|
||||||
token,
|
token,
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,6 +284,20 @@ impl Args {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_mut_left_or_key(&mut self, key: &str) -> Option<&mut Expr> {
|
||||||
|
if !self.pos_args.is_empty() {
|
||||||
|
Some(&mut self.pos_args.get_mut(0)?.expr)
|
||||||
|
} else if let Some(pos) = self
|
||||||
|
.kw_args
|
||||||
|
.iter()
|
||||||
|
.position(|arg| &arg.keyword.inspect()[..] == key)
|
||||||
|
{
|
||||||
|
Some(&mut self.kw_args.get_mut(pos)?.expr)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn insert_pos(&mut self, idx: usize, pos: PosArg) {
|
pub fn insert_pos(&mut self, idx: usize, pos: PosArg) {
|
||||||
self.pos_args.insert(idx, pos);
|
self.pos_args.insert(idx, pos);
|
||||||
}
|
}
|
||||||
|
@ -351,8 +367,8 @@ impl Identifier {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn private(name: Str) -> Self {
|
pub fn private(name: &'static str) -> Self {
|
||||||
Self::bare(None, VarName::from_str(name))
|
Self::bare(None, VarName::from_static(name))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn private_with_line(name: Str, line: usize) -> Self {
|
pub fn private_with_line(name: Str, line: usize) -> Self {
|
||||||
|
|
|
@ -59,6 +59,10 @@ impl<'a> Linker<'a> {
|
||||||
self.replace_import(&mut elem.expr);
|
self.replace_import(&mut elem.expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Array::WithLength(arr) => {
|
||||||
|
self.replace_import(&mut arr.elem);
|
||||||
|
self.replace_import(&mut arr.len);
|
||||||
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
},
|
},
|
||||||
Expr::Tuple(tuple) => match tuple {
|
Expr::Tuple(tuple) => match tuple {
|
||||||
|
@ -74,9 +78,11 @@ impl<'a> Linker<'a> {
|
||||||
self.replace_import(&mut elem.expr);
|
self.replace_import(&mut elem.expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Set::WithLength(_) => todo!(),
|
Set::WithLength(st) => {
|
||||||
|
self.replace_import(&mut st.elem);
|
||||||
|
self.replace_import(&mut st.len);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
Expr::Dict(_dict) => {
|
Expr::Dict(_dict) => {
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
@ -241,7 +247,7 @@ impl<'a> Linker<'a> {
|
||||||
mod_name_lit.ln_begin().unwrap(),
|
mod_name_lit.ln_begin().unwrap(),
|
||||||
mod_name_lit.col_begin().unwrap(),
|
mod_name_lit.col_begin().unwrap(),
|
||||||
);
|
);
|
||||||
let mod_name = Expr::Lit(Literal::from(token));
|
let mod_name = Expr::Lit(Literal::try_from(token).unwrap());
|
||||||
args.insert_pos(0, PosArg::new(mod_name));
|
args.insert_pos(0, PosArg::new(mod_name));
|
||||||
let line = expr.ln_begin().unwrap_or(0);
|
let line = expr.ln_begin().unwrap_or(0);
|
||||||
for attr in comps {
|
for attr in comps {
|
||||||
|
|
|
@ -15,6 +15,7 @@ use erg_parser::ast;
|
||||||
use erg_parser::ast::AST;
|
use erg_parser::ast::AST;
|
||||||
use erg_parser::build_ast::ASTBuilder;
|
use erg_parser::build_ast::ASTBuilder;
|
||||||
use erg_parser::token::{Token, TokenKind};
|
use erg_parser::token::{Token, TokenKind};
|
||||||
|
use erg_parser::Parser;
|
||||||
|
|
||||||
use erg_type::constructors::{
|
use erg_type::constructors::{
|
||||||
array, array_mut, builtin_mono, builtin_poly, free_var, func, mono, proc, quant, set, set_mut,
|
array, array_mut, builtin_mono, builtin_poly, free_var, func, mono, proc, quant, set, set_mut,
|
||||||
|
@ -182,6 +183,19 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn lower_literal(&self, lit: ast::Literal) -> LowerResult<hir::Literal> {
|
||||||
|
let loc = lit.loc();
|
||||||
|
let lit = hir::Literal::try_from(lit.token).map_err(|_| {
|
||||||
|
LowerError::invalid_literal(
|
||||||
|
self.cfg.input.clone(),
|
||||||
|
line!() as usize,
|
||||||
|
loc,
|
||||||
|
self.ctx.caused_by(),
|
||||||
|
)
|
||||||
|
})?;
|
||||||
|
Ok(lit)
|
||||||
|
}
|
||||||
|
|
||||||
fn lower_array(&mut self, array: ast::Array) -> LowerResult<hir::Array> {
|
fn lower_array(&mut self, array: ast::Array) -> LowerResult<hir::Array> {
|
||||||
log!(info "entered {}({array})", fn_name!());
|
log!(info "entered {}({array})", fn_name!());
|
||||||
match array {
|
match array {
|
||||||
|
@ -260,6 +274,8 @@ impl ASTLowerer {
|
||||||
"ArrayWithMutType!",
|
"ArrayWithMutType!",
|
||||||
vec![TyParam::t(elem.t()), TyParam::Value(v)],
|
vec![TyParam::t(elem.t()), TyParam::Value(v)],
|
||||||
)
|
)
|
||||||
|
} else if self.ctx.subtype_of(&elem.t(), &Type::Type) {
|
||||||
|
builtin_poly("ArrayType", vec![TyParam::t(elem.t()), TyParam::Value(v)])
|
||||||
} else {
|
} else {
|
||||||
array(elem.t(), TyParam::Value(v))
|
array(elem.t(), TyParam::Value(v))
|
||||||
}
|
}
|
||||||
|
@ -429,6 +445,8 @@ impl ASTLowerer {
|
||||||
"SetWithMutType!",
|
"SetWithMutType!",
|
||||||
vec![TyParam::t(elem.t()), TyParam::Value(v)],
|
vec![TyParam::t(elem.t()), TyParam::Value(v)],
|
||||||
)
|
)
|
||||||
|
} else if self.ctx.subtype_of(&elem.t(), &Type::Type) {
|
||||||
|
builtin_poly("SetType", vec![TyParam::t(elem.t()), TyParam::Value(v)])
|
||||||
} else {
|
} else {
|
||||||
set(elem.t(), TyParam::Value(v))
|
set(elem.t(), TyParam::Value(v))
|
||||||
}
|
}
|
||||||
|
@ -489,7 +507,7 @@ impl ASTLowerer {
|
||||||
}
|
}
|
||||||
ast::Accessor::TupleAttr(t_attr) => {
|
ast::Accessor::TupleAttr(t_attr) => {
|
||||||
let obj = self.lower_expr(*t_attr.obj)?;
|
let obj = self.lower_expr(*t_attr.obj)?;
|
||||||
let index = hir::Literal::from(t_attr.index.token);
|
let index = self.lower_literal(t_attr.index)?;
|
||||||
let n = enum_unwrap!(index.value, ValueObj::Nat);
|
let n = enum_unwrap!(index.value, ValueObj::Nat);
|
||||||
let t = enum_unwrap!(
|
let t = enum_unwrap!(
|
||||||
obj.ref_t().typarams().get(n as usize).unwrap().clone(),
|
obj.ref_t().typarams().get(n as usize).unwrap().clone(),
|
||||||
|
@ -562,9 +580,27 @@ impl ASTLowerer {
|
||||||
Ok(hir::UnaryOp::new(unary.op, expr, t))
|
Ok(hir::UnaryOp::new(unary.op, expr, t))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: single `import`
|
|
||||||
fn lower_call(&mut self, call: ast::Call) -> LowerResult<hir::Call> {
|
fn lower_call(&mut self, call: ast::Call) -> LowerResult<hir::Call> {
|
||||||
log!(info "entered {}({}{}(...))", fn_name!(), call.obj, fmt_option!(call.method_name));
|
log!(info "entered {}({}{}(...))", fn_name!(), call.obj, fmt_option!(call.method_name));
|
||||||
|
let opt_cast_to = if call.is_assert_cast() {
|
||||||
|
if let Some(typ) = call.assert_cast_target_type() {
|
||||||
|
Some(Parser::expr_to_type_spec(typ.clone()).map_err(|e| {
|
||||||
|
let e = LowerError::new(e.into(), self.input().clone(), self.ctx.caused_by());
|
||||||
|
LowerErrors::from(e)
|
||||||
|
})?)
|
||||||
|
} else {
|
||||||
|
return Err(LowerErrors::from(LowerError::syntax_error(
|
||||||
|
self.input().clone(),
|
||||||
|
line!() as usize,
|
||||||
|
call.args.loc(),
|
||||||
|
self.ctx.caused_by(),
|
||||||
|
"invalid assert casting type",
|
||||||
|
None,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
let (pos_args, kw_args, paren) = call.args.deconstruct();
|
let (pos_args, kw_args, paren) = call.args.deconstruct();
|
||||||
let mut hir_args = hir::Args::new(
|
let mut hir_args = hir::Args::new(
|
||||||
Vec::with_capacity(pos_args.len()),
|
Vec::with_capacity(pos_args.len()),
|
||||||
|
@ -597,7 +633,7 @@ impl ASTLowerer {
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let call = hir::Call::new(obj, method_name, hir_args, sig_t);
|
let mut call = hir::Call::new(obj, method_name, hir_args, sig_t);
|
||||||
match call.additional_operation() {
|
match call.additional_operation() {
|
||||||
Some(kind @ (OperationKind::Import | OperationKind::PyImport)) => {
|
Some(kind @ (OperationKind::Import | OperationKind::PyImport)) => {
|
||||||
let mod_name =
|
let mod_name =
|
||||||
|
@ -621,7 +657,12 @@ impl ASTLowerer {
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {}
|
_ => {
|
||||||
|
if let Some(type_spec) = opt_cast_to {
|
||||||
|
log!(err "cast({type_spec}): {call}");
|
||||||
|
self.ctx.cast(type_spec, &mut call)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(call)
|
Ok(call)
|
||||||
}
|
}
|
||||||
|
@ -1241,7 +1282,7 @@ impl ASTLowerer {
|
||||||
fn lower_expr(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
fn lower_expr(&mut self, expr: ast::Expr) -> LowerResult<hir::Expr> {
|
||||||
log!(info "entered {}", fn_name!());
|
log!(info "entered {}", fn_name!());
|
||||||
match expr {
|
match expr {
|
||||||
ast::Expr::Lit(lit) => Ok(hir::Expr::Lit(hir::Literal::from(lit.token))),
|
ast::Expr::Lit(lit) => Ok(hir::Expr::Lit(self.lower_literal(lit)?)),
|
||||||
ast::Expr::Array(arr) => Ok(hir::Expr::Array(self.lower_array(arr)?)),
|
ast::Expr::Array(arr) => Ok(hir::Expr::Array(self.lower_array(arr)?)),
|
||||||
ast::Expr::Tuple(tup) => Ok(hir::Expr::Tuple(self.lower_tuple(tup)?)),
|
ast::Expr::Tuple(tup) => Ok(hir::Expr::Tuple(self.lower_tuple(tup)?)),
|
||||||
ast::Expr::Record(rec) => Ok(hir::Expr::Record(self.lower_record(rec)?)),
|
ast::Expr::Record(rec) => Ok(hir::Expr::Record(self.lower_record(rec)?)),
|
||||||
|
|
|
@ -156,6 +156,10 @@ impl OwnershipChecker {
|
||||||
self.check_expr(&a.expr, ownership, false);
|
self.check_expr(&a.expr, ownership, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Array::WithLength(arr) => {
|
||||||
|
self.check_expr(&arr.elem, ownership, false);
|
||||||
|
self.check_expr(&arr.len, ownership, false);
|
||||||
|
}
|
||||||
_ => todo!(),
|
_ => todo!(),
|
||||||
},
|
},
|
||||||
Expr::Tuple(tuple) => match tuple {
|
Expr::Tuple(tuple) => match tuple {
|
||||||
|
@ -182,12 +186,15 @@ impl OwnershipChecker {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Expr::Set(set) => match set {
|
Expr::Set(set) => match set {
|
||||||
hir::Set::Normal(set) => {
|
hir::Set::Normal(st) => {
|
||||||
for a in set.elems.pos_args.iter() {
|
for a in st.elems.pos_args.iter() {
|
||||||
self.check_expr(&a.expr, ownership, false);
|
self.check_expr(&a.expr, ownership, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::Set::WithLength(_) => todo!(),
|
hir::Set::WithLength(st) => {
|
||||||
|
self.check_expr(&st.elem, ownership, false);
|
||||||
|
self.check_expr(&st.len, ownership, false);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// TODO: capturing
|
// TODO: capturing
|
||||||
Expr::Lambda(lambda) => {
|
Expr::Lambda(lambda) => {
|
||||||
|
|
107
compiler/erg_compiler/std/_erg_std_prelude.py
Normal file
107
compiler/erg_compiler/std/_erg_std_prelude.py
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
from collections.abc import Iterable, Sequence, Iterator, Container
|
||||||
|
|
||||||
|
def in_operator(x, y):
|
||||||
|
if type(y) == type:
|
||||||
|
if isinstance(x, y):
|
||||||
|
return True
|
||||||
|
# TODO: trait check
|
||||||
|
return False
|
||||||
|
elif (type(y) == list or type(y) == set) and type(y[0]) == type:
|
||||||
|
# FIXME:
|
||||||
|
type_check = in_operator(x[0], y[0])
|
||||||
|
len_check = len(x) == len(y)
|
||||||
|
return type_check and len_check
|
||||||
|
elif type(y) == dict and type(y[0]) == type:
|
||||||
|
NotImplemented
|
||||||
|
else:
|
||||||
|
return x in y
|
||||||
|
|
||||||
|
class Range:
|
||||||
|
def __init__(self, start, end):
|
||||||
|
self.start = start
|
||||||
|
self.end = end
|
||||||
|
def __contains__(self, item):
|
||||||
|
pass
|
||||||
|
def __getitem__(self, item):
|
||||||
|
pass
|
||||||
|
def __len__(self):
|
||||||
|
pass
|
||||||
|
def __iter__(self):
|
||||||
|
return RangeIterator(rng=self)
|
||||||
|
|
||||||
|
Sequence.register(Range)
|
||||||
|
Container.register(Range)
|
||||||
|
Iterable.register(Range)
|
||||||
|
|
||||||
|
# represents `start<..end`
|
||||||
|
class LeftOpenRange(Range):
|
||||||
|
def __contains__(self, item):
|
||||||
|
return self.start < item <= self.end
|
||||||
|
def __getitem__(self, item):
|
||||||
|
return NotImplemented
|
||||||
|
def __len__(self):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
# represents `start..<end`
|
||||||
|
class RightOpenRange(Range):
|
||||||
|
def __contains__(self, item):
|
||||||
|
return self.start <= item < self.end
|
||||||
|
def __getitem__(self, item):
|
||||||
|
return NotImplemented
|
||||||
|
def __len__(self):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
# represents `start<..<end`
|
||||||
|
class OpenRange(Range):
|
||||||
|
def __contains__(self, item):
|
||||||
|
return self.start < item < self.end
|
||||||
|
def __getitem__(self, item):
|
||||||
|
return NotImplemented
|
||||||
|
def __len__(self):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
# represents `start..end`
|
||||||
|
class ClosedRange(Range):
|
||||||
|
def __contains__(self, item):
|
||||||
|
return self.start <= item <= self.end
|
||||||
|
def __getitem__(self, item):
|
||||||
|
return NotImplemented
|
||||||
|
def __len__(self):
|
||||||
|
return NotImplemented
|
||||||
|
|
||||||
|
class RangeIterator:
|
||||||
|
def __init__(self, rng):
|
||||||
|
self.rng = rng
|
||||||
|
self.needle = self.rng.start
|
||||||
|
if type(self.rng.start) == int:
|
||||||
|
if not(self.needle in self.rng):
|
||||||
|
self.needle += 1
|
||||||
|
elif type(self.rng.start) == str:
|
||||||
|
if not(self.needle in self.rng):
|
||||||
|
self.needle = chr(ord(self.needle) + 1)
|
||||||
|
else:
|
||||||
|
if not(self.needle in self.rng):
|
||||||
|
self.needle = self.needle.incremented()
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __next__(self):
|
||||||
|
if type(self.rng.start) == int:
|
||||||
|
if self.needle in self.rng:
|
||||||
|
result = self.needle
|
||||||
|
self.needle += 1
|
||||||
|
return result
|
||||||
|
elif type(self.rng.start) == str:
|
||||||
|
if self.needle in self.rng:
|
||||||
|
result = self.needle
|
||||||
|
self.needle = chr(ord(self.needle) + 1)
|
||||||
|
return result
|
||||||
|
else:
|
||||||
|
if self.needle in self.rng:
|
||||||
|
result = self.needle
|
||||||
|
self.needle = self.needle.incremented()
|
||||||
|
return result
|
||||||
|
raise StopIteration
|
||||||
|
|
||||||
|
Iterator.register(RangeIterator)
|
|
@ -2,7 +2,8 @@ discard _x = None
|
||||||
|
|
||||||
discard 1
|
discard 1
|
||||||
|
|
||||||
cond c, then, else =
|
# if: |T, U|(Bool, T, U) -> T or U
|
||||||
|
cond|T: Type|(c: Bool, then: T, else: T): T =
|
||||||
if c:
|
if c:
|
||||||
do then
|
do then
|
||||||
do else
|
do else
|
|
@ -1,22 +1,22 @@
|
||||||
[package]
|
[package]
|
||||||
name = "erg_parser"
|
name = "erg_parser"
|
||||||
version = "0.5.7"
|
|
||||||
description = "The Erg parser"
|
description = "The Erg parser"
|
||||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
documentation = "http://docs.rs/erg_parser"
|
||||||
license = "MIT OR Apache-2.0"
|
version.workspace = true
|
||||||
edition = "2021"
|
authors.workspace = true
|
||||||
repository = "https://github.com/erg-lang/erg/tree/main/src/erg_compiler/erg_parser"
|
license.workspace = true
|
||||||
documentation = "https://docs.rs/erg_parser"
|
edition.workspace = true
|
||||||
homepage = "https://erg-lang.github.io/"
|
repository.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
debug = [ "erg_common/debug" ]
|
debug = ["erg_common/debug"]
|
||||||
japanese = [ "erg_common/japanese" ]
|
japanese = ["erg_common/japanese"]
|
||||||
simplified_chinese = [ "erg_common/simplified_chinese" ]
|
simplified_chinese = ["erg_common/simplified_chinese"]
|
||||||
traditional_chinese = [ "erg_common/traditional_chinese" ]
|
traditional_chinese = ["erg_common/traditional_chinese"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erg_common = { version = "0.5.7", path = "../erg_common" }
|
erg_common = { version = "0.5.9-nightly.0", path = "../erg_common" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
|
@ -11,7 +11,7 @@ use erg_common::{
|
||||||
fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct,
|
fmt_option, fmt_vec, impl_display_for_enum, impl_display_for_single_struct,
|
||||||
impl_display_from_nested, impl_displayable_stream_for_wrapper, impl_locational,
|
impl_display_from_nested, impl_displayable_stream_for_wrapper, impl_locational,
|
||||||
impl_locational_for_enum, impl_nested_display_for_chunk_enum, impl_nested_display_for_enum,
|
impl_locational_for_enum, impl_nested_display_for_chunk_enum, impl_nested_display_for_enum,
|
||||||
impl_stream, impl_stream_for_wrapper,
|
impl_stream, impl_stream_for_wrapper, option_enum_unwrap,
|
||||||
};
|
};
|
||||||
use erg_common::{fmt_vec_split_with, Str};
|
use erg_common::{fmt_vec_split_with, Str};
|
||||||
|
|
||||||
|
@ -960,6 +960,32 @@ impl Call {
|
||||||
args,
|
args,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_match(&self) -> bool {
|
||||||
|
self.obj
|
||||||
|
.get_name()
|
||||||
|
.map(|s| &s[..] == "match")
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_assert_cast(&self) -> bool {
|
||||||
|
self.obj
|
||||||
|
.get_name()
|
||||||
|
.map(|s| &s[..] == "assert")
|
||||||
|
.unwrap_or(false)
|
||||||
|
&& self
|
||||||
|
.args
|
||||||
|
.get_left_or_key("pred")
|
||||||
|
.map(|pred| pred.is_bin_in())
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assert_cast_target_type(&self) -> Option<&Expr> {
|
||||||
|
self.args
|
||||||
|
.get_left_or_key("pred")
|
||||||
|
.and_then(|pred| option_enum_unwrap!(pred, Expr::BinOp))
|
||||||
|
.map(|bin| bin.args[1].as_ref())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// e.g. `Data::{x = 1; y = 2}`
|
/// e.g. `Data::{x = 1; y = 2}`
|
||||||
|
@ -3132,7 +3158,11 @@ impl_locational_for_enum!(Expr; Lit, Accessor, Array, Tuple, Dict, Set, Record,
|
||||||
|
|
||||||
impl Expr {
|
impl Expr {
|
||||||
pub fn is_match_call(&self) -> bool {
|
pub fn is_match_call(&self) -> bool {
|
||||||
matches!(self, Expr::Call(Call{ obj, .. }) if obj.get_name().map(|s| &s[..] == "match").unwrap_or(false))
|
matches!(self, Expr::Call(call) if call.is_match())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_bin_in(&self) -> bool {
|
||||||
|
matches!(self, Expr::BinOp(bin) if bin.op.is(TokenKind::InOp))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_const_acc(&self) -> bool {
|
pub fn is_const_acc(&self) -> bool {
|
||||||
|
|
|
@ -11,6 +11,18 @@ use erg_common::{impl_display_and_error, impl_stream_for_wrapper, switch_lang};
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LexError(ErrorCore);
|
pub struct LexError(ErrorCore);
|
||||||
|
|
||||||
|
impl From<ErrorCore> for LexError {
|
||||||
|
fn from(core: ErrorCore) -> Self {
|
||||||
|
Self(core)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<LexError> for ErrorCore {
|
||||||
|
fn from(err: LexError) -> Self {
|
||||||
|
err.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LexErrors(Vec<LexError>);
|
pub struct LexErrors(Vec<LexError>);
|
||||||
|
|
||||||
|
|
|
@ -461,15 +461,30 @@ impl Lexer /*<'a>*/ {
|
||||||
let mut num = mantissa;
|
let mut num = mantissa;
|
||||||
debug_power_assert!(self.peek_cur_ch(), ==, Some('e'));
|
debug_power_assert!(self.peek_cur_ch(), ==, Some('e'));
|
||||||
num.push(self.consume().unwrap()); // e
|
num.push(self.consume().unwrap()); // e
|
||||||
num.push(self.consume().unwrap()); // + | -
|
if self.peek_cur_ch().is_some() {
|
||||||
while let Some(cur) = self.peek_cur_ch() {
|
num.push(self.consume().unwrap()); // + | -
|
||||||
if cur.is_ascii_digit() || cur == '_' {
|
while let Some(cur) = self.peek_cur_ch() {
|
||||||
num.push(self.consume().unwrap());
|
if cur.is_ascii_digit() || cur == '_' {
|
||||||
} else {
|
num.push(self.consume().unwrap());
|
||||||
break;
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Ok(self.emit_token(RatioLit, &num))
|
||||||
|
} else {
|
||||||
|
let token = self.emit_token(RatioLit, &num);
|
||||||
|
Err(LexError::syntax_error(
|
||||||
|
0,
|
||||||
|
token.loc(),
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => format!("`{}`は無効な十進数リテラルです", &token.content),
|
||||||
|
"simplified_chinese" => format!("`{}`是无效的十进制字词", &token.content),
|
||||||
|
"traditional_chinese" => format!("`{}`是無效的十進製文字", &token.content),
|
||||||
|
"english" => format!("`{}` is invalid decimal literal", &token.content),
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
Ok(self.emit_token(RatioLit, &num))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `_` will be removed at compiletime
|
/// `_` will be removed at compiletime
|
||||||
|
@ -851,6 +866,10 @@ impl Iterator for Lexer /*<'a>*/ {
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Some('-') => {
|
||||||
|
self.consume();
|
||||||
|
self.accept(Inclusion, "<-")
|
||||||
|
}
|
||||||
Some('=') => {
|
Some('=') => {
|
||||||
self.consume();
|
self.consume();
|
||||||
self.accept(LessEq, "<=")
|
self.accept(LessEq, "<=")
|
||||||
|
|
|
@ -471,7 +471,8 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(t) if t.is(LSqBr) => {
|
// x[...] (`x [...]` will interpreted as `x([...])`)
|
||||||
|
Some(t) if t.is(LSqBr) && acc.col_end().unwrap() == t.col_begin().unwrap() => {
|
||||||
self.skip();
|
self.skip();
|
||||||
let index = self
|
let index = self
|
||||||
.try_reduce_expr(false, false, false)
|
.try_reduce_expr(false, false, false)
|
||||||
|
@ -510,52 +511,6 @@ impl Parser {
|
||||||
Ok(acc)
|
Ok(acc)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_const_expr(&mut self, expr: Expr) -> ParseResult<ConstExpr> {
|
|
||||||
match expr {
|
|
||||||
Expr::Lit(l) => Ok(ConstExpr::Lit(l)),
|
|
||||||
Expr::Accessor(Accessor::Ident(local)) => {
|
|
||||||
let local = ConstLocal::new(local.name.into_token());
|
|
||||||
Ok(ConstExpr::Accessor(ConstAccessor::Local(local)))
|
|
||||||
}
|
|
||||||
Expr::Array(array) => match array {
|
|
||||||
Array::Normal(arr) => {
|
|
||||||
let (elems, _, _) = arr.elems.deconstruct();
|
|
||||||
let mut const_elems = vec![];
|
|
||||||
for elem in elems.into_iter() {
|
|
||||||
let const_expr = self.validate_const_expr(elem.expr)?;
|
|
||||||
const_elems.push(ConstPosArg::new(const_expr));
|
|
||||||
}
|
|
||||||
let elems = ConstArgs::new(const_elems, vec![], None);
|
|
||||||
let const_arr = ConstArray::new(arr.l_sqbr, arr.r_sqbr, elems, None);
|
|
||||||
Ok(ConstExpr::Array(const_arr))
|
|
||||||
}
|
|
||||||
other => {
|
|
||||||
self.errs.push(ParseError::feature_error(
|
|
||||||
line!() as usize,
|
|
||||||
other.loc(),
|
|
||||||
"???",
|
|
||||||
));
|
|
||||||
Err(())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// TODO: App, Record, BinOp, UnaryOp,
|
|
||||||
other => {
|
|
||||||
self.errs.push(ParseError::syntax_error(
|
|
||||||
0,
|
|
||||||
other.loc(),
|
|
||||||
switch_lang!(
|
|
||||||
"japanese" => "この式はコンパイル時計算できないため、型引数には使用できません",
|
|
||||||
"simplified_chinese" => "此表达式在编译时不可计算,因此不能用作类型参数",
|
|
||||||
"traditional_chinese" => "此表達式在編譯時不可計算,因此不能用作類型參數",
|
|
||||||
"english" => "this expression is not computable at the compile-time, so cannot used as a type-argument",
|
|
||||||
),
|
|
||||||
None,
|
|
||||||
));
|
|
||||||
Err(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// For parsing elements of arrays and tuples
|
/// For parsing elements of arrays and tuples
|
||||||
fn try_reduce_elems(&mut self) -> ParseResult<ArrayInner> {
|
fn try_reduce_elems(&mut self) -> ParseResult<ArrayInner> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
|
@ -950,9 +905,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let defs = RecordAttrs::from(defs);
|
let defs = RecordAttrs::from(defs);
|
||||||
let class = self
|
let class = Self::expr_to_type_spec(class).map_err(|e| self.errs.push(e))?;
|
||||||
.convert_rhs_to_type_spec(class)
|
|
||||||
.map_err(|_| self.stack_dec())?;
|
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(Methods::new(class, vis, defs))
|
Ok(Methods::new(class, vis, defs))
|
||||||
}
|
}
|
||||||
|
@ -1036,9 +989,7 @@ impl Parser {
|
||||||
let t_spec = self
|
let t_spec = self
|
||||||
.try_reduce_expr(false, false, false)
|
.try_reduce_expr(false, false, false)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let t_spec = self
|
let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?;
|
||||||
.convert_rhs_to_type_spec(t_spec)
|
|
||||||
.map_err(|_| self.stack_dec())?;
|
|
||||||
let expr = Expr::TypeAsc(TypeAscription::new(lhs, op, t_spec));
|
let expr = Expr::TypeAsc(TypeAscription::new(lhs, op, t_spec));
|
||||||
stack.push(ExprOrOp::Expr(expr));
|
stack.push(ExprOrOp::Expr(expr));
|
||||||
}
|
}
|
||||||
|
@ -1280,9 +1231,7 @@ impl Parser {
|
||||||
let t_spec = self
|
let t_spec = self
|
||||||
.try_reduce_expr(false, in_type_args, in_brace)
|
.try_reduce_expr(false, in_type_args, in_brace)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
let t_spec = self
|
let t_spec = Self::expr_to_type_spec(t_spec).map_err(|e| self.errs.push(e))?;
|
||||||
.convert_rhs_to_type_spec(t_spec)
|
|
||||||
.map_err(|_| self.stack_dec())?;
|
|
||||||
let expr = Expr::TypeAsc(TypeAscription::new(lhs, op, t_spec));
|
let expr = Expr::TypeAsc(TypeAscription::new(lhs, op, t_spec));
|
||||||
stack.push(ExprOrOp::Expr(expr));
|
stack.push(ExprOrOp::Expr(expr));
|
||||||
}
|
}
|
||||||
|
@ -2173,9 +2122,7 @@ impl Parser {
|
||||||
pack: DataPack,
|
pack: DataPack,
|
||||||
) -> ParseResult<VarDataPackPattern> {
|
) -> ParseResult<VarDataPackPattern> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
let class = self
|
let class = Self::expr_to_type_spec(*pack.class).map_err(|e| self.errs.push(e))?;
|
||||||
.convert_rhs_to_type_spec(*pack.class)
|
|
||||||
.map_err(|_| self.stack_dec())?;
|
|
||||||
let args = self
|
let args = self
|
||||||
.convert_record_to_record_pat(pack.args)
|
.convert_record_to_record_pat(pack.args)
|
||||||
.map_err(|_| self.stack_dec())?;
|
.map_err(|_| self.stack_dec())?;
|
||||||
|
@ -2463,7 +2410,7 @@ impl Parser {
|
||||||
fn convert_kw_arg_to_default_param(&mut self, arg: KwArg) -> ParseResult<ParamSignature> {
|
fn convert_kw_arg_to_default_param(&mut self, arg: KwArg) -> ParseResult<ParamSignature> {
|
||||||
debug_call_info!(self);
|
debug_call_info!(self);
|
||||||
let pat = ParamPattern::VarName(VarName::new(arg.keyword));
|
let pat = ParamPattern::VarName(VarName::new(arg.keyword));
|
||||||
let expr = self.validate_const_expr(arg.expr)?;
|
let expr = Self::validate_const_expr(arg.expr).map_err(|e| self.errs.push(e))?;
|
||||||
let param = ParamSignature::new(pat, arg.t_spec, Some(expr));
|
let param = ParamSignature::new(pat, arg.t_spec, Some(expr));
|
||||||
self.level -= 1;
|
self.level -= 1;
|
||||||
Ok(param)
|
Ok(param)
|
||||||
|
@ -2672,95 +2619,51 @@ impl Parser {
|
||||||
TypeBoundSpecs::empty(),
|
TypeBoundSpecs::empty(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn convert_rhs_to_type_spec(&mut self, rhs: Expr) -> ParseResult<TypeSpec> {
|
// The APIs defined below are also used by `ASTLowerer` to interpret expressions as types.
|
||||||
debug_call_info!(self);
|
impl Parser {
|
||||||
match rhs {
|
fn validate_const_expr(expr: Expr) -> Result<ConstExpr, ParseError> {
|
||||||
Expr::Accessor(acc) => {
|
match expr {
|
||||||
let t_spec = self
|
Expr::Lit(l) => Ok(ConstExpr::Lit(l)),
|
||||||
.convert_accessor_to_type_spec(acc)
|
Expr::Accessor(Accessor::Ident(local)) => {
|
||||||
.map_err(|_| self.stack_dec())?;
|
let local = ConstLocal::new(local.name.into_token());
|
||||||
self.level -= 1;
|
Ok(ConstExpr::Accessor(ConstAccessor::Local(local)))
|
||||||
Ok(t_spec)
|
|
||||||
}
|
}
|
||||||
Expr::Call(call) => {
|
Expr::Array(array) => match array {
|
||||||
let predecl = self
|
Array::Normal(arr) => {
|
||||||
.convert_call_to_predecl_type_spec(call)
|
let (elems, _, _) = arr.elems.deconstruct();
|
||||||
.map_err(|_| self.stack_dec())?;
|
let mut const_elems = vec![];
|
||||||
self.level -= 1;
|
for elem in elems.into_iter() {
|
||||||
Ok(TypeSpec::PreDeclTy(predecl))
|
let const_expr = Self::validate_const_expr(elem.expr)?;
|
||||||
}
|
const_elems.push(ConstPosArg::new(const_expr));
|
||||||
Expr::Lambda(lambda) => {
|
}
|
||||||
let lambda = self
|
let elems = ConstArgs::new(const_elems, vec![], None);
|
||||||
.convert_lambda_to_subr_type_spec(lambda)
|
let const_arr = ConstArray::new(arr.l_sqbr, arr.r_sqbr, elems, None);
|
||||||
.map_err(|_| self.stack_dec())?;
|
Ok(ConstExpr::Array(const_arr))
|
||||||
self.level -= 1;
|
|
||||||
Ok(TypeSpec::Subr(lambda))
|
|
||||||
}
|
|
||||||
Expr::Array(array) => {
|
|
||||||
let array = self
|
|
||||||
.convert_array_to_array_type_spec(array)
|
|
||||||
.map_err(|_| self.stack_dec())?;
|
|
||||||
self.level -= 1;
|
|
||||||
Ok(TypeSpec::Array(array))
|
|
||||||
}
|
|
||||||
Expr::Set(set) => {
|
|
||||||
let set = self
|
|
||||||
.convert_set_to_set_type_spec(set)
|
|
||||||
.map_err(|_| self.stack_dec())?;
|
|
||||||
self.level -= 1;
|
|
||||||
Ok(TypeSpec::Set(set))
|
|
||||||
}
|
|
||||||
Expr::BinOp(bin) => {
|
|
||||||
if bin.op.kind.is_range_op() {
|
|
||||||
let op = bin.op;
|
|
||||||
let mut args = bin.args.into_iter();
|
|
||||||
let lhs = self
|
|
||||||
.validate_const_expr(*args.next().unwrap())
|
|
||||||
.map_err(|_| self.stack_dec())?;
|
|
||||||
let rhs = self
|
|
||||||
.validate_const_expr(*args.next().unwrap())
|
|
||||||
.map_err(|_| self.stack_dec())?;
|
|
||||||
self.level -= 1;
|
|
||||||
Ok(TypeSpec::Interval { op, lhs, rhs })
|
|
||||||
} else if bin.op.kind == TokenKind::AndOp {
|
|
||||||
let mut args = bin.args.into_iter();
|
|
||||||
let lhs = self
|
|
||||||
.convert_rhs_to_type_spec(*args.next().unwrap())
|
|
||||||
.map_err(|_| self.stack_dec())?;
|
|
||||||
let rhs = self
|
|
||||||
.convert_rhs_to_type_spec(*args.next().unwrap())
|
|
||||||
.map_err(|_| self.stack_dec())?;
|
|
||||||
self.level -= 1;
|
|
||||||
Ok(TypeSpec::and(lhs, rhs))
|
|
||||||
} else if bin.op.kind == TokenKind::OrOp {
|
|
||||||
let mut args = bin.args.into_iter();
|
|
||||||
let lhs = self
|
|
||||||
.convert_rhs_to_type_spec(*args.next().unwrap())
|
|
||||||
.map_err(|_| self.stack_dec())?;
|
|
||||||
let rhs = self
|
|
||||||
.convert_rhs_to_type_spec(*args.next().unwrap())
|
|
||||||
.map_err(|_| self.stack_dec())?;
|
|
||||||
self.level -= 1;
|
|
||||||
Ok(TypeSpec::or(lhs, rhs))
|
|
||||||
} else {
|
|
||||||
self.level -= 1;
|
|
||||||
let err = ParseError::simple_syntax_error(line!() as usize, bin.loc());
|
|
||||||
self.errs.push(err);
|
|
||||||
Err(())
|
|
||||||
}
|
}
|
||||||
}
|
other => Err(ParseError::feature_error(
|
||||||
other => {
|
line!() as usize,
|
||||||
self.level -= 1;
|
other.loc(),
|
||||||
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
|
"???",
|
||||||
self.errs.push(err);
|
)),
|
||||||
Err(())
|
},
|
||||||
}
|
// TODO: App, Record, BinOp, UnaryOp,
|
||||||
|
other => Err(ParseError::syntax_error(
|
||||||
|
line!() as usize,
|
||||||
|
other.loc(),
|
||||||
|
switch_lang!(
|
||||||
|
"japanese" => "この式はコンパイル時計算できないため、型引数には使用できません",
|
||||||
|
"simplified_chinese" => "此表达式在编译时不可计算,因此不能用作类型参数",
|
||||||
|
"traditional_chinese" => "此表達式在編譯時不可計算,因此不能用作類型參數",
|
||||||
|
"english" => "this expression is not computable at the compile-time, so cannot used as a type-argument",
|
||||||
|
),
|
||||||
|
None,
|
||||||
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_accessor_to_type_spec(&mut self, accessor: Accessor) -> ParseResult<TypeSpec> {
|
fn accessor_to_type_spec(accessor: Accessor) -> Result<TypeSpec, ParseError> {
|
||||||
debug_call_info!(self);
|
|
||||||
let t_spec = match accessor {
|
let t_spec = match accessor {
|
||||||
Accessor::Ident(ident) => {
|
Accessor::Ident(ident) => {
|
||||||
let predecl =
|
let predecl =
|
||||||
|
@ -2768,32 +2671,22 @@ impl Parser {
|
||||||
TypeSpec::PreDeclTy(predecl)
|
TypeSpec::PreDeclTy(predecl)
|
||||||
}
|
}
|
||||||
Accessor::TypeApp(tapp) => {
|
Accessor::TypeApp(tapp) => {
|
||||||
let spec = self
|
let spec = Self::expr_to_type_spec(*tapp.obj)?;
|
||||||
.convert_rhs_to_type_spec(*tapp.obj)
|
|
||||||
.map_err(|_| self.stack_dec())?;
|
|
||||||
TypeSpec::type_app(spec, tapp.type_args)
|
TypeSpec::type_app(spec, tapp.type_args)
|
||||||
}
|
}
|
||||||
other => {
|
other => {
|
||||||
self.level -= 1;
|
|
||||||
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
|
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
|
||||||
self.errs.push(err);
|
return Err(err);
|
||||||
return Err(());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
self.level -= 1;
|
|
||||||
Ok(t_spec)
|
Ok(t_spec)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_call_to_predecl_type_spec(&mut self, _call: Call) -> ParseResult<PreDeclTypeSpec> {
|
fn call_to_predecl_type_spec(_call: Call) -> Result<PreDeclTypeSpec, ParseError> {
|
||||||
debug_call_info!(self);
|
|
||||||
todo!()
|
todo!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_lambda_to_subr_type_spec(
|
fn lambda_to_subr_type_spec(mut lambda: Lambda) -> Result<SubrTypeSpec, ParseError> {
|
||||||
&mut self,
|
|
||||||
mut lambda: Lambda,
|
|
||||||
) -> ParseResult<SubrTypeSpec> {
|
|
||||||
debug_call_info!(self);
|
|
||||||
let bounds = lambda.sig.bounds;
|
let bounds = lambda.sig.bounds;
|
||||||
let lparen = lambda.sig.params.parens.map(|(l, _)| l);
|
let lparen = lambda.sig.params.parens.map(|(l, _)| l);
|
||||||
let mut non_defaults = vec![];
|
let mut non_defaults = vec![];
|
||||||
|
@ -2838,8 +2731,7 @@ impl Parser {
|
||||||
};
|
};
|
||||||
defaults.push(param);
|
defaults.push(param);
|
||||||
}
|
}
|
||||||
let return_t = self.convert_rhs_to_type_spec(lambda.body.remove(0))?;
|
let return_t = Self::expr_to_type_spec(lambda.body.remove(0))?;
|
||||||
self.level -= 1;
|
|
||||||
Ok(SubrTypeSpec::new(
|
Ok(SubrTypeSpec::new(
|
||||||
bounds,
|
bounds,
|
||||||
lparen,
|
lparen,
|
||||||
|
@ -2851,45 +2743,86 @@ impl Parser {
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_array_to_array_type_spec(&mut self, array: Array) -> ParseResult<ArrayTypeSpec> {
|
fn array_to_array_type_spec(array: Array) -> Result<ArrayTypeSpec, ParseError> {
|
||||||
debug_call_info!(self);
|
|
||||||
match array {
|
match array {
|
||||||
Array::Normal(arr) => {
|
Array::Normal(arr) => {
|
||||||
// TODO: add hint
|
// TODO: add hint
|
||||||
self.errs
|
let err = ParseError::simple_syntax_error(line!() as usize, arr.loc());
|
||||||
.push(ParseError::simple_syntax_error(line!() as usize, arr.loc()));
|
Err(err)
|
||||||
Err(())
|
|
||||||
}
|
}
|
||||||
Array::WithLength(arr) => {
|
Array::WithLength(arr) => {
|
||||||
let t_spec = self.convert_rhs_to_type_spec(arr.elem.expr)?;
|
let t_spec = Self::expr_to_type_spec(arr.elem.expr)?;
|
||||||
let len = self.validate_const_expr(*arr.len)?;
|
let len = Self::validate_const_expr(*arr.len)?;
|
||||||
self.level -= 1;
|
|
||||||
Ok(ArrayTypeSpec::new(t_spec, len))
|
Ok(ArrayTypeSpec::new(t_spec, len))
|
||||||
}
|
}
|
||||||
Array::Comprehension(arr) => {
|
Array::Comprehension(arr) => {
|
||||||
// TODO: add hint
|
// TODO: add hint
|
||||||
self.errs
|
let err = ParseError::simple_syntax_error(line!() as usize, arr.loc());
|
||||||
.push(ParseError::simple_syntax_error(line!() as usize, arr.loc()));
|
Err(err)
|
||||||
Err(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_set_to_set_type_spec(&mut self, set: Set) -> ParseResult<SetTypeSpec> {
|
fn set_to_set_type_spec(set: Set) -> Result<SetTypeSpec, ParseError> {
|
||||||
debug_call_info!(self);
|
|
||||||
match set {
|
match set {
|
||||||
Set::Normal(arr) => {
|
Set::Normal(arr) => {
|
||||||
// TODO: add hint
|
// TODO: add hint
|
||||||
self.errs
|
let err = ParseError::simple_syntax_error(line!() as usize, arr.loc());
|
||||||
.push(ParseError::simple_syntax_error(line!() as usize, arr.loc()));
|
Err(err)
|
||||||
Err(())
|
|
||||||
}
|
}
|
||||||
Set::WithLength(set) => {
|
Set::WithLength(set) => {
|
||||||
let t_spec = self.convert_rhs_to_type_spec(set.elem.expr)?;
|
let t_spec = Self::expr_to_type_spec(set.elem.expr)?;
|
||||||
let len = self.validate_const_expr(*set.len)?;
|
let len = Self::validate_const_expr(*set.len)?;
|
||||||
self.level -= 1;
|
|
||||||
Ok(SetTypeSpec::new(t_spec, len))
|
Ok(SetTypeSpec::new(t_spec, len))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn expr_to_type_spec(rhs: Expr) -> Result<TypeSpec, ParseError> {
|
||||||
|
match rhs {
|
||||||
|
Expr::Accessor(acc) => Self::accessor_to_type_spec(acc),
|
||||||
|
Expr::Call(call) => {
|
||||||
|
let predecl = Self::call_to_predecl_type_spec(call)?;
|
||||||
|
Ok(TypeSpec::PreDeclTy(predecl))
|
||||||
|
}
|
||||||
|
Expr::Lambda(lambda) => {
|
||||||
|
let lambda = Self::lambda_to_subr_type_spec(lambda)?;
|
||||||
|
Ok(TypeSpec::Subr(lambda))
|
||||||
|
}
|
||||||
|
Expr::Array(array) => {
|
||||||
|
let array = Self::array_to_array_type_spec(array)?;
|
||||||
|
Ok(TypeSpec::Array(array))
|
||||||
|
}
|
||||||
|
Expr::Set(set) => {
|
||||||
|
let set = Self::set_to_set_type_spec(set)?;
|
||||||
|
Ok(TypeSpec::Set(set))
|
||||||
|
}
|
||||||
|
Expr::BinOp(bin) => {
|
||||||
|
if bin.op.kind.is_range_op() {
|
||||||
|
let op = bin.op;
|
||||||
|
let mut args = bin.args.into_iter();
|
||||||
|
let lhs = Self::validate_const_expr(*args.next().unwrap())?;
|
||||||
|
let rhs = Self::validate_const_expr(*args.next().unwrap())?;
|
||||||
|
Ok(TypeSpec::Interval { op, lhs, rhs })
|
||||||
|
} else if bin.op.kind == TokenKind::AndOp {
|
||||||
|
let mut args = bin.args.into_iter();
|
||||||
|
let lhs = Self::expr_to_type_spec(*args.next().unwrap())?;
|
||||||
|
let rhs = Self::expr_to_type_spec(*args.next().unwrap())?;
|
||||||
|
Ok(TypeSpec::and(lhs, rhs))
|
||||||
|
} else if bin.op.kind == TokenKind::OrOp {
|
||||||
|
let mut args = bin.args.into_iter();
|
||||||
|
let lhs = Self::expr_to_type_spec(*args.next().unwrap())?;
|
||||||
|
let rhs = Self::expr_to_type_spec(*args.next().unwrap())?;
|
||||||
|
Ok(TypeSpec::or(lhs, rhs))
|
||||||
|
} else {
|
||||||
|
let err = ParseError::simple_syntax_error(line!() as usize, bin.loc());
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
other => {
|
||||||
|
let err = ParseError::simple_syntax_error(line!() as usize, other.loc());
|
||||||
|
Err(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -109,6 +109,8 @@ pub enum TokenKind {
|
||||||
RefMutOp,
|
RefMutOp,
|
||||||
/// =
|
/// =
|
||||||
Equal,
|
Equal,
|
||||||
|
/// <-
|
||||||
|
Inclusion,
|
||||||
/// :=
|
/// :=
|
||||||
Walrus,
|
Walrus,
|
||||||
/// ->
|
/// ->
|
||||||
|
@ -214,9 +216,8 @@ impl TokenKind {
|
||||||
| InfLit => TokenCategory::Literal,
|
| InfLit => TokenCategory::Literal,
|
||||||
PrePlus | PreMinus | PreBitNot | Mutate | RefOp | RefMutOp => TokenCategory::UnaryOp,
|
PrePlus | PreMinus | PreBitNot | Mutate | RefOp | RefMutOp => TokenCategory::UnaryOp,
|
||||||
Try => TokenCategory::PostfixOp,
|
Try => TokenCategory::PostfixOp,
|
||||||
Comma | Colon | DblColon | SupertypeOf | SubtypeOf | Dot | Pipe | Walrus => {
|
Comma | Colon | DblColon | SupertypeOf | SubtypeOf | Dot | Pipe | Walrus
|
||||||
TokenCategory::SpecialBinOp
|
| Inclusion => TokenCategory::SpecialBinOp,
|
||||||
}
|
|
||||||
Equal => TokenCategory::DefOp,
|
Equal => TokenCategory::DefOp,
|
||||||
FuncArrow | ProcArrow => TokenCategory::LambdaOp,
|
FuncArrow | ProcArrow => TokenCategory::LambdaOp,
|
||||||
Semi | Newline => TokenCategory::Separator,
|
Semi | Newline => TokenCategory::Separator,
|
||||||
|
@ -246,14 +247,14 @@ impl TokenKind {
|
||||||
BitOr => 120, // ||
|
BitOr => 120, // ||
|
||||||
Closed | LeftOpen | RightOpen | Open => 100, // range operators
|
Closed | LeftOpen | RightOpen | Open => 100, // range operators
|
||||||
Less | Gre | LessEq | GreEq | DblEq | NotEq | InOp | NotInOp | IsOp | IsNotOp => 90, // < > <= >= == != in notin is isnot
|
Less | Gre | LessEq | GreEq | DblEq | NotEq | InOp | NotInOp | IsOp | IsNotOp => 90, // < > <= >= == != in notin is isnot
|
||||||
AndOp => 80, // and
|
AndOp => 80, // and
|
||||||
OrOp => 70, // or
|
OrOp => 70, // or
|
||||||
FuncArrow | ProcArrow => 60, // -> =>
|
FuncArrow | ProcArrow | Inclusion => 60, // -> => <-
|
||||||
Colon | SupertypeOf | SubtypeOf => 50, // : :> <:
|
Colon | SupertypeOf | SubtypeOf => 50, // : :> <:
|
||||||
Comma => 40, // ,
|
Comma => 40, // ,
|
||||||
Equal | Walrus => 20, // = :=
|
Equal | Walrus => 20, // = :=
|
||||||
Newline | Semi => 10, // \n ;
|
Newline | Semi => 10, // \n ;
|
||||||
LParen | LBrace | LSqBr | Indent => 0, // ( { [ Indent
|
LParen | LBrace | LSqBr | Indent => 0, // ( { [ Indent
|
||||||
_ => return None,
|
_ => return None,
|
||||||
};
|
};
|
||||||
Some(prec)
|
Some(prec)
|
||||||
|
|
|
@ -1,25 +1,25 @@
|
||||||
[package]
|
[package]
|
||||||
name = "erg_type"
|
name = "erg_type"
|
||||||
version = "0.5.7"
|
|
||||||
description = "APIs for Erg types"
|
description = "APIs for Erg types"
|
||||||
authors = ["erg-lang team <moderation.erglang@gmail.com>"]
|
documentation = "http://docs.rs/erg_type"
|
||||||
license = "MIT OR Apache-2.0"
|
version.workspace = true
|
||||||
edition = "2021"
|
authors.workspace = true
|
||||||
repository = "https://github.com/erg-lang/erg/tree/main/compiler/erg_type"
|
license.workspace = true
|
||||||
documentation = "https://docs.rs/erg_type"
|
edition.workspace = true
|
||||||
homepage = "https://erg-lang.github.io/"
|
repository.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
debug = [ "erg_common/debug" ]
|
debug = ["erg_common/debug"]
|
||||||
japanese = [ "erg_common/japanese" ]
|
japanese = ["erg_common/japanese"]
|
||||||
simplified_chinese = [ "erg_common/simplified_chinese" ]
|
simplified_chinese = ["erg_common/simplified_chinese"]
|
||||||
traditional_chinese = [ "erg_common/traditional_chinese" ]
|
traditional_chinese = ["erg_common/traditional_chinese"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
erg_common = { version = "0.5.7", path = "../erg_common" }
|
erg_common = { version = "0.5.9-nightly.0", path = "../erg_common" }
|
||||||
erg_parser = { version = "0.5.7", path = "../erg_parser" }
|
erg_parser = { version = "0.5.9-nightly.0", path = "../erg_parser" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
|
@ -330,7 +330,17 @@ pub fn callable(param_ts: Vec<Type>, return_t: Type) -> Type {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn builtin_mono<S: Into<Str>>(name: S) -> Type {
|
pub fn builtin_mono<S: Into<Str>>(name: S) -> Type {
|
||||||
Type::BuiltinMono(name.into())
|
let name = name.into();
|
||||||
|
if cfg!(feature = "debug") {
|
||||||
|
// do not use for: `Int`, `Nat`, ...
|
||||||
|
match &name[..] {
|
||||||
|
"Obj" | "Int" | "Nat" | "Ratio" | "Float" | "Bool" | "Str" | "NoneType" | "Code"
|
||||||
|
| "Frame" | "Error" | "Inf" | "NegInf" | "Type" | "ClassType" | "TraitType"
|
||||||
|
| "Patch" | "NotImplemented" | "Ellipsis" | "Never" => todo!("{name}"),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Type::BuiltinMono(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -325,6 +325,17 @@ impl<T> FreeKind<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn new_unbound(lev: Level, constraint: Constraint) -> Self {
|
||||||
|
UNBOUND_ID.with(|id| {
|
||||||
|
*id.borrow_mut() += 1;
|
||||||
|
Self::Unbound {
|
||||||
|
id: *id.borrow(),
|
||||||
|
lev,
|
||||||
|
constraint,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub const fn named_unbound(name: Str, lev: Level, constraint: Constraint) -> Self {
|
pub const fn named_unbound(name: Str, lev: Level, constraint: Constraint) -> Self {
|
||||||
Self::NamedUnbound {
|
Self::NamedUnbound {
|
||||||
name,
|
name,
|
||||||
|
@ -440,6 +451,14 @@ impl<T: Clone + HasLevel> Free<T> {
|
||||||
*self.borrow_mut() = FreeKind::Linked(to.clone());
|
*self.borrow_mut() = FreeKind::Linked(to.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn replace(&self, to: FreeKind<T>) {
|
||||||
|
// prevent linking to self
|
||||||
|
if self.is_linked() && addr_eq!(*self.borrow(), to) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*self.borrow_mut() = to;
|
||||||
|
}
|
||||||
|
|
||||||
/// NOTE: Do not use this except to rewrite circular references.
|
/// NOTE: Do not use this except to rewrite circular references.
|
||||||
/// No reference to any type variable may be left behind when rewriting.
|
/// No reference to any type variable may be left behind when rewriting.
|
||||||
/// However, `get_bound_types` is safe because it does not return references.
|
/// However, `get_bound_types` is safe because it does not return references.
|
||||||
|
|
|
@ -1284,15 +1284,9 @@ impl PartialEq for Type {
|
||||||
rhs: rrhs,
|
rhs: rrhs,
|
||||||
},
|
},
|
||||||
) => lhs == rlhs && rhs == rrhs,
|
) => lhs == rlhs && rhs == rrhs,
|
||||||
|
(Self::FreeVar(fv), other) if fv.is_linked() => &*fv.crack() == other,
|
||||||
|
(_self, Self::FreeVar(fv)) if fv.is_linked() => _self == &*fv.crack(),
|
||||||
(Self::FreeVar(l), Self::FreeVar(r)) => l == r,
|
(Self::FreeVar(l), Self::FreeVar(r)) => l == r,
|
||||||
(Self::FreeVar(fv), other) => match &*fv.borrow() {
|
|
||||||
FreeKind::Linked(t) => t == other,
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
(self_, Self::FreeVar(fv)) => match &*fv.borrow() {
|
|
||||||
FreeKind::Linked(t) => t == self_,
|
|
||||||
_ => false,
|
|
||||||
},
|
|
||||||
(Self::Failure, Self::Failure) | (Self::Uninited, Self::Uninited) => true,
|
(Self::Failure, Self::Failure) | (Self::Uninited, Self::Uninited) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -1922,11 +1916,6 @@ impl Type {
|
||||||
matches!(self, Self::FreeVar(_))
|
matches!(self, Self::FreeVar(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// FIXME: `Int or Str` should be monomorphic
|
|
||||||
pub fn is_monomorphic(&self) -> bool {
|
|
||||||
matches!(self.typarams_len(), Some(0) | None)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const fn is_callable(&self) -> bool {
|
pub const fn is_callable(&self) -> bool {
|
||||||
matches!(self, Self::Subr { .. } | Self::Callable { .. })
|
matches!(self, Self::Subr { .. } | Self::Callable { .. })
|
||||||
}
|
}
|
||||||
|
@ -1935,6 +1924,18 @@ impl Type {
|
||||||
matches!(self, Self::FreeVar(fv) if fv.is_unbound() || fv.crack().is_unbound_var())
|
matches!(self, Self::FreeVar(fv) if fv.is_unbound() || fv.crack().is_unbound_var())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See also: `is_monomorphized`
|
||||||
|
pub fn is_monomorphic(&self) -> bool {
|
||||||
|
matches!(self.typarams_len(), Some(0) | None)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `Set(Int, 3)` is not monomorphic but monomorphized
|
||||||
|
pub fn is_monomorphized(&self) -> bool {
|
||||||
|
matches!(self.typarams_len(), Some(0) | None)
|
||||||
|
|| (self.has_no_qvar() && self.has_no_unbound_var())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// if the type is polymorphic
|
||||||
pub fn has_qvar(&self) -> bool {
|
pub fn has_qvar(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::MonoQVar(_) | Self::PolyQVar { .. } => true,
|
Self::MonoQVar(_) | Self::PolyQVar { .. } => true,
|
||||||
|
@ -1972,6 +1973,10 @@ impl Type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn has_no_qvar(&self) -> bool {
|
||||||
|
!self.has_qvar()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_cachable(&self) -> bool {
|
pub fn is_cachable(&self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
Self::FreeVar(_) => false,
|
Self::FreeVar(_) => false,
|
||||||
|
|
|
@ -406,27 +406,35 @@ impl ValueObj {
|
||||||
matches!(self, Self::Mut(_))
|
matches!(self, Self::Mut(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_str(t: Type, content: Str) -> Self {
|
pub fn from_str(t: Type, content: Str) -> Option<Self> {
|
||||||
match t {
|
match t {
|
||||||
Type::Int => Self::Int(content.replace('_', "").parse::<i32>().unwrap()),
|
Type::Int => content.replace('_', "").parse::<i32>().ok().map(Self::Int),
|
||||||
Type::Nat => Self::Nat(content.replace('_', "").parse::<u64>().unwrap()),
|
Type::Nat => content.replace('_', "").parse::<u64>().ok().map(Self::Nat),
|
||||||
Type::Float => Self::Float(content.replace('_', "").parse::<f64>().unwrap()),
|
Type::Float => content
|
||||||
|
.replace('_', "")
|
||||||
|
.parse::<f64>()
|
||||||
|
.ok()
|
||||||
|
.map(Self::Float),
|
||||||
// TODO:
|
// TODO:
|
||||||
Type::Ratio => Self::Float(content.replace('_', "").parse::<f64>().unwrap()),
|
Type::Ratio => content
|
||||||
|
.replace('_', "")
|
||||||
|
.parse::<f64>()
|
||||||
|
.ok()
|
||||||
|
.map(Self::Float),
|
||||||
Type::Str => {
|
Type::Str => {
|
||||||
if &content[..] == "\"\"" {
|
if &content[..] == "\"\"" {
|
||||||
Self::Str(Str::from(""))
|
Some(Self::Str(Str::from("")))
|
||||||
} else {
|
} else {
|
||||||
let replaced = content.trim_start_matches('\"').trim_end_matches('\"');
|
let replaced = content.trim_start_matches('\"').trim_end_matches('\"');
|
||||||
Self::Str(Str::rc(replaced))
|
Some(Self::Str(Str::rc(replaced)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type::Bool => Self::Bool(&content[..] == "True"),
|
Type::Bool => Some(Self::Bool(&content[..] == "True")),
|
||||||
Type::NoneType => Self::None,
|
Type::NoneType => Some(Self::None),
|
||||||
Type::Ellipsis => Self::Ellipsis,
|
Type::Ellipsis => Some(Self::Ellipsis),
|
||||||
Type::NotImplemented => Self::NotImplemented,
|
Type::NotImplemented => Some(Self::NotImplemented),
|
||||||
Type::Inf => Self::Inf,
|
Type::Inf => Some(Self::Inf),
|
||||||
Type::NegInf => Self::NegInf,
|
Type::NegInf => Some(Self::NegInf),
|
||||||
_ => todo!("{t} {content}"),
|
_ => todo!("{t} {content}"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -534,7 +542,7 @@ impl ValueObj {
|
||||||
Self::None => Type::NoneType,
|
Self::None => Type::NoneType,
|
||||||
other => panic!("{other} object cannot be mutated"),
|
other => panic!("{other} object cannot be mutated"),
|
||||||
},
|
},
|
||||||
Self::Illegal => todo!(),
|
Self::Illegal => Type::Failure,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
9
doc/EN/dev_guide/troubleshooting.md
Normal file
9
doc/EN/dev_guide/troubleshooting.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Troubleshooting
|
||||||
|
|
||||||
|
## Q: Local builds succeed, but GitHub Actions builds fail
|
||||||
|
|
||||||
|
A: The branch you are working on may not be following the changes in `main`.
|
||||||
|
|
||||||
|
## Q: The pre-commit check fails
|
||||||
|
|
||||||
|
A: Try committing again. It may fail the first time. If it fails again and again, the code may contain a bug.
|
12
doc/JA/dev_guide/troubleshooting.md
Normal file
12
doc/JA/dev_guide/troubleshooting.md
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
# トラブルシューティング
|
||||||
|
|
||||||
|
[](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/dev_guide/troubleshooting.md&commit_hash=e033e4942e70657008427f05def2d1b1bfb5ed66)
|
||||||
|
|
||||||
|
|
||||||
|
## Q: ローカルでのビルドは成功したが、GitHub Actionsのビルドが失敗する
|
||||||
|
|
||||||
|
A: あなたの作業しているブランチが`main`の変更に追従していない可能性があります。
|
||||||
|
|
||||||
|
## Q: pre-commitのチェックが失敗する
|
||||||
|
|
||||||
|
A: もう一度コミットを試みてください。最初の1回は失敗することがあります。何度やっても失敗する場合、コードにバグが含まれている可能性があります。
|
11
doc/zh_CN/dev_guide/troubleshooting.md
Normal file
11
doc/zh_CN/dev_guide/troubleshooting.md
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# 故障诊断
|
||||||
|
|
||||||
|
[](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/dev_guide/troubleshooting.md&commit_hash=e033e4942e70657008427f05def2d1b1bfb5ed66)
|
||||||
|
|
||||||
|
## Q: 本地生成成功, 但 GitHub Actions 生成失败
|
||||||
|
|
||||||
|
A: 您正在处理的分支可能没有Pull`main`中的更改
|
||||||
|
|
||||||
|
## Q: 提交前检查失败
|
||||||
|
|
||||||
|
A: 尝试再次提交, 第一次可能会误判, 如果一次又一次的失败, 那么你的代码可能包含错误
|
11
doc/zh_TW/dev_guide/troubleshooting.md
Normal file
11
doc/zh_TW/dev_guide/troubleshooting.md
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# 故障診斷
|
||||||
|
|
||||||
|
[](https://gezf7g7pd5.execute-api.ap-northeast-1.amazonaws.com/default/source_up_to_date?owner=erg-lang&repos=erg&ref=main&path=doc/EN/dev_guide/troubleshooting.md&commit_hash=e033e4942e70657008427f05def2d1b1bfb5ed66)
|
||||||
|
|
||||||
|
## Q: 本地生成成功, 但 GitHub Actions 生成失敗
|
||||||
|
|
||||||
|
A: 您正在處理的分支可能沒有Pull`main`中的更改
|
||||||
|
|
||||||
|
## Q: 提交前檢查失敗
|
||||||
|
|
||||||
|
A: 嘗試再次提交, 第一次可能會誤判, 如果一次又一次的失敗, 那麼你的代碼可能包含錯誤
|
3
examples/assert_cast.er
Normal file
3
examples/assert_cast.er
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
i: Int = 2 - 1
|
||||||
|
assert i in Nat
|
||||||
|
i: Nat
|
|
@ -109,6 +109,9 @@ impl Runnable for DummyVM {
|
||||||
.replace(".er", ".pyc");
|
.replace(".er", ".pyc");
|
||||||
self.compiler
|
self.compiler
|
||||||
.compile_and_dump_as_pyc(&filename, self.input().read(), "exec")?;
|
.compile_and_dump_as_pyc(&filename, self.input().read(), "exec")?;
|
||||||
|
if self.cfg().dump_as_pyc {
|
||||||
|
return Ok(0);
|
||||||
|
}
|
||||||
let code = exec_pyc(&filename);
|
let code = exec_pyc(&filename);
|
||||||
remove_file(&filename).unwrap();
|
remove_file(&filename).unwrap();
|
||||||
Ok(code.unwrap_or(1))
|
Ok(code.unwrap_or(1))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
for! 1..<100, i =>
|
for! 1..<100, i =>
|
||||||
match (i % 3, i % 5):
|
match [i % 3, i % 5]:
|
||||||
(0, 0) => print! "FizzBuzz"
|
[0, 0] => print! "FizzBuzz"
|
||||||
(0, _) => print! "Fizz"
|
[0, _] => print! "Fizz"
|
||||||
(_, 0) => print! "Buzz"
|
[_, 0] => print! "Buzz"
|
||||||
(_, _) => print! i
|
[_, _] => print! i
|
||||||
|
|
|
@ -11,6 +11,11 @@ fn exec_addition() -> Result<(), ()> {
|
||||||
expect_failure("tests/addition.er")
|
expect_failure("tests/addition.er")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exec_assert_cast() -> Result<(), ()> {
|
||||||
|
expect_success("examples/assert_cast.er")
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_class() -> Result<(), ()> {
|
fn exec_class() -> Result<(), ()> {
|
||||||
expect_success("examples/class.er")
|
expect_success("examples/class.er")
|
||||||
|
@ -51,6 +56,11 @@ fn exec_move_check() -> Result<(), ()> {
|
||||||
expect_failure("examples/move_check.er")
|
expect_failure("examples/move_check.er")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn exec_prelude() -> Result<(), ()> {
|
||||||
|
expect_success("compiler/erg_compiler/std/prelude.er")
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn exec_quantified() -> Result<(), ()> {
|
fn exec_quantified() -> Result<(), ()> {
|
||||||
expect_success("examples/quantified.er")
|
expect_success("examples/quantified.er")
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue