lisp-interpreter 0.4.0 → 0.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0f2eed4083aad91446e2fd71b4b7ad1181e7c4d4
4
- data.tar.gz: 553180b55363be657880ebeeefc78a46f410e95b
3
+ metadata.gz: d0691fe861df7ee5e54aac3b2f291df8e517a48d
4
+ data.tar.gz: d370f3810b7e2e9caa9af9372f3ac2cc2ea1601f
5
5
  SHA512:
6
- metadata.gz: 67963dab535ddc3f856fb7dbe0b286eae6f0ac1d4a2d728d144374fe805639f489ecf57b50928d51ee47710e50d105e7b4cc3cb411406c72a4232efe587d82b5
7
- data.tar.gz: 78bcaad6f467ad69d83af2afedc9d9f4c9631b9383f2a769dc56efc787e917a2cd98591eb5bd7ce6b74562f82ad4c4fd4839d61e47bc742d453dcb91506fa042
6
+ metadata.gz: 16869c9165eaebbd985f3c866f25fdd0c55f18f21bd13c841b6aac63f6217134ef0464ee4962770088b13442bceaada40c1e69e371911cf5d316c462b3a60bb1
7
+ data.tar.gz: 31711dfa5b59c031d06aa2e67c4b68a5f3edd0cf41e02a88b83505d2e2ba5c9490ddce51a022b55a888de9617bb054ae1d638583c31047d3ef5fbf2712c7c470
@@ -30,7 +30,7 @@ module SchemeBooleans
30
30
  def not(other)
31
31
  raise arg_err_build 1, other.size if other.size != 1
32
32
  valid = check_for_bool other[0]
33
- raise data_type_err '<boolean>', other[0].type unless valid
33
+ raise type_err '<boolean>', other[0].type unless valid
34
34
  other[0] == '#t' ? '#f' : '#t'
35
35
  end
36
36
 
@@ -20,7 +20,7 @@ module ErrorMessages
20
20
  'Unbound symbol ' + symbol.to_s
21
21
  end
22
22
 
23
- def data_type_err(exp, got)
23
+ def type_err(exp, got)
24
24
  'Invalid data type, expected ' + exp.to_s + ' got ' + got.to_s
25
25
  end
26
26
  end
@@ -76,7 +76,7 @@ module SchemeListsHelper
76
76
 
77
77
  def find_list_function_value(other)
78
78
  raise arg_err_build 1, other.size if other.size != 1
79
- raise data_type_err '<list>', other[0].type unless other[0].list?
79
+ raise type_err '<list>', other[0].type unless other[0].list?
80
80
  split_list_as_string other[0].to_s
81
81
  end
82
82
 
@@ -2,7 +2,7 @@
2
2
  module SchemeNumbersHelper
3
3
  def get_one_arg_function(other)
4
4
  raise arg_err_build 1, other.size if other.size != 1
5
- raise data_type_err '<number>', other[0].type unless check_for_num other[0]
5
+ raise type_err '<number>', other[0].type unless check_for_num other[0]
6
6
  other[0].to_num
7
7
  end
8
8
 
@@ -24,7 +24,7 @@ module SchemeNumbersHelper
24
24
 
25
25
  def get_num_denom(other)
26
26
  num, other = find_next_value other
27
- raise data_type_err '<number>', num.type unless check_for_num num
27
+ raise type_err '<number>', num.type unless check_for_num num
28
28
  return [num, 1] if other.empty?
29
29
  denom, other = find_next_value other
30
30
  raise arg_err_build 1, other.size unless other.empty?
@@ -40,7 +40,7 @@ module SchemeNumbersHelper
40
40
 
41
41
  def convert_to_num(other)
42
42
  other.each do |t|
43
- raise data_type_err '<number>', t.type unless check_for_num t
43
+ raise type_err '<number>', t.type unless check_for_num t
44
44
  end
45
45
  other.map(&:to_num)
46
46
  end
@@ -124,7 +124,7 @@ module SchemeNumbers
124
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
- raise data_type_err '<number>', result.type unless check_for_num result
127
+ raise type_err '<number>', result.type unless check_for_num result
128
128
  result.to_num
129
129
  end
130
130
 
@@ -132,7 +132,7 @@ module SchemeNumbers
132
132
  raise arg_err_build 1, 0 if other.empty?
133
133
  other = num_denom_helper other
134
134
  result = (get_num_denom other)[1]
