nydp 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.
- checksums.yaml +4 -4
- data/lib/lisp/boot.nydp +44 -1
- data/lib/lisp/test-runner.nydp +1 -2
- data/lib/lisp/tests/boot-tests.nydp +80 -28
- data/lib/lisp/tests/foundation-test.nydp +53 -1
- data/lib/nydp/builtin.rb +15 -0
- data/lib/nydp/builtin/hash.rb +34 -8
- data/lib/nydp/builtin/parse.rb +15 -0
- data/lib/nydp/compiler.rb +6 -0
- data/lib/nydp/core.rb +3 -2
- data/lib/nydp/hash.rb +2 -0
- data/lib/nydp/helper.rb +27 -0
- data/lib/nydp/literal.rb +2 -0
- data/lib/nydp/pair.rb +5 -0
- data/lib/nydp/parser.rb +14 -7
- data/lib/nydp/runner.rb +2 -0
- data/lib/nydp/string_atom.rb +1 -1
- data/lib/nydp/string_token.rb +3 -3
- data/lib/nydp/symbol.rb +13 -3
- data/lib/nydp/tokeniser.rb +4 -2
- data/lib/nydp/version.rb +1 -1
- data/spec/hash_spec.rb +98 -0
- data/spec/literal_spec.rb +9 -0
- data/spec/{nypd_spec.rb → nydp_spec.rb} +0 -0
- data/spec/pair_spec.rb +7 -1
- data/spec/parser_spec.rb +12 -0
- data/spec/string_atom_spec.rb +9 -0
- data/spec/symbol_spec.rb +7 -0
- metadata +12 -6
- data/spec/boot_spec.rb +0 -69
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56ae5257ab6792eeaef112c3e81991dae7c43ce1
|
4
|
+
data.tar.gz: 327b5770bc8f1c442202d340f5392288e58efdbe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 65b2df58e4d78c39e8ea8aacb1e3e0298269b5f2b03f6d9fb11e3ce44bf45012cd35b7b397a74de46d6e10f36a1b64be179c9efae28d5ca709959c50c9574e2b
|
7
|
+
data.tar.gz: 9e787875c9011054dbaa9b416b84ef162f798bea1f5c33fde9a834322fc54e8435d537a37ce7a7e62e1972db95103aca67a3336b2e727bf7da07b94953af34f8
|
data/lib/lisp/boot.nydp
CHANGED
@@ -30,6 +30,8 @@
|
|
30
30
|
(fn (arg)
|
31
31
|
(assign *debug-pre-compile* arg)))
|
32
32
|
|
33
|
+
(assign *debug-pre-compile* nil)
|
34
|
+
|
33
35
|
(assign pre-compile-expr
|
34
36
|
(fn (name body)
|
35
37
|
(mac-expand (hash-get macs name) name body)))
|
@@ -192,6 +194,14 @@
|
|
192
194
|
(cons (list (car a) (car b))
|
193
195
|
(zip (cdr a) (cdr b)))))
|
194
196
|
|
197
|
+
(def reversify (things acc)
|
198
|
+
(if (no things)
|
199
|
+
acc
|
200
|
+
(reversify (cdr things)
|
201
|
+
(cons (car things) acc))))
|
202
|
+
|
203
|
+
(def rev (things) (reversify things nil))
|
204
|
+
|
195
205
|
(mac push (x things)
|
196
206
|
`(assign ,things (cons ,x ,things)))
|
197
207
|
|
@@ -252,10 +262,14 @@
|
|
252
262
|
(iso (car x) (car y))
|
253
263
|
(iso (cdr x) (cdr y)))))
|
254
264
|
|
255
|
-
(def isa
|
265
|
+
(def isa (type obj) (eq? (type-of obj) type))
|
256
266
|
(mac just (arg) arg)
|
257
267
|
(def quotify (arg) `(quote ,arg))
|
258
268
|
|
269
|
+
(def caris (obj things)
|
270
|
+
(and (isa 'pair things)
|
271
|
+
(eq? (car things) obj)))
|
272
|
+
|
259
273
|
(def len (xs)
|
260
274
|
(if (pair? xs)
|
261
275
|
(+ 1 (len (cdr xs)))
|
@@ -264,7 +278,10 @@
|
|
264
278
|
(def build-keyword-args (pairs)
|
265
279
|
(map (fn (ab) `(list (quote ,(car ab)) ,@(cdr ab))) pairs))
|
266
280
|
|
281
|
+
(assign dynamics (hash))
|
282
|
+
|
267
283
|
(mac dynamic (name)
|
284
|
+
(hash-set dynamics name t)
|
268
285
|
(let with-mac-name (sym "w/~name")
|
269
286
|
(w/uniq prev
|
270
287
|
`(do
|
@@ -276,3 +293,29 @@
|
|
276
293
|
(hash-set (thread-locals) ',',name ,',prev)
|
277
294
|
,result))))
|
278
295
|
(def ,name () (hash-get (thread-locals) ',name))))))
|
296
|
+
|
297
|
+
;; (build-hash-getters '(a b c))
|
298
|
+
;; => (hash-get (hash-get a 'b) 'c)
|
299
|
+
(def build-hash-getters (names acc)
|
300
|
+
(if (no acc)
|
301
|
+
(build-hash-getters (cdr names) (car names))
|
302
|
+
names
|
303
|
+
(build-hash-getters (cdr names) `(hash-get ,acc ',(car names)))
|
304
|
+
acc))
|
305
|
+
|
306
|
+
(mac hash-lookup (names)
|
307
|
+
(build-hash-getters names nil))
|
308
|
+
|
309
|
+
(mac dot-syntax names `(hash-lookup ,names))
|
310
|
+
|
311
|
+
(def dot-syntax-assignment (names value-expr)
|
312
|
+
(let rnames (rev names)
|
313
|
+
`(hash-set ,(build-hash-getters (rev (cdr rnames)) nil)
|
314
|
+
',(car rnames)
|
315
|
+
,value-expr)))
|
316
|
+
|
317
|
+
(mac = (name value)
|
318
|
+
(if (isa 'symbol name)
|
319
|
+
`(assign ,name ,value)
|
320
|
+
(caris 'dot-syntax name)
|
321
|
+
(dot-syntax-assignment (cdr name) value)))
|
data/lib/lisp/test-runner.nydp
CHANGED
@@ -16,8 +16,7 @@
|
|
16
16
|
(/ passed (+ passed failed)))))
|
17
17
|
|
18
18
|
(def run-tests (tests passf failf verbose)
|
19
|
-
(execute-test "" tests passf failf verbose)
|
20
|
-
results)
|
19
|
+
(execute-test "" tests passf failf verbose))
|
21
20
|
|
22
21
|
(def execute-test (desc test passf failf verbose)
|
23
22
|
(if (eq? 'suite (car test))
|
@@ -27,6 +27,26 @@
|
|
27
27
|
(pairs '(1 a 2 b 3 c))
|
28
28
|
((1 a) (2 b) (3 c)))
|
29
29
|
|
30
|
+
("'rev reverses a list"
|
31
|
+
(rev '(a b c))
|
32
|
+
(c b a))
|
33
|
+
|
34
|
+
("'rev handles nil"
|
35
|
+
(rev nil)
|
36
|
+
nil)
|
37
|
+
|
38
|
+
("'rev doesn't recurse"
|
39
|
+
(rev '(a b (c d e) f g))
|
40
|
+
(g f (c d e) b a))
|
41
|
+
|
42
|
+
("joins elements into a string"
|
43
|
+
(joinstr "" '("foo" "bar" "bax"))
|
44
|
+
"foobarbax")
|
45
|
+
|
46
|
+
("joins elements into a string"
|
47
|
+
(joinstr " - " '(1 2 3))
|
48
|
+
"1 - 2 - 3")
|
49
|
+
|
30
50
|
("'flatten returns a flat list of things"
|
31
51
|
(flatten '((poo (x) (* x x)) (1 2 3)))
|
32
52
|
(poo x * x x 1 2 3)))
|
@@ -36,34 +56,66 @@
|
|
36
56
|
(map (fn (x) (* x x)) '(1 2 3))
|
37
57
|
(1 4 9)))
|
38
58
|
|
39
|
-
(suite "
|
40
|
-
("
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
(
|
51
|
-
|
52
|
-
("
|
53
|
-
(
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
59
|
+
(suite "pre-compile"
|
60
|
+
("expands 'let"
|
61
|
+
(do
|
62
|
+
(def x+3*z (x y)
|
63
|
+
(let y 3
|
64
|
+
(fn (z) (* (+ x y) z))))
|
65
|
+
((x+3*z 2 99) 5))
|
66
|
+
25)
|
67
|
+
|
68
|
+
("expands 'and"
|
69
|
+
(pre-compile '(and a b c))
|
70
|
+
(cond a (cond b c)))
|
71
|
+
|
72
|
+
("expands 'or"
|
73
|
+
(do (reset-uniq-counter)
|
74
|
+
(pre-compile '(or a b c)))
|
75
|
+
((fn (ora-1)
|
76
|
+
(cond ora-1
|
77
|
+
ora-1
|
78
|
+
((fn (ora-2)
|
79
|
+
(cond ora-2
|
80
|
+
ora-2
|
81
|
+
((fn (ora-3)
|
82
|
+
(cond ora-3
|
83
|
+
ora-3
|
84
|
+
nil)) c))) b))) a))
|
85
|
+
|
86
|
+
("w/uniq provides unique variables for macro expansion"
|
87
|
+
(do (reset-uniq-counter)
|
88
|
+
(pre-compile '(w/uniq a foo)))
|
89
|
+
((fn (a) foo) (uniq 'a)))
|
90
|
+
|
91
|
+
(suite "quasiquote"
|
92
|
+
("same as quote for standalone item"
|
93
|
+
`a
|
94
|
+
a)
|
95
|
+
("same as quote for standalone list"
|
96
|
+
`(a b c)
|
97
|
+
(a b c))
|
98
|
+
("substitutes single variables"
|
99
|
+
(let b 10 `(a ,b c))
|
100
|
+
(a 10 c))
|
101
|
+
("substitutes a list"
|
102
|
+
(let b '(1 2 3) `(a ,@b c))
|
103
|
+
(a 1 2 3 c))
|
104
|
+
("substitutes a list at the end of a given list"
|
105
|
+
(let b '(1 2 3) `(a ,b ,@b))
|
106
|
+
(a (1 2 3) 1 2 3))
|
107
|
+
("more complicated substitution example"
|
108
|
+
(with (d '(1 2 3) g '(x y z)) `(a (b c ,d (e f ,@g))))
|
109
|
+
(a (b c (1 2 3) (e f x y z))))
|
110
|
+
("peeks inside nested quotes"
|
111
|
+
`(a b '(c ,(+ 1 2)))
|
112
|
+
(a b '(c 3)))
|
113
|
+
("handles nested unquote-splicing"
|
114
|
+
``(a ,,@(list '+ 1 2) b)
|
115
|
+
`((a ,(+ 1 2) b)))
|
116
|
+
("returns nested quasiquotes"
|
117
|
+
`(a b `(c d ,(+ 1 2) ,,(+ 3 4)))
|
118
|
+
(a b `(c d ,(+ 1 2) ,7)))))
|
67
119
|
|
68
120
|
(suite "build-keyword-args"
|
69
121
|
("takes a list of lists and returns the list with the first item of each sublist quoted"
|
@@ -28,7 +28,7 @@
|
|
28
28
|
(if t "hello" "goodbye")
|
29
29
|
"hello")
|
30
30
|
|
31
|
-
("nil is boolean
|
31
|
+
("nil is boolean false"
|
32
32
|
(if nil "hello" "goodbye")
|
33
33
|
"goodbye")
|
34
34
|
|
@@ -48,6 +48,58 @@
|
|
48
48
|
x)
|
49
49
|
43))
|
50
50
|
|
51
|
+
(suite "assignment with '="
|
52
|
+
("assigns a symbol"
|
53
|
+
(pre-compile '(= this 'that))
|
54
|
+
(assign this 'that)))
|
55
|
+
|
56
|
+
(suite "hash"
|
57
|
+
("hash-lookup"
|
58
|
+
(pre-compile 'a.b.c)
|
59
|
+
(hash-get (hash-get a 'b) 'c))
|
60
|
+
|
61
|
+
("hash assignment"
|
62
|
+
(pre-compile '(= a.b 42))
|
63
|
+
(hash-set a 'b 42))
|
64
|
+
|
65
|
+
("recursive hash assignment"
|
66
|
+
(pre-compile '(= a.b.c.d 42))
|
67
|
+
(hash-set (hash-get (hash-get a 'b) 'c) 'd 42)))
|
68
|
+
|
69
|
+
|
70
|
+
(suite "parse"
|
71
|
+
("parses a colon-syntax symbol"
|
72
|
+
(parse "this:that")
|
73
|
+
((colon-syntax this that)) )
|
74
|
+
|
75
|
+
("parses a dot-syntax symbol"
|
76
|
+
(parse "this.that.zozo")
|
77
|
+
((dot-syntax this that zozo)) )
|
78
|
+
|
79
|
+
("parses an expression"
|
80
|
+
(parse "(foo bar \"hello, String\") 1 2 (3 t nil) nil")
|
81
|
+
((foo bar "hello, String") 1 2 (3 t nil))))
|
82
|
+
|
83
|
+
(suite "isa"
|
84
|
+
("t for 'pair for list"
|
85
|
+
(isa 'pair '(a b c))
|
86
|
+
t)
|
87
|
+
("nil for 'pair for non-list"
|
88
|
+
(isa 'pair 42)
|
89
|
+
nil)
|
90
|
+
("t for 'symbol for symbol"
|
91
|
+
(isa 'symbol 'foo)
|
92
|
+
t)
|
93
|
+
("nil for 'symbol for non-symbol"
|
94
|
+
(isa 'symbol "foo")
|
95
|
+
nil)
|
96
|
+
("t for 'string for string"
|
97
|
+
(isa 'string "foo")
|
98
|
+
t)
|
99
|
+
("nil for 'string for string"
|
100
|
+
(isa 'string '(a b c))
|
101
|
+
nil))
|
102
|
+
|
51
103
|
(suite "Lists"
|
52
104
|
(suite "cons"
|
53
105
|
("cons creates a list"
|
data/lib/nydp/builtin.rb
CHANGED
@@ -1,6 +1,21 @@
|
|
1
1
|
require 'nydp'
|
2
2
|
|
3
3
|
module Nydp::Builtin
|
4
|
+
module Base
|
5
|
+
def indent_text txt
|
6
|
+
txt.split(/\n/).map { |line| " #{line}"}.join("\n")
|
7
|
+
end
|
8
|
+
|
9
|
+
def invoke vm, args
|
10
|
+
builtin_invoke vm, args
|
11
|
+
rescue Exception => e
|
12
|
+
new_msg = "Invoking #{self.class.name}\nwith args #{args}\nraised\n#{indent_text e.message}"
|
13
|
+
raise $!, new_msg, $!.backtrace
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def inspect ; self.class.name ; end
|
18
|
+
def to_s ; self.class.name ; end
|
4
19
|
end
|
5
20
|
|
6
21
|
Dir[File.join(File.dirname(__FILE__), "builtin", "**/*.rb")].each {|f|
|
data/lib/nydp/builtin/hash.rb
CHANGED
@@ -1,30 +1,56 @@
|
|
1
|
+
require "nydp/hash"
|
2
|
+
|
1
3
|
class Nydp::Builtin::Hash
|
2
|
-
|
3
|
-
|
4
|
+
include Nydp::Helper, Nydp::Builtin::Base
|
5
|
+
def builtin_invoke vm, args
|
6
|
+
vm.push_arg(Nydp::Hash.new)
|
4
7
|
end
|
5
8
|
end
|
6
9
|
|
7
10
|
class Nydp::Builtin::HashGet
|
8
|
-
|
11
|
+
include Nydp::Helper, Nydp::Builtin::Base
|
12
|
+
attr_accessor :ns
|
13
|
+
def initialize ns ; @ns = ns; end
|
14
|
+
def builtin_invoke vm, args
|
9
15
|
hash = args.car
|
10
16
|
key = args.cdr.car
|
11
|
-
|
17
|
+
case hash
|
18
|
+
when Nydp::Hash
|
19
|
+
vm.push_arg(hash[key] || Nydp.NIL)
|
20
|
+
else
|
21
|
+
key = n2r args.cdr.car
|
22
|
+
vm.push_arg(r2n hash[key], ns)
|
23
|
+
end
|
12
24
|
end
|
13
25
|
end
|
14
26
|
|
15
27
|
class Nydp::Builtin::HashSet
|
16
|
-
|
28
|
+
include Nydp::Helper, Nydp::Builtin::Base
|
29
|
+
def builtin_invoke vm, args
|
17
30
|
hash = args.car
|
18
31
|
key = args.cdr.car
|
19
32
|
value = args.cdr.cdr.car
|
20
|
-
hash
|
33
|
+
case hash
|
34
|
+
when Nydp::Hash
|
35
|
+
hash[key] = value
|
36
|
+
else
|
37
|
+
hash[n2r key] = n2r value
|
38
|
+
end
|
21
39
|
vm.push_arg value
|
22
40
|
end
|
23
41
|
end
|
24
42
|
|
25
43
|
class Nydp::Builtin::HashKeys
|
26
|
-
|
44
|
+
include Nydp::Helper, Nydp::Builtin::Base
|
45
|
+
attr_accessor :ns
|
46
|
+
def initialize ns ; @ns = ns; end
|
47
|
+
def builtin_invoke vm, args
|
27
48
|
hash = args.car
|
28
|
-
|
49
|
+
case hash
|
50
|
+
when Nydp::Hash
|
51
|
+
vm.push_arg Nydp::Pair.from_list hash.keys
|
52
|
+
else
|
53
|
+
vm.push_arg r2n(hash.keys, ns)
|
54
|
+
end
|
29
55
|
end
|
30
56
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class Nydp::Builtin::Parse
|
2
|
+
def initialize ns
|
3
|
+
@parser = Nydp::Parser.new(ns)
|
4
|
+
end
|
5
|
+
|
6
|
+
def invoke vm, args
|
7
|
+
tokens = Nydp::Tokeniser.new Nydp::StringReader.new args.car.to_s
|
8
|
+
exprs = []
|
9
|
+
while !tokens.finished
|
10
|
+
expr = @parser.expression(tokens)
|
11
|
+
exprs << expr unless expr == nil
|
12
|
+
end
|
13
|
+
vm.push_arg Nydp::Pair.from_list exprs
|
14
|
+
end
|
15
|
+
end
|
data/lib/nydp/compiler.rb
CHANGED
@@ -8,6 +8,12 @@ module Nydp
|
|
8
8
|
extend Helper
|
9
9
|
|
10
10
|
def self.compile expression, bindings
|
11
|
+
compile_expr expression, bindings
|
12
|
+
rescue Exception => e
|
13
|
+
raise "failed to compile expression #{expression.inspect},\nerror was #{e.message}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.compile_expr expression, bindings
|
11
17
|
if expression.is_a? Nydp::Symbol
|
12
18
|
SymbolLookup.build expression, bindings
|
13
19
|
elsif literal? expression
|
data/lib/nydp/core.rb
CHANGED
@@ -37,6 +37,7 @@ module Nydp
|
|
37
37
|
Symbol.mk(:apply, ns).assign(Nydp::Builtin::Apply.new)
|
38
38
|
Symbol.mk(:error, ns).assign(Nydp::Builtin::Error.new)
|
39
39
|
Symbol.mk(:quit, ns).assign(Nydp::Builtin::Quit.new)
|
40
|
+
Symbol.mk(:parse, ns).assign(Nydp::Builtin::Parse.new(ns))
|
40
41
|
Symbol.mk(:p, ns).assign(Nydp::Builtin::Puts.new)
|
41
42
|
Symbol.mk(:PI, ns).assign Literal.new(3.1415)
|
42
43
|
Symbol.mk(:nil, ns).assign Nydp.NIL
|
@@ -57,9 +58,9 @@ module Nydp
|
|
57
58
|
Symbol.mk(:"eq?", ns).assign(Nydp::Builtin::IsEqual.new)
|
58
59
|
Symbol.mk(:"pair?", ns).assign(Nydp::Builtin::IsPair.new)
|
59
60
|
Symbol.mk(:"cdr-set", ns).assign(Nydp::Builtin::CdrSet.new)
|
60
|
-
Symbol.mk(:"hash-get", ns).assign(Nydp::Builtin::HashGet.new)
|
61
|
+
Symbol.mk(:"hash-get", ns).assign(Nydp::Builtin::HashGet.new ns)
|
61
62
|
Symbol.mk(:"hash-set", ns).assign(Nydp::Builtin::HashSet.new)
|
62
|
-
Symbol.mk(:"hash-keys", ns).assign(Nydp::Builtin::HashKeys.new)
|
63
|
+
Symbol.mk(:"hash-keys", ns).assign(Nydp::Builtin::HashKeys.new(ns))
|
63
64
|
Symbol.mk(:"vm-info", ns).assign Nydp::Builtin::VmInfo.new
|
64
65
|
Symbol.mk(:"pre-compile", ns).assign Nydp::Builtin::PreCompile.new
|
65
66
|
end
|
data/lib/nydp/hash.rb
ADDED
data/lib/nydp/helper.rb
CHANGED
@@ -1,5 +1,32 @@
|
|
1
1
|
module Nydp
|
2
|
+
R2NHELPERS = {
|
3
|
+
::Symbol => ->(obj, ns) { Nydp::Symbol.mk(obj, ns) },
|
4
|
+
Array => ->(obj, ns) { Nydp::Pair.from_list obj.map { |o| Nydp.r2n o, ns } },
|
5
|
+
String => ->(obj, ns) { Nydp::StringAtom.new obj.to_s },
|
6
|
+
NilClass => ->(obj, ns) { Nydp::Nil },
|
7
|
+
FalseClass => ->(obj, ns) { Nydp::Nil },
|
8
|
+
TrueClass => ->(obj, ns) { Nydp::T },
|
9
|
+
}
|
10
|
+
|
11
|
+
def self.n2r nydp
|
12
|
+
nydp.respond_to?(:to_ruby) ? nydp.to_ruby : nydp
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.r2n ruby_obj, ns
|
16
|
+
rklass = ruby_obj.class
|
17
|
+
R2NHELPERS.each do |hklass, proc|
|
18
|
+
if rklass <= hklass
|
19
|
+
return proc.call ruby_obj, ns
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
ruby_obj
|
24
|
+
end
|
25
|
+
|
2
26
|
module Helper
|
27
|
+
def n2r obj ; Nydp.n2r obj ; end
|
28
|
+
def r2n obj, ns ; Nydp.r2n obj, ns ; end
|
29
|
+
|
3
30
|
def sym? expr, name
|
4
31
|
expr.is_a?(Nydp::Symbol) && (expr.is? name)
|
5
32
|
end
|
data/lib/nydp/literal.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Nydp
|
2
2
|
class Literal
|
3
|
+
include Nydp::Helper
|
3
4
|
attr_reader :expression
|
4
5
|
|
5
6
|
def initialize expression
|
@@ -21,6 +22,7 @@ module Nydp
|
|
21
22
|
def nydp_type ; :literal ; end
|
22
23
|
def inspect ; @expression.inspect ; end
|
23
24
|
def to_s ; @expression.to_s ; end
|
25
|
+
def to_ruby ; n2r @expression ; end
|
24
26
|
|
25
27
|
def coerce _
|
26
28
|
[_, expression]
|
data/lib/nydp/pair.rb
CHANGED
@@ -18,6 +18,11 @@ class Nydp::Pair
|
|
18
18
|
def cdar ; car.cdr ; end
|
19
19
|
def cddr ; cdr.cdr ; end
|
20
20
|
|
21
|
+
def to_ruby list=[]
|
22
|
+
list << n2r(car)
|
23
|
+
cdr.is_a?(Nydp::Pair) ? cdr.to_ruby(list) : list
|
24
|
+
end
|
25
|
+
|
21
26
|
def self.parse_list list
|
22
27
|
if sym? list.slice(-2), "."
|
23
28
|
from_list(list[0...-2], list.slice(-1))
|
data/lib/nydp/parser.rb
CHANGED
@@ -40,6 +40,7 @@ module Nydp
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def parse_symbol txt
|
43
|
+
txt = txt.to_s
|
43
44
|
case txt
|
44
45
|
when /^[-+]?[0-9]*\.[0-9]+([eE][-+]?[0-9]+)?$/
|
45
46
|
txt.to_f
|
@@ -53,20 +54,22 @@ module Nydp
|
|
53
54
|
Pair.from_list [sym(:"unquote-splicing"), parse_symbol($1)]
|
54
55
|
when /^,(.+)$/
|
55
56
|
Pair.from_list [sym(:unquote), parse_symbol($1)]
|
57
|
+
when /^\.$/
|
58
|
+
sym txt
|
56
59
|
else
|
57
|
-
syms = txt.
|
60
|
+
syms = txt.split /\./, -1
|
58
61
|
return split_sym syms, sym("dot-syntax") if syms.length > 1
|
59
62
|
|
60
|
-
syms = txt.split
|
63
|
+
syms = txt.split /::/, -1
|
61
64
|
return split_sym syms, sym("colon-colon-syntax") if syms.length > 1
|
62
65
|
|
63
|
-
syms = txt.split
|
66
|
+
syms = txt.split /:/, -1
|
64
67
|
return split_sym syms, sym("colon-syntax") if syms.length > 1
|
65
68
|
|
66
|
-
syms = txt.split
|
69
|
+
syms = txt.split /->/, -1
|
67
70
|
return split_sym syms, sym("arrow-syntax") if syms.length > 1
|
68
71
|
|
69
|
-
syms = txt.split(
|
72
|
+
syms = txt.split(/=>/, -1)
|
70
73
|
return split_sym syms, sym("rocket-syntax") if syms.length > 1
|
71
74
|
|
72
75
|
sym txt
|
@@ -89,6 +92,8 @@ module Nydp
|
|
89
92
|
case token.first
|
90
93
|
when :string_open_delim
|
91
94
|
string token_stream, token.last, close_delimiter_for(token.last)
|
95
|
+
when :sym_open_delim
|
96
|
+
sym token_stream.next_string_fragment(token.last, /\|/, nil)
|
92
97
|
when :left_paren
|
93
98
|
prefix_list token[1], read_list(token_stream, :right_paren)
|
94
99
|
when :left_brace
|
@@ -106,13 +111,15 @@ module Nydp
|
|
106
111
|
next_form token_stream.next_token, token_stream
|
107
112
|
end
|
108
113
|
|
114
|
+
INTERPOLATION_SIGN = /~/
|
115
|
+
|
109
116
|
def string token_stream, open_delimiter, close_delimiter
|
110
117
|
fragments = [sym(:"string-pieces")]
|
111
|
-
string_token = token_stream.next_string_fragment(open_delimiter, close_delimiter)
|
118
|
+
string_token = token_stream.next_string_fragment(open_delimiter, close_delimiter, INTERPOLATION_SIGN)
|
112
119
|
fragments << Nydp::StringAtom.new(string_token.string, string_token)
|
113
120
|
while !(string_token.is_a? StringFragmentCloseToken)
|
114
121
|
fragments << expression(token_stream)
|
115
|
-
string_token = token_stream.next_string_fragment('', close_delimiter)
|
122
|
+
string_token = token_stream.next_string_fragment('', close_delimiter, INTERPOLATION_SIGN)
|
116
123
|
fragments << Nydp::StringAtom.new(string_token.string, string_token)
|
117
124
|
end
|
118
125
|
|
data/lib/nydp/runner.rb
CHANGED
data/lib/nydp/string_atom.rb
CHANGED
data/lib/nydp/string_token.rb
CHANGED
data/lib/nydp/symbol.rb
CHANGED
@@ -1,8 +1,15 @@
|
|
1
1
|
class Nydp::Symbol
|
2
|
+
EMPTY = :""
|
2
3
|
attr_accessor :name
|
3
4
|
|
4
5
|
def initialize name
|
5
6
|
@name = name.to_sym
|
7
|
+
@inspection = name.to_s
|
8
|
+
@inspection = "|#{name}|" if untidy(@inspection)
|
9
|
+
end
|
10
|
+
|
11
|
+
def untidy str
|
12
|
+
(str == "") || (str == nil) || (str =~ /\s/)
|
6
13
|
end
|
7
14
|
|
8
15
|
def is? nm
|
@@ -10,9 +17,11 @@ class Nydp::Symbol
|
|
10
17
|
end
|
11
18
|
|
12
19
|
def value context=nil
|
20
|
+
raise "unbound symbol: #{self.inspect}" if @value == nil
|
13
21
|
@value || Nydp.NIL
|
14
22
|
end
|
15
23
|
|
24
|
+
|
16
25
|
def self.mk name, ns
|
17
26
|
name = name.to_sym
|
18
27
|
return Nydp.NIL if name == :nil
|
@@ -29,9 +38,10 @@ class Nydp::Symbol
|
|
29
38
|
ns[name.to_sym]
|
30
39
|
end
|
31
40
|
|
32
|
-
def nydp_type ; :symbol
|
33
|
-
def inspect ;
|
34
|
-
def to_s ; name.to_s
|
41
|
+
def nydp_type ; :symbol ; end
|
42
|
+
def inspect ; @inspection ; end
|
43
|
+
def to_s ; name.to_s ; end
|
44
|
+
def to_ruby ; name ; end
|
35
45
|
|
36
46
|
def == other
|
37
47
|
other.is_a?(Nydp::Symbol) && (self.name == other.name)
|
data/lib/nydp/tokeniser.rb
CHANGED
@@ -25,7 +25,7 @@ module Nydp
|
|
25
25
|
scanner.scan(delim)
|
26
26
|
end
|
27
27
|
|
28
|
-
def next_string_fragment open_delimiter, close_delimiter
|
28
|
+
def next_string_fragment open_delimiter, close_delimiter, interpolation_sign
|
29
29
|
s = @scanner
|
30
30
|
rep = "#{open_delimiter}"
|
31
31
|
string = ""
|
@@ -42,7 +42,7 @@ module Nydp
|
|
42
42
|
elsif closer = close_delimiter?(s, close_delimiter)
|
43
43
|
rep << closer
|
44
44
|
return StringFragmentCloseToken.new(string, rep)
|
45
|
-
elsif start_interpolation = s.scan(
|
45
|
+
elsif interpolation_sign && (start_interpolation = s.scan(interpolation_sign))
|
46
46
|
rep << start_interpolation
|
47
47
|
return StringFragmentToken.new(string, rep)
|
48
48
|
else
|
@@ -66,6 +66,8 @@ module Nydp
|
|
66
66
|
tok = [:comment, comment[1..-1].strip]
|
67
67
|
elsif open_str = s.scan(/"/)
|
68
68
|
tok = [:string_open_delim, open_str]
|
69
|
+
elsif open_sym = s.scan(/\|/)
|
70
|
+
tok = [:sym_open_delim, open_sym]
|
69
71
|
elsif list_prefix = s.scan(/[^\s()]*\(/)
|
70
72
|
tok = [:left_paren, list_prefix[0...-1]]
|
71
73
|
elsif list_prefix = s.scan(/[^\s()]*\{/)
|
data/lib/nydp/version.rb
CHANGED
data/spec/hash_spec.rb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Nydp::Hash do
|
4
|
+
|
5
|
+
let(:vm) { Nydp::VM.new }
|
6
|
+
|
7
|
+
describe "nydp hashes" do
|
8
|
+
describe "new hash" do
|
9
|
+
it "returns a new Nydp hash" do
|
10
|
+
Nydp::Builtin::Hash.new.invoke vm, Nydp.NIL
|
11
|
+
h = vm.pop_arg
|
12
|
+
expect(h).to be_a Nydp::Hash
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "hash set" do
|
17
|
+
it "sets a value on a hash" do
|
18
|
+
h = Nydp::Hash.new
|
19
|
+
k = sym "keysym"
|
20
|
+
v = 42
|
21
|
+
args = Nydp::Pair.from_list([h, k, v])
|
22
|
+
Nydp::Builtin::HashSet.new.invoke vm, args
|
23
|
+
|
24
|
+
expect(h.keys). to eq [k]
|
25
|
+
expect(h[k]). to eq v
|
26
|
+
expect(vm.pop_arg).to eq v
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "hash get" do
|
31
|
+
it "gets a value from a hash" do
|
32
|
+
h = Nydp::Hash.new
|
33
|
+
k = sym "keysym"
|
34
|
+
v = 42
|
35
|
+
h[k] = v
|
36
|
+
|
37
|
+
args = Nydp::Pair.from_list([h, k])
|
38
|
+
Nydp::Builtin::HashGet.new(ns).invoke vm, args
|
39
|
+
expect(vm.pop_arg).to eq v
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe "hash keys" do
|
44
|
+
it "returns a list of keys" do
|
45
|
+
h = Nydp::Hash.new
|
46
|
+
h[sym "k0"] = 42
|
47
|
+
h[sym "k1"] = 84
|
48
|
+
|
49
|
+
args = Nydp::Pair.from_list([h])
|
50
|
+
Nydp::Builtin::HashKeys.new(ns).invoke vm, args
|
51
|
+
expect(vm.pop_arg).to eq pair_list [sym("k0"), sym("k1")]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "foreign hashes" do
|
57
|
+
let(:ahash) { Hash.new }
|
58
|
+
|
59
|
+
describe "hash set" do
|
60
|
+
it "returns a new Nydp hash" do
|
61
|
+
k = Nydp::Symbol.mk "keysym", ns
|
62
|
+
v = Nydp::StringAtom.new "foobar"
|
63
|
+
args = pair_list [ahash, k, v]
|
64
|
+
Nydp::Builtin::HashSet.new.invoke vm, args
|
65
|
+
|
66
|
+
expect(ahash[:keysym]). to eq "foobar"
|
67
|
+
expect(ahash[:keysym].class).to eq String
|
68
|
+
expect(ahash.keys). to eq [:keysym]
|
69
|
+
|
70
|
+
expect(vm.pop_arg).to eq v
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "hash get" do
|
75
|
+
it "converts ruby value to nydp value" do
|
76
|
+
ahash[:keysym] = "avalue"
|
77
|
+
k = sym("keysym")
|
78
|
+
args = [ ahash, k ]
|
79
|
+
|
80
|
+
Nydp::Builtin::HashGet.new(ns).invoke vm, pair_list(args)
|
81
|
+
|
82
|
+
expect(vm.pop_arg).to eq Nydp::StringAtom.new("avalue")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe "hash keys" do
|
87
|
+
it "returns a list of keys" do
|
88
|
+
ahash[:k0] = 42
|
89
|
+
ahash[:k1] = 84
|
90
|
+
args = [ahash]
|
91
|
+
|
92
|
+
Nydp::Builtin::HashKeys.new(ns).invoke vm, pair_list(args)
|
93
|
+
|
94
|
+
expect(vm.pop_arg).to eq pair_list [sym("k0"), sym("k1")]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
File without changes
|
data/spec/pair_spec.rb
CHANGED
@@ -52,7 +52,7 @@ describe Nydp::Pair do
|
|
52
52
|
expect(p.cdr).to eq :b
|
53
53
|
end
|
54
54
|
|
55
|
-
it "should convert a ruby list" do
|
55
|
+
it "should convert from a ruby list" do
|
56
56
|
p = pair_list [:a, :b, :c, :d]
|
57
57
|
expect(p.car).to eq :a
|
58
58
|
p = p.cdr
|
@@ -69,6 +69,12 @@ describe Nydp::Pair do
|
|
69
69
|
expect(p.cdr).to eq Nydp.NIL
|
70
70
|
end
|
71
71
|
|
72
|
+
it "should convert to a ruby list" do
|
73
|
+
pair = pair_list [:a, :b, :c, :d]
|
74
|
+
ruby = pair.to_ruby
|
75
|
+
expect(ruby).to eq [:a, :b, :c, :d]
|
76
|
+
end
|
77
|
+
|
72
78
|
it "should have size zero when empty" do
|
73
79
|
expect(pair_list([]).size).to eq 0
|
74
80
|
end
|
data/spec/parser_spec.rb
CHANGED
@@ -49,6 +49,13 @@ describe Nydp::Parser do
|
|
49
49
|
expect(parse "(foo bar)").to eq pair_list([foo, bar])
|
50
50
|
end
|
51
51
|
|
52
|
+
it "should parse untidy symbols" do
|
53
|
+
s0 = sym "foo bar"
|
54
|
+
s1 = sym ""
|
55
|
+
s2 = sym '" hello, there, silly billy!"'
|
56
|
+
expect(parse "(|foo bar| || |\" hello, there, silly billy!\"|)").to eq pair_list([s0, s1, s2])
|
57
|
+
end
|
58
|
+
|
52
59
|
it "should parse numbers expression" do
|
53
60
|
expect(parse "(1 2 3)").to eq pair_list([1, 2, 3])
|
54
61
|
end
|
@@ -138,6 +145,11 @@ describe Nydp::Parser do
|
|
138
145
|
expect([two, three, four].map &:class).to eq [Fixnum, Fixnum, Fixnum]
|
139
146
|
end
|
140
147
|
|
148
|
+
it "should handle prefix and postfix syntax also" do
|
149
|
+
parsed = parse(".foo123:")
|
150
|
+
expect(parsed.inspect).to eq "(dot-syntax || (colon-syntax foo123 ||))"
|
151
|
+
end
|
152
|
+
|
141
153
|
it "should parse a dotted symbol" do
|
142
154
|
expect(parse "(list a b foo.bar c)").to eq pair_list([sym(:list), a, b, pair_list([dotsyn, foo, bar]), c])
|
143
155
|
end
|
data/spec/symbol_spec.rb
CHANGED
@@ -1,6 +1,11 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Nydp::Symbol do
|
4
|
+
it "returns a ruby symbol in #to_ruby" do
|
5
|
+
sym = Nydp::Symbol.mk :foo, ns
|
6
|
+
expect(sym.to_ruby).to eq :foo
|
7
|
+
end
|
8
|
+
|
4
9
|
it "should not recognise an unknown symbol" do
|
5
10
|
sym = Nydp::Symbol.find :foo, ns
|
6
11
|
expect(sym).to eq nil
|
@@ -15,6 +20,7 @@ describe Nydp::Symbol do
|
|
15
20
|
sym1 = Nydp::Symbol.mk :baz, ns
|
16
21
|
sym2 = Nydp::Symbol.mk :baz, ns
|
17
22
|
|
23
|
+
expect(sym1).to eq sym2
|
18
24
|
expect(sym1).to equal sym2
|
19
25
|
end
|
20
26
|
|
@@ -26,5 +32,6 @@ describe Nydp::Symbol do
|
|
26
32
|
sym2 = Nydp::Symbol.mk :baz, ns2
|
27
33
|
|
28
34
|
expect(sym1).to eq sym2
|
35
|
+
expect(sym1).not_to equal sym2
|
29
36
|
end
|
30
37
|
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.
|
4
|
+
version: 0.0.6
|
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-05-
|
11
|
+
date: 2015-05-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -109,6 +109,7 @@ files:
|
|
109
109
|
- lib/nydp/builtin/load_tests.rb
|
110
110
|
- lib/nydp/builtin/millisecs.rb
|
111
111
|
- lib/nydp/builtin/minus.rb
|
112
|
+
- lib/nydp/builtin/parse.rb
|
112
113
|
- lib/nydp/builtin/plus.rb
|
113
114
|
- lib/nydp/builtin/pre_compile.rb
|
114
115
|
- lib/nydp/builtin/puts.rb
|
@@ -129,6 +130,7 @@ files:
|
|
129
130
|
- lib/nydp/core.rb
|
130
131
|
- lib/nydp/error.rb
|
131
132
|
- lib/nydp/function_invocation.rb
|
133
|
+
- lib/nydp/hash.rb
|
132
134
|
- lib/nydp/helper.rb
|
133
135
|
- lib/nydp/interpreted_function.rb
|
134
136
|
- lib/nydp/lexical_context.rb
|
@@ -147,12 +149,14 @@ files:
|
|
147
149
|
- lib/nydp/vm.rb
|
148
150
|
- lib/tasks/tests.rake
|
149
151
|
- nydp.gemspec
|
150
|
-
- spec/boot_spec.rb
|
151
152
|
- spec/embedded_spec.rb
|
152
|
-
- spec/
|
153
|
+
- spec/hash_spec.rb
|
154
|
+
- spec/literal_spec.rb
|
155
|
+
- spec/nydp_spec.rb
|
153
156
|
- spec/pair_spec.rb
|
154
157
|
- spec/parser_spec.rb
|
155
158
|
- spec/spec_helper.rb
|
159
|
+
- spec/string_atom_spec.rb
|
156
160
|
- spec/string_token_spec.rb
|
157
161
|
- spec/symbol_spec.rb
|
158
162
|
- spec/thread_local_spec.rb
|
@@ -181,12 +185,14 @@ signing_key:
|
|
181
185
|
specification_version: 4
|
182
186
|
summary: A new lisp for a new age
|
183
187
|
test_files:
|
184
|
-
- spec/boot_spec.rb
|
185
188
|
- spec/embedded_spec.rb
|
186
|
-
- spec/
|
189
|
+
- spec/hash_spec.rb
|
190
|
+
- spec/literal_spec.rb
|
191
|
+
- spec/nydp_spec.rb
|
187
192
|
- spec/pair_spec.rb
|
188
193
|
- spec/parser_spec.rb
|
189
194
|
- spec/spec_helper.rb
|
195
|
+
- spec/string_atom_spec.rb
|
190
196
|
- spec/string_token_spec.rb
|
191
197
|
- spec/symbol_spec.rb
|
192
198
|
- spec/thread_local_spec.rb
|
data/spec/boot_spec.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Nydp do
|
4
|
-
let(:vm) { Nydp::VM.new }
|
5
|
-
|
6
|
-
before {
|
7
|
-
Nydp.setup ns
|
8
|
-
boot_path = File.expand_path File.join File.expand_path(File.dirname(__FILE__)), '../lib/lisp/boot.nydp'
|
9
|
-
reader = Nydp::StreamReader.new(File.new(boot_path))
|
10
|
-
Nydp::Runner.new(vm, ns, reader).run
|
11
|
-
}
|
12
|
-
|
13
|
-
def list *things
|
14
|
-
Nydp::Pair.from_list things.map { |thing|
|
15
|
-
case thing
|
16
|
-
when Symbol
|
17
|
-
sym(thing)
|
18
|
-
when Array
|
19
|
-
list(*thing)
|
20
|
-
else
|
21
|
-
thing
|
22
|
-
end
|
23
|
-
}
|
24
|
-
end
|
25
|
-
|
26
|
-
def run txt
|
27
|
-
Nydp::Runner.new(vm, ns, Nydp::StringReader.new(txt)).run
|
28
|
-
end
|
29
|
-
|
30
|
-
describe :let do
|
31
|
-
it "should create an inner scope with a single variable" do
|
32
|
-
lisp = "(def x+3*z (x) (let y 3 (fn (z) (* (+ x y) z)))) ((x+3*z 2) 5)"
|
33
|
-
result = run lisp
|
34
|
-
expect(result).to eq 25
|
35
|
-
end
|
36
|
-
end
|
37
|
-
|
38
|
-
describe :and do
|
39
|
-
it "should produce some nested conds" do
|
40
|
-
result = run "(pre-compile '(and a b c))"
|
41
|
-
expect(result).to eq list :cond, :a, [:cond, :b, :c]
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe :w_uniq do
|
46
|
-
it "should handle single-var case" do
|
47
|
-
result = run "(reset-uniq-counter) (pre-compile '(w/uniq a foo))"
|
48
|
-
expect(result).to eq list [:fn, [:a], :foo], [:uniq, [:quote, :a]]
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
describe :or do
|
53
|
-
it "should produce some nested conds" do
|
54
|
-
result = run "(reset-uniq-counter) (pre-compile '(or a b c))"
|
55
|
-
expect(result).to eq parse "((fn (ora-1) (cond ora-1 ora-1 ((fn (ora-2) (cond ora-2 ora-2 ((fn (ora-3) (cond ora-3 ora-3 nil)) c))) b))) a)"
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
describe :join do
|
60
|
-
it "should join a list of strings together" do
|
61
|
-
joining = %{(joinstr "" '("foo" "bar" "bax"))}
|
62
|
-
expect(run joining).to eq "foobarbax"
|
63
|
-
end
|
64
|
-
|
65
|
-
it "should join a list of things together as a string" do
|
66
|
-
expect(run %{(joinstr " - " '(1 2 3))}).to eq "1 - 2 - 3"
|
67
|
-
end
|
68
|
-
end
|
69
|
-
end
|