LLVM поддерживает структуры, верно? Вот что делают типичные компиляторы.
Вам необходимо создать анонимную структуру с полями, сгенерированными из каждой внешней переменной, на которую вы ссылаетесь. Затем вы создаете анонимную функцию, соответствующую b()
, которая принимает эту структуру в качестве аргумента и работает с ней. По сути, вы превращаете b()
в обычную функцию верхнего уровня. Наконец, вы преобразуете код a()
так, что он создает экземпляр структуры и вызывает анонимную функцию. На данный момент возможны дальнейшие оптимизации. Будьте готовы: это совсем не просто, возможно, очень сложная тема для преобразования кода.
Например
func a()
int x = 1;
func b() {
return x+1;
}
return b() + 2;
}
становится
struct tmp {
int tmpx; // reference or value?
}
func tmp_b(tmp& instance) {
instance.tmpx += 1;
return instance.tmpx;
}
func a() {
int x = 1;
tmp instance(tmpx = x); // should it go by reference or value?
return tmp_b(instance) + 2;
}
В качестве альтернативы вы можете преобразовать b()
в b(int x)
функцию верхнего уровня. Но такой подход менее гибок ИМО. Или в зависимости от контекста использовать оба подхода, почему бы и нет.
Обратите внимание, что все это, вероятно, можно упростить, если ваш язык поддерживает надлежащие классы с перегрузкой методов и / или операторов (в данном случае оператора вызова).