nydp 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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 +30 -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 +88 -24
  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