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.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +77 -56
- data/lib/lisp/core-000.nydp +1 -1
- data/lib/lisp/core-010-precompile.nydp +49 -29
- data/lib/lisp/core-012-utils.nydp +12 -8
- data/lib/lisp/core-015-documentation.nydp +41 -15
- data/lib/lisp/core-017-builtin-dox.nydp +621 -100
- data/lib/lisp/core-020-utils.nydp +33 -6
- data/lib/lisp/core-025-warnings.nydp +1 -1
- data/lib/lisp/core-030-syntax.nydp +64 -48
- data/lib/lisp/core-035-flow-control.nydp +20 -28
- data/lib/lisp/core-037-list-utils.nydp +84 -21
- data/lib/lisp/core-040-utils.nydp +8 -5
- data/lib/lisp/core-041-string-utils.nydp +17 -11
- data/lib/lisp/core-043-list-utils.nydp +140 -77
- data/lib/lisp/core-045-dox-utils.nydp +1 -0
- data/lib/lisp/core-050-test-runner.nydp +8 -12
- data/lib/lisp/core-070-prefix-list.nydp +19 -15
- data/lib/lisp/core-080-pretty-print.nydp +13 -5
- data/lib/lisp/core-090-hook.nydp +11 -11
- data/lib/lisp/core-100-utils.nydp +51 -66
- data/lib/lisp/core-110-hash-utils.nydp +34 -7
- data/lib/lisp/core-120-settings.nydp +14 -9
- data/lib/lisp/core-130-validations.nydp +28 -13
- data/lib/lisp/core-900-benchmarking.nydp +420 -47
- data/lib/lisp/tests/000-empty-args-examples.nydp +5 -0
- data/lib/lisp/tests/andify-examples.nydp +1 -1
- data/lib/lisp/tests/auto-hash-examples.nydp +6 -1
- data/lib/lisp/tests/best-examples.nydp +1 -1
- data/lib/lisp/tests/boot-tests.nydp +1 -1
- data/lib/lisp/tests/date-examples.nydp +129 -102
- data/lib/lisp/tests/destructuring-examples.nydp +1 -1
- data/lib/lisp/tests/dox-tests.nydp +2 -2
- data/lib/lisp/tests/hash-examples.nydp +58 -33
- data/lib/lisp/tests/list-tests.nydp +137 -1
- data/lib/lisp/tests/pretty-print-tests.nydp +12 -0
- data/lib/lisp/tests/rotate-2d-array-examples.nydp +26 -0
- data/lib/lisp/tests/sort-examples.nydp +5 -5
- data/lib/lisp/tests/string-tests.nydp +16 -5
- data/lib/lisp/tests/syntax-tests.nydp +10 -2
- data/lib/lisp/tests/time-examples.nydp +8 -1
- data/lib/lisp/tests/unparse-tests.nydp +13 -7
- data/lib/nydp/assignment.rb +15 -28
- data/lib/nydp/builtin/abs.rb +4 -3
- data/lib/nydp/builtin/apply.rb +8 -10
- data/lib/nydp/builtin/cdr_set.rb +1 -1
- data/lib/nydp/builtin/comment.rb +1 -3
- data/lib/nydp/builtin/date.rb +11 -28
- data/lib/nydp/builtin/divide.rb +3 -10
- data/lib/nydp/builtin/ensuring.rb +6 -21
- data/lib/nydp/builtin/error.rb +2 -4
- data/lib/nydp/builtin/eval.rb +9 -4
- data/lib/nydp/builtin/greater_than.rb +7 -8
- data/lib/nydp/builtin/handle_error.rb +10 -34
- data/lib/nydp/builtin/hash.rb +24 -45
- data/lib/nydp/builtin/inspect.rb +1 -3
- data/lib/nydp/builtin/is_equal.rb +4 -7
- data/lib/nydp/builtin/less_than.rb +6 -7
- data/lib/nydp/builtin/log.rb +7 -0
- data/lib/nydp/builtin/math_ceiling.rb +1 -3
- data/lib/nydp/builtin/math_floor.rb +1 -3
- data/lib/nydp/builtin/math_power.rb +1 -3
- data/lib/nydp/builtin/math_round.rb +2 -2
- data/lib/nydp/builtin/minus.rb +7 -14
- data/lib/nydp/builtin/parse.rb +5 -5
- data/lib/nydp/builtin/parse_in_string.rb +5 -7
- data/lib/nydp/builtin/plus.rb +14 -31
- data/lib/nydp/builtin/pre_compile.rb +1 -3
- data/lib/nydp/builtin/puts.rb +4 -8
- data/lib/nydp/builtin/quit.rb +1 -1
- data/lib/nydp/builtin/rand.rb +6 -11
- data/lib/nydp/builtin/random_string.rb +2 -4
- data/lib/nydp/builtin/rng.rb +25 -0
- data/lib/nydp/builtin/ruby_wrap.rb +27 -14
- data/lib/nydp/builtin/script_run.rb +1 -3
- data/lib/nydp/builtin/set_intersection.rb +3 -4
- data/lib/nydp/builtin/set_union.rb +3 -4
- data/lib/nydp/builtin/sort.rb +2 -7
- data/lib/nydp/builtin/string_match.rb +5 -13
- data/lib/nydp/builtin/string_replace.rb +2 -7
- data/lib/nydp/builtin/string_split.rb +3 -8
- data/lib/nydp/builtin/sym.rb +2 -9
- data/lib/nydp/builtin/thread_locals.rb +2 -2
- data/lib/nydp/builtin/time.rb +38 -44
- data/lib/nydp/builtin/times.rb +6 -15
- data/lib/nydp/builtin/to_integer.rb +8 -14
- data/lib/nydp/builtin/to_string.rb +2 -13
- data/lib/nydp/builtin/type_of.rb +10 -16
- data/lib/nydp/builtin/vm_info.rb +2 -10
- data/lib/nydp/builtin.rb +15 -37
- data/lib/nydp/compiler.rb +29 -19
- data/lib/nydp/cond.rb +95 -88
- data/lib/nydp/context_symbol.rb +11 -9
- data/lib/nydp/core.rb +74 -73
- data/lib/nydp/core_ext.rb +87 -26
- data/lib/nydp/date.rb +22 -19
- data/lib/nydp/error.rb +2 -3
- data/lib/nydp/function_invocation.rb +76 -289
- data/lib/nydp/helper.rb +18 -9
- data/lib/nydp/interpreted_function.rb +159 -25
- data/lib/nydp/lexical_context.rb +9 -8
- data/lib/nydp/lexical_context_builder.rb +1 -1
- data/lib/nydp/literal.rb +3 -7
- data/lib/nydp/loop.rb +72 -0
- data/lib/nydp/namespace.rb +52 -0
- data/lib/nydp/pair.rb +146 -50
- data/lib/nydp/parser.rb +9 -11
- data/lib/nydp/plugin.rb +88 -19
- data/lib/nydp/runner.rb +141 -23
- data/lib/nydp/symbol.rb +16 -26
- data/lib/nydp/symbol_lookup.rb +3 -2
- data/lib/nydp/tokeniser.rb +1 -1
- data/lib/nydp/truth.rb +2 -37
- data/lib/nydp/version.rb +1 -1
- data/lib/nydp.rb +33 -44
- data/nydp.gemspec +2 -1
- data/spec/date_spec.rb +26 -32
- data/spec/embedded_spec.rb +22 -22
- data/spec/error_spec.rb +12 -16
- data/spec/foreign_hash_spec.rb +21 -36
- data/spec/hash_non_hash_behaviour_spec.rb +12 -29
- data/spec/hash_spec.rb +36 -49
- data/spec/literal_spec.rb +6 -6
- data/spec/nydp_spec.rb +14 -14
- data/spec/pair_spec.rb +8 -8
- data/spec/parser_spec.rb +41 -37
- data/spec/rand_spec.rb +1 -4
- data/spec/spec_helper.rb +3 -3
- data/spec/string_atom_spec.rb +15 -16
- data/spec/symbol_spec.rb +27 -52
- data/spec/thread_local_spec.rb +23 -8
- data/spec/time_spec.rb +4 -10
- data/spec/tokeniser_spec.rb +10 -10
- metadata +25 -13
- data/lib/nydp/builtin/modulo.rb +0 -11
- data/lib/nydp/builtin/regexp.rb +0 -7
- data/lib/nydp/builtin/sqrt.rb +0 -7
- data/lib/nydp/builtin/string_pad_left.rb +0 -7
- data/lib/nydp/builtin/string_pad_right.rb +0 -7
- data/lib/nydp/hash.rb +0 -9
- data/lib/nydp/image_store.rb +0 -21
- data/lib/nydp/vm.rb +0 -129
data/lib/nydp/pair.rb
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
class Nydp::Pair
|
|
2
|
-
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
|
|
18
|
-
def cdr= thing ; @cdr = thing
|
|
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
|
|
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
|
|
27
|
-
def
|
|
28
|
-
def
|
|
29
|
-
def
|
|
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
|
-
|
|
55
|
-
|
|
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
|
|
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=
|
|
67
|
-
|
|
68
|
-
last
|
|
69
|
-
|
|
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
|
-
|
|
80
|
-
|
|
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
|
|
85
|
-
if
|
|
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
|
|
91
|
-
if
|
|
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
|
|
97
|
-
|
|
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
|
|
103
|
-
if
|
|
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
|
|
109
|
-
if
|
|
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
|
|
123
|
-
nil
|
|
124
|
-
else
|
|
231
|
+
elsif cdr
|
|
125
232
|
". #{cdr.to_s}"
|
|
126
233
|
end
|
|
127
234
|
|
|
128
|
-
[
|
|
235
|
+
[to_s_car, cdr_s].compact.join " "
|
|
129
236
|
end
|
|
130
237
|
|
|
131
238
|
def inspect_rest
|
|
132
|
-
res = [car.
|
|
239
|
+
res = [car._nydp_inspect]
|
|
133
240
|
it = cdr
|
|
134
|
-
while it
|
|
241
|
+
while it
|
|
135
242
|
if it.is_a?(self.class)
|
|
136
|
-
res << it.car.
|
|
243
|
+
res << it.car._nydp_inspect
|
|
137
244
|
it = it.cdr
|
|
138
245
|
else
|
|
139
246
|
res << "."
|
|
140
|
-
res << it.
|
|
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
|
-
|
|
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 '
|
|
1
|
+
require 'digest'
|
|
2
2
|
|
|
3
3
|
module Nydp
|
|
4
4
|
PLUGINS = []
|
|
5
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
18
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
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 = @
|
|
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
|
-
|
|
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 :
|
|
72
|
+
attr_accessor :ns, :name
|
|
41
73
|
|
|
42
|
-
def initialize
|
|
43
|
-
@name
|
|
44
|
-
@
|
|
45
|
-
@
|
|
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
|
|
80
|
+
def compile_expr expr
|
|
51
81
|
begin
|
|
52
|
-
|
|
82
|
+
Compiler.compile(expr, nil, ns)
|
|
53
83
|
rescue StandardError => e
|
|
54
|
-
raise Nydp::Error, "failed to
|
|
84
|
+
raise Nydp::Error, "failed to compile #{expr._nydp_inspect}"
|
|
55
85
|
end
|
|
56
86
|
end
|
|
57
87
|
|
|
58
|
-
def
|
|
59
|
-
|
|
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
|
-
|
|
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
|
|
69
|
-
super
|
|
185
|
+
def initialize ns, stream, printer=nil, name=nil, manifest=[]
|
|
186
|
+
super ns, name
|
|
70
187
|
@printer = printer
|
|
71
|
-
@parser = Nydp.new_parser
|
|
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.
|
|
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 =
|
|
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
|