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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8c1432b7602bbe14e2c346f16068b7f8aea35317
4
- data.tar.gz: 664df28016183708d50c31a000088176ba6fe38a
3
+ metadata.gz: 56ae5257ab6792eeaef112c3e81991dae7c43ce1
4
+ data.tar.gz: 327b5770bc8f1c442202d340f5392288e58efdbe
5
5
  SHA512:
6
- metadata.gz: 08fa70dd03b03b37e7427524502c216a3f7b82cdd12d9800282d91020d4d59e8faa2fdf860038299d66559f12367125913b9e699d24fe476f656599a1d49b9da
7
- data.tar.gz: 40746bd05d453ab458c4e389c215546e9ffadb27e53455387a112539adc5ef189d762072f4e8988086d8813892cb9a29e53af2794fb1591e51df52bfb294f4ae
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 (type obj) (eq? (type-of obj) type))
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)))
@@ -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 "quasiquote"
40
- ("same as quote for standalone item"
41
- `a
42
- a)
43
- ("same as quote for standalone list"
44
- `(a b c)
45
- (a b c))
46
- ("substitutes single variables"
47
- (let b 10 `(a ,b c))
48
- (a 10 c))
49
- ("substitutes a list"
50
- (let b '(1 2 3) `(a ,@b c))
51
- (a 1 2 3 c))
52
- ("substitutes a list at the end of a given list"
53
- (let b '(1 2 3) `(a ,b ,@b))
54
- (a (1 2 3) 1 2 3))
55
- ("more complicated substitution example"
56
- (with (d '(1 2 3) g '(x y z)) `(a (b c ,d (e f ,@g))))
57
- (a (b c (1 2 3) (e f x y z))))
58
- ("peeks inside nested quotes"
59
- `(a b '(c ,(+ 1 2)))
60
- (a b '(c 3)))
61
- ("handles nested unquote-splicing"
62
- ``(a ,,@(list '+ 1 2) b)
63
- `((a ,(+ 1 2) b)))
64
- ("returns nested quasiquotes"
65
- `(a b `(c d ,(+ 1 2) ,,(+ 3 4)))
66
- (a b `(c d ,(+ 1 2) ,7))))
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 fale"
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|
@@ -1,30 +1,56 @@
1
+ require "nydp/hash"
2
+
1
3
  class Nydp::Builtin::Hash
2
- def invoke vm, args
3
- vm.push_arg({ })
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
- def invoke vm, args
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
- vm.push_arg(hash[key] || Nydp.NIL)
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
- def invoke vm, args
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[key] = value
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
- def invoke vm, args
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
- vm.push_arg Nydp::Pair.from_list hash.keys
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
@@ -0,0 +1,2 @@
1
+ class Nydp::Hash < ::Hash
2
+ end
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.to_s.split /\./
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
@@ -48,6 +48,8 @@ module Nydp
48
48
 
49
49
  def compile_and_eval expr
50
50
  vm.thread Pair.new(Compiler.compile(expr, Nydp.NIL), Nydp.NIL)
51
+ rescue Exception => e
52
+ raise "failed to eval #{expr.inspect},\nerror was #{e.message}\nvm state is #{vm.error}"
51
53
  end
52
54
 
53
55
  def quote expr
@@ -7,6 +7,7 @@ module Nydp
7
7
 
8
8
  def nydp_type ; :string ; end
9
9
  def to_s ; string ; end
10
+ def to_ruby ; string ; end
10
11
 
11
12
  def inspect
12
13
  string.inspect
@@ -19,6 +20,5 @@ module Nydp
19
20
  def + other
20
21
  StringAtom.new "#{@string}#{other}"
21
22
  end
22
-
23
23
  end
24
24
  end
@@ -5,9 +5,9 @@ module Nydp
5
5
  @string, @rep = string, rep
6
6
  end
7
7
 
8
- def to_s
9
- rep
10
- end
8
+ def to_s ; rep ; end
9
+ def inspect ; rep ; end
10
+ def to_sym ; string.to_sym ; end
11
11
 
12
12
  def == other
13
13
  (self.class == other.class) && (self.string == other.string)
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 ; end
33
- def inspect ; to_s ; end
34
- def to_s ; name.to_s ; end
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)
@@ -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
@@ -1,3 +1,3 @@
1
1
  module Nydp
2
- VERSION = "0.0.5"
2
+ VERSION = "0.0.6"
3
3
  end
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
@@ -0,0 +1,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Nydp::Literal do
4
+ it "returns a ruby symbol in #to_ruby" do
5
+ sym = Nydp::Symbol.mk :foo, ns
6
+ lit = Nydp::Literal.new sym
7
+ expect(lit.to_ruby).to eq :foo
8
+ end
9
+ 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
@@ -0,0 +1,9 @@
1
+ require "spec_helper"
2
+
3
+ describe Nydp::StringAtom do
4
+ it "returns its string in #to_ruby" do
5
+ s = Nydp::StringAtom.new "harrypotter"
6
+ expect(s.to_ruby).to eq "harrypotter"
7
+ expect(s.to_ruby.class).to eq String
8
+ end
9
+ 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.5
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-15 00:00:00.000000000 Z
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/nypd_spec.rb
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/nypd_spec.rb
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