nydp 0.2.3 → 0.2.5

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.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/bin/nydp +1 -1
  3. data/lib/lisp/core-000.nydp +1 -0
  4. data/lib/lisp/core-010-precompile.nydp +15 -15
  5. data/lib/lisp/core-012-utils.nydp +6 -5
  6. data/lib/lisp/core-020-utils.nydp +20 -6
  7. data/lib/lisp/core-030-syntax.nydp +14 -16
  8. data/lib/lisp/core-035-flow-control.nydp +26 -8
  9. data/lib/lisp/core-040-utils.nydp +4 -15
  10. data/lib/lisp/core-041-string-utils.nydp +3 -3
  11. data/lib/lisp/core-043-list-utils.nydp +81 -16
  12. data/lib/lisp/core-045-dox-utils.nydp +2 -2
  13. data/lib/lisp/core-060-benchmarking.nydp +92 -27
  14. data/lib/lisp/tests/all-examples.nydp +20 -0
  15. data/lib/lisp/tests/any-examples.nydp +28 -0
  16. data/lib/lisp/tests/builtin-tests.nydp +3 -1
  17. data/lib/lisp/tests/collect-tests.nydp +10 -0
  18. data/lib/lisp/tests/curry-tests.nydp +7 -2
  19. data/lib/lisp/tests/error-tests.nydp +11 -0
  20. data/lib/lisp/tests/foundation-test.nydp +66 -0
  21. data/lib/lisp/tests/len-examples.nydp +1 -0
  22. data/lib/lisp/tests/list-gsub-examples.nydp +25 -0
  23. data/lib/lisp/tests/list-match-examples.nydp +40 -0
  24. data/lib/lisp/tests/list-tests.nydp +13 -0
  25. data/lib/lisp/tests/none-examples.nydp +16 -0
  26. data/lib/lisp/tests/parser-tests.nydp +4 -5
  27. data/lib/lisp/tests/quasiquote-examples.nydp +2 -0
  28. data/lib/lisp/tests/syntax-tests.nydp +3 -2
  29. data/lib/lisp/tests/tuples-examples.nydp +2 -2
  30. data/lib/nydp.rb +50 -18
  31. data/lib/nydp/assignment.rb +3 -1
  32. data/lib/nydp/builtin.rb +15 -13
  33. data/lib/nydp/builtin/error.rb +1 -1
  34. data/lib/nydp/builtin/handle_error.rb +8 -2
  35. data/lib/nydp/builtin/parse_in_string.rb +1 -1
  36. data/lib/nydp/builtin/plus.rb +4 -4
  37. data/lib/nydp/closure.rb +5 -1
  38. data/lib/nydp/compiler.rb +2 -3
  39. data/lib/nydp/cond.rb +134 -13
  40. data/lib/nydp/context_symbol.rb +4 -1
  41. data/lib/nydp/error.rb +8 -0
  42. data/lib/nydp/function_invocation.rb +46 -48
  43. data/lib/nydp/helper.rb +15 -0
  44. data/lib/nydp/interpreted_function.rb +10 -14
  45. data/lib/nydp/lexical_context.rb +13 -2
  46. data/lib/nydp/lexical_context_builder.rb +28 -13
  47. data/lib/nydp/pair.rb +35 -36
  48. data/lib/nydp/parser.rb +3 -0
  49. data/lib/nydp/runner.rb +4 -32
  50. data/lib/nydp/string_atom.rb +3 -2
  51. data/lib/nydp/symbol.rb +1 -1
  52. data/lib/nydp/symbol_lookup.rb +9 -1
  53. data/lib/nydp/truth.rb +1 -1
  54. data/lib/nydp/version.rb +1 -1
  55. data/lib/nydp/vm.rb +2 -2
  56. data/nydp.gemspec +1 -1
  57. data/spec/error_spec.rb +14 -4
  58. data/spec/hash_non_hash_behaviour_spec.rb +19 -12
  59. data/spec/hash_spec.rb +0 -13
  60. data/spec/pair_spec.rb +17 -3
  61. data/spec/spec_helper.rb +13 -1
  62. data/spec/symbol_spec.rb +1 -1
  63. metadata +9 -4
@@ -31,13 +31,16 @@ class #{cname} < Nydp::ContextSymbol
31
31
 
32
32
  def assign value, ctx
33
33
  ctx#{getctx}.#{set_index}
34
+ rescue StandardError => e
35
+ raise "problem in \#{self.class.name}#assign, name is \#{@name}, depth is \#{depth}, index is #{binding_index}"
34
36
  end
35
37
 
36
38
  def execute vm