135
- raise data_type_err '<number>', result.type unless check_for_num result
135
+ raise type_err '<number>', result.type unless check_for_num result
136
136
  result.to_num
137
137
  end
138
138
 
@@ -39,7 +39,7 @@ module SchemeStringsHelper
39
39
  def arg_function_validator(other, vars = 1)
40
40
  raise arg_err_build other.size, vars if other.size != vars
41
41
  res = other[0..vars - 1].reject { |v| check_for_string v }
42
- raise data_type_err '<string>', res[0].type unless res.empty?
42
+ raise type_err '<string>', res[0].type unless res.empty?
43
43
  res
44
44
  end
45
45
 
@@ -51,13 +51,13 @@ module SchemeStringsHelper
51
51
 
52
52
  def strjoin_validate(other)
53
53
  raise arg_err_build '[1, 2]', other.size unless other.size.between? 1, 2
54
- raise data_type_err '<list>', other[0].type unless other[0].to_s.list?
54
+ raise type_err '<list>', other[0].type unless other[0].to_s.list?
55
55
  end
56
56
 
57
57
  def substring_validator(from, to)
58
58
  valid = (check_for_num from) && (to.nil? || (check_for_num to))
59
59
  type = [from, to].first { |t| t.type if t.type != 'number' }
60
- raise data_type_err '<number>', type unless valid
60
+ raise type_err '<number>', type unless valid
61
61
  end
62
62
  end
63
63
 
