问题描述
的改进/阐述
// module_1.js
// global variables
var CONST = 6541
function add(a,b) {
return CONST + a + b
}
function sub(a,b) {
return CONST - a - b
}
function mul(a,b) {
return CONST * a * b
}
// module_2.js
// global variables
var a = 11
var b = 5
var c = 2
main()
function main() {
var v = foo_1()
var w = foo_2()
var t = v(1,2,3)
var u = w(4)
var k = add(t,u)
// OUTPUT
console.log(k)
// nested functions
function foo_1() {
var d = bar_1(2,3)
var e = bar_2(10)
// returning functions as results.
return bar_3
// super nested functions.
function bar_1(x,y) {
var m = mul(x,a)
var n = sub(m,y)
var o = mul(n,c)
return o
}
function bar_2(x) {
var m = mul(x,x)
var n = add(m,3)
var o = mul(n,a)
return n
}
function bar_3(x,y,z) {
var m = mul(x,y)
var o = add(n,b)
var p = mul(o,z)
var q = sub(p,c)
var r = mul(q,d)
var s = add(r,e)
return s
}
}
function foo_2() {
return bar_2
function bar_1(x,y) {
var p = add(y,a)
var q = add(x,p)
return q
}
function bar_2(x) {
var p = bar_1(x,2)
var q = bar_1(x,4)
var r = mul(p,a)
var s = add(q,c)
return r * s
}
}
}
因此,基本上,有2个模块,每个模块在其功能中使用全局变量。第二个模块具有一系列嵌套函数,并在某些点返回函数。
我要做的是拼凑编译器将要执行的操作顺序。这是我几个小时后到目前为止得到的:
main.closure = createClosure(a,b,c)
main.foo_1.closure = createClosure(parent: main.closure,d,e)
main.foo_1.bar_1.closure = createClosure(parent: main.foo_1.closure,x,m,n,o)
mul.closure = createClosure(CONST,a,b)
也就是说,每个函数都使用(包装在)闭包中进行初始化。
-> call(main)
-> main.env = createEnvironment({
closure: main.closure,a: 11,b: 5,c: 2
})
-> call(foo_1)
-> main.foo_1.env = createEnvironment({
closure: main.foo_1.closure,// with parent environment
parent: main.env,d: null,e: null
})
-> call(bar_1,3)
-> main.foo_1.bar_1.env = createEnvironment({
closure: main.foo_1.bar_1.closure,// with parent environment
parent: main.foo_1.env,x: 2,y: 3,m: null,n: null,o: null
})
-> call(mul,main.foo_1.bar_1.env.x,main.foo_1.bar_1.env.parent.parent.a)
-> mul.env = createEnvironment({
closure: mul.closure,// no parent environment
CONST: 6541,a: main.foo_1.bar_1.env.x,b: main.foo_1.bar_1.env.y
})
或者按照实际情况变平:
-> call(main) =
-> main.env = createEnvironment({
closure: main.closure,c: 2
})
-> call(foo_1) =
-> main.foo_1.env = createEnvironment({
closure: main.foo_1.closure,// with parent environment
parent: main.env,e: null
})
-> call(bar_1,3) =
-> main.foo_1.bar_1.env = createEnvironment({
closure: main.foo_1.bar_1.closure,// with parent environment
parent: main.foo_1.env,o: null
})
-> call(mul,main.foo_1.bar_1.env.parent.parent.a) =
-> mul.env = createEnvironment({
closure: mul.closure,// no parent environment
CONST: 6541,b: main.foo_1.bar_1.env.y
})
所以基本上:
- 为每个函数创建一个闭包(在调用任何函数之前)。它基本上会创建一个可以在函数中访问的所有变量的列表。
- 每个函数的调用都会创建一个新的 environment ,该环境是基于闭包创建的。这将获取闭包中定义的所有变量,以供在函数中使用。
- 环境将其所有变量设置为当前值。也许它具有指向父环境值或参数的指针?
我仍然不太了解整个图片。如果有人可以为操作顺序写出伪代码,那将是我想要的全部。基本上,一系列嵌套函数(以及在其他模块中定义的具有其他“全局变量”的函数)是如何实现为一系列原始调用(以创建环境或其他方式)实现的。
基本上,我正在努力实现支持这些功能的编译器。我需要获取函数定义(作为AST),并将其编译为类似于原始程序集的指令块。每个指令“块”或“标签”都是指令序列(按照程序集定义)。因此,它将类似于以下程序集伪代码:
data a,11
data a,5
data a,2
main:
call foo_1
call foo_2
...
foo_1:
push 2
push 3
call bar_1
...
foo_1_bar_1:
...
...
...
foo_2:
...
foo_3:
...
但是,它将包含更多,并且还将包含每个通话的环境。像这样:
main:
// create main environment
push a
push b
push c
// some other stuff perhaps for constructing the environment.
call foo_1
...
因此,基本上,我陷入了如何想象将面向语言语法的“嵌套函数和模块”转换为类似汇编的“指令序列”的步骤。尤其是与创建环境和关闭包有关。
用伪代码编写的环境并不一定比我的优雅,
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)