nydp 0.0.12 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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