@@ -0,0 +1,183 @@
1
+ # Helper functions for SchemeLists
2
+ module SchemeListsHelper
3
+ def evaluate_list(tokens, no_quotes)
4
+ find_all_values_list_evaluate tokens, no_quotes
5
+ end
6
+
7
+ def no_eval_list(tokens, no_quotes = false)
8
+ result = []
9
+ until tokens.empty?
10
+ value, tokens = build_next_value_as_string tokens
11
+ value = value[1..-2] if no_quotes && (check_for_string value.to_s)
12
+ result << value
13
+ end
14
+ result
15
+ end
16
+
17
+ def find_to_evaluate_or_not(tokens, no_quotes = false)
18
+ if tokens[0..1].join == '(list'
19
+ evaluate_list tokens[2..-2], no_quotes
20
+ elsif tokens[0..1].join == '(cons'
21
+ result = cons tokens[2..-2]
22
+ result[2..-2].split(' ')
23
+ else
24
+ no_eval_list tokens[2..-2], no_quotes
25
+ end
26
+ end
27
+
28
+ def find_idx_for_list(tokens)
29
+ if tokens[0] == '('
30
+ find_bracket_idx tokens, 0
31
+ elsif tokens[1] == '('
32
+ find_bracket_idx tokens, 1
33
+ end
34
+ end
35
+
36
+ def find_all_values_list_evaluate(tokens, no_quotes = false)
37
+ result = []
38
+ until tokens.empty?
39
+ x, tokens = find_next_value tokens
40
+ x = x[1..-2] if no_quotes && (check_for_string x.to_s)
41
+ result << x
42
+ end
43
+ result
44
+ end
45
+
46
+ def build_list(values)
47
+ '\'(' + values.join(' ') + ')'
48
+ end
49
+
50
+ def build_cons_from_list(values)
51
+ spacer = values[1].size == 3 ? '' : ' '
52
+ values[0].to_s + spacer + values[1][2..-2].to_s
53
+ end
54
+
55
+ def cons_helper(values)
56
+ result =
57
+ if values[1].to_s[0..1] == '\'('
58
+ build_cons_from_list values
59
+ else
60
+ values[0].to_s + ' . ' + values[1].to_s
61
+ end
62
+ '\'(' + result + ')'
63
+ end
64
+
65
+ def get_cons_values(tokens)
66
+ result = get_k_arguments tokens, false, 2
67
+ raise arg_err_build 2, result.size if result.size != 2
68
+ result
69
+ end
70
+
71
+ def split_list_string(list)
72
+ result = list.split(/(\(|\)|\.)|\ /)
73
+ result.delete('')
74
+ result
75
+ end
76
+
77
+ def find_list_function_value(other)
78
+ raise arg_err_build 1, other.size if other.size != 1
79
+ raise data_type_err 'list', other[0].type unless other[0].list?
80
+ split_list_as_string other[0].to_s
81
+ end
82
+
83
+ def split_list_as_string(list_as_string)
84
+ split_value = split_list_string list_as_string.to_s
85
+ no_eval_list split_value[2..-2]
86
+ end
87
+
88
+ def car_cdr_values(other)
89
+ raise arg_err_build 1, other.size if other.size != 1
90
+ return find_list_function_value other if other[0].list?
91
+ (split_list_string other[0].to_s)[2..-2] if other[0].pair?
92
+ end
93
+
94
+ def map_helper(lst, func)
95
+ return lst.map { |t| func.call(*t) } if func.is_a? Proc
96
+ lst.map { |t| send func, t }
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
105
+
106
+ def car_cdr_infinite_helper(value, fn)
107
+ fn.reverse[1..-2].each_char do |t|
108
+ value = t == 'a' ? (car [value]) : (cdr [value])
109
+ end
110
+ value
111
+ end
112
+ end
113
+
114
+ # Scheme lists module
115
+ module SchemeLists
116
+ include SchemeListsHelper
117
+ def cons(other)
118
+ raise arg_err_build 2, other.size if other.size != 2
119
+ cons_helper other
120
+ end
121
+
122
+ def list(other)
123
+ build_list other
124
+ end
125
+
126
+ def car(other)
127
+ value = car_cdr_values other
128
+ raise 'Cannot apply car on ' + other[0].to_s if value.nil? || value.empty?
129
+ value.shift
130
+ end
131
+
132
+ def cdr(other)
133
+ value = car_cdr_values other
134
+ raise 'Cannot apply cdr on ' + other[0].to_s if value.nil? || value.empty?
135
+ idx = value[1] == '.' ? 2 : 1
136
+ build_list value[idx..-1]
137
+ end
138
+
139
+ def list?(other)
140
+ raise arg_err_build 1, other.size if other.size != 1
141
+ other[0].to_s.list? ? '#t' : '#f'
142
+ end
143
+
144
+ def pair?(other)
145
+ raise arg_err_build 1, other.size if other.size != 1
146
+ other[0].to_s.pair? ? '#t' : '#f'
147
+ end
148
+
149
+ def null?(other)
150
+ raise arg_err_build 1, other.size if other.size != 1
151
+ return '#f' unless other[0].to_s.list?
152
+ other[0].to_s.size == 3 ? '#t' : '#f'
153
+ end
154
+
155
+ def length(other)
156
+ (find_list_function_value other).size
157
+ end
158
+
159
+ def reverse(other)
160
+ value = find_list_function_value other
161
+ build_list value.reverse
162
+ end
163
+
164
+ def map(other)
165
+ func, other = map_validate_helper other
166
+ lst = find_all_values other
167
+ lst = lst.map { |t| find_list_function_value [t] }
168
+ lst = (equalize_lists lst).transpose
169
+ build_list map_helper lst, func
170
+ end
171
+
172
+ def shuffle(other)
173
+ values = find_list_function_value other
174
+ build_list values.shuffle
175
+ end
176
+
177
+ def car_cdr_infinite(other)
178
+ fn = other[1]
179
+ values = find_all_values other[2..-2]
180
+ raise 'Incorrect number of arguments' unless values.size == 1
181
+ car_cdr_infinite_helper values[0], fn
182
+ end
183
+ end
@@ -0,0 +1,162 @@
1
+ # Helper functions for SchemeNumbers
2
+ module SchemeNumbersHelper
3
+ def get_one_arg_function(other)
4
+ raise arg_err_build 1, other.size if other.size != 1
5
+ raise type_err 'number', other[0].type unless check_for_num other[0]
6
+ other[0].to_num
7
+ end
8
+
9
+ def find_idx_numerators(other)
10
+ other[0] == '(' ? (find_bracket_idx other, 0) + 1 : 1
11
+ end
12
+
13
+ def num_denom_helper(other)
14
+ if other.size == 1
15
+ other = other[0].split('/')
16
+ else
17
+ _, temp = find_next_value other
18
+ raise arg_err_build 1, 0 unless temp[0] == '/' || temp.empty?
19
+ i = find_idx_numerators other
20
+ other.delete_at(i)
21
+ end
22
+ other
23
+ end
24
+
25
+ def get_num_denom(other)
26
+ num, other = find_next_value other
27
+ raise 'Invalid data type' unless check_for_num num
28
+ return [num, 1] if other.empty?
29
+ denom, other = find_next_value other
30
+ raise arg_err_build 1, other.size unless other.empty?
31
+ [num, denom]
32
+ end
33
+
34
+ def compare_value_arithmetic(other, oper)
35
+ raise arg_err_build 'at least 2', other.size if other.size < 2
36
+ other = convert_to_num other
37
+ result = other.each_cons(2).all? { |x, y| x.public_send oper, y }
38
+ result ? '#t' : '#f'
39
+ end
40
+
41
+ def convert_to_num(other)
42
+ other.each do |t|
43
+ raise 'Invalid data type' unless check_for_num t
44
+ end
45
+ other.map(&:to_num)
46
+ end
47
+
48
+ def divide_special_convert(other)
49
+ other = convert_to_num other
50
+ return [0] if other.size == 1 && other[0] == 0.0
51
+ other
52
+ end
53
+
54
+ def divide_number(a, b)
55
+ return a / b if (a / b).to_i.to_f == a / b.to_f
56
+ a / b.to_f
57
+ end
58
+ end
59
+
60
+ # Scheme numbers module
61
+ module SchemeNumbers
62
+ include SchemeNumbersHelper
63
+
64
+ def <(other)
65
+ compare_value_arithmetic other, '<'
66
+ end
67
+
68
+ def >(other)
69
+ compare_value_arithmetic other, '>'
70
+ end
71
+
72
+ def <=(other)
73
+ compare_value_arithmetic other, '<='
74
+ end
75
+
76
+ def >=(other)
77
+ compare_value_arithmetic other, '>='
78
+ end
79
+
80
+ def +(other)
81
+ other = convert_to_num other
82
+ other.reduce(0, :+)
83
+ end
84
+
85
+ def -(other)
86
+ return 0 if other.empty?
87
+ other = convert_to_num other
88
+ return -other[0] if other.size == 1
89
+ other[0] + other[1..-1].reduce(0, :-)
90
+ end
91
+
92
+ def *(other)
93
+ other = convert_to_num other
94
+ other.reduce(1, :*)
95
+ end
96
+
97
+ def /(other)
98
+ raise arg_err_build 'at least 1', 0 if other.empty?
99
+ other = divide_special_convert other
100
+ return (divide_number 1, other[0].to_num) if other.size == 1
101
+ other[1..-1].inject(other[0]) { |res, t| divide_number res, t }
102
+ end
103
+
104
+ def quotient(other)
105
+ raise arg_err_build 2, other.size if other.size != 2
106
+ x, y = convert_to_num other
107
+ result = divide_number x, y
108
+ result < 0 ? result.ceil : result.floor
109
+ end
110
+
111
+ def remainder(other)
112
+ raise arg_err_build 2, other.size if other.size != 2
113
+ x, y = convert_to_num other
114
+ (x.abs % y.abs) * (x / x.abs)
115
+ end
116
+
117
+ def modulo(other)
118
+ raise arg_err_build 2, other.size if other.size != 2
119
+ x, y = convert_to_num other
120
+ x.modulo y
121
+ end
122
+
123
+ def numerator(other)
124
+ raise arg_err_build 1, 0 if other.empty?
125
+ other = num_denom_helper other
126
+ result = (get_num_denom other)[0]
127
+ raise 'Invalid data type' unless check_for_num result
128
+ result.to_num
129
+ end
130
+
131
+ def denominator(other)
132
+ raise arg_err_build 1, 0 if other.empty?
133
+ other = num_denom_helper other
134
+ result = (get_num_denom other)[1]
135
+ raise 'Invalid data type' unless check_for_num result
136
+ result.to_num
137
+ end
138
+
139
+ def abs(other)
140
+ (get_one_arg_function other).abs
141
+ end
142
+
143
+ def add1(other)
144
+ (get_one_arg_function other) + 1
145
+ end
146
+
147
+ def sub1(other)
148
+ (get_one_arg_function other) - 1
149
+ end
150
+
151
+ def min(other)
152
+ raise arg_err_build 'at least 1', 0 if other.empty?
153
+ other = convert_to_num other
154
+ other.min
155
+ end
156
+
157
+ def max(other)
158
+ raise arg_err_build 'at least 1', 0 if other.empty?
159
+ other = convert_to_num other
160
+ other.max
161
+ end
162
+ end
@@ -1,5 +1,5 @@
1
1
  module Lisp
