;; A simple CPS transformer which does proper tail-call and does not

;; duplicate contexts for if-expressions.

;;author : Yin Wang(yw21@cs.indiana.edu)

(load "pmatch.scm")

(define cps
  (lambda (exp)
    (letrec
      ([trivial? (lambda (x) (memq x '(zero? add1 sub1)))]
       [id (lambda (v) v)]
       [ctx0 (lambda (v) `(k ,v))] ; tail context
       [fv (let ([n -1])
        (lambda ()
          (set! n (+ 1 n))
          (string->symbol (string-append "v" (number->string n)))))]
      [cps1
        (lambda (exp ctx)
        (pmatch exp
          [,x (guard (not (pair? x))) (ctx x)]
          [(if ,test ,conseq ,alt)
           (cps1 test
            (lambda (t)
              (cond

                [(memq ctx (list ctx0 id))

                `(if ,t ,(cps1 conseq ctx) ,(cps1 alt ctx))]
                [else
                  (let ([u (fv)])
                  `(let ([k (lambda (,u) ,(ctx u))])
                    (if ,t ,(cps1 conseq ctx0) ,(cps1 alt ctx0))))])))]
      [(lambda (,x) ,body)
        (ctx `(lambda (,x k) ,(cps1 body ctx0)))]
      [(,op ,a ,b)
        (cps1 a (lambda (v1)
          (cps1 b (lambda (v2)
             (ctx `(,op ,v1 ,v2))))))]
      [(,rator ,rand)
       (cps1 rator
        (lambda (r)
          (cps1 rand
            (lambda (d)
            (cond
              [(trivial? r) (ctx `(,r ,d))]
              [(eq? ctx ctx0) `(,r ,d k)]     ; ;tail call
                [else
                  (let ([u (fv)])
                    `(,r ,d (lambda (,u) ,(ctx u))))])))))]))])
      (cps1 exp id))))

;;; tests