37
39
  vm.push_arg value vm.current_context
38
40
  end
39
41
 
40
- def inspect ; to_s ; end
42
+ def depth ; #{depth} ; end
43
+ def inspect ; to_s ; end
41
44
  def to_s ; "[#{depth}##{binding_index}]\#{@name}" ; end
42
45
  end
43
46
  KLASS
@@ -4,5 +4,13 @@ module Nydp
4
4
  end
5
5
 
6
6
  class Error < StandardError
7
+ def initialize message, nydp_cause=nil
8
+ super(message)
9
+ @nydp_cause = nydp_cause
10
+ end
11
+
12
+ def cause
13
+ @nydp_cause || super
14
+ end
7
15
  end
8
16
  end
@@ -9,17 +9,20 @@ module Nydp
9
9
  @source_expression = source_expression
10
10
  end
11
11
 
12
- def handle e, f, args
12
+ def handle e, f, invoker, *args
13
13
  case e
14
14
  when Nydp::Error, InvocationFailed
15
- raise e
15
+ raise
16
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
17
+ if e.is_a?(NoMethodError) && !f.respond_to?(invoker)
18
+ raise InvocationFailed.new("#{f} is not a function")
19
+ else
20
+ msg = args.map { |a| " #{a.inspect}"}.join("\n")
21
+ msg = "failed to execute invocation #{f.inspect}\n#{msg}"
22
+ msg += "\nsource was #{source.inspect}"
23
+ msg += "\nfunction name was #{source.car.inspect}"
24
+ raise InvocationFailed.new msg
25
+ end
23
26
  end
24
27
  end
25
28
 
@@ -32,8 +35,8 @@ module Nydp
32
35
  def execute vm
33
36
  f = vm.args.pop
34
37
  f.invoke_1 vm
35
- rescue Exception => e
36
- handle e, f, Nydp::NIL
38
+ rescue StandardError => e
39
+ handle e, f, :invoke_1
37
40
  end
38
41
  end
39
42
 
@@ -41,10 +44,9 @@ module Nydp
41
44
  def execute vm
42
45
  arg = vm.args.pop
43
46
  f = vm.args.pop
44
-
45
47
  f.invoke_2 vm, arg
46
- rescue Exception => e
47
- handle e, f, cons(arg)
48
+ rescue StandardError => e
49
+ handle e, f, :invoke_2, arg
48
50
  end
49
51
  end
50
52
 
@@ -54,8 +56,8 @@ module Nydp
54
56
  arg_0 = vm.args.pop
55
57
  f = vm.args.pop
56
58
  f.invoke_3 vm, arg_0, arg_1
57
- rescue Exception => e
58
- handle e, f, cons(arg_0, cons(arg_1))
59
+ rescue StandardError => e
60
+ handle e, f, :invoke_3, arg_0, arg_1
59
61
  end
60
62
  end
61
63
 
@@ -66,8 +68,8 @@ module Nydp
66
68
  arg_0 = vm.args.pop
67
69
  f = vm.args.pop
68
70
  f.invoke_4 vm, arg_0, arg_1, arg_2
69
- rescue Exception => e
70
- handle e, f, cons(arg_0, cons(arg_1, cons(arg_2)))
71
+ rescue StandardError => e
72
+ handle e, f, :invoke_4, arg_0, arg_1, arg_2
71
73
  end
72
74
  end
73
75
 
@@ -80,13 +82,16 @@ module Nydp
80
82
  def execute vm
81
83
  args = vm.pop_args @arg_count
82
84
  args.car.invoke vm, args.cdr
83
- rescue Exception => e
84
- handle e, args.car, args.cdr
85
+ rescue StandardError => e
86
+ handle e, args.car, :invoke, args.cdr
85
87
  end
86
88
  end
87
89
 
88
90
  # TODO generate various Invocation_XXX classes on-demand instead of hand_coding them all up front
91
+ SIGS = Set.new
92
+
89
93
  class Invocation_LEX < Invocation::Base
94
+ SIGS << self.name
90
95
  def initialize expr, src
91
96
  super src
92
97
  @sym = expr.car
@@ -94,12 +99,13 @@ module Nydp
94
99
 
95
100
  def execute vm
96
101
  @sym.value(vm.current_context).invoke_1 vm
97
- rescue Exception => e
98
- handle e, @sym.value(vm.current_context), Nydp::NIL
102
+ rescue StandardError => e
103
+ handle e, @sym.value(vm.current_context), :invoke_1
99
104
  end
100
105
  end
101
106
 
102
107
  class Invocation_SYM < Invocation::Base
108
+ SIGS << self.name
103
109
  def initialize expr, src
