nydp 0.0.12 → 0.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e7ea4e19c5b46b3a1c56299814f4412262c19ee
4
- data.tar.gz: e812a2a39dab9ac0eb1a27b8cce1d6f0fd0b8f21
3
+ metadata.gz: ebd833948c836f583d77adc0028df3838bd30ed3
4
+ data.tar.gz: 85458c42aa0466e0802771a3a62b3593cc26d25d
5
5
  SHA512:
6
- metadata.gz: 6b65eac655935ae485b2c66e4e90f50dce3b5fcab5afb7f4c2394ae7f5a72b1451a65f24dadcb72460ad2e6f5b51a4e4c6ccbf7353ebc2d31aa8bc9294292d47
7
- data.tar.gz: 95d9519c024596480c2a604db56055bfe6d5ec929c0b57a3c5356ff0b1150b92c698199f35116036c85ad0431d6d083918279abeab3640dbfa736af4b937f444
6
+ metadata.gz: 6b0981f75b8ecf590694377973f0bc9b013250cd54ad0278d0b79cfba43cc6c8f870f4842238e1df43448fdcfad15a2cb7634c2b30c141b60dbb1bca87a610ee
7
+ data.tar.gz: cd44bec0ad3c3fe9b1bfc8c38937ac5850de8529b0f74004378bbbae3dbe376d9e39c02ea5db3c1383888b26bcf8f6fea34fc50adf634a1e8a3ef134587d598a
@@ -21,7 +21,7 @@
21
21
 
22
22
  (assign pre-compile-msg
23
23
  (fn (src compiled)
24
- (pre-compile-msg "pre-compile" src "\n -> " compiled)
24
+ (p "pre-compile" src "\n -> " compiled)
25
25
  compiled))
26
26
 
27
27
  (assign pre-compile-raw
@@ -1,8 +1,6 @@
1
- ; -*- lisp -*-
2
-
3
1
  (def map (f things)
4
2
  (if (no things)
5
3
  nil
6
- (pair? things)
7
- (cons (f (car things)) (map f (cdr things)))
8
- (map f (list things))))
4
+ (pair? things)
5
+ (cons (f (car things)) (map f (cdr things)))
6
+ (map f (list things))))
@@ -1,5 +1,3 @@
1
- ; -*- lisp -*-
2
-
3
1
  (mac unless (arg . body)
4
2
  `(if (no ,arg) (do ,@body)))
5
3
 
@@ -1,10 +1,3 @@
1
- ; -*- lisp -*-
2
-
3
- (def each (f acc things)
4
- (if things
5
- (each f (f acc (car things)) (cdr things))
6
- acc))
7
-
8
1
  (def eachr (f things)
9
2
  (when things
10
3
  (eachr f (cdr things))
@@ -46,6 +39,15 @@
46
39
  (def string-pieces pieces
47
40
  (joinstr "" pieces))
48
41
 
42
+ (def detect (f things)
43
+ (if (pair? things)
44
+ (let it (car things)
45
+ (or
46
+ (and (f it) it)
47
+ (detect f (cdr things))))
48
+ (f things)
49
+ things))
50
+
49
51
  (def nth (n things)
50
52
  (if (eq? n 0)
51
53
  (car things)
@@ -122,3 +124,20 @@
122
124
  `(map (fn (,x) ,expr) ,things))
123
125
 
124
126
  (def empty? (things) (eq? (len things) 0))
