nydp 0.5.1 → 0.6.0

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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/README.md +77 -56
  4. data/lib/lisp/core-000.nydp +1 -1
  5. data/lib/lisp/core-010-precompile.nydp +49 -29
  6. data/lib/lisp/core-012-utils.nydp +12 -8
  7. data/lib/lisp/core-015-documentation.nydp +41 -15
  8. data/lib/lisp/core-017-builtin-dox.nydp +621 -100
  9. data/lib/lisp/core-020-utils.nydp +33 -6
  10. data/lib/lisp/core-025-warnings.nydp +1 -1
  11. data/lib/lisp/core-030-syntax.nydp +64 -48
  12. data/lib/lisp/core-035-flow-control.nydp +20 -28
  13. data/lib/lisp/core-037-list-utils.nydp +84 -21
  14. data/lib/lisp/core-040-utils.nydp +8 -5
  15. data/lib/lisp/core-041-string-utils.nydp +17 -11
  16. data/lib/lisp/core-043-list-utils.nydp +140 -77
  17. data/lib/lisp/core-045-dox-utils.nydp +1 -0
  18. data/lib/lisp/core-050-test-runner.nydp +8 -12
  19. data/lib/lisp/core-070-prefix-list.nydp +19 -15
  20. data/lib/lisp/core-080-pretty-print.nydp +13 -5
  21. data/lib/lisp/core-090-hook.nydp +11 -11
  22. data/lib/lisp/core-100-utils.nydp +51 -66
  23. data/lib/lisp/core-110-hash-utils.nydp +34 -7
  24. data/lib/lisp/core-120-settings.nydp +14 -9
  25. data/lib/lisp/core-130-validations.nydp +28 -13
  26. data/lib/lisp/core-900-benchmarking.nydp +420 -47
  27. data/lib/lisp/tests/000-empty-args-examples.nydp +5 -0
  28. data/lib/lisp/tests/andify-examples.nydp +1 -1
  29. data/lib/lisp/tests/auto-hash-examples.nydp +6 -1
  30. data/lib/lisp/tests/best-examples.nydp +1 -1
  31. data/lib/lisp/tests/boot-tests.nydp +1 -1
  32. data/lib/lisp/tests/date-examples.nydp +129 -102
  33. data/lib/lisp/tests/destructuring-examples.nydp +1 -1
  34. data/lib/lisp/tests/dox-tests.nydp +2 -2
  35. data/lib/lisp/tests/hash-examples.nydp +58 -33
  36. data/lib/lisp/tests/list-tests.nydp +137 -1
  37. data/lib/lisp/tests/pretty-print-tests.nydp +12 -0
  38. data/lib/lisp/tests/rotate-2d-array-examples.nydp +26 -0
  39. data/lib/lisp/tests/sort-examples.nydp +5 -5
  40. data/lib/lisp/tests/string-tests.nydp +16 -5
  41. data/lib/lisp/tests/syntax-tests.nydp +10 -2
  42. data/lib/lisp/tests/time-examples.nydp +8 -1
  43. data/lib/lisp/tests/unparse-tests.nydp +13 -7
  44. data/lib/nydp/assignment.rb +15 -28
  45. data/lib/nydp/builtin/abs.rb +4 -3
  46. data/lib/nydp/builtin/apply.rb +8 -10
  47. data/lib/nydp/builtin/cdr_set.rb +1 -1
  48. data/lib/nydp/builtin/comment.rb +1 -3
  49. data/lib/nydp/builtin/date.rb +11 -28
  50. data/lib/nydp/builtin/divide.rb +3 -10
  51. data/lib/nydp/builtin/ensuring.rb +6 -21
  52. data/lib/nydp/builtin/error.rb +2 -4
  53. data/lib/nydp/builtin/eval.rb +9 -4
  54. data/lib/nydp/builtin/greater_than.rb +7 -8
  55. data/lib/nydp/builtin/handle_error.rb +10 -34
  56. data/lib/nydp/builtin/hash.rb +24 -45
  57. data/lib/nydp/builtin/inspect.rb +1 -3
  58. data/lib/nydp/builtin/is_equal.rb +4 -7
  59. data/lib/nydp/builtin/less_than.rb +6 -7
  60. data/lib/nydp/builtin/log.rb +7 -0
  61. data/lib/nydp/builtin/math_ceiling.rb +1 -3
  62. data/lib/nydp/builtin/math_floor.rb +1 -3
  63. data/lib/nydp/builtin/math_power.rb +1 -3
  64. data/lib/nydp/builtin/math_round.rb +2 -2
  65. data/lib/nydp/builtin/minus.rb +7 -14
  66. data/lib/nydp/builtin/parse.rb +5 -5
  67. data/lib/nydp/builtin/parse_in_string.rb +5 -7
  68. data/lib/nydp/builtin/plus.rb +14 -31
  69. data/lib/nydp/builtin/pre_compile.rb +1 -3
  70. data/lib/nydp/builtin/puts.rb +4 -8
  71. data/lib/nydp/builtin/quit.rb +1 -1
  72. data/lib/nydp/builtin/rand.rb +6 -11
  73. data/lib/nydp/builtin/random_string.rb +2 -4
  74. data/lib/nydp/builtin/rng.rb +25 -0
  75. data/lib/nydp/builtin/ruby_wrap.rb +27 -14
  76. data/lib/nydp/builtin/script_run.rb +1 -3
  77. data/lib/nydp/builtin/set_intersection.rb +3 -4
  78. data/lib/nydp/builtin/set_union.rb +3 -4
  79. data/lib/nydp/builtin/sort.rb +2 -7
  80. data/lib/nydp/builtin/string_match.rb +5 -13
  81. data/lib/nydp/builtin/string_replace.rb +2 -7
  82. data/lib/nydp/builtin/string_split.rb +3 -8
  83. data/lib/nydp/builtin/sym.rb +2 -9
  84. data/lib/nydp/builtin/thread_locals.rb +2 -2
  85. data/lib/nydp/builtin/time.rb +38 -44
  86. data/lib/nydp/builtin/times.rb +6 -15
  87. data/lib/nydp/builtin/to_integer.rb +8 -14
  88. data/lib/nydp/builtin/to_string.rb +2 -13
  89. data/lib/nydp/builtin/type_of.rb +10 -16
  90. data/lib/nydp/builtin/vm_info.rb +2 -10
  91. data/lib/nydp/builtin.rb +15 -37
  92. data/lib/nydp/compiler.rb +29 -19
  93. data/lib/nydp/cond.rb +95 -88
  94. data/lib/nydp/context_symbol.rb +11 -9
  95. data/lib/nydp/core.rb +74 -73
  96. data/lib/nydp/core_ext.rb +87 -26
  97. data/lib/nydp/date.rb +22 -19
  98. data/lib/nydp/error.rb +2 -3
  99. data/lib/nydp/function_invocation.rb +76 -289
  100. data/lib/nydp/helper.rb +18 -9
  101. data/lib/nydp/interpreted_function.rb +159 -25
  102. data/lib/nydp/lexical_context.rb +9 -8
  103. data/lib/nydp/lexical_context_builder.rb +1 -1
  104. data/lib/nydp/literal.rb +3 -7
  105. data/lib/nydp/loop.rb +72 -0
  106. data/lib/nydp/namespace.rb +52 -0
  107. data/lib/nydp/pair.rb +146 -50
  108. data/lib/nydp/parser.rb +9 -11
  109. data/lib/nydp/plugin.rb +88 -19
  110. data/lib/nydp/runner.rb +141 -23
  111. data/lib/nydp/symbol.rb +16 -26
  112. data/lib/nydp/symbol_lookup.rb +3 -2
  113. data/lib/nydp/tokeniser.rb +1 -1
  114. data/lib/nydp/truth.rb +2 -37
  115. data/lib/nydp/version.rb +1 -1
  116. data/lib/nydp.rb +33 -44
  117. data/nydp.gemspec +2 -1
  118. data/spec/date_spec.rb +26 -32
  119. data/spec/embedded_spec.rb +22 -22
  120. data/spec/error_spec.rb +12 -16
  121. data/spec/foreign_hash_spec.rb +21 -36
  122. data/spec/hash_non_hash_behaviour_spec.rb +12 -29
  123. data/spec/hash_spec.rb +36 -49
  124. data/spec/literal_spec.rb +6 -6
  125. data/spec/nydp_spec.rb +14 -14
  126. data/spec/pair_spec.rb +8 -8
  127. data/spec/parser_spec.rb +41 -37
  128. data/spec/rand_spec.rb +1 -4
  129. data/spec/spec_helper.rb +3 -3
  130. data/spec/string_atom_spec.rb +15 -16
  131. data/spec/symbol_spec.rb +27 -52
  132. data/spec/thread_local_spec.rb +23 -8
  133. data/spec/time_spec.rb +4 -10
  134. data/spec/tokeniser_spec.rb +10 -10
  135. metadata +25 -13
  136. data/lib/nydp/builtin/modulo.rb +0 -11
  137. data/lib/nydp/builtin/regexp.rb +0 -7
  138. data/lib/nydp/builtin/sqrt.rb +0 -7
  139. data/lib/nydp/builtin/string_pad_left.rb +0 -7
  140. data/lib/nydp/builtin/string_pad_right.rb +0 -7
  141. data/lib/nydp/hash.rb +0 -9
  142. data/lib/nydp/image_store.rb +0 -21
  143. data/lib/nydp/vm.rb +0 -129
