lisp-interpreter 0.4.1 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d0691fe861df7ee5e54aac3b2f291df8e517a48d
4
- data.tar.gz: d370f3810b7e2e9caa9af9372f3ac2cc2ea1601f
3
+ metadata.gz: 1c06307db17d9007ce246997ac2100a2ac99ba95
4
+ data.tar.gz: 97d7681eb86cee8dc7090d70f1520d82e3eb3b6e
5
5
  SHA512:
6
- metadata.gz: 16869c9165eaebbd985f3c866f25fdd0c55f18f21bd13c841b6aac63f6217134ef0464ee4962770088b13442bceaada40c1e69e371911cf5d316c462b3a60bb1
7
- data.tar.gz: 31711dfa5b59c031d06aa2e67c4b68a5f3edd0cf41e02a88b83505d2e2ba5c9490ddce51a022b55a888de9617bb054ae1d638583c31047d3ef5fbf2712c7c470
6
+ metadata.gz: 4eaa3515460cf21508cb83f5d4d68a91631c30a9d4b1c51f7693f1831c83e81454ac531acacbd047a0e26bef4b7ea00b4bb0f370f1b161dfce0796043b143b76
7
+ data.tar.gz: 6a94f764325de0b5bf3693ea15f1df0a0aa250beab7654d017e6d3020934b5f4ab8d39e4f6746b13fa866569ef29012d68bf23ce856751ab14cb4bafc073a42e
data/README.md CHANGED
@@ -130,25 +130,45 @@ list and pairs:
130
130
 
131
131
  (foldr cons '() '(1 2 3 4 5)); (1 2 3 4 5)
132
132
 
