Skip to content

Commit

Permalink
計算施術
Browse files Browse the repository at this point in the history
  • Loading branch information
MROS committed Oct 16, 2024
1 parent 355f4b9 commit 9bc6d3f
Showing 1 changed file with 32 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,38 @@ fn 計算(
}
}
```
### 計算施術

相比零.一版,此處增加了一種算式——`施術`,依然可用堆疊機來完成,先分別計算各個實參,將實參的值壓入棧中,等實參都計算完畢後,將實參值載入參數暫存器後,施術(call)。

### 計算施術
```rust
// 結束時,棧頂 = t0 = 術的歸值
fn 施術(真言檔: &mut File, 術: &O施術, 符號表: &O符號表) -> io::Result<()> {
writeln!(真言檔, "# 施展「{}」", 術.術名)?;

assert!(術.實參.len() <= 8, "音界咒暫不支援超過八個術參");

// 將參數計算結果逐一推入棧中
// NOTE: 不可將計算結果直接賦值給暫存器
// 因其下個參數的計算過程中,可能又會汙染掉參數暫存器
for 參數 in &.實參 {
// 任何計算完成後,棧會擴大一個字長
// 計算結果會被置於棧頂
Self::計算(真言檔, 參數, 符號表)?;
}
// 將參數從棧中逐一載入參數暫存器
for 編號 in (0...實參.len()).rev() {
writeln!(真言檔, "\tld a{}, 0(sp)", 編號)?;
writeln!(真言檔, "\taddi sp, sp, 8")?; // 將參數計算結果彈出
}

writeln!(真言檔, "\tcall {}", 術.術名)?;

// 歸值放回 t0
writeln!(真言檔, "\tmv t0, a0")?;
writeln!(真言檔, "\taddi sp, sp, -8")?; // 增加棧 64 位元的空間
writeln!(真言檔, "\tsd t0, 0(sp)") // t0 放入棧頂
}
```

至此,術的編譯大致講解完畢,部分與零.一版重複的程式碼就先不貼上來了。若有興趣,可直接參考[音界咒源碼](https://github.com/MROS/yinjie-lang/blob/3c6389823284722338642e3de672ef48d8e8ac9e/%E9%9B%B6%E8%99%9F%E7%B7%A8%E8%AD%AF%E5%99%A8/src/%E7%9C%9F%E8%A8%80%E7%94%9F%E6%88%90/%E7%9C%9F%E8%A8%80%E7%94%9F%E6%88%90%E5%99%A8.rs)

0 comments on commit 9bc6d3f

Please sign in to comment.