data/lib/nydp/pair.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  class Nydp::Pair
2
- NIL = Nydp::NIL
2
+ NIL = nil
3
3
  include Nydp::Helper, Enumerable
4
4
  extend Nydp::Helper
5
5
 
@@ -14,19 +14,95 @@ class Nydp::Pair
14
14
  def cadr ; cdr.car ; end
15
15
  def cdar ; car.cdr ; end
16
16
  def cddr ; cdr.cdr ; end
17
- def car= thing ; @car = thing ; @_hash = nil ; end
18
- def cdr= thing ; @cdr = thing ; @_hash = nil ; end
19
- # def hash ; @_hash ||= (car.hash + cdr.hash) ; end
20
- def hash ; (car.hash + cdr.hash) ; end # can't cache hash of symbol, breaks when unmarshalling
17
+ def car= thing ; @car = thing ; end
18
+ def cdr= thing ; @cdr = thing ; end
21
19
  def eql? other ; self == other ; end
22
- def copy ; cons(car, cdr.copy) ; end
23
- def + other ; copy.append other ; end
20
+ def + other ; copy_append other ; end
24
21
  def size ; 1 + (cdr.is_a?(Nydp::Pair) ? cdr.size : 0) ; end
25
22
  def inspect ; "(#{inspect_rest})" ; end
