lisp-interpreter 0.4.2 → 0.4.3
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/lib/lisp/interpreter/functional.rb +290 -0
- data/lib/lisp/interpreter/tokenizer.rb +1 -0
- data/lib/lisp/interpreter/version.rb +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bac8ea2951af78891e06278ec6ae00b35858f875
|
4
|
+
data.tar.gz: e8a83f418220ff4fba37e74bb52223fd9e34e80f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 690b6efb7cf32a7e8534d54ef4521e0eaf28f7ec8aa66e70973901236e39754d2b46fb45d3c5b263571e6af115641cd6631d530fdbdf47853d918689de51a9a0
|
7
|
+
data.tar.gz: 411a2c4f8239fb7e0bd86d0589e7c5a10a7d5917b47d3dfd9500f69fb039288ade0b1c8d0b6c1416e5b25ce275f3aa405f176c97b74db27b654757e518586d08
|
@@ -0,0 +1,290 @@
|
|
1
|
+
# Optimization module
|
2
|
+
module Optimize
|
3
|
+
def fold_values_helper(other)
|
4
|
+
other = other.map { |t| find_list_function_value [t] }
|
5
|
+
(equalize_lists other).transpose
|
6
|
+
end
|
7
|
+
|
8
|
+
def get_fold_values(other)
|
9
|
+
values = find_all_values other
|
10
|
+
raise arg_err_build 'at least 2', 0 if values.empty?
|
11
|
+
x = values[0]
|
12
|
+
y = fold_values_helper values[1..-1]
|
13
|
+
[x, y]
|
14
|
+
end
|
15
|
+
|
16
|
+
def rm_from_in_scope(scope, idx, def_vars)
|
17
|
+
i = find_bracket_idx scope, idx
|
18
|
+
def_vars[scope[idx + 2].to_s] = scope[idx + 3..i - 1]
|
19
|
+
scope.slice!(idx..i)
|
20
|
+
[i + 1, scope, def_vars]
|
21
|
+
end
|
22
|
+
|
23
|
+
def inner_scope_replace(scope, vars)
|
24
|
+
scope.each_with_index do |t, i|
|
25
|
+
scope[i] = vars[t.to_s] if vars.key? t.to_s
|
26
|
+
end
|
27
|
+
scope.flatten
|
28
|
+
end
|
29
|
+
|
30
|
+
def fetch_inner_scope(scope, idx = 0, def_vars = {})
|
31
|
+
until idx >= scope.size
|
32
|
+
if scope[idx] == 'define'
|
33
|
+
idx, scope, def_vars = rm_from_in_scope scope, idx - 1, def_vars
|
34
|
+
else
|
35
|
+
idx += 1
|
36
|
+
end
|
37
|
+
end
|
38
|
+
inner_scope_replace scope, def_vars
|
39
|
+
end
|
40
|
+
|
41
|
+
def filter_helper(func, values)
|
42
|
+
result =
|
43
|
+
if func.is_a? Proc
|
44
|
+
values.select { |t| func.call(*t) == '#t' }
|
45
|
+
else
|
46
|
+
values.select { |t| (send func, [t]) == '#t' }
|
47
|
+
end
|
48
|
+
build_list result
|
49
|
+
end
|
50
|
+
|
51
|
+
def apply_helper(func, values)
|
52
|
+
*vs, lst = values
|
53
|
+
raise 'Incorrect data type' unless lst.list?
|
54
|
+
(find_list_function_value [lst]).each { |t| vs << t }
|
55
|
+
return func.call(*vs) if func.is_a? Proc
|
56
|
+
send func, vs
|
57
|
+
end
|
58
|
+
|
59
|
+
def call_compose_helper(other)
|
60
|
+
tmp = ['(', *other[1..-1]]
|
61
|
+
idx = find_bracket_idx tmp, 0
|
62
|
+
funcs = find_all_values tmp[1..idx - 1]
|
63
|
+
return '' if tmp[idx + 1..-1].nil? && funcs.empty?
|
64
|
+
[funcs, idx, tmp]
|
65
|
+
end
|
66
|
+
|
67
|
+
def call_compose(other)
|
68
|
+
funcs, idx, tmp = call_compose_helper other
|
69
|
+
value = find_all_values tmp[idx + 1..-1]
|
70
|
+
funcs.reverse.each do |t|
|
71
|
+
value = value.to_s unless value.is_a? Array
|
72
|
+
value = calc_input_val ['(', t, *value, ')']
|
73
|
+
end
|
74
|
+
value
|
75
|
+
end
|
76
|
+
|
77
|
+
def build_compose_expr(funcs)
|
78
|
+
expr = ['(', 'x', ')']
|
79
|
+
funcs.each do |f|
|
80
|
+
expr << '('
|
81
|
+
expr << f
|
82
|
+
end
|
83
|
+
expr << 'x'
|
84
|
+
funcs.size.times { expr << ')' }
|
85
|
+
expr
|
86
|
+
end
|
87
|
+
|
88
|
+
def do_not_call_compose(other)
|
89
|
+
funcs = find_all_values other
|
90
|
+
raise 'Incorrect data type' if funcs.any? { |t| t.to_s.number? }
|
91
|
+
expr = build_compose_expr funcs
|
92
|
+
proc_lambda expr
|
93
|
+
end
|
94
|
+
|
95
|
+
def define_var_stl(var, values)
|
96
|
+
puts methods.to_s
|
97
|
+
valid_stl = methods.include? values.to_s[2..-3].to_sym
|
98
|
+
return set_var var, values.to_s[2..-3].to_sym if valid_stl
|
99
|
+
set_var var, values[0]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# FunctionalScheme helper
|
104
|
+
module FunctionalSchemeHelper
|
105
|
+
include Optimize
|
106
|
+
def foldl_helper(func, accum, lst)
|
107
|
+
return accum if lst.empty?
|
108
|
+
value = func.call(*lst[0], accum.to_s) if func.is_a? Proc
|
109
|
+
value = send func, [*lst[0], accum] if value.nil?
|
110
|
+
foldl_helper func, value.to_s, lst[1..-1]
|
111
|
+
end
|
112
|
+
|
113
|
+
def foldr_helper(func, accum, lst)
|
114
|
+
return accum if lst.empty?
|
115
|
+
value = foldr_helper func, accum, lst[1..-1]
|
116
|
+
return func.call(*lst[0], value.to_s) if func.is_a? Proc
|
117
|
+
send func, [*lst[0], value.to_s]
|
118
|
+
end
|
119
|
+
|
120
|
+
def equalize_lists(other)
|
121
|
+
min = other.map(&:size).min
|
122
|
+
other.map { |t| t[0..min - 1] }
|
123
|
+
end
|
124
|
+
|
125
|
+
def member_helper(to_check, values)
|
126
|
+
return '#f' unless values.include? to_check
|
127
|
+
idx = values.index(to_check)
|
128
|
+
build_list values[idx..-1]
|
129
|
+
end
|
130
|
+
|
131
|
+
def find_params_lambda(other)
|
132
|
+
raise 'Invalid syntax' if other[0] != '('
|
133
|
+
idx = find_bracket_idx other, 0
|
134
|
+
[other[1..idx - 1], other[idx + 1..-1]]
|
135
|
+
end
|
136
|
+
|
137
|
+
def eval_lambda(other)
|
138
|
+
idx = find_bracket_idx other.unshift('('), 0
|
139
|
+
to_eval = other[1..idx - 1]
|
140
|
+
(proc_lambda to_eval, true).call(*other[idx + 1..-1])
|
141
|
+
end
|
142
|
+
|
143
|
+
def proc_lambda_helper(other, params, args)
|
144
|
+
args = arg_finder args
|
145
|
+
raise arg_err_build params.size, args.size unless params.size == args.size
|
146
|
+
define_func_helper other.dup, params.dup, args
|
147
|
+
end
|
148
|
+
|
149
|
+
def proc_lambda(other, is_call = false)
|
150
|
+
params, other = find_params_lambda other
|
151
|
+
other = fetch_inner_scope other
|
152
|
+
valid = params.all? { |t| valid_var_name t } || is_call
|
153
|
+
raise 'Invalid syntax' unless valid
|
154
|
+
to_return = other[0..1].join == '(compose' && params.empty?
|
155
|
+
return calc_input_val other if to_return
|
156
|
+
proc = proc do |*args|
|
157
|
+
proc_lambda_helper other, params, args
|
158
|
+
end
|
159
|
+
proc
|
160
|
+
end
|
161
|
+
|
162
|
+
def fetch_define(other)
|
163
|
+
if other[0] == '('
|
164
|
+
define_function other
|
165
|
+
else
|
166
|
+
define_var other[0].to_s, (find_all_values other[1..-1])
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def define_var(var, values)
|
171
|
+
raise arg_err_build 1, values.size if values.size != 1
|
172
|
+
raise 'Invalid variable name' unless valid_var_name var
|
173
|
+
define_var_stl var, values
|
174
|
+
end
|
175
|
+
|
176
|
+
def set_values_define(other, params, args)
|
177
|
+
args = [args] unless args.is_a? Array
|
178
|
+
other.each_with_index do |t, idx|
|
179
|
+
if params.include? t
|
180
|
+
i = params.index t
|
181
|
+
other[idx] = args[i]
|
182
|
+
end
|
183
|
+
end
|
184
|
+
other
|
185
|
+
end
|
186
|
+
|
187
|
+
def define_func_helper(other, params, args)
|
188
|
+
temp = set_values_define other, params, args
|
189
|
+
calc_input_val temp
|
190
|
+
end
|
191
|
+
|
192
|
+
def arg_finder_helper(name, args)
|
193
|
+
if !name.nil?
|
194
|
+
args = args[1..-1]
|
195
|
+
[name, args]
|
196
|
+
else
|
197
|
+
find_next_value args
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
def arg_finder(args)
|
202
|
+
result = []
|
203
|
+
until args.empty?
|
204
|
+
name = predefined_method_caller [args[0]]
|
205
|
+
temp, args = arg_finder_helper name, args
|
206
|
+
result << temp
|
207
|
+
end
|
208
|
+
result
|
209
|
+
end
|
210
|
+
|
211
|
+
def define_function(other)
|
212
|
+
idx = find_bracket_idx other, 0
|
213
|
+
name, *params = other[1..idx - 1]
|
214
|
+
build_fn = ['(', 'lambda', '(', *params, ')', *other[idx + 1..-1], ')']
|
215
|
+
define_var name, (find_all_values build_fn)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
# Functional programming main functions
|
220
|
+
module FunctionalScheme
|
221
|
+
include FunctionalSchemeHelper
|
222
|
+
def foldl(other)
|
223
|
+
raise arg_err_build 'at least 2', other.size if other.size < 2
|
224
|
+
func, other = valid_function other
|
225
|
+
val_one, val_two = get_fold_values other
|
226
|
+
foldl_helper func, val_one, val_two
|
227
|
+
end
|
228
|
+
|
229
|
+
def foldr(other)
|
230
|
+
raise arg_err_build 'at least 2', other.size if other.size < 2
|
231
|
+
func, other = valid_function other
|
232
|
+
val_one, val_two = get_fold_values other
|
233
|
+
foldr_helper func, val_one, val_two
|
234
|
+
end
|
235
|
+
|
236
|
+
def filter(other)
|
237
|
+
raise arg_err_build 2, other.size if other.size < 2
|
238
|
+
func, other = valid_function other
|
239
|
+
raise arg_err_build 2, 1 if other.empty?
|
240
|
+
values = find_all_values other
|
241
|
+
values = find_list_function_value [values[0]]
|
242
|
+
filter_helper func, values
|
243
|
+
end
|
244
|
+
|
245
|
+
def member(other)
|
246
|
+
raise arg_err_build 2, other.size unless other.size == 2
|
247
|
+
to_check = other[0]
|
248
|
+
split_val = split_list_string other[1]
|
249
|
+
raise 'Invalid argument' unless split_val.pair? || split_val.list?
|
250
|
+
values = find_all_values split_val[2..-2]
|
251
|
+
member_helper to_check, values
|
252
|
+
end
|
253
|
+
|
254
|
+
def remove(other)
|
255
|
+
raise arg_err_build 2, other.size unless other.size == 2
|
256
|
+
to_remove = other[0]
|
257
|
+
values = find_list_function_value [other[1]]
|
258
|
+
values.delete_at(values.index(to_remove) || values.length)
|
259
|
+
build_list values
|
260
|
+
end
|
261
|
+
|
262
|
+
def apply(other)
|
263
|
+
raise arg_err_build 'at least 2', 0 if other.nil? || other.empty?
|
264
|
+
func, other = valid_function other
|
265
|
+
raise arg_err_build 'at least 2', 1 if other.empty?
|
266
|
+
values = find_all_values other
|
267
|
+
apply_helper func, values
|
268
|
+
end
|
269
|
+
|
270
|
+
def compose(other)
|
271
|
+
if other[0] != 'compose'
|
272
|
+
do_not_call_compose other
|
273
|
+
else
|
274
|
+
call_compose other
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
def lambda(other)
|
279
|
+
if other[0] == 'lambda'
|
280
|
+
eval_lambda other[1..-1]
|
281
|
+
else
|
282
|
+
proc_lambda other
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
def define(other)
|
287
|
+
raise arg_err_build 2, other.size if other.size < 2
|
288
|
+
fetch_define other
|
289
|
+
end
|
290
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lisp-interpreter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zaki Petrov
|
@@ -79,6 +79,7 @@ files:
|
|
79
79
|
- lib/lisp/interpreter/core/numbers.rb
|
80
80
|
- lib/lisp/interpreter/core/object.rb
|
81
81
|
- lib/lisp/interpreter/core/strings.rb
|
82
|
+
- lib/lisp/interpreter/functional.rb
|
82
83
|
- lib/lisp/interpreter/parser.rb
|
83
84
|
- lib/lisp/interpreter/run.rb
|
84
85
|
- lib/lisp/interpreter/tokenizer.rb
|