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 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