新手,写了个简单的Lisp 解释器 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
爱意满满的作品展示区。
tioover
V2EX    分享创造

新手,写了个简单的Lisp 解释器

  •  
  •   tioover
    tioover 2013-09-01 01:23:21 +08:00 6471 次点击
    这是一个创建于 4482 天前的主题,其中的信息可能已经有所发展或是发生改变。
    https://github.com/tioover/schepy/tree/master

    其实我Scheme 不怎么会,SICP 才正在看第二章,不过有一天心血来潮想要写一个解释器,于是照着[一个知乎上的回答]( http://www.zhihu.com/question/20115358/answer/15350593 )开始写了。写完了要测试,连运行多条表达式都不会,然后才找到begin 给解释器加上。几秒前我才发现这篇文章( http://www.googies.info/articles/lispy.html )

    本来是很简单的东西,但是我水平挺臭写了四天,不包括测试用例一共四百多行。原本以为最难的部分是函数,像作用域啊,递归啊什么的,但是没想到(或者说果然),在求值器删删改改了以后,函数这一块反而一两个小时就弄好了。

    ## 已知问题

    有些打算慢慢在这几天解决,有些打算边学边在今明年解决,有些可能永远也不会解决了(Python 最大递归深度……)。

    * 我连标准都还没看过。
    * 仅仅是个玩具,大量功能缺失:向量、尾递归优化、符号、eval、元编程。
    * 很多语法糖不能使用,而且只能严格按照S-表达式,比如说只能用 (cons x y) 定义序对,(define foobar (lambda ...)) 定义函数。
    * 参数只能用列表的形式:(lambda (a b c) ...)
    * 错误信息不完善,有些地方还忘了写异常(这里记一下:函数的参数个数。)
    * 如果在上下文中找不到,那就会直接在Python 中eval,可以弄出各种诡异的东西,需要用正则表达式判断类型再eval。
    * 为了获取链表的长度(len(li)),会多一次对链表的遍历。
    * Python 的最大递归深度限制。
    * 重写求值器以后忘了写处理符号的部分了。因为符号的类型已经写好了所以很好弄。
    第 1 条附言    2013-09-01 17:44:50 +08:00
    附一副图XD 因为用的是Python 3 所以Unicode 不在话下。

    第 2 条附言    2013-09-05 02:50:05 +08:00
    好激动,我做到了,尾递归优化~~~~ Python 的最大递归深度限制你看看你

    8 条回复    1970-01-01 08:00:00 +08:00
    felix021
        1
    felix021  
       2013-09-01 02:13:09 +08:00
    赞。。我就是为了解释器去看SICP的,现在看到3.3.5了,好艰辛……
    cxe2v
        2
    cxe2v  
       2013-09-01 09:27:12 +08:00
    牛逼,都能写解释器了就不能叫新手了,绝对是老手
    tioover
        3
    tioover  
    OP
       2013-09-01 17:36:50 +08:00
    昨天今天解决了一些问题:
    * define 惰性求值。
    * 符号,eval,判断类型
    * 一些错误提示
    * 之前字符串里面如果有空格会出错,现在修复了,不过词法分析器现在用了一些正则表达式。
    * 一些语法糖,可以直接用define 来定义函数了,不需要define lambda。也可以用(a . b) 定义序对了。
    JackLinMaker
        4
    JackLinMaker  
       2013-09-02 10:04:00 +08:00
    改天我写个ruby的:)
    yuelang85
        5
    yuelang85  
       2013-09-02 10:05:19 +08:00
    cool
    gadmyth
        6
    gadmyth  
       2013-09-02 13:06:48 +08:00
    Lisp还支持变量为unicode的,不知楼主是否支持
    tioover
        7
    tioover  
    OP
       2013-09-03 01:05:23 +08:00
    搞错define 的语法了,还以为函数定义函数名要单独写一个原子(define foobar (x) ()),结果不用,已经修复了。还有对于define 要惰性求值也是因此而起的误解(SICP 习题1.5)

    今天开了个dev 分支,新功能都写在里面,没问题了再合并,刚刚支持了词法闭包……其实就是在定义函数的时候复制一部分环境呗。

    明天打算试试看尾递归优化。
    tioover
        8
    tioover  
    OP
       2013-09-05 19:20:13 +08:00
    尾递归原本只是对函数体归约的思路,不过 提醒了我蹦跳床函数,这个东西专门把尾递归栈转化成循环,不错。

    昨天把尾递归给弄好了,今天迷迷糊糊的已经忘了昨天的思路了,但是测试了一下工作正常,尾递归计算过程中内存占用也比较稳定,那就好了。

    不过效率令人发指,和racket 比较了一下,差了人家百倍吧,还是递归空转的效率,不过也就是一个练习用的东西。

    嗯,总之作为一个练习项目差不多是完成了的,之后是修修补补了吧,有空把里面的递归都变成循环,毕竟Python 不提倡递归。

    打算SICP 大成以后用C 写一个,最好能编译……
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5303 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 06:42 PVG 14:42 LAX 22:42 JFK 01:42
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86