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