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