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
data/lib/heist.rb
CHANGED
@@ -2,16 +2,15 @@ require 'forwardable'
|
|
2
2
|
require 'rational'
|
3
3
|
require 'complex'
|
4
4
|
|
5
|
-
require 'rubygems'
|
6
5
|
require 'treetop'
|
7
6
|
|
8
7
|
# +Heist+ is the root module for all of Heist's components, and hosts a few
|
9
8
|
# utility methods that don't belong anywhere else. See the README for an
|
10
9
|
# overview of Heist's features.
|
11
10
|
module Heist
|
12
|
-
VERSION = '0.3.
|
11
|
+
VERSION = '0.3.3'
|
13
12
|
|
14
|
-
ROOT_PATH = File.expand_path(File.dirname(__FILE__))
|
13
|
+
ROOT_PATH = File.expand_path(File.dirname(__FILE__)) + '/heist'
|
15
14
|
PARSER_PATH = ROOT_PATH + '/parser/'
|
16
15
|
RUNTIME_PATH = ROOT_PATH + '/runtime/'
|
17
16
|
BUILTIN_PATH = ROOT_PATH + '/builtin/'
|
@@ -52,6 +51,7 @@ module Heist
|
|
52
51
|
# Returns the result of evaluating the given +Expression+ in the given +Scope+.
|
53
52
|
# If the first argument is not an +Expression+ it will be returned unaltered.
|
54
53
|
def evaluate(expression, scope)
|
54
|
+
return expression.value if Runtime::Value === expression
|
55
55
|
Runtime::Expression === expression ?
|
56
56
|
expression.eval(scope) :
|
57
57
|
expression
|
@@ -0,0 +1 @@
|
|
1
|
+
program [[:define, :quit, :exit], [:define, [:newline], [:display, "\n"]], [:define, [:force, :promise], [:promise]], [:define, :"call/cc", :"call-with-current-continuation"], [:define, :eq?, :eqv?], [:define, [:not, :x], [:if, :x, false, true]], [:define, :true, true], [:define, :false, false], [:define, [:boolean?, :x], [:or, [:eqv?, :x, true], [:eqv?, :x, false]]], [:define, :number?, :complex?], [:define, [:exact?, :x], [:or, [:rational?, :x], [:and, [:not, [:zero?, [:"imag-part", :x]]], [:exact?, [:"real-part", :x]], [:exact?, [:"imag-part", :x]]]]], [:define, [:inexact?, :x], [:not, [:exact?, :x]]], [:define, [:"=", :".", :args], [:define, [:iter, :x, :rest], [:if, [:null?, :rest], true, [:let, [[:y, [:car, :rest]]], [:if, [:or, [:not, [:number?, :x]], [:not, [:number?, :y]], [:not, [:equal?, :x, :y]]], false, [:iter, :x, [:cdr, :rest]]]]]], [:iter, [:car, :args], [:cdr, :args]]], [:define, [:zero?, :x], [:eqv?, :x, 0]], [:define, [:positive?, :x], [:>, :x, 0]], [:define, [:negative?, :x], [:<, :x, 0]], [:define, [:odd?, :x], [:"=", 1, [:remainder, :x, 2]]], [:define, [:even?, :x], [:zero?, [:remainder, :x, 2]]], [:define, [:max, :".", :values], [:"fold-right", [:lambda, [:a, :b], [:if, [:>=, :a, :b], :a, :b]], [:car, :values], [:cdr, :values]]], [:define, [:min, :".", :values], [:"fold-right", [:lambda, [:a, :b], [:if, [:<=, :a, :b], :a, :b]], [:car, :values], [:cdr, :values]]], [:define, [:abs, :x], [:if, [:negative?, :x], [:-, :x], :x]], [:define, [:quotient, :x, :y], [:let, [[:result, [:/, :x, :y]]], [[:if, [:positive?, :result], :floor, :ceiling], :result]]], [:define, [:remainder, :x, :y], [:-, [:round, :x], [:*, [:round, :y], [:quotient, :x, :y]]]], [:define, [:modulo, :x, :y], [:+, [:remainder, :x, :y], [:if, [:negative?, [:*, :x, :y]], [:round, :y], 0]]], [:define, [:gcd, :x, :y, :".", :rest], [:if, [:null?, :rest], [:if, [:zero?, :y], [:abs, :x], [:gcd, :y, [:remainder, :x, :y]]], [:apply, :gcd, [:cons, [:gcd, :x, :y], :rest]]]], [:define, [:lcm, :x, :y, :".", :rest], [:if, [:null?, :rest], [:/, [:abs, [:*, :x, :y]], [:gcd, :x, :y]], [:apply, :lcm, [:cons, [:lcm, :x, :y], :rest]]]], [:define, :ceiling, :ceil], [:define, [:rationalize, :x, :tolerance], [:cond, [[:rational?, :x], :x], [[:not, [:zero?, [:"imag-part", :x]]], [:"make-rectangular", [:rationalize, [:"real-part", :x], :tolerance], [:rationalize, [:"imag-part", :x], :tolerance]]], [:else, [:"let*", [[:t, [:abs, :tolerance]], [:a, [:-, :x, :t]], [:b, [:+, :x, :t]]], [:do, [[:i, 1, [:+, :i, 1]], [:z, false]], [[:number?, :z], :z], [:let, [[:p, [:ceiling, [:*, :a, :i]]], [:q, [:floor, [:*, :b, :i]]]], [:if, [:<=, :p, :q], [:set!, :z, [:/, [:if, [:positive?, :p], :p, :q], :i]]]]]]]]], [:define, [:"make-polar", :magnitude, :angle], [:let, [[:re, [:*, :magnitude, [:cos, :angle]]], [:im, [:*, :magnitude, [:sin, :angle]]]], [:"make-rectangular", :re, :im]]], [:define, [:magnitude, :z], [:let, [[:re, [:"real-part", :z]], [:im, [:"imag-part", :z]]], [:sqrt, [:+, [:*, :re, :re], [:*, :im, :im]]]]], [:define, [:angle, :z], [:let, [[:re, [:"real-part", :z]], [:im, [:"imag-part", :z]]], [:atan, :im, :re]]], [:define, [:factorial, :x], [:define, [:iter, :y, :acc], [:if, [:zero?, :y], :acc, [:iter, [:-, :y, 1], [:*, :y, :acc]]]], [:iter, :x, 1]], [:define, [:null?, :object], [:eqv?, [:quote, []], :object]], [:define, [:list?, :object], [:or, [:null?, :object], [:and, [:pair?, :object], [:list?, [:cdr, :object]]]]], [:define, [:list, :".", :args], :args], [:define, [:length, :object], [:define, [:iter, :list, :acc], [:if, [:null?, :list], :acc, [:iter, [:cdr, :list], [:+, 1, :acc]]]], [:iter, :object, 0]], [:define, [:append, :first, :".", :rest], [:cond, [[:null?, :rest], :first], [[:null?, :first], [:apply, :append, :rest]], [:else, [:cons, [:car, :first], [:append, [:cdr, :first], [:apply, :append, :rest]]]]]], [:define, [:reverse, :object], [:if, [:null?, :object], :object, [:append, [:reverse, [:cdr, :object]], [:list, [:car, :object]]]]], [:define, [:"list-tail", :list, :k], [:do, [[:pair, :list, [:cdr, :pair]], [:i, :k, [:-, :i, 1]]], [[:zero?, :i], :pair]]], [:define, [:"list-ref", :list, :k], [:car, [:"list-tail", :list, :k]]], [:define, [:"list-transform-search", :transform], [:lambda, [:predicate], [:lambda, [:object, :list], [:do, [[:pair, :list, [:cdr, :pair]]], [[:or, [:null?, :pair], [:predicate, [:car, [:transform, :pair]], :object]], [:if, [:null?, :pair], false, [:transform, :pair]]]]]]], [:define, :"list-search", [:"list-transform-search", [:lambda, [:x], :x]]], [:define, :memq, [:"list-search", :eq?]], [:define, :memv, [:"list-search", :eqv?]], [:define, :member, [:"list-search", :equal?]], [:define, :"assoc-list-search", [:"list-transform-search", :car]], [:define, :assq, [:"assoc-list-search", :eq?]], [:define, :assv, [:"assoc-list-search", :eqv?]], [:define, :assoc, [:"assoc-list-search", :equal?]], [:define, [:map, :proc, :list1, :".", :list2], [:if, [:null?, :list1], :list1, [:if, [:null?, :list2], [:cons, [:proc, [:car, :list1]], [:map, :proc, [:cdr, :list1]]], [:"let*", [[:all, [:cons, :list1, :list2]], [:args, [:map, :car, :all]], [:rest, [:map, :cdr, :all]]], [:cons, [:apply, :proc, :args], [:apply, :map, [:cons, :proc, :rest]]]]]]], [:define, [:"for-each", :proc, :list1, :".", :list2], [:do, [[:pair, :list1, [:cdr, :pair]], [:others, :list2, [:map, :cdr, :others]]], [[:null?, :pair], [:quote, []]], [:apply, :proc, [:cons, [:car, :pair], [:map, :car, :others]]]]], [:define, [:"fold-right", :proc, :value, :list], [:if, [:null?, :list], :value, [:proc, [:car, :list], [:"fold-right", :proc, :value, [:cdr, :list]]]]], [:define, [:"fold-left", :proc, :value, :list], [:if, [:null?, :list], :value, [:"fold-left", :proc, [:proc, :value, [:car, :list]], [:cdr, :list]]]], [:define, [:sublist, :list, :start, :end], [:cond, [[:null?, :list], [:quote, []]], [[:>, :start, 0], [:sublist, [:cdr, :list], [:-, :start, 1], [:-, :end, 1]]], [[:<=, :end, 0], [:quote, []]], [:else, [:cons, [:car, :list], [:sublist, [:cdr, :list], 0, [:-, :end, 1]]]]]], [:define, [:char, :string], [:if, [:and, [:string?, :string], [:"=", [:"string-length", :string], 1]], [:"string-ref", :string, 0], [:quote, []]]], [:define, [:"char-upper-case?", :letter], [:and, [:char?, :letter], [:let, [[:code, [:"char->integer", :letter]]], [:and, [:>=, :code, 65], [:<=, :code, 90]]]]], [:define, [:"char-lower-case?", :letter], [:and, [:char?, :letter], [:let, [[:code, [:"char->integer", :letter]]], [:and, [:>=, :code, 97], [:<=, :code, 122]]]]], [:define, [:"char-alphabetic?", :char], [:or, [:"char-upper-case?", :char], [:"char-lower-case?", :char]]], [:define, [:"char-numeric?", :char], [:and, [:char?, :char], [:let, [[:code, [:"char->integer", :char]]], [:and, [:>=, :code, 48], [:<=, :code, 57]]]]], [:define, [:"char-whitespace?", :char], [:and, [:char?, :char], [:if, [:member, [:"char->integer", :char], [:quote, [9, 10, 32]]], true, false]]], [:define, [:"char-upcase", :char], [:let, [[:code, [:"char->integer", :char]]], [:if, [:and, [:>=, :code, 97], [:<=, :code, 122]], [:"integer->char", [:-, :code, 32]], [:"integer->char", :code]]]], [:define, [:"char-downcase", :char], [:let, [[:code, [:"char->integer", :char]]], [:if, [:and, [:>=, :code, 65], [:<=, :code, 90]], [:"integer->char", [:+, :code, 32]], [:"integer->char", :code]]]], [:define, [:"char-compare-ci", :operator], [:lambda, [:x, :y], [:operator, [:"char-downcase", :x], [:"char-downcase", :y]]]], [:define, :"char-ci=?", [:"char-compare-ci", :"char=?"]], [:define, :"char-ci<?", [:"char-compare-ci", :"char<?"]], [:define, :"char-ci>?", [:"char-compare-ci", :"char>?"]], [:define, :"char-ci<=?", [:"char-compare-ci", :"char<=?"]], [:define, :"char-ci>=?", [:"char-compare-ci", :"char>=?"]], [:define, [:string, :".", :chars], [:"list->string", :chars]], [:define, [:"string-compare", :string1, :string2, :"char-less?", :"char-greater?"], [:if, [:or, [:not, [:string?, :string1]], [:not, [:string?, :string2]]], [:error, "Expected two strings as arguments"], [:do, [[:pair1, [:"string->list", :string1], [:cdr, :pair1]], [:pair2, [:"string->list", :string2], [:cdr, :pair2]], [:diff, [:quote, []]]], [[:integer?, :diff], :diff], [:set!, :diff, [:cond, [[:null?, :pair1], [:if, [:null?, :pair2], 0, -1]], [[:null?, :pair2], 1], [:else, [:let, [[:char1, [:car, :pair1]], [:char2, [:car, :pair2]]], [:cond, [[:"char-less?", :char1, :char2], -1], [[:"char-greater?", :char1, :char2], 1], [:else, [:quote, []]]]]]]]]]], [:define, [:"string=?", :string1, :string2], [:zero?, [:"string-compare", :string1, :string2, :"char<?", :"char>?"]]], [:define, [:"string-ci=?", :string1, :string2], [:zero?, [:"string-compare", :string1, :string2, :"char-ci<?", :"char-ci>?"]]], [:define, [:"string<?", :string1, :string2], [:"=", [:"string-compare", :string1, :string2, :"char<?", :"char>?"], -1]], [:define, [:"string>?", :string1, :string2], [:"=", [:"string-compare", :string1, :string2, :"char<?", :"char>?"], 1]], [:define, [:"string<=?", :string1, :string2], [:not, [:"string>?", :string1, :string2]]], [:define, [:"string>=?", :string1, :string2], [:not, [:"string<?", :string1, :string2]]], [:define, [:"string-ci<?", :string1, :string2], [:"=", [:"string-compare", :string1, :string2, :"char-ci<?", :"char-ci>?"], -1]], [:define, [:"string-ci>?", :string1, :string2], [:"=", [:"string-compare", :string1, :string2, :"char-ci<?", :"char-ci>?"], 1]], [:define, [:"string-ci<=?", :string1, :string2], [:not, [:"string-ci>?", :string1, :string2]]], [:define, [:"string-ci>=?", :string1, :string2], [:not, [:"string-ci<?", :string1, :string2]]], [:define, [:substring, :string, :start, :end], [:"list->string", [:sublist, [:"string->list", :string], :start, :end]]], [:define, [:"list->string", :chars], [:"let*", [[:size, [:length, :chars]], [:str, [:"make-string", :size]]], [:do, [[:list, :chars, [:cdr, :list]], [:i, 0, [:+, :i, 1]]], [[:"=", :i, :size], :str], [:"string-set!", :str, :i, [:car, :list]]]]], [:define, [:"string->list", :string], [:let, [[:size, [:"string-length", :string]]], [:do, [[:i, :size, [:-, :i, 1]], [:list, [:quote, []], [:cons, [:"string-ref", :string, [:-, :i, 1]], :list]]], [[:zero?, :i], :list]]]], [:define, [:"string-copy", :string], [:"list->string", [:"string->list", :string]]], [:define, [:"string-fill!", :string, :char], [:let, [[:size, [:"string-length", :string]]], [:do, [[:i, :size, [:-, :i, 1]]], [[:zero?, :i], :string], [:"string-set!", :string, [:-, :i, 1], :char]]]], [:define, [:"string-append", :".", :strings], [:"list->string", [:apply, :append, [:map, :"string->list", :strings]]]], [:define, [:vector, :".", :args], [:"list->vector", :args]], [:define, [:"list->vector", :list], [:"let*", [[:size, [:length, :list]], [:"new-vector", [:"make-vector", :size]]], [:do, [[:i, 0, [:+, :i, 1]], [:pair, :list, [:cdr, :pair]]], [[:"=", :i, :size], :"new-vector"], [:"vector-set!", :"new-vector", :i, [:car, :pair]]]]], [:define, [:"vector->list", :vector], [:do, [[:i, [:"vector-length", :vector], [:-, :i, 1]], [:pair, [:quote, []], [:cons, [:"vector-ref", :vector, [:-, :i, 1]], :pair]]], [[:zero?, :i], :pair]]], [:define, [:"vector-fill!", :vector, :fill], [:do, [[:i, [:"vector-length", :vector], [:-, :i, 1]]], [[:zero?, :i], :vector], [:"vector-set!", :vector, [:-, :i, 1], :fill]]]]
|
@@ -0,0 +1,74 @@
|
|
1
|
+
; (char string)
|
2
|
+
; Returns a character from a single-character string. Mostly
|
3
|
+
; useful for succinct representation of characters in hand-
|
4
|
+
; written Ruby code.
|
5
|
+
(define (char string)
|
6
|
+
(if (and (string? string) (= (string-length string) 1))
|
7
|
+
(string-ref string 0)
|
8
|
+
'()))
|
9
|
+
|
10
|
+
; (char-upper-case? letter)
|
11
|
+
; Returns true iff letter is an uppercase letter
|
12
|
+
(define (char-upper-case? letter)
|
13
|
+
(and (char? letter)
|
14
|
+
(let ((code (char->integer letter)))
|
15
|
+
(and (>= code 65)
|
16
|
+
(<= code 90)))))
|
17
|
+
|
18
|
+
; (char-lower-case? letter)
|
19
|
+
; Returns true iff letter is a lowercase letter
|
20
|
+
(define (char-lower-case? letter)
|
21
|
+
(and (char? letter)
|
22
|
+
(let ((code (char->integer letter)))
|
23
|
+
(and (>= code 97)
|
24
|
+
(<= code 122)))))
|
25
|
+
|
26
|
+
; (char-alphabetic? char)
|
27
|
+
; Returns true iff char is an alphabetic character
|
28
|
+
(define (char-alphabetic? char)
|
29
|
+
(or (char-upper-case? char)
|
30
|
+
(char-lower-case? char)))
|
31
|
+
|
32
|
+
; (char-numeric? char)
|
33
|
+
; Returns true iff char is a numeric character
|
34
|
+
(define (char-numeric? char)
|
35
|
+
(and (char? char)
|
36
|
+
(let ((code (char->integer char)))
|
37
|
+
(and (>= code 48)
|
38
|
+
(<= code 57)))))
|
39
|
+
|
40
|
+
; (char-whitespace? char)
|
41
|
+
; Returns true iff char is a whitespace character
|
42
|
+
(define (char-whitespace? char)
|
43
|
+
(and (char? char)
|
44
|
+
(if (member (char->integer char)
|
45
|
+
'(9 10 32))
|
46
|
+
#t
|
47
|
+
#f)))
|
48
|
+
|
49
|
+
; (char-upcase char)
|
50
|
+
; Returns an uppercase copy of char
|
51
|
+
(define (char-upcase char)
|
52
|
+
(let ((code (char->integer char)))
|
53
|
+
(if (and (>= code 97) (<= code 122))
|
54
|
+
(integer->char (- code 32))
|
55
|
+
(integer->char code))))
|
56
|
+
|
57
|
+
; (char-downcase char)
|
58
|
+
; Returns a lowercase copy of char
|
59
|
+
(define (char-downcase char)
|
60
|
+
(let ((code (char->integer char)))
|
61
|
+
(if (and (>= code 65) (<= code 90))
|
62
|
+
(integer->char (+ code 32))
|
63
|
+
(integer->char code))))
|
64
|
+
|
65
|
+
(define (char-compare-ci operator)
|
66
|
+
(lambda (x y)
|
67
|
+
(operator (char-downcase x)
|
68
|
+
(char-downcase y))))
|
69
|
+
|
70
|
+
(define char-ci=? (char-compare-ci char=?))
|
71
|
+
(define char-ci<? (char-compare-ci char<?))
|
72
|
+
(define char-ci>? (char-compare-ci char>?))
|
73
|
+
(define char-ci<=? (char-compare-ci char<=?))
|
74
|
+
(define char-ci>=? (char-compare-ci char>=?))
|
@@ -0,0 +1,149 @@
|
|
1
|
+
; (null? object)
|
2
|
+
; Returns true iff object is the empty list
|
3
|
+
(define (null? object)
|
4
|
+
(eqv? '() object))
|
5
|
+
|
6
|
+
; (list? object)
|
7
|
+
; Returns true iff object is a proper list
|
8
|
+
(define (list? object)
|
9
|
+
(or (null? object)
|
10
|
+
(and (pair? object)
|
11
|
+
(list? (cdr object)))))
|
12
|
+
|
13
|
+
; (list arg ...)
|
14
|
+
; Allocates and returns a new list from its arguments
|
15
|
+
(define (list . args) args)
|
16
|
+
|
17
|
+
; (length object)
|
18
|
+
; Returns the length of a proper list
|
19
|
+
(define (length object)
|
20
|
+
(define (iter list acc)
|
21
|
+
(if (null? list)
|
22
|
+
acc
|
23
|
+
(iter (cdr list) (+ 1 acc))))
|
24
|
+
(iter object 0))
|
25
|
+
|
26
|
+
; (append list ...)
|
27
|
+
; Returns a new list formed by concatenating the arguments.
|
28
|
+
; The final argument is not copied and the return value of
|
29
|
+
; (append) shares structure with it.
|
30
|
+
(define (append first . rest)
|
31
|
+
(cond ((null? rest) first)
|
32
|
+
((null? first) (apply append rest))
|
33
|
+
(else
|
34
|
+
(cons (car first)
|
35
|
+
(append (cdr first)
|
36
|
+
(apply append rest))))))
|
37
|
+
|
38
|
+
; (reverse list)
|
39
|
+
; Returns a newly allocated list consisting of the
|
40
|
+
; elements of list in reverse order.
|
41
|
+
(define (reverse object)
|
42
|
+
(if (null? object)
|
43
|
+
object
|
44
|
+
(append (reverse (cdr object))
|
45
|
+
(list (car object)))))
|
46
|
+
|
47
|
+
; (list-tail list k)
|
48
|
+
; Returns the sublist of list obtained by omitting the
|
49
|
+
; first k elements.
|
50
|
+
(define (list-tail list k)
|
51
|
+
(do ((pair list (cdr pair))
|
52
|
+
(i k (- i 1)))
|
53
|
+
((zero? i) pair)))
|
54
|
+
|
55
|
+
; (list-ref list k)
|
56
|
+
; Returns the kth element of list.
|
57
|
+
(define (list-ref list k)
|
58
|
+
(car (list-tail list k)))
|
59
|
+
|
60
|
+
; (memq obj list)
|
61
|
+
; (memv obj list)
|
62
|
+
; (member obj list)
|
63
|
+
; These procedures return the first sublist of list whose
|
64
|
+
; car is obj, where the sublists of list are the non-empty
|
65
|
+
; lists returned by (list-tail list k) for k less than the
|
66
|
+
; length of list. If obj does not occur in list, then #f
|
67
|
+
; (not the empty list) is returned. Memq uses eq? to compare
|
68
|
+
; obj with the elements of list, while memv uses eqv? and
|
69
|
+
; member uses equal?.
|
70
|
+
|
71
|
+
(define (list-transform-search transform)
|
72
|
+
(lambda (predicate)
|
73
|
+
(lambda (object list)
|
74
|
+
(do ((pair list (cdr pair)))
|
75
|
+
((or (null? pair)
|
76
|
+
(predicate (car (transform pair)) object))
|
77
|
+
(if (null? pair)
|
78
|
+
#f
|
79
|
+
(transform pair)))))))
|
80
|
+
|
81
|
+
(define list-search (list-transform-search (lambda (x) x)))
|
82
|
+
(define memq (list-search eq?))
|
83
|
+
(define memv (list-search eqv?))
|
84
|
+
(define member (list-search equal?))
|
85
|
+
|
86
|
+
; (assq obj alist)
|
87
|
+
; (assv obj alist)
|
88
|
+
; (assoc obj alist)
|
89
|
+
; Alist (for "association list") must be a list of pairs.
|
90
|
+
; These procedures find the first pair in alist whose car
|
91
|
+
; field is obj, and returns that pair. If no pair in alist
|
92
|
+
; has obj as its car, then #f (not the empty list) is
|
93
|
+
; returned. Assq uses eq? to compare obj with the car fields
|
94
|
+
; of the pairs in alist, while assv uses eqv? and assoc
|
95
|
+
; uses equal?.
|
96
|
+
|
97
|
+
(define assoc-list-search (list-transform-search car))
|
98
|
+
(define assq (assoc-list-search eq?))
|
99
|
+
(define assv (assoc-list-search eqv?))
|
100
|
+
(define assoc (assoc-list-search equal?))
|
101
|
+
|
102
|
+
; (map proc list1 list2 ...)
|
103
|
+
; Returns a new list formed by applying proc to each member
|
104
|
+
; (or set of members) of the given list(s).
|
105
|
+
(define (map proc list1 . list2)
|
106
|
+
(if (null? list1)
|
107
|
+
list1
|
108
|
+
(if (null? list2)
|
109
|
+
(cons (proc (car list1))
|
110
|
+
(map proc (cdr list1)))
|
111
|
+
(let* ((all (cons list1 list2))
|
112
|
+
(args (map car all))
|
113
|
+
(rest (map cdr all)))
|
114
|
+
(cons (apply proc args)
|
115
|
+
(apply map (cons proc rest)))))))
|
116
|
+
|
117
|
+
; (for-each proc list1 list2 ...)
|
118
|
+
; Calls proc once for each member of list1, passing each
|
119
|
+
; member (or set of members if more than one list given)
|
120
|
+
; as arguments to proc.
|
121
|
+
(define (for-each proc list1 . list2)
|
122
|
+
(do ((pair list1 (cdr pair))
|
123
|
+
(others list2 (map cdr others)))
|
124
|
+
((null? pair) '())
|
125
|
+
(apply proc (cons (car pair)
|
126
|
+
(map car others)))))
|
127
|
+
|
128
|
+
; (fold-right proc value list)
|
129
|
+
(define (fold-right proc value list)
|
130
|
+
(if (null? list)
|
131
|
+
value
|
132
|
+
(proc (car list)
|
133
|
+
(fold-right proc value (cdr list)))))
|
134
|
+
|
135
|
+
; (fold-left proc value list)
|
136
|
+
(define (fold-left proc value list)
|
137
|
+
(if (null? list)
|
138
|
+
value
|
139
|
+
(fold-left proc
|
140
|
+
(proc value (car list))
|
141
|
+
(cdr list))))
|
142
|
+
|
143
|
+
; (sublist list start end)
|
144
|
+
(define (sublist list start end)
|
145
|
+
(cond ((null? list) '())
|
146
|
+
((> start 0) (sublist (cdr list) (- start 1) (- end 1)))
|
147
|
+
((<= end 0) '())
|
148
|
+
(else (cons (car list)
|
149
|
+
(sublist (cdr list) 0 (- end 1))))))
|
@@ -0,0 +1,17 @@
|
|
1
|
+
; (eq? x y)
|
2
|
+
; Currently an alias for (eqv? x y). TODO implement properly
|
3
|
+
(define eq? eqv?)
|
4
|
+
|
5
|
+
; (not x)
|
6
|
+
; Boolean inverse of x
|
7
|
+
(define (not x)
|
8
|
+
(if x #f #t))
|
9
|
+
|
10
|
+
; Longhand aliases for boolean constants
|
11
|
+
(define true #t)
|
12
|
+
(define false #f)
|
13
|
+
|
14
|
+
; (boolean? x)
|
15
|
+
; Returns true iff x is a boolean value
|
16
|
+
(define (boolean? x)
|
17
|
+
(or (eqv? x #t) (eqv? x #f)))
|
@@ -0,0 +1,184 @@
|
|
1
|
+
; (number? x)
|
2
|
+
; Returns true iff x is any type of number
|
3
|
+
(define number? complex?)
|
4
|
+
|
5
|
+
; (exact? x)
|
6
|
+
; Returns true iff the given number is exact i.e. an integer, a
|
7
|
+
; rational, or a complex made of integers or rationals
|
8
|
+
(define (exact? x)
|
9
|
+
(or (rational? x)
|
10
|
+
(and (not (zero? (imag-part x)))
|
11
|
+
(exact? (real-part x))
|
12
|
+
(exact? (imag-part x)))))
|
13
|
+
|
14
|
+
; (inexact? x)
|
15
|
+
; Returns true iff x is not an exact number
|
16
|
+
(define (inexact? x)
|
17
|
+
(not (exact? x)))
|
18
|
+
|
19
|
+
; Returns true iff all arguments are numerically equal
|
20
|
+
(define (= . args)
|
21
|
+
(define (iter x rest)
|
22
|
+
(if (null? rest)
|
23
|
+
#t
|
24
|
+
(let ((y (car rest)))
|
25
|
+
(if (or (not (number? x))
|
26
|
+
(not (number? y))
|
27
|
+
(not (equal? x y)))
|
28
|
+
#f
|
29
|
+
(iter x (cdr rest))))))
|
30
|
+
(iter (car args) (cdr args)))
|
31
|
+
|
32
|
+
; (zero? x)
|
33
|
+
; Returns true iff x is zero
|
34
|
+
(define (zero? x)
|
35
|
+
(eqv? x 0))
|
36
|
+
|
37
|
+
; (positive? x)
|
38
|
+
; Returns true iff x > 0
|
39
|
+
(define (positive? x)
|
40
|
+
(> x 0))
|
41
|
+
|
42
|
+
; (negative? x)
|
43
|
+
; Returns true iff x < 0
|
44
|
+
(define (negative? x)
|
45
|
+
(< x 0))
|
46
|
+
|
47
|
+
; (odd? x)
|
48
|
+
; Returns true iff x is odd
|
49
|
+
(define (odd? x)
|
50
|
+
(= 1 (remainder x 2)))
|
51
|
+
|
52
|
+
; (even? x)
|
53
|
+
; Returns true iff x is even
|
54
|
+
(define (even? x)
|
55
|
+
(zero? (remainder x 2)))
|
56
|
+
|
57
|
+
; (max arg1 arg2 ...)
|
58
|
+
; Returns the maximum value in the list of arguments
|
59
|
+
(define (max . values)
|
60
|
+
(fold-right (lambda (a b) (if (>= a b) a b))
|
61
|
+
(car values)
|
62
|
+
(cdr values)))
|
63
|
+
|
64
|
+
; (min arg1 arg2 ...)
|
65
|
+
; Returns the minimum value in the list of arguments
|
66
|
+
(define (min . values)
|
67
|
+
(fold-right (lambda (a b) (if (<= a b) a b))
|
68
|
+
(car values)
|
69
|
+
(cdr values)))
|
70
|
+
|
71
|
+
; (abs x)
|
72
|
+
; Returns the absolute value of a number
|
73
|
+
(define (abs x)
|
74
|
+
(if (negative? x)
|
75
|
+
(- x)
|
76
|
+
x))
|
77
|
+
|
78
|
+
; (quotient) and (remainder) satisfy
|
79
|
+
;
|
80
|
+
; (= n1 (+ (* n2 (quotient n1 n2))
|
81
|
+
; (remainder n1 n2)))
|
82
|
+
|
83
|
+
; (quotient x y)
|
84
|
+
; Returns the quotient of two numbers, i.e. performs n1/n2
|
85
|
+
; and rounds toward zero.
|
86
|
+
(define (quotient x y)
|
87
|
+
(let ((result (/ x y)))
|
88
|
+
((if (positive? result)
|
89
|
+
floor
|
90
|
+
ceiling)
|
91
|
+
result)))
|
92
|
+
|
93
|
+
; (remainder x y)
|
94
|
+
; Returns the remainder after dividing the first operand
|
95
|
+
; by the second
|
96
|
+
(define (remainder x y)
|
97
|
+
(- (round x)
|
98
|
+
(* (round y)
|
99
|
+
(quotient x y))))
|
100
|
+
|
101
|
+
; (modulo x y)
|
102
|
+
; Returns the first operand modulo the second
|
103
|
+
(define (modulo x y)
|
104
|
+
(+ (remainder x y)
|
105
|
+
(if (negative? (* x y))
|
106
|
+
(round y)
|
107
|
+
0)))
|
108
|
+
|
109
|
+
; (gcd x y)
|
110
|
+
; Returns the greatest common divisor of two numbers
|
111
|
+
; http://en.wikipedia.org/wiki/Euclidean_algorithm
|
112
|
+
(define (gcd x y . rest)
|
113
|
+
(if (null? rest)
|
114
|
+
(if (zero? y)
|
115
|
+
(abs x)
|
116
|
+
(gcd y (remainder x y)))
|
117
|
+
(apply gcd (cons (gcd x y) rest))))
|
118
|
+
|
119
|
+
; (lcm x y)
|
120
|
+
; Returns the lowest common multiple of two numbers
|
121
|
+
; http://en.wikipedia.org/wiki/Least_common_multiple
|
122
|
+
(define (lcm x y . rest)
|
123
|
+
(if (null? rest)
|
124
|
+
(/ (abs (* x y))
|
125
|
+
(gcd x y))
|
126
|
+
(apply lcm (cons (lcm x y) rest))))
|
127
|
+
|
128
|
+
(define ceiling ceil)
|
129
|
+
|
130
|
+
; (rationalize x tolerance)
|
131
|
+
; Returns the simplest rational number that differs from x by
|
132
|
+
; no more than tolerance. Here 'simplest' means the smallest
|
133
|
+
; possible denominator is found first, and with that set the
|
134
|
+
; smallest corresponding numerator is chosen.
|
135
|
+
(define (rationalize x tolerance)
|
136
|
+
(cond ((rational? x)
|
137
|
+
x)
|
138
|
+
((not (zero? (imag-part x)))
|
139
|
+
(make-rectangular (rationalize (real-part x) tolerance)
|
140
|
+
(rationalize (imag-part x) tolerance)))
|
141
|
+
(else
|
142
|
+
(let* ((t (abs tolerance))
|
143
|
+
(a (- x t))
|
144
|
+
(b (+ x t)))
|
145
|
+
(do ((i 1 (+ i 1))
|
146
|
+
(z #f))
|
147
|
+
((number? z) z)
|
148
|
+
(let ((p (ceiling (* a i)))
|
149
|
+
(q (floor (* b i))))
|
150
|
+
(if (<= p q)
|
151
|
+
(set! z (/ (if (positive? p) p q)
|
152
|
+
i)))))))))
|
153
|
+
|
154
|
+
; (make-polar magnitude angle)
|
155
|
+
; Returns a new complex number with the given
|
156
|
+
; magnitude and angle
|
157
|
+
(define (make-polar magnitude angle)
|
158
|
+
(let ((re (* magnitude (cos angle)))
|
159
|
+
(im (* magnitude (sin angle))))
|
160
|
+
(make-rectangular re im)))
|
161
|
+
|
162
|
+
; (magnitude z)
|
163
|
+
; Returns the magnitude of a complex number
|
164
|
+
(define (magnitude z)
|
165
|
+
(let ((re (real-part z))
|
166
|
+
(im (imag-part z)))
|
167
|
+
(sqrt (+ (* re re) (* im im)))))
|
168
|
+
|
169
|
+
; (angle z)
|
170
|
+
; Returns the angle a complex number makes with the
|
171
|
+
; real axis when plotted in the complex plane
|
172
|
+
(define (angle z)
|
173
|
+
(let ((re (real-part z))
|
174
|
+
(im (imag-part z)))
|
175
|
+
(atan im re)))
|
176
|
+
|
177
|
+
; (factorial x)
|
178
|
+
; Returns factorial of x
|
179
|
+
(define (factorial x)
|
180
|
+
(define (iter y acc)
|
181
|
+
(if (zero? y)
|
182
|
+
acc
|
183
|
+
(iter (- y 1) (* y acc))))
|
184
|
+
(iter x 1))
|