heist 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -0
- data/README.txt +28 -8
- data/lib/builtin/library.scm +45 -9
- data/lib/heist.rb +13 -1
- data/lib/repl.rb +1 -10
- data/lib/runtime/data/cons.rb +3 -3
- data/lib/runtime/data/vector.rb +3 -3
- data/test/arithmetic.scm +2 -0
- data/test/numbers.scm +7 -0
- metadata +2 -2
data/History.txt
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
=== Version 0.3.1 (2009-08-23)
|
2
|
+
|
3
|
+
* Added the (rationalize) procedure
|
4
|
+
* Allowed (gcd) and (lcm) to take more than two arguments
|
5
|
+
* Fixed string output so the REPL prints all data types correctly
|
6
|
+
|
7
|
+
|
1
8
|
=== Version 0.3.0 (2009-07-31)
|
2
9
|
|
3
10
|
We've got all your data types now
|
data/README.txt
CHANGED
@@ -38,7 +38,7 @@ languages.
|
|
38
38
|
Heist nominally targets R5RS (http://www.schemers.org/Documents/Standards/R5RS/HTML).
|
39
39
|
It has good support for many Scheme runtime features such as tail call
|
40
40
|
optimisation, macros and first-class continuations, as well as reasonably
|
41
|
-
complete
|
41
|
+
complete libraries for all the Scheme data types.
|
42
42
|
|
43
43
|
Currently implemented R5RS features include:
|
44
44
|
|
@@ -71,9 +71,9 @@ Currently implemented R5RS features include:
|
|
71
71
|
<tt>abs</tt>, <tt>quotient</tt>, <tt>remainder</tt>, <tt>modulo</tt>,
|
72
72
|
<tt>gcd</tt>, <tt>lcm</tt>, <tt>numerator</tt>, <tt>denominator</tt>,
|
73
73
|
<tt>floor</tt>, <tt>ceiling</tt>, <tt>truncate</tt>, <tt>round</tt>,
|
74
|
-
<tt>
|
75
|
-
<tt>
|
76
|
-
<tt>make-rectangular</tt>, <tt>make-polar</tt>, <tt>real-part</tt>,
|
74
|
+
<tt>rationalize</tt>, <tt>exp</tt>, <tt>log</tt>, <tt>sin</tt>, <tt>cos</tt>,
|
75
|
+
<tt>tan</tt>, <tt>asin</tt>, <tt>acos</tt>, <tt>atan</tt>, <tt>sqrt</tt>,
|
76
|
+
<tt>expt</tt>, <tt>make-rectangular</tt>, <tt>make-polar</tt>, <tt>real-part</tt>,
|
77
77
|
<tt>imag-part</tt>, <tt>magnitude</tt>, <tt>angle</tt>, <tt>number->string</tt>,
|
78
78
|
<tt>string->number</tt>
|
79
79
|
* Boolean library: <tt>and</tt>, <tt>or</tt>, <tt>not</tt>, <tt>boolean?</tt>
|
@@ -215,7 +215,9 @@ interface. Quoting syntax is out, so the expression <tt>'(1 2 3)</tt> would
|
|
215
215
|
need to be written <tt>[:quote, [1, 2, 3]]</tt>. Dotted pairs and improper
|
216
216
|
lists are also not available, though you can work around this to some extent
|
217
217
|
using <tt>:cons</tt>. Vectors should be written as <tt>[:vector, 1, 2, 3]</tt>
|
218
|
-
for example. Characters
|
218
|
+
for example. Characters can be generated using the <tt>char</tt> procedure
|
219
|
+
with a unit-length string, for example <tt>[:char, "Z"]</tt> produces the
|
220
|
+
character <tt>#\\Z</tt>.
|
219
221
|
|
220
222
|
|
221
223
|
== Notes
|
@@ -226,6 +228,8 @@ explicitly documented in this file can be assumed to work according to
|
|
226
228
|
the Scheme standard, or according to the information presented here,
|
227
229
|
and can be assumed to be reasonably stable.
|
228
230
|
|
231
|
+
=== Ruby-based syntax
|
232
|
+
|
229
233
|
I have not documented how to write your own syntax using Ruby because
|
230
234
|
it requires far too much knowledge of Heist's plumbing at present (I
|
231
235
|
suspect this may be unavoidable). Besides, we have macros so if you
|
@@ -233,11 +237,25 @@ want new syntax we've got you covered. In fact, writing syntax using
|
|
233
237
|
macros makes sure that new syntactic forms support continuations
|
234
238
|
correctly, and Heist itself eschews Ruby-based syntax where possible.
|
235
239
|
|
240
|
+
=== Valid symbols
|
241
|
+
|
236
242
|
Heist is extremely liberal as regards symbols. Any sequence of
|
237
243
|
characters that does not contain any spaces or parentheses and that
|
238
|
-
is not a boolean literal, a number
|
239
|
-
|
240
|
-
|
244
|
+
is not a boolean literal, a number, a character literal or a string
|
245
|
+
is considered a valid symbol.
|
246
|
+
|
247
|
+
=== Vectors and quoting
|
248
|
+
|
249
|
+
Vectors do not need to be quoted, for example the expression <tt>#(1 2 3)</tt>
|
250
|
+
evaluates to itself. If a vector is quoted, it is made immutable and
|
251
|
+
a quoted vector expression returns the same in-memory object every time
|
252
|
+
it is evaluated. In contrast, an unquoted vector returns a new vector
|
253
|
+
object every time it is evaluated. Unquoted vectors are not frozen
|
254
|
+
as this makes macro transformations hard to implement, and because we
|
255
|
+
cannot let the <tt>vector-set!</tt> procedure modify the parse tree
|
256
|
+
each unquoted vector is copied on evaluation.
|
257
|
+
|
258
|
+
=== Macros
|
241
259
|
|
242
260
|
Macros are slightly more liberal than R5RS, in that this is a valid
|
243
261
|
macro:
|
@@ -274,6 +292,8 @@ conditionally, certainly this will not work with macros as the
|
|
274
292
|
inlining process will overwrite conditional code using the first
|
275
293
|
expansion generated.
|
276
294
|
|
295
|
+
=== Laziness
|
296
|
+
|
277
297
|
Lazy evaluation mode is mainly useful for doing lambda calculus
|
278
298
|
without being concerned about the difference between normal and
|
279
299
|
applicative order, which for example affects the expression for
|
data/lib/builtin/library.scm
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
; in Scheme should go here. If at all possible, write
|
3
3
|
; builtins in Scheme rather than Ruby.
|
4
4
|
|
5
|
+
(define quit exit)
|
5
6
|
|
6
7
|
; (newline)
|
7
8
|
; prints a new-line character
|
@@ -149,22 +150,48 @@
|
|
149
150
|
; (gcd x y)
|
150
151
|
; Returns the greatest common divisor of two numbers
|
151
152
|
; http://en.wikipedia.org/wiki/Euclidean_algorithm
|
152
|
-
|
153
|
-
(
|
154
|
-
|
155
|
-
|
156
|
-
|
153
|
+
(define (gcd x y . rest)
|
154
|
+
(if (null? rest)
|
155
|
+
(if (zero? y)
|
156
|
+
(abs x)
|
157
|
+
(gcd y (remainder x y)))
|
158
|
+
(apply gcd (cons (gcd x y) rest))))
|
157
159
|
|
158
160
|
; (lcm x y)
|
159
161
|
; Returns the lowest common multiple of two numbers
|
160
162
|
; http://en.wikipedia.org/wiki/Least_common_multiple
|
161
|
-
|
162
|
-
(
|
163
|
-
|
164
|
-
|
163
|
+
(define (lcm x y . rest)
|
164
|
+
(if (null? rest)
|
165
|
+
(/ (abs (* x y))
|
166
|
+
(gcd x y))
|
167
|
+
(apply lcm (cons (lcm x y) rest))))
|
165
168
|
|
166
169
|
(define ceiling ceil)
|
167
170
|
|
171
|
+
; (rationalize x tolerance)
|
172
|
+
; Returns the simplest rational number that differs from x by
|
173
|
+
; no more than tolerance. Here 'simplest' means the smallest
|
174
|
+
; possible denominator is found first, and with that set the
|
175
|
+
; smallest corresponding numerator is chosen.
|
176
|
+
(define (rationalize x tolerance)
|
177
|
+
(cond [(rational? x)
|
178
|
+
x]
|
179
|
+
[(not (zero? (imag-part x)))
|
180
|
+
(make-rectangular (rationalize (real-part x) tolerance)
|
181
|
+
(rationalize (imag-part x) tolerance))]
|
182
|
+
[else
|
183
|
+
(let* ([t (abs tolerance)]
|
184
|
+
[a (- x t)]
|
185
|
+
[b (+ x t)])
|
186
|
+
(do ([i 1 (+ i 1)]
|
187
|
+
[z #f])
|
188
|
+
((number? z) z)
|
189
|
+
(let ([p (ceiling (* a i))]
|
190
|
+
[q (floor (* b i))])
|
191
|
+
(if (<= p q)
|
192
|
+
(set! z (/ (if (positive? p) p q)
|
193
|
+
i))))))]))
|
194
|
+
|
168
195
|
; (make-polar magnitude angle)
|
169
196
|
; Returns a new complex number with the given
|
170
197
|
; magnitude and angle
|
@@ -342,6 +369,15 @@
|
|
342
369
|
|
343
370
|
; Character functions
|
344
371
|
|
372
|
+
; (char string)
|
373
|
+
; Returns a character from a single-character string. Mostly
|
374
|
+
; useful for succinct representation of characters in hand-
|
375
|
+
; written Ruby code.
|
376
|
+
(define (char string)
|
377
|
+
(if (and (string? string) (= (string-length string) 1))
|
378
|
+
(string-ref string 0)
|
379
|
+
'()))
|
380
|
+
|
345
381
|
; (char-upper-case? letter)
|
346
382
|
; Returns true iff letter is an uppercase letter
|
347
383
|
(define (char-upper-case? letter)
|
data/lib/heist.rb
CHANGED
@@ -9,7 +9,7 @@ require 'treetop'
|
|
9
9
|
# utility methods that don't belong anywhere else. See the README for an
|
10
10
|
# overview of Heist's features.
|
11
11
|
module Heist
|
12
|
-
VERSION = '0.3.
|
12
|
+
VERSION = '0.3.1'
|
13
13
|
|
14
14
|
ROOT_PATH = File.expand_path(File.dirname(__FILE__))
|
15
15
|
PARSER_PATH = ROOT_PATH + '/parser/'
|
@@ -66,6 +66,18 @@ module Heist
|
|
66
66
|
op1.to_f / op2
|
67
67
|
end
|
68
68
|
|
69
|
+
# Returns a string representation of the object suitable for display on the
|
70
|
+
# command line. Some built-in Ruby types need special handling to display
|
71
|
+
# according to Scheme conventions.
|
72
|
+
def stringify(object)
|
73
|
+
case object
|
74
|
+
when Runtime::Character, String then object.inspect
|
75
|
+
when TrueClass then '#t'
|
76
|
+
when FalseClass then '#f'
|
77
|
+
else object.to_s
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
69
81
|
end
|
70
82
|
end
|
71
83
|
|
data/lib/repl.rb
CHANGED
@@ -31,7 +31,7 @@ module Heist
|
|
31
31
|
reset!
|
32
32
|
result = @scope.eval(tree)
|
33
33
|
unless result.nil?
|
34
|
-
puts "; => #{
|
34
|
+
puts "; => #{ Heist.stringify(result) }\n\n"
|
35
35
|
@results << result
|
36
36
|
@scope['^'] = result
|
37
37
|
end
|
@@ -64,15 +64,6 @@ module Heist
|
|
64
64
|
@indent = 0
|
65
65
|
end
|
66
66
|
|
67
|
-
def text(object)
|
68
|
-
case object
|
69
|
-
when Runtime::Character, String then object.inspect
|
70
|
-
when TrueClass then '#t'
|
71
|
-
when FalseClass then '#f'
|
72
|
-
else object.to_s
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
67
|
def push(line)
|
77
68
|
old_depth = depth
|
78
69
|
@buffer << line
|
data/lib/runtime/data/cons.rb
CHANGED
@@ -218,13 +218,13 @@ module Heist
|
|
218
218
|
end
|
219
219
|
|
220
220
|
# Returns a Scheme-style string representation of the list.
|
221
|
-
def
|
221
|
+
def to_s
|
222
222
|
strings = []
|
223
|
-
tail = each { |value| strings << value
|
223
|
+
tail = each { |value| strings << Heist.stringify(value) }.cdr
|
224
224
|
'(' + (strings * ' ') +
|
225
225
|
(tail == NULL ? '' : ' . ' + tail.to_s) + ')'
|
226
226
|
end
|
227
|
-
alias :
|
227
|
+
alias :inspect :to_s
|
228
228
|
end
|
229
229
|
|
230
230
|
end
|
data/lib/runtime/data/vector.rb
CHANGED
@@ -54,10 +54,10 @@ module Heist
|
|
54
54
|
end
|
55
55
|
|
56
56
|
# Returns a Scheme-style string representation of the +Vector+.
|
57
|
-
def
|
58
|
-
'#(' + map { |cell| cell
|
57
|
+
def to_s
|
58
|
+
'#(' + map { |cell| Heist.stringify(cell) }.join(' ') + ')'
|
59
59
|
end
|
60
|
-
alias :
|
60
|
+
alias :inspect :to_s
|
61
61
|
end
|
62
62
|
|
63
63
|
end
|
data/test/arithmetic.scm
CHANGED
@@ -41,6 +41,8 @@
|
|
41
41
|
(assert-equal 4 (gcd 32 -36))
|
42
42
|
(assert-equal 288 (lcm 32 -36))
|
43
43
|
(assert-equal 288.0 (lcm 32.0 -36)) ; inexact
|
44
|
+
(assert-equal 6 (lcm 2 6))
|
45
|
+
(assert-equal 12 (lcm 2 6 4))
|
44
46
|
|
45
47
|
(assert-equal 3 (numerator (/ 6 4)))
|
46
48
|
(assert-equal 2 (denominator (/ 6 4)))
|
data/test/numbers.scm
CHANGED
@@ -39,3 +39,10 @@
|
|
39
39
|
|
40
40
|
(assert-equal 1 (make-polar 1 0))
|
41
41
|
|
42
|
+
(assert-equal 3 (rationalize 5.5 3))
|
43
|
+
(assert-equal 4 (rationalize 5.5 2))
|
44
|
+
(assert-equal 5 (rationalize 5.5 1))
|
45
|
+
(assert-equal 11/2 (rationalize 5.5 0.1))
|
46
|
+
(assert-equal 16/3 (rationalize 5.25 0.1))
|
47
|
+
(assert-equal 21/4 (rationalize 5.25 0.01))
|
48
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: heist
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Coglan
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-08-23 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|