razyk 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/LICENSE ADDED
@@ -0,0 +1,56 @@
1
+ RazyK is copyrighted free software by Tomoyuki Chikanaga <nagachika00@gmail.com>.
2
+ You can redistribute it and/or modify it under either the terms of the
3
+ 2-clause BSDL (see the file BSDL), or the conditions below:
4
+
5
+ 1. You may make and give away verbatim copies of the source form of the
6
+ software without restriction, provided that you duplicate all of the
7
+ original copyright notices and associated disclaimers.
8
+
9
+ 2. You may modify your copy of the software in any way, provided that
10
+ you do at least ONE of the following:
11
+
12
+ a) place your modifications in the Public Domain or otherwise
13
+ make them Freely Available, such as by posting said
14
+ modifications to Usenet or an equivalent medium, or by allowing
15
+ the author to include your modifications in the software.
16
+
17
+ b) use the modified software only within your corporation or
18
+ organization.
19
+
20
+ c) give non-standard binaries non-standard names, with
21
+ instructions on where to get the original software distribution.
22
+
23
+ d) make other distribution arrangements with the author.
24
+
25
+ 3. You may distribute the software in object code or binary form,
26
+ provided that you do at least ONE of the following:
27
+
28
+ a) distribute the binaries and library files of the software,
29
+ together with instructions (in the manual page or equivalent)
30
+ on where to get the original distribution.
31
+
32
+ b) accompany the distribution with the machine-readable source of
33
+ the software.
34
+
35
+ c) give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 4. You may modify and include the part of the software into any other
41
+ software (possibly commercial). But some files in the distribution
42
+ are not written by the author, so that they are not under these terms.
43
+
44
+ For the list of those files and their copying conditions, see the
45
+ file LEGAL.
46
+
47
+ 5. The scripts and library files supplied as input to or produced as
48
+ output from the software do not automatically fall under the
49
+ copyright of the software, but belong to whomever generated them,
50
+ and may be sold commercially, and may be aggregated with this
51
+ software.
52
+
53
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
54
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
55
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
56
+ PURPOSE.
data/README.rdoc ADDED
@@ -0,0 +1,17 @@
1
+ = RazyK
2
+
3
+ RazyK is a LazyK implementation by pure ruby.
4
+
5
+ == LazyK
6
+ LazyK is referentially transparent functional programming language.
7
+ * LazyK programs are expressed by only S, K, I combinators
8
+ * Lazy evaluation
9
+ * Stream I/O system
10
+
11
+ For details, see website bellow.
12
+
13
+ http://homepages.cwi.nl/~tromp/cl/lazy-k.html
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 nagachika. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,62 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "razyk"
8
+ gem.summary = %Q{pure ruby LazyK implementation}
9
+ gem.description = %Q{RazyK is a LazyK implementetion by pure ruby}
10
+ gem.email = "nagachika00@gmail.com"
11
+ gem.homepage = "http://github.com/nagachika/razyk"
12
+ gem.authors = ["nagachika"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ gem.add_dependency "rack"
15
+ gem.add_dependency "ruby-graphviz"
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
+ end
22
+
23
+ begin
24
+ require 'spec/rake/spectask'
25
+ Spec::Rake::SpecTask.new(:spec) do |spec|
26
+ spec.libs << 'lib' << 'spec'
27
+ spec.spec_files = FileList['spec/**/*_spec.rb']
28
+ end
29
+
30
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
31
+ spec.libs << 'lib' << 'spec'
32
+ spec.pattern = 'spec/**/*_spec.rb'
33
+ spec.rcov = true
34
+ end
35
+
36
+ task :spec => :check_dependencies
37
+ rescue LoadError
38
+ require "rspec/core/rake_task"
39
+ RSpec::Core::RakeTask.new(:spec)
40
+
41
+ RSpec::Core::RakeTask.new(:rcov) do |t|
42
+ t.rcov_opts = %q[--exclude "spec"]
43
+ end
44
+
45
+ task :spec => :check_dependencies
46
+ end
47
+
48
+ task :default => :spec
49
+
50
+ require 'rake/rdoctask'
51
+ Rake::RDocTask.new do |rdoc|
52
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
53
+
54
+ rdoc.rdoc_dir = 'rdoc'
55
+ rdoc.title = "razyk #{version}"
56
+ rdoc.rdoc_files.include('README*')
57
+ rdoc.rdoc_files.include('lib/**/*.rb')
58
+ end
59
+
60
+ task :racc => [ "lib/razyk/parser.y" ] do
61
+ sh "racc -o lib/razyk/parser.rb lib/razyk/parser.y"
62
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.0
data/bin/razyk ADDED
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "razyk"
4
+ require "optparse"
5
+
6
+ module RazyK
7
+ class Application
8
+ def initialize
9
+ @program = nil
10
+ @step = false
11
+ @web_server = false
12
+ @optparse = option_parser
13
+ end
14
+
15
+ def option_parser
16
+ OptionParser.new do |opt|
17
+ opt.on("-e 'program'",
18
+ "specify LazyK program string. Omit [programfile]") do |prog|
19
+ @program = prog
20
+ end
21
+ opt.on("-s", "--step", "step execution. Dump combinator tree by each step") do
22
+ @step = true
23
+ end
24
+ opt.on("--server [PORT]", "start web server") do |port|
25
+ @port = Integer(port || 9292)
26
+ @step = true
27
+ @web_server = true
28
+ end
29
+ end
30
+ end
31
+ private :option_parser
32
+
33
+ def run(argv)
34
+ @optparse.parse!(argv)
35
+
36
+ if @web_server
37
+ require "razyk/webapp"
38
+ app = RazyK::WebApp.new
39
+ # This should work, but rack-1.2.1 fails. :app don't overwrite config.ru
40
+ #Rack::Server.start(:app => app, :Port => @port)
41
+ trap(:INT) do
42
+ if Rack::Handler::WEBrick.respond_to?(:shutdown)
43
+ Rack::Handler::WEBrick.shutdown
44
+ else
45
+ exit
46
+ end
47
+ end
48
+ Rack::Handler::WEBrick.run(app, :Port => @port)
49
+ return
50
+ end
51
+
52
+ if @program.nil?
53
+ if argv.empty?
54
+ raise "please specify LazyK program file"
55
+ end
56
+ filepath = argv.shift
57
+ @program = IO.read(filepath)
58
+ end
59
+
60
+ if @step
61
+ RazyK.run(@program) do |vm|
62
+ $stderr.puts vm.tree.inspect
63
+ end
64
+ else
65
+ RazyK.run(@program)
66
+ end
67
+ end
68
+ end
69
+ end
70
+
71
+ app = RazyK::Application.new
72
+ app.run(ARGV)
@@ -0,0 +1,328 @@
1
+ ;;
2
+ ;; Lazier, a "compiler" from lambda calculus to Lazy K.
3
+ ;; Copyright 2002 Ben Rudiak-Gould. Distributed under the GPL.
4
+ ;;
5
+ ;; Usage examples:
6
+ ;;
7
+ ;; > (lazy-def '(myprog input) '(cdr (cdr input))) ; drops first two bytes of input
8
+ ;; > (lazy-def 'myprog '(o cdr cdr)) ; equivalent definition
9
+ ;;
10
+ ;; > (laze 'myprog)
11
+ ;; ((s ((s i) (k (k i)))) (k (k i)))
12
+ ;;
13
+ ;; > (print-as-cc (laze 'myprog))
14
+ ;; S(SI(K(KI)))(K(KI))
15
+ ;;
16
+ ;; > (print-as-unlambda (laze 'myprog))
17
+ ;; ``s``si`k`ki`k`ki
18
+ ;;
19
+ ;; > (print-as-iota (laze 'myprog))
20
+ ;; ***i*i*i*ii***i*i*i*ii*ii**i*i*ii**i*i*ii*ii**i*i*ii**i*i*ii*ii
21
+ ;;
22
+ ;; > (print-as-jot (laze 'myprog))
23
+ ;; 111111100011111110001111111110000011110011110011111111100000111100111100
24
+ ;; 11111111100000
25
+ ;;
26
+ ;; > (lazy-def '(f x y z) '(x (y z))) ; \
27
+ ;; > (lazy-def 'f '(lambda (x y z) '(x (y z)))) ; | equivalent
28
+ ;; > (lazy-def 'f '(lambda (x) (lambda (y) ...))) ; /
29
+ ;;
30
+ ;; > (laze '(f arg1 arg2))
31
+ ;; ((s (k arg1)) arg2)
32
+ ;;
33
+ ;; > (print-as-unlambda (laze '(f arg1 arg2)))
34
+ ;; ``s`k[arg1][arg2]
35
+ ;;
36
+
37
+
38
+ ; lazy-def.
39
+
40
+ (define lazy-defs '())
41
+
42
+ (define (lazy-def name body)
43
+ (set! lazy-defs
44
+ (cons (if (pair? name)
45
+ (cons (car name)
46
+ (curry-lambda (cdr name) (curry body)) )
47
+ (cons name (curry body)) )
48
+ lazy-defs )))
49
+
50
+ (define (lazy-def-lookup name)
51
+ (assv name lazy-defs) )
52
+
53
+
54
+ ; Currying.
55
+
56
+ (define (curry expr)
57
+ (cond ((not (pair? expr)) expr)
58
+ ((eq? (car expr) 'lambda)
59
+ (curry-lambda (cadr expr) (curry (caddr expr))) )
60
+ (else
61
+ (curry-app (map curry expr)) )))
62
+
63
+ (define (curry-lambda vars body)
64
+ (if (null? vars)
65
+ body
66
+ `(lambda (,(car vars)) ,(curry-lambda (cdr vars) body)) ))
67
+
68
+ (define (curry-app lst)
69
+ (let iter ((sofar (car lst))
70
+ (togo (cdr lst)) )
71
+ (if (null? togo)
72
+ sofar
73
+ (iter (list sofar (car togo)) (cdr togo)) )))
74
+
75
+
76
+ ; Macro expansion.
77
+
78
+ (define (expr-dispatch expr leaf appl lamb)
79
+ (if (pair? expr)
80
+ (if (eq? (car expr) 'lambda)
81
+ (lamb (caadr expr) (caddr expr))
82
+ (appl (car expr) (cadr expr)) )
83
+ (leaf expr) ))
84
+
85
+ (define (expand-macros expr)
86
+ (let helper ((expr expr) (exclude '()) (stack '()))
87
+ (expr-dispatch expr
88
+ (lambda (leaf)
89
+ (cond ((memv leaf exclude) leaf)
90
+ ((memv leaf stack)
91
+ (display "Recursion within lazy-defs detected: ")
92
+ (display (cons leaf stack))
93
+ (newline)
94
+ (error) )
95
+ (else
96
+ (let ((def (lazy-def-lookup leaf)))
97
+ (if def
98
+ (helper (cdr def) exclude (cons leaf stack))
99
+ leaf )))))
100
+ (lambda (f g)
101
+ (list (helper f exclude stack) (helper g exclude stack)) )
102
+ (lambda (var body)
103
+ `(lambda (,var) ,(helper body (cons var exclude) stack)) ))))
104
+
105
+
106
+ ; Replace ((lambda (var) body) value) with body[value/var] if:
107
+ ;
108
+ ; - value is a symbol, or
109
+ ; - var appears only once in body and value contains no
110
+ ; more than one free variable which is not in body.
111
+ ;
112
+ ; I'm not sure if the first of these is ever needed -- it may
113
+ ; always be handled by the other optimizations -- but it's easy
114
+ ; to check for.
115
+
116
+ (define (apply-lambdas expr)
117
+ (let ((top-level-free-vars (free-vars expr)))
118
+ (let self ((expr expr))
119
+ (expr-dispatch expr
120
+ (lambda (leaf) leaf)
121
+ (lambda (f g)
122
+ (let ((f: (self f))
123
+ (g: (self g)) )
124
+ (expr-dispatch f:
125
+ (lambda (leaf) (list f: g:))
126
+ (lambda (f:: g::) (list f: g:))
127
+ (lambda (var body)
128
+ (if (or (not (pair? g:))
129
+ (and (<= (count-occurrences var body) 1)
130
+ (not (more-than-one-additional
131
+ (free-vars g:)
132
+ (append top-level-free-vars (free-vars f:)) ))))
133
+ (var-subst var g: body)
134
+ (list f: g:) )))))
135
+ (lambda (var body)
136
+ `(lambda (,var) ,(self body)) )))))
137
+
138
+ (define (add-prime var)
139
+ (string->symbol (string-append (symbol->string var) ":")) )
140
+
141
+ (define (var-subst var value template)
142
+ (if (eqv? var value)
143
+ template
144
+ (let loop ((template template))
145
+ (expr-dispatch template
146
+ (lambda (leaf)
147
+ (if (eqv? var leaf) value leaf) )
148
+ (lambda (f g)
149
+ (list (loop f) (loop g)) )
150
+ (lambda (v body)
151
+ (if (eqv? var v)
152
+ template
153
+ (do ((template-vars (free-vars template))
154
+ (value-vars (free-vars value))
155
+ (v: v (add-prime v:)) )
156
+ ((and (not (memv v: template-vars))
157
+ (not (memv v: value-vars)) )
158
+ `(lambda (,v:)
159
+ ,(loop (var-subst v v: body)) )))))))))
160
+
161
+ (define (more-than-one-additional a b)
162
+ (let loop ((a a) (last-sym (cons #f #f)))
163
+ (cond ((null? a) #f)
164
+ ((memv (car a) b)
165
+ (loop (cdr a) last-sym) )
166
+ ((or (pair? last-sym) ; no last symbol
167
+ (eqv? last-sym (car a)) )
168
+ (loop (cdr a) (car a)) )
169
+ (else #t) )))
170
+
171
+ (define (free-vars expr)
172
+ (let loop ((expr expr) (bound ()))
173
+ (expr-dispatch expr
174
+ (lambda (leaf)
175
+ (if (memv leaf bound)
176
+ ()
177
+ (list leaf) ))
178
+ (lambda (f g)
179
+ (append (loop f bound) (loop g bound)) )
180
+ (lambda (var body)
181
+ (loop body (cons var bound)) ))))
182
+
183
+ (define (contains-free-variable param template)
184
+ (expr-dispatch template
185
+ (lambda (leaf)
186
+ (eqv? param leaf) )
187
+ (lambda (f g)
188
+ (or (contains-free-variable param f)
189
+ (contains-free-variable param g) ))
190
+ (lambda (var body)
191
+ (and (not (eqv? param var))
192
+ (contains-free-variable param body) ))))
193
+
194
+ (define (count-occurrences param template)
195
+ (expr-dispatch template
196
+ (lambda (leaf)
197
+ (if (eqv? param leaf) 1 0) )
198
+ (lambda (f g)
199
+ (+ (count-occurrences param f) (count-occurrences param g)) )
200
+ (lambda (var body)
201
+ (if (eqv? var param)
202
+ 0
203
+ (count-occurrences param body) ))))
204
+
205
+
206
+ ; Abstraction elimination.
207
+
208
+ (define (unabstract-lambda var body)
209
+ (if (contains-free-variable var body)
210
+ (expr-dispatch body
211
+ (lambda (leaf) 'i)
212
+ (lambda (f g)
213
+ (if (and (eqv? var g) (not (contains-free-variable var f)))
214
+ f
215
+ `((s ,(unabstract-lambda var f)) ,(unabstract-lambda var g)) ))
216
+ (lambda (v b)
217
+ (unabstract-lambda var (unabstract body)) ))
218
+ (list 'k body) ))
219
+
220
+ (define (unabstract code)
221
+ (expr-dispatch code
222
+ (lambda (leaf) leaf)
223
+ (lambda (f g)
224
+ (list (unabstract f) (unabstract g)) )
225
+ (lambda (var body)
226
+ (unabstract-lambda var (unabstract body)) )))
227
+
228
+
229
+ ; Reduces expressions involving the S, K, I combinators where this
230
+ ; results in a shorter expression. Usually results in only a small
231
+ ; benefit.
232
+
233
+ (define (apply-ski expr)
234
+ (if (not (pair? expr))
235
+ expr
236
+ (let ((lhs (apply-ski (car expr)))
237
+ (rhs (cadr expr)) )
238
+ (cond ((eq? lhs 'i) ; Ix -> x
239
+ (apply-ski rhs) )
240
+ ((and (pair? lhs) ; Kxy -> x
241
+ (eq? 'k (car lhs)) )
242
+ (cadr lhs) )
243
+ ((and (pair? lhs) ; Sxyz -> xz(yz) when x or y is K_
244
+ (pair? (car lhs))
245
+ (eq? 's (caar lhs)) )
246
+ (let ((z rhs)
247
+ (y (cadr lhs))
248
+ (x (cadar lhs)) )
249
+ (if (or (and (pair? x) (eq? (car x) 'k))
250
+ (and (pair? y) (eq? (car y) 'k)) )
251
+ (apply-ski `((,x ,z) (,y ,z)))
252
+ (list lhs (apply-ski rhs)) )))
253
+ (else
254
+ (list lhs (apply-ski rhs)) )))))
255
+
256
+
257
+ ; This converts expressions of the form ((x z) (y z)) to (s x y z).
258
+ ; If z is just a symbol, then this change makes no difference to
259
+ ; Unlambda output, always reduces the size of CC output (I think),
260
+ ; and can either increase or reduce the side of Iota and Jot output.
261
+ ; Currently the change is made only when z is not just a symbol.
262
+ ;
263
+ ; Like apply-ski, this gives only a small benefit in most cases.
264
+
265
+ (define (unapply-s expr)
266
+ (expr-dispatch expr
267
+ (lambda (leaf) leaf)
268
+ (lambda (f g)
269
+ (let ((f: (unapply-s f))
270
+ (g: (unapply-s g)) )
271
+ (if (and (pair? f:)
272
+ (pair? g:)
273
+ (pair? (cadr f:))
274
+ (equal? (cadr f:) (cadr g:)) )
275
+ `(((s ,(car f:)) ,(car g:)) ,(cadr f:))
276
+ (list f: g:) )))
277
+ (lambda (var body)
278
+ `(lambda (,var) ,(unapply-s body)) )))
279
+
280
+
281
+ ; Putting it all together.
282
+
283
+ (define (laze code)
284
+ (unapply-s (apply-ski (unabstract (apply-lambdas (expand-macros (curry code)))))) )
285
+
286
+
287
+ ; Printing it out.
288
+
289
+ (define (print-as-cc lazified-code)
290
+ (let self ((code lazified-code))
291
+ (expr-dispatch code
292
+ (lambda (leaf)
293
+ (if (memq leaf '(i k s))
294
+ (display (char-upcase (string-ref (symbol->string leaf) 0)))
295
+ (begin
296
+ (display "[")
297
+ (display leaf)
298
+ (display "]") )))
299
+ (lambda (f g)
300
+ (self f)
301
+ (if (pair? g) (display "("))
302
+ (self g)
303
+ (if (pair? g) (display ")")) )
304
+ (lambda (var body)
305
+ (error "Can't print lambdas as CC!") )))
306
+ (newline) )
307
+
308
+
309
+ (define (print-as-generic aply k s i)
310
+ (lambda (lazified-code)
311
+ (let self ((code lazified-code))
312
+ (expr-dispatch code
313
+ (lambda (leaf)
314
+ (cond ((eq? leaf 'i) (display i))
315
+ ((eq? leaf 'k) (display k))
316
+ ((eq? leaf 's) (display s))
317
+ (else (display "[") (display leaf) (display "]")) ))
318
+ (lambda (f g)
319
+ (display aply)
320
+ (self f)
321
+ (self g) )
322
+ (lambda (var body)
323
+ (error "Can't print lambdas as Lazy code!") )))
324
+ (newline) ))
325
+
326
+ (define print-as-unlambda (print-as-generic "`" "k" "s" "i"))
327
+ (define print-as-iota (print-as-generic "*" "*i*i*ii" "*i*i*i*ii" "*ii"))
328
+ (define print-as-jot (print-as-generic "1" "11100" "11111000" "11111111100000"))
@@ -0,0 +1,86 @@
1
+ ;; Some commonly useful macros for Lazier.
2
+ ;;
3
+ ;; There must not be any circular definitions here
4
+ ;; (e.g. a definition containing its own name). If
5
+ ;; you need recursion, you'll have to roll your own.
6
+ ;;
7
+ ;; Unfortunately, sometimes these functions have
8
+ ;; more than one form, and the one which is best for
9
+ ;; inlining is longer when not inlined. I know that
10
+ ;; this is the case for and, or, and list-of. In all
11
+ ;; three cases I picked the form preferable for
12
+ ;; inlining.
13
+
14
+ ;;; logic
15
+ (lazy-def #t '(lambda (x y) x))
16
+ (lazy-def #f '(lambda (x y) y))
17
+ (lazy-def '(if p x y) '(p x y))
18
+ (lazy-def '(not p) '(if p #f #t))
19
+ (lazy-def '(and p q) '(if p q #f))
20
+ (lazy-def '(or p q) '(if p #t q))
21
+
22
+ ;;; lists
23
+ (lazy-def '(cons x y) '(lambda (f) (f x y)))
24
+ (lazy-def '(car list) '(list #t))
25
+ (lazy-def '(cdr list) '(list #f))
26
+ (lazy-def () '(lambda (f) #t))
27
+ (lazy-def '(null? list) '(list (lambda (x y) #f)))
28
+ (lazy-def '(nth n lst) '(car ((n cdr) lst)))
29
+ (lazy-def '(list-ref lst n) '(nth n lst))
30
+
31
+ ;;; Church numerals (see also prelude-numbers.scm)
32
+ (lazy-def '(1+ a) '(lambda (f) (lambda (x) (f ((a f) x)))))
33
+ (lazy-def 'succ '1+)
34
+ (lazy-def 0 '(lambda (f) (lambda (x) x)))
35
+ (lazy-def 1 '(lambda (f) f))
36
+ (lazy-def 2 '(1+ 1))
37
+ (lazy-def 4 '((lambda (x) (x x)) 2))
38
+ (lazy-def 256 '((lambda (x) (x x)) 4))
39
+ (lazy-def '(+ a) '(a 1+))
40
+ (lazy-def '(* a b) '(lambda (f) (a (b f))))
41
+ (lazy-def '(^ a b) '(b a))
42
+ (lazy-def '(ifnonzero n x y) '((n (k x)) y))
43
+
44
+ (lazy-def '(= a b)
45
+ '(nth b ((a (cons #f))
46
+ (cons #t (list-of #f)) )))
47
+ (lazy-def '(!= a b)
48
+ '(nth b ((a (cons #t))
49
+ (cons #f (list-of #t)) )))
50
+
51
+ ; the following neat <= function is stolen from the Unlambda page
52
+ (lazy-def '(if<= m n x y) '((m ^ (k x)) (n ^ (k y))))
53
+ (lazy-def '(if> m n x y) '(if<= m n y x))
54
+ (lazy-def '(if>= m n x y) '(if<= n m x y))
55
+ (lazy-def '(if< m n x y) '(if<= n m y x))
56
+
57
+
58
+ ;;; miscellaneous
59
+
60
+ (lazy-def 'end-of-output '(lambda (f) 256))
61
+
62
+ (lazy-def 'list-from
63
+ '((lambda (x) (x x))
64
+ (lambda (self n)
65
+ (cons n (self self (1+ n))) )))
66
+
67
+ ; functional composition (same as *)
68
+ (lazy-def '(o f g) '(lambda (x) (f (g x))))
69
+
70
+ (lazy-def '(list-of elt)
71
+ '(Y (cons elt)) )
72
+
73
+ (lazy-def '(Y f)
74
+ '((lambda (x) (x x))
75
+ (lambda (self)
76
+ (f (self self)) )))
77
+
78
+ ; The following definition of the Y combinator is taken from
79
+ ; "Kolmogorov Complexity in Combinatory Logic" by John Tromp
80
+ ; (http://www.cwi.nl/~tromp/cl/CL.ps). It is shorter by itself,
81
+ ; but longer when applied. Interestingly, there is no way (that
82
+ ; I found) to produce this from a lambda expression using
83
+ ; Lazier. Specifically, Lazier can't figure out that
84
+ ; (lambda (y) (x (w y x))) is equivalent to SS(Sw)(Kx).
85
+
86
+ ;(lazy-def 'Y '(S S K (S (K (S S (S (S S K)))) K)))
@@ -0,0 +1,20 @@
1
+ K
2
+ (SII(S(K(S(S(K(SII(S(S(KS)(S(K(S(KS)))(S(K(S(S(KS)(SS(S(S(KS)K))(KK)))))
3
+ (S(S(KS)(S(KK)(S(KS)(S(S(KS)(S(KK)(S(KS)(S(S(KS)(S(KK)(SII)))
4
+ (K(SI(KK)))))))(K(S(K(S(S(KS)(S(K(SI))(S(KK)(S(K(S(S(KS)K)(S(S(KS)K)I)
5
+ (S(SII)I(S(S(KS)K)I)(S(S(KS)K)))))(SI(K(KI)))))))))(S(KK)K)))))))(K(S(KK)
6
+ (S(SI(K(S(S(S(S(SSK(SI(K(KI))))(K(S(S(KS)K)I(S(S(KS)K)(S(S(KS)K)I))
7
+ (S(K(S(SI(K(KI)))))K)(KK))))(KK))(S(S(KS)(S(K(SI))(S(KK)(S(K(S(S(KS)K)))
8
+ (SI(KK))))))(K(K(KI)))))(S(S(KS)(S(K(SI))(SS(SI)(KK))))(S(KK)
9
+ (S(K(S(S(KS)K)))(SI(K(KI)))))))))(K(K(KI))))))))))(K(KI)))))(SI(KK)))))
10
+ (S(K(S(K(S(K(S(SI(K(S(K(S(S(KS)K)I))(S(SII)I(S(S(KS)K)I)))))))K))))
11
+ (S(S(KS)(S(KK)(SII)))(K(SI(K(KI)))))))(SII(S(K(S(S(KS)(S(K(S(S(SI(KK))
12
+ (KI))))(SS(S(S(KS)(S(KK)(S(KS)(S(K(SI))K)))))(KK))))))(S(S(KS)
13
+ (S(K(S(KS)))(S(K(S(KK)))(S(S(KS)(S(KK)(SII)))(K(S(S(KS)K)))))))(K(S(S(KS)
14
+ (S(K(S(S(SI(KK))(KI))))(S(KK)(S(K(SII(S(K(S(S(KS)(S(K(S(K(S(S(KS)(S(KK)
15
+ (S(KS)(S(K(SI))K))))(KK)))))(S(S(KS)(S(KK)(S(K(SI(KK)))(SI(KK)))))
16
+ (K(SI(KK))))))))(S(S(KS)(S(K(S(KS)))(S(K(S(KK)))(S(S(KS)(S(KK)(SII)))
17
+ (K(SI(K(KI))))))))(K(K(SI(K(KI)))))))))(S(K(SII))(S(K(S(K(SI(K(KI))))))
18
+ (S(S(KS)(S(KK)(SI(K(S(K(S(SI(K(KI)))))K)))))(K(S(K(S(SI(KK))))
19
+ (S(KK)(SII)))))))))))(K(SI(K(KI))))))))(S(S(KS)K)I)
20
+ (SII(S(K(S(K(S(SI(K(KI)))))K))(SII)))))
@@ -0,0 +1,4 @@
1
+ ````sii``s`k`s``s`ks``s`kk``s`k````sii```sii``s``s`kski``s`k`sikk
2
+ ``s`k`s`k`s``s``si`kk`k``s`k`sik``s`k`s`k`s`kk``s``s`ks``s`k`s`ks
3
+ ``s``s`ks``s`kk``s`ks``s`kk``sii`k``s`k`s``s`ks``s`k`si```ss`si`kk
4
+ ``s`kkk`k`k``si`k`ki`k```sii```sii``s``s`kski
@@ -0,0 +1,12 @@
1
+ (load "lazier.scm")
2
+ (load "prelude.scm")
3
+
4
+ (lazy-def 'rev
5
+ '((lambda (f) (f end-of-output))
6
+ ((lambda (x) (x x))
7
+ (lambda (self dst src)
8
+ (if>= (car src) 256
9
+ dst
10
+ (self self (cons (car src) dst) (cdr src)) )))))
11
+
12
+ (print-as-unlambda (laze 'rev))