code-ruby 1.5.6 → 1.6.0

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.
@@ -52,7 +52,7 @@ class Code
52
52
  end
53
53
 
54
54
  def right_statement
55
- OrKeyword
55
+ Statement
56
56
  end
57
57
 
58
58
  def operator
@@ -19,7 +19,7 @@ class Code
19
19
  str("<")
20
20
  end
21
21
 
22
- def exclamation_point
22
+ def exclamation_mark
23
23
  str("!")
24
24
  end
25
25
 
@@ -32,9 +32,10 @@ class Code
32
32
  end
33
33
 
34
34
  def operator
35
- (equal << equal << equal) | (equal << equal) |
36
- (lesser << equal << greater) | (exclamation_point << equal) |
37
- (equal << tilde) | (tilde << equal) | (exclamation_point << tilde)
35
+ (exclamation_mark << equal << equal) | (equal << equal << equal) |
36
+ (equal << equal) | (lesser << equal << greater) |
37
+ (exclamation_mark << equal) | (equal << tilde) | (tilde << equal) |
38
+ (exclamation_mark << tilde)
38
39
  end
39
40
  end
40
41
  end
@@ -51,6 +51,10 @@ class Code
51
51
  str("elsif")
52
52
  end
53
53
 
54
+ def elsunless_keyword
55
+ str("elsunless")
56
+ end
57
+
54
58
  def else_keyword
55
59
  str("else")
56
60
  end
@@ -76,8 +80,9 @@ class Code
76
80
  statement.aka(:first_statement) << body.aka(:first_body) <<
