教学级即时编程

2021-05-08 22:53:45

即时编程是一个用于自上而下的程序的工作流程,而程序正在运行。这在Smarktalk环境中是典型的。

我认为描述教学级别立交编程(IL-JIT编程)的最佳方法是通过展示它的工作原理。我' ll从经典的fibonacci example(rosetta代码有很多实现)。我们' ll在评估fib(3)时实施fibonacci。

遵循的示例是一种连接语言,即FLPCForth的简化版本。要知道的主要事情是它有

并且所有函数都是正式的,但是具有隐含的ARITITY,由它们从全局参数堆栈的顶部删除的元素数量定义。它们的返回值被推到该堆栈的顶部。

这里的整个视频的整个视频'我们逐步走过。点击它播放。

内存显示左右,包裹到下一行。每个存储器单元都保存函数,字符串或标签(将其作为NO-OP执行)。输入堆栈绘制在程序计数器上方。仅示出了呼叫堆栈的顶部。

每次编写指令时,程序计数器都需要一步。我们还可以在不撰写任何指令的情况下向程序计数器推进。

FIB ISN' t定义尚未给出错误。 我们' ll创建fib并重试呼叫。 通常,我们可能想检查一些基本情况。 然而,由于我们在手中有争论3,让'■只写i> 2例现在。 我们应该返回FIB(I-2)+ FIB(I-1)。 计算第一部分FIB(I-2)。 由于此递归调用FIB,让我们遵循执行。 首先,我们手动让一些指令执行 直到我们需要介入。 在此递归调用中,我= 1所以我们现在需要基本情况。 喜欢fib,'基地' 是指尚未存在的函数。 如前所述,创建功能并再次调用。 当我< 3,我们' ll只是返回1,所以这就是基础的作用。

典型的JIT编程重新启动错误帧。也就是说,它可以展开许多帧(由用户决定)。例如,如果我们叫一个名为F2的F1,其中称为F4的F2,则堆栈将如下所示

通过教学级别JIT编程,没有堆栈在展开,其实大部分时间都没有,没有什么是撤消的。指令计数器仅暂停,直到要求再次逐步逐步暂停。即使对于缺少函数,我们可以暂停,等待要创建的功能并尝试再次调用它。

虽然我认为IL JIT编程将受益于补充帧重启,但是当需要更大的代码块时需要纠正。

您可以访问当前程序的完整状态,如变量。当你不需要抽象地思考并避免像逐个错误一样审视并避免错误。

首先,您可以在简单的情况下编写程序的部件并填写更复杂的案例。这使您可以在为其提高努力之前测试您的整体设计。

我想我可以得到这样的东西来为FLPC工作,甚至在高级FLPCPYTHON语言中写作。这里和#39;它如何工作。

当字节码到内存编译器/转录器时遇到某些呼叫者的正文时遇到未知的函数名称,而不是将(对内存)指向该函数的指针(存在),它会写入字符串函数名称为字符串和A"未实施的"原始的内存。

当正文执行时,"未实施的"遇到原语,原始检查是否现在定义了该名称的函数,如果不向内存添加固定大小的空函数并将其定义

创建块时(例如,如果...:或重复:块),则将匿名固定尺寸的空函数添加到内存中,并将其写入作为呼叫者主体的一部分。

如果有人将和指令插入内存中,则将每个函数体中的每个未来指令转移到内存右侧。由于函数体是固定的尺寸并插入内存需要人类的交互,因此应该足够快。

在这里,'&内存可能看起来像以前相同的fibonacci示例。

名称dict:fib - > 100Memory:<分配:> < str i> < prive pushi:> < int 2> < prim - > < mem 100 fib>地址:100 101 102 103 104 105

我们在第二次调用fib后运行程序,我们插入基壳检查

名称dict:fib - > 100Memory:< newfunc1> <分配:> < str i> < prive pushi:> < int 3> < prim< < mem 200匿名> < prim>地址:100 101 102 103 104 105 106 107Memory:< prive pushi:> < int 2> < prim - > < mem 100 fib>地址:108 109 110 111Memory:[...]< prim beakpoint> < prim断点> < prim beakpoint>地址:200 201 2010 2010

名称dict:fib - > 100Memory:< newfunc1> <分配:> < str i> < prive pushi:> < prim 3> < prim< < mem 200匿名> < prim>地址:100 101 102 103 104 105 106 107Memory:< prive pushi:> < int 2> < prim - > < mem 100 fib>地址:108 109 110 111Memory:[...]< prive pushi:> < int 1> < prim return>地址:200 201 202

从递归调用返回后,我们可以添加函数体的其余部分。

fib< - 有趣[i]:如果我< 3:返回(1)FIB(I - 2)+ FIB(I - 1)返回()

名称dict:fib - > 100Memory:< newfunc1> <分配:> < str i> < prive pushi:> < prim 3> < prim< < mem 200匿名> < prim>地址:100 101 102 103 104 105 106 107Memory:< prive pushi:> < int 2> < prim - > < mem 100 fib>地址:108 109 110 111Memory:< prive pushi:> < int 1> < prim - > < mem 100 fib> < prim +> < prim return>地址:112 113 114 115 116 117Memory:[...]< prive pushi:> < int 1> < prim return>地址:200 201 202

这个设计似乎工作,但我不知道我是否会将它添加到FLPC。

我没有找到任何在吱吱声smalltalk中使用的工作流的规范名称,所以我在这里打电话给它jit编程。其中一个名叫它的C2 Wiki页面。其他一些可能的名称:自上而下编程,增量编程。

[副作用]如果某些功能已经执行了从文件的读取或网络请求等副作用,则这些不是未完成的并且程序可能以不一致的状态结束。在这种情况下,需要重新启动更多的程序。

然而,我们通常可以在本地(即,根据每个功能基础)从纯净或&#34中单独副作用;纯粹" 职能。 然后只重新启动纯部分(或重新格式化所有副作用的较大组)。 无论如何,这种分离是您可能需要的东西