63 lines
1.9 KiB
Markdown
63 lines
1.9 KiB
Markdown
|
---
|
||
|
date: 2024-12-25 15:10
|
||
|
---
|
||
|
#programming-language #compiler-design
|
||
|
|
||
|
例えば似た変数名の候補を返すとか、スコープ外にある変数の候補をサジェストしてくれるような評価環境を作りたい
|
||
|
|
||
|
また、単に見つかった変数への参照を返すだけでなく、それがローカル、upvalue、global、externalなのかの区別も欲しい
|
||
|
|
||
|
これも参照を引き回すのがだるいのでSlotmapとかで実装するのがいいかもしれない
|
||
|
|
||
|
ネストされたletは1つずつ環境を作っていくが、ブロックとかで閉じたスコープを作れる
|
||
|
|
||
|
```rust
|
||
|
fn test(arg1,arg2){
|
||
|
let a = {
|
||
|
let hoge = 100
|
||
|
hoge + 20
|
||
|
};
|
||
|
let b = 200
|
||
|
let c = hoge //this should be an error but suggested by language server
|
||
|
b
|
||
|
}
|
||
|
```
|
||
|
|
||
|
ほかにも、let-tupleや複数引数のラムダなど、単に変数-値のペアのシングルリストではなく、レベルごとに複数のペアが混ざってるような形を取りうる。
|
||
|
|
||
|
上のコードでcを評価する直前の変数環境はこんな感じ
|
||
|
|
||
|
![[img/スクリーンショット 2024-12-25 15.23.26.png]]
|
||
|
|
||
|
- とりあえず親のリストへ辿る方向で探索する
|
||
|
- 見つからなかった(セマンティクス的にエラーになる)場合は親を兄弟含めて検索して、候補が見つかったら返す
|
||
|
- このときはついでに類似度検索で近いやつが否いかも探す
|
||
|
|
||
|
|
||
|
```rust
|
||
|
#[derive(Default)]
|
||
|
pub struct Env<K,T>{
|
||
|
parent: Option<Rc<Self>>,
|
||
|
siblings: Vec<Rc<Self>>,
|
||
|
local: Vec<(K,T)>
|
||
|
}
|
||
|
|
||
|
impl <K,T> Env<K,T>{
|
||
|
pub fn from_iter(parent:Rc<Self>,iter:impl Iterator<Item=(K,T)>)->Self{
|
||
|
Self{
|
||
|
parent,
|
||
|
local: HashMap::from_iter(iter)
|
||
|
..Default::default()
|
||
|
}
|
||
|
}
|
||
|
pub fn is_global(&self)->bool{
|
||
|
self.parent.is_none()
|
||
|
}
|
||
|
pub fn lookup(&self,name:K)->Result<T,Error>{
|
||
|
|
||
|
}
|
||
|
}
|
||
|
```
|
||
|
|
||
|
結局siblingを作るケースはblockでスコープ作る時だけか
|