77
81
  (
78
82
  (
79
- elsif_keyword.aka(:operator) << whitespace <<
80
- statement.aka(:statement) << body.aka(:body)
83
+ (elsif_keyword | elsunless_keyword).aka(
84
+ :operator
85
+ ) << whitespace << statement.aka(:statement) << body.aka(:body)
81
86
  ) |
82
87
  (
83
88
  else_keyword << whitespace <<
@@ -99,7 +99,47 @@ class Code
99
99
  str("else")
100
100
  end
101
101
 
102
- def special_character
102
+ def while_keyword
103
+ str("while")
104
+ end
105
+
106
+ def until_keyword
107
+ str("until")
108
+ end
109
+
110
+ def if_keyword
111
+ str("if")
112
+ end
113
+
114
+ def unless_keyword
115
+ str("unless")
116
+ end
117
+
118
+ def elsunless_keyword
119
+ str("elsunless")
120
+ end
121
+
122
+ def true_keyword
123
+ str("true")
124
+ end
125
+
126
+ def false_keyword
127
+ str("false")
128
+ end
129
+
130
+ def nothing_keyword
131
+ str("nothing")
132
+ end
133
+
134
+ def exclamation_mark
135
+ str("!")
136
+ end
137
+
138
+ def question_mark
139
+ str("?")
140
+ end
141
+
142
+ def reserved_character
103
143
  ampersand | equal | pipe | dot | colon | comma | space | newline |
104
144
  opening_curly_bracket | closing_curly_bracket | opening_parenthesis |
105
145
  closing_parenthesis | opening_square_bracket |
@@ -108,19 +148,27 @@ class Code
108
148
  end
109
149
 
110
150
  def character
111
- special_character.absent << any
151
+ reserved_character.absent << any
112
152
  end
113
153
 
114
154
  def separator
115
- special_character | any.absent
155
+ reserved_character | any.absent
156
+ end
157
+
158
+ def special_characters
159
+ exclamation_mark | question_mark
160
+ end
161
+
162
+ def keyword
163
+ do_keyword | begin_keyword | end_keyword | while_keyword |
164
+ until_keyword | if_keyword | elsif_keyword | else_keyword |
165
+ unless_keyword | elsunless_keyword | true_keyword | false_keyword |
166
+ nothing_keyword
116
167
  end
117
168
 
118
169
  def root
119
- (do_keyword << separator).absent << (
120
- begin_keyword << separator
121
- ).absent << (else_keyword << separator).absent <<
122
- (elsif_keyword << separator).absent <<
123
- (end_keyword << separator).absent << character.repeat(1)
170
+ (keyword << separator).absent << special_characters.absent <<
171
+ character.repeat(1)
124
172
  end
125
173
  end
126
174
  end
@@ -3,7 +3,7 @@
3
3
  class Code
4
4
  class Parser
5
5
  class Negation < Language
6
- def exclamation_point
6
+ def exclamation_mark
7
7
  str("!")
8
8
  end
9
9
 
@@ -16,7 +16,7 @@ class Code
16
16
  end
17
17
 
18
18
  def operator
19
- exclamation_point | tilde | plus
19
+ exclamation_mark | tilde | plus
20
20
  end
21
21
 
22
22
  def negation
data/lib/code.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Code
4
- GLOBALS = %i[context error input object output source object].freeze
4
+ GLOBALS = %i[context error input object output source].freeze
5
5
  DEFAULT_TIMEOUT = 0
6
6
 
7
7
  def initialize(
@@ -24,7 +24,6 @@ RSpec.describe Code::Object::Decimal do
24
24
  %w[-1.123.floor(2) -1.13],
25
25
  %w[1.1.round 1],
26
26
  %w[1.123.round(2) 1.12],
27
- %w[1.2.clone 1.2],
28
27
  %w[0.0.zero? true],
29
28
  %w[1.2.truncate 1],
30
29
  %w[1.234.truncate(2) 1.23],
@@ -3,77 +3,81 @@
3
3
  require "spec_helper"
4
4
 
5
5
  RSpec.describe Code::Object::Http do
6
- VERBS = %w[get head post put delete options trace patch].freeze
6
+ def self.verbs
7
+ %w[get head post put delete options trace patch]
8
+ end
7
9
 
8
- RESPONSE_CODES = {
9
- continue: 100,
10
- switching_protocols: 101,
11
- processing: 102,
12
- early_hints: 103,
13
- ok: 200,
14
- created: 201,
15
- accepted: 202,
16
- non_authoritative_information: 203,
17
- no_content: 204,
18
- reset_content: 205,
19
- partial_content: 206,
20
- multi_status: 207,
21
- already_reported: 208,
22
- im_used: 226,
23
- multiple_choices: 300,
24
- moved_permanently: 301,
25
- found: 302,
26
- see_other: 303,
27
- not_modified: 304,
28
- use_proxy: 305,
29
- reserved: 306,
30
- temporary_redirect: 307,
31
- permanent_redirect: 308,
32
- bad_request: 400,
33
- unauthorized: 401,
34
- payment_required: 402,
35
- forbidden: 403,
36
- not_found: 404,
37
- method_not_allowed: 405,
38
- not_acceptable: 406,
39
- proxy_authentication_required: 407,
40
- request_timeout: 408,
41
- conflict: 409,
42
- gone: 410,
43
- length_required: 411,
44
- precondition_failed: 412,
45
- request_entity_too_large: 413,
46
- request_uri_too_long: 414,
47
- unsupported_media_type: 415,
48
- requested_range_not_satisfiable: 416,
49
- expectation_failed: 417,
50
- misdirected_request: 421,
51
- unprocessable_entity: 422,
52
- locked: 423,
53
- failed_dependency: 424,
54
- too_early: 425,
55
- upgrade_required: 426,
56
- precondition_required: 428,
57
- too_many_requests: 429,
58
- request_header_fields_too_large: 431,
59
- unavailable_for_legal_reasons: 451,
60
- internal_server_error: 500,
61
- not_implemented: 501,
62
- bad_gateway: 502,
63
- service_unavailable: 503,
64
- gateway_timeout: 504,
65
- http_version_not_supported: 505,
66
- variant_also_negotiates: 506,
67
- insufficient_storage: 507,
68
- loop_detected: 508,
69
- bandwidth_limit_exceeded: 509,
70
- not_extended: 510,
71
- network_authentication_required: 511
72
- }.freeze
10
+ def self.response_codes
11
+ {
12
+ continue: 100,
13
+ switching_protocols: 101,
14
+ processing: 102,
15
+ early_hints: 103,
16
+ ok: 200,
17
+ created: 201,
18
+ accepted: 202,
19
+ non_authoritative_information: 203,
20
+ no_content: 204,
21
+ reset_content: 205,
22
+ partial_content: 206,
23
+ multi_status: 207,
24
+ already_reported: 208,
25
+ im_used: 226,
26
+ multiple_choices: 300,
27
+ moved_permanently: 301,
28
+ found: 302,
29
+ see_other: 303,
30
+ not_modified: 304,
31
+ use_proxy: 305,
32
+ reserved: 306,
33
+ temporary_redirect: 307,
34
+ permanent_redirect: 308,
35
+ bad_request: 400,
36
+ unauthorized: 401,
37
+ payment_required: 402,
38
+ forbidden: 403,
39
+ not_found: 404,
40
+ method_not_allowed: 405,
41
+ not_acceptable: 406,
42
+ proxy_authentication_required: 407,
43
+ request_timeout: 408,
44
+ conflict: 409,
45
+ gone: 410,
46
+ length_required: 411,
47
+ precondition_failed: 412,
48
+ request_entity_too_large: 413,
49
+ request_uri_too_long: 414,
50
+ unsupported_media_type: 415,
51
+ requested_range_not_satisfiable: 416,
52
+ expectation_failed: 417,
53
+ misdirected_request: 421,
54
+ unprocessable_entity: 422,
55
+ locked: 423,
56
+ failed_dependency: 424,
57
+ too_early: 425,
58
+ upgrade_required: 426,
59
+ precondition_required: 428,
60
+ too_many_requests: 429,
61
+ request_header_fields_too_large: 431,
62
+ unavailable_for_legal_reasons: 451,
63
+ internal_server_error: 500,
64
+ not_implemented: 501,
65
+ bad_gateway: 502,
66
+ service_unavailable: 503,
67
+ gateway_timeout: 504,
68
+ http_version_not_supported: 505,
69
+ variant_also_negotiates: 506,
70
+ insufficient_storage: 507,
71
+ loop_detected: 508,
72
+ bandwidth_limit_exceeded: 509,
73
+ not_extended: 510,
74
+ network_authentication_required: 511
75
+ }
76
+ end
73
77
 
74
- VERBS.each do |verb|
78
+ verbs.each do |verb|
75
79
  describe ".#{verb}" do
76
- RESPONSE_CODES.each do |status, code|
80
+ response_codes.each do |status, code|
77
81
  it "returns #{code} as code and #{status} as status" do
78
82
  expect(Code.evaluate(<<~INPUT)).to eq(Code.evaluate(<<~OUTPUT))
79
83
  response = Http.#{verb}("https://httpbin.org/status/#{code}")
@@ -24,7 +24,6 @@ RSpec.describe Code::Object::Integer do
24
24
  %w[1234.floor(-2) 1200],
25
25
  %w[1.round 1],
26
26
  %w[1234.round(-2) 1200],
27
- %w[1.clone 1],
28
27
  %w[0.zero? true],
29
28
  %w[1.truncate 1],
30
29
  %w[1234.truncate(-2) 1200],
@@ -8,8 +8,8 @@ RSpec.describe Code::Parser::IfModifier do
8
8
  ["1 if false", "nothing"],
9
9
  ["1 unless true", "nothing"],
10
10
  ["1 unless false", "1"],
11
- ["a = 0 a += 1 while a < 10 a", "10"],
12
- ["a = 0 a += 1 until a > 10 a", "11"]
11
+ ["a = 0 (a += 1) while a < 10 a", "10"],
12
+ ["a = 0 (a += 1) until a > 10 a", "11"]
13
13
  ].each do |input, expected|
14
14
  it "#{input} == #{expected}" do
15
15
  expect(Code.evaluate(input)).to eq(Code.evaluate(expected))
data/spec/code_spec.rb CHANGED
@@ -4,136 +4,146 @@ require "spec_helper"
4
4
 
5
5
  RSpec.describe Code do
6
6
  (
7
- %w[
8
- {}.zero?
9
- {}.any?
10
- {}.many?
11
- 1.zero?
12
- 1.any?
13
- 1.many?
14
- 1.0.zero?
15
- 1.0.any?
16
- 1.0.many?
17
- [].zero?
18
- [].any?
19
- [].many?
20
- Base64
21
- Base64.new
22
- Smtp
23
- Smtp.new
24
- Time.monday?
25
- Time.tuesday?
26
- Time.wednesday?
27
- Time.thursday?
28
- Time.friday?
29
- Time.saturday?
30
- Time.sunday?
31
- Time.now.monday?
32
- Time.now.tuesday?
33
- Time.now.wednesday?
34
- Time.now.thursday?
35
- Time.now.friday?
36
- Time.now.saturday?
37
- Time.now.sunday?
38
- Time.now.second
39
- Time.now.seconds
40
- Time.now.minute
41
- Time.now.minutes
42
- Time.now.hour
43
- Time.now.hours
44
- Time.now.day
45
- Time.now.days
46
- Time.now.month
47
- Time.now.months
48
- Time.now.year
49
- Time.now.years
50
- Time.second
51
- Time.seconds
52
- Time.minute
53
- Time.minutes
54
- Time.hour
55
- Time.hours
56
- Time.day
57
- Time.days
58
- Time.month
59
- Time.months
60
- Time.year
61
- Time.years
62
- 1.day.ago
63
- 1.day.from_now
64
- 1.hour.ago
65
- 1.hour.from_now
66
- 2.days.ago
67
- 2.days.from_now
68
- 2.hours.ago
69
- 2.hours.ago.hour
70
- 2.hours.from_now
71
- 2.hours.from_now.hour
72
- Time.hour
73
- Date.hour
74
- Boolean.new
75
- Boolean.new(true)
76
- Boolean.new(false)
77
- Class.new
78
- Class.new(Boolean)
79
- Class.new(Class)
80
- Context.new
81
- Context.new(a:1)
82
- Date.new
83
- Date.new.hour
84
- Date.new("2024-03-05")
85
- Date.new("2024-03-05").hour
86
- Date.today
87
- Date.yesterday
88
- Date.tomorrow
89
- Date.tomorrow.hour
90
- Decimal.new
91
- Decimal.new(0)
92
- Decimal.new(1.2)
93
- Dictionary.new
94
- Dictionary.new(a:1)
95
- Duration.new
96
- Duration.new(1.day)
97
- Duration.new("P1D")
98
- Function.new
99
- Integer.new
100
- Integer.new(0)
101
- Integer.new(1)
102
- Integer.new(1.2)
103
- List.new
104
- List.new([])
105
- List.new([1,2])
106
- Nothing.new
107
- Nothing.new(1)
108
- Object.new
109
- Object.new(1)
110
- Range.new
111
- Range.new(1,2)
112
- Range.new(-1)
113
- Range.new(1,2,exclude_end:false)
114
- Range.new(1,2,exclude_end:true)
115
- String.new
116
- String.new(:hello)
117
- Time.new
118
- Time.new("2024-03-05.06:10:59.UTC")
119
- Time.now
120
- Time.tomorrow
121
- Time.yesterday
122
- Time.tomorrow
123
- Code.new
124
- Parameter.new
125
- IdentifierList.new
126
- IdentifierList.new([])
127
- Time.new(nothing).before?
128
- Html.link_to
129
- Html.link_to('/')
130
- Html.link_to('Home','/')
131
- Json.parse('1')
132
- Json.parse('[]')
133
- Json.parse('{}')
134
- Json.parse('random-string')
135
- {}["".to_string]
136
- ] + ["Time.hour >= 6 and Time.hour <= 23"]
7
+ [
8
+ "{ a: 1, b: 2 }.transform_values { |key| key.upcase }",
9
+ "{ a: { b: [1, 2, 3, 4] } }.dig(:a, :b, 2)",
10
+ "{ a: 1, b: 2 }.transform_values { |key, value, index| index * 2 }",
11
+ "{ a: 1, b: 2 }.transform_values { |key, value, index, dictionary| dictionary.a }",
12
+ "sum = (a, b: 2) => { a + b } sum(1)",
13
+ "Object.new !== Object.new"
14
+ ] +
15
+ %w[
16
+ :abc.size
17
+ Date.new.change
18
+ {}.zero?
19
+ {}.any?
20
+ {}.many?
21
+ 1.zero?
22
+ 1.any?
23
+ 1.many?
24
+ 1.0.zero?
25
+ 1.0.any?
26
+ 1.0.many?
27
+ [].zero?
28
+ [].any?
29
+ [].many?
30
+ Base64
31
+ Base64.new
32
+ Smtp
33
+ Smtp.new
34
+ Time.monday?
35
+ Time.tuesday?
36
+ Time.wednesday?
37
+ Time.thursday?
38
+ Time.friday?
39
+ Time.saturday?
40
+ Time.sunday?
41
+ Time.now.monday?
42
+ Time.now.tuesday?
43
+ Time.now.wednesday?
44
+ Time.now.thursday?
45
+ Time.now.friday?
46
+ Time.now.saturday?
47
+ Time.now.sunday?
48
+ Time.now.second
49
+ Time.now.seconds
50
+ Time.now.minute
51
+ Time.now.minutes
52
+ Time.now.hour
53
+ Time.now.hours
54
+ Time.now.day
55
+ Time.now.days
56
+ Time.now.month
57
+ Time.now.months
58
+ Time.now.year
59
+ Time.now.years
60
+ Time.second
61
+ Time.seconds
62
+ Time.minute
63
+ Time.minutes
64
+ Time.hour
65
+ Time.hours
66
+ Time.day
67
+ Time.days
68
+ Time.month
69
+ Time.months
70
+ Time.year
71
+ Time.years
72
+ 1.day.ago
73
+ 1.day.from_now
74
+ 1.hour.ago
75
+ 1.hour.from_now
76
+ 2.days.ago
77
+ 2.days.from_now
78
+ 2.hours.ago
79
+ 2.hours.ago.hour
80
+ 2.hours.from_now
81
+ 2.hours.from_now.hour
82
+ Time.hour
83
+ Date.hour
84
+ Boolean.new
85
+ Boolean.new(true)
86
+ Boolean.new(false)
87
+ Class.new
88
+ Class.new(Boolean)
89
+ Class.new(Class)
90
+ Context.new
91
+ Context.new(a:1)
92
+ Date.new
93
+ Date.new.hour
94
+ Date.new("2024-03-05")
95
+ Date.new("2024-03-05").hour
96
+ Date.today
97
+ Date.yesterday
98
+ Date.tomorrow
99
+ Date.tomorrow.hour
100
+ Decimal.new
101
+ Decimal.new(0)
102
+ Decimal.new(1.2)
103
+ Dictionary.new
104
+ Dictionary.new(a:1)
105
+ Duration.new
106
+ Duration.new(1.day)
107
+ Duration.new("P1D")
108
+ Function.new
109
+ Integer.new
110
+ Integer.new(0)
111
+ Integer.new(1)
112
+ Integer.new(1.2)
113
+ List.new
114
+ List.new([])
115
+ List.new([1,2])
116
+ Nothing.new
117
+ Nothing.new(1)
118
+ Object.new
119
+ Object.new(1)
120
+ Range.new
121
+ Range.new(1,2)
122
+ Range.new(-1)
123
+ Range.new(1,2,exclude_end:false)
124
+ Range.new(1,2,exclude_end:true)
125
+ String.new
126
+ String.new(:hello)
127
+ Time.new
128
+ Time.new("2024-03-05.06:10:59.UTC")
129
+ Time.now
130
+ Time.tomorrow
131
+ Time.yesterday
132
+ Time.tomorrow
133
+ Code.new
134
+ Parameter.new
135
+ IdentifierList.new
136
+ IdentifierList.new([])
137
+ Time.new(nothing).before?
138
+ Html.link_to
139
+ Html.link_to('/')
140
+ Html.link_to('Home','/')
141
+ Json.parse('1')
142
+ Json.parse('[]')
143
+ Json.parse('{}')
144
+ Json.parse('random-string')
145
+ {}["".to_string]
146
+ ] + ["Time.hour >= 6 and Time.hour <= 23"]
137
147
  ).each { |input| it(input) { described_class.evaluate(input) } }
138
148
 
139
149
  [
@@ -258,8 +268,8 @@ RSpec.describe Code do
258
268
  ["Class(true, 1)", "Boolean"],
259
269
  ["Class.new(Boolean, Time)", "Boolean"],
260
270
  ["Class.new(Time, Boolean)", "Time"],
261
- ["Date(2024, 3, 2).to_string", ":2024-03-02"],
262
- ["Date(2024,3, 2).to_string", ":2024-03-02"],
271
+ ['Date("2024-3-2").to_string', ":2024-03-02"],
272
+ ['Date("2024-3-2").to_string', ":2024-03-02"],
263
273
  ["Decimal(1, :2)", "100"],
264
274
  ["Decimal(:1, 2)", "100.0"],
265
275
  ["Decimal.new(1, :2)", "100"],