rbl 0.0.5 → 0.0.6

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/rubylisp/core.rbl CHANGED
@@ -1,274 +1,423 @@
1
1
  ; TODO:
2
- ; and, or
3
- ; implement macros
4
- ; defn
5
- ; str
6
2
  ; comment
7
3
  ; ->, ->>
8
4
  ; private vars/fns
9
5
  ; if-not, when, when-not, if-let, when-let
10
- ; cond
11
6
  ; case
7
+ ; destructuring
8
+ ; gensym and gensym# syntax for macros
9
+ ; throw an error when an undefined symbol is used in a fn or macro definition
10
+ ; make strings enumerable, e.g.
11
+ ; (apply str "hello") should return "hello"
12
+ ; (take 3 "hello") should return ("h" "e" "l")
13
+ ; note: (seq "hello") already returns ("h" "e" "l" "l" "o") because of special
14
+ ; logic in the definition of seq
15
+ ; make equality semantics work like clojure's:
16
+ ; (= 2 2.0) should be false
17
+ ; (== 2 2.0) should be true
12
18
 
13
19
  (ns rubylisp.core)
14
20
 
15
- ;; MATH & LOGIC
21
+ ;; awkwardly defined basic functions that will make it easier to define other
22
+ ;; functions and macros
23
+
24
+ (def seq
25
+ (fn seq [x]
26
+ (if (.nil? x)
27
+ nil
28
+ (if (.empty? x)
29
+ nil
30
+ (if (.is_a? x Kernel::String)
31
+ (.to_list (.chars x))
32
+ (.to_list x))))))
16
33
 
17
- (def +
18
- (fn + [x y & more]
19
- (let [xy (.+ x y)]
20
- (if more
21
- (apply + xy more)
22
- xy))))
23
-
24
- (def -
25
- (fn - [x y & more]
26
- (let [xy (.- x y)]
27
- (if more
28
- (apply - xy more)
29
- xy))))
30
-
31
- (def inc
32
- (fn inc [x]
33
- (+ x 1)))
34
-
35
- (def dec
36
- (fn dec [x]
37
- (- x 1)))
38
-
39
- (def *
40
- (fn * [x y & more]
41
- (let [xy (.* x y)]
42
- (if more
43
- (apply * xy more)
44
- xy))))
45
-
46
- (def /
47
- (fn / [x y & more]
48
- (let [xy (./ x y)]
49
- (if more
50
- (apply / xy more)
51
- xy))))
52
-
53
- (def <
54
- (fn < [x y & more]
55
- (let [xy (.< x y)]
56
- (if more
57
- (apply < xy more)
58
- xy))))
59
-
60
- (def <=
61
- (fn <= [x y & more]
62
- (let [xy (.<= x y)]
63
- (if more
64
- (apply <= xy more)
65
- xy))))
66
-
67
- (def =
68
- (fn = [x y & more]
69
- (let [xy (.== x y)]
70
- (if more
71
- (apply = xy more)
72
- xy))))
73
-
74
- (def not=
75
- (fn not= [x y & more]
76
- (let [xy (.!= x y)]
77
- (if more
78
- (apply not= xy more)
79
- xy))))
80
-
81
- (def boolean
82
- (fn boolean [x]
83
- (if x true false)))
84
-
85
- (def not
86
- (fn not [x]
87
- (if x false true)))
88
-
89
- (def >
90
- (fn > [x y & more]
91
- (let [xy (.> x y)]
92
- (if more
93
- (apply > xy more)
94
- xy))))
95
-
96
- (def >=
97
- (fn >= [x y & more]
98
- (let [xy (.>= x y)]
99
- (if more
100
- (apply >= xy more)
101
- xy))))
102
-
103
- (def pos?
104
- (fn pos? [x]
105
- (> (count x) 0)))
106
-
107
- (def neg?
108
- (fn neg? [x]
109
- (< (count x) 0)))
110
-
111
- (def zero?
112
- (fn zero? [x]
113
- (= 0 x)))
114
-
115
- ;; LISTS & COLLECTIONS
116
-
117
- (def nil?
118
- (fn nil? [x]
119
- (= nil x)))
120
-
121
- (def string?
122
- (fn string? [x]
123
- (.is_a? x Kernel::String)))
124
-
125
- ;; TODO: implement & use cond
126
34
  (def count
127
35
  (fn count [x]
128
- (if (nil? x)
129
- 0
130
- (if (string? x)
131
- (.count (seq x))
132
- (.count x)))))
36
+ (let [coll (seq x)]
37
+ (if (.nil? coll)
38
+ 0
39
+ (.count coll)))))
133
40
 
