rubylisp 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3e43b771e458951f6724a4ea368359b651af68aa
4
+ data.tar.gz: 32043fab0730d6414558a3fed26e3063b0a16943
5
+ SHA512:
6
+ metadata.gz: 13a455aa9220f5f7850a5a2f9e6c54f2544cc6b5f946d3529cc056a0d4b589ca856f426da3604f22e1c986ff7535b1b96690a08fd4d30f25883eed3c2151a23a
7
+ data.tar.gz: c5fd927f7d655390e1dc5d9a415f1ccb04fb1ed775e59d8b60aa5b16da3eb19325aeb99bc74aff20ef76321736c7c6866fbb77593deefad49bcee2a404b7499d
data/bin/rubylisp ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubylisp'
4
+ require 'readline'
5
+
6
+ Lisp::Initializer.register_builtins
7
+
8
+ puts 'RubyLisp REPL'
9
+ parser = Lisp::Parser.new
10
+
11
+ while line = Readline.readline('> ', true)
12
+ puts parser.parse(line).evaluate(Lisp::EnvironmentFrame.global).to_s
13
+ end
14
+
@@ -0,0 +1,230 @@
1
+ module Lisp
2
+
3
+ class AList < Object
4
+ include Enumerable
5
+
6
+ def self.register
7
+ Primitive.register("acons") {|args, env| Lisp::AList::acons_impl(args, env) }
8
+ Primitive.register("assoc") {|args, env| Lisp::AList::assoc_impl(args, env) }
9
+ Primitive.register("rassoc") {|args, env| Lisp::AList::rassoc_impl(args, env) }
10
+ Primitive.register("dissoc") {|args, env| Lisp::AList::dissoc_impl(args, env) }
11
+ Primitive.register("zip") {|args, env| Lisp::AList::zip_impl(args, env) }
12
+ Primitive.register("alist-to-list") {|args, env| Lisp::AList::alist_to_list_impl(args, env) }
13
+ Primitive.register("list-to-alist") {|args, env| Lisp::AList::list_to_alist_impl(args, env) }
14
+ end
15
+
16
+ def self.acons_impl(args, env)
17
+ raise "acons require at least 2 or 3 arguments" unless args.length == 2 || args.length == 3
18
+ key = args.car.evaluate(env)
19
+ value = args.cadr.evaluate(env)
20
+ alist = args.length == 2 ? nil : args.caddr.evaluate(env)
21
+ alist = Lisp::AList.from_list(alist) if !alist.nil? && alist.list? && !alist.alist?
22
+ raise "the last argument to acons has to be an association list" unless alist.nil? || alist.alist?
23
+
24
+ if alist.nil?
25
+ Lisp::AList.new({key => value})
26
+ else
27
+ alist.acons(key, value)
28
+ end
29
+ end
30
+
31
+ def self.assoc_impl(args, env)
32
+ raise "assoc require 2 arguments" unless args.length == 2
33
+ key = args.car.evaluate(env)
34
+ alist = args.cadr.evaluate(env)
35
+ alist = Lisp::AList.from_list(alist) if alist.list? && !alist.alist?
36
+ raise "the last argument to assoc has to be an association list" unless alist.alist?
37
+ alist.assoc(key)
38
+ end
39
+
40
+ def self.rassoc_impl(args, env)
41
+ raise "assoc require 2 arguments" unless args.length == 2
42
+ value = args.car.evaluate(env)
43
+ alist = args.cadr.evaluate(env)
44
+ alist = Lisp::AList.from_list(alist) if alist.list? && !alist.alist?
45
+ raise "the last argument to rassoc has to be an association list" unless alist.alist?
46
+ alist.rassoc(value)
47
+ end
48
+
49
+ def self.dissoc_impl(args, env)
50
+ raise "assoc require 2 arguments" unless args.length == 2
51
+ key = args.car.evaluate(env)
52
+ alist = args.cadr.evaluate(env)
53
+ alist = Lisp::AList.from_list(alist) if alist.list? && !alist.alist?
54
+ raise "the last argument to dissoc has to be an association list" unless alist.alist?
55
+ alist.dissoc(key)
56
+ end
57
+
58
+ def self.zip_impl(args, env)
59
+ raise "assoc require 2 or 3arguments" unless args.length == 2 || args.length == 3
60
+ key_list = args.car.evaluate(env)
61
+ raise "the keys supplied to zip has to be a list" unless key_list.list?
62
+ value_list = args.cadr.evaluate(env)
63
+ raise "the values supplied to zip has to be a list" unless value_list.list?
64
+ raise "zip requires the same number of keys and values" unless key_list.length == value_list.length
65
+
66
+ if args.length == 3
67
+ alist = args.caddr.evaluate(env)
68
+ alist = Lisp::AList.from_list(alist) if alist.list? && !alist.alist?
69
+ raise "the third argument to zip has to be an association list" unless alist.alist?
70
+ alist.zip(key_list.to_a, value_list.to_a)
71
+ else
72
+ Lisp::AList.zip(key_list.to_a, value_list.to_a)
73
+ end
74
+ end
75
+
76
+ def self.alist_to_list_impl(args, env)
77
+ raise "alist-to-list requires 1 arguments" unless args.length == 1
78
+ alist = args.car.evaluate(env)
79
+ return alist if alist.list? && !alist.alist?
80
+ raise "the argument to alist-to-list has to be an association list" unless alist.alist?
81
+
82
+ alist.to_list
83
+ end
84
+
85
+ def self.list_to_alist_impl(args, env)
86
+ raise "list-to-alist requires 1 arguments" unless args.length == 1
87
+ list = args.car.evaluate(env)
88
+ raise "the argument to list-to-alist has to be a list" unless list.list?
89
+
90
+ Lisp::AList.from_list(list)
91
+ end
92
+
93
+
94
+ def initialize(h=nil)
95
+ @value = h || {}
96
+ end
97
+
98
+ def lisp_object?
99
+ true
100
+ end
101
+
102
+ def eq?(sexpr)
103
+ return false unless sexpr.alist?
104
+ @value == sexpr.value
105
+ end
106
+
107
+ def empty?
108
+ @value.empty?
109
+ end
110
+
111
+ def string?
112
+ false
113
+ end
114
+
115
+ def character?
116
+ false
117
+ end
118
+
119
+ def number?
120
+ false
121
+ end
122
+
123
+ def positive?
124
+ false
125
+ end
126
+
127
+ def zero?
128
+ false
129
+ end
130
+
131
+ def negative?
132
+ false
133
+ end
134
+
135
+ def symbol?
136
+ false
137
+ end
138
+
139
+ def primitive?
140
+ false
141
+ end
142
+
143
+ def function?
144
+ false
145
+ end
146
+
147
+ def macro?
148
+ false
149
+ end
150
+
151
+ def pair?
152
+ true
153
+ end
154
+
155
+ def list?
156
+ true
157
+ end
158
+
159
+ def alist?
160
+ true
161
+ end
162
+
163
+ def frame?
164
+ false
165
+ end
166
+
167
+ def length
168
+ return @value.length
169
+ end
170
+
171
+ def car
172
+ @value.first
173
+ end
174
+
175
+ def cdr
176
+ end
177
+
178
+ def acons(k, v)
179
+ @value[k] = v
180
+ self
181
+ end
182
+
183
+ def assoc(k)
184
+ v = @value[k]
185
+ Lisp::ConsCell.cons(k, v)
186
+ end
187
+
188
+ def rassoc(value)
189
+ @value.each do |k, v|
190
+ return Lisp::ConsCell.cons(k, v) if value == v || value.eq?(v)
191
+ end
192
+ end
193
+
194
+ def dissoc(k)
195
+ @value.delete(k)
196
+ self
197
+ end
198
+
199
+ def zip(keys, values)
200
+ keys.zip(values).each {|k, v| @value[k] = v}
201
+ self
202
+ end
203
+
204
+ def self.zip(keys, values)
205
+ self.new.zip(keys, values)
206
+ end
207
+
208
+ def self.from_list(list)
209
+ h = {}
210
+ list.each do |pair|
211
+ h[pair.car] = pair.cdr
212
+ end
213
+ self.new(h)
214
+ end
215
+
216
+ def to_list
217
+ Lisp::ConsCell.array_to_list(@value.map {|k, v| Lisp::ConsCell.cons(k, v)})
218
+ end
219
+
220
+ def to_s
221
+ to_list.to_s
222
+ end
223
+
224
+ def print_string
225
+ self.to_s
226
+ end
227
+
228
+ end
229
+
230
+ end
@@ -0,0 +1,65 @@
1
+ module Lisp
2
+
3
+ class Assignment
4
+
5
+ def self.register
6
+ Primitive.register("set!", "(set! _name_ _new-value_)\n\nThe way to assign (i.e. rebind) a symbol. `name` is the symbol to be rebound.
7
+ The `new-value` sexpr is evaluated to arrive at the new value to be bound to. Use of `set!` is frowned upon, and should not be used without thought.") do |args, env|
8
+ Lisp::Assignment::setbang_impl(args, env)
9
+ end
10
+
11
+ Primitive.register("set-car!", "(set-car! _cons-cell_ _new-value_)\n\nSet the `car` pointer of `cons-cell`.") do |args, env|
12
+ Lisp::Assignment::setcarbang_impl(args, env)
13
+ end
14
+
15
+ Primitive.register("set-cdr!", "(set-cdr! _cons-cell_ _new-value_)\n\nSet the `cdr` pointer of `cons-cell`.") do |args, env|
16
+ Lisp::Assignment::setcdrbang_impl(args, env)
17
+ end
18
+
19
+ Primitive.register("set-nth!", "(set-nth! _n_ _list-or-vector_ _new-value_)\n\nSets the `n`th element of `list-or-vector` to `new-value`.") do |args, env|
20
+ Lisp::Assignment::setnthbang_impl(args, env)
21
+ end
22
+
23
+ end
24
+
25
+
26
+ def self.setbang_impl(args, env)
27
+ sym = args.car
28
+ raise "set! requires a raw (unevaluated) symbol as it's first argument." unless sym.symbol?
29
+ value = args.cadr.evaluate(env)
30
+ env.set(sym, value)
31
+ end
32
+
33
+
34
+ def self.setcarbang_impl(args, env)
35
+ pair = args.car.evaluate(env)
36
+ raise "set-car! requires a pair as it's first argument." unless pair.pair?
37
+ value = args.cadr.evaluate(env)
38
+ pair.set_car!(value)
39
+ end
40
+
41
+
42
+ def self.setcdrbang_impl(args, env)
43
+ pair = args.car.evaluate(env)
44
+ raise "set-cdr! requires a pair as it's first argument." unless pair.pair?
45
+ value = args.cadr.evaluate(env)
46
+ pair.set_cdr!(value)
47
+ end
48
+
49
+
50
+ def self.setnthbang_impl(args, env)
51
+ raise "set-nth! requires 3 arguments." unless args.length == 3
52
+ n = args.car.evaluate(env)
53
+ raise "The first argument of set-nth! has to be an number." unless n.number?
54
+ raise "The first argument of set-nth! has to be positive." unless n.value > 0
55
+
56
+ l = args.cadr.evaluate(env)
57
+ raise "set-nth! requires a list or vector as it's first argument." unless l.list? || l.vector?
58
+ value = args.caddr.evaluate(env)
59
+ l.set_nth!(n.value, value)
60
+ l
61
+ end
62
+
63
+
64
+ end
65
+ end
@@ -0,0 +1,149 @@
1
+ module Lisp
2
+
3
+ class Atom < Object
4
+
5
+ attr_reader :value
6
+
7
+ def lisp_object?
8
+ true
9
+ end
10
+
11
+ def string?
12
+ false
13
+ end
14
+
15
+ def character?
16
+ false
17
+ end
18
+
19
+ def number?
20
+ false
21
+ end
22
+
23
+ def positive?
24
+ false
25
+ end
26
+
27
+ def zero?
28
+ false
29
+ end
30
+
31
+ def negative?
32
+ false
33
+ end
34
+
35
+ def symbol?
36
+ false
37
+ end
38
+
39
+ def pair?
40
+ false
41
+ end
42
+
43
+ def list?
44
+ false
45
+ end
46
+
47
+ def primitive?
48
+ false
49
+ end
50
+
51
+ def special?
52
+ false
53
+ end
54
+
55
+ def function?
56
+ false
57
+ end
58
+
59
+ def macro?
60
+ false
61
+ end
62
+
63
+ def object?
64
+ false
65
+ end
66
+
67
+ def class?
68
+ false
69
+ end
70
+
71
+ def alist?
72
+ false
73
+ end
74
+
75
+ def frame?
76
+ false
77
+ end
78
+
79
+ def vector?
80
+ false
81
+ end
82
+
83
+ def length
84
+ 1
85
+ end
86
+
87
+ def copy
88
+ self.class.new(self.value)
89
+ end
90
+
91
+ def eq?(sexpr)
92
+ return false if sexpr.nil?
93
+ return false if self.type != sexpr.type
94
+ self.value == sexpr.value
95
+ end
96
+
97
+ def type
98
+ :unknown
99
+ end
100
+
101
+ def evaluate(env)
102
+ self
103
+ end
104
+
105
+ def apply_to(args, env)
106
+ nil
107
+ end
108
+
109
+ def all?(&block)
110
+ false
111
+ end
112
+
113
+ def true?
114
+ true
115
+ end
116
+
117
+ def false?
118
+ false
119
+ end
120
+
121
+ def car
122
+ nil
123
+ end
124
+
125
+ def cdr
126
+ nil
127
+ end
128
+
129
+ def quoted
130
+ Lisp::ConsCell.cons(Symbol.named("quote"), self)
131
+ end
132
+
133
+ def set!(v)
134
+ end
135
+
136
+ def print_string
137
+ self.to_s
138
+ end
139
+
140
+ alias print_string_helper print_string
141
+
142
+
143
+ def doc
144
+ nil
145
+ end
146
+
147
+ end
148
+
149
+ end
@@ -0,0 +1,17 @@
1
+ module Lisp
2
+
3
+ class Binding
4
+ attr_accessor :symbol, :value
5
+
6
+ def initialize(symbol, value)
7
+ @symbol = symbol
8
+ @value = value
9
+ self
10
+ end
11
+
12
+ def to_s
13
+ "#{symbol.name} -> #{value.to_s}"
14
+ end
15
+ end
16
+
17
+ end
@@ -0,0 +1,49 @@
1
+ module Lisp
2
+
3
+ class Boolean < Atom
4
+ def self.TRUE
5
+ @true_constant ||= Boolean.new(true)
6
+ end
7
+
8
+ def self.FALSE
9
+ @false_constant ||= Boolean.new(false)
10
+ end
11
+
12
+ def self.with_value(b)
13
+ b ? self.TRUE : self.FALSE
14
+ end
15
+
16
+ def initialize(b)
17
+ @value = b
18
+ end
19
+
20
+ def type
21
+ :boolean
22
+ end
23
+
24
+ def boolean?
25
+ true
26
+ end
27
+
28
+ def to_s
29
+ return "#t" if @value
30
+ "#f"
31
+ end
32
+
33
+ def true?
34
+ @value
35
+ end
36
+
37
+ def false?
38
+ !@value
39
+ end
40
+
41
+ def negate
42
+ Lisp::Boolean.with_value(!@value)
43
+ end
44
+
45
+ end
46
+
47
+ TRUE = Boolean.TRUE
48
+ FALSE = Boolean.FALSE
49
+ end
@@ -0,0 +1,31 @@
1
+ module Lisp
2
+
3
+ class Initializer
4
+
5
+ def self.initialize_global_environment
6
+ Lisp::EnvironmentFrame.global.bind(Symbol.named("nil"), nil)
7
+ end
8
+
9
+ def self.register_builtins
10
+ Lisp::Equivalence.register
11
+ Lisp::Math.register
12
+ Lisp::Logical.register
13
+ Lisp::SpecialForms.register
14
+ Lisp::ListSupport.register
15
+ Lisp::Relational.register
16
+ Lisp::TypeChecks.register
17
+ Lisp::Assignment.register
18
+ Lisp::Testing.register
19
+ Lisp::IO.register
20
+ Lisp::AList.register
21
+ Lisp::Frame.register
22
+ Lisp::Character.register
23
+ Lisp::String.register
24
+ Lisp::NativeObject.register
25
+ Lisp::ClassObject.register
26
+ Lisp::System.register
27
+ Lisp::Vector.register
28
+ end
29
+ end
30
+
31
+ end