nydp 0.4.0 → 0.4.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +44 -0
- data/lib/lisp/core-010-precompile.nydp +13 -16
- data/lib/lisp/core-012-utils.nydp +21 -6
- data/lib/lisp/core-015-documentation.nydp +60 -19
- data/lib/lisp/core-017-builtin-dox.nydp +50 -39
- data/lib/lisp/core-020-utils.nydp +5 -5
- data/lib/lisp/core-030-syntax.nydp +103 -61
- data/lib/lisp/core-035-flow-control.nydp +18 -9
- data/lib/lisp/core-037-list-utils.nydp +36 -14
- data/lib/lisp/core-039-module.nydp +24 -0
- data/lib/lisp/core-040-utils.nydp +41 -23
- data/lib/lisp/core-041-string-utils.nydp +37 -9
- data/lib/lisp/core-042-date-utils.nydp +21 -1
- data/lib/lisp/core-043-list-utils.nydp +93 -67
- data/lib/lisp/core-045-dox-utils.nydp +5 -0
- data/lib/lisp/core-080-pretty-print.nydp +55 -17
- data/lib/lisp/core-090-hook.nydp +35 -1
- data/lib/lisp/core-100-utils.nydp +130 -28
- data/lib/lisp/core-110-hash-utils.nydp +61 -0
- data/lib/lisp/core-120-settings.nydp +46 -0
- data/lib/lisp/core-130-validations.nydp +51 -0
- data/lib/lisp/{core-060-benchmarking.nydp → core-900-benchmarking.nydp} +108 -5
- data/lib/lisp/tests/accum-examples.nydp +28 -1
- data/lib/lisp/tests/aif-examples.nydp +8 -3
- data/lib/lisp/tests/andify-examples.nydp +7 -0
- data/lib/lisp/tests/at-syntax-examples.nydp +17 -0
- data/lib/lisp/tests/best-examples.nydp +9 -0
- data/lib/lisp/tests/builtin-tests.nydp +19 -0
- data/lib/lisp/tests/case-examples.nydp +14 -0
- data/lib/lisp/tests/cdr-set-examples.nydp +6 -0
- data/lib/lisp/tests/date-examples.nydp +56 -1
- data/lib/lisp/tests/destructuring-examples.nydp +5 -5
- data/lib/lisp/tests/detect-examples.nydp +12 -0
- data/lib/lisp/tests/dp-examples.nydp +24 -0
- data/lib/lisp/tests/empty-examples.nydp +1 -1
- data/lib/lisp/tests/error-tests.nydp +4 -4
- data/lib/lisp/tests/filter-forms-examples.nydp +30 -0
- data/lib/lisp/tests/foundation-test.nydp +12 -0
- data/lib/lisp/tests/hash-examples.nydp +26 -2
- data/lib/lisp/tests/list-grep-examples.nydp +40 -0
- data/lib/lisp/tests/list-tests.nydp +58 -1
- data/lib/lisp/tests/map-hash-examples.nydp +11 -0
- data/lib/lisp/tests/mapreduce-examples.nydp +10 -0
- data/lib/lisp/tests/module-examples.nydp +10 -0
- data/lib/lisp/tests/multi-assign-examples.nydp +6 -0
- data/lib/lisp/tests/parser-tests.nydp +21 -0
- data/lib/lisp/tests/pretty-print-tests.nydp +16 -13
- data/lib/lisp/tests/set-difference-examples.nydp +8 -0
- data/lib/lisp/tests/set-intersection-examples.nydp +32 -0
- data/lib/lisp/tests/set-union-examples.nydp +24 -0
- data/lib/lisp/tests/settings-examples.nydp +40 -0
- data/lib/lisp/tests/sort-examples.nydp +8 -0
- data/lib/lisp/tests/string-tests.nydp +61 -1
- data/lib/lisp/tests/syntax-tests.nydp +5 -1
- data/lib/lisp/tests/to-integer-examples.nydp +16 -0
- data/lib/lisp/tests/validation-examples.nydp +15 -0
- data/lib/lisp/tests/zap-examples.nydp +12 -0
- data/lib/nydp.rb +13 -7
- data/lib/nydp/assignment.rb +10 -3
- data/lib/nydp/builtin.rb +1 -1
- data/lib/nydp/builtin/abs.rb +8 -0
- data/lib/nydp/builtin/cdr_set.rb +1 -6
- data/lib/nydp/builtin/date.rb +15 -1
- data/lib/nydp/builtin/error.rb +1 -1
- data/lib/nydp/builtin/handle_error.rb +1 -1
- data/lib/nydp/builtin/hash.rb +27 -45
- data/lib/nydp/builtin/inspect.rb +1 -1
- data/lib/nydp/builtin/plus.rb +10 -2
- data/lib/nydp/builtin/rand.rb +18 -0
- data/lib/nydp/builtin/random_string.rb +2 -2
- data/lib/nydp/builtin/ruby_wrap.rb +72 -0
- data/lib/nydp/builtin/set_intersection.rb +8 -0
- data/lib/nydp/builtin/set_union.rb +8 -0
- data/lib/nydp/builtin/string_match.rb +2 -2
- data/lib/nydp/builtin/string_pad_left.rb +7 -0
- data/lib/nydp/builtin/string_pad_right.rb +7 -0
- data/lib/nydp/builtin/string_replace.rb +1 -1
- data/lib/nydp/builtin/string_split.rb +1 -2
- data/lib/nydp/builtin/to_integer.rb +23 -0
- data/lib/nydp/builtin/to_string.rb +2 -9
- data/lib/nydp/builtin/type_of.rb +9 -6
- data/lib/nydp/closure.rb +0 -3
- data/lib/nydp/cond.rb +23 -1
- data/lib/nydp/context_symbol.rb +14 -6
- data/lib/nydp/core.rb +45 -33
- data/lib/nydp/core_ext.rb +54 -0
- data/lib/nydp/date.rb +37 -31
- data/lib/nydp/function_invocation.rb +34 -26
- data/lib/nydp/hash.rb +5 -6
- data/lib/nydp/helper.rb +41 -25
- data/lib/nydp/interpreted_function.rb +68 -40
- data/lib/nydp/literal.rb +1 -1
- data/lib/nydp/pair.rb +25 -9
- data/lib/nydp/parser.rb +8 -6
- data/lib/nydp/string_atom.rb +16 -22
- data/lib/nydp/symbol.rb +40 -27
- data/lib/nydp/symbol_lookup.rb +7 -7
- data/lib/nydp/tokeniser.rb +2 -2
- data/lib/nydp/truth.rb +17 -10
- data/lib/nydp/version.rb +1 -1
- data/lib/nydp/vm.rb +7 -2
- data/nydp.gemspec +2 -4
- data/spec/date_spec.rb +115 -22
- data/spec/embedded_spec.rb +12 -12
- data/spec/foreign_hash_spec.rb +14 -2
- data/spec/hash_non_hash_behaviour_spec.rb +7 -7
- data/spec/hash_spec.rb +24 -2
- data/spec/nydp_spec.rb +14 -2
- data/spec/parser_spec.rb +27 -16
- data/spec/rand_spec.rb +45 -0
- data/spec/spec_helper.rb +13 -1
- data/spec/symbol_spec.rb +31 -0
- data/spec/time_spec.rb +1 -1
- metadata +38 -37
- data/lib/nydp/builtin/car.rb +0 -7
- data/lib/nydp/builtin/cdr.rb +0 -7
- data/lib/nydp/builtin/cons.rb +0 -9
@@ -0,0 +1,54 @@
|
|
1
|
+
class Object
|
2
|
+
def _nydp_get a ; raise "_nydp_get : not gettable: #{a.inspect} on #{self.class.name}" ; end
|
3
|
+
def _nydp_set a, v ; raise "_nydp_get : not settable: #{a.inspect} on #{self.class.name}" ; end
|
4
|
+
def _nydp_keys ; [] ; end
|
5
|
+
def _nydp_wrapper ; self ; end
|
6
|
+
def lexical_reach n ; n ; end
|
7
|
+
end
|
8
|
+
|
9
|
+
class Method
|
10
|
+
include Nydp::Converter
|
11
|
+
def invoke_1 vm ; vm.push_arg call._nydp_wrapper ; end
|
12
|
+
def invoke_2 vm, a0 ; vm.push_arg call(n2r(a0))._nydp_wrapper ; end
|
13
|
+
def invoke_3 vm, a0, a1 ; vm.push_arg call(n2r(a0), n2r(a1))._nydp_wrapper ; end
|
14
|
+
def invoke_4 vm, a0, a1, a2 ; vm.push_arg call(n2r(a0), n2r(a1), n2r(a2))._nydp_wrapper ; end
|
15
|
+
def invoke vm, args ; vm.push_arg call(*(args.map { |a| n2r a}))._nydp_wrapper ; end
|
16
|
+
end
|
17
|
+
|
18
|
+
class NilClass
|
19
|
+
def _nydp_wrapper ; Nydp::NIL ; end
|
20
|
+
end
|
21
|
+
|
22
|
+
class FalseClass
|
23
|
+
def _nydp_wrapper ; Nydp::NIL ; end
|
24
|
+
end
|
25
|
+
|
26
|
+
class TrueClass
|
27
|
+
def _nydp_wrapper ; Nydp::T ; end
|
28
|
+
end
|
29
|
+
|
30
|
+
class ::Symbol
|
31
|
+
def _nydp_wrapper ; Nydp::FrozenSymbol.mk(self) ; end
|
32
|
+
end
|
33
|
+
|
34
|
+
class ::Date
|
35
|
+
def _nydp_wrapper ; Nydp::Date.new self ; end
|
36
|
+
end
|
37
|
+
|
38
|
+
class ::Array
|
39
|
+
def _nydp_wrapper ; Nydp::Pair.from_list map &:_nydp_wrapper ; end
|
40
|
+
end
|
41
|
+
|
42
|
+
class ::String
|
43
|
+
# def _nydp_wrapper ; Nydp::StringAtom.new self ; end
|
44
|
+
def as_method_name ; self.gsub(/-/, '_').to_sym ; end
|
45
|
+
def nydp_type ; :string ; end
|
46
|
+
def to_ruby ; self ; end
|
47
|
+
end
|
48
|
+
|
49
|
+
class ::Hash
|
50
|
+
include Nydp::Helper
|
51
|
+
def _nydp_get a ; self[n2r a] ; end
|
52
|
+
def _nydp_set a, v ; self[n2r a] = n2r(v) ; end
|
53
|
+
def _nydp_keys ; keys ; end
|
54
|
+
end
|
data/lib/nydp/date.rb
CHANGED
@@ -16,23 +16,22 @@ module Nydp
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
def initialize ruby_date
|
20
|
-
@ruby_date = ruby_date
|
21
|
-
end
|
19
|
+
def initialize ruby_date ; @ruby_date = ruby_date ; end
|
22
20
|
|
23
|
-
def
|
24
|
-
def
|
25
|
-
def
|
26
|
-
def
|
27
|
-
def
|
28
|
-
def >
|
29
|
-
def <
|
30
|
-
def ==
|
31
|
-
def <=> other ; is_date?(other) && ruby_date <=> other.ruby_date
|
32
|
-
def eql?
|
33
|
-
def hash ; ruby_date.hash
|
34
|
-
def is_date? other ; other.is_a? Nydp::Date
|
35
|
-
def - other ; r2n(ruby_date - (is_date?(other) ? other.ruby_date : other)
|
21
|
+
def to_date ; ruby_date ; end
|
22
|
+
def to_s ; ruby_date.to_s ; end
|
23
|
+
def to_ruby ; ruby_date ; end
|
24
|
+
def inspect ; ruby_date.inspect ; end
|
25
|
+
def nydp_type ; :date ; end
|
26
|
+
def > other ; is_date?(other) && ruby_date > other.ruby_date ; end
|
27
|
+
def < other ; is_date?(other) && ruby_date < other.ruby_date ; end
|
28
|
+
def == other ; is_date?(other) && ruby_date == other.ruby_date ; end
|
29
|
+
def <=> other ; is_date?(other) && ruby_date <=> other.ruby_date ; end
|
30
|
+
def eql? d ; self == d ; end
|
31
|
+
def hash ; ruby_date.hash ; end
|
32
|
+
def is_date? other ; other.is_a? Nydp::Date ; end
|
33
|
+
def - other ; r2n(ruby_date - (is_date?(other) ? other.ruby_date : other)) ; end
|
34
|
+
def + int ; int.is_a?(Fixnum) ? r2n(ruby_date + int) : r2n(change(*int.to_ruby)) ; end
|
36
35
|
|
37
36
|
@@pass_through = %i{ monday? tuesday? wednesday? thursday? friday? saturday? sunday? }
|
38
37
|
@@keys = Set.new %i{
|
@@ -40,7 +39,7 @@ module Nydp
|
|
40
39
|
last_year next_year beginning_of_year end_of_year
|
41
40
|
last_month next_month beginning_of_month end_of_month
|
42
41
|
last_week next_week beginning_of_week end_of_week
|
43
|
-
yesterday tomorrow
|
42
|
+
yesterday tomorrow age
|
44
43
|
} + @@pass_through
|
45
44
|
|
46
45
|
def year y, m, d, w ; y ; end
|
@@ -48,15 +47,15 @@ module Nydp
|
|
48
47
|
def day y, m, d, w ; d ; end
|
49
48
|
def week_day y, m, d, w ; w ; end
|
50
49
|
|
51
|
-
def last_year y, m, d, w ;
|
50
|
+
def last_year y, m, d, w ; ruby_date.prev_year ; end
|
52
51
|
def next_year y, m, d, w ; ruby_date.next_year ; end
|
53
52
|
def beginning_of_year y, m, d, w ; build(y, 1, 1) ; end
|
54
53
|
def end_of_year y, m, d, w ; build(y, 12, 31) ; end
|
55
54
|
|
56
|
-
def last_month y, m, d, w ;
|
55
|
+
def last_month y, m, d, w ; ruby_date.prev_month ; end
|
57
56
|
def next_month y, m, d, w ; ruby_date.next_month ; end
|
58
57
|
def beginning_of_month y, m, d, w ; build(y, m, 1) ; end
|
59
|
-
def end_of_month y, m, d, w ;
|
58
|
+
def end_of_month y, m, d, w ; beginning_of_month(*splat(ruby_date.next_month)) - 1 ; end
|
60
59
|
|
61
60
|
def last_week y, m, d, w ; ruby_date - 7 ; end
|
62
61
|
def next_week y, m, d, w ; ruby_date + 7 ; end
|
@@ -66,21 +65,28 @@ module Nydp
|
|
66
65
|
def yesterday y, m, d, w ; ruby_date - 1 ; end
|
67
66
|
def tomorrow y, m, d, w ; ruby_date + 1 ; end
|
68
67
|
|
68
|
+
def age y,m,d,w # args not used
|
69
|
+
interval = (::Date.today - ruby_date) / 365.0
|
70
|
+
age_in_years = interval.to_i
|
71
|
+
extra_months = (12 * (interval - age_in_years)).to_i
|
72
|
+
{ years: age_in_years, months: extra_months }
|
73
|
+
end
|
74
|
+
|
69
75
|
@@pass_through.each do |n|
|
70
76
|
class_eval "def #{n} * ; ruby_date.#{n} ; end"
|
71
77
|
end
|
72
78
|
|
73
|
-
def
|
74
|
-
def dispatch
|
75
|
-
|
76
|
-
def
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
79
|
+
def _nydp_keys ; @@keys.to_a ; end
|
80
|
+
def dispatch key, y, m, d, w ; self.send(key, y, m, d, w) if _nydp_keys.include?(key) ; end
|
81
|
+
def splat date ; [date.year, date.month, date.day, date.wday] ; end
|
82
|
+
def lookup key, date ; r2n(dispatch(key.to_s.gsub(/-/, '_').to_sym, *splat(date))) ; end
|
83
|
+
def _nydp_get key ; lookup key, ruby_date ; end
|
84
|
+
def change amount, attr
|
85
|
+
if attr == :day ; (ruby_date + amount)
|
86
|
+
elsif attr == :week ; (ruby_date + (7 * amount))
|
87
|
+
elsif attr == :month ; (ruby_date >> amount)
|
88
|
+
elsif attr == :year ; (ruby_date >> (12 * amount))
|
89
|
+
end
|
84
90
|
end
|
85
91
|
end
|
86
92
|
end
|
@@ -13,9 +13,8 @@ module Nydp
|
|
13
13
|
|
14
14
|
class Base
|
15
15
|
include Helper
|
16
|
-
def initialize
|
17
|
-
@
|
18
|
-
@sig = sig
|
16
|
+
def initialize expr, source, sig=nil
|
17
|
+
@expr, @source, @sig = expr, source, sig
|
19
18
|
end
|
20
19
|
|
21
20
|
def handle e, f, invoker, *args
|
@@ -24,7 +23,7 @@ module Nydp
|
|
24
23
|
raise
|
25
24
|
else
|
26
25
|
if e.is_a?(NoMethodError) && !f.respond_to?(invoker)
|
27
|
-
raise InvocationFailed.new("#{f.inspect} is not a function: args were #{args.inspect}")
|
26
|
+
raise InvocationFailed.new("#{f.inspect} is not a function: args were #{args.inspect} in #{source.inspect}")
|
28
27
|
else
|
29
28
|
msg = args.map { |a| " #{a.inspect}"}.join("\n")
|
30
29
|
msg = "failed to execute invocation #{f.inspect}\n#{msg}"
|
@@ -35,9 +34,14 @@ module Nydp
|
|
35
34
|
end
|
36
35
|
end
|
37
36
|
|
38
|
-
|
39
|
-
def
|
40
|
-
|
37
|
+
# TODO: speed up compilation by writing custom #lexical_reach for sig-based subclasses (when you know which elements of #expr are lexical symbols)
|
38
|
+
def lexical_reach n
|
39
|
+
@expr.map { |x| x.lexical_reach n}.max
|
40
|
+
end
|
41
|
+
|
42
|
+
def inspect ; @expr.map { |x| x.inspect }.join ' ' ; end
|
43
|
+
def source ; @source ; end
|
44
|
+
def to_s ; source.to_s ; end
|
41
45
|
end
|
42
46
|
|
43
47
|
class Invocation_1 < Invocation::Base
|
@@ -87,8 +91,8 @@ module Nydp
|
|
87
91
|
end
|
88
92
|
|
89
93
|
class Invocation_N < Invocation::Base
|
90
|
-
def initialize arg_count,
|
91
|
-
super
|
94
|
+
def initialize arg_count, expr, source
|
95
|
+
super expr, source
|
92
96
|
@arg_count = arg_count
|
93
97
|
end
|
94
98
|
|
@@ -107,7 +111,7 @@ module Nydp
|
|
107
111
|
class Invocation_LEX < Invocation::Base
|
108
112
|
SIGS << self.name
|
109
113
|
def initialize expr, src
|
110
|
-
super src
|
114
|
+
super expr, src
|
111
115
|
@sym = expr.car
|
112
116
|
end
|
113
117
|
|
@@ -122,7 +126,7 @@ module Nydp
|
|
122
126
|
class Invocation_SYM < Invocation::Base
|
123
127
|
SIGS << self.name
|
124
128
|
def initialize expr, src
|
125
|
-
super src
|
129
|
+
super expr, src
|
126
130
|
@sym = expr.car
|
127
131
|
end
|
128
132
|
|
@@ -137,7 +141,7 @@ module Nydp
|
|
137
141
|
class Invocation_LEX_LEX < Invocation::Base
|
138
142
|
SIGS << self.name
|
139
143
|
def initialize expr, src
|
140
|
-
super src
|
144
|
+
super expr, src
|
141
145
|
@lex0 = expr.car
|
142
146
|
@lex1 = expr.cdr.car
|
143
147
|
end
|
@@ -155,7 +159,7 @@ module Nydp
|
|
155
159
|
class Invocation_SYM_LEX < Invocation::Base
|
156
160
|
SIGS << self.name
|
157
161
|
def initialize expr, src
|
158
|
-
super src
|
162
|
+
super expr, src
|
159
163
|
@sym = expr.car
|
160
164
|
@lex = expr.cdr.car
|
161
165
|
end
|
@@ -172,7 +176,7 @@ module Nydp
|
|
172
176
|
class Invocation_SYM_LIT < Invocation::Base
|
173
177
|
SIGS << self.name
|
174
178
|
def initialize expr, src
|
175
|
-
super src
|
179
|
+
super expr, src
|
176
180
|
@sym = expr.car
|
177
181
|
@lit = expr.cdr.car.expression
|
178
182
|
end
|
@@ -188,7 +192,7 @@ module Nydp
|
|
188
192
|
class Invocation_LEX_LEX_LEX < Invocation::Base
|
189
193
|
SIGS << self.name
|
190
194
|
def initialize expr, src
|
191
|
-
super src
|
195
|
+
super expr, src
|
192
196
|
@lex_0 = expr.car
|
193
197
|
@lex_1 = expr.cdr.car
|
194
198
|
@lex_2 = expr.cdr.cdr.car
|
@@ -208,7 +212,7 @@ module Nydp
|
|
208
212
|
class Invocation_SYM_LEX_LEX < Invocation::Base
|
209
213
|
SIGS << self.name
|
210
214
|
def initialize expr, src
|
211
|
-
super src
|
215
|
+
super expr, src
|
212
216
|
@sym = expr.car
|
213
217
|
@lex_0 = expr.cdr.car
|
214
218
|
@lex_1 = expr.cdr.cdr.car
|
@@ -227,7 +231,7 @@ module Nydp
|
|
227
231
|
class Invocation_SYM_LEX_LEX_LEX < Invocation::Base
|
228
232
|
SIGS << self.name
|
229
233
|
def initialize expr, src
|
230
|
-
super src
|
234
|
+
super expr, src
|
231
235
|
@sym = expr.car
|
232
236
|
@lex_0 = expr.cdr.car
|
233
237
|
@lex_1 = expr.cdr.cdr.car
|
@@ -248,7 +252,7 @@ module Nydp
|
|
248
252
|
class Invocation_SYM_LEX_LIT_LEX < Invocation::Base
|
249
253
|
SIGS << self.name
|
250
254
|
def initialize expr, src
|
251
|
-
super src
|
255
|
+
super expr, src
|
252
256
|
@sym = expr.car
|
253
257
|
@lex_0 = expr.cdr.car
|
254
258
|
@lit_1 = expr.cdr.cdr.car.expression
|
@@ -268,7 +272,7 @@ module Nydp
|
|
268
272
|
class Invocation_SYM_LIT_LEX < Invocation::Base
|
269
273
|
SIGS << self.name
|
270
274
|
def initialize expr, src
|
271
|
-
super src
|
275
|
+
super expr, src
|
272
276
|
@sym = expr.car
|
273
277
|
@lit_0 = expr.cdr.car.expression
|
274
278
|
@lex_1 = expr.cdr.cdr.car
|
@@ -288,6 +292,10 @@ module Nydp
|
|
288
292
|
extend Helper
|
289
293
|
attr_accessor :function_instruction, :argument_instructions
|
290
294
|
|
295
|
+
def lexical_reach n
|
296
|
+
function_instruction.car.lexical_reach(n)
|
297
|
+
end
|
298
|
+
|
291
299
|
def self.build expression, bindings
|
292
300
|
compiled = Compiler.compile_each(expression, bindings)
|
293
301
|
invocation_sig = compiled.map { |x| sig x }.join("_")
|
@@ -303,15 +311,15 @@ module Nydp
|
|
303
311
|
|
304
312
|
invocation = cons case expression.size
|
305
313
|
when 1
|
306
|
-
Invocation::Invocation_1.new(expression)
|
314
|
+
Invocation::Invocation_1.new(compiled, expression)
|
307
315
|
when 2
|
308
|
-
Invocation::Invocation_2.new(expression)
|
316
|
+
Invocation::Invocation_2.new(compiled, expression)
|
309
317
|
when 3
|
310
|
-
Invocation::Invocation_3.new(expression)
|
318
|
+
Invocation::Invocation_3.new(compiled, expression)
|
311
319
|
when 4
|
312
|
-
Invocation::Invocation_4.new(expression)
|
320
|
+
Invocation::Invocation_4.new(compiled, expression)
|
313
321
|
else
|
314
|
-
Invocation::Invocation_N.new(expression.size, expression)
|
322
|
+
Invocation::Invocation_N.new(expression.size, compiled, expression)
|
315
323
|
end
|
316
324
|
new invocation, compiled, expression, cname
|
317
325
|
end
|
@@ -327,7 +335,7 @@ module Nydp
|
|
327
335
|
vm.push_ctx_instructions argument_instructions
|
328
336
|
end
|
329
337
|
|
330
|
-
def inspect ; @
|
331
|
-
def to_s ; @source.to_s
|
338
|
+
def inspect ; @function_instruction.inspect ; end
|
339
|
+
def to_s ; @source.to_s ; end
|
332
340
|
end
|
333
341
|
end
|
data/lib/nydp/hash.rb
CHANGED
@@ -1,10 +1,9 @@
|
|
1
1
|
class Nydp::Hash < ::Hash
|
2
2
|
include Nydp::Helper
|
3
3
|
|
4
|
-
def nydp_type
|
5
|
-
def to_ruby
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
4
|
+
def nydp_type ; :hash ; end
|
5
|
+
def to_ruby ; each_with_object({}) {|(k,v),h| h[n2r k] = n2r v} ; end
|
6
|
+
def _nydp_get a ; self[a] ; end
|
7
|
+
def _nydp_set a, v ; self[a] = v ; end
|
8
|
+
def _nydp_keys ; keys ; end
|
10
9
|
end
|
data/lib/nydp/helper.rb
CHANGED
@@ -1,34 +1,50 @@
|
|
1
1
|
module Nydp
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
2
|
+
module AutoWrap
|
3
|
+
# include this and be sure to either override #_nydp_ok? or #_nydp_whitelist
|
4
|
+
# #_nydp_whitelist should return a list of accessor (zero-arg) methods which are safe for nydp to invoke
|
5
|
+
# #_nydp_procify should return a list of methods that can be exposed to script code.
|
6
|
+
#
|
7
|
+
# class Blub
|
8
|
+
# _nydp_procs << :blubme
|
9
|
+
# def blubme where, when
|
10
|
+
# puts "blubme #{where}, #{when}"
|
11
|
+
# end
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# in nydp, if blub is an instance of Blub:
|
15
|
+
#
|
16
|
+
# (blub.blubme "here" "now")
|
17
|
+
#
|
18
|
+
# prints
|
19
|
+
#
|
20
|
+
# blubme here, now
|
21
|
+
#
|
22
|
+
def _nydp_wrapper ; self ; end
|
23
|
+
def _nydp_ok? method ; _nydp_whitelist.include? method ; end
|
24
|
+
def _nydp_procify? method ; _nydp_procs.include? method ; end # override to allow returning Method instances for given method name
|
25
|
+
def _nydp_get key ; _nydp_safe_send(key.to_s.as_method_name) ; end
|
26
|
+
def to_ruby ; self ; end
|
27
|
+
def _nydp_safe_send meth, *args
|
28
|
+
return send meth, *args if _nydp_ok?(meth)
|
29
|
+
return method(meth) if _nydp_procify?(meth)
|
30
|
+
end
|
14
31
|
end
|
15
32
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
if rklass <= hklass
|
22
|
-
return proc.call ruby_obj, ns
|
23
|
-
end
|
24
|
-
end
|
33
|
+
class Struct < ::Struct
|
34
|
+
include AutoWrap
|
35
|
+
def _nydp_whitelist ; members ; end
|
36
|
+
def _nydp_procs ; [] ; end
|
37
|
+
end
|
25
38
|
|
26
|
-
|
39
|
+
module Converter
|
40
|
+
def n2r o ; o.respond_to?(:to_ruby) ? o.to_ruby : o ; end
|
41
|
+
def r2n o, ns=nil ; o._nydp_wrapper ; end
|
27
42
|
end
|
28
43
|
|
44
|
+
extend Converter
|
45
|
+
|
29
46
|
module Helper
|
30
|
-
|
31
|
-
def r2n obj, ns ; Nydp.r2n obj, ns ; end
|
47
|
+
include Converter
|
32
48
|
|
33
49
|
def sig klass
|
34
50
|
case klass
|
@@ -67,7 +83,7 @@ module Nydp
|
|
67
83
|
|
68
84
|
def literal? expr
|
69
85
|
case expr
|
70
|
-
when String, Float, Integer, Fixnum, Nydp::Symbol, Nydp::
|
86
|
+
when String, Float, Integer, Fixnum, Nydp::Symbol, Nydp::Truth, Nydp::Nil
|
71
87
|
true
|
72
88
|
else
|
73
89
|
false
|
@@ -5,8 +5,8 @@ require 'nydp/closure'
|
|
5
5
|
module Nydp
|
6
6
|
class PopArg
|
7
7
|
def self.execute vm ; vm.args.pop ; end
|
8
|
-
def self.to_s ; ""
|
9
|
-
def self.inspect ; "#pop_arg"
|
8
|
+
def self.to_s ; "" ; end
|
9
|
+
def self.inspect ; "#pop_arg" ; end
|
10
10
|
end
|
11
11
|
|
12
12
|
class InterpretedFunction
|
@@ -16,42 +16,22 @@ module Nydp
|
|
16
16
|
|
17
17
|
attr_accessor :arg_names, :body, :context_builder
|
18
18
|
|
19
|
-
def
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
def invoke_2 vm, parent_context, arg
|
24
|
-
vm.push_instructions self.body, set_args_1(parent_context, arg)
|
25
|
-
end
|
26
|
-
|
27
|
-
def invoke_3 vm, parent_context, arg_0, arg_1
|
28
|
-
vm.push_instructions self.body, set_args_2(parent_context, arg_0, arg_1)
|
29
|
-
end
|
30
|
-
|
31
|
-
def invoke_4 vm, parent_context, arg_0, arg_1, arg_2
|
32
|
-
vm.push_instructions self.body, set_args_3(parent_context, arg_0, arg_1, arg_2)
|
33
|
-
end
|
34
|
-
|
35
|
-
def invoke vm, parent_context, arg_values
|
36
|
-
vm.push_instructions self.body, set_args(parent_context, arg_values)
|
37
|
-
end
|
38
|
-
|
39
|
-
def setup_context context, names, values
|
40
|
-
if pair? names
|
41
|
-
context.set names.car, values.car
|
42
|
-
setup_context context, names.cdr, values.cdr
|
43
|
-
elsif NIL != names
|
44
|
-
context.set names, values
|
45
|
-
end
|
19
|
+
def lexical_reach n
|
20
|
+
body.map { |b| b.lexical_reach(n - 1) }.max
|
46
21
|
end
|
47
22
|
|
48
23
|
def self.build arg_list, body, bindings
|
49
24
|
my_params = { }
|
50
25
|
index_parameters arg_list, my_params
|
51
|
-
|
26
|
+
body = compile_body body, cons(my_params, bindings), []
|
27
|
+
reach = body.map { |b| b.lexical_reach(-1) }.max
|
28
|
+
|
29
|
+
ifn_klass = reach >= 0 ? InterpretedFunctionWithClosure : InterpretedFunctionWithoutClosure
|
30
|
+
ifn = ifn_klass.new
|
52
31
|
ifn.arg_names = arg_list
|
32
|
+
ifn.body = body
|
33
|
+
|
53
34
|
ifn.extend Nydp::LexicalContextBuilder.select arg_list
|
54
|
-
ifn.body = compile_body body, cons(my_params, bindings), []
|
55
35
|
ifn
|
56
36
|
end
|
57
37
|
|
@@ -62,6 +42,11 @@ module Nydp
|
|
62
42
|
if Nydp::NIL.is? rest
|
63
43
|
return Pair.from_list(instructions)
|
64
44
|
else
|
45
|
+
# PopArg is necessary because each expression pushes an arg onto the arg stack.
|
46
|
+
# we only need to keep the arg pushed by the last expression in a function
|
47
|
+
# so we need the following line in order to remove unwanted args from the stack.
|
48
|
+
# Each expression at some executes vm.push_arg(thing)
|
49
|
+
# TODO find a more intelligent way to do this, eg change the meaning of vm or of push_arg in the expression vm.push_arg(thing)
|
65
50
|
instructions << PopArg
|
66
51
|
compile_body rest, bindings, instructions
|
67
52
|
end
|
@@ -76,19 +61,62 @@ module Nydp
|
|
76
61
|
end
|
77
62
|
end
|
78
63
|
|
79
|
-
def execute vm
|
80
|
-
# TODO do not create a new Closure if this function does not refer to it
|
81
|
-
# - including top-level function definitions
|
82
|
-
# - and any other function that does not refer to any lexically-bound outer variable
|
83
|
-
# - for example (fn (x) (* x x)) in (map λx(* x x) things) does not need a closure, because
|
84
|
-
# the function does not refer to any lexical variable outside itself.
|
85
|
-
vm.push_arg Closure.new(self, vm.current_context)
|
86
|
-
end
|
87
|
-
|
88
64
|
def nydp_type ; "fn" ; end
|
89
65
|
def inspect ; to_s ; end
|
90
66
|
def to_s
|
91
67
|
"(fn #{arg_names.inspect} #{body.map { |b| b.inspect}.join(' ')})"
|
92
68
|
end
|
93
69
|
end
|
70
|
+
|
71
|
+
class InterpretedFunctionWithClosure < InterpretedFunction
|
72
|
+
def invoke_1 vm, ctx
|
73
|
+
vm.push_instructions self.body, set_args_0(ctx)
|
74
|
+
end
|
75
|
+
|
76
|
+
def invoke_2 vm, ctx, arg
|
77
|
+
vm.push_instructions self.body, set_args_1(ctx, arg)
|
78
|
+
end
|
79
|
+
|
80
|
+
def invoke_3 vm, ctx, arg_0, arg_1
|
81
|
+
vm.push_instructions self.body, set_args_2(ctx, arg_0, arg_1)
|
82
|
+
end
|
83
|
+
|
84
|
+
def invoke_4 vm, ctx, arg_0, arg_1, arg_2
|
85
|
+
vm.push_instructions self.body, set_args_3(ctx, arg_0, arg_1, arg_2)
|
86
|
+
end
|
87
|
+
|
88
|
+
def invoke vm, ctx, arg_values
|
89
|
+
vm.push_instructions self.body, set_args(ctx, arg_values)
|
90
|
+
end
|
91
|
+
|
92
|
+
def execute vm
|
93
|
+
vm.push_arg Closure.new(self, vm.current_context)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
class InterpretedFunctionWithoutClosure < InterpretedFunction
|
98
|
+
def invoke_1 vm
|
99
|
+
vm.push_instructions self.body, set_args_0(vm.current_context)
|
100
|
+
end
|
101
|
+
|
102
|
+
def invoke_2 vm, arg
|
103
|
+
vm.push_instructions self.body, set_args_1(vm.current_context, arg)
|
104
|
+
end
|
105
|
+
|
106
|
+
def invoke_3 vm, arg_0, arg_1
|
107
|
+
vm.push_instructions self.body, set_args_2(vm.current_context, arg_0, arg_1)
|
108
|
+
end
|
109
|
+
|
110
|
+
def invoke_4 vm, arg_0, arg_1, arg_2
|
111
|
+
vm.push_instructions self.body, set_args_3(vm.current_context, arg_0, arg_1, arg_2)
|
112
|
+
end
|
113
|
+
|
114
|
+
def invoke vm, arg_values
|
115
|
+
vm.push_instructions self.body, set_args(vm.current_context, arg_values)
|
116
|
+
end
|
117
|
+
|
118
|
+
def execute vm
|
119
|
+
vm.push_arg self
|
120
|
+
end
|
121
|
+
end
|
94
122
|
end
|