Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
2 changes: 2 additions & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
- [VSC Support](./tutorial/vscsupport.md)
- [References](./references/README.md)
- [Basic](./references/basic.md)
- [Operator](./references/operator/README.md)
- [Type Operator](./references/operator/tyops.md)
- [Array](./references/array.md)
- [closure](./references/closure.md)
- [Module](./references/module.md)
Expand Down
2 changes: 1 addition & 1 deletion book/src/dev-prepare.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ brew install llvm@18

如果你使用的是ubuntu,可以使用[这里](https://github.com/Pivot-Studio/setup-llvm/blob/main/scripts/install_llvm.sh)的脚本进行安装

# CMake
## CMake

我们的垃圾回收模块使用了LLVM中的StackMap功能,需要使用CMake进行编译。

Expand Down
2 changes: 1 addition & 1 deletion book/src/references/basic.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,4 @@

例如:

- `let x = (false && true_with_pnanic()) || (true || !true_with_pnanic());`是一个复杂的逻辑运算
- `let x = (false && true_with_panic()) || (true || !true_with_panic());`是一个复杂的逻辑运算
74 changes: 74 additions & 0 deletions book/src/references/operator/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# Operators

本节收录了所有的运算符。

## 算术运算符

| 运算符 | 描述 | 示例 |
| --- | --- | --- |
| `+` | 加法 | `1 + 1` |
| `-` | 减法 | `1 - 1` |
| `*` | 乘法 | `1 * 1` |
| `/` | 除法 | `1 / 1` |
| `%` | 取余 | `1 % 1` |

## 位运算符

| 运算符 | 描述 | 示例 |
| --- | --- | --- |
| `&` | 与 | `1 & 1` |
| `\|` | 或 | `1 \| 1` |
| `^` | 异或 | `1 ^ 1` |
| `<<` | 左移 | `1 << 1` |
| `>>` | 右移 | `1 >> 1` |

## 逻辑运算符

| 运算符 | 描述 | 示例 |
| --- | --- | --- |
| `&&` | 逻辑与 | `true && false` |
| `\|\|` | 逻辑或 | `true \|\| false` |
| `!` | 逻辑非 | `!true` |

## 比较运算符

| 运算符 | 描述 | 示例 |
| --- | --- | --- |
| `==` | 等于 | `1 == 1` |
| `!=` | 不等于 | `1 != 1` |
| `>` | 大于 | `1 > 1` |
| `<` | 小于 | `1 < 1` |
| `>=` | 大于等于 | `1 >= 1` |
| `<=` | 小于等于 | `1 <= 1` |

## 赋值运算符

| 运算符 | 描述 | 示例 |
| --- | --- | --- |
| `=` | 赋值 | `a = 1` |

## 类型运算符

详见[类型运算符](./tyops.md)。

| 运算符 | 描述 | 示例 |
| --- | --- | --- |
| `as` | 类型转换 | `1 as i32` |
| `is` | 类型判断 | `1 is i32` |
| `impl` | 实现 | `a impl TestTrait?` |

## 其他运算符

| 运算符 | 描述 | 示例 |
| --- | --- | --- |
| `&` | 取地址 | `&a` |
| `*` | 取值 | `*a` |
| `()` | 函数调用 | `test_vm()` |
| `[]` | 索引 | `a[1]` |
| `.` | 成员访问 | `a.b` |
| `:` | 类型标注 | `let a: i32 = 1` |
| `;` | 语句结束 | `let a = 1;` |




186 changes: 186 additions & 0 deletions book/src/references/operator/tyops.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
# Type Operators 类型运算符

本章节会对三种特殊的运算符进行介绍:`as`、`is` 和 `impl`。

## `as` 类型转换运算符

`as` 运算符用于将一个值转换为另一个类型。

### 基础类型转换

在转换一些基础类型的时候(比如int类型之间的转换),`as` 运算符是不会失败的,例如:

```plang
let a: i64 = 1;
let b: i32 = a as i32;
```

在这个例子中,`a` 是一个 `i64` 类型的变量,我们将其转换为 `i32` 类型的变量 `b`。这种转换永远成功,尽管可能会导致精度丢失或者损失一部分数据。

### 和类型转换

`as`也可以进行对`和类型`的转换,假设我们有如下类型:

```plang
struct ST{};
type Test<T> = T | ST;
```

我们可以将任意一个类型用`as`转换为`Option`类型:

```plang
let a: i64 = 1;
let b = a as Test<i64>;
```

将子类型转换为和类型是不可能失败的。如果尝试转化为一个不可能的类型,编译器会报错。

反之,`as`运算符也可以将和类型转换为子类型:

```plang
let a: i64 = 1;
let b = a as Test<i64>;
let c: i64 = b as i64!;
let d: Option<i64> = b as i64?;
```

但是,将和类型转换为子类型可能会失败,编译器不会允许你直接使用常规的`as`语句进行转换,你必须使用`?`或`!`来标注转换是非强制的还是强制的。

如果使用`?`标注,那么`x as T?`语句会返回一个`Option<T>`类型,如果转换失败,则该返回值是`None`。

如果使用`!`标注,那么`x as T!`语句会返回一个`T`类型,如果转换失败,则会导致运行时错误(__cast_panic)。

### 泛型类型转换

`as`运算符也可以用于泛型类型的转换:

```plang
fn test<T>(x: T) i64 {
let y = x as i64!;
return x;
}
```

如果泛型类型转换失败,会导致运行时错误(__cast_panic)。这种转换是编译期进行的,没有运行时开销。

泛型的转换一定是强制的,需要带上`!`标注。

#### if let ... as ... 语法

`if let ... as ...` 语法可以用于安全的对泛型类型进行转换:

```plang
fn test<T>(x: T) i64 {
if let y = x as i64 {
return y;
}
return -1;
}
```

## `is` 类型判断运算符

### 基础类型判断

`is` 运算符用于判断一个值是否是某个类型。例如:

```plang
let a: i64 = 1;
let b = a is i64;
```

在这个例子中,`b` 的值是 `true`,因为 `a` 是一个 `i64` 类型的变量。

### 和类型判断

`is` 运算符也可以用于判断和类型:

```plang
let a: i64 = 1;
let b = a as Test<i64>;
let c = b is i64;
```

在这个例子中,`c` 的值是 `true`,因为 `b` 是一个 `i64` 类型的变量。

### 泛型类型判断

特殊的,`is` 运算符也可以用于判断泛型类型:

```plang
fn test<T>(x: T) T {
if x is i64 {
doSth();
}
return x;
}
```

## `impl` 判断实现运算符

`impl` 运算符用于判断一个泛型是否实现了某个trait。例如:

```plang
trait TestTrait {
fn test();
}

struct TestStruct{};

impl TestTrait for TestStruct {
fn test() {
println("test");
}
}

fn test<T>(x: T) T {
let y = x impl TestTrait?;
let z = x impl TestTrait!;
z.test();
return x;
}

```

普通的`impl`语句必须带上`?`或`!`标注,否则编译器会报错。

对于`?`标注,如果泛型类型没有实现trait,那么语句会返回`false`,否则返回`true`。

对于`!`标注,如果泛型类型没有实现trait,那么语句会导致运行时错误(__impl_panic)。以上方例子举例,如果`x`没有实现`TestTrait`,那么`let z = x impl TestTrait!;`会导致运行时错误。反之,如果`x`实现了`TestTrait`,`z`将会是是一个特殊的`T`类型,但是他的增加了实现`TestTrait`的约束,使得下一行代码可以调用`TestTrait`trait的`test`方法。请注意,虽然`z`的类型和`x`的类型都是`T`,但是他们的约束是不同的,严格来说并不是同一类型。`z`的类型`T`,也不是上下文中的`T`类型。

### `if let ... impl ...` 语法

`if let ... impl ...` 语法可以用于安全的对泛型类型进行trait实现判断:

```plang
fn test<T>(x: T) T {
if let y = x impl TestTrait {
y.test();
}
return x;
}
```

他等同于

```plang
fn test<T>(x: T) T {
if x impl TestTrait? {
let y = x impl TestTrait!;
y.test();
}
return x;
}

```











6 changes: 3 additions & 3 deletions src/ast/compiler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ pub fn compile(db: &dyn Db, docs: MemDocsInput, out: String, op: Options) {
}
let total_steps = 3;
let pb = &COMPILE_PROGRESS;
prepare_prgressbar(
prepare_progressbar(
pb,
op,
format!("{}[{:2}/{:2}]", LOOKING_GLASS, 1, total_steps),
Expand Down Expand Up @@ -208,7 +208,7 @@ pub fn process_llvm_ir<'a>(

let total_steps = 3;
let pb = ProgressBar::hidden();
prepare_prgressbar(&pb, op, format!("{}[{:2}/{:2}]", TRUCK, 2, total_steps));
prepare_progressbar(&pb, op, format!("{}[{:2}/{:2}]", TRUCK, 2, total_steps));
pb.set_length(mods.len() as u64);

let mut set = FxHashSet::default();
Expand Down Expand Up @@ -329,7 +329,7 @@ pub fn pl_link(llvmmod: Module, oxbjs: Vec<PathBuf>, out: String, op: Options) {

let total_steps = 3;
let pb = ProgressBar::hidden();
prepare_prgressbar(
prepare_progressbar(
&pb,
op,
format!("{}[{:2}/{:2}]", CLIP, total_steps, total_steps),
Expand Down
2 changes: 1 addition & 1 deletion src/ast/compiler/progress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ lazy_static! {
}

#[cfg(feature = "llvm")]
pub fn prepare_prgressbar(pb: &indicatif::ProgressBar, op: Options, prefix: String) {
pub fn prepare_progressbar(pb: &indicatif::ProgressBar, op: Options, prefix: String) {
pb.enable_steady_tick(Duration::from_millis(50));
pb.set_style(PROGRESS_STYLE.clone());

Expand Down
Loading