Vczh Library++的NativeX语言最后一个特性完成——异常处理

Vczh Library++的NativeX语言最后一个特性完成——异常处理
    因为在开发 CMinus的过程中为了异常处理(最终没有实现进CMinus),曾经学习了一下 怎么用汇编语言写try-catch,因此这个CPU相关的处理方法就被我偷了哈,实现在了 NativeX的虚拟机里。

    在NativeX里面,try-catch和throw非常简单。throw你可以加一个值当异常数据,也可以不加(不会修改上次的异常数据,可以当rethrow用)。catch的话没办法跟C++一样根据类型来判断,因此我会给你一个异常数据的指针,你自己看着办哈,因为NativeX跟C一样没有RTTI。因此throw就很简单了,就是恢复栈顶和栈底指针之后跳转到最近的异常处理程序里面去。try和catch就是用来创建和销毁异常处理程序的。所有的异常处理程序构成了一个链表,这个链表被我记在了堆栈里面,而最近的异常处理节点的指针则被我放在了整个堆栈控件的最顶部,接在后面的是异常对象的数据。你每次throw的东西的尺寸可以不同,因此占用的“堆栈最顶部空间”也不同。当然如果你函数递归太深而导致栈顶覆盖了异常对象的数据区域时,就会触发“堆栈溢出”事件。在NativeX里面堆栈溢出代表你这程序已经废了,因此这个是不能catch的,虚拟机返回给宿主程序一个信号然后就停止执行了。

    我们来看一个简单的例子,如何throw之后把异常对象的返回给函数,首先是代码:
 1  /* NativeX Code */
 2  unit nativex_program_generated;
 3  function int32 main()
 4  {
 5      (result  =  10s32);
 6       try
 7          Throw();
 8       catch
 9          (result  =  (  *  cast < int32 *> (exception)));
10  }
11 
12  function  void  Throw()
13       throw  20s32;

    main函数首先将函数返回值设置成10,然后调用throw函数。throw函数会把20给throw出来,然后main函数catch了,把结果返回。NativeX使用了关键字exception来表达异常对象的地址。当然你如果要throw各种不同的东西的话,你得自己做标记(亲自实现RTTI)了。好了,我们看看产生的指令:
 1  //  unit nativex_program_generated;
 2        0 : stack_reserve  0
 3        1 : stack_reserve  0
 4        2 : ret  0
 5  //  function int32 main()
 6        3 : stack_reserve  0
 7  //  (result = 10s32);
 8        4 : push s32  10
 9        5 : resptr
10        6 : write s32
11  //  try
12        7 : exception_handler_push  14
13  //  Throw();
14        8 : stack_reserve  1
15        9 : stack_top  0
16       10 : call  20   1
17       11 : stack_reserve  - 1
18  //  try
19       12 : exception_handler_pop
20       13 : jump  18   1
21       14 : exception_handler_pop
22  //  (result = ( * cast<int32*>(exception)));
23       15 : exception_object_address
24       16 : resptr
25       17 : copymem  4
26  //  function int32 main()
27       18 : stack_reserve  0
28       19 : ret  0
29  //  function void Throw()
30       20 : stack_reserve  0
31  //  throw 20s32;
32       21 : exception_object_reserve  4
33       22 : push s32  20
34       23 : exception_object_address
35       24 : write s32
36       25 : exception_raise
37  //  function void Throw()
38       26 : stack_reserve  0
39       27 : ret  0

    try首先会将catch之后的第一个指令给exception_handler_push了,在try的结尾当然要取消掉这个异常处理函数了,因此pop一下,然后jump到catch后面。当然catch的第一件事也是exception_handler_pop。exception_object_reserve在栈顶预留指定的空间来存放异常对象,exception_object_address则是获得异常对象的地址,exception_raise就是跳转到最近的异常处理函数了。raise不会把异常处理函数的记录给pop掉,所以要靠catch自己去pop。

    NativeX已经完成了,接下来就可以开始打造周边工具了哇哈哈。将来的目标是将类似C#和Javascript的语言都编译到NativeX上,然后为这三类语言写很多语法分析器,然后他们就变成很多语言了。当然这些语言只是demo。 Vczh Library++的目的是提供实现编译器的中间每一层的类库,因此想干嘛就可以干嘛了哈。

你可能感兴趣的:(Vczh Library++的NativeX语言最后一个特性完成——异常处理)