;; var
(cps 'x)
(cps '(lambda (x) x))
(cps '(lambda (x) (x 1)))

;; no lambda (will generate identity functions to return to the toplevel)
(cps '(if (f x) a b))
(cps '(if x (f a) b))

;; if stand-alone (tail)
(cps '(lambda (x) (if (f x) a b)))

;; if inside if-test (non-tail)
(cps '(lambda (x) (if (if x (f a) b) c d)))

;; both branches are trivial, should do some more optimizations
(cps '(lambda (x) (if (if x (zero? a) b) c d)))

;; if inside if-branch (tail)
(cps '(lambda (x) (if t (if x (f a) b) c)))

;; if inside if-branch, but again inside another if-test (non-tail)
(cps '(lambda (x) (if (if t (if x (f a) b) c) e w)))

;; if as operand (non-tail)
(cps '(lambda (x) (h (if x (f a) b))))

;; if as operator (non-tail)
(cps '(lambda (x) ((if x (f g) h) c)))

;; why we need more than two names
(cps '(((f a) (g b)) ((f c) (g d))))

;; factorial
(define fact-cps
(cps
'(lambda (n)
((lambda (fact)
((fact fact) n))
(lambda (fact)
(lambda (n)
(if (zero? n)
1
(* n ((fact fact) (sub1 n))))))))))

;; print out CPSed function
(pretty-print fact-cps)
;; =>
;; '(lambda (n k)
;; ((lambda (fact k) (fact fact (lambda (v0) (v0 n k))))
;; (lambda (fact k)
;; (k
;; (lambda (n k)
;; (if (zero? n)
;; (k 1)
;; (fact
;; fact
;; (lambda (v1) (v1 (sub1 n) (lambda (v2) (k (* n v2))))))))))
;; k))

((eval fact-cps) 5 (lambda (v) v))
;; => 120

王垠-40行代码 -cps.ss的更多相关文章

  1. 分享一个开源的JavaScript统计图表库,40行代码实现专业统计图表

    提升程序员工作效率的工具/技巧推荐系列 推荐一个功能强大的文件搜索工具SearchMyFiles 介绍一个好用的免费流程图和UML绘制软件-Diagram Designer 介绍Windows任务管理 ...

  2. 王垠的40行代码,究竟diao在哪里

    王垠是谁? 不用我说了吧!!! 别傻谈,亮码瞧! ;; A simple CPS transformer which does proper tail-call and does not;; dupl ...

  3. Python人脸识别最佳教材典范,40行代码搭建人脸识别系统!

    Face Id是一款高端的人脸解锁软件,官方称:"在一百万张脸中识别出你的脸."百度.谷歌.腾讯等各大企业都花费数亿来鞭策人工智能的崛起,而实际的人脸识别技术是否有那么神奇? 绿帽 ...

  4. jquery轮播图详解,40行代码即可简单解决。

    我在两个月以前没有接触过html,css,jquery,javascript.今天我却在这里分享一篇技术贴,可能在技术大牛面前我的文章漏洞百出,也请斧正. 可以看出来,无论是div+css布局还是jq ...

  5. 40行代码爬取猫眼电影TOP100榜所有信息

    主要内容: 一.基础爬虫框架的三大模块 二.完整代码解析及效果展示 1️⃣  基础爬虫框架的三大模块 1.HTML下载器:利用requests模块下载HTML网页. 2.HTML解析器:利用re正则表 ...

  6. 女朋友汇总表格弄了大半天,我实在看不下去了,用40行代码解决问题 | Python使用openpyxl库读写表格Excel(xlsx)

    1.openpyxl基本操作 python程序从excel文件中读数据基本遵循以下步骤: 1.import openpyxl 2.调用openpyxl模块下的load_workbook('你的文件名. ...

  7. 带大家用40行python代码实现一个疫情地图

    最近两个月,因为新冠病毒无情的肆虐,相信会给每个中国人的记忆中画上重重的一笔.到今天为止,疫情形势依然十分严峻,虽然除湖北外的其他省份已经连续十一天确诊人数下降,但是接下来还有将近至少1.6亿的人口迁 ...

  8. 一个只有99行代码的JS流程框架

    张镇圳,腾讯Web前端高级工程师,对内部系统前端建设有多年经验,喜欢钻研捣鼓各种前端组件和框架. 最近一直在想一个问题,如何能让js代码写起来更语义化和更具有可读性. 上周末的时候突发奇想,当代码在运 ...

  9. 王垠:完全用Linux工作

    来自: Zentaur(alles klar) 录一篇旧文 作者:王垠 完全用Linux工作,抛弃windows 我已经半年没有使用 Windows 的方式工作了.Linux 高效的完成了我所有的工作 ...

随机推荐

  1. [BZOJ2038]:[2009国家集训队]小Z的袜子(hose)(离线莫队)

    题目传送门 题目描述 作为一个生活散漫的人,小$Z$每天早上都要耗费很久从一堆五颜六色的袜子中找出一双来穿.终于有一天,小Z再也无法忍受这恼人的找袜子过程,于是他决定听天由命……具体来说,小$Z$把这 ...

  2. 移动端与PHP服务端接口通信流程设计(基础版)

    转载自:http://blog.snsgou.com/post-766.html --->非开放性平台 --->公司内部产品 接口特点汇总: 1.因为是非开放性的,所以所有的接口都是封闭的 ...

  3. 设计 4 个线程,其中两个线程每次对 j 增加 1,另外两个线程对 j 每次减少 1。写出程序。

    先设计一个类处理加减这一行为: public class ManyThread { private int j = 0; public synchronized void inc(){ j++; Sy ...

  4. 北风设计模式课程---单一职责原则(Single Responsibility Principle)

    北风设计模式课程---单一职责原则(Single Responsibility Principle) 一.总结 一句话总结: 一个类应该有且只有一个变化的原因:单一职责原则(SRP:Single Re ...

  5. LuceneNET全文检索封装

    一.源码特点       1.  Lucene.net是Lucene的.net移植版本,是一个开源的全文检索引擎开发包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎 ...

  6. Android传感器系统架构【转】

    本文转载自:http://blog.csdn.net/qianjin0703/article/details/5942579 版权声明:本文为博主原创文章,未经博主允许不得转载. 1. 体系结构 2. ...

  7. BeautifulSoup模块学习文档

    一.BeautifulSoup简介 1.BeautifulSoup模块 Beautiful Soup 是一个可以从HTML或XML文件中提取数据的Python库.它能够通过你喜欢的转换器实现惯用的文档 ...

  8. Win7下64位机安装SQL2000

    win7下64位机安装SQLSERVER20001.右击计算机属性,查看操作系统 2.打开安装文件夹,按图点击 3.开始安装 4. 下一步选择 安装SQL Server2000 组件 5. 下一步 选 ...

  9. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_05 IO字符流_3_字符输出流_Writer类&FileWriter类

  10. 测开之路一百一十:bootstrap图片

    bootstrap图片 引入bootstrap 原版的图片 bootstrap处理后的: 圆角.圆形.缩略图 自适应窗口