heist 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|