104
110
  super src
105
111
  @sym = expr.car
@@ -107,12 +113,13 @@ module Nydp
107
113
 
108
114
  def execute vm
109
115
  @sym.value.invoke_1 vm
110
- rescue Exception => e
111
- handle e, @sym.value, Nydp::NIL
116
+ rescue StandardError => e
117
+ handle e, @sym.value, :invoke_1
112
118
  end
113
119
  end
114
120
 
115
121
  class Invocation_LEX_LEX < Invocation::Base
122
+ SIGS << self.name
116
123
  def initialize expr, src
117
124
  super src
118
125
  @lex0 = expr.car
@@ -123,12 +130,13 @@ module Nydp
123
130
  fn = @lex0.value(vm.current_context)
124
131
  a0 = @lex1.value(vm.current_context)
125
132
  fn.invoke_2 vm, a0
126
- rescue Exception => e
127
- handle e, fn, cons(a0)
133
+ rescue StandardError => e
134
+ handle e, fn, :invoke_2, a0
128
135
  end
129
136
  end
130
137
 
131
138
  class Invocation_SYM_LEX < Invocation::Base
139
+ SIGS << self.name
132
140
  def initialize expr, src
133
141
  super src
134
142
  @sym = expr.car
@@ -139,12 +147,13 @@ module Nydp
139
147
  fn = @sym.value
140
148
  a0 = @lex.value(vm.current_context)
141
149
  fn.invoke_2 vm, a0
142
- rescue Exception => e
143
- handle e, fn, cons(a0)
150
+ rescue StandardError => e
151
+ handle e, fn, :invoke_2, a0
144
152
  end
145
153
  end
146
154
 
147
155
  class Invocation_LEX_LEX_LEX < Invocation::Base
156
+ SIGS << self.name
148
157
  def initialize expr, src
149
158
  super src
150
159
  @lex_0 = expr.car
@@ -157,12 +166,13 @@ module Nydp
157
166
  a0 = @lex_1.value(vm.current_context)
158
167
  a1 = @lex_2.value(vm.current_context)
159
168
  fn.invoke_3 vm, a0, a1
160
- rescue Exception => e
161
- handle e, fn, cons(a0, cons(a1))
169
+ rescue StandardError => e
170
+ handle e, fn, :invoke_3, a0, a1
162
171
  end
163
172
  end
164
173
 
165
174
  class Invocation_SYM_LEX_LEX < Invocation::Base
175
+ SIGS << self.name
166
176
  def initialize expr, src
167
177
  super src
168
178
  @sym = expr.car
@@ -175,8 +185,8 @@ module Nydp
175
185
  a0 = @lex_0.value(vm.current_context)
176
186
  a1 = @lex_1.value(vm.current_context)
177
187
  fn.invoke_3 vm, a0, a1
178
- rescue Exception => e
179
- handle e, fn, cons(a0, cons(a1))
188
+ rescue StandardError => e
189
+ handle e, fn, :invoke_3, a0, a1
180
190
  end
181
191
  end
182
192
  end
@@ -184,29 +194,17 @@ module Nydp
184
194
  class FunctionInvocation
185
195
  extend Helper
186
196
  attr_accessor :function_instruction, :argument_instructions
197
+ @@put = nil
187
198
 
188
- def self.sig klass
189
- case klass
190
- when Nydp::Symbol ; "SYM"
191
- when Nydp::ContextSymbol ; "LEX"
192
- when Nydp::Literal ; "LIT"
193
- when Nydp::FunctionInvocation ; "NVK"
194
- when Nydp::Invocation::Base ; "NVB"
195
- when Nydp::InterpretedFunction ; "IFN"
196
- when Nydp::Cond ; "CND"
197
- when Nydp::Assignment ; "ASN"
198
- else ; raise "no sig for #{klass.class.name}"
199
- end
200
- end
201
199
  def self.build expression, bindings
202
200
  compiled = Compiler.compile_each(expression, bindings)
203
201
  invocation_sig = compiled.map { |x| sig x }.join("_")
204
202
 
205
203
  cname = "Invocation_#{invocation_sig}"
206
- iclass = Nydp::Invocation.const_get(cname) rescue nil
207
- if iclass
208
- # puts "found #{cname}"
209
- return iclass.new(compiled, expression)
204
+
205
+ exists = Invocation::SIGS.include? "Nydp::Invocation::#{cname}"
206
+ if exists
207
+ return Nydp::Invocation.const_get(cname).new(compiled, expression)
210
208
  end
211
209
 
212
210
  invocation = cons case expression.size
