一个简单的Python制Scheme实现
Programming languages should be designed not by piling feature on top of feature, but by removing the weaknesses and restrictions that make additional features appear necessary. Scheme demonstrates that a very small number of rules for forming expressions, with no restrictions on how they are composed, suffice to form a practical and efficient programming language that is flexible enough to support most of the major programming paradigms in use today. ——摘自《R5RS·Introduction》
- 更多的测试代码
- 改进语句宏
- 引入syntax-rule/case实现
- slib支持
- 改善错误提示,对语句错误给出合理提示
- 代码生成
- 移植其他Scm实现中的测试代码
- 简化宏展开过程
- foreach和let的bug
- 测试amb功能
- 调整内置类型
- 复数和向量类型
- 区分精确和非精确数字类型
- Python2 的整数除法问题
- 区分字符串,字符类型和符号类型
- 识别字符串中的转码
- 注意和Python内置类型的混合使用
- 分离多参数apply的实现为单独的过程(宏?)
- 把全局环境作为build和eval的参数,即取消全局环境
一个简单的Python制Scheme实现
- 名称
- Casuistry Scheme
- 用途
- 娱乐
- 作者
- ee.zsy
no`!’ scope tail-call call/cc
坑
Nov.2011~
实现了主要的功能
第一个版本,可以定义阶乘(递归)函数然后计算,一般的表达式计算也。 用正则模拟lex,手写的递归下降解析器,read函数,以及基本的eval。 可define可lambda,可用Python或Scheme来预定义环境。
实现内部宏,方便扩充语法了,跑了一个计算24的代码,很慢很花内存。 现在的预定义的函数是用到一个就加进去一个,已经工作很良好了。
单独实现了初步支持call/cc的eval版本,之后建立导出的API的时候再来合并代码吧。 如果call/cc支持多返回值的话,又得重实现一个eval了,虽然代码可照搬。
用Trampoline让eval可以尾递归,函数尾部自己调用自己不再StackOverflow了。 另外让py可以调用scm里面返回的lambda表达式了,最然暂且只是序列形式的参数。
对代码进行整理和修补
调整API来独立出测试代码,Repl也以单独的文件提供,顺带合并代码和功能。 独立当前版本的eval函数及相关代码,移除对先前版本的依赖,引用移到新的实现上。
可通过内部定义的全局Macro来扩展eval的行为,并可用Scm文件提供预定义过程。 稍稍整理了一下预定义的过程,不过其实这个不是很必要,可以到需要时再定义。
补完quasiquote词法,不过目前都是些不大要紧调整,无非就是在现有实现上改改代码了。 看来可以有另一条思路并行来实现一些新的东西了,比如正考虑尝试支持代码生成版本。
为quasiquote词法引入相应的宏实现,驳接了TinyScheme里面的相应宏的代码。 测试发现不小心出bug了,原因是当前‘string?’的判断只是一个替代实现,不严格。
导入了Psyche和Sisc的测试代码,看着满屏幕的Fail和Error给人充满干劲的样子。 词法实现了字符类型的识别,实现了let*,letrec宏,合并TinyScheme部分Scheme过程。 补完了一些没有实现的预置过程,fix了一些语义上的错误,不过其实还没做完,就这样。
修补清理了一些测试中的问题,于是现在性能成大问题了,而且debug困难,看来可以准备基础性的调整了。 需要整理代码结构,调整预置类型,调整预置过程并调整预置宏,目标是IEEE标准以及与Python的混用。
添加一些其他的扩展功能
给编译期一个env用来执行代码,独立出AST类型。
- 只做TODO1里面的事情
- 参照IEEE标准补充预定义过程和测试代码
- 和Py的混合使用
- 定义导出的API
- 用list取代dict实现Env类型,增强抽象语法的生成
- 在AST中保留代码信息,以加强错误提示
- 一部分运算和分支转移到编译时进行
- 基于unicode的字符串,注意和Py类型混用的情况
- 词法中的#
- 合并相同功能的不同实现
- 规范一下抛出异常的类型
- 模块化代码
- quote词法以及宏
- pypy
- 持久化和dump
- R5RS宏的宏
- 运行时词法作用域宏与Lazy
- 让env成为first-class
- call/cc和预置过程混合使用的情况
- Android上运行
- 静态的env分析
- delay和stream
- 性能啊
- 整理代码
- define-syntax词法作用域或者预处理
- 内部marco
- 词法和句法中的’#’
- 代码生成
- 调用PyGame
- 调用HttpServer/Bottle/flask
- 除‘null?’外以’?’结尾的过程
- 以’?’结尾的过程正确判断不相交的类型
- 区分#t#f‘()但是要使用Python内置类型,保证能互相调用
- pprint
- 语法前端
- TTK_GUI
- 所有’!’结尾的过程
- io相关的过程
- 交互中提供eval过程
- 交互中提供macro相关
- 除eq?外的无泛型的eq过程
- 混合OCaml和Python风格的语法前端
- 基于透明结构和Overload的对象机制
- 运行过程中的流程rewrite
- 模块和包
- 简化用作数据配置文件
- 单独的全局作用域*set*!,用于set!,不可define
- 保持简单
- 不必要遵守以下代码原则
- 能暂时不实现的功能就不去实现它,可以不实现的就不实现,能推迟的改动尽量推迟
- 推迟可能的rename,很麻烦且没必要,重在另一个模块里定义倒是可以的
- 当功能有眼前看得见的好处的时候才去实现它,比如实现另一个功能用到
- 优先考虑实现新的功能,即使重构也是整理新版本出来,切勿做出多余的事情来
- 对函数的参数和返回值的类型进行限定,要求特定的类型的子类或者特定的类型的并集
- 写测试分解测试然后实现,特别是实现新功能的时候,测试过的只做修补和添加分派
- 有大的改动时,重写新的版本的函数,不改变已写代码的命名和行为习惯
- 不论需求怎么多样化,保持一个最平坦最原始最简陋的core模块
- 不看注释也要很容易看明白代码,通过细分函数的功能约束副作用以及测试代码
- 一个过程限制在最小的功能和行数,额外的扩展可以写一个依赖它的新过程
- 将每个过程尽可能细分为单个表达式的逻辑,在一个函数内减少有次序依赖的逻辑
- 导出的API可以以后修改,旧的实现的接口在有更新时可以重构到新的实现上
- 别用OO堆结构,按照测试实现接口的顺序,实现少量的method并用异常减少重复的条件判断
- 在没有测试覆盖工具的时候,不能判断执行正确地方简单实现,执行时抛出异常
- 优先考虑写在代码开头的说明文件
- SICP
- IEEE 1178
- R5RS
- Lambda Paper
- tinyscheme
- scm/slib
- biwascheme
- pyscheme
- psyche
- Heist