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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6cb7040e607f04ac084dcf352dfe736d7c800d0b
4
- data.tar.gz: 6c157638bebfa82f3b027ed38aa12dd1452b8396
3
+ metadata.gz: 6e7ea4e19c5b46b3a1c56299814f4412262c19ee
4
+ data.tar.gz: e812a2a39dab9ac0eb1a27b8cce1d6f0fd0b8f21
5
5
  SHA512:
6
- metadata.gz: 231c62ab18da966168e4f1320f36bf9c1df91d9597cb4d68fee07bfac9b3e8ea8092ae9b1161a747483bc1711edfaa3985edcd1eeec2b7f59cc49825e63b8642
7
- data.tar.gz: 96ab3742b6e55da13118b92ad3837517f7710e7fad80708361ca1f5909c0be726ec58ad8a57f48eef5a49610530a865bd325dc19cb860410665bda145da97cfd
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 (2n+1)th items are literal symbol keys, and every (2(n+1))th item is the corresponding value which is evaluated at run time.
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 with macros to define dynamic variables backed by ruby threadlocals.
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
+ ))
@@ -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
- new_msg = "Called #{self.inspect}\nwith args #{args.inspect}\nraised\n#{Nydp.indent_text e.message}"
12
- raise $!, new_msg, $!.backtrace
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
@@ -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
- key = n2r args.cdr.car
22
- vm.push_arg(r2n hash[key], ns)
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[n2r key] = n2r value
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
@@ -2,6 +2,7 @@ class Nydp::Builtin::PreCompile
2
2
  include Nydp::Builtin::Base
3
3
 
4
4
  def builtin_invoke vm, args
5
+ raise Nydp:Error.new("pre-compile: expects one arg, got #{args.inspect}") unless Nydp.NIL == args.cdr
5
6
  vm.push_arg args.car
6
7
  end
7
8
  end
@@ -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
- class InvokeFunctionInstruction
6
- def initialize arg_count, source_expression
7
- @source_expression = source_expression
8
- @arg_count = arg_count
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
- def execute vm
12
- args = vm.pop_args @arg_count
13
- args.car.invoke vm, args.cdr
14
- rescue Nydp::Error => ne
15
- raise ne
16
- rescue InvocationFailed => i_f
17
- raise i_f
18
- rescue Exception => e
19
- msg = "failed to execute invocation #{args.inspect}"
20
- msg += "\nsource was #{source.inspect}"
21
- msg += "\nfunction name was #{source.car.inspect}"
22
- i_f = InvocationFailed.new "#{msg}\n#{e.message}"
23
- i_f.set_backtrace e.backtrace
24
- raise i_f
25
- end
26
-
27
- def inspect ; source.inspect ; end
28
- def source ; @source_expression ; end
29
- def to_s ; source.to_s ; end
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
- new cons(InvokeFunctionInstruction.new(expression.size, expression)), Compiler.compile_each(expression, bindings), expression
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
- vm.pop_arg
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
- setup_context lc, arg_names, arg_values
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
@@ -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
@@ -55,6 +55,10 @@ class Nydp::Pair
55
55
  1 + (cdr.is_a?(Nydp::Pair) ? cdr.size : 0)
56
56
  end
57
57
 
58
+ def proper?
59
+ Nydp.NIL.is?(cdr) || (cdr.is_a?(Nydp::Pair) && cdr.proper?)
60
+ end
61
+
58
62
  def each &block
59
63
  yield car
60
64
  cdr.each(&block) unless Nydp.NIL.is?(cdr)
@@ -1,3 +1,3 @@
1
1
  module Nydp
2
- VERSION = "0.0.11"
2
+ VERSION = "0.0.12"
3
3
  end
@@ -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.11
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-08-11 00:00:00.000000000 Z
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