2
2
  module Interpreter
3
- VERSION = '0.4.0'.freeze
3
+ VERSION = '0.4.1'.freeze
4
4
  end
5
5
  end
@@ -9,8 +9,7 @@ RSpec.describe Lisp::Interpreter do
9
9
  @p.parse('(define y 0.999)')
10
10
  @msg =
11
11
  {
12
- 'zero_div' => 'divided by 0',
13
- 'inv_type' => 'Invalid data type'
12
+ 'zero_div' => 'divided by 0'
14
13
  }
15
14
 
16
15
  def car_cdr_err(got, fn)
@@ -43,19 +42,19 @@ RSpec.describe Lisp::Interpreter do
43
42
 
44
43
  context 'incorrect argument type' do
45
44
  it 'throws error when <number> is expected' do
46
- expect(@p.parse('(+ #t)')).to eq @msg['inv_type']
45
+ expect(@p.parse('(+ #t)')).to eq type_err '<number>', '<boolean>'
47
46
  end
48
47
 
49
48
  it 'throws error when <string> is expected' do
50
- expect(@p.parse('(string-length 1)')).to eq @msg['inv_type']
49
+ expect(@p.parse('(substring 1)')).to eq arg_err_build '[2, 3]', '1'
51
50
  end
52
51
 
53
52
  it 'throws error when <boolean> is expected' do
