UOJ Logo dram的博客

博客

一个编译器

2016-07-29 22:14:52 By dram

传送门

特别感谢 peg.js (提供语法解析支持)和 decimal.js (提供高精支持)

  • (我是更新区,这里经常变)
  • 目前加入了节点链接功能,可以稍微方便点地查看数据流。
  • 然后加入了奇怪的 hover 高亮和变量名标注

各位大神一起来把 flea-compiler 黑掉吧!谢谢啦!

(话说是不是出成 uoj 题就会有一堆人来找 bug 来 hack 了 2333)

另外跪求 sigmoid 的靠谱计算方法。。。


众所周知,NOI 2016 旷野大计算,vfk 提供的题解里面,代码是写成这样的

x = in()
p = s((x + 1e-30) << 500) << 152 
y = s((x >> 150) + p)
r  = x + ((-y + 0.5) << 153) + p
out(r)

于是我就开了个坑,写了个编译器

语法稍微有点变动的说:

          { 我是注释 }
x = in(1) { 1 代表第一个输入 }
p = s((x + 1e-30) << 500) << 152 
y = s((x >> 150) + p)
r  = x + ((-y + 0.5) << 153) + p
out(r)

可是为什么会这样改呢?因为。。我觉得 I 全在前面没有问题啊。。

那为什么 O 不要都在后面呢。。

这个。。哎呀。。 不要在意那些细节。。

于是生成的代码是

I
C 1 0.000000000000000000000000000001
< 2 500
S 3
< 4 152
> 1 150
+ 6 5
S 7
- 8
C 9 0.5
< 10 153
+ 1 11
+ 12 5
O 13

表达式的语法大家自己体会体会吧 orz,网页上也有一个 help

(话说可以改进呢,泥萌如果想要的话我可以搞几个优先级不一样的 shl shr cmp max 之类的保留字运算符出来啊,大家有意可以在下面讨论)

后来的变量会隐藏前面的变量,所以排序那题就不用生成一大堆临时名字了

写完之后点那个 [Share your fleas] 然后地址栏里就是一个自带代码的网址了,然后就可以 Share 了。哎呀好像有点长。。

然后目前有两个优化:

  • 如果整个子表达式或者整个变量就是个常数,它会被尽量内联,同时造成精度损失(额)。如果真的需要常量节点的话,这么算:$C = (\texttt{in(1)} \gg 10000) + C$

    (以下是一点题外话)

      $ cat compute.out 
      I
      > 1 10000
      O 2
      $ ./checker -f compute.out
      1
      0.000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001

    但是 $2^{-10000} \approx 5.0124\times 10^{-3011}$

  • 公用子表达式消除!Common sub-expression elimination, CSE。发现重复出现的表达式可以避免重复计算。

具体可以见默认的样例代码。

文件的话有这些

  • http://dram.cf/flea-compiler/
    • vendor/decimal.min.js
    • index.html
    • parse.pegjs
    • parse.jsparse.pegjs 生成
    • compiler.js

评论

WrongAnswer
orz 好像很神奇的样子。 (表示不会做那东西……果断写C++代码)
ruanxingzhi
您这是解释器啊QAQ
Picks
23333有趣!@vfleaking
xia_xue_QAQ
dram大佬好厉害QAQ无限Orz(Orz)*

发表评论

可以用@mike来提到mike这个用户,mike会被高亮显示。如果你真的想打“@”这个字符,请用“@@”。