lisp-interpreter 0.3.1 → 0.3.2
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/README.md +4 -2
- data/bin/zakichan.bat +1 -0
- data/lib/lisp/interpreter/boolean.rb +4 -4
- data/lib/lisp/interpreter/checker.rb +2 -2
- data/lib/lisp/interpreter/errors.rb +4 -0
- data/lib/lisp/interpreter/functional.rb +22 -20
- data/lib/lisp/interpreter/list.rb +15 -10
- data/lib/lisp/interpreter/numbers.rb +12 -11
- data/lib/lisp/interpreter/parser.rb +6 -16
- data/lib/lisp/interpreter/strings.rb +9 -5
- data/lib/lisp/interpreter/tokenizer.rb +3 -3
- data/lib/lisp/interpreter/version.rb +1 -1
- data/spec/lisp/interpreter_spec.rb +18 -10
- metadata +2 -3
- data/bin/converter.bat +0 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2e3026ff75a77f9f9f3d0b0a6a82021bd3b08f47
|
4
|
+
data.tar.gz: da8f9e91a5af019a8a6c564b530bf99534318611
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: faa24cfec02e0a84a25af4d3580a2d2965ee1c7a6524bbadab0cb5bfc1aebad8430e78c3ec152b922396445c847c95cfdedd74ef26767eec84fa7a4a09e21507
|
7
|
+
data.tar.gz: 4e7b97e227764fb61e022eeea697c3cec1d119cf59683a44d5ce4ebe4d9c7eeeb36c720da01cbba35542e6cc1e2d472348d3798e4c88e86a4ce3dac04da79f6c
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# Lisp::Interpreter
|
2
2
|
Lisp interpreter implemented in Ruby.
|
3
3
|
|
4
4
|
## Installation
|
@@ -156,7 +156,9 @@ other:
|
|
156
156
|
|
157
157
|
## Development
|
158
158
|
|
159
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/
|
159
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
160
|
+
|
161
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
160
162
|
|
161
163
|
## Contributing
|
162
164
|
|
data/bin/zakichan.bat
CHANGED
@@ -23,20 +23,20 @@ end
|
|
23
23
|
module SchemeBooleans
|
24
24
|
include SchemeBooleansHelper
|
25
25
|
def equal?(other)
|
26
|
-
raise
|
26
|
+
raise arg_err_build 2, other.size if other.size != 2
|
27
27
|
other[0].to_s == other[1].to_s ? '#t' : '#f'
|
28
28
|
end
|
29
29
|
|
30
30
|
def not(other)
|
31
|
-
raise
|
31
|
+
raise arg_err_build 1, other.size if other.size != 1
|
32
32
|
raise 'Invalid data type' unless check_for_bool other[0]
|
33
33
|
other[0] == '#t' ? '#f' : '#t'
|
34
34
|
end
|
35
35
|
|
36
36
|
def if(other)
|
37
|
-
raise
|
37
|
+
raise arg_err_build 3, 0 if other.empty?
|
38
38
|
expr, other = find_next_value other
|
39
|
-
raise
|
39
|
+
raise 3, 1 if other.empty?
|
40
40
|
if_helper expr, other
|
41
41
|
end
|
42
42
|
end
|
@@ -24,7 +24,7 @@ module SchemeChecker
|
|
24
24
|
def check_for_quote(token)
|
25
25
|
return true if token[0].quote?
|
26
26
|
is_instance_var = check_instance_var token
|
27
|
-
return true if is_instance_var && (
|
27
|
+
return true if is_instance_var && (check_for_number get_var token)
|
28
28
|
false
|
29
29
|
end
|
30
30
|
|
@@ -39,7 +39,7 @@ module SchemeChecker
|
|
39
39
|
return true if var == '#\space'
|
40
40
|
return true if var.character?
|
41
41
|
is_instance_var = check_instance_var var
|
42
|
-
return true if is_instance_var && (
|
42
|
+
return true if is_instance_var && (check_for_character get_var var)
|
43
43
|
false
|
44
44
|
end
|
45
45
|
end
|
@@ -7,6 +7,10 @@ module ErrorMessages
|
|
7
7
|
def unbalanced_quotes_error
|
8
8
|
'error signaled: unbalanced quotes'
|
9
9
|
end
|
10
|
+
|
11
|
+
def arg_err_build(exp, got)
|
12
|
+
'Incorrect number of arguments, expected ' + exp.to_s + ' got ' + got.to_s
|
13
|
+
end
|
10
14
|
end
|
11
15
|
|
12
16
|
class SchemeException < RuntimeError
|
@@ -7,7 +7,7 @@ module Optimize
|
|
7
7
|
|
8
8
|
def get_fold_values(other)
|
9
9
|
values = find_all_values other
|
10
|
-
raise '
|
10
|
+
raise arg_err_build 'at least 2', 0 if values.empty?
|
11
11
|
x = values[0]
|
12
12
|
y = fold_values_helper values[1..-1]
|
13
13
|
[x, y]
|
@@ -49,23 +49,27 @@ module Optimize
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def apply_helper(func, values)
|
52
|
-
|
53
|
-
|
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
|
54
57
|
end
|
55
58
|
|
56
59
|
def call_compose_helper(other)
|
57
60
|
tmp = ['(', *other[1..-1]]
|
58
61
|
idx = find_bracket_idx tmp, 0
|
59
62
|
funcs = find_all_values tmp[1..idx - 1]
|
60
|
-
|
63
|
+
return '' if tmp[idx + 1..-1].nil? && funcs.empty?
|
61
64
|
[funcs, idx, tmp]
|
62
65
|
end
|
63
66
|
|
64
67
|
def call_compose(other)
|
65
68
|
funcs, idx, tmp = call_compose_helper other
|
66
|
-
value
|
69
|
+
value = find_all_values tmp[idx + 1..-1]
|
67
70
|
funcs.reverse.each do |t|
|
68
|
-
value =
|
71
|
+
value = value.to_s unless value.is_a? Array
|
72
|
+
value = calc_input_val ['(', t, *value, ')']
|
69
73
|
end
|
70
74
|
value
|
71
75
|
end
|
@@ -131,7 +135,7 @@ module FunctionalSchemeHelper
|
|
131
135
|
|
132
136
|
def proc_lambda_helper(other, params, args)
|
133
137
|
args = arg_finder args
|
134
|
-
raise
|
138
|
+
raise arg_err_build params.size, args.size unless params.size == args.size
|
135
139
|
define_func_helper other.dup, params.dup, args
|
136
140
|
end
|
137
141
|
|
@@ -155,7 +159,7 @@ module FunctionalSchemeHelper
|
|
155
159
|
end
|
156
160
|
|
157
161
|
def define_var(var, values)
|
158
|
-
raise
|
162
|
+
raise arg_err_build 1, values.size if values.size != 1
|
159
163
|
raise 'Invalid variable name' unless valid_var_name var
|
160
164
|
set_var_helper var, values[0]
|
161
165
|
end
|
@@ -207,30 +211,30 @@ end
|
|
207
211
|
module FunctionalScheme
|
208
212
|
include FunctionalSchemeHelper
|
209
213
|
def foldl(other)
|
210
|
-
raise '
|
214
|
+
raise arg_err_build 'at least 2', other.size if other.size < 2
|
211
215
|
func, other = valid_function other
|
212
216
|
val_one, val_two = get_fold_values other
|
213
217
|
foldl_helper func, val_one, val_two
|
214
218
|
end
|
215
219
|
|
216
220
|
def foldr(other)
|
217
|
-
raise '
|
221
|
+
raise arg_err_build 'at least 2', other.size if other.size < 2
|
218
222
|
func, other = valid_function other
|
219
223
|
val_one, val_two = get_fold_values other
|
220
224
|
foldr_helper func, val_one, val_two
|
221
225
|
end
|
222
226
|
|
223
227
|
def filter(other)
|
224
|
-
raise
|
228
|
+
raise arg_err_build 2, other.size if other.size < 2
|
225
229
|
func, other = valid_function other
|
226
|
-
raise
|
230
|
+
raise arg_err_build 2, 1 if other.empty?
|
227
231
|
values = find_all_values other
|
228
232
|
values = find_list_function_value [values[0]]
|
229
233
|
filter_helper func, values
|
230
234
|
end
|
231
235
|
|
232
236
|
def member(other)
|
233
|
-
raise
|
237
|
+
raise arg_err_build 2, other.size unless other.size == 2
|
234
238
|
to_check = other[0]
|
235
239
|
split_val = split_list_string other[1]
|
236
240
|
raise 'Invalid argument' unless split_val.pair? || split_val.list?
|
@@ -239,7 +243,7 @@ module FunctionalScheme
|
|
239
243
|
end
|
240
244
|
|
241
245
|
def remove(other)
|
242
|
-
raise
|
246
|
+
raise arg_err_build 2, other.size unless other.size == 2
|
243
247
|
to_remove = other[0]
|
244
248
|
values = find_list_function_value [other[1]]
|
245
249
|
values.delete_at(values.index(to_remove) || values.length)
|
@@ -247,13 +251,11 @@ module FunctionalScheme
|
|
247
251
|
end
|
248
252
|
|
249
253
|
def apply(other)
|
250
|
-
raise '
|
254
|
+
raise arg_err_build 'at least 2', 0 if other.nil? || other.empty?
|
251
255
|
func, other = valid_function other
|
256
|
+
raise arg_err_build 'at least 2', 1 if other.empty?
|
252
257
|
values = find_all_values other
|
253
|
-
|
254
|
-
raise 'Incorrect data type' unless lst.list?
|
255
|
-
(find_list_function_value [lst]).each { |t| vs << t }
|
256
|
-
apply_helper func, vs
|
258
|
+
apply_helper func, values
|
257
259
|
end
|
258
260
|
|
259
261
|
def compose(other)
|
@@ -273,7 +275,7 @@ module FunctionalScheme
|
|
273
275
|
end
|
274
276
|
|
275
277
|
def define(other)
|
276
|
-
raise
|
278
|
+
raise arg_err_build 2, other.size if other.size < 2
|
277
279
|
fetch_define other
|
278
280
|
end
|
279
281
|
end
|
@@ -64,7 +64,7 @@ module SchemeListsHelper
|
|
64
64
|
|
65
65
|
def get_cons_values(tokens)
|
66
66
|
result = get_k_arguments tokens, false, 2
|
67
|
-
raise
|
67
|
+
raise arg_err_build 2, result.size if result.size != 2
|
68
68
|
result
|
69
69
|
end
|
70
70
|
|
@@ -75,7 +75,7 @@ module SchemeListsHelper
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def find_list_function_value(other)
|
78
|
-
raise
|
78
|
+
raise arg_err_build 1, other.size if other.size != 1
|
79
79
|
raise 'Invalid data type' unless other[0].list?
|
80
80
|
split_list_as_string other[0].to_s
|
81
81
|
end
|
@@ -86,7 +86,7 @@ module SchemeListsHelper
|
|
86
86
|
end
|
87
87
|
|
88
88
|
def car_cdr_values(other)
|
89
|
-
raise
|
89
|
+
raise arg_err_build 1, other.size if other.size != 1
|
90
90
|
return find_list_function_value other if other[0].list?
|
91
91
|
(split_list_string other[0].to_s)[2..-2] if other[0].pair?
|
92
92
|
end
|
@@ -95,13 +95,20 @@ module SchemeListsHelper
|
|
95
95
|
return lst.map { |t| func.call(*t) } if func.is_a? Proc
|
96
96
|
lst.map { |t| send func, t }
|
97
97
|
end
|
98
|
+
|
99
|
+
def map_validate_helper(other)
|
100
|
+
raise arg_err_build 'at least 2', 0 if other.empty?
|
101
|
+
func, other = valid_function other
|
102
|
+
raise arg_err_build 'at least 2', 1 if other.empty?
|
103
|
+
[func, other]
|
104
|
+
end
|
98
105
|
end
|
99
106
|
|
100
107
|
# Scheme lists module
|
101
108
|
module SchemeLists
|
102
109
|
include SchemeListsHelper
|
103
110
|
def cons(other)
|
104
|
-
raise
|
111
|
+
raise arg_err_build 2, other.size if other.size != 2
|
105
112
|
cons_helper other
|
106
113
|
end
|
107
114
|
|
@@ -123,17 +130,17 @@ module SchemeLists
|
|
123
130
|
end
|
124
131
|
|
125
132
|
def list?(other)
|
126
|
-
raise
|
133
|
+
raise arg_err_build 1, other.size if other.size != 1
|
127
134
|
other[0].to_s.list? ? '#t' : '#f'
|
128
135
|
end
|
129
136
|
|
130
137
|
def pair?(other)
|
131
|
-
raise
|
138
|
+
raise arg_err_build 1, other.size if other.size != 1
|
132
139
|
other[0].to_s.pair? ? '#t' : '#f'
|
133
140
|
end
|
134
141
|
|
135
142
|
def null?(other)
|
136
|
-
raise
|
143
|
+
raise arg_err_build 1, other.size if other.size != 1
|
137
144
|
return '#f' unless other[0].to_s.list?
|
138
145
|
other[0].to_s.size == 3 ? '#t' : '#f'
|
139
146
|
end
|
@@ -148,9 +155,7 @@ module SchemeLists
|
|
148
155
|
end
|
149
156
|
|
150
157
|
def map(other)
|
151
|
-
|
152
|
-
func, other = valid_function other
|
153
|
-
raise 'Incorrect number of arguments' if other.empty?
|
158
|
+
func, other = map_validate_helper other
|
154
159
|
lst = find_all_values other
|
155
160
|
lst = lst.map { |t| find_list_function_value [t] }
|
156
161
|
lst = (equalize_lists lst).transpose
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# Helper functions for SchemeNumbers
|
2
2
|
module SchemeNumbersHelper
|
3
3
|
def get_one_arg_function(other)
|
4
|
-
raise
|
4
|
+
raise arg_err_build 1, other.size if other.size != 1
|
5
5
|
raise 'Invalid data type' unless check_for_number other[0]
|
6
6
|
other[0].to_num
|
7
7
|
end
|
@@ -11,12 +11,11 @@ module SchemeNumbersHelper
|
|
11
11
|
end
|
12
12
|
|
13
13
|
def num_denom_helper(other)
|
14
|
-
raise 'Incorrect number of arguments' if other.empty?
|
15
14
|
if other.size == 1
|
16
15
|
other = other[0].split('/')
|
17
16
|
else
|
18
17
|
_, temp = find_next_value other
|
19
|
-
raise
|
18
|
+
raise arg_err_build 1, 0 unless temp[0] == '/' || temp.empty?
|
20
19
|
i = find_idx_numerators other
|
21
20
|
other.delete_at(i)
|
22
21
|
end
|
@@ -28,12 +27,12 @@ module SchemeNumbersHelper
|
|
28
27
|
raise 'Invalid data type' unless check_for_number num
|
29
28
|
return [num, 1] if other.empty?
|
30
29
|
denom, other = find_next_value other
|
31
|
-
raise
|
30
|
+
raise arg_err_build 1, other.size unless other.empty?
|
32
31
|
[num, denom]
|
33
32
|
end
|
34
33
|
|
35
34
|
def compare_value_arithmetic(other, oper)
|
36
|
-
raise '
|
35
|
+
raise arg_err_build 'at least 2', other.size if other.size < 2
|
37
36
|
other = convert_to_num other
|
38
37
|
result = other.each_cons(2).all? { |x, y| x.public_send oper, y }
|
39
38
|
result ? '#t' : '#f'
|
@@ -96,32 +95,33 @@ module SchemeNumbers
|
|
96
95
|
end
|
97
96
|
|
98
97
|
def /(other)
|
99
|
-
raise '
|
98
|
+
raise arg_err_build 'at least 1', 0 if other.empty?
|
100
99
|
other = divide_special_convert other
|
101
100
|
return (divide_number 1, other[0].to_num) if other.size == 1
|
102
101
|
other[1..-1].inject(other[0]) { |res, t| divide_number res, t }
|
103
102
|
end
|
104
103
|
|
105
104
|
def quotient(other)
|
106
|
-
raise
|
105
|
+
raise arg_err_build 2, other.size if other.size != 2
|
107
106
|
x, y = convert_to_num other
|
108
107
|
result = divide_number x, y
|
109
108
|
result < 0 ? result.ceil : result.floor
|
110
109
|
end
|
111
110
|
|
112
111
|
def remainder(other)
|
113
|
-
raise
|
112
|
+
raise arg_err_build 2, other.size if other.size != 2
|
114
113
|
x, y = convert_to_num other
|
115
114
|
(x.abs % y.abs) * (x / x.abs)
|
116
115
|
end
|
117
116
|
|
118
117
|
def modulo(other)
|
119
|
-
raise
|
118
|
+
raise arg_err_build 2, other.size if other.size != 2
|
120
119
|
x, y = convert_to_num other
|
121
120
|
x.modulo y
|
122
121
|
end
|
123
122
|
|
124
123
|
def numerator(other)
|
124
|
+
raise arg_err_build 1, 0 if other.empty?
|
125
125
|
other = num_denom_helper other
|
126
126
|
result = (get_num_denom other)[0]
|
127
127
|
raise 'Invalid data type' unless check_for_number result
|
@@ -129,6 +129,7 @@ module SchemeNumbers
|
|
129
129
|
end
|
130
130
|
|
131
131
|
def denominator(other)
|
132
|
+
raise arg_err_build 1, 0 if other.empty?
|
132
133
|
other = num_denom_helper other
|
133
134
|
result = (get_num_denom other)[1]
|
134
135
|
raise 'Invalid data type' unless check_for_number result
|
@@ -148,13 +149,13 @@ module SchemeNumbers
|
|
148
149
|
end
|
149
150
|
|
150
151
|
def min(other)
|
151
|
-
raise '
|
152
|
+
raise arg_err_build 'at least 1', 0 if other.empty?
|
152
153
|
other = convert_to_num other
|
153
154
|
other.min
|
154
155
|
end
|
155
156
|
|
156
157
|
def max(other)
|
157
|
-
raise '
|
158
|
+
raise arg_err_build 'at least 1', 0 if other.empty?
|
158
159
|
other = convert_to_num other
|
159
160
|
other.max
|
160
161
|
end
|
@@ -51,12 +51,11 @@ class Parser
|
|
51
51
|
token = token[5..-1].nil? ? token[4..-1] : token[5..-1]
|
52
52
|
msg = 'File with name "' + token + '" is not valid scheme file'
|
53
53
|
return msg
|
54
|
-
return false
|
55
54
|
end
|
56
55
|
true
|
57
56
|
end
|
58
57
|
|
59
|
-
def read_file_reader(f,
|
58
|
+
def read_file_reader(f, expr)
|
60
59
|
while (c = f.read(1))
|
61
60
|
expr << c
|
62
61
|
if (validate_token expr).nil? && expr != ''
|
@@ -70,28 +69,19 @@ class Parser
|
|
70
69
|
def read_file_executor(file)
|
71
70
|
f = File.open(file)
|
72
71
|
expr = ''
|
73
|
-
|
74
|
-
read_file_reader f, last_value, expr
|
72
|
+
read_file_reader f, expr
|
75
73
|
end
|
76
74
|
|
77
|
-
def read_file(token)
|
75
|
+
def read_file(token)
|
78
76
|
res = read_file_helper token
|
79
77
|
return res if res.is_a? String
|
80
78
|
filename = token[5..-1]
|
81
|
-
if
|
82
|
-
|
83
|
-
else
|
84
|
-
read_file_executor filename
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
def fetch_file_read(token)
|
89
|
-
res = read_file token
|
90
|
-
print_result res unless res.to_s.empty?
|
79
|
+
return read_file_executor filename if File.exist? filename
|
80
|
+
'File with name "' + filename + '" does not exist!'
|
91
81
|
end
|
92
82
|
|
93
83
|
def parse(token)
|
94
|
-
return
|
84
|
+
return read_file token if token.start_with? 'ghci'
|
95
85
|
token_error = validate_token token
|
96
86
|
result =
|
97
87
|
if token_error.nil?
|
@@ -37,7 +37,7 @@ module SchemeStringsHelper
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def arg_function_validator(other, vars = 1)
|
40
|
-
raise
|
40
|
+
raise arg_err_build other.size, vars if other.size != vars
|
41
41
|
result = other[0..vars - 1].all? { |v| check_for_string v }
|
42
42
|
raise 'Invalid data type' unless result
|
43
43
|
result
|
@@ -48,13 +48,18 @@ module SchemeStringsHelper
|
|
48
48
|
delim_result = find_delimeter dilimeter
|
49
49
|
'"' + (values.join delim_result) + '"'
|
50
50
|
end
|
51
|
+
|
52
|
+
def strjoin_validate(other)
|
53
|
+
raise arg_err_build '[1, 2]', other.size unless other.size.between? 1, 2
|
54
|
+
raise 'Invalid data type' unless other[0].to_s.list?
|
55
|
+
end
|
51
56
|
end
|
52
57
|
|
53
58
|
# Scheme numbers module
|
54
59
|
module SchemeStrings
|
55
60
|
include SchemeStringsHelper
|
56
61
|
def substring(other)
|
57
|
-
raise '
|
62
|
+
raise arg_err_build '[2, 3]', other.size unless other.size.between? 2, 3
|
58
63
|
str, from, to = other
|
59
64
|
arg_function_validator [str]
|
60
65
|
valid = (check_for_number from) && (to.nil? || (check_for_number to))
|
@@ -63,7 +68,7 @@ module SchemeStrings
|
|
63
68
|
end
|
64
69
|
|
65
70
|
def string?(other)
|
66
|
-
raise
|
71
|
+
raise arg_err_build 1, other.size if other.size != 1
|
67
72
|
result = check_for_string other[0].to_s
|
68
73
|
result ? '#t' : '#f'
|
69
74
|
end
|
@@ -123,8 +128,7 @@ module SchemeStrings
|
|
123
128
|
end
|
124
129
|
|
125
130
|
def strjoin(other)
|
126
|
-
|
127
|
-
raise 'Invalid data type' unless other[0].to_s.list?
|
131
|
+
strjoin_validate other
|
128
132
|
arg_function_validator [other[1]] if other.size == 2
|
129
133
|
string_join_helper other[0], other[1]
|
130
134
|
end
|
@@ -39,8 +39,7 @@ module TokenizerHelper
|
|
39
39
|
'string-contains?' => 'strcontains', 'string-length' => 'strlen',
|
40
40
|
'string->list' => 'strlist', 'string-split' => 'strsplit',
|
41
41
|
'string-sufix?' => 'strsufix', 'string-prefix?' => 'strprefix',
|
42
|
-
'string-replace' => 'strreplace', 'string-join' => 'strjoin'
|
43
|
-
'list-ref' => 'listref', 'list-tail' => 'listtail'
|
42
|
+
'string-replace' => 'strreplace', 'string-join' => 'strjoin'
|
44
43
|
}
|
45
44
|
end
|
46
45
|
|
@@ -89,12 +88,13 @@ module TokenizerHelper
|
|
89
88
|
val = (predefined_method_caller [var])
|
90
89
|
return val unless val.nil?
|
91
90
|
valid = valid_var var
|
92
|
-
valid ? var : (raise '
|
91
|
+
valid ? var : (raise 'Unbound symbol "' + var + '"')
|
93
92
|
end
|
94
93
|
end
|
95
94
|
|
96
95
|
# Tokenizer class
|
97
96
|
class Tokenizer
|
97
|
+
include ErrorMessages
|
98
98
|
include TokenizerHelper
|
99
99
|
include ValueFinder
|
100
100
|
include SchemeChecker
|
@@ -7,7 +7,6 @@ RSpec.describe Lisp::Interpreter do
|
|
7
7
|
@p.parse('(define y 0.999)')
|
8
8
|
@msg =
|
9
9
|
{
|
10
|
-
'inc_number' => 'Incorrect number of arguments',
|
11
10
|
'zero_div' => 'divided by 0',
|
12
11
|
'inv_type' => 'Invalid data type'
|
13
12
|
}
|
@@ -20,6 +19,14 @@ RSpec.describe Lisp::Interpreter do
|
|
20
19
|
'(' + arr.join(' ') + ')'
|
21
20
|
end
|
22
21
|
|
22
|
+
def arg_err_build(e, g)
|
23
|
+
'Incorrect number of arguments, expected ' + e.to_s + ' got ' + g.to_s
|
24
|
+
end
|
25
|
+
|
26
|
+
def unbound_symbol(sym)
|
27
|
+
'Unbound symbol "' + sym.to_s + '"'
|
28
|
+
end
|
29
|
+
|
23
30
|
@p.parse('(define xl (lambda (x) (* 2 x)))')
|
24
31
|
@p.parse('(define yl (lambda () 5))')
|
25
32
|
@p.parse('(define zl (lambda ()))')
|
@@ -28,15 +35,15 @@ RSpec.describe Lisp::Interpreter do
|
|
28
35
|
describe 'exceptions' do
|
29
36
|
context 'wrong number of arguments' do
|
30
37
|
it 'throws error when less arguments are provided' do
|
31
|
-
expect(@p.parse('(cons 1)')).to eq
|
38
|
+
expect(@p.parse('(cons 1)')).to eq arg_err_build 2, 1
|
32
39
|
end
|
33
40
|
|
34
41
|
it 'throws error when more arguments are provided' do
|
35
|
-
expect(@p.parse('(xl 6 6)')).to eq
|
42
|
+
expect(@p.parse('(xl 6 6)')).to eq arg_err_build 1, 2
|
36
43
|
end
|
37
44
|
|
38
45
|
it 'throws error when no arguments are expected' do
|
39
|
-
expect(@p.parse('(yl 5)')).to eq
|
46
|
+
expect(@p.parse('(yl 5)')).to eq arg_err_build 0, 1
|
40
47
|
end
|
41
48
|
end
|
42
49
|
|
@@ -61,7 +68,7 @@ RSpec.describe Lisp::Interpreter do
|
|
61
68
|
|
62
69
|
describe 'literals' do
|
63
70
|
it 'throws invalid variable error when the data is invalid' do
|
64
|
-
expect(@p.parse('#\invalid')).to eq
|
71
|
+
expect(@p.parse('#\invalid')).to eq unbound_symbol '#\invalid'
|
65
72
|
end
|
66
73
|
|
67
74
|
it 'can parse integers' do
|
@@ -981,18 +988,19 @@ RSpec.describe Lisp::Interpreter do
|
|
981
988
|
expr1 = '(define prodfive (lambda (x)(define yy 5)(* x yy)))'
|
982
989
|
expect(@p.parse(expr1)).to be_instance_of(Proc)
|
983
990
|
expect(@p.parse('(prodfive 6)')).to eq 30
|
984
|
-
expect(@p.parse('yy')).to eq
|
991
|
+
expect(@p.parse('yy')).to eq unbound_symbol 'yy'
|
985
992
|
end
|
986
993
|
end
|
987
994
|
|
988
|
-
# You must provide fullpath of the file or place it in the directory where you run the script
|
989
995
|
describe 'file read' do
|
990
996
|
it 'reads from .ss file' do
|
991
|
-
|
997
|
+
expr1 = 'ghci D:/Github/Ruby-Project/lisp-interpreter/spec/lisp/test.ss'
|
998
|
+
expect(@p.parse(expr1)).to be_instance_of(Proc)
|
992
999
|
end
|
993
|
-
|
1000
|
+
|
994
1001
|
it 'reads from .scm file' do
|
995
|
-
|
1002
|
+
expr1 = 'ghci D:/Github/Ruby-Project/lisp-interpreter/spec/lisp/test.scm'
|
1003
|
+
expect(@p.parse(expr1)).to eq 3
|
996
1004
|
end
|
997
1005
|
|
998
1006
|
it 'returns error if the file is missing or not valid scheme file' do
|
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.3.
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Zaki Petrov
|
@@ -67,7 +67,6 @@ files:
|
|
67
67
|
- LICENSE.txt
|
68
68
|
- README.md
|
69
69
|
- Rakefile
|
70
|
-
- bin/converter.bat
|
71
70
|
- bin/setup
|
72
71
|
- bin/start.rb
|
73
72
|
- bin/zakichan.bat
|
@@ -112,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
112
111
|
version: '0'
|
113
112
|
requirements: []
|
114
113
|
rubyforge_project:
|
115
|
-
rubygems_version: 2.
|
114
|
+
rubygems_version: 2.6.12
|
116
115
|
signing_key:
|
117
116
|
specification_version: 4
|
118
117
|
summary: Lisp interpreter gem
|
data/bin/converter.bat
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
;@echo off
|
2
|
-
; rem https://github.com/npocmaka/batch.scripts/edit/master/hybrids/iexpress/bat2exeIEXP.bat
|
3
|
-
;if "%~2" equ "" (
|
4
|
-
; echo usage: %~nx0 batFile.bat target.Exe
|
5
|
-
;)
|
6
|
-
;set "target.exe=%__cd__%%~2"
|
7
|
-
;set "batch_file=%~f1"
|
8
|
-
;set "bat_name=%~nx1"
|
9
|
-
;set "bat_dir=%~dp1"
|
10
|
-
|
11
|
-
;copy /y "%~f0" "%temp%\2exe.sed" >nul
|
12
|
-
|
13
|
-
;(echo()>>"%temp%\2exe.sed"
|
14
|
-
;(echo(AppLaunched=cmd.exe /c "%bat_name%")>>"%temp%\2exe.sed"
|
15
|
-
;(echo(TargetName=%target.exe%)>>"%temp%\2exe.sed"
|
16
|
-
;(echo(FILE0="%bat_name%")>>"%temp%\2exe.sed"
|
17
|
-
;(echo([SourceFiles])>>"%temp%\2exe.sed"
|
18
|
-
;(echo(SourceFiles0=%bat_dir%)>>"%temp%\2exe.sed"
|
19
|
-
;(echo([SourceFiles0])>>"%temp%\2exe.sed"
|
20
|
-
;(echo(%%FILE0%%=)>>"%temp%\2exe.sed"
|
21
|
-
|
22
|
-
|
23
|
-
;iexpress /n /q /m %temp%\2exe.sed
|
24
|
-
|
25
|
-
;del /q /f "%temp%\2exe.sed"
|
26
|
-
;exit /b 0
|
27
|
-
|
28
|
-
[Version]
|
29
|
-
Class=IEXPRESS
|
30
|
-
SEDVersion=3
|
31
|
-
[Options]
|
32
|
-
PackagePurpose=InstallApp
|
33
|
-
ShowInstallProgramWindow=0
|
34
|
-
HideExtractAnimation=1
|
35
|
-
UseLongFileName=1
|
36
|
-
InsideCompressed=0
|
37
|
-
CAB_FixedSize=0
|
38
|
-
CAB_ResvCodeSigning=0
|
39
|
-
RebootMode=N
|
40
|
-
InstallPrompt=%InstallPrompt%
|
41
|
-
DisplayLicense=%DisplayLicense%
|
42
|
-
FinishMessage=%FinishMessage%
|
43
|
-
TargetName=%TargetName%
|
44
|
-
FriendlyName=%FriendlyName%
|
45
|
-
AppLaunched=%AppLaunched%
|
46
|
-
PostInstallCmd=%PostInstallCmd%
|
47
|
-
AdminQuietInstCmd=%AdminQuietInstCmd%
|
48
|
-
UserQuietInstCmd=%UserQuietInstCmd%
|
49
|
-
SourceFiles=SourceFiles
|
50
|
-
|
51
|
-
[Strings]
|
52
|
-
InstallPrompt=
|
53
|
-
DisplayLicense=
|
54
|
-
FinishMessage=
|
55
|
-
FriendlyName=-
|
56
|
-
PostInstallCmd=<None>
|
57
|
-
AdminQuietInstCmd=
|
58
|
-
UserQuietInstCmd=
|