nydp 0.5.0 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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 +30 -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 +88 -24
- 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
@@ -3,14 +3,37 @@ require 'nydp/lexical_context_builder'
|
|
3
3
|
require 'nydp/closure'
|
4
4
|
|
5
5
|
module Nydp
|
6
|
-
class
|
7
|
-
|
8
|
-
def
|
9
|
-
|
6
|
+
class Fn < Proc
|
7
|
+
attr_accessor :src
|
8
|
+
def initialize &b
|
9
|
+
super &b
|
10
|
+
end
|
11
|
+
def to_s
|
12
|
+
Nydp.nydp_from_backtrace(source_location.join(":"))
|
13
|
+
end
|
14
|
+
def container_class_name
|
15
|
+
file, line = source_location
|
16
|
+
[file.split(/\//).last, line].join(":")
|
17
|
+
end
|
18
|
+
def inspect
|
19
|
+
[@name, Nydp.nydp_from_backtrace(source_location.join(":"))].compact.join(" : ")
|
20
|
+
end
|
21
|
+
def src
|
22
|
+
Nydp.nydp_from_backtrace(source_location.join(":"))
|
23
|
+
end
|
24
|
+
def nydp_type
|
25
|
+
:fn
|
26
|
+
end
|
27
|
+
|
28
|
+
def is_named name
|
29
|
+
@name = name
|
30
|
+
end
|
31
|
+
|
32
|
+
alias _nydp_call call
|
10
33
|
end
|
11
34
|
|
12
35
|
class InterpretedFunction
|
13
|
-
NIL =
|
36
|
+
NIL = nil
|
14
37
|
include Helper
|
15
38
|
extend Helper
|
16
39
|
|
@@ -20,10 +43,63 @@ module Nydp
|
|
20
43
|
body.map { |b| b.lexical_reach(n - 1) }.max
|
21
44
|
end
|
22
45
|
|
23
|
-
def
|
46
|
+
def can_do?
|
47
|
+
arg_names == nil
|
48
|
+
end
|
49
|
+
|
50
|
+
def compile_do_expr_to_ruby indent, srcs
|
51
|
+
body.
|
52
|
+
map { |expr| expr.compile_to_ruby(" ", srcs, cando: true) }.
|
53
|
+
to_a.
|
54
|
+
join("\n").
|
55
|
+
split(/\n/). # need join-split to separate out embedded newlines (TODO worry about newlines within literal strings?)
|
56
|
+
map { |e| "#{indent} #{e}" }.
|
57
|
+
join("\n")
|
58
|
+
end
|
59
|
+
|
60
|
+
def compile_to_ruby indent, srcs, opts={}
|
61
|
+
an = arg_names
|
62
|
+
rubyargs = []
|
63
|
+
src_index = srcs.length
|
64
|
+
|
65
|
+
srcs << to_s
|
66
|
+
|
67
|
+
while (pair? an)
|
68
|
+
rubyargs << "_arg_#{an.car.to_s._nydp_name_to_rb_name}=nil"
|
69
|
+
an = an.cdr
|
70
|
+
end
|
71
|
+
|
72
|
+
if an
|
73
|
+
rest_arg = "_arg_#{an.to_s._nydp_name_to_rb_name}"
|
74
|
+
rubyargs << "*#{rest_arg}"
|
75
|
+
end
|
76
|
+
|
77
|
+
if rubyargs == []
|
78
|
+
rubyargs = ""
|
79
|
+
else
|
80
|
+
rubyargs = "|#{rubyargs.join ","}|"
|
81
|
+
# rubyargs = "(#{rubyargs.join ","})"
|
82
|
+
end
|
83
|
+
|
84
|
+
# code = "#{indent}(Nydp::Fn.new(@@src_#{src_index}) {#{rubyargs}\n"
|
85
|
+
code = "#{indent}##> (fn #{arg_names._nydp_inspect} #{body.to_a.map(&:_nydp_inspect).join(" ").gsub(/\n/, '\n')})\n"
|
86
|
+
code << "#{indent}(Nydp::Fn.new {#{rubyargs}\n"
|
87
|
+
# code << "#{indent}(Proc.new {#{rubyargs}\n"
|
88
|
+
# code = "(->#{rubyargs} {\n"
|
89
|
+
if rest_arg
|
90
|
+
code << "#{indent} #{rest_arg} = #{rest_arg}._nydp_wrapper\n"
|
91
|
+
end
|
92
|
+
bodycode = body.map { |expr| expr.compile_to_ruby(" ", srcs, cando: true) }.to_a
|
93
|
+
|
94
|
+
bodycode.push "#{bodycode.pop}._nydp_wrapper"
|
95
|
+
code << bodycode.join("\n").split(/\n/).map { |e| "#{indent} #{e}" }.join("\n")
|
96
|
+
code << "\n#{indent}})"
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.build arg_list, body, bindings, ns
|
24
100
|
my_params = { }
|
25
101
|
index_parameters arg_list, my_params
|
26
|
-
body = compile_body body, cons(my_params, bindings), []
|
102
|
+
body = compile_body body, cons(my_params, bindings), [], ns
|
27
103
|
reach = body.map { |b| b.lexical_reach(-1) }.max
|
28
104
|
|
29
105
|
ifn_klass = reach >= 0 ? InterpretedFunctionWithClosure : InterpretedFunctionWithoutClosure
|
@@ -35,11 +111,11 @@ module Nydp
|
|
35
111
|
ifn
|
36
112
|
end
|
37
113
|
|
38
|
-
def self.compile_body body_forms, bindings, instructions
|
39
|
-
instructions << Nydp::Compiler.compile(body_forms.car, bindings)
|
114
|
+
def self.compile_body body_forms, bindings, instructions, ns
|
115
|
+
instructions << Nydp::Compiler.compile(body_forms.car, bindings, ns)
|
40
116
|
|
41
117
|
rest = body_forms.cdr
|
42
|
-
if
|
118
|
+
if !rest
|
43
119
|
return Pair.from_list(instructions)
|
44
120
|
else
|
45
121
|
# PopArg is necessary because each expression pushes an arg onto the arg stack.
|
@@ -47,8 +123,8 @@ module Nydp
|
|
47
123
|
# so we need the following line in order to remove unwanted args from the stack.
|
48
124
|
# Each expression at some executes vm.push_arg(thing)
|
49
125
|
# 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)
|
50
|
-
instructions << PopArg
|
51
|
-
compile_body rest, bindings, instructions
|
126
|
+
# instructions << PopArg
|
127
|
+
compile_body rest, bindings, instructions, ns
|
52
128
|
end
|
53
129
|
end
|
54
130
|
|
@@ -64,59 +140,117 @@ module Nydp
|
|
64
140
|
def nydp_type ; "fn" ; end
|
65
141
|
def inspect ; to_s ; end
|
66
142
|
def to_s
|
67
|
-
"(fn #{arg_names.
|
143
|
+
"(fn #{arg_names._nydp_inspect} #{body.map { |b| b._nydp_inspect}.join('\n')})"
|
144
|
+
end
|
145
|
+
|
146
|
+
def run_body vm
|
147
|
+
res = nil
|
148
|
+
self.body.each { |x| res = x.execute(vm) }
|
149
|
+
res
|
68
150
|
end
|
69
151
|
end
|
70
152
|
|
71
153
|
class InterpretedFunctionWithClosure < InterpretedFunction
|
72
154
|
def invoke_1 vm, ctx
|
73
|
-
vm.
|
155
|
+
cc = vm.current_context
|
156
|
+
vm.current_context = set_args_0(ctx)
|
157
|
+
res = run_body(vm)
|
158
|
+
vm.current_context = cc
|
159
|
+
res
|
160
|
+
# vm.push_instructions self.body, set_args_0(ctx)
|
74
161
|
end
|
75
162
|
|
76
163
|
def invoke_2 vm, ctx, arg
|
77
|
-
vm.
|
164
|
+
cc = vm.current_context
|
165
|
+
vm.current_context = set_args_1(ctx, arg)
|
166
|
+
res = run_body(vm)
|
167
|
+
vm.current_context = cc
|
168
|
+
res
|
169
|
+
# vm.push_instructions self.body, set_args_1(ctx, arg)
|
78
170
|
end
|
79
171
|
|
80
172
|
def invoke_3 vm, ctx, arg_0, arg_1
|
81
|
-
vm.
|
173
|
+
cc = vm.current_context
|
174
|
+
vm.current_context = set_args_2(ctx, arg_0, arg_1)
|
175
|
+
res = run_body(vm)
|
176
|
+
vm.current_context = cc
|
177
|
+
res
|
178
|
+
# vm.push_instructions self.body, set_args_2(ctx, arg_0, arg_1)
|
82
179
|
end
|
83
180
|
|
84
181
|
def invoke_4 vm, ctx, arg_0, arg_1, arg_2
|
85
|
-
vm.
|
182
|
+
cc = vm.current_context
|
183
|
+
vm.current_context = set_args_3(ctx, arg_0, arg_1, arg_2)
|
184
|
+
res = run_body(vm)
|
185
|
+
vm.current_context = cc
|
186
|
+
res
|
187
|
+
# vm.push_instructions self.body, set_args_3(ctx, arg_0, arg_1, arg_2)
|
86
188
|
end
|
87
189
|
|
88
190
|
def invoke vm, ctx, arg_values
|
89
|
-
vm.
|
191
|
+
cc = vm.current_context
|
192
|
+
vm.current_context = set_args(ctx, arg_values)
|
193
|
+
res = run_body(vm)
|
194
|
+
vm.current_context = cc
|
195
|
+
res
|
196
|
+
# vm.push_instructions self.body, set_args(ctx, arg_values)
|
90
197
|
end
|
91
198
|
|
92
199
|
def execute vm
|
93
|
-
|
200
|
+
Closure.new(self, vm.current_context)
|
201
|
+
# vm.push_arg Closure.new(self, vm.current_context)
|
94
202
|
end
|
95
203
|
end
|
96
204
|
|
97
205
|
class InterpretedFunctionWithoutClosure < InterpretedFunction
|
98
206
|
def invoke_1 vm
|
99
|
-
|
207
|
+
cc = vm.current_context
|
208
|
+
vm.current_context = set_args_0(vm.current_context)
|
209
|
+
res = run_body(vm)
|
210
|
+
vm.current_context = cc
|
211
|
+
res
|
212
|
+
# vm.push_instructions self.body, set_args_0(vm.current_context)
|
100
213
|
end
|
101
214
|
|
102
215
|
def invoke_2 vm, arg
|
103
|
-
|
216
|
+
cc = vm.current_context
|
217
|
+
vm.current_context = set_args_1(vm.current_context, arg)
|
218
|
+
res = run_body(vm)
|
219
|
+
vm.current_context = cc
|
220
|
+
res
|
221
|
+
# vm.push_instructions self.body, set_args_1(vm.current_context, arg)
|
104
222
|
end
|
105
223
|
|
106
224
|
def invoke_3 vm, arg_0, arg_1
|
107
|
-
|
225
|
+
cc = vm.current_context
|
226
|
+
vm.current_context = set_args_2(vm.current_context, arg_0, arg_1)
|
227
|
+
res = run_body(vm)
|
228
|
+
vm.current_context = cc
|
229
|
+
res
|
230
|
+
# vm.push_instructions self.body, set_args_2(vm.current_context, arg_0, arg_1)
|
108
231
|
end
|
109
232
|
|
110
233
|
def invoke_4 vm, arg_0, arg_1, arg_2
|
111
|
-
|
234
|
+
cc = vm.current_context
|
235
|
+
vm.current_context = set_args_3(vm.current_context, arg_0, arg_1, arg_2)
|
236
|
+
res = run_body(vm)
|
237
|
+
vm.current_context = cc
|
238
|
+
res
|
239
|
+
# vm.push_instructions self.body, set_args_3(vm.current_context, arg_0, arg_1, arg_2)
|
112
240
|
end
|
113
241
|
|
114
242
|
def invoke vm, arg_values
|
115
|
-
|
243
|
+
cc = vm.current_context
|
244
|
+
vm.current_context = set_args(vm.current_context, arg_values)
|
245
|
+
res = run_body(vm)
|
246
|
+
vm.current_context = cc
|
247
|
+
res
|
248
|
+
# vm.push_instructions self.body, set_args(vm.current_context, arg_values)
|
116
249
|
end
|
117
250
|
|
118
251
|
def execute vm
|
119
|
-
vm.push_arg self
|
252
|
+
# vm.push_arg self
|
253
|
+
self
|
120
254
|
end
|
121
255
|
end
|
122
256
|
end
|
data/lib/nydp/lexical_context.rb
CHANGED
@@ -49,14 +49,15 @@ module Nydp
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def to_s
|
52
|
-
values = []
|
53
|
-
n = 0
|
54
|
-
while at_index n
|
55
|
-
|
56
|
-
|
57
|
-
end
|
58
|
-
parent_s = parent ? " parent #{parent.to_s}" : ""
|
59
|
-
"(context (#{values.join ' '})#{parent_s})"
|
52
|
+
# values = []
|
53
|
+
# n = 0
|
54
|
+
# while at_index n
|
55
|
+
# values << at_index(n)._nydp_inspect
|
56
|
+
# n += 1
|
57
|
+
# end
|
58
|
+
# parent_s = parent ? " parent #{parent.to_s}" : ""
|
59
|
+
# "(context (#{values.join ' '})#{parent_s})"
|
60
|
+
"(NEW context)"
|
60
61
|
end
|
61
62
|
end
|
62
63
|
end
|
data/lib/nydp/literal.rb
CHANGED
@@ -7,12 +7,12 @@ module Nydp
|
|
7
7
|
@expression = expression
|
8
8
|
end
|
9
9
|
|
10
|
-
def self.build expression, bindings
|
10
|
+
def self.build expression, bindings, ns
|
11
11
|
new expression
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
|
14
|
+
def compile_to_ruby indent, srcs, opts=nil
|
15
|
+
"#{indent}#{expression.compile_to_ruby "", srcs}"
|
16
16
|
end
|
17
17
|
|
18
18
|
def nydp_type ; :literal ; end
|
@@ -20,10 +20,6 @@ module Nydp
|
|
20
20
|
def to_s ; @expression.to_s ; end
|
21
21
|
def to_ruby ; n2r @expression ; end
|
22
22
|
|
23
|
-
def coerce _
|
24
|
-
[_, expression]
|
25
|
-
end
|
26
|
-
|
27
23
|
def > other
|
28
24
|
other < expression
|
29
25
|
end
|
data/lib/nydp/loop.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
module Nydp
|
2
|
+
# class LoopBodyInstruction
|
3
|
+
# extend Helper
|
4
|
+
# include Helper
|
5
|
+
|
6
|
+
# def initialize loop_body, condition
|
7
|
+
# @loop_body, @condition = loop_body, cons(Nydp::PopArg, cons(condition))
|
8
|
+
# # @loop_body, @condition = loop_body, cons(condition)
|
9
|
+
# end
|
10
|
+
|
11
|
+
# def lexical_reach n
|
12
|
+
# @loop_body.lexical_reach(n)
|
13
|
+
# end
|
14
|
+
|
15
|
+
# def execute vm
|
16
|
+
# if vm.args.pop
|
17
|
+
# vm.push_ctx_instructions @condition
|
18
|
+
# @loop_body.execute vm
|
19
|
+
# else
|
20
|
+
# vm.push_arg nil
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
|
24
|
+
# def inspect
|
25
|
+
# "loop_body:#{@loop_body._nydp_inspect}"
|
26
|
+
# end
|
27
|
+
|
28
|
+
# def to_s
|
29
|
+
# "#{@loop_body.to_s}"
|
30
|
+
# end
|
31
|
+
# end
|
32
|
+
|
33
|
+
class Loop
|
34
|
+
extend Helper
|
35
|
+
include Helper
|
36
|
+
attr_reader :condition, :loop_body
|
37
|
+
|
38
|
+
def initialize cond, loop_body
|
39
|
+
@condition, @loop_body = cond, loop_body
|
40
|
+
end
|
41
|
+
|
42
|
+
def lexical_reach n
|
43
|
+
[condition.lexical_reach(n), loop_body.lexical_reach(n)].max
|
44
|
+
end
|
45
|
+
|
46
|
+
def inspect
|
47
|
+
"loop:#{condition._nydp_inspect}:#{loop_body._nydp_inspect}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def to_s
|
51
|
+
"(loop #{condition.to_s} #{loop_body.to_s})"
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.build expressions, bindings, ns
|
55
|
+
if expressions.is_a? Nydp::Pair
|
56
|
+
cond = Compiler.compile expressions.car, bindings, ns
|
57
|
+
loop_body = Compiler.compile expressions.cdr.car, bindings, ns
|
58
|
+
csig = sig(cond)
|
59
|
+
new(cond, loop_body)
|
60
|
+
else
|
61
|
+
raise "can't compile Loop: #{expressions._nydp_inspect}"
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def compile_to_ruby indent, srcs, opts=nil
|
66
|
+
"#{indent}##> #{to_s.split(/\n/).join('\n')}\n" +
|
67
|
+
"#{indent}while (#{condition.compile_to_ruby "", srcs})
|
68
|
+
#{loop_body.compile_to_ruby(indent + " ", srcs, cando: true)}
|
69
|
+
#{indent}end"
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module Nydp
|
2
|
+
class Namespace
|
3
|
+
include Nydp::Helper
|
4
|
+
|
5
|
+
def method_missing name, *args
|
6
|
+
if name.to_s =~ /^ns_/
|
7
|
+
attr = name.to_s.gsub(/=$/, '').to_sym
|
8
|
+
singleton_class.instance_eval do
|
9
|
+
attr_accessor attr
|
10
|
+
end
|
11
|
+
send name, *args
|
12
|
+
else
|
13
|
+
super
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def names
|
18
|
+
mm = methods.select { |m| m.to_s =~ /^ns_.*[^=]$/ }.map { |m| nydp_name(m).to_sym }
|
19
|
+
end
|
20
|
+
|
21
|
+
def nydp_name n
|
22
|
+
n.to_s.gsub(/^ns_/, '').gsub(/_../) { |ch| ch[1,2].to_i(16).chr }
|
23
|
+
end
|
24
|
+
|
25
|
+
def ruby_name n
|
26
|
+
n.to_s._nydp_name_to_rb_name
|
27
|
+
end
|
28
|
+
|
29
|
+
def assign name, value
|
30
|
+
send "ns_#{ruby_name name}=", value
|
31
|
+
end
|
32
|
+
|
33
|
+
def fetch name
|
34
|
+
send "ns_#{ruby_name name}"
|
35
|
+
end
|
36
|
+
|
37
|
+
def apply name, *args
|
38
|
+
fn = if name.is_a?(String) || name.is_a?(::Symbol)
|
39
|
+
fetch name
|
40
|
+
elsif name.respond_to? :call
|
41
|
+
name
|
42
|
+
end
|
43
|
+
|
44
|
+
raise "can't apply #{name.inspect} : not a function" unless fn && fn.respond_to?(:call)
|
45
|
+
|
46
|
+
fn.call *(args.map { |a| r2n a })
|
47
|
+
|
48
|
+
rescue StandardError => e
|
49
|
+
raise Nydp::Error.new("Invoking #{name}\nwith args (#{args.map(&:_nydp_compact_inspect).join(' ')})")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|