heist 0.3.2 → 0.3.3
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 +12 -0
- data/{README.txt → README.rdoc} +131 -148
- data/bin/heist +35 -10
- data/lib/heist.rb +3 -3
- data/lib/heist/builtin/compiled_library.rb +1 -0
- data/lib/heist/builtin/lib/character.scm +74 -0
- data/lib/heist/builtin/lib/list.scm +149 -0
- data/lib/heist/builtin/lib/logic.scm +17 -0
- data/lib/heist/builtin/lib/numeric.scm +184 -0
- data/lib/heist/builtin/lib/string.scm +117 -0
- data/lib/heist/builtin/lib/util.scm +18 -0
- data/lib/heist/builtin/lib/vector.scm +27 -0
- data/lib/{builtin → heist/builtin}/primitives.rb +0 -0
- data/lib/{builtin → heist/builtin}/syntax.scm +52 -52
- data/lib/{parser → heist/parser}/nodes.rb +0 -0
- data/lib/{parser → heist/parser}/ruby.rb +0 -0
- data/lib/{parser → heist/parser}/scheme.rb +0 -0
- data/lib/{parser → heist/parser}/scheme.tt +0 -0
- data/lib/{repl.rb → heist/repl.rb} +0 -0
- data/lib/{runtime → heist/runtime}/binding.rb +5 -0
- data/lib/{runtime → heist/runtime}/callable/continuation.rb +6 -1
- data/lib/{runtime → heist/runtime}/callable/function.rb +0 -0
- data/lib/{runtime → heist/runtime}/callable/macro.rb +1 -1
- data/lib/{runtime → heist/runtime}/callable/macro/expansion.rb +0 -0
- data/lib/{runtime → heist/runtime}/callable/macro/matches.rb +0 -0
- data/lib/{runtime → heist/runtime}/callable/macro/tree.rb +0 -0
- data/lib/{runtime → heist/runtime}/callable/syntax.rb +0 -0
- data/lib/{runtime → heist/runtime}/data/character.rb +0 -0
- data/lib/{runtime → heist/runtime}/data/cons.rb +0 -0
- data/lib/{runtime → heist/runtime}/data/expression.rb +0 -0
- data/lib/{runtime → heist/runtime}/data/identifier.rb +0 -0
- data/lib/heist/runtime/data/value.rb +14 -0
- data/lib/{runtime → heist/runtime}/data/vector.rb +0 -0
- data/lib/{runtime → heist/runtime}/frame.rb +3 -0
- data/lib/{runtime → heist/runtime}/runtime.rb +2 -2
- data/lib/{runtime → heist/runtime}/scope.rb +0 -0
- data/lib/{runtime → heist/runtime}/stack.rb +0 -0
- data/lib/{runtime → heist/runtime}/stackless.rb +0 -0
- data/lib/{stdlib → heist/stdlib}/benchmark.scm +0 -0
- data/lib/{stdlib → heist/stdlib}/birdhouse.scm +0 -0
- data/lib/{trie.rb → heist/trie.rb} +0 -0
- data/spec/heist_spec.rb +88 -0
- data/{test → spec}/helpers/lib.scm +0 -0
- data/{test → spec}/helpers/macro-helpers.scm +0 -0
- data/{test → spec}/helpers/vars.scm +0 -0
- data/{test → spec}/plt-macros.txt +0 -0
- data/{test → spec}/scheme_tests/arithmetic.scm +0 -0
- data/{test → spec}/scheme_tests/benchmarks.scm +0 -0
- data/{test → spec}/scheme_tests/booleans.scm +0 -0
- data/{test → spec}/scheme_tests/closures.scm +0 -0
- data/{test → spec}/scheme_tests/conditionals.scm +0 -0
- data/{test → spec}/scheme_tests/continuations.scm +14 -1
- data/{test → spec}/scheme_tests/define_functions.scm +0 -0
- data/{test → spec}/scheme_tests/define_values.scm +0 -0
- data/{test → spec}/scheme_tests/delay.scm +0 -0
- data/{test → spec}/scheme_tests/equivalence.scm +0 -0
- data/{test → spec}/scheme_tests/file_loading.scm +0 -0
- data/{test → spec}/scheme_tests/functional.scm +3 -0
- data/{test → spec}/scheme_tests/hygienic.scm +0 -0
- data/{test → spec}/scheme_tests/let.scm +0 -0
- data/{test → spec}/scheme_tests/lists.scm +0 -0
- data/{test → spec}/scheme_tests/macros.scm +0 -0
- data/{test → spec}/scheme_tests/numbers.scm +0 -0
- data/{test → spec}/scheme_tests/protection.scm +0 -0
- data/spec/scheme_tests/quoting.scm +14 -0
- data/{test → spec}/scheme_tests/strings.scm +0 -0
- data/{test → spec}/scheme_tests/unhygienic.scm +0 -0
- data/{test → spec}/scheme_tests/vectors.scm +0 -0
- data/spec/spec_helper.rb +4 -0
- metadata +98 -113
- data/Manifest.txt +0 -64
- data/Rakefile +0 -43
- data/lib/bin_spec.rb +0 -25
- data/lib/builtin/library.rb +0 -1
- data/lib/builtin/library.scm +0 -605
- data/test/test_heist.rb +0 -148
@@ -0,0 +1,117 @@
|
|
1
|
+
; (string char ...)
|
2
|
+
; Returns a new string formed by combining the given characters
|
3
|
+
(define (string . chars) (list->string chars))
|
4
|
+
|
5
|
+
(define (string-compare string1 string2 char-less? char-greater?)
|
6
|
+
(if (or (not (string? string1))
|
7
|
+
(not (string? string2)))
|
8
|
+
(error "Expected two strings as arguments")
|
9
|
+
(do ((pair1 (string->list string1) (cdr pair1))
|
10
|
+
(pair2 (string->list string2) (cdr pair2))
|
11
|
+
(diff '()))
|
12
|
+
((integer? diff) diff)
|
13
|
+
(set! diff (cond ((null? pair1) (if (null? pair2) 0 -1))
|
14
|
+
((null? pair2) 1)
|
15
|
+
(else (let ((char1 (car pair1))
|
16
|
+
(char2 (car pair2)))
|
17
|
+
(cond ((char-less? char1 char2) -1)
|
18
|
+
((char-greater? char1 char2) 1)
|
19
|
+
(else '())))))))))
|
20
|
+
|
21
|
+
; (string=? string1 string2)
|
22
|
+
; Returns true iff string1 and string2 are equal strings
|
23
|
+
(define (string=? string1 string2)
|
24
|
+
(zero? (string-compare string1 string2 char<? char>?)))
|
25
|
+
|
26
|
+
; (string-ci=? string1 string2)
|
27
|
+
; Returns true iff string1 and string2 are equal strings, ignoring case
|
28
|
+
(define (string-ci=? string1 string2)
|
29
|
+
(zero? (string-compare string1 string2 char-ci<? char-ci>?)))
|
30
|
+
|
31
|
+
; (string<? string1 string2)
|
32
|
+
; Returns true iff string1 is lexicographically less than string2
|
33
|
+
(define (string<? string1 string2)
|
34
|
+
(= (string-compare string1 string2 char<? char>?) -1))
|
35
|
+
|
36
|
+
; (string>? string1 string2)
|
37
|
+
; Returns true iff string1 is lexicographically greater than string2
|
38
|
+
(define (string>? string1 string2)
|
39
|
+
(= (string-compare string1 string2 char<? char>?) 1))
|
40
|
+
|
41
|
+
; (string<=? string1 string2)
|
42
|
+
; Returns true iff string1 is lexicographically less than or equal
|
43
|
+
; to string2
|
44
|
+
(define (string<=? string1 string2)
|
45
|
+
(not (string>? string1 string2)))
|
46
|
+
|
47
|
+
; (string>=? string1 string2)
|
48
|
+
; Returns true iff string1 is lexicographically greater than or equal
|
49
|
+
; to string2
|
50
|
+
(define (string>=? string1 string2)
|
51
|
+
(not (string<? string1 string2)))
|
52
|
+
|
53
|
+
; (string-ci<? string1 string2)
|
54
|
+
; Returns true iff string1 is lexicographically less than string2,
|
55
|
+
; ignoring differences in case
|
56
|
+
(define (string-ci<? string1 string2)
|
57
|
+
(= (string-compare string1 string2 char-ci<? char-ci>?) -1))
|
58
|
+
|
59
|
+
; (string-ci>? string1 string2)
|
60
|
+
; Returns true iff string1 is lexicographically greater than string2,
|
61
|
+
; ignoring differences in case
|
62
|
+
(define (string-ci>? string1 string2)
|
63
|
+
(= (string-compare string1 string2 char-ci<? char-ci>?) 1))
|
64
|
+
|
65
|
+
; (string-ci<=? string1 string2)
|
66
|
+
; Returns true iff string1 is lexicographically less than or equal
|
67
|
+
; to string2, ignoring differences in case
|
68
|
+
(define (string-ci<=? string1 string2)
|
69
|
+
(not (string-ci>? string1 string2)))
|
70
|
+
|
71
|
+
; (string-ci>=? string1 string2)
|
72
|
+
; Returns true iff string1 is lexicographically greater than or equal
|
73
|
+
; to string2, ignoring differences in case
|
74
|
+
(define (string-ci>=? string1 string2)
|
75
|
+
(not (string-ci<? string1 string2)))
|
76
|
+
|
77
|
+
; (substring string start end)
|
78
|
+
; Returns a string composed of the characters from start (inclusive)
|
79
|
+
; to end (exclusive) in string
|
80
|
+
(define (substring string start end)
|
81
|
+
(list->string (sublist (string->list string) start end)))
|
82
|
+
|
83
|
+
; (list->string chars)
|
84
|
+
; Returns a new string formed by combining the list
|
85
|
+
(define (list->string chars)
|
86
|
+
(let* ((size (length chars))
|
87
|
+
(str (make-string size)))
|
88
|
+
(do ((list chars (cdr list))
|
89
|
+
(i 0 (+ i 1)))
|
90
|
+
((= i size) str)
|
91
|
+
(string-set! str i (car list)))))
|
92
|
+
|
93
|
+
; (string->list string)
|
94
|
+
; Returns a newly allocated list of the characters in the string
|
95
|
+
(define (string->list string)
|
96
|
+
(let ((size (string-length string)))
|
97
|
+
(do ((i size (- i 1))
|
98
|
+
(list '() (cons (string-ref string (- i 1)) list)))
|
99
|
+
((zero? i) list))))
|
100
|
+
|
101
|
+
; (string-copy string)
|
102
|
+
; Returns a newly allocated copy of the string
|
103
|
+
(define (string-copy string)
|
104
|
+
(list->string (string->list string)))
|
105
|
+
|
106
|
+
; (string-fill! string char)
|
107
|
+
; Replaces every character of string with char
|
108
|
+
(define (string-fill! string char)
|
109
|
+
(let ((size (string-length string)))
|
110
|
+
(do ((i size (- i 1)))
|
111
|
+
((zero? i) string)
|
112
|
+
(string-set! string (- i 1) char))))
|
113
|
+
|
114
|
+
; (string-append string ...)
|
115
|
+
; Returns a new string formed by concatenating the arguments
|
116
|
+
(define (string-append . strings)
|
117
|
+
(list->string (apply append (map string->list strings))))
|
@@ -0,0 +1,18 @@
|
|
1
|
+
; Any built-in functions that we can implement directly
|
2
|
+
; in Scheme should go here. If at all possible, write
|
3
|
+
; builtins in Scheme rather than Ruby.
|
4
|
+
|
5
|
+
(define quit exit)
|
6
|
+
|
7
|
+
; (newline)
|
8
|
+
; prints a new-line character
|
9
|
+
(define (newline)
|
10
|
+
(display "\n"))
|
11
|
+
|
12
|
+
; (force)
|
13
|
+
; Extracts the value of a promise created using (delay)
|
14
|
+
(define (force promise) (promise))
|
15
|
+
|
16
|
+
; (call/cc)
|
17
|
+
; Alias for (call-with-current-continuation)
|
18
|
+
(define call/cc call-with-current-continuation)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
; (vector object ...)
|
2
|
+
; Returns a newly allocated vector from its arguments
|
3
|
+
(define (vector . args) (list->vector args))
|
4
|
+
|
5
|
+
; (list->vector list)
|
6
|
+
; Returns a newly allocated vector from a list
|
7
|
+
(define (list->vector list)
|
8
|
+
(let* ((size (length list))
|
9
|
+
(new-vector (make-vector size)))
|
10
|
+
(do ((i 0 (+ i 1))
|
11
|
+
(pair list (cdr pair)))
|
12
|
+
((= i size) new-vector)
|
13
|
+
(vector-set! new-vector i (car pair)))))
|
14
|
+
|
15
|
+
; (vector->list vector)
|
16
|
+
; Returns a newly allocated proper list from a vector
|
17
|
+
(define (vector->list vector)
|
18
|
+
(do ((i (vector-length vector) (- i 1))
|
19
|
+
(pair '() (cons (vector-ref vector (- i 1)) pair)))
|
20
|
+
((zero? i) pair)))
|
21
|
+
|
22
|
+
; (vector-fill! vector fill)
|
23
|
+
; Sets every element of vector to fill
|
24
|
+
(define (vector-fill! vector fill)
|
25
|
+
(do ((i (vector-length vector) (- i 1)))
|
26
|
+
((zero? i) vector)
|
27
|
+
(vector-set! vector (- i 1) fill)))
|
File without changes
|
@@ -5,18 +5,18 @@
|
|
5
5
|
; found, its consequent is tail-called and no further
|
6
6
|
; preconditions are evaluated.
|
7
7
|
(define-syntax cond (syntax-rules (else =>)
|
8
|
-
|
9
|
-
|
10
|
-
(begin expr1 expr2 ...)
|
11
|
-
|
12
|
-
(let (
|
8
|
+
((cond) #f)
|
9
|
+
((cond (else expr1 expr2 ...))
|
10
|
+
(begin expr1 expr2 ...))
|
11
|
+
((cond (test => function) clause ...)
|
12
|
+
(let ((temp test))
|
13
13
|
(if temp
|
14
14
|
(function temp)
|
15
|
-
(cond clause ...)))
|
16
|
-
|
15
|
+
(cond clause ...))))
|
16
|
+
((cond (test expression ...) clause ...)
|
17
17
|
(if test
|
18
18
|
(begin expression ...)
|
19
|
-
(cond clause ...))
|
19
|
+
(cond clause ...)))))
|
20
20
|
|
21
21
|
; (case) acts like Ruby's case statement. The value of the
|
22
22
|
; given expression is compared against a series of lists;
|
@@ -24,17 +24,17 @@
|
|
24
24
|
; following the list are evaluated and no further lists
|
25
25
|
; are tested.
|
26
26
|
(define-syntax case (syntax-rules (else)
|
27
|
-
|
28
|
-
|
29
|
-
(begin expr1 expr2 ...)
|
30
|
-
|
27
|
+
((case key) #f)
|
28
|
+
((case key (else expr1 expr2 ...))
|
29
|
+
(begin expr1 expr2 ...))
|
30
|
+
((case key
|
31
31
|
((cell ...) expr1 expr2 ...)
|
32
32
|
clause ...)
|
33
|
-
(let (
|
33
|
+
(let ((temp key))
|
34
34
|
(if (member temp '(cell ...))
|
35
35
|
(begin expr1 expr2 ...)
|
36
36
|
(case temp
|
37
|
-
clause ...)))
|
37
|
+
clause ...))))))
|
38
38
|
|
39
39
|
;----------------------------------------------------------------
|
40
40
|
|
@@ -47,33 +47,33 @@
|
|
47
47
|
; (let) evaluates values in the enclosing scope, so lambdas will
|
48
48
|
; not be able to refer to other values assigned using the (let).
|
49
49
|
(define-syntax let (syntax-rules ()
|
50
|
-
|
50
|
+
((let ((variable init) ...) body ...)
|
51
51
|
((lambda (variable ...)
|
52
52
|
body ...)
|
53
|
-
init ...)
|
54
|
-
|
55
|
-
(letrec (
|
56
|
-
body ...)
|
57
|
-
(name init ...))
|
53
|
+
init ...))
|
54
|
+
((let name ((variable init) ...) body ...)
|
55
|
+
(letrec ((name (lambda (variable ...)
|
56
|
+
body ...)))
|
57
|
+
(name init ...)))))
|
58
58
|
|
59
59
|
; (let*) creates a new scope for each variable and evaluates
|
60
60
|
; each expression in its enclosing scope. Basically a shorthand
|
61
61
|
; for several nested (let)s. Variables may refer to those that
|
62
62
|
; preceed them but not vice versa.
|
63
63
|
(define-syntax let* (syntax-rules ()
|
64
|
-
|
65
|
-
(let (
|
66
|
-
(let* (
|
67
|
-
|
68
|
-
(let (
|
64
|
+
((let* ((n1 e1) (n2 e2) (n3 e3) ...) body ...) ; 2 or more bindings
|
65
|
+
(let ((n1 e1))
|
66
|
+
(let* ((n2 e2) (n3 e3) ...) body ...)))
|
67
|
+
((let* ((name expression) ...) body ...) ; 0 or 1 binding
|
68
|
+
(let ((name expression) ...) body ...))))
|
69
69
|
|
70
70
|
; (letrec) evaluates values in the inner scope, so lambdas are
|
71
71
|
; able to refer to other values assigned using the (letrec).
|
72
72
|
(define-syntax letrec (syntax-rules ()
|
73
|
-
|
73
|
+
((letrec ((variable init) ...) body ...)
|
74
74
|
((lambda ()
|
75
75
|
(define variable init) ...
|
76
|
-
body ...))
|
76
|
+
body ...)))))
|
77
77
|
|
78
78
|
(define let-syntax let)
|
79
79
|
(define letrec-syntax letrec)
|
@@ -89,19 +89,19 @@
|
|
89
89
|
; loop is halted and the value of the expression following
|
90
90
|
; the test is returned.
|
91
91
|
(define-syntax do (syntax-rules ()
|
92
|
-
|
92
|
+
((do ((variable init step ...) ...) ; Allow 0 or 1 step
|
93
93
|
(test expression ...)
|
94
94
|
command ...)
|
95
|
-
(let loop (
|
95
|
+
(let loop ((variable init) ...)
|
96
96
|
(if test
|
97
97
|
(begin expression ...)
|
98
98
|
(begin
|
99
99
|
command ...
|
100
|
-
(loop (do "step" variable step ...) ...))))
|
101
|
-
|
102
|
-
variable
|
103
|
-
|
104
|
-
step
|
100
|
+
(loop (do "step" variable step ...) ...)))))
|
101
|
+
((do "step" variable)
|
102
|
+
variable)
|
103
|
+
((do "step" variable step)
|
104
|
+
step)))
|
105
105
|
|
106
106
|
;----------------------------------------------------------------
|
107
107
|
|
@@ -111,23 +111,23 @@
|
|
111
111
|
; of expressions, or returns the value of the last expression
|
112
112
|
; if all values are truthy.
|
113
113
|
(define-syntax and (syntax-rules ()
|
114
|
-
|
115
|
-
|
116
|
-
(let (
|
114
|
+
((and test) test)
|
115
|
+
((and test1 test2 ...)
|
116
|
+
(let ((temp test1))
|
117
117
|
(if (not temp)
|
118
118
|
temp
|
119
|
-
(and test2 ...)))
|
119
|
+
(and test2 ...))))))
|
120
120
|
|
121
121
|
; (or) returns the first truthy value returned by the list
|
122
122
|
; of expressions, or returns the value of the last expression
|
123
123
|
; if all values are falsey.
|
124
124
|
(define-syntax or (syntax-rules ()
|
125
|
-
|
126
|
-
|
127
|
-
(let (
|
125
|
+
((or test) test)
|
126
|
+
((or test1 test2 ...)
|
127
|
+
(let ((temp test1))
|
128
128
|
(if temp
|
129
129
|
temp
|
130
|
-
(or test2 ...)))
|
130
|
+
(or test2 ...))))))
|
131
131
|
|
132
132
|
;----------------------------------------------------------------
|
133
133
|
|
@@ -139,16 +139,16 @@
|
|
139
139
|
; ever evaluated once, so a promise can be implemented as a
|
140
140
|
; memoized closure.
|
141
141
|
(define-syntax delay (syntax-rules ()
|
142
|
-
|
143
|
-
(let (
|
144
|
-
|
142
|
+
((delay expression)
|
143
|
+
(let ((forced #f)
|
144
|
+
(memo #f))
|
145
145
|
(lambda ()
|
146
146
|
(if forced
|
147
147
|
memo
|
148
148
|
(begin
|
149
149
|
(set! memo expression)
|
150
150
|
(set! forced #t)
|
151
|
-
memo))))
|
151
|
+
memo)))))))
|
152
152
|
|
153
153
|
;----------------------------------------------------------------
|
154
154
|
|
@@ -159,10 +159,10 @@
|
|
159
159
|
; it will evaluate it and insert the result into the
|
160
160
|
; surrounding quoted list.
|
161
161
|
(define-syntax quasiquote (syntax-rules (unquote unquote-splicing)
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
162
|
+
(`,expr expr)
|
163
|
+
(`(,@first . rest) (append first `rest))
|
164
|
+
(`(first . rest) (cons `first `rest))
|
165
|
+
(`#(,@first rest ...) (list->vector `(,@first rest ...)))
|
166
|
+
(`#(expr ...) (list->vector `(expr ...)))
|
167
|
+
(`expr 'expr)))
|
168
168
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -52,6 +52,11 @@ module Heist
|
|
52
52
|
def innermost_binding(identifier)
|
53
53
|
@scope
|
54
54
|
end
|
55
|
+
|
56
|
+
# Returns a Rubyish representation of the binding's expression.
|
57
|
+
def to_ruby
|
58
|
+
@expression.respond_to?(:to_ruby) ? @expression.to_ruby : @expression
|
59
|
+
end
|
55
60
|
|
56
61
|
# Returns a string representation of the binding's +Expression+.
|
57
62
|
def to_s
|
@@ -28,8 +28,13 @@ module Heist
|
|
28
28
|
# replace it with the stack returned by this method before continuing
|
29
29
|
# execution.
|
30
30
|
def call(scope, cells)
|
31
|
+
apply(cells.to_a)
|
32
|
+
end
|
33
|
+
|
34
|
+
# TODO support call-with-values
|
35
|
+
def apply(params)
|
31
36
|
stack = @stack.copy
|
32
|
-
stack.fill!(@target,
|
37
|
+
stack.fill!(@target, Value.new(params.first))
|
33
38
|
stack
|
34
39
|
end
|
35
40
|
|
File without changes
|
@@ -62,7 +62,7 @@ module Heist
|
|
62
62
|
rule, matches = *rule_for(cells, scope)
|
63
63
|
return Expansion.new(@scope, scope, rule.cdr.car, matches) if rule
|
64
64
|
raise SyntaxError.new(
|
65
|
-
"Bad syntax: no macro expansion found for #{Cons.new(@name, cells)}")
|
65
|
+
"Bad syntax: no macro expansion found for #{Cons.new(Identifier.new(@name), cells)}")
|
66
66
|
end
|
67
67
|
|
68
68
|
# Returns a string placeholder for the +Macro+, containing its
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
@@ -95,6 +95,9 @@ module Heist
|
|
95
95
|
# +value+. When a hole is filled, the <tt>@current</tt> pointer is moved
|
96
96
|
# to the next subexpression that needs evaluating.
|
97
97
|
def fill!(subexpr, value)
|
98
|
+
value = value.value if Value === value and @values and
|
99
|
+
not (Syntax === @values.car)
|
100
|
+
|
98
101
|
epair, vpair = @expression, @values
|
99
102
|
while Cons === epair and not epair.null?
|
100
103
|
if epair.car.equal?(subexpr)
|