54
- expect(@p.parse('(not \'apple)')).to eq @msg['inv_type']
53
+ expect(@p.parse('(not \'apple)')).to eq type_err '<boolean>', '<quote>'
55
54
  end
56
55
 
57
56
  it 'throws error when <list> is expected' do
58
- expect(@p.parse('(length "not list")')).to eq @msg['inv_type']
57
+ expect(@p.parse('(length "str")')).to eq type_err '<list>', '<string>'
59
58
  end
60
59
  end
61
60
  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.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zaki Petrov
@@ -79,7 +79,8 @@ 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/object.rb
82
+ - lib/lisp/interpreter/list.rb
83
+ - lib/lisp/interpreter/numbers.rb
83
84
  - lib/lisp/interpreter/parser.rb
84
85
  - lib/lisp/interpreter/run.rb
85
86
  - lib/lisp/interpreter/strings.rb
@@ -87,7 +88,6 @@ files:
87
88
  - lib/lisp/interpreter/validator.rb
88
89
  - lib/lisp/interpreter/value_finder.rb
89
90
  - lib/lisp/interpreter/version.rb
90
- - lisp-interpreter-0.3.5.gem
91
91
  - lisp-interpreter.gemspec
92
92
  - spec/lisp/interpreter_spec.rb
93
93
  - spec/lisp/test.scm
@@ -1,66 +0,0 @@
1
- # redefine method in Object class
2
- class Object
3
- def number?
4
- to_f.to_s == to_s || to_i.to_s == to_s
5
- end
6
-
7
- def to_num
8
- return to_f if to_f.to_s == to_s
9
- return to_i if to_i.to_s == to_s
10
- end
11
-
12
- def character?
13
- return true if self == '#\space'
14
- (start_with? '#\\') && (('a'..'z').to_a.include? self[2]) && size == 3
15
- end
16
-
17
- def string?
18
- return false unless self.class == String
19
- (start_with? '"') && (end_with? '"') && (size != 1)
20
- end
21
-
22
- def list?
23
- return false if size < 3
24
- check_for_list
25
- end
26
-
27
- def pair?
28
- res = object_split if is_a? String
29
- res = to_a if is_a? Array
30
- return true if res[-3] == '.'
31
- list? && !res[2..-2].empty?
32
- end
33
-
34
- def quote?
35
- return true if start_with? '\''
36
- false
37
- end
38
-
39
- def boolean?
40
- ['#t', '#f'].include? self
41
- end
42
-
43
- def type
44
- return 'list' if list?
45
- return 'pair' if pair?
46
- return 'string' if string?
47
- return 'number' if number?
48
- return 'character' if character?
49
- return 'boolean' if boolean?
50
- 'quote'
51
- end
52
-
53
- private
54
-
55
- def object_split
56
- result = to_s.split(/(\(|\)|\.)|\ /)
57
- result.delete('')
58
- result
59
- end
60
-
61
- def check_for_list
62
- res = to_a if is_a? Array
63
- res = object_split if is_a? String
64
- res[0..1].join == '\'(' && res[-1] == ')' && res[-3] != '.'
65
- end
66
- end
Binary file