26
- def & other ; self.class.from_list((Set.new(self) & other).to_a) ; end
27
- def | other ; self.class.from_list((Set.new(self) | other).to_a) ; end
28
- def - other ; self.class.from_list((Set.new(self) - other).to_a) ; end
29
- def proper? ; Nydp::NIL.is?(cdr) || (cdr.is_a?(Nydp::Pair) && cdr.proper?) ; end
23
+ def [] i ; nth i ; end
24
+ def & other ; self.class.from_list((Set.new(self) & Array(other)).to_a) ; end
25
+ def | other ; self.class.from_list((Set.new(self) | Array(other)).to_a) ; end
26
+ def - other ; self.class.from_list((Set.new(self) - Array(other)).to_a) ; end
27
+ def proper? ; (!cdr) || (cdr.is_a?(Nydp::Pair) && cdr.proper?) ; end
28
+
29
+ # def method_missing m, *args
30
+ # to_a.send m, *args
31
+ # end
32
+
33
+ # can't cache hash of symbol, breaks when unmarshalling
34
+ def hash
35
+ a = 0
36
+ x = self
37
+ while (x.is_a? Nydp::Pair)
38
+ a = a + x.car.hash
39
+ x = x.cdr
40
+ end
41
+
42
+ a + x.hash
43
+ end
44
+
45
+ def copy
46
+ a = last = cons
47
+ x = self
48
+ while (x.is_a? Nydp::Pair)
49
+ last = last.cdr = cons(x.car)
50
+ x = x.cdr
51
+ end
52
+
53
+ last.cdr = x
54
+ a.cdr
55
+ end
56
+
57
+ def copy_append lastcdr
58
+ a = last = cons
59
+ x = self
60
+ while (x.is_a? Nydp::Pair)
61
+ last = last.cdr = cons(x.car)
62
+ x = x.cdr
63
+ end
64
+
65
+ last.cdr = lastcdr
66
+ a.cdr
67
+ end
68
+
69
+ def map
70
+ a = last = cons
71
+ x = self
72
+ while (x.is_a? Nydp::Pair)
73
+ last = last.cdr = cons(yield x.car)
74
+ x = x.cdr
75
+ end
76
+
77
+ last.cdr = yield(x) if x
78
+ a.cdr
79
+ end
80
+
81
+ def join str
82
+ to_a.join(str)
83
+ end
84
+
85
+ def compile_to_ruby indent, srcs, opts=nil
86
+ a,x = [], self
87
+ while x.is_a?(Nydp::Pair)
88
+ a << x.car.compile_to_ruby("", srcs)
89
+ x = x.cdr
90
+ end
91
+
92
+ if !x || (x.is_a?(Nydp::Literal) && !x.expression)
93
+ "#{indent}list(" + a.join(", ") + ")"
94
+ else
95
+ "#{indent}Nydp::Pair.from_list([" + a.join(", ") + "], #{x.compile_to_ruby "", srcs})"
96
+ end
97
+ end
98
+
99
+ def nth n
100
+ xs = self
101
+ while n > 0
102
+ xs, n = xs.cdr, n-1
103
+ end
104
+ xs.car
105
+ end
30
106
 
