quartz-research-note/content/エラーフレンドリーな評価環境の実装.md
松浦 知也 Matsuura Tomoya c88ebcc7ee
All checks were successful
Build / build (push) Successful in 4m16s
[obsidian] vault backup: 2024-12-25 16:00:07[
2024-12-25 16:00:07 +09:00

1.9 KiB

date
2024-12-25 15:10

#programming-language #compiler-design

例えば似た変数名の候補を返すとか、スコープ外にある変数の候補をサジェストしてくれるような評価環境を作りたい

また、単に見つかった変数への参照を返すだけでなく、それがローカル、upvalue、global、externalなのかの区別も欲しい

これも参照を引き回すのがだるいのでSlotmapとかで実装するのがいいかもしれない

ネストされたletは1つずつ環境を作っていくが、ブロックとかで閉じたスコープを作れる

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

  • とりあえず親のリストへ辿る方向で探索する
  • 見つからなかった(セマンティクス的にエラーになる)場合は親を兄弟含めて検索して、候補が見つかったら返す
    • このときはついでに類似度検索で近いやつが否いかも探す
#[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でスコープ作る時だけか