.\icu

Blog of @megakite.


January 1, 0001

为了符合「作用域」的定义,哈希表应该采用头插法。 这块我写得真的是非常诡异……为了暴露哈希表的细节,还假装自己模拟了一个友元出来。

错用container_of导致ASAN在某次成员访问的时候报了一个heap-buffer-overflow,一开始还以为是误报。这个错用的过程真的是环环相扣。

最终决定元信息(levelscope)还是要暴露在公共类型里,具体来说,是直接放到symbols_t里,而不是仅仅作为view暴露出来。

事实上比较数学的处理变量作用域的思路应该是类似LISP和ML的let...in关键字,这是一个完全递归的、完备的思路,而且和树同构,但是可以预想到内存占用多、搜索效率差——但其实我这个破烂十字链表应该也高不到哪去吧……

做到发现迭代式的思路甚至还需要用栈记录Stmtindex的时候就做不下去了。很明显,迭代式的思路无法满足lexical scope的要求(或者至少复杂度非常高),必然要在一定程度上借助let...in的思路。

最终实际的scope(和其数据结构)其实是这样的:

                              // (-, -)
( int main()                  //   (0, 0)
  {                           //     (1, 0)
    ( int a = 1;              //       (2, 0)
      {                       //         (3, 0)
        ( int a = 2;          //          | (4, 0)
          a = 3;              //          |  |
        )                     //          |  |
	  }                       //          V  |
      {                       //         (3, 1)
        a = a + 4;            //             V
        ( int b = a;          //            (4, 1)
          ( int c = b + 5, d; //              (5, 0)
            a = c + 6;
            d = 7;
          )
        )
      }
      return a;
    )
  }
)

每次leave()或者dedent()都会直接回到该层的{ ... }结尾处;同时把对同层不同序(order)的scope的访问用队强行串起来了……

我一开始分了64K给bump allocator,结果在跑06_complex_scopes的时候竟然不够了……我写了个什么怪物出来,怎么能做到这么占内存的。我估计raw->ty没有作压缩应该占很大一部分原因。

最后还是终于搞明白了used_by到底是个什么机制——其实很简单,在kind里用到谁就往谁里面加。这是什么意思?是后序遍历

有一个问题死活找不出来,结果发现是把strcmp()的比较条件「写反了」:

#if 0
if (strcmp(a, b)) { ... }
#else
if (strcmp(a, b) == 0) { ... }
#endif

这个,呃……行吧。