31
107
  def index_of x
32
108
  if x == car
@@ -51,24 +127,34 @@ class Nydp::Pair
51
127
 
52
128
  # returns Array of elements as they are
53
129
  def to_a list=[]
54
- list << car
55
- cdr.is_a?(Nydp::Pair) ? cdr.to_a(list) : list
130
+ x = self
131
+ while x.is_a?(Nydp::Pair)
132
+ list << x.car
133
+ x = x.cdr
134
+ end
135
+ list
56
136
  end
57
137
 
138
+ # this breaks everything even though it seems like the logical thing to do...
139
+ # def to_ary
140
+ # to_a
141
+ # end
142
+
58
143
  def self.parse_list list
59
- if sym? list.slice(-2), "."
144
+ if list.slice(-2) == :"."
60
145
  from_list(list[0...-2], list.slice(-1))
61
146
  else
62
147
  from_list list
63
148
  end
64
149
  end
65
150
 
66
- def self.from_list list, last=Nydp::NIL, n=0
67
- if n >= list.size
68
- last
69
- else
70
- Nydp::Pair.new list[n], from_list(list, last, n+1)
151
+ def self.from_list list, last=nil, n=list.size-1
152
+ while (n >= 0)
153
+ last = cons(list[n], last)
154
+ n -= 1
71
155
  end
156
+
157
+ last
72
158
  end
73
159
 
74
160
  def == other
@@ -76,37 +162,48 @@ class Nydp::Pair
76
162
  end
77
163
 
78
164
  def each &block
79
- yield car
80
- cdr.each(&block) unless Nydp::NIL.is?(cdr)
165
+ xs = self
166
+ while xs
167
+ yield xs.car
168
+ xs = xs.cdr
169
+ end
81
170
  end
82
171
 
83
172
  def to_s
84
- if car.is_a?(Nydp::Symbol) && car.is?(:quote)
85
- if Nydp::NIL.is? cdr.cdr
173
+ if (car == :quote)
174
+ if !cdr.cdr
86
175
  "'#{cdr.car.to_s}"
87
176
  else
88
177
  "'#{cdr.to_s}"
89
178
  end
90
- elsif car.is_a?(Nydp::Symbol) && car.is?(:"brace-list")
91
- if Nydp::NIL.is? cdr
179
+ elsif (car == :"brace-list")
180
+ if !cdr
92
181
  "{}"
93
182
  else
94
183
  "{ #{cdr.to_s_rest} }"
95
184
  end
96
- elsif car.is_a?(Nydp::Symbol) && car.is?(:quasiquote)
97
- if Nydp::NIL.is? cdr.cdr
185
+ elsif (car == :"percent-syntax")
186
+ cdr.to_a.compact.join("%")
187
+ elsif (car == :"colon-syntax")
188
+ cdr.to_a.compact.join(":")
189
+ elsif (car == :"dot-syntax")
190
+ cdr.to_a.compact.join(".")
191
+ elsif (car == :"prefix-list")
192
+ "#{cdr.car.to_s}#{cdr.cdr.car.to_s}"
193
+ elsif (car == :quasiquote)
194
+ if !cdr.cdr
98
195
  "`#{cdr.car.to_s}"
99
196
  else
100
197
  "`#{cdr.to_s}"
101
198
  end
