---
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でスコープ作る時だけか
