Skip to content

Commit 7d87b9c

Browse files
committedOct 28, 2014
4.1字节码 更新
1 parent b355442 commit 7d87b9c

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed
 

‎.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
res/Thumbs.db

‎04.1-Bytecode.md

+49
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,52 @@ private:
402402
403403
只剩下一个问题了:真正去创建字节码。眼下我们将一段伪代码编译成了字节码。除非你真的很闲,否则这在实践中根本行不通。
404404

405+
###语法转换工具
406+
407+
我们的一个最初目标是在较高的层次上编写行为,但是我们已经做了些比C++还底层的东西。它能兼顾我们需要的运行时性能和安全性,但是彻底缺乏对设计师友好的可用性。
408+
409+
为了填补这个缺陷,我们需要些工具。我们需要一个程序,让用户在高层次上定义法术的行为,并能够生成对应的低层次字节码。
410+
411+
这听起来比创建一个虚拟机还难。很多程序员在大学的时候被扔到一个编译器课程中,其中所得除了看到封面上有条龙或者"lex"和"yacc"这些词时就犯的创伤后应激障碍之外,什么也没有。
412+
413+
> 我所说的,当然是这篇经典的[编译器:原则、技术和工具](http://en.wikipedia.org/wiki/Compilers:_Principles,_Techniques,_and_Tools)
414+
415+
其实,编译一个基于文本的语言并非不能,只是这里篇幅有限。但是,你没必要这么做。我说你需要一个工具——并不一定得是个能编译输入文本的编译器。
416+
417+
恰恰相反,我希望你考虑做一个图形界面来让用户定义行为,他别是对于那些不太擅长技术的人。对于一个没有多年面对编译器各种报错的经验的人来说,书写语法正确的文本太难了。
418+
419+
反之,你可以创建一个应用,让用户通过点击和拖拽一些小方块、点选菜单或者其他任何对创建行为有意义的事情。
420+
421+
![](./res/bytecode-ui.png)
422+
423+
> 我为[Henry Hatsworth in the Puzzling Adventure](http://en.wikipedia.org/wiki/Henry_Hatsworth_in_the_Puzzling_Adventure)编写的脚本系统的原理就是这样的。
424+
425+
这么做的好处是你的UI让用户几乎难以创建“非法的”程序。 你可以前瞻性地禁用按钮或者提供默认值来保证他们创建的东西在任何时候都是合法的,而不是丢出一大堆错误信息。
426+
427+
> 我要强调下错误处理的重要性。作为程序员,我们倾向于把人为错误看做是耻辱的人性缺陷而竭尽全力避免发生在自己身上。
428+
429+
> 为了做出一个用户喜欢的系统,你得拥抱他们的人性,这就包括了不可靠性。人们总是犯错,它是创造活动的组成部分。通过一些撤销之类的功能来优雅地处理掉这些问题能让你的用户更有创造力并更好地完成任务。
430+
431+
这让你免于为一个小语言设计语法并编写语法分析器。但我也清楚,有些人对UI编程同样很不习惯。那么,这里我也没别的办法。
432+
433+
最终,这个模式还是关于如何用一种用户友好并能在高层次编辑的条件下表达行为的。你得去创建用户表达式。为了获得高执行效率,你得把它翻译成低级形式。这就是真正的工作,但如果你接受这个挑战,它会给你回报的。
434+
435+
##设计决定
436+
437+
我试图让这一章尽可能简单,但是我们真的是在创建一种语言。它是一个很开放的设计空间。在其中尝试非常有趣,所以,别忘了完成你的游戏。
438+
439+
> 因为这是本书中最长的一章,这个任务我失败了。
440+
441+
###指令如何访问堆栈?
442+
443+
字节码虚拟机有两种大风格:基于栈和基于寄存器。在基于栈的虚拟机中,指令总是操作栈顶,正如我们的示例代码一样。例如,INST_ADD 出栈两个值,将它们相加,然后将结果入栈。
444+
445+
基于寄存器的虚拟机也有一个堆栈。唯一的区别是指令可以从栈的更深层次中读取输入。不像INST_ADD那样总是出栈操作数,它在字节码中存储两个索引来表示应该从堆栈的哪个位置读取操作数。
446+
447+
* 基于栈的虚拟机:
448+
* 指令很小。因为每个指令都从隐式从栈顶寻找它的参数,你无需对任何数据做编码。这意味着每个指令都非常小,通常只用一个字节。
449+
* 代码生成更简单。当你要编写一个编译器或生成字节码输出的工具时,你会发现机遇栈的虚拟机更简单。每个指令都隐式操作栈顶,你只需要以正确的顺序输出指令,来实现参数传递。
450+
* 指令数更多。每个指令都只操作栈顶。这意味着生成类似a = b + c这样的代码。你就得用分离指令把b和c分别放到栈顶,执行操作,然后将结果存入a。
451+
452+
* 基于寄存器的虚拟机:
453+

0 commit comments

Comments
 (0)
Please sign in to comment.