nydp 0.0.11 → 0.0.12
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/README.md +16 -6
- data/lib/lisp/core-06-benchmarking.nydp +42 -0
- data/lib/lisp/tests/invocation-tests.nydp +119 -0
- data/lib/nydp/builtin.rb +25 -4
- data/lib/nydp/builtin/hash.rb +15 -3
- data/lib/nydp/builtin/pre_compile.rb +1 -0
- data/lib/nydp/closure.rb +12 -0
- data/lib/nydp/function_invocation.rb +79 -24
- data/lib/nydp/interpreted_function.rb +24 -13
- data/lib/nydp/lexical_context.rb +18 -0
- data/lib/nydp/lexical_context_builder.rb +130 -0
- data/lib/nydp/pair.rb +4 -0
- data/lib/nydp/version.rb +1 -1
- data/spec/hash_spec.rb +70 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e7ea4e19c5b46b3a1c56299814f4412262c19ee
|
4
|
+
data.tar.gz: e812a2a39dab9ac0eb1a27b8cce1d6f0fd0b8f21
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6b65eac655935ae485b2c66e4e90f50dce3b5fcab5afb7f4c2394ae7f5a72b1451a65f24dadcb72460ad2e6f5b51a4e4c6ccbf7353ebc2d31aa8bc9294292d47
|
7
|
+
data.tar.gz: 95d9519c024596480c2a604db56055bfe6d5ec929c0b57a3c5356ff0b1150b92c698199f35116036c85ad0431d6d083918279abeab3640dbfa736af4b937f444
|
data/README.md
CHANGED
@@ -136,6 +136,9 @@ nydp > (pre-compile (parse "&foo"))
|
|
136
136
|
((fn (obj) (hash-get obj (quote foo))))
|
137
137
|
|
138
138
|
nydp > (assign hsh { foo 1 bar 2 })
|
139
|
+
nydp > (&bar hsh)
|
140
|
+
2
|
141
|
+
|
139
142
|
nydp > (&lastname (car german-composers))
|
140
143
|
Bach
|
141
144
|
|
@@ -159,7 +162,7 @@ nydp > (parse "{ a 1 b 2 }")
|
|
159
162
|
|
160
163
|
```
|
161
164
|
|
162
|
-
`brace-list` is a macro that expands to create a hash literal. It assumes every
|
165
|
+
`brace-list` is a macro that expands to create a hash literal. It assumes every item 0 is a literal symbol key, item 1 is the corresponding value which is evaluated at run time, and so on for each following item-pair.
|
163
166
|
|
164
167
|
```lisp
|
165
168
|
|
@@ -201,7 +204,7 @@ nydp > (with (a 1 b 2)
|
|
201
204
|
==> AND ALSO, Consider 3, the third (and final) thing
|
202
205
|
```
|
203
206
|
|
204
|
-
By default, `string-pieces` is a function that just concatenates the string value of its arguments. You can redefine it as a macro to perform more fun stuff, or you can detect it within another macro to do extra-special stuff with it.
|
207
|
+
By default, `string-pieces` is a function that just concatenates the string value of its arguments. You can redefine it as a macro to perform more fun stuff, or you can detect it within another macro to do extra-special stuff with it. The 'nydp-html gem detects 'string-pieces and gives it special treatment in order to render haml and textile efficiently, and also to capture and report errors inside interpolations and report them correctly.
|
205
208
|
|
206
209
|
|
207
210
|
#### 5. No continuations.
|
@@ -210,7 +213,14 @@ Sorry. While technically possible ... why bother?
|
|
210
213
|
|
211
214
|
#### 6. No argument destructuring
|
212
215
|
|
213
|
-
However, this doesn't need to be built-in, it can be done with macros alone.
|
216
|
+
However, this doesn't need to be built-in, it can be done with macros alone. On the other hand, "rest" arguments are implicitly available using the same syntax as Arc uses:
|
217
|
+
|
218
|
+
```lisp
|
219
|
+
(def fun (a b . others) ...)
|
220
|
+
```
|
221
|
+
|
222
|
+
In this example, `'others` is either nil, or a list containing the third and subsequent arguments to the call to `'fun`. For many examples of this kind of invocation, see [invocation-tests](lib/lisp/tests/invocation-tests.nydp) in the `tests` directory.
|
223
|
+
|
214
224
|
|
215
225
|
|
216
226
|
## Besides that, what can Nydp do?
|
@@ -232,14 +242,14 @@ elsif c
|
|
232
242
|
else e
|
233
243
|
```
|
234
244
|
|
235
|
-
#### 5. Lexically scoped, but
|
245
|
+
#### 5. Lexically scoped, but dynamic variables possible, using thread-locals
|
236
246
|
|
237
247
|
```lisp
|
238
|
-
nydp> (dynamic foo)
|
248
|
+
nydp> (dynamic foo) ;; declares 'foo as a dynamic variable
|
239
249
|
|
240
250
|
nydp> (def do-something () (+ (foo) 1))
|
241
251
|
|
242
|
-
nydp> (w/foo 99 (do-something))
|
252
|
+
nydp> (w/foo 99 (do-something)) ;; sets 'foo to 99 for the duration of the call to 'do-something, will set it back to its previous value afterwards.
|
243
253
|
|
244
254
|
==> 100
|
245
255
|
|
@@ -0,0 +1,42 @@
|
|
1
|
+
(def bm-pythag ()
|
2
|
+
(for i 1 50
|
3
|
+
(for j 1 50
|
4
|
+
(sqrt (+ (* i i) (* j j))))))
|
5
|
+
|
6
|
+
(def bm-repeat (f n)
|
7
|
+
(for b 1 n (f)))
|
8
|
+
|
9
|
+
(def bm (desc f repeats iterations)
|
10
|
+
(p "\n================================================")
|
11
|
+
(p "Benchmark: ~desc - ~repeats runs of ~iterations iterations each")
|
12
|
+
(let times 0
|
13
|
+
(for reps 1 repeats
|
14
|
+
(let time (millisecs)
|
15
|
+
(bm-repeat f iterations)
|
16
|
+
(let elapsed (- (millisecs) time)
|
17
|
+
(assign times (+ elapsed times))
|
18
|
+
(p " took: ~elapsed ms, ~(/ elapsed iterations) ms per iteration"))))
|
19
|
+
(p "total ~(just times), average ~(/ times repeats) per run")
|
20
|
+
(p "================================================\n"))
|
21
|
+
nil)
|
22
|
+
|
23
|
+
(let private-x 0
|
24
|
+
(let inc-x (fn () (assign private-x (+ 1 private-x)))
|
25
|
+
(def bm-zero-arg-call ()
|
26
|
+
(for i 0 400 (inc-x)))))
|
27
|
+
|
28
|
+
(let private-y 0
|
29
|
+
(let inc-y (fn (n) (assign private-y (+ n private-y)))
|
30
|
+
(def bm-one-arg-call ()
|
31
|
+
(for i 0 400 (inc-y 10)))))
|
32
|
+
|
33
|
+
(let private-z 0
|
34
|
+
(let inc-z (fn (n m) (assign private-z (+ (* n m) private-z)))
|
35
|
+
(def bm-two-arg-call ()
|
36
|
+
(for i 0 400 (inc-z 2 5)))))
|
37
|
+
|
38
|
+
(def rbs ()
|
39
|
+
(bm "pythag" bm-pythag 10 100)
|
40
|
+
(bm "zero arg call" bm-zero-arg-call 10 500)
|
41
|
+
(bm "one arg call" bm-one-arg-call 10 500)
|
42
|
+
(bm "two arg call" bm-two-arg-call 10 500))
|
@@ -0,0 +1,119 @@
|
|
1
|
+
;; test that basic function invocation works for various combinations
|
2
|
+
;; of parameter lists and invocation arguments
|
3
|
+
;;
|
4
|
+
;; important mostly because these kind of calls are subject to the
|
5
|
+
;; most aggressive optimisation so it's useful to have a quick
|
6
|
+
;; smoke test to check that nothing obvious is broken
|
7
|
+
;;
|
8
|
+
|
9
|
+
(def tst-0 () "success" )
|
10
|
+
(def tst-0-n n "success n: ~(inspect n)" )
|
11
|
+
(def tst-1 (a) "success a: ~a" )
|
12
|
+
(def tst-1-n (a . n) "success a: ~a . n: ~(inspect n)" )
|
13
|
+
(def tst-2 (a b) "success a: ~a b: ~b" )
|
14
|
+
(def tst-2-n (a b . n) "success a: ~a b: ~b . n: ~(inspect n)" )
|
15
|
+
(def tst-3 (a b c) "success a: ~a b: ~b c: ~c" )
|
16
|
+
(def tst-3-n (a b c . n) "success a: ~a b: ~b c: ~c . n: ~(inspect n)" )
|
17
|
+
(def tst-4 (a b c d) "success a: ~a b: ~b c: ~c d: ~d" )
|
18
|
+
(def tst-4-n (a b c d . n) "success a: ~a b: ~b c: ~c d: ~d . n: ~(inspect n)" )
|
19
|
+
(def tst-5 (a b c d e) "success a: ~a b: ~b c: ~c d: ~d e: ~e" )
|
20
|
+
(def tst-5-n (a b c d e . n) "success a: ~a b: ~b c: ~c d: ~d e: ~e . n: ~(inspect n)" )
|
21
|
+
|
22
|
+
(register-test
|
23
|
+
'(suite "Invocation Tests"
|
24
|
+
(suite "zero-params"
|
25
|
+
("no args" (tst-0) "success" )
|
26
|
+
("one arg" (tst-0 1) "success" )
|
27
|
+
("two args" (tst-0 1 2) "success" )
|
28
|
+
("three args" (tst-0 1 2 3) "success" )
|
29
|
+
("four args" (tst-0 1 2 3 4) "success" )
|
30
|
+
("five args" (tst-0 1 2 3 4 5) "success" ))
|
31
|
+
|
32
|
+
(suite "single rest-param"
|
33
|
+
("no args" (tst-0-n) "success n: nil" )
|
34
|
+
("one arg" (tst-0-n 1) "success n: (1)" )
|
35
|
+
("two args" (tst-0-n 1 2) "success n: (1 2)" )
|
36
|
+
("three args" (tst-0-n 1 2 3) "success n: (1 2 3)" )
|
37
|
+
("four args" (tst-0-n 1 2 3 4) "success n: (1 2 3 4)" )
|
38
|
+
("five args" (tst-0-n 1 2 3 4 5) "success n: (1 2 3 4 5)" ))
|
39
|
+
|
40
|
+
(suite "single param"
|
41
|
+
("no args" (tst-1) "success a: " )
|
42
|
+
("one arg" (tst-1 1) "success a: 1" )
|
43
|
+
("two args" (tst-1 1 2) "success a: 1" )
|
44
|
+
("three args" (tst-1 1 2 3) "success a: 1" )
|
45
|
+
("four args" (tst-1 1 2 3 4) "success a: 1" )
|
46
|
+
("five args" (tst-1 1 2 3 4 5) "success a: 1" ))
|
47
|
+
|
48
|
+
(suite "single param and rest param"
|
49
|
+
("no args" (tst-1-n) "success a: . n: nil" )
|
50
|
+
("one arg" (tst-1-n 1) "success a: 1 . n: nil" )
|
51
|
+
("two args" (tst-1-n 1 2) "success a: 1 . n: (2)" )
|
52
|
+
("three args" (tst-1-n 1 2 3) "success a: 1 . n: (2 3)" )
|
53
|
+
("four args" (tst-1-n 1 2 3 4) "success a: 1 . n: (2 3 4)" )
|
54
|
+
("five args" (tst-1-n 1 2 3 4 5) "success a: 1 . n: (2 3 4 5)" ))
|
55
|
+
|
56
|
+
(suite "two params"
|
57
|
+
("no args" (tst-2) "success a: b: " )
|
58
|
+
("one arg" (tst-2 1) "success a: 1 b: " )
|
59
|
+
("two args" (tst-2 1 2) "success a: 1 b: 2" )
|
60
|
+
("three args" (tst-2 1 2 3) "success a: 1 b: 2" )
|
61
|
+
("four args" (tst-2 1 2 3 4) "success a: 1 b: 2" )
|
62
|
+
("five args" (tst-2 1 2 3 4 5) "success a: 1 b: 2" ))
|
63
|
+
|
64
|
+
(suite "two params and rest param"
|
65
|
+
("no args" (tst-2-n) "success a: b: . n: nil" )
|
66
|
+
("one arg" (tst-2-n 1) "success a: 1 b: . n: nil" )
|
67
|
+
("two args" (tst-2-n 1 2) "success a: 1 b: 2 . n: nil" )
|
68
|
+
("three args" (tst-2-n 1 2 3) "success a: 1 b: 2 . n: (3)" )
|
69
|
+
("four args" (tst-2-n 1 2 3 4) "success a: 1 b: 2 . n: (3 4)" )
|
70
|
+
("five args" (tst-2-n 1 2 3 4 5) "success a: 1 b: 2 . n: (3 4 5)" ))
|
71
|
+
|
72
|
+
(suite "three params"
|
73
|
+
("no args" (tst-3) "success a: b: c: " )
|
74
|
+
("one arg" (tst-3 1) "success a: 1 b: c: " )
|
75
|
+
("two args" (tst-3 1 2) "success a: 1 b: 2 c: " )
|
76
|
+
("three args" (tst-3 1 2 3) "success a: 1 b: 2 c: 3" )
|
77
|
+
("four args" (tst-3 1 2 3 4) "success a: 1 b: 2 c: 3" )
|
78
|
+
("five args" (tst-3 1 2 3 4 5) "success a: 1 b: 2 c: 3" ))
|
79
|
+
|
80
|
+
(suite "three params and rest param"
|
81
|
+
("no args" (tst-3-n) "success a: b: c: . n: nil" )
|
82
|
+
("one arg" (tst-3-n 1) "success a: 1 b: c: . n: nil" )
|
83
|
+
("two args" (tst-3-n 1 2) "success a: 1 b: 2 c: . n: nil" )
|
84
|
+
("three args" (tst-3-n 1 2 3) "success a: 1 b: 2 c: 3 . n: nil" )
|
85
|
+
("four args" (tst-3-n 1 2 3 4) "success a: 1 b: 2 c: 3 . n: (4)" )
|
86
|
+
("five args" (tst-3-n 1 2 3 4 5) "success a: 1 b: 2 c: 3 . n: (4 5)" ))
|
87
|
+
|
88
|
+
(suite "four params"
|
89
|
+
("no args" (tst-4) "success a: b: c: d: " )
|
90
|
+
("one arg" (tst-4 1) "success a: 1 b: c: d: " )
|
91
|
+
("two args" (tst-4 1 2) "success a: 1 b: 2 c: d: " )
|
92
|
+
("three args" (tst-4 1 2 3) "success a: 1 b: 2 c: 3 d: " )
|
93
|
+
("four args" (tst-4 1 2 3 4) "success a: 1 b: 2 c: 3 d: 4" )
|
94
|
+
("five args" (tst-4 1 2 3 4 5) "success a: 1 b: 2 c: 3 d: 4" ))
|
95
|
+
|
96
|
+
(suite "four params and rest param"
|
97
|
+
("no args" (tst-4-n) "success a: b: c: d: . n: nil" )
|
98
|
+
("one arg" (tst-4-n 1) "success a: 1 b: c: d: . n: nil" )
|
99
|
+
("two args" (tst-4-n 1 2) "success a: 1 b: 2 c: d: . n: nil" )
|
100
|
+
("three args" (tst-4-n 1 2 3) "success a: 1 b: 2 c: 3 d: . n: nil" )
|
101
|
+
("four args" (tst-4-n 1 2 3 4) "success a: 1 b: 2 c: 3 d: 4 . n: nil" )
|
102
|
+
("five args" (tst-4-n 1 2 3 4 5) "success a: 1 b: 2 c: 3 d: 4 . n: (5)" ))
|
103
|
+
|
104
|
+
(suite "five params"
|
105
|
+
("no args" (tst-5) "success a: b: c: d: e: " )
|
106
|
+
("one arg" (tst-5 1) "success a: 1 b: c: d: e: " )
|
107
|
+
("two args" (tst-5 1 2) "success a: 1 b: 2 c: d: e: " )
|
108
|
+
("three args" (tst-5 1 2 3) "success a: 1 b: 2 c: 3 d: e: " )
|
109
|
+
("four args" (tst-5 1 2 3 4) "success a: 1 b: 2 c: 3 d: 4 e: " )
|
110
|
+
("five args" (tst-5 1 2 3 4 5) "success a: 1 b: 2 c: 3 d: 4 e: 5" ))
|
111
|
+
|
112
|
+
(suite "five params and rest param"
|
113
|
+
("no args" (tst-5-n) "success a: b: c: d: e: . n: nil" )
|
114
|
+
("one arg" (tst-5-n 1) "success a: 1 b: c: d: e: . n: nil" )
|
115
|
+
("two args" (tst-5-n 1 2) "success a: 1 b: 2 c: d: e: . n: nil" )
|
116
|
+
("three args" (tst-5-n 1 2 3) "success a: 1 b: 2 c: 3 d: e: . n: nil" )
|
117
|
+
("four args" (tst-5-n 1 2 3 4) "success a: 1 b: 2 c: 3 d: 4 e: . n: nil" )
|
118
|
+
("five args" (tst-5-n 1 2 3 4 5) "success a: 1 b: 2 c: 3 d: 4 e: 5 . n: nil" ))
|
119
|
+
))
|
data/lib/nydp/builtin.rb
CHANGED
@@ -3,13 +3,34 @@ require 'nydp/error'
|
|
3
3
|
|
4
4
|
module Nydp::Builtin
|
5
5
|
module Base
|
6
|
+
include Nydp::Helper
|
7
|
+
|
8
|
+
def invoke_1 vm
|
9
|
+
invoke vm, Nydp.NIL
|
10
|
+
end
|
11
|
+
|
12
|
+
def invoke_2 vm, arg
|
13
|
+
invoke vm, cons(arg)
|
14
|
+
end
|
15
|
+
|
16
|
+
def invoke_3 vm, arg_0, arg_1
|
17
|
+
invoke vm, cons(arg_0, cons(arg_1))
|
18
|
+
end
|
19
|
+
|
6
20
|
def invoke vm, args
|
7
21
|
builtin_invoke vm, args
|
8
|
-
rescue Nydp::Error => ne
|
9
|
-
raise ne
|
10
22
|
rescue Exception => e
|
11
|
-
|
12
|
-
|
23
|
+
handle_error e, args
|
24
|
+
end
|
25
|
+
|
26
|
+
def handle_error e, args
|
27
|
+
case e
|
28
|
+
when Nydp::Error
|
29
|
+
raise e
|
30
|
+
else
|
31
|
+
new_msg = "Called #{self.inspect}\nwith args #{args.inspect}\nraised\n#{Nydp.indent_text e.message}\nat #{e.backtrace.first}"
|
32
|
+
raise $!, new_msg, $!.backtrace
|
33
|
+
end
|
13
34
|
end
|
14
35
|
|
15
36
|
def name
|
data/lib/nydp/builtin/hash.rb
CHANGED
@@ -17,9 +17,15 @@ class Nydp::Builtin::HashGet
|
|
17
17
|
case hash
|
18
18
|
when Nydp::Hash
|
19
19
|
vm.push_arg(hash[key] || Nydp.NIL)
|
20
|
+
when NilClass, Nydp.NIL
|
21
|
+
vm.push_arg Nydp.NIL
|
20
22
|
else
|
21
|
-
|
22
|
-
|
23
|
+
if hash.respond_to? :[]
|
24
|
+
key = n2r args.cdr.car
|
25
|
+
vm.push_arg(r2n hash[key], ns)
|
26
|
+
else
|
27
|
+
raise "hash-get: Not a hash: #{hash.class.name}"
|
28
|
+
end
|
23
29
|
end
|
24
30
|
end
|
25
31
|
end
|
@@ -33,8 +39,14 @@ class Nydp::Builtin::HashSet
|
|
33
39
|
case hash
|
34
40
|
when Nydp::Hash
|
35
41
|
hash[key] = value
|
42
|
+
when NilClass, Nydp.NIL
|
43
|
+
nil
|
36
44
|
else
|
37
|
-
hash[
|
45
|
+
if hash.respond_to?(:[]=)
|
46
|
+
hash[n2r key] = n2r value
|
47
|
+
else
|
48
|
+
raise "hash-set: Not a hash: #{hash.class.name}"
|
49
|
+
end
|
38
50
|
end
|
39
51
|
vm.push_arg value
|
40
52
|
end
|
data/lib/nydp/closure.rb
CHANGED
@@ -6,6 +6,18 @@ module Nydp
|
|
6
6
|
@ifn, @context = ifn, context
|
7
7
|
end
|
8
8
|
|
9
|
+
def invoke_1 vm
|
10
|
+
ifn.invoke_1 vm, context
|
11
|
+
end
|
12
|
+
|
13
|
+
def invoke_2 vm, arg
|
14
|
+
ifn.invoke_2 vm, context, arg
|
15
|
+
end
|
16
|
+
|
17
|
+
def invoke_3 vm, arg_0, arg_1
|
18
|
+
ifn.invoke_3 vm, context, arg_0, arg_1
|
19
|
+
end
|
20
|
+
|
9
21
|
def invoke vm, arg_values
|
10
22
|
ifn.invoke vm, context, arg_values
|
11
23
|
end
|
@@ -2,38 +2,93 @@ module Nydp
|
|
2
2
|
class InvocationFailed < StandardError
|
3
3
|
end
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
module Invocation
|
6
|
+
class Base
|
7
|
+
include Helper
|
8
|
+
def initialize source_expression
|
9
|
+
@source_expression = source_expression
|
10
|
+
end
|
11
|
+
|
12
|
+
def handle e, f, args
|
13
|
+
case e
|
14
|
+
when Nydp::Error, InvocationFailed
|
15
|
+
raise e
|
16
|
+
else
|
17
|
+
msg = "failed to execute invocation #{f.inspect} #{args.inspect}"
|
18
|
+
msg += "\nsource was #{source.inspect}"
|
19
|
+
msg += "\nfunction name was #{source.car.inspect}"
|
20
|
+
i_f = InvocationFailed.new "#{msg}\n#{e.message}"
|
21
|
+
i_f.set_backtrace e.backtrace
|
22
|
+
raise i_f
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def inspect ; source.inspect ; end
|
27
|
+
def source ; @source_expression ; end
|
28
|
+
def to_s ; source.to_s ; end
|
9
29
|
end
|
10
30
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
31
|
+
class Invocation_1 < Invocation::Base
|
32
|
+
def execute vm
|
33
|
+
f = vm.pop_arg
|
34
|
+
f.invoke_1 vm
|
35
|
+
rescue Exception => e
|
36
|
+
handle e, f, Nydp.NIL
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class Invocation_2 < Invocation::Base
|
41
|
+
def execute vm
|
42
|
+
arg = vm.pop_arg
|
43
|
+
f = vm.pop_arg
|
44
|
+
f.invoke_2 vm, arg
|
45
|
+
rescue Exception => e
|
46
|
+
handle e, f, cons(arg)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class Invocation_3 < Invocation::Base
|
51
|
+
def execute vm
|
52
|
+
arg_1 = vm.pop_arg
|
53
|
+
arg_0 = vm.pop_arg
|
54
|
+
f = vm.pop_arg
|
55
|
+
f.invoke_3 vm, arg_0, arg_1
|
56
|
+
rescue Exception => e
|
57
|
+
handle e, f, cons(arg_0, cons(arg_1))
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class Invocation_N < Invocation::Base
|
62
|
+
def initialize arg_count, source_expression
|
63
|
+
super source_expression
|
64
|
+
@arg_count = arg_count
|
65
|
+
end
|
66
|
+
|
67
|
+
def execute vm
|
68
|
+
args = vm.pop_args @arg_count
|
69
|
+
args.car.invoke vm, args.cdr
|
70
|
+
rescue Exception => e
|
71
|
+
handle e, args.car, args.cdr
|
72
|
+
end
|
73
|
+
end
|
30
74
|
end
|
31
75
|
|
32
76
|
class FunctionInvocation
|
33
77
|
extend Helper
|
34
78
|
|
35
79
|
def self.build expression, bindings
|
36
|
-
|
80
|
+
compiled = Compiler.compile_each(expression, bindings)
|
81
|
+
invocation = cons case expression.size
|
82
|
+
when 1
|
83
|
+
Invocation::Invocation_1.new(expression)
|
84
|
+
when 2
|
85
|
+
Invocation::Invocation_2.new(expression)
|
86
|
+
when 3
|
87
|
+
Invocation::Invocation_3.new(expression)
|
88
|
+
else
|
89
|
+
Invocation::Invocation_N.new(expression.size, expression)
|
90
|
+
end
|
91
|
+
new invocation, compiled, expression
|
37
92
|
end
|
38
93
|
|
39
94
|
def initialize function_instruction, argument_instructions, source
|
@@ -1,30 +1,39 @@
|
|
1
1
|
require 'nydp/lexical_context'
|
2
|
+
require 'nydp/lexical_context_builder'
|
2
3
|
require 'nydp/closure'
|
3
4
|
|
4
5
|
module Nydp
|
5
6
|
class PopArg
|
6
|
-
def self.execute vm
|
7
|
-
|
8
|
-
end
|
9
|
-
|
10
|
-
def self.to_s
|
11
|
-
""
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.inspect
|
15
|
-
"#pop_arg"
|
16
|
-
end
|
7
|
+
def self.execute vm ; vm.pop_arg ; end
|
8
|
+
def self.to_s ; "" ; end
|
9
|
+
def self.inspect ; "#pop_arg" ; end
|
17
10
|
end
|
18
11
|
|
19
12
|
class InterpretedFunction
|
20
13
|
include Helper
|
21
14
|
extend Helper
|
22
15
|
|
23
|
-
attr_accessor :arg_names, :body
|
16
|
+
attr_accessor :arg_names, :body, :context_builder
|
17
|
+
|
18
|
+
def invoke_1 vm, parent_context
|
19
|
+
vm.push_instructions self.body, LexicalContext.new(parent_context)
|
20
|
+
end
|
21
|
+
|
22
|
+
def invoke_2 vm, parent_context, arg
|
23
|
+
lc = LexicalContext.new parent_context
|
24
|
+
set_args_1 lc, arg
|
25
|
+
vm.push_instructions self.body, lc
|
26
|
+
end
|
27
|
+
|
28
|
+
def invoke_3 vm, parent_context, arg_0, arg_1
|
29
|
+
lc = LexicalContext.new parent_context
|
30
|
+
set_args_2 lc, arg_0, arg_1
|
31
|
+
vm.push_instructions self.body, lc
|
32
|
+
end
|
24
33
|
|
25
34
|
def invoke vm, parent_context, arg_values
|
26
35
|
lc = LexicalContext.new parent_context
|
27
|
-
|
36
|
+
set_args lc, arg_values
|
28
37
|
vm.push_instructions self.body, lc
|
29
38
|
end
|
30
39
|
|
@@ -42,6 +51,8 @@ module Nydp
|
|
42
51
|
index_parameters arg_list, my_params
|
43
52
|
ifn = Nydp::InterpretedFunction.new
|
44
53
|
ifn.arg_names = arg_list
|
54
|
+
ifn.extend Nydp::LexicalContextBuilder.select arg_list
|
55
|
+
ifn.initialize_names arg_list
|
45
56
|
ifn.body = compile_body body, cons(my_params, bindings), []
|
46
57
|
ifn
|
47
58
|
end
|
data/lib/nydp/lexical_context.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
class Nydp::LexicalContext
|
2
|
+
include Nydp::Helper
|
2
3
|
attr_reader :names, :values, :parent
|
3
4
|
|
4
5
|
def initialize parent
|
@@ -31,6 +32,23 @@ class Nydp::LexicalContext
|
|
31
32
|
values << value
|
32
33
|
end
|
33
34
|
|
35
|
+
def set_args_1 names, arg
|
36
|
+
if pair? names
|
37
|
+
set names.car, arg
|
38
|
+
elsif Nydp.NIL.isnt? names
|
39
|
+
set names, cons(arg)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def set_args_2 names, arg_0, arg_1
|
44
|
+
if pair? names
|
45
|
+
set names.car, arg_0
|
46
|
+
set_args_1 names.cdr, arg_1
|
47
|
+
elsif Nydp.NIL.isnt? names
|
48
|
+
set names, cons(arg_0, cons(arg_1))
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
34
52
|
def set_index index, value
|
35
53
|
values[index] = value
|
36
54
|
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
module Nydp::LexicalContextBuilder
|
2
|
+
extend Nydp::Helper
|
3
|
+
|
4
|
+
module B_0
|
5
|
+
def initialize_names _ ; end
|
6
|
+
def set_args_1 lc, a ; end
|
7
|
+
def set_args_2 lc, a_0, a_1 ; end
|
8
|
+
def set_args lc, args ; end
|
9
|
+
end
|
10
|
+
|
11
|
+
module B_1
|
12
|
+
def initialize_names names ; @param_name = names.car ; end
|
13
|
+
def set_args_1 lc, arg ; lc.set @param_name, arg ; end
|
14
|
+
def set_args_2 lc, arg_0, arg_1 ; lc.set @param_name, arg_0 ; end
|
15
|
+
def set_args lc, args ; lc.set @param_name, args.car ; end
|
16
|
+
end
|
17
|
+
|
18
|
+
module B_2
|
19
|
+
def initialize_names names
|
20
|
+
@param_name_0 = names.car
|
21
|
+
@param_name_1 = names.cdr.car
|
22
|
+
end
|
23
|
+
def set_args_1 lc, arg
|
24
|
+
lc.set @param_name_0, arg
|
25
|
+
end
|
26
|
+
def set_args_2 lc, arg_0, arg_1
|
27
|
+
lc.set @param_name_0, arg_0
|
28
|
+
lc.set @param_name_1, arg_1
|
29
|
+
end
|
30
|
+
def set_args lc, args
|
31
|
+
lc.set @param_name_0, args.car
|
32
|
+
lc.set @param_name_1, args.cdr.car
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
module B_0_Rest
|
37
|
+
include Nydp::Helper
|
38
|
+
def initialize_names names ; @param_name = names ; end
|
39
|
+
def set_args_1 lc, arg ; lc.set @param_name, cons(arg) ; end
|
40
|
+
def set_args_2 lc, arg_0, arg_1 ; lc.set @param_name, cons(arg_0, cons(arg_1)) ; end
|
41
|
+
def set_args lc, args ; lc.set @param_name, args ; end
|
42
|
+
end
|
43
|
+
|
44
|
+
module B_1_Rest
|
45
|
+
include Nydp::Helper
|
46
|
+
def initialize_names names
|
47
|
+
@param_name_0 = names.car
|
48
|
+
@param_name_1 = names.cdr
|
49
|
+
end
|
50
|
+
def set_args_1 lc, arg
|
51
|
+
lc.set @param_name_0, arg
|
52
|
+
end
|
53
|
+
def set_args_2 lc, arg_0, arg_1
|
54
|
+
lc.set @param_name_0, arg_0
|
55
|
+
lc.set @param_name_1, cons(arg_1)
|
56
|
+
end
|
57
|
+
def set_args lc, args
|
58
|
+
lc.set @param_name_0, args.car
|
59
|
+
lc.set @param_name_1, args.cdr
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
module B_2_Rest
|
64
|
+
def initialize_names names
|
65
|
+
@param_name_0 = names.car
|
66
|
+
@param_name_1 = names.cdr.car
|
67
|
+
@param_name_2 = names.cdr.cdr
|
68
|
+
end
|
69
|
+
def set_args_1 lc, arg
|
70
|
+
lc.set @param_name_0, arg
|
71
|
+
end
|
72
|
+
def set_args_2 lc, arg_0, arg_1
|
73
|
+
lc.set @param_name_0, arg_0
|
74
|
+
lc.set @param_name_1, arg_1
|
75
|
+
end
|
76
|
+
def set_args lc, args
|
77
|
+
lc.set @param_name_0, args.car
|
78
|
+
lc.set @param_name_1, args.cdr.car
|
79
|
+
lc.set @param_name_2, args.cdr.cdr
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
module B_X
|
84
|
+
def initialize_names names
|
85
|
+
@param_names = names
|
86
|
+
end
|
87
|
+
def set_args_1 lc, arg
|
88
|
+
lc.set @param_names.car, arg
|
89
|
+
end
|
90
|
+
def set_args_2 lc, arg_0, arg_1
|
91
|
+
lc.set @param_names.car, arg_0
|
92
|
+
lc.set @param_names.cdr.car, arg_1
|
93
|
+
end
|
94
|
+
def set_args lc, args
|
95
|
+
_set_args lc, @param_names, args
|
96
|
+
end
|
97
|
+
def _set_args lc, names, args
|
98
|
+
unless Nydp.NIL.is? names
|
99
|
+
lc.set names.car, args.car
|
100
|
+
_set_args lc, names.cdr, args.cdr
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
module B_X_Rest
|
106
|
+
include Nydp::Helper
|
107
|
+
def initialize_names names ; @param_names = names ; end
|
108
|
+
def set_args_1 lc, arg ; set_args lc, cons(arg) ; end
|
109
|
+
def set_args_2 lc, arg_0, arg_1 ; set_args lc, cons(arg_0, cons(arg_1)) ; end
|
110
|
+
def set_args lc, args ; _set_args lc, @param_names, args ; end
|
111
|
+
def _set_args lc, names, args
|
112
|
+
if pair? names
|
113
|
+
lc.set names.car, args.car
|
114
|
+
_set_args lc, names.cdr, args.cdr
|
115
|
+
elsif Nydp.NIL.isnt? names
|
116
|
+
lc.set names, args
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.select arg_names
|
122
|
+
if pair? arg_names
|
123
|
+
size = pair?(arg_names) ? arg_names.size : 0
|
124
|
+
class_name = "B_#{size > 2 ? "X" : size}#{arg_names.proper? ? "" : "_Rest"}"
|
125
|
+
else
|
126
|
+
class_name = "B_0_Rest"
|
127
|
+
end
|
128
|
+
self.const_get(class_name.to_sym)
|
129
|
+
end
|
130
|
+
end
|
data/lib/nydp/pair.rb
CHANGED
data/lib/nydp/version.rb
CHANGED
data/spec/hash_spec.rb
CHANGED
@@ -153,4 +153,74 @@ describe Nydp::Hash do
|
|
153
153
|
end
|
154
154
|
end
|
155
155
|
end
|
156
|
+
|
157
|
+
describe "get/set nil" do
|
158
|
+
let(:ahash) { Nydp.NIL }
|
159
|
+
|
160
|
+
describe "hash set" do
|
161
|
+
it "does nothing, returns its value" do
|
162
|
+
k = Nydp::Symbol.mk "keysym", ns
|
163
|
+
v = Nydp::StringAtom.new "foobar"
|
164
|
+
args = pair_list [ahash, k, v]
|
165
|
+
Nydp::Builtin::HashSet.new.invoke vm, args
|
166
|
+
|
167
|
+
expect(ahash). to eq Nydp.NIL
|
168
|
+
expect(vm.pop_arg).to eq v
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
describe "hash get" do
|
173
|
+
it "converts ruby value to nydp value" do
|
174
|
+
k = Nydp::Symbol.mk "keysym", ns
|
175
|
+
args = [ ahash, k ]
|
176
|
+
|
177
|
+
Nydp::Builtin::HashGet.new(ns).invoke vm, pair_list(args)
|
178
|
+
|
179
|
+
expect(vm.pop_arg).to eq Nydp.NIL
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
describe "non-hash" do
|
185
|
+
let(:ahash) { Nydp::StringAtom.new "this here ain't no hash, hombre" }
|
186
|
+
|
187
|
+
describe "hash set" do
|
188
|
+
it "does nothing, returns its value" do
|
189
|
+
k = Nydp::Symbol.mk "keysym", ns
|
190
|
+
v = Nydp::StringAtom.new "foobar"
|
191
|
+
args = pair_list [ahash, k, v]
|
192
|
+
|
193
|
+
begin
|
194
|
+
Nydp::Builtin::HashSet.new.invoke vm, args
|
195
|
+
rescue Exception => e
|
196
|
+
error = e
|
197
|
+
end
|
198
|
+
|
199
|
+
expect(error.message.gsub(/at \/.*:in `builtin_invoke'/, '<error info>')).to eq "Called builtin/hash-set
|
200
|
+
with args (\"this here ain't no hash, hombre\" keysym \"foobar\")
|
201
|
+
raised
|
202
|
+
hash-set: Not a hash: Nydp::StringAtom
|
203
|
+
<error info>"
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
describe "hash get" do
|
208
|
+
it "converts ruby value to nydp value" do
|
209
|
+
k = Nydp::Symbol.mk "keysym", ns
|
210
|
+
args = [ ahash, k ]
|
211
|
+
|
212
|
+
begin
|
213
|
+
Nydp::Builtin::HashGet.new(ns).invoke vm, pair_list(args)
|
214
|
+
rescue Exception => e
|
215
|
+
error = e
|
216
|
+
end
|
217
|
+
|
218
|
+
expect(error.message.gsub(/at \/.*:in `builtin_invoke'/, '<error info>')).to eq "Called builtin/hash-get
|
219
|
+
with args (\"this here ain't no hash, hombre\" keysym)
|
220
|
+
raised
|
221
|
+
hash-get: Not a hash: Nydp::StringAtom
|
222
|
+
<error info>"
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|
156
226
|
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.12
|
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-
|
11
|
+
date: 2015-09-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -90,11 +90,13 @@ files:
|
|
90
90
|
- lib/lisp/core-03-syntax.nydp
|
91
91
|
- lib/lisp/core-04-utils.nydp
|
92
92
|
- lib/lisp/core-05-test-runner.nydp
|
93
|
+
- lib/lisp/core-06-benchmarking.nydp
|
93
94
|
- lib/lisp/tests/boot-tests.nydp
|
94
95
|
- lib/lisp/tests/builtin-tests.nydp
|
95
96
|
- lib/lisp/tests/dynamic-scope-test.nydp
|
96
97
|
- lib/lisp/tests/error-tests.nydp
|
97
98
|
- lib/lisp/tests/foundation-test.nydp
|
99
|
+
- lib/lisp/tests/invocation-tests.nydp
|
98
100
|
- lib/lisp/tests/parser-tests.nydp
|
99
101
|
- lib/nydp.rb
|
100
102
|
- lib/nydp/assignment.rb
|
@@ -148,6 +150,7 @@ files:
|
|
148
150
|
- lib/nydp/helper.rb
|
149
151
|
- lib/nydp/interpreted_function.rb
|
150
152
|
- lib/nydp/lexical_context.rb
|
153
|
+
- lib/nydp/lexical_context_builder.rb
|
151
154
|
- lib/nydp/literal.rb
|
152
155
|
- lib/nydp/pair.rb
|
153
156
|
- lib/nydp/parser.rb
|