133
- (filter (<= 3) '(1 2 3 4 5)); (1 2 3)
133
+ (filter (lambda (x) (<= x 3)) '(1 2 3 4 5)); (1 2 3)
134
134
 
135
- (member 2 (list 1 2 3 4)); (2 3 4
135
+ (member 2 (list 1 2 3 4)); (2 3 4)
136
136
 
137
137
  functions and procedures:
138
138
 
139
- (lambda (x) (* 2 x)); <Proc>
139
+ (lambda (x) (* 2 x)); <#Closure>
140
140
 
141
141
  ((lambda (x) (* 2 x)) 5); 10
142
142
 
143
143
  (apply + '(1 2 3)); 6
144
144
 
145
145
  ((compose fn1 fn2) val); (fn1 (fn2 val))
146
+
147
+ (compose fn1 fn2); #<Closure>
148
+
149
+ errors:
150
+
151
+ (+ 1 2 #t); "Invalid data type, expected <number> got <boolean>"
152
+
153
+ (string-length 123); "Invalid data type, expected <string> got <number>"
154
+
155
+ (string-join "SAMPLE"); "Invalid data type, expected <list> got <string>"
156
+
157
+ (substring "sample"); "Incorrect number of arguments, expected [2, 3] got 1"
158
+
159
+ (x); "x is not a function"
160
+
161
+ x; "Unbound symbol x"
146
162
 
147
163
  other:
148
164
 
149
- (define x 5) ; 5
165
+ (define x 5); 5
166
+
167
+ (define x (lambda (x) (* 2 x))); <#Closure>
150
168
 
151
- (define (even? x) (if (equal? (remainder x 2) 0) #t #f))
169
+ (define (even? x) (if (equal? (remainder x 2) 0) #t #f)); <#Closure>
170
+
171
+ (define map foldl); <Function foldl>
152
172
 
153
173
  (even? 4); #t
154
174
 
@@ -13,7 +13,7 @@ module ErrorMessages
13
13
  end
14
14
 
15
15
  def no_procedure_build(name)
16
- 'No procedure found ' + name.to_s
16
+ name.to_s + ' is not function'
17
17
  end
18
18
 
19
19
  def unbound_symbol_err(symbol)
@@ -71,7 +71,8 @@ module Optimize
71
71
  value = value.to_s unless value.is_a? Array
72
72
  value = calc_input_val ['(', t, *value, ')']
73
73
  end
74
- value
74
+ is_arr = value.is_a? Array
75
+ is_arr ? value[0] : value
75
76
  end
76
77
 
77
78
  def build_compose_expr(funcs)
@@ -111,7 +111,7 @@ class Tokenizer
111
111
 
112
112
  def check_car_cdr(arr)
113
113
  result = arr[1].match(/c[ad]{2,}r/)
114
- raise arr[1].to_s + ' is not a function' if result.nil?
114
+ raise no_procedure_build arr[1].to_s if result.nil?
115
115
  car_cdr_infinite arr
116
116
  end
117
117
 
@@ -140,7 +140,7 @@ class Tokenizer
140
140
  end
141
141
 
142
142
  def validate_call_method(m_name)
143
- raise m_name.to_s + ' is not a function' if valid_var m_name.to_s
143
+ raise no_procedure_build m_name.to_s if valid_var m_name.to_s
144
144
  end
145
145
 
146
146
  def call_predefined_method(m_name, arr)
@@ -1,5 +1,5 @@
1
1
  module Lisp
2
2
  module Interpreter
3
- VERSION = '0.4.1'.freeze
3
+ VERSION = '0.4.2'.freeze
4
4
  end
5
5
  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.1
4
+ version: 0.4.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zaki Petrov
@@ -79,11 +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/list.rb
83
- - lib/lisp/interpreter/numbers.rb
84
82
  - lib/lisp/interpreter/parser.rb
85
83
  - lib/lisp/interpreter/run.rb
86
- - lib/lisp/interpreter/strings.rb
87
84
  - lib/lisp/interpreter/tokenizer.rb
88
85
  - lib/lisp/interpreter/validator.rb
89
86
  - lib/lisp/interpreter/value_finder.rb
@@ -1,183 +0,0 @@
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
@@ -1,162 +0,0 @@
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,135 +0,0 @@
1
- # Helper functions for SchemeStrings
2
- module SchemeStringsHelper
3
- def substring_builder(str, from, to)
4
- result = (str[1..-2])[from..(to.nil? ? -1 : to - 1)]
5
- return '""' if result.nil?
6
- '"' + result + '"'
7
- end
8
-
9
- def find_delimeter(other)
10
- return ' ' if other.nil?
11
- other[1..-2]
12
- end
13
-
14
- def build_as_string_helper(other, idx)
15
- value = other[0..idx].join(' ').gsub('( ', '(').gsub(' )', ')')
16
- [value, other[idx + 1..-1]]
17
- end
18
-
19
- def build_next_value_as_string(other)
20
- idx = find_idx_for_list other
21
- if other[0] == '('
22
- build_as_string_helper other, idx
23
- elsif other[0..1].join == '\'('
24
- [(get_raw_value other[0..idx]), other[idx + 1..-1]]
25
- else
26
- [other[0], other[1..-1]]
27
- end
28
- end
29
-
30
- def build_character(char)
31
- '#\\' + (char == ' ' ? 'space' : char)
32
- end
33
-
34
- def remove_carriage(str)
35
- str = str[1..-2]
36
- str.gsub('\n', '').gsub('\r', '').gsub('\t', '').strip.squeeze(' ')
37
- end
38
-
39
- def arg_function_validator(other, vars = 1)
40
- raise arg_err_build other.size, vars if other.size != vars
41
- result = other[0..vars - 1].all? { |v| check_for_string v }
42
- raise 'Invalid data type' unless result
43
- result
44
- end
45
-
46
- def string_join_helper(other, dilimeter)
47
- values = split_list_as_string other.to_s
48
- delim_result = find_delimeter dilimeter
49
- '"' + (values.join delim_result) + '"'
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
56
- end
57
-
58
- # Scheme numbers module
59
- module SchemeStrings
60
- include SchemeStringsHelper
61
- def substring(other)
62
- raise arg_err_build '[2, 3]', other.size unless other.size.between? 2, 3
63
- str, from, to = other
64
- arg_function_validator [str]
65
- valid = (check_for_num from) && (to.nil? || (check_for_num to))
66
- raise 'Incorrect parameter type' unless valid
67
- substring_builder str, from.to_num, to.to_num
68
- end
69
-
70
- def string?(other)
71
- raise arg_err_build 1, other.size if other.size != 1
72
- result = check_for_string other[0].to_s
73
- result ? '#t' : '#f'
74
- end
75
-
76
- def strlen(other)
77
- arg_function_validator other
78
- other[0][1..-2].length
79
- end
80
-
81
- def strupcase(other)
82
- arg_function_validator other
83
- other[0].upcase
84
- end
85
-
86
- def strdowncase(other)
87
- arg_function_validator other
88
- other[0].downcase
89
- end
90
-
91
- def strcontains(other)
92
- arg_function_validator other, 2
93
- result = other[0][1..-2].include? other[1][1..-2]
94
- result ? '#t' : '#f'
95
- end
96
-
97
- def strsplit(other)
98
- arg_function_validator other
99
- str = remove_carriage other[0]
100
- result = str.split(' ').map { |s| '"' + s + '"' }
101
- build_list result
102
- end
103
-
104
- def strlist(other)
105
- arg_function_validator other
106
- result = other[0][1..-2].chars.map { |c| build_character c }
107
- build_list result
108
- end
109
-
110
- def strreplace(other)
111
- arg_function_validator other, 3
112
- str, to_replace, replace_with = other.map { |t| t[1..-2] }
113
- '"' + (str.gsub to_replace, replace_with) + '"'
114
- end
115
-
116
- def strprefix(other)
117
- arg_function_validator other, 2
118
- str, to_check = other.map { |t| t[1..-2] }
119
- result = str.start_with? to_check
120
- result ? '#t' : '#f'
121
- end
122
-
123
- def strsufix(other)
124
- arg_function_validator other, 2
125
- str, to_check = other.map { |t| t[1..-2] }
126
- result = str.end_with? to_check
127
- result ? '#t' : '#f'
128
- end
129
-
130
- def strjoin(other)
131
- strjoin_validate other
132
- arg_function_validator [other[1]] if other.size == 2
133
- string_join_helper other[0], other[1]
134
- end
135
- end