134
41
  (def empty?
135
42
  (fn empty? [coll]
136
- (if (nil? coll)
137
- true
138
- (.empty? coll))))
139
-
140
- (def list
141
- (fn list [& args]
142
- (.to_list (if (nil? args)
143
- []
144
- args))))
145
-
146
- (def list?
147
- (fn list? [x]
148
- (.is_a? x Hamster::List)))
149
-
150
- (def vector
151
- (fn vector [& args]
152
- (Hamster::Vector::new args)))
153
-
154
- (def vector?
155
- (fn vector? [x]
156
- (.is_a? x Hamster::Vector)))
157
-
158
- (def vec
159
- (fn vec [coll]
160
- (Hamster::Vector::new coll)))
161
-
162
- (def hash-map
163
- (fn hash-map [& args]
164
- (Hamster::Hash::new (.to_h (.each_slice args 2)))))
165
-
166
- (def map?
167
- (fn map? [x]
168
- (.is_a? x Hamster::Hash)))
169
-
170
- (def seq
171
- (fn seq [x]
172
- (if (not (empty? x))
173
- (if (string? x)
174
- (.to_list (.chars x))
175
- (.to_list x)))))
43
+ (if (.nil? coll)
44
+ true
45
+ (.empty? coll))))
176
46
 
177
47
  (def cons
178
48
  (fn cons [x y]
179
- (let [lst (if (nil? y) (Hamster::List::empty) (.to_list y))]
49
+ (let [lst (if (.nil? y) () (.to_list y))]
180
50
  (.cons lst x))))
181
51
 
182
- (def first
183
- (fn first [coll]
52
+ (def concat
53
+ (fn concat [& colls]
54
+ (if (.nil? colls)
55
+ ()
56
+ (if (.== 1 (.count colls))
57
+ (.to_list (.first colls))
58
+ (.+ (.to_list (.first colls)) (apply concat (.drop colls 1)))))))
59
+
60
+ ;; defn, defmacro
61
+
62
+ ;; TODO: docstring support
63
+ (defmacro* defmacro
64
+ (fn [name & more]
65
+ `(defmacro* ~name
66
+ (fn ~name ~@more))))
67
+
68
+ ;; TODO: docstring support
69
+ (defmacro defn
70
+ [name & more]
71
+ `(def ~name
72
+ (fn ~name ~@more)))
73
+
74
+ ;; CONTROL FLOW
75
+
76
+ (defn boolean
77
+ [x]
78
+ (if x true false))
79
+
80
+ (defn not
81
+ [x]
82
+ (if x false true))
83
+
84
+ (defn throw
85
+ [e]
86
+ (Kernel::raise e))
87
+
88
+ (defmacro cond
89
+ [& xs]
90
+ (if (.> (count xs) 0)
91
+ (list 'if (.first xs)
92
+ (if (.> (count xs) 1)
93
+ (.at xs 1)
94
+ (throw "`cond` requires an even number of forms."))
95
+ (cons 'cond (.drop xs 2)))))
96
+
97
+ (defmacro or
98
+ [& xs]
99
+ (cond
100
+ (empty? xs)
101
+ nil
102
+
103
+ (.== 1 (count xs))
104
+ (.first xs)
105
+
106
+ ;; FIXME: implement gensym and use it here so the macro is hygenic
107
+ :else
108
+ `(let [or_FIXME ~(.first xs)]
109
+ (if or_FIXME or_FIXME (or ~@(.drop xs 1))))))
110
+
111
+ (defmacro and
112
+ [& xs]
113
+ (cond
114
+ (empty? xs)
115
+ true
116
+
117
+ (.== 1 (count xs))
118
+ (.first xs)
119
+
120
+ ;; FIXME: implement gensym and use it here so the macro is hygenic
121
+ :else
122
+ `(let [and_FIXME ~(.first xs)]
123
+ (if and_FIXME (and ~@(.drop xs 1)) and_FIXME))))
124
+
125
+ ;; LISTS & OTHER COLLECTIONS
126
+
127
+ (defn nil?
128
+ [x]
129
+ (.== nil x))
130
+
131
+ (defn string?
132
+ [x]
133
+ (.is_a? x Kernel::String))
134
+
135
+ (defn list
136
+ [& args]
137
+ (.to_list (if (nil? args)
138
+ []
139
+ args)))
140
+
141
+ (defn list?
142
+ [x]
143
+ (.is_a? x Hamster::List))
144
+
145
+ (defn vector
146
+ [& args]
147
+ (Hamster::Vector::new args))
148
+
149
+ (defn vector?
150
+ [x]
151
+ (.is_a? x Hamster::Vector))
152
+
153
+ ;; TODO: implement `or` and use it here
154
+ (defn sequential?
155
+ [x]
156
+ (or (list? x) (vector? x) (.is_a? x Kernel::Array)))
157
+
158
+ (defn vec
159
+ [coll]
160
+ (Hamster::Vector::new coll))
161
+
162
+ (defn hash-map
163
+ [& args]
164
+ (Hamster::Hash::new (.to_h (.each_slice args 2))))
165
+
166
+ (defn map?
167
+ [x]
168
+ (.is_a? x Hamster::Hash))
169
+
170
+ ;; TODO: multiple arity fn
171
+ (defn nth
172
+ [coll index & more]
173
+ (if more
174
+ (let [not-found (.first more)]
175
+ (if (.>= index (count coll))
176
+ not-found
177
+ (.at coll index)))
178
+ (if (.>= index (count coll))
179
+ (Kernel::raise Kernel::IndexError)
180
+ (.at coll index))))
181
+
182
+ (defn first
183
+ [coll]
184
+ (if (not (nil? coll))
184
185
  (.first coll)))
185
186
 
186
- (def last
187
- (fn last [coll]
188
- (.last coll)))
187
+ (defn ffirst
188
+ [coll]
189
+ (first (first coll)))
189
190
 
190
- (def rest
191
- (fn rest [coll]
192
- (let [lst (if (nil? coll) (Hamster::List::empty) (.to_list coll))]
193
- (.tail lst))))
191
+ (defn second
192
+ [coll]
193
+ (nth coll 1))
194
194
 
195
- (def take
196
- (fn take [n coll]
197
- (.to_list (.take coll n))))
195
+ (defn last
196
+ [coll]
197
+ (.last coll))
198
198
 
199
- ;; TODO: support mapping over multiple collections
200
- (def map
201
- (fn map [f coll]
202
- (if (empty? coll)
203
- ()
204
- (cons (f (first coll)) (map f (rest coll))))))
199
+ (defn rest
200
+ [coll]
201
+ (let [lst (if (nil? coll) () (.to_list coll))]
202
+ (.tail lst)))
203
+
204
+ (defn take
205
+ [n coll]
206
+ (.to_list (.take coll n)))
205
207
 
206
- (def reverse
207
- (fn reverse [coll]
208
- (if (empty? coll)
209
- coll
210
- (+ [(last coll)]
211
- (reverse (.slice coll 0 (dec (count coll))))))))
208
+ (defn butlast
209
+ [coll]
210
+ (take (.- (count coll) 1) coll))
211
+
212
+ ;; TODO: support mapping over multiple collections
213
+ (defn map
214
+ [f coll]
215
+ (if (empty? coll)
216
+ ()
217
+ (cons (f (first coll))
218
+ (call-with-block .map (rest coll) [] f))))
219
+
220
+ (defn reverse
221
+ [coll]
222
+ (if (empty? coll)
223
+ coll
224
+ (cons (last coll) (reverse (butlast coll)))))
225
+
226
+ ;; TODO: multiple arity fn
227
+ (defn range
228
+ [& args]
229
+ (cond
230
+ (.== 0 (count args))
231
+ ;; requires adjusting call-with-block so that it can use namespaced methods
232
+ "TODO: zero-arity that produces a lazy list, i.e. Hamster::iterate(0, &:next)"
233
+
234
+ (.== 1 (count args))
235
+ (apply range 0 args)
236
+
237
+ :else
238
+ (let [start (first args)
239
+ end (.- (second args) 1)]
240
+ (Hamster::interval start end))))
212
241
 
213
242
  ;; TODO: implement as multiple arity fn
214
- ;; TODO: zero-arity that produces a lazy list, i.e. Hamster::iterate(0,
215
- ;; &:next).take(5)
216
- ;; (requires some kind of block syntax)
217
- (def range
218
- (fn range [& args]
219
- (if (= 1 (count args))
220
- (apply range 0 args)
221
- (apply Hamster::interval args))))
243
+ (defn repeat
244
+ [& args]
245
+ (if (.== 1 (count args))
246
+ (apply Hamster::repeat args)
247
+ (apply Hamster::replicate args)))
222
248
 
223
249
  ;; TODO: implement as multiple arity fn
224
- (def repeat
225
- (fn repeat [& args]
226
- (if (= 1 (count args))
227
- (apply Hamster::repeat args)
228
- (apply Hamster::replicate args))))
250
+ (defn reduce
251
+ [f & args]
252
+ (if (.== 1 (count args))
253
+ (let [xs (first args)]
254
+ (reduce f (first xs) (rest xs)))
255
+ (let [init (first args)
256
+ xs (second args)]
257
+ (if (.== 0 (count xs))
258
+ init
259
+ (reduce f (f init (first xs)) (rest xs))))))
260
+
261
+ ;; MATH & LOGIC
262
+
263
+ ;; TODO: zero arity that returns 0
264
+ ;; TODO: one arity that returns x
265
+ (defn +
266
+ [x y & more]
267
+ (let [xy (.+ x y)]
268
+ (if more
269
+ (apply + xy more)
270
+ xy)))
271
+
272
+ ;; TODO: one arity that returns x * -1
273
+ (defn -
274
+ [x y & more]
275
+ (let [xy (.- x y)]
276
+ (if more
277
+ (apply - xy more)
278
+ xy)))
279
+
280
+ (defn inc
281
+ [x]
282
+ (+ x 1))
283
+
284
+ (defn dec
285
+ [x]
286
+ (- x 1))
287
+
288
+ ;; TODO: zero arity that returns 1
289
+ ;; TODO: one arity that returns x (i.e. x * 1)
290
+ (defn *
291
+ [x y & more]
292
+ (let [xy (.* x y)]
293
+ (if more
294
+ (apply * xy more)
295
+ xy)))
296
+
297
+ ;; TODO: one arity that returns 1 / x
298
+ (defn /
299
+ [x y & more]
300
+ (let [xy (./ x y)]
301
+ (if more
302
+ (apply / xy more)
303
+ xy)))
304
+
305
+ (defn <
306
+ [x & xs]
307
+ (boolean (reduce (fn [x y] (if (and x (.< x y)) y)) x xs)))
308
+
309
+ (defn <=
310
+ [x & xs]
311
+ (boolean (reduce (fn [x y] (if (and x (.<= x y)) y)) x xs)))
312
+
313
+ (defn =
314
+ [x & xs]
315
+ (boolean (reduce (fn [x y] (if (and x (.== x y)) y)) x xs)))
316
+
317
+ (defn not=
318
+ [& xs]
319
+ (not (apply = xs)))
320
+
321
+ (defn >
322
+ [x & xs]
323
+ (boolean (reduce (fn [x y] (if (and x (.> x y)) y)) x xs)))
324
+
325
+ (defn >=
326
+ [x & xs]
327
+ (boolean (reduce (fn [x y] (if (and x (.>= x y)) y)) x xs)))
328
+
329
+ (defn pos?
330
+ [x]
331
+ (> x 0))
332
+
333
+ (defn neg?
334
+ [x]
335
+ (< x 0))
336
+
337
+ (defn zero?
338
+ [x]
339
+ (= 0 x))
229
340
 
230
341
  ;; STRINGS & KEYWORDS
231
342
 
232
- (def str
233
- (fn str [& args]
234
- (.join (map .to_s args))))
343
+ (defn str
344
+ [& args]
345
+ (.join (map .to_s args)))
346
+
347
+ (defn name
348
+ [x]
349
+ (if (string? x)
350
+ x
351
+ (.name x)))
235
352
 
236
- (def name
237
- (fn name [x]
238
- (if (string? x)
239
- x
240
- (.name x))))
353
+ (defn read-string
354
+ [s]
355
+ (first (RubyLisp::Reader::read_str s)))
356
+
357
+ ;; problem: this is defined in rubylisp.core, so code is evaluated there
358
+ (defn load-string
359
+ [s]
360
+ (eval (RubyLisp::Reader::read_str s)))
241
361
 
242
362
  ;; I/O
243
363
 
244
- (def pr-str
245
- (fn pr-str [& args]
246
- (if (zero? (count args))
247
- ""
248
- (apply RubyLisp::Printer::pr_str args))))
364
+ (defn pr-str
365
+ [& args]
366
+ (if (zero? (count args))
367
+ ""
368
+ (apply RubyLisp::Printer::pr_str args)))
369
+
370
+ (defn prn
371
+ [& args]
372
+ (Kernel::puts (apply pr-str args))
373
+ nil)
249
374
 
250
- (def prn
251
- (fn prn [& args]
252
- (Kernel::puts (apply pr-str args))
253
- nil))
375
+ (defn print
376
+ [& args]
377
+ (Kernel::print (.join (map str args) " "))
378
+ nil)
254
379
 
255
- (def print
256
- (fn print [& args]
257
- (Kernel::print (.join (map str args) " "))
258
- nil))
380
+ (defn println
381
+ [& args]
382
+ (Kernel::puts (.join (map str args) " "))
383
+ nil)
259
384
 
260
- (def println
261
- (fn print [& args]
262
- (Kernel::puts (.join (map str args) " "))
263
- nil))
385
+ (defn slurp
386
+ [filename]
387
+ (File::read filename))
388
+
389
+ (defn load-file
390
+ [filename]
391
+ (load-string (slurp filename)))
264
392
 
265
393
  ;; RUBY INTEROP
266
394
 
267
- (def =@
268
- (fn =@ [obj kw value]
269
- (.instance_variable_set obj (.to_sym (+ "@" (name kw))) value)))
395
+ (defn =@
396
+ [obj kw value]
397
+ (.instance_variable_set obj (.to_sym (+ "@" (name kw))) value))
398
+
399
+ (defn class
400
+ [x]
401
+ (.class x))
402
+
403
+ ;; CONCURRENCY
404
+
405
+ (defn deref
406
+ [x]
407
+ (.deref x))
408
+
409
+ (defn atom
410
+ [value]
411
+ (Concurrent::Atom::new value))
412
+
413
+ (defn atom?
414
+ [value]
415
+ (.is_a? value Concurrent::Atom))
270
416
 
271
- (def class
272
- (fn class [x]
273
- (.class x)))
417
+ (defn swap!
418
+ [a f & args]
419
+ (call-with-block .swap a (if (nil? args) [] args) f))
274
420
 
421
+ (defn reset!
422
+ [a new-value]
423
+ (.reset a new-value))
data/rubylisp.gemspec CHANGED
@@ -31,4 +31,5 @@ Gem::Specification.new do |spec|
31
31
  spec.add_development_dependency "rake", "~> 10.0"
32
32
  spec.add_development_dependency "rspec", "~> 3.0"
33
33
  spec.add_runtime_dependency 'hamster', '3.0.0'
34
+ spec.add_runtime_dependency 'concurrent-ruby', '1.0.5'
34
35
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rbl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dave Yarwood
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-04-11 00:00:00.000000000 Z
11
+ date: 2017-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - '='
53
53
  - !ruby/object:Gem::Version
54
54
  version: 3.0.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: concurrent-ruby
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.0.5
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '='
67
+ - !ruby/object:Gem::Version
68
+ version: 1.0.5
55
69
  description: A Lisp dialect of Ruby
56
70
  email:
57
71
  - dave.yarwood@gmail.com
@@ -73,11 +87,14 @@ files:
73
87
  - lib/rubylisp.rb
74
88
  - lib/rubylisp/environment.rb
75
89
  - lib/rubylisp/evaluator.rb
90
+ - lib/rubylisp/function.rb
76
91
  - lib/rubylisp/parser.rb
77
92
  - lib/rubylisp/printer.rb
93
+ - lib/rubylisp/rbl_readline.rb
78
94
  - lib/rubylisp/reader.rb
79
95
  - lib/rubylisp/repl.rb
80
96
  - lib/rubylisp/types.rb
97
+ - lib/rubylisp/util.rb
81
98
  - lib/rubylisp/version.rb
82
99
  - rubylisp.gemspec
83
100
  - rubylisp/core.rbl