102
- elsif car.is_a?(Nydp::Symbol) && car.is?(:unquote)
103
- if Nydp::NIL.is? cdr.cdr
199
+ elsif (car == :unquote)
200
+ if !cdr.cdr
104
201
  ",#{cdr.car.to_s}"
105
202
  else
106
203
  ",#{cdr.to_s}"
107
204
  end
108
- elsif car.is_a?(Nydp::Symbol) && car.is?(:"unquote-splicing")
109
- if Nydp::NIL.is? cdr.cdr
205
+ elsif (car == :"unquote-splicing")
206
+ if !cdr.cdr
110
207
  ",@#{cdr.car.to_s}"
111
208
  else
112
209
  ",@#{cdr.to_s}"
@@ -116,42 +213,41 @@ class Nydp::Pair
116
213
  end
117
214
  end
118
215
 
216
+ def to_s_car
217
+ if (!car)
218
+ "nil"
219
+ elsif car.is_a?(String)
220
+ car.inspect
221
+ elsif car.is_a?(Symbol)
222
+ car._nydp_inspect
223
+ else
224
+ car.to_s
225
+ end
226
+ end
227
+
119
228
  def to_s_rest
120
229
  cdr_s = if cdr.is_a?(self.class)
121
230
  cdr.to_s_rest
122
- elsif Nydp::NIL.is? cdr
123
- nil
124
- else
231
+ elsif cdr
125
232
  ". #{cdr.to_s}"
126
233
  end
127
234
 
128
- [car.to_s, cdr_s].compact.join " "
235
+ [to_s_car, cdr_s].compact.join " "
129
236
  end
130
237
 
131
238
  def inspect_rest
132
- res = [car.inspect]
239
+ res = [car._nydp_inspect]
133
240
  it = cdr
134
- while it && it != Nydp::NIL
241
+ while it
135
242
  if it.is_a?(self.class)
136
- res << it.car.inspect
243
+ res << it.car._nydp_inspect
137
244
  it = it.cdr
138
245
  else
139
246
  res << "."
140
- res << it.inspect
247
+ res << it._nydp_inspect
141
248
  it = nil
142
249
  end
143
250
  end
144
251
  res.compact.join " "
145
252
  end
146
-
147
- def append thing
148
- if Nydp::NIL.is? self.cdr
149
- self.cdr = thing
150
- elsif pair? self.cdr
151
- self.cdr.append thing
152
- else
153
- raise "can't append #{thing} to list #{self} : cdr is #{self.cdr.inspect}"
154
- end
155
- self
156
- end
157
253
  end
data/lib/nydp/parser.rb CHANGED
@@ -1,16 +1,14 @@
1
1
  module Nydp
2
2
  class Parser
3
- attr_accessor :ns
4
-
5
- def initialize ns
6
- @ns = ns
7
- # TODO pre-initialize all the hard-coded syms used here, eg
8
- # @quote = sym(:quote)
9
- # @quasiquote = sym(:quasiquote)
10
- end
11
-
12
3
  def sym name
13
- Nydp::Symbol.mk name.to_sym, ns
4
+ n = name.to_s.to_sym
5
+ if n == :nil
6
+ nil
7
+ elsif n == :t
8
+ true
9
+ else
10
+ n
11
+ end
14
12
  end
15
13
 
16
14
  def read_list token_stream, termination_token, list=[]
@@ -102,7 +100,7 @@ module Nydp
102
100
  when :string_open_delim
103
101
  string token_stream, token.last, close_delimiter_for(token.last)
104
102
  when :sym_open_delim
105
- sym token_stream.next_string_fragment(token.last, /\|/, nil)
103
+ sym token_stream.next_string_fragment(token.last, /\|/, nil).string
106
104
  when :left_paren
107
105
  prefix_list token[1], read_list(token_stream, :right_paren)
108
106
  when :left_brace
data/lib/nydp/plugin.rb CHANGED
@@ -1,40 +1,109 @@
1
- require 'nydp/image_store'
1
+ require 'digest'
2
2
 
3
3
  module Nydp
4
4
  PLUGINS = []
5
- @@image_store = Nydp::ImageStore.new
5
+ COMMENT_RX = /^.*##> /
6
+ GENERATED_CLASS_PREFIX_REGEXP = /#{Nydp::GENERATED_CLASS_PREFIX}/
6
7
 
