heist 0.3.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|