127
+
128
+ (mac each (var things code)
129
+ (w/uniq (xs c)
130
+ `((rfn ,c (,xs)
131
+ (if (pair? ,xs)
132
+ (do
133
+ (let ,var (car ,xs) ,code)
134
+ (,c (cdr ,xs)))))
135
+ ,things)))
136
+
137
+ (def reduce (f things)
138
+ ((rfn rd (acc list)
139
+ (if (pair? list)
140
+ (rd (f acc (car list))
141
+ (cdr list))
142
+ acc))
143
+ (car things) (cdr things)))
@@ -21,6 +21,7 @@
21
21
  (def execute-test (desc test passf failf verbose)
22
22
  (if (eq? 'suite (car test))
23
23
  (execute-tests (+ desc " - " (cadr test)) (cddr test) passf failf verbose)
24
+ (!eq? 'comment (car test))
24
25
  (execute-single-test desc test passf failf verbose)))
25
26
 
26
27
  (def execute-single-test (desc test passf failf verbose)
@@ -0,0 +1,26 @@
1
+
2
+ (assign prefix-list-prefixes ())
3
+
4
+ (def prefix-match-fn (txt)
5
+ (fn (rule) (string-match txt (car rule))))
6
+
7
+ (def find-prefix-rule (prefix)
8
+ (cdr:detect (prefix-match-fn prefix)
9
+ prefix-list-prefixes))
10
+
11
+ (mac prefix-list (prefix list)
12
+ (let handler (find-prefix-rule prefix)
13
+ (and handler (handler prefix list))))
14
+
15
+ (mac define-prefix-list-macro (regex prefix-var list-var . body)
16
+ `(push (cons ,regex (fn (,prefix-var ,list-var) ,@body))
17
+ prefix-list-prefixes))
18
+
19
+ ;;
20
+ ;; so you can write (map λa(upcase a.name) people)
21
+ ;;
22
+ ;; instead of (map (fn (a) (upcase a.name)) people)
23
+ ;;
24
+ (define-prefix-list-macro "^λ.+" vars expr
25
+ (let var-list (map sym (cdr:string-split vars))
26
+ `(fn ,var-list ,expr)))
@@ -138,6 +138,35 @@
138
138
  (mapx '(1 2 3 4) n (* n 2))
139
139
  (2 4 6 8))))
140
140
 
141
+ (suite "reduce"
142
+ ("it applies a function cumulatively over a list"
143
+ (reduce + '(1 2 3))
144
+ 6))
145
+
146
+ (suite "detect"
147
+ ("returns first matching item in a list"
148
+ (detect (fn (x) (eq? (len x) 2))
149
+ (list "foo" "bar" "xx" "pp"))
150
+ "xx")
151
+
152
+ ("returns nil when nothing matches"
153
+ (detect (fn (x) (eq? (len x) 20))
154
+ (list "foo" "bar" "xx" "pp"))
155
+ nil)
156
+
157
+ ;; kind of pointless
158
+ ("returns nil if nil is the matching item"
159
+ (detect no (list "foo" "bar" nil "pp"))
160
+ nil)
161
+
162
+ ("returns item if it's an atom and matches"
163
+ (detect (fn (x) (eq? (len x) 2)) "zz")
164
+ "zz")
165
+
166
+ ("returns nil if it's an atom and doesn't match"
167
+ (detect (fn (x) (eq? (len x) 20))
168
+ "zz")
169
+ nil))
141
170
 
142
171
  (suite "pre-compile"
143
172
  (suite "bang-syntax"
@@ -0,0 +1,5 @@
1
+ (register-test
2
+ '(suite "'each Tests"
3
+ ("iterates over each item in list"
4
+ (let acc 0 (each x '(1 2 3 4) (assign acc (+ x acc))) acc)
5
+ 10)))
@@ -25,6 +25,11 @@
25
25
  (list m.match m.captures))
26
26
  ("and" nil))
27
27
 
28
+ ("no match with regexp"
29
+ (let m (string-match "a and b and c and d" "not-in-string")
30
+ (list m.match m.captures))
31
+ (nil nil))
32
+
28
33
  ("match with regexp and capturing groups"
29
34
  (let m (string-match " foo\b bar" "(^\\s+)")
30
35
  (list m.match m.captures))
@@ -92,6 +97,11 @@
92
97
  (pre-compile '(= this 'that))
93
98
  (assign this 'that)))
94
99
 
100
+ (suite "argument default value"
101
+ ("is nil"
102
+ ( (fn (x y z) (list x y (car z))) 'a 'b )
103
+ (a b nil)))
104
+
95
105
  (suite "hash"
96
106
  ("hash-lookup"
97
107
  (pre-compile 'a.b.c)
@@ -12,6 +12,27 @@
12
12
  (parse "{foo bar 1 2 3}")
13
13
  ((brace-list foo bar 1 2 3))))
14
14
 
15
+ (suite "prefix-list"
16
+ ("parse quasiquote"
17
+ (parse "`(1 2 3)")
18
+ ((quasiquote (1 2 3))))
19
+
20
+ ("parse unquote unquote-splicing"
21
+ (parse ",,@(1 2 3)")
22
+ ((unquote (unquote-splicing (1 2 3)))))
23
+
24
+ ("parse unquote"
25
+ (parse ",(1 2 3)")
26
+ ((unquote (1 2 3))))
27
+
28
+ ("parse custom prefix-lists"
29
+ (parse "x(1 2 3)")
30
+ ((prefix-list "x" (1 2 3))))
31
+
32
+ ("parse custom prefix-lists with a special-syntax prefix"
33
+ (parse "x.y(1 2 3)")
34
+ ((prefix-list "x.y" (1 2 3)))))
35
+
15
36
  (suite "parse"
16
37
  ("parses an empty symbol"
17
38
  (parse "||")
@@ -21,6 +42,14 @@
21
42
  (parse "this:that")
22
43
  ((colon-syntax this that)) )
23
44
 
45
+ ("parses a percent-syntax symbol"
46
+ (parse "this%that")
47
+ ((percent-syntax this that)) )
48
+
49
+ ("parses a percent-prefix-syntax symbol"
50
+ (parse "%this-and-that")
51
+ ((percent-syntax || this-and-that)) )
52
+
24
53
  ("parses a dot-syntax symbol"
25
54
  (parse "this.that.zozo")
26
55
  ((dot-syntax this that zozo)) )
@@ -74,4 +103,7 @@
74
103
  (len (parse-in-string (joinstr "" (list "hello " '~ " world"))))
75
104
  13)
76
105
 
106
+ ("reports parse errors gracefully"
107
+ (on-err "CAUGHT: ~err" (parse-in-string (joinstr "" "blah ~~(\"stri...")))
108
+ "CAUGHT: parse error: \"unterminated string\" in\n blah ~~(\"stri..." )
77
109
  )))
@@ -0,0 +1,16 @@
1
+ (register-test
2
+ '(suite "syntax tests"
3
+ (suite "lambda shortcut"
4
+ ("one argument"
5
+ (map λa(len a.name)
6
+ (list { name "bob" } { name "willy" } { name "pteradactyl" }))
7
+ (3 5 11))
8
+
9
+ ("with two args"
10
+ (reduce λxy(joinstr ":" x y)
11
+ '(a b c d e f))
12
+ "a:b:c:d:e:f")
13
+
14
+ ("with two args, to be sure"
15
+ (λpq(+ p (* p q)) 3 5)
16
+ 18))))
@@ -12,20 +12,27 @@ class Nydp::Builtin::HashGet
12
12
  attr_accessor :ns
13
13
  def initialize ns ; @ns = ns; end
14
14
  def builtin_invoke vm, args
15
- hash = args.car
15
+ hsh = args.car
16
16
  key = args.cdr.car
17
- case hash
17
+ case hsh
18
18
  when Nydp::Hash
19
- vm.push_arg(hash[key] || Nydp.NIL)
19
+ vm.push_arg(hsh[key] || Nydp.NIL)
20
20
  when NilClass, Nydp.NIL
21
21
  vm.push_arg Nydp.NIL
22
22
  else
23
- if hash.respond_to? :[]
24
- key = n2r args.cdr.car
25
- vm.push_arg(r2n hash[key], ns)
26
- else
27
- raise "hash-get: Not a hash: #{hash.class.name}"
28
- end
23
+ v = hsh.respond_to?(:[]) ? hsh[n2r key] : ruby_call(hsh, key)
24
+ vm.push_arg(r2n v, ns)
25
+ end
26
+ end
27
+
28
+ def ruby_call obj, method_name
29
+ if obj.respond_to? :_nydp_safe_methods
30
+ m = n2r(method_name).to_s.to_sym
31
+ allowed = obj._nydp_safe_methods
32
+
33
+ obj.send n2r(m) if allowed.include?(m)
34
+ else
35
+ raise "hash-get: Not a hash: #{obj.class.name}"
29
36
  end
30
37
  end
31
38
  end
@@ -6,8 +6,12 @@ class Nydp::Builtin::ParseInString
6
6
  end
7
7
 
8
8
  def builtin_invoke vm, args
9
- tokens = Nydp::Tokeniser.new Nydp::StringReader.new args.car.to_s
9
+ parsable = args.car.to_s
10
+ tokens = Nydp::Tokeniser.new Nydp::StringReader.new parsable
10
11
  expr = @parser.string(tokens, "", :eof)
11
12
  vm.push_arg expr
13
+ rescue Exception => e
14
+ new_msg = "parse error: #{e.message.inspect} in\n#{Nydp.indent_text parsable}"
15
+ raise Nydp::Error.new new_msg
12
16
  end
13
17
  end
@@ -19,12 +19,8 @@ class Nydp::LexicalContext
19
19
  end
20
20
  end
21
21
 
22
- def at name
23
- values[name]
24
- end
25
-
26
22
  def at_index index
27
- values[index]
23
+ values[index] || Nydp.NIL
28
24
  end
29
25
 
30
26
  def set name, value
data/lib/nydp/parser.rb CHANGED
@@ -31,7 +31,8 @@ module Nydp
31
31
  when /^(.*),@$/
32
32
  prefix_list $1, Pair.from_list([sym(:"unquote-splicing"), list])
33
33
  else
34
- list
34
+ pfx = Nydp::StringAtom.new prefix
35
+ Pair.from_list([sym(:"prefix-list"), pfx, list])
35
36
  end
36
37
  end
37
38
 
@@ -41,6 +42,7 @@ module Nydp
41
42
 
42
43
  SYMBOL_OPERATORS =
43
44
  [
45
+ [ /%/, "percent-syntax" ],
44
46
  [ /\!/, "bang-syntax" ],
45
47
  [ /&/, "ampersand-syntax" ],
46
48
  [ /\./, "dot-syntax" ],
@@ -119,6 +121,7 @@ module Nydp
119
121
  def string token_stream, open_delimiter, close_delimiter
120
122
  fragments = [sym(:"string-pieces")]
121
123
  string_token = token_stream.next_string_fragment(open_delimiter, close_delimiter, INTERPOLATION_SIGN, INTERPOLATION_ESCAPES)
124
+ raise "unterminated string" if string_token.nil?
122
125
  fragments << Nydp::StringAtom.new(string_token.string, string_token)
123
126
  while !(string_token.is_a? StringFragmentCloseToken)
124
127
  fragments << expression(token_stream)
data/lib/nydp/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Nydp
2
- VERSION = "0.0.12"
2
+ VERSION = "0.1.0"
3
3
  end
data/spec/hash_spec.rb CHANGED
@@ -2,6 +2,19 @@ require "spec_helper"
2
2
 
3
3
  describe Nydp::Hash do
4
4
 
5
+ class TestThing
6
+ attr_accessor :a, :b, :c
7
+ def initialize a, b, c
8
+ @a, @b, @c = a, b, c
9
+ end
10
+
11
+ def inspect
12
+ "(TestThing #{a.inspect} #{b.inspect})"
13
+ end
14
+
15
+ def _nydp_safe_methods ; %i{ a b } ; end
16
+ end
17
+
5
18
  let(:vm) { Nydp::VM.new }
6
19
 
7
20
  describe "#to_ruby" do
@@ -181,6 +194,44 @@ describe Nydp::Hash do
181
194
  end
182
195
  end
183
196
 
197
+ describe "friendly non-hashes" do
198
+ let(:ahash) { TestThing.new 123, "hello there", "private" }
199
+
200
+ describe "hash get" do
201
+ it "returns a plain number" do
202
+ k = Nydp::Symbol.mk "a", ns
203
+ args = [ ahash, k ]
204
+
205
+ Nydp::Builtin::HashGet.new(ns).invoke vm, pair_list(args)
206
+ expect(vm.pop_arg).to eq 123
207
+ end
208
+
209
+ it "converts ruby value to nydp value" do
210
+ k = Nydp::Symbol.mk "b", ns
211
+ args = [ ahash, k ]
212
+
213
+ Nydp::Builtin::HashGet.new(ns).invoke vm, pair_list(args)
214
+ expect(vm.pop_arg).to eq Nydp::StringAtom.new("hello there")
215
+ end
216
+
217
+ it "converts string keys to method names" do
218
+ k = Nydp::StringAtom.new "b"
219
+ args = [ ahash, k ]
220
+
221
+ Nydp::Builtin::HashGet.new(ns).invoke vm, pair_list(args)
222
+ expect(vm.pop_arg).to eq Nydp::StringAtom.new("hello there")
223
+ end
224
+
225
+ it "returns nil for unavailable methods" do
226
+ k = Nydp::Symbol.mk "c", ns
227
+ args = [ ahash, k ]
228
+
229
+ Nydp::Builtin::HashGet.new(ns).invoke vm, pair_list(args)
230
+ expect(vm.pop_arg).to eq Nydp.NIL
231
+ end
232
+ end
233
+ end
234
+
184
235
  describe "non-hash" do
185
236
  let(:ahash) { Nydp::StringAtom.new "this here ain't no hash, hombre" }
186
237
 
@@ -206,8 +257,8 @@ raised
206
257
 
207
258
  describe "hash get" do
208
259
  it "converts ruby value to nydp value" do
209
- k = Nydp::Symbol.mk "keysym", ns
210
- args = [ ahash, k ]
260
+ k = Nydp::Symbol.mk "keysym", ns
261
+ args = [ ahash, k ]
211
262
 
212
263
  begin
213
264
  Nydp::Builtin::HashGet.new(ns).invoke vm, pair_list(args)
@@ -215,7 +266,7 @@ raised
215
266
  error = e
216
267
  end
217
268
 
218
- expect(error.message.gsub(/at \/.*:in `builtin_invoke'/, '<error info>')).to eq "Called builtin/hash-get
269
+ expect(error.message.gsub(/at \/.*:in `ruby_call'/, '<error info>')).to eq "Called builtin/hash-get
219
270
  with args (\"this here ain't no hash, hombre\" keysym)
220
271
  raised
221
272
  hash-get: Not a hash: Nydp::StringAtom
data/spec/parser_spec.rb CHANGED
@@ -13,6 +13,7 @@ describe Nydp::Parser do
13
13
  let(:quote) { Nydp::Symbol.mk :quote, ns }
14
14
  let(:quasiquote) { Nydp::Symbol.mk :quasiquote, ns }
15
15
  let(:unquote) { Nydp::Symbol.mk :unquote, ns }
16
+ let(:prefix_list) { Nydp::Symbol.mk :"prefix-list", ns }
16
17
  let(:unquote_splicing) { Nydp::Symbol.mk :"unquote-splicing", ns }
17
18
  let(:comment) { Nydp::Symbol.mk :comment, ns }
18
19
  let(:dotsyn) { Nydp::Symbol.mk :"dot-syntax", ns }
@@ -214,6 +215,10 @@ describe Nydp::Parser do
214
215
  expect(parse ",(bar)").to eq pair_list([unquote, pair_list([bar])])
215
216
  end
216
217
 
218
+ it "retains otherwise unidentified list prefixes" do
219
+ expect(parse "%wong(bar)").to eq pair_list([prefix_list, "%wong", pair_list([bar])])
220
+ end
221
+
217
222
  it "should do some complicated unquote stuff with lists" do
218
223
  expect(parse("`(a b `(c d ,(+ 1 2) ,,(+ 3 4)))").inspect).to eq "(quasiquote (a b (quasiquote (c d (unquote (+ 1 2)) (unquote (unquote (+ 3 4)))))))"
219
224
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: nydp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.12
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Conan Dalton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-23 00:00:00.000000000 Z
11
+ date: 2015-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -91,13 +91,16 @@ files:
91
91
  - lib/lisp/core-04-utils.nydp
92
92
  - lib/lisp/core-05-test-runner.nydp
93
93
  - lib/lisp/core-06-benchmarking.nydp
94
+ - lib/lisp/core-07-prefix-list.nydp
94
95
  - lib/lisp/tests/boot-tests.nydp
95
96
  - lib/lisp/tests/builtin-tests.nydp
96
97
  - lib/lisp/tests/dynamic-scope-test.nydp
98
+ - lib/lisp/tests/each-tests.nydp
97
99
  - lib/lisp/tests/error-tests.nydp
98
100
  - lib/lisp/tests/foundation-test.nydp
99
101
  - lib/lisp/tests/invocation-tests.nydp
100
102
  - lib/lisp/tests/parser-tests.nydp
103
+ - lib/lisp/tests/syntax-tests.nydp
101
104
  - lib/nydp.rb
102
105
  - lib/nydp/assignment.rb
103
106
  - lib/nydp/builtin.rb