8
+ module PluginHelper
9
+ def base_path ; "" ; end # override this to provide common prefix for plugin filenames
10
+
11
+ def file_readers filenames, bp=base_path
12
+ filenames.map { |f| Nydp::FileReader.new(f.gsub(bp, ""), f) }
13
+ end
14
+
15
+ def relative_path name
16
+ # File.join File.expand_path(File.dirname(__FILE__)), name
17
+ File.join File.expand_path(File.dirname(caller[0].split(/:\d+:/)[0])), name
18
+ end
19
+ end
20
+
21
+ def self.nydp_from_backtrace str
22
+ file, original_line, meth = str.split(/:/)
23
+ line = original_line.to_i - 2 # -1 to convert from 1-based index to zero-based index ; -1 to start looking backwards from previous line
24
+ filepath = File.expand_path file
25
+
26
+ if filepath =~ Nydp::GENERATED_CLASS_PREFIX_REGEXP
27
+ code = File.read filepath
28
+ lines = code.split /\n/
29
+
30
+ while line > 0 && !(lines[line] =~ COMMENT_RX)
31
+ line = line - 1
32
+ end
33
+
34
+ if (line >= 0 && (lines[line] =~ COMMENT_RX))
35
+ comment = lines[line].sub(COMMENT_RX, '').gsub(/\\n/, "\n")
36
+ return [(filepath.sub(base_gen_path + '/', '') + ":" + original_line), comment].join("\n")
37
+ else
38
+ return str
39
+ end
40
+ end
41
+
42
+ str
43
+ end
44
+
45
+ def self.enhance_backtrace bt
46
+ bt.map { |s| nydp_from_backtrace s }
47
+ end
48
+
49
+ def self.base_gen_path ; File.expand_path("rubycode/") ; end
7
50
  def self.plug_in plugin ; PLUGINS << plugin ; end
8
51
  def self.load_rake_tasks ; PLUGINS.each &:load_rake_tasks ; end
9
52
  def self.setup ns ; PLUGINS.each { |plg| plg.setup ns } ; end
10
- def self.loadfiles ; PLUGINS.map(&:loadfiles).flatten ; end
11
- def self.testfiles ; PLUGINS.map(&:testfiles).flatten ; end
12
53
  def self.plugin_names ; PLUGINS.map(&:name) ; end
13
- def self.loadall ns, plugin, files
14
- vm = VM.new(ns)
15
- apply_function ns, :"script-run", :"plugin-start", plugin.name if plugin
54
+
55
+ def self.loadall ns, plugin, files, manifest
56
+ ns.apply :"script-run", :"plugin-start", plugin.name if plugin
16
57
  files.each { |f|
17
- script_name = f.gsub plugin.base_path, ""
18
- reader = Nydp::StreamReader.new(File.new(f))
19
- Nydp::Runner.new(vm, ns, reader, nil, (script_name || f)).run
20
- yield script_name if block_given?
58
+ Nydp::Runner.new(ns, f, nil, f.name, manifest).run
59
+ yield f.name if block_given?
21
60
  }
22
61
  ensure
23
- apply_function ns, :"script-run", :"plugin-end", plugin.name if plugin
62
+ ns.apply :"script-run", :"plugin-end", plugin.name if plugin
24
63
  end
25
64
 
26
65
  def self.all_files ; PLUGINS.each_with_object([]) { |plg, list| plg.loadfiles.each { |f| list << f } } ; end
27
- def self.set_image_store store ; @@image_store = store ; end
28
-
29
- def self.get_nydp ; @@image_store.get ; end
30
66
 
31
67
  def self.build_nydp &block
32
- ns = Namespace.new
68
+ rc = base_gen_path
69
+ $LOAD_PATH.unshift rc unless $LOAD_PATH.include?(rc)
70
+
71
+ digest = Digest::SHA256.hexdigest(all_files.map { |f| f.read }.join("\n"))
72
+ mname = "Manifest_#{digest}"
73
+
74
+ ns = ::Nydp::Namespace.new
33
75
  setup(ns)