@@ -30,6 +30,21 @@ module Nydp
30
30
  def n2r obj ; Nydp.n2r obj ; end
31
31
  def r2n obj, ns ; Nydp.r2n obj, ns ; end
32
32
 
33
+ def sig klass
34
+ case klass
35
+ when Nydp::Symbol ; "SYM"
36
+ when Nydp::ContextSymbol ; "LEX"
37
+ when Nydp::Literal ; "LIT"
38
+ when Nydp::FunctionInvocation ; "NVK"
39
+ when Nydp::Invocation::Base ; "NVB"
40
+ when Nydp::InterpretedFunction ; "IFN"
41
+ when Nydp::Cond ; "CND"
42
+ when Nydp::CondBase ; "CND"
43
+ when Nydp::Assignment ; "ASN"
44
+ else ; raise "no sig for #{klass.class.name}"
45
+ end
46
+ end
47
+
33
48
  def sym? expr, name
34
49
  expr.is_a?(Nydp::Symbol) && (expr.is? name)
35
50
  end
@@ -17,35 +17,27 @@ module Nydp
17
17
 
18
18
  def invoke_1 vm, parent_context
19
19
  vm.instructions.push self.body
20
- vm.contexts.push LexicalContext.new(parent_context)
20
+ vm.contexts.push set_args_0 parent_context
21
21
  end
22
22
 
23
23
  def invoke_2 vm, parent_context, arg
24
- lc = LexicalContext.new parent_context
25
- set_args_1 lc, arg
26
24
  vm.instructions.push self.body
27
- vm.contexts.push lc
25
+ vm.contexts.push set_args_1(parent_context, arg)
28
26
  end
29
27
 
30
28
  def invoke_3 vm, parent_context, arg_0, arg_1
31
- lc = LexicalContext.new parent_context
32
- set_args_2 lc, arg_0, arg_1
33
29
  vm.instructions.push self.body
34
- vm.contexts.push lc
30
+ vm.contexts.push set_args_2(parent_context, arg_0, arg_1)
35
31
  end
36
32
 
37
33
  def invoke_4 vm, parent_context, arg_0, arg_1, arg_2
38
- lc = LexicalContext.new parent_context
39
- set_args_3 lc, arg_0, arg_1, arg_2
40
34
  vm.instructions.push self.body
41
- vm.contexts.push lc
35
+ vm.contexts.push set_args_3(parent_context, arg_0, arg_1, arg_2)
42
36
  end
43
37
 
44
38
  def invoke vm, parent_context, arg_values
45
- lc = LexicalContext.new parent_context
46
- set_args lc, arg_values
47
39
  vm.instructions.push self.body
48
- vm.contexts.push lc
40
+ vm.contexts.push set_args(parent_context, arg_values)
49
41
  end
50
42
 
51
43
  def setup_context context, names, values
@@ -63,7 +55,6 @@ module Nydp
63
55
  ifn = Nydp::InterpretedFunction.new
64
56
  ifn.arg_names = arg_list
65
57
  ifn.extend Nydp::LexicalContextBuilder.select arg_list
66
- ifn.initialize_names arg_list
67
58
  ifn.body = compile_body body, cons(my_params, bindings), []
68
59
  ifn
69
60
  end
@@ -90,6 +81,11 @@ module Nydp
90
81
  end
91
82
 
92
83
  def execute vm
84
+ # TODO do not create a new Closure if this function does not refer to it
85
+ # - including top-level function definitions
86
+ # - and any other function that does not refer to any lexically-bound outer variable
87
+ # - for example (fn (x) (* x x)) in (map λx(* x x) things) does not need a closure, because
88
+ # the function does not refer to any lexical variable outside itself.
93
89
  vm.push_arg Closure.new(self, vm.current_context)
94
90
  end
95
91
 
@@ -38,14 +38,25 @@ module Nydp
38
38
  end
39
39
 
40
40
  def to_s_with_indent str
