heist 0.3.2 → 0.3.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. data/History.txt +12 -0
  2. data/{README.txt → README.rdoc} +131 -148
  3. data/bin/heist +35 -10
  4. data/lib/heist.rb +3 -3
  5. data/lib/heist/builtin/compiled_library.rb +1 -0
  6. data/lib/heist/builtin/lib/character.scm +74 -0
  7. data/lib/heist/builtin/lib/list.scm +149 -0
  8. data/lib/heist/builtin/lib/logic.scm +17 -0
  9. data/lib/heist/builtin/lib/numeric.scm +184 -0
  10. data/lib/heist/builtin/lib/string.scm +117 -0
  11. data/lib/heist/builtin/lib/util.scm +18 -0
  12. data/lib/heist/builtin/lib/vector.scm +27 -0
  13. data/lib/{builtin → heist/builtin}/primitives.rb +0 -0
  14. data/lib/{builtin → heist/builtin}/syntax.scm +52 -52
  15. data/lib/{parser → heist/parser}/nodes.rb +0 -0
  16. data/lib/{parser → heist/parser}/ruby.rb +0 -0
  17. data/lib/{parser → heist/parser}/scheme.rb +0 -0
  18. data/lib/{parser → heist/parser}/scheme.tt +0 -0
  19. data/lib/{repl.rb → heist/repl.rb} +0 -0
  20. data/lib/{runtime → heist/runtime}/binding.rb +5 -0
  21. data/lib/{runtime → heist/runtime}/callable/continuation.rb +6 -1
  22. data/lib/{runtime → heist/runtime}/callable/function.rb +0 -0
  23. data/lib/{runtime → heist/runtime}/callable/macro.rb +1 -1
  24. data/lib/{runtime → heist/runtime}/callable/macro/expansion.rb +0 -0
  25. data/lib/{runtime → heist/runtime}/callable/macro/matches.rb +0 -0
  26. data/lib/{runtime → heist/runtime}/callable/macro/tree.rb +0 -0
  27. data/lib/{runtime → heist/runtime}/callable/syntax.rb +0 -0
  28. data/lib/{runtime → heist/runtime}/data/character.rb +0 -0
  29. data/lib/{runtime → heist/runtime}/data/cons.rb +0 -0
  30. data/lib/{runtime → heist/runtime}/data/expression.rb +0 -0
  31. data/lib/{runtime → heist/runtime}/data/identifier.rb +0 -0
  32. data/lib/heist/runtime/data/value.rb +14 -0
  33. data/lib/{runtime → heist/runtime}/data/vector.rb +0 -0
  34. data/lib/{runtime → heist/runtime}/frame.rb +3 -0
  35. data/lib/{runtime → heist/runtime}/runtime.rb +2 -2
  36. data/lib/{runtime → heist/runtime}/scope.rb +0 -0
  37. data/lib/{runtime → heist/runtime}/stack.rb +0 -0
  38. data/lib/{runtime → heist/runtime}/stackless.rb +0 -0
  39. data/lib/{stdlib → heist/stdlib}/benchmark.scm +0 -0
  40. data/lib/{stdlib → heist/stdlib}/birdhouse.scm +0 -0
  41. data/lib/{trie.rb → heist/trie.rb} +0 -0
  42. data/spec/heist_spec.rb +88 -0
  43. data/{test → spec}/helpers/lib.scm +0 -0
  44. data/{test → spec}/helpers/macro-helpers.scm +0 -0
  45. data/{test → spec}/helpers/vars.scm +0 -0
  46. data/{test → spec}/plt-macros.txt +0 -0
  47. data/{test → spec}/scheme_tests/arithmetic.scm +0 -0
  48. data/{test → spec}/scheme_tests/benchmarks.scm +0 -0
  49. data/{test → spec}/scheme_tests/booleans.scm +0 -0
  50. data/{test → spec}/scheme_tests/closures.scm +0 -0
  51. data/{test → spec}/scheme_tests/conditionals.scm +0 -0
  52. data/{test → spec}/scheme_tests/continuations.scm +14 -1
  53. data/{test → spec}/scheme_tests/define_functions.scm +0 -0
  54. data/{test → spec}/scheme_tests/define_values.scm +0 -0
  55. data/{test → spec}/scheme_tests/delay.scm +0 -0
  56. data/{test → spec}/scheme_tests/equivalence.scm +0 -0
  57. data/{test → spec}/scheme_tests/file_loading.scm +0 -0
  58. data/{test → spec}/scheme_tests/functional.scm +3 -0
  59. data/{test → spec}/scheme_tests/hygienic.scm +0 -0
  60. data/{test → spec}/scheme_tests/let.scm +0 -0
  61. data/{test → spec}/scheme_tests/lists.scm +0 -0
  62. data/{test → spec}/scheme_tests/macros.scm +0 -0
  63. data/{test → spec}/scheme_tests/numbers.scm +0 -0
  64. data/{test → spec}/scheme_tests/protection.scm +0 -0
  65. data/spec/scheme_tests/quoting.scm +14 -0
  66. data/{test → spec}/scheme_tests/strings.scm +0 -0
  67. data/{test → spec}/scheme_tests/unhygienic.scm +0 -0
  68. data/{test → spec}/scheme_tests/vectors.scm +0 -0
  69. data/spec/spec_helper.rb +4 -0
  70. metadata +98 -113
  71. data/Manifest.txt +0 -64
  72. data/Rakefile +0 -43
  73. data/lib/bin_spec.rb +0 -25
  74. data/lib/builtin/library.rb +0 -1
  75. data/lib/builtin/library.scm +0 -605
  76. data/test/test_heist.rb +0 -148
@@ -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.2'
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))