34
- PLUGINS.each { |plg|
35
- loadall ns, plg, plg.loadfiles, &block
36
- loadall ns, plg, plg.testfiles, &block
76
+
77
+ digest = ""
78
+
79
+ PLUGINS.each { |plugin|
80
+ digest = install_plugin ns, plugin, digest, &block
37
81
  }
82
+
38
83
  ns
39
84
  end
85
+
86
+ def self.install_plugin ns, plugin, digest, &block
87
+ f0 = plugin.loadfiles.map { |f| f.read }.join("\n")
88
+ f1 = plugin.testfiles.map { |f| f.read }.join("\n")
89
+ digest = Digest::SHA256.hexdigest([digest, f0, f1].join("\n"))
90
+ mname = "Manifest_#{digest}"
91
+
92
+ if Nydp.logger
93
+ Nydp.logger.info "manifest name for plugin #{plugin.name.inspect} is #{mname.inspect}"
94
+ end
95
+
96
+ begin
97
+ require mname
98
+ const_get(mname).build ns
99
+
100
+ rescue LoadError => e
101
+ manifest = []
102
+ loadall ns, plugin, plugin.loadfiles, manifest, &block
103
+ loadall ns, plugin, plugin.testfiles, manifest, &block
104
+ Nydp::Evaluator.mk_manifest "Manifest_#{digest}", manifest
105
+ end
106
+
107
+ digest
108
+ end
40
109
  end
data/lib/nydp/runner.rb CHANGED
@@ -1,19 +1,51 @@
1
+ require 'digest'
1
2
  require 'readline'
2
3
  require 'nydp/readline_history'
3
4
 
4
5
  module Nydp
5
6
  class StringReader
6
- def initialize string ; @string = string ; end
7
+ attr_accessor :name
8
+
9
+ def initialize name, string
10
+ @name, @string, @read = name, string, string
11
+ end
12
+
7
13
  def nextline
8
- s = @string ; @string = nil ; s
14
+ s = @read ; @read = nil ; s
15
+ end
16
+
17
+ def read
18
+ @string
9
19
  end
10
20
  end
11
21
 
12
22
  class StreamReader
13
- def initialize stream ; @stream = stream ; end
23
+ attr_accessor :name
24
+
25
+ def initialize name, stream
26
+ @name, @stream = name, stream
27
+ end
28
+
14
29
  def nextline
15
30
  @stream.readline unless @stream.eof?
16
31
  end
32
+
33
+ def read
34
+ ""
35
+ end
36
+ end
37
+
38
+ class FileReader < StreamReader
39
+ attr_accessor :filename
40
+
41
+ def initialize name, filename
42
+ super name, File.new(filename)
43
+ @filename = filename
44
+ end
45
+
46
+ def read
47
+ File.read filename
48
+ end
17
49
  end
18
50
 
19
51
  class ReadlineReader
@@ -37,52 +69,138 @@ module Nydp
37
69
  end
38
70
 
39
71
  class Evaluator
40
- attr_accessor :vm, :ns, :name
72
+ attr_accessor :ns, :name
41
73
 
42
- def initialize vm, ns, name
43
- @name = name
44
- @vm = vm
45
- @ns = ns
46
- @precompile = Symbol.mk(:"pre-compile", ns)
47
- @quote = Symbol.mk(:quote, ns)
74
+ def initialize ns, name
75
+ @name = name
76
+ @ns = ns
77
+ @rubydir = FileUtils.mkdir_p "rubycode"
48
78
  end
49
79
 
50
- def compile_and_eval expr
80
+ def compile_expr expr
51
81
  begin
52
- vm.thread_with_expr Pair.new(Compiler.compile(expr, Nydp::NIL), Nydp::NIL)
82
+ Compiler.compile(expr, nil, ns)
53
83
  rescue StandardError => e
54
- raise Nydp::Error, "failed to eval #{expr.inspect}"
84
+ raise Nydp::Error, "failed to compile #{expr._nydp_inspect}"
55
85
  end
56
86
  end
57
87
 
58
- def pre_compile expr
59
- compile_and_eval(Pair.from_list [@precompile, Pair.from_list([@quote, expr])])
88
+ def self.mk_manifest name, class_list
89
+ class_expr = <<KLA
90
+ #{class_list.map {|k| "require '#{k}'" }.join("\n")}
91
+
92
+ class #{name}
93
+ def self.build ns
94
+ #{class_list.map {|k| "#{k}.new(ns).call" }.join("\n ")}
95
+ end
96
+ end
97
+ KLA
98
+ File.open("rubycode/#{name}.rb", "w") { |f|
99
+ fullpath = File.expand_path("rubycode/#{name}.rb")
100
+ Nydp.logger.info "writing #{fullpath}" if Nydp.logger
101
+ f.write class_expr
102
+ }
103
+ end
104
+
105
+ class CompiledExpression
106
+ attr_accessor :ns
107
+ def initialize ns
108
+ @ns = ns
109
+ end
110
+
111
+ def list *things
112
+ Nydp::Pair.from_list things
113
+ end
114
+ end
115
+
116
+ def mk_ruby_source src, precompiled, compiled_expr, cname
117
+ srcs = []
118
+ ruby_expr = compiled_expr.compile_to_ruby " ", srcs
119
+ six = 0
120
+ srcs = srcs.map { |s|
121
+ s = " @@src_#{six} = #{s.inspect}"
122
+ six += 1
123
+ s
124
+ }
125
+ class_expr = "class #{cname} < Nydp::Runner::CompiledExpression
126
+
127
+ #{srcs.join("\n")}
128
+
129
+ def src
130
+ #{src.inspect.inspect}
131
+ end
132
+
133
+ def precompiled
134
+ #{precompiled.inspect.inspect}
135
+ end
136
+
137
+ def call
138
+ #{ruby_expr}
139
+ end
140
+ end
141
+
142
+ #{cname}
143
+ "
144
+ File.open("rubycode/#{cname}.rb", "w") { |f| f.write class_expr }
145
+ class_expr
146
+ end
147
+
148
+ def mk_ruby_class src, precompiled, compiled_expr, cname
149
+ begin
150
+ require cname
151
+ self.class.const_get(cname)
152
+
153
+ rescue LoadError => e
154
+ # compiled_expr = compile_expr precompiled # TODO : delete line in #evaluate and uncomment this one
155
+ fname = "rubycode/#{cname}.rb"
156
+ txt = mk_ruby_source src, precompiled, compiled_expr, cname
157
+
158
+ eval(txt, nil, fname) || raise("failed to generate class #{cname} from src #{src}")
159
+ end
160
+ end
161
+
162
+ def eval_compiled compiled_expr, precompiled, src, manifest
163
+ return nil unless precompiled
164
+
165
+ digest = Digest::SHA256.hexdigest(precompiled.inspect)
166
+ cname = "#{GENERATED_CLASS_PREFIX}_#{digest.upcase}"
167
+ kla = mk_ruby_class src, precompiled, compiled_expr, cname
168
+
169
+ manifest << cname
170
+
171
+ kla.new(ns).call
172
+
173
+ rescue Exception => e
174
+ raise Nydp::Error, "failed to eval #{compiled_expr._nydp_inspect} from src #{src._nydp_inspect}"
60
175
  end
61
176
 
62
- def evaluate expr
63
- compile_and_eval(pre_compile(expr))
177
+ def evaluate expr, manifest=[]
178
+ precompiled = ns.apply :"pre-compile-new-expression", expr
179
+ compiled = compile_expr precompiled # TODO : we don't need this step if the class already exists! Do it later only when we need it
180
+ eval_compiled compiled, precompiled, expr, manifest
64
181
  end
65
182
  end
66
183
 
67
184
  class Runner < Evaluator
68
- def initialize vm, ns, stream, printer=nil, name=nil
69
- super vm, ns, name
185
+ def initialize ns, stream, printer=nil, name=nil, manifest=[]
186
+ super ns, name
70
187
  @printer = printer
71
- @parser = Nydp.new_parser(ns)
188
+ @parser = Nydp.new_parser
72
189
  @tokens = Nydp.new_tokeniser stream
190
+ @manifest = manifest
73
191
  end
74
192
 
75
193
  def print val
76
- @printer.puts val.inspect if @printer
194
+ @printer.puts val._nydp_inspect if @printer
77
195
  end
78
196
 
79
197
  def run
80
198
  Nydp.apply_function ns, :"script-run", :"script-start", name
81
- res = Nydp::NIL
199
+ res = nil
82
200
  begin
83
201
  while !@tokens.finished
84
202
  expr = @parser.expression(@tokens)
85
- print(res = evaluate(expr)) unless expr.nil?
203
+ print(res = evaluate(expr, @manifest)) unless expr.nil?
86
204
  end
87
205
  ensure
88
206
  Nydp.apply_function ns, :"script-run", :"script-end", name