41
- me = @values.map { |k, v|
41
+ me = (@values || { }).map { |k, v|
42
42
  [str, k, "=>", v].join ' '
43
43
  }.join "\n"
44
44
  me + (parent ? parent.to_s_with_indent(" #{str}") : '')
45
45
  end
46
46
 
47
- def to_s
47
+ def pretty
48
48
  to_s_with_indent ''
49
49
  end
50
+
51
+ def to_s
52
+ values = []
53
+ n = 0
54
+ while at_index n
55
+ values << at_index(n).inspect
56
+ n += 1
57
+ end
58
+ parent_s = parent ? " parent #{parent.to_s}" : ""
59
+ "(context (#{values.join ' '})#{parent_s})"
60
+ end
50
61
  end
51
62
  end
@@ -1,12 +1,22 @@
1
1
  module Nydp::LexicalContextBuilder
2
2
  extend Nydp::Helper
3
3
 
4
+ def self.mklc nexpected
5
+ (nexpected > 0) ? "lc = Nydp::LexicalContext.new lc\n " : ""
6
+ end
7
+
8
+ def self.build_arg_names ngiven
9
+ (["lc"] + (0...ngiven ).map { |i| "arg_#{i}"}).join ", "
10
+ end
11
+
4
12
  def self.build_set_args_n_method ngiven, nexpected
5
13
  setter_count = [ngiven, nexpected].min
6
- arg_names = (0...ngiven ).map { |i| "arg_#{i}"}
7
14
  setters = (0...setter_count).map { |i| "lc.at_#{i}= arg_#{i}"}
8
- " def set_args_#{ngiven} lc, #{arg_names.join ", "}
9
- #{setters.join "\n "}
15
+ " def set_args_#{ngiven} #{build_arg_names ngiven}
16
+ #{mklc nexpected}#{setters.join "\n "}
17
+ lc
18
+ rescue StandardError => e
19
+ raise \"error in \#{self.class.name}#set_args_#{ngiven}\"
10
20
  end
11
21
  "
12
22
  end
@@ -26,9 +36,12 @@ module Nydp::LexicalContextBuilder
26
36
  if ngiven > setter_count
27
37
  rest_setter = "lc.at_#{nexpected}= #{build_arg_conses arg_names[setter_count..-1], 0}"
28
38
  end
29
- " def set_args_#{ngiven} lc, #{arg_names.join ", "}
30
- #{setters.join "\n "}
39
+ " def set_args_#{ngiven} #{build_arg_names ngiven}
40
+ #{mklc 1}#{setters.join "\n "}
31
41
  #{rest_setter}
42
+ lc
43
+ rescue StandardError => e
44
+ raise \"error in \#{self.class.name}#set_args_#{ngiven}\"
32
45
  end
33
46
  "
34
47
  end
@@ -36,7 +49,10 @@ module Nydp::LexicalContextBuilder
36
49
  def self.build_set_args_method nexpected
37
50
  setters = (0...nexpected).map { |i| "lc.at_#{i}= args#{ ([".cdr"] * i).join }.car"}
38
51
  " def set_args lc, args
39
- #{setters.join "\n "}
52
+ #{mklc nexpected}#{setters.join "\n "}
53
+ lc
54
+ rescue StandardError => e
55
+ raise \"error in \#{self.class.name}#set_args\"
40
56
  end
41
57
  "
42
58
  end
@@ -45,8 +61,11 @@ module Nydp::LexicalContextBuilder
45
61
  setters = (0...nexpected).map { |i| "lc.at_#{i}= args#{ ([".cdr"] * i).join }.car"}
46
62
  rest_set = "lc.at_#{nexpected}= args#{ ([".cdr"] *(nexpected)).join }"
47
63
  " def set_args lc, args
48
- #{setters.join "\n "}
64
+ #{mklc 1}#{setters.join "\n "}
49
65
  #{rest_set}
66
+ lc
67
+ rescue StandardError => e
68
+ raise \"error in \#{self.class.name}#set_args\"
50
69
  end
51
70
  "
52
71
  end
@@ -56,12 +75,10 @@ module Nydp::LexicalContextBuilder
56
75
  existing = const_get(name) rescue nil
57
76
  return name if existing
58
77
 
59
- n_methods = (1..3).map { |given| build_set_args_n_method given, expected_arg_count }
78
+ n_methods = (0..3).map { |given| build_set_args_n_method given, expected_arg_count }
60
79
  x_method = build_set_args_method expected_arg_count
61
80
  klass = <<KLASS
62
81
  module #{name}
63
- def initialize_names names ; end
64
-
65
82
  #{n_methods.join "\n"}
66
83
  #{x_method}
67
84
  end
@@ -76,12 +93,10 @@ KLASS
76
93
  existing = const_get(name) rescue nil
77
94
  return name if existing
78
95
 
79
- n_methods = (1..3).map { |given| build_set_args_n_rest_method given, proper_arg_count }
96
+ n_methods = (0..3).map { |given| build_set_args_n_rest_method given, proper_arg_count }
80
97
  x_method = build_set_args_rest_method proper_arg_count
81
98
  klass = <<KLASS
82
99
  module #{name}
83
- def initialize_names names ; end
84
-
85
100
  #{n_methods.join "\n"}
86
101
  #{x_method}
87
102
  end