Skip to content

myzsyweb/Casuistry

Repository files navigation

一个简单的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》

施工中TODO

  • 更多的测试代码
  • 改进语句宏
  • 引入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

使用

Changelog

Nov.2011~

阶段一

实现了主要的功能

Nov.25

第一个版本,可以定义阶乘(递归)函数然后计算,一般的表达式计算也。 用正则模拟lex,手写的递归下降解析器,read函数,以及基本的eval。 可define可lambda,可用Python或Scheme来预定义环境。

Nov.27

实现内部宏,方便扩充语法了,跑了一个计算24的代码,很慢很花内存。 现在的预定义的函数是用到一个就加进去一个,已经工作很良好了。

Nov.28

单独实现了初步支持call/cc的eval版本,之后建立导出的API的时候再来合并代码吧。 如果call/cc支持多返回值的话,又得重实现一个eval了,虽然代码可照搬。

Nov.29

用Trampoline让eval可以尾递归,函数尾部自己调用自己不再StackOverflow了。 另外让py可以调用scm里面返回的lambda表达式了,最然暂且只是序列形式的参数。

阶段二

对代码进行整理和修补

Nov.30

调整API来独立出测试代码,Repl也以单独的文件提供,顺带合并代码和功能。 独立当前版本的eval函数及相关代码,移除对先前版本的依赖,引用移到新的实现上。

Dec.1

可通过内部定义的全局Macro来扩展eval的行为,并可用Scm文件提供预定义过程。 稍稍整理了一下预定义的过程,不过其实这个不是很必要,可以到需要时再定义。

Dec.2

补完quasiquote词法,不过目前都是些不大要紧调整,无非就是在现有实现上改改代码了。 看来可以有另一条思路并行来实现一些新的东西了,比如正考虑尝试支持代码生成版本。

Dec.3

为quasiquote词法引入相应的宏实现,驳接了TinyScheme里面的相应宏的代码。 测试发现不小心出bug了,原因是当前‘string?’的判断只是一个替代实现,不严格。

Dec.5-7

导入了Psyche和Sisc的测试代码,看着满屏幕的Fail和Error给人充满干劲的样子。 词法实现了字符类型的识别,实现了let*,letrec宏,合并TinyScheme部分Scheme过程。 补完了一些没有实现的预置过程,fix了一些语义上的错误,不过其实还没做完,就这样。

Dec.8

修补清理了一些测试中的问题,于是现在性能成大问题了,而且debug困难,看来可以准备基础性的调整了。 需要整理代码结构,调整预置类型,调整预置过程并调整预置宏,目标是IEEE标准以及与Python的混用。

阶段三

添加一些其他的扩展功能

想法

给编译期一个env用来执行代码,独立出AST类型。

TODO2

  • 只做TODO1里面的事情

优先级不高的TODO

  • 参照IEEE标准补充预定义过程和测试代码
  • 和Py的混合使用
  • 定义导出的API
  • 用list取代dict实现Env类型,增强抽象语法的生成
  • 在AST中保留代码信息,以加强错误提示
  • 一部分运算和分支转移到编译时进行
  • 基于unicode的字符串,注意和Py类型混用的情况
  • 词法中的#
  • 合并相同功能的不同实现
  • 规范一下抛出异常的类型
  • 模块化代码
  • quote词法以及宏
  • pypy
  • 持久化和dump
  • R5RS宏的宏
  • 运行时词法作用域宏与Lazy
  • 让env成为first-class
  • call/cc和预置过程混合使用的情况
  • Android上运行
  • 静态的env分析
  • delay和stream

优先级更不高的TODO

  • 性能啊
  • 整理代码
  • define-syntax词法作用域或者预处理
  • 内部marco
  • 词法和句法中的’#’
  • 代码生成
  • 调用PyGame
  • 调用HttpServer/Bottle/flask
  • 除‘null?’外以’?’结尾的过程
  • 以’?’结尾的过程正确判断不相交的类型
  • 区分#t#f‘()但是要使用Python内置类型,保证能互相调用
  • pprint
  • 语法前端
  • TTK_GUI

不想添加的功能

  • 所有’!’结尾的过程
  • io相关的过程
  • 交互中提供eval过程
  • 交互中提供macro相关
  • 除eq?外的无泛型的eq过程

R5RS以外的扩展TODO

  • 混合OCaml和Python风格的语法前端
  • 基于透明结构和Overload的对象机制
  • 运行过程中的流程rewrite
  • 模块和包
  • 简化用作数据配置文件
  • 单独的全局作用域*set*!,用于set!,不可define

代码原则

  • 保持简单
  • 不必要遵守以下代码原则
  • 能暂时不实现的功能就不去实现它,可以不实现的就不实现,能推迟的改动尽量推迟
  • 推迟可能的rename,很麻烦且没必要,重在另一个模块里定义倒是可以的
  • 当功能有眼前看得见的好处的时候才去实现它,比如实现另一个功能用到
  • 优先考虑实现新的功能,即使重构也是整理新版本出来,切勿做出多余的事情来
  • 对函数的参数和返回值的类型进行限定,要求特定的类型的子类或者特定的类型的并集
  • 写测试分解测试然后实现,特别是实现新功能的时候,测试过的只做修补和添加分派
  • 有大的改动时,重写新的版本的函数,不改变已写代码的命名和行为习惯
  • 不论需求怎么多样化,保持一个最平坦最原始最简陋的core模块
  • 不看注释也要很容易看明白代码,通过细分函数的功能约束副作用以及测试代码
  • 一个过程限制在最小的功能和行数,额外的扩展可以写一个依赖它的新过程
  • 将每个过程尽可能细分为单个表达式的逻辑,在一个函数内减少有次序依赖的逻辑
  • 导出的API可以以后修改,旧的实现的接口在有更新时可以重构到新的实现上
  • 别用OO堆结构,按照测试实现接口的顺序,实现少量的method并用异常减少重复的条件判断
  • 在没有测试覆盖工具的时候,不能判断执行正确地方简单实现,执行时抛出异常
  • 优先考虑写在代码开头的说明文件

链接

About

Casuistry Scheme

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published