code-ruby 3.1.2 → 4.0.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.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/bin/code +97 -20
- data/lib/code/concerns/shared.rb +331 -15
- data/lib/code/format.rb +15 -1
- data/lib/code/network.rb +87 -0
- data/lib/code/node/call.rb +79 -2
- data/lib/code/node/call_argument.rb +14 -0
- data/lib/code/node/code.rb +5 -4
- data/lib/code/node/function_parameter.rb +7 -4
- data/lib/code/node/list.rb +29 -1
- data/lib/code/object/base_64.rb +132 -6
- data/lib/code/object/boolean.rb +60 -0
- data/lib/code/object/class.rb +138 -2
- data/lib/code/object/code.rb +111 -3
- data/lib/code/object/context.rb +57 -1
- data/lib/code/object/cryptography.rb +63 -0
- data/lib/code/object/date.rb +13339 -462
- data/lib/code/object/decimal.rb +1725 -0
- data/lib/code/object/dictionary.rb +1790 -11
- data/lib/code/object/duration.rb +28 -0
- data/lib/code/object/function.rb +261 -23
- data/lib/code/object/global.rb +534 -1
- data/lib/code/object/html.rb +179 -7
- data/lib/code/object/http.rb +244 -14
- data/lib/code/object/ics.rb +75 -13
- data/lib/code/object/identifier_list.rb +17 -2
- data/lib/code/object/integer.rb +1937 -2
- data/lib/code/object/json.rb +75 -1
- data/lib/code/object/list.rb +3383 -10
- data/lib/code/object/nothing.rb +53 -0
- data/lib/code/object/number.rb +110 -0
- data/lib/code/object/parameter.rb +140 -0
- data/lib/code/object/range.rb +576 -14
- data/lib/code/object/smtp.rb +95 -12
- data/lib/code/object/string.rb +944 -3
- data/lib/code/object/super.rb +10 -1
- data/lib/code/object/time.rb +13358 -498
- data/lib/code/object/url.rb +65 -0
- data/lib/code/object.rb +543 -0
- data/lib/code/parser.rb +161 -24
- data/lib/code-ruby.rb +3 -0
- data/lib/code.rb +30 -3
- metadata +135 -84
- data/.github/dependabot.yml +0 -15
- data/.github/workflows/ci.yml +0 -38
- data/.gitignore +0 -30
- data/.node-version +0 -1
- data/.npm-version +0 -1
- data/.prettierignore +0 -2
- data/.rspec +0 -1
- data/.rubocop.yml +0 -140
- data/.ruby-version +0 -1
- data/.tool-versions +0 -3
- data/AGENTS.md +0 -43
- data/Gemfile +0 -22
- data/Gemfile.lock +0 -292
- data/Rakefile +0 -5
- data/bin/bundle +0 -123
- data/bin/bundle-audit +0 -31
- data/bin/bundler-audit +0 -31
- data/bin/dorian +0 -31
- data/bin/rspec +0 -31
- data/bin/rubocop +0 -31
- data/bin/test +0 -5
- data/code-ruby.gemspec +0 -34
- data/docs/precedence.txt +0 -36
- data/package-lock.json +0 -14
- data/package.json +0 -7
- data/spec/bin/code_spec.rb +0 -48
- data/spec/code/format_spec.rb +0 -153
- data/spec/code/node/call_spec.rb +0 -11
- data/spec/code/object/boolean_spec.rb +0 -18
- data/spec/code/object/cryptography_spec.rb +0 -25
- data/spec/code/object/decimal_spec.rb +0 -50
- data/spec/code/object/dictionary_spec.rb +0 -98
- data/spec/code/object/function_spec.rb +0 -268
- data/spec/code/object/http_spec.rb +0 -33
- data/spec/code/object/ics_spec.rb +0 -50
- data/spec/code/object/integer_spec.rb +0 -42
- data/spec/code/object/list_spec.rb +0 -22
- data/spec/code/object/nothing_spec.rb +0 -14
- data/spec/code/object/range_spec.rb +0 -23
- data/spec/code/object/string_spec.rb +0 -26
- data/spec/code/parser/boolean_spec.rb +0 -11
- data/spec/code/parser/chained_call_spec.rb +0 -16
- data/spec/code/parser/dictionary_spec.rb +0 -18
- data/spec/code/parser/function_spec.rb +0 -16
- data/spec/code/parser/group_spec.rb +0 -11
- data/spec/code/parser/if_modifier_spec.rb +0 -18
- data/spec/code/parser/list_spec.rb +0 -17
- data/spec/code/parser/number_spec.rb +0 -11
- data/spec/code/parser/string_spec.rb +0 -20
- data/spec/code/parser_spec.rb +0 -52
- data/spec/code/type_spec.rb +0 -21
- data/spec/code_spec.rb +0 -717
- data/spec/spec_helper.rb +0 -21
- data/spec/zeitwerk/loader_spec.rb +0 -7
data/docs/precedence.txt
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
Code
|
|
2
|
-
Statement
|
|
3
|
-
Splat
|
|
4
|
-
Class
|
|
5
|
-
While
|
|
6
|
-
If
|
|
7
|
-
IfModifier
|
|
8
|
-
OrKeyword
|
|
9
|
-
NotKeyword
|
|
10
|
-
Equal
|
|
11
|
-
Rescue
|
|
12
|
-
Ternary
|
|
13
|
-
Range
|
|
14
|
-
OrOperator
|
|
15
|
-
AndOperator
|
|
16
|
-
Equality
|
|
17
|
-
Greater
|
|
18
|
-
BitwiseOr
|
|
19
|
-
BitwiseAnd
|
|
20
|
-
Shift
|
|
21
|
-
Addition
|
|
22
|
-
Multiplication
|
|
23
|
-
Negation
|
|
24
|
-
ChainedCall
|
|
25
|
-
SquareBracket
|
|
26
|
-
UnaryMinus
|
|
27
|
-
Power
|
|
28
|
-
Function
|
|
29
|
-
Dictionary
|
|
30
|
-
List
|
|
31
|
-
String
|
|
32
|
-
Number
|
|
33
|
-
Boolean
|
|
34
|
-
Nothing
|
|
35
|
-
Group
|
|
36
|
-
Call
|
data/package-lock.json
DELETED
data/package.json
DELETED
data/spec/bin/code_spec.rb
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "open3"
|
|
4
|
-
require "spec_helper"
|
|
5
|
-
|
|
6
|
-
RSpec.describe "bin/code" do
|
|
7
|
-
let(:bin) { File.expand_path("../../bin/code", __dir__) }
|
|
8
|
-
let(:tmp_glob_dir) { File.expand_path("../tmp/code_glob", __dir__) }
|
|
9
|
-
|
|
10
|
-
after { FileUtils.rm_rf(tmp_glob_dir) }
|
|
11
|
-
|
|
12
|
-
it "formats input with -f" do
|
|
13
|
-
stdout, stderr, status = Open3.capture3(bin, "-f", "{a:1}")
|
|
14
|
-
|
|
15
|
-
expect(status.success?).to be(true)
|
|
16
|
-
expect(stderr).to eq("")
|
|
17
|
-
expect(stdout).to eq("{ a: 1 }")
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
it "formats quoted globbed files with -f" do
|
|
21
|
-
FileUtils.mkdir_p(File.join(tmp_glob_dir, "a"))
|
|
22
|
-
FileUtils.mkdir_p(File.join(tmp_glob_dir, "b"))
|
|
23
|
-
File.write(File.join(tmp_glob_dir, "a", "first.code"), "{a:1}")
|
|
24
|
-
File.write(File.join(tmp_glob_dir, "b", "second.code"), "{b:2}")
|
|
25
|
-
|
|
26
|
-
stdout, stderr, status =
|
|
27
|
-
Open3.capture3(bin, "-f", File.join(tmp_glob_dir, "**", "*.code"))
|
|
28
|
-
|
|
29
|
-
expect(status.success?).to be(true)
|
|
30
|
-
expect(stderr).to eq("")
|
|
31
|
-
expect(stdout).to eq("{ a: 1 }\n\n{ b: 2 }")
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
it "formats shell-expanded globbed files with -f" do
|
|
35
|
-
FileUtils.mkdir_p(File.join(tmp_glob_dir, "a"))
|
|
36
|
-
FileUtils.mkdir_p(File.join(tmp_glob_dir, "b"))
|
|
37
|
-
first = File.join(tmp_glob_dir, "a", "first.code")
|
|
38
|
-
second = File.join(tmp_glob_dir, "b", "second.code")
|
|
39
|
-
File.write(first, "{a:1}")
|
|
40
|
-
File.write(second, "{b:2}")
|
|
41
|
-
|
|
42
|
-
stdout, stderr, status = Open3.capture3(bin, "-f", first, second)
|
|
43
|
-
|
|
44
|
-
expect(status.success?).to be(true)
|
|
45
|
-
expect(stderr).to eq("")
|
|
46
|
-
expect(stdout).to eq("{ a: 1 }\n\n{ b: 2 }")
|
|
47
|
-
end
|
|
48
|
-
end
|
data/spec/code/format_spec.rb
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "spec_helper"
|
|
4
|
-
require "json"
|
|
5
|
-
|
|
6
|
-
RSpec.describe Code::Format do
|
|
7
|
-
describe ".format" do
|
|
8
|
-
[
|
|
9
|
-
%w[Time.now.second Time.now.second],
|
|
10
|
-
%w[{} {}],
|
|
11
|
-
["[]", "[]"],
|
|
12
|
-
%w["" ""],
|
|
13
|
-
%w[100000 100_000],
|
|
14
|
-
%w[1000000 1_000_000],
|
|
15
|
-
%w[1.0000000001 1.000_000_000_1],
|
|
16
|
-
["true || false", "true or false"],
|
|
17
|
-
["true && false", "true and false"],
|
|
18
|
-
["{a:1}", "{ a: 1 }"],
|
|
19
|
-
["{ :mobility: mobility }", "{ mobility: mobility }"],
|
|
20
|
-
['{ "hello": "world" }', "{ hello: :world }"],
|
|
21
|
-
['{ "hello" => "world" }', "{ hello: :world }"],
|
|
22
|
-
["[1,2,3]", "[1, 2, 3]"],
|
|
23
|
-
["[1, 2, 3].select { |n| n.even? }", "[1, 2, 3].select { |n| n.even? }"],
|
|
24
|
-
[
|
|
25
|
-
"if true 1 elsif false 2 else 3 end",
|
|
26
|
-
"if true\n 1\nelsif false\n 2\nelse\n 3\nend"
|
|
27
|
-
],
|
|
28
|
-
[
|
|
29
|
-
"if false 1 else if true 2 else 3 end",
|
|
30
|
-
"if false\n 1\nelse\n if true\n 2\n else\n 3\n end\nend"
|
|
31
|
-
],
|
|
32
|
-
[
|
|
33
|
-
"event[:uid].present? and event[:summary].present? and event[:starts_at].present? and event[:ends_at].present?",
|
|
34
|
-
"event[:uid].present?\n and event[:summary].present?\n and event[:starts_at].present?\n and event[:ends_at].present?"
|
|
35
|
-
],
|
|
36
|
-
[
|
|
37
|
-
"Html.p { \"x{Time.new(event.starts_at).format}y\" + \"{Time.new(event.ends_at).format}\" }",
|
|
38
|
-
"Html.p {\n \"x{Time.new(event.starts_at).format}y\"\n + \"{Time.new(event.ends_at).format}\"\n}"
|
|
39
|
-
],
|
|
40
|
-
[
|
|
41
|
-
"sum = (a, b: 2) => { a + b } sum(1)",
|
|
42
|
-
"sum = (a, b: 2) => {\n a + b\n}\n\nsum(1)"
|
|
43
|
-
],
|
|
44
|
-
[
|
|
45
|
-
"Http.post(\"https://api.openai.com/v1/chat/completions\", headers: { authorization: \"Bearer {open_ai_api_key}\", \"content-type\": \"application/json\" }, body: { model: model, messages: [{ role: \"system\", content: \"hello\" }, { role: \"user\", content: \"world\" }] }.to_json)",
|
|
46
|
-
"Http.post(\n \"https://api.openai.com/v1/chat/completions\",\n headers: {\n authorization: \"Bearer {open_ai_api_key}\",\n \"content-type\": \"application/json\"\n },\n body: {\n model: model,\n messages: [\n { role: :system, content: :hello },\n { role: :user, content: :world }\n ]\n }.to_json\n)"
|
|
47
|
-
],
|
|
48
|
-
[
|
|
49
|
-
"proxy_url = (url) => { \"{proxy_base_url}?{{ url: url, disposition: proxy_inline_disposition }.to_query}\" }",
|
|
50
|
-
"proxy_url = (url) => {\n \"{proxy_base_url}?\"\n + \"{{\n url: url,\n disposition: proxy_inline_disposition\n }.to_query}\"\n}"
|
|
51
|
-
],
|
|
52
|
-
[
|
|
53
|
-
"x = { content: \"you select the funniest tweets for a french \" + \"audience from the provided candidates. pick up to \" + \"{max_selected}. prioritize genuinely funny content\" + \" (jokes, memes, punchlines, absurd). avoid \" + \"politics/news/serious content. output only json.\" }",
|
|
54
|
-
"x = {\n content: \"you select the funniest tweets for a french \"\n + \"audience from the provided candidates. pick up to \"\n + \"{max_selected}. prioritize genuinely funny content\"\n + \" (jokes, memes, punchlines, absurd). avoid \"\n + \"politics/news/serious content. output only json.\"\n}"
|
|
55
|
-
],
|
|
56
|
-
[
|
|
57
|
-
"blocks << { title: \"hello world\", description: \"lorem ipsum dolor es sit\", position: 1 }",
|
|
58
|
-
"blocks << {\n title: \"hello world\",\n description: \"lorem ipsum dolor es sit\",\n position: 1\n}"
|
|
59
|
-
],
|
|
60
|
-
[
|
|
61
|
-
"query = { :mobility: mobility, :unit_organization_id: unit_organization_id, :limit: limit, :offset: offset }",
|
|
62
|
-
"query = {\n mobility: mobility,\n unit_organization_id: unit_organization_id,\n limit: limit,\n offset: offset\n}"
|
|
63
|
-
],
|
|
64
|
-
[
|
|
65
|
-
"sections << Html.join([Html.p { Html.b { \"{index + 1}. {title}\" } }, Html.p { query } if query.presence, Html.p { Html.a(href: link || inline_url) { :source } } if (link || inline_url), Html.p { Html.a(href: inline_url) { Html.img(src: inline_url, alt: title) } }, Html.p { Html.a(href: attachment_url) { \"télécharger\" } }].compact)",
|
|
66
|
-
"sections << Html.join(\n [\n Html.p { Html.b { \"{index + 1}. {title}\" } },\n Html.p { query } if query.presence,\n Html.p {\n Html.a(href: link or inline_url) { :source }\n } if (link or inline_url),\n Html.p {\n Html.a(href: inline_url) { Html.img(src: inline_url, alt: title) }\n },\n Html.p {\n Html.a(href: attachment_url) { \"télécharger\" }\n }\n ].compact\n)"
|
|
67
|
-
],
|
|
68
|
-
[
|
|
69
|
-
"safe = post.present? and !post[:over_18] and post[:post_hint] == :image and post[:url].to_string.strip.presence and (post[:url].to_string.strip.ends_with?(\".jpg\") or post[:url].to_string.strip.ends_with?(\".jpeg\") or post[:url].to_string.strip.ends_with?(\".png\") or post[:url].to_string.strip.include?(\"i.redd.it\"))",
|
|
70
|
-
"safe = post.present?\n and !post[:over_18]\n and post[:post_hint] == :image\n and post[:url].to_string.strip.presence\n and (\n post[:url].to_string.strip.ends_with?(\".jpg\")\n or post[:url].to_string.strip.ends_with?(\".jpeg\")\n or post[:url].to_string.strip.ends_with?(\".png\")\n or post[:url].to_string.strip.include?(\"i.redd.it\")\n)"
|
|
71
|
-
],
|
|
72
|
-
[
|
|
73
|
-
"items.each { |item, index| proxied_image_url = if image_url proxy_url(image_url) else nothing end }",
|
|
74
|
-
"items.each { |item, index|\n proxied_image_url = if image_url\n proxy_url(image_url)\n else\n nothing\n end\n}"
|
|
75
|
-
],
|
|
76
|
-
[
|
|
77
|
-
"lines << \"vacances scolaires france {zone} (prochains {months_ahead} mois) :\".downcase",
|
|
78
|
-
"lines << (\n \"vacances scolaires france {zone} (prochains \"\n + \"{months_ahead} mois) :\"\n).downcase"
|
|
79
|
-
],
|
|
80
|
-
[
|
|
81
|
-
"src = \"https://proxy.dorianmarie.com?\" + \"{{ url: src, disposition: :inline }.to_query}\" if src",
|
|
82
|
-
"src = (\n \"https://proxy.dorianmarie.com?\"\n + \"{{ url: src, disposition: :inline }.to_query}\"\n) if src"
|
|
83
|
-
],
|
|
84
|
-
[
|
|
85
|
-
"inline_image = image ? \"https://proxy.dorianmarie.com?\" + \"{inline_params.to_query}\" : nothing",
|
|
86
|
-
"inline_image = image ? (\n \"https://proxy.dorianmarie.com?\"\n + \"{inline_params.to_query}\"\n) : nothing"
|
|
87
|
-
]
|
|
88
|
-
].each do |input, expected|
|
|
89
|
-
it "formats #{input.inspect}" do
|
|
90
|
-
expect(described_class.format(Code.parse(input))).to eq(expected)
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
it "formats #{input.inspect} idempotently" do
|
|
94
|
-
formatted = described_class.format(Code.parse(input))
|
|
95
|
-
|
|
96
|
-
expect(described_class.format(Code.parse(formatted))).to eq(formatted)
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
|
|
100
|
-
it "round-trips parse and evaluation semantics for formatted code" do
|
|
101
|
-
input = "user = {name: :Dorian, age: 31} user.age"
|
|
102
|
-
formatted = described_class.format(Code.parse(input))
|
|
103
|
-
|
|
104
|
-
expect(Code.parse(formatted)).to be_present
|
|
105
|
-
expect(Code.evaluate(formatted)).to eq(Code.evaluate(input))
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
it "keeps grouped multiline receivers stable" do
|
|
109
|
-
input = <<~CODE.chomp
|
|
110
|
-
lines << (
|
|
111
|
-
"vacances scolaires france {zone} (prochains "
|
|
112
|
-
+ "{months_ahead} mois) :"
|
|
113
|
-
).downcase
|
|
114
|
-
CODE
|
|
115
|
-
|
|
116
|
-
expect(described_class.format(Code.parse(input))).to eq(input)
|
|
117
|
-
end
|
|
118
|
-
|
|
119
|
-
it "does not split operators inside string interpolations when wrapping" do
|
|
120
|
-
input =
|
|
121
|
-
%q(body_text = "{title}\n\n{description}\n\ningrédients :\n" + ingredients.map { |ingredient| "- {ingredient}" }.join("\n") + "\n\ninstructions :\n" + instructions.map { |instruction, index| "{index + 1}. {instruction}" }.join("\n"))
|
|
122
|
-
|
|
123
|
-
formatted = described_class.format(Code.parse(input))
|
|
124
|
-
|
|
125
|
-
expect(formatted).to include(
|
|
126
|
-
'instructions.map { |instruction, index| "{index + 1}. {instruction}" }'
|
|
127
|
-
)
|
|
128
|
-
expect(formatted).not_to include(
|
|
129
|
-
"\"{index\n + 1}. {instruction}\""
|
|
130
|
-
)
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
it "does not emit whitespace-only blank lines" do
|
|
134
|
-
input = <<~CODE.chomp
|
|
135
|
-
body = Html.join(elements.map { |element| title = element.at_css(".x") value = element.at_css(".y") title }, Html.br)
|
|
136
|
-
CODE
|
|
137
|
-
|
|
138
|
-
formatted = described_class.format(Code.parse(input))
|
|
139
|
-
|
|
140
|
-
expect(formatted.lines).not_to include(match(/\A[ \t]+\n\z/))
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
it "keeps lines within 80 characters" do
|
|
144
|
-
input = <<~CODE.chomp
|
|
145
|
-
src = "https://proxy.dorianmarie.com?" + "{{ url: src, disposition: :inline }.to_query}" if src
|
|
146
|
-
CODE
|
|
147
|
-
|
|
148
|
-
formatted = described_class.format(Code.parse(input))
|
|
149
|
-
|
|
150
|
-
expect(formatted.lines.map { |line| line.chomp.length }.max).to be <= 80
|
|
151
|
-
end
|
|
152
|
-
end
|
|
153
|
-
end
|
data/spec/code/node/call_spec.rb
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "spec_helper"
|
|
4
|
-
|
|
5
|
-
RSpec.describe Code::Object::Boolean do
|
|
6
|
-
[
|
|
7
|
-
["true & false", "false"],
|
|
8
|
-
%w[true.bitwise_and(false) false],
|
|
9
|
-
["true | false", "true"],
|
|
10
|
-
%w[true.bitwise_or(false) true],
|
|
11
|
-
["true ^ false", "true"],
|
|
12
|
-
%w[true.bitwise_xor(false) true]
|
|
13
|
-
].each do |input, expected|
|
|
14
|
-
it "#{input} == #{expected}" do
|
|
15
|
-
expect(Code.evaluate(input)).to eq(Code.evaluate(expected))
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "spec_helper"
|
|
4
|
-
|
|
5
|
-
RSpec.describe Code::Object::Cryptography do
|
|
6
|
-
it "returns sha256 hexdigest by default" do
|
|
7
|
-
expect(Code.evaluate("Cryptography.sha256(:hello)").to_s).to eq(
|
|
8
|
-
Digest::SHA256.hexdigest("hello")
|
|
9
|
-
)
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
it "supports base64 format for sha1" do
|
|
13
|
-
expected = Base64.strict_encode64(Digest::SHA1.digest("hello"))
|
|
14
|
-
|
|
15
|
-
expect(
|
|
16
|
-
Code.evaluate("Cryptography.sha1(:hello, format: :base64)").to_s
|
|
17
|
-
).to eq(expected)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
it "raises on unknown formats" do
|
|
21
|
-
expect do
|
|
22
|
-
Code.evaluate("Cryptography.sha256(:hello, format: :unknown)")
|
|
23
|
-
end.to raise_error(Code::Error, /unknown format/i)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "spec_helper"
|
|
4
|
-
|
|
5
|
-
RSpec.describe Code::Object::Decimal do
|
|
6
|
-
[
|
|
7
|
-
["10.2 % 5.1", "0"],
|
|
8
|
-
["5.5 * 2.5", "13.75"],
|
|
9
|
-
["1.5 ** 2", "2.25"],
|
|
10
|
-
["1.5 + 1.5", "3"],
|
|
11
|
-
["1.5 - 0.5", "1"],
|
|
12
|
-
%w[-1.5 -3/2],
|
|
13
|
-
["1.5 / 2", "0.75"],
|
|
14
|
-
["1.1 < 1.2", "true"],
|
|
15
|
-
["1.1 <= 1.1", "true"],
|
|
16
|
-
["1.1 <=> 1.2", "-1"],
|
|
17
|
-
["1.1 > 0.9", "true"],
|
|
18
|
-
["1.1 >= 1.1", "true"],
|
|
19
|
-
["1.1 === 1.1", "true"],
|
|
20
|
-
%w[-1.1.abs 1.1],
|
|
21
|
-
%w[-1.1.ceil -1],
|
|
22
|
-
%w[-1.123.ceil(2) -1.12],
|
|
23
|
-
%w[-1.1.floor -2],
|
|
24
|
-
%w[-1.123.floor(2) -1.13],
|
|
25
|
-
%w[1.1.round 1],
|
|
26
|
-
%w[1.123.round(2) 1.12],
|
|
27
|
-
%w[0.0.zero? true],
|
|
28
|
-
%w[1.2.truncate 1],
|
|
29
|
-
%w[1.234.truncate(2) 1.23],
|
|
30
|
-
%w[1.2.to_string "1.2"],
|
|
31
|
-
%w[1.2.to_integer 1],
|
|
32
|
-
%w[1.2.to_decimal 1.2],
|
|
33
|
-
%w[4.0.sqrt 2.0],
|
|
34
|
-
%w[0.0.zero? true],
|
|
35
|
-
%w[1.0.one? true],
|
|
36
|
-
%w[2.0.two? true],
|
|
37
|
-
%w[3.0.three? true],
|
|
38
|
-
%w[4.0.four? true],
|
|
39
|
-
%w[5.0.five? true],
|
|
40
|
-
%w[6.0.six? true],
|
|
41
|
-
%w[7.0.seven? true],
|
|
42
|
-
%w[8.0.eight? true],
|
|
43
|
-
%w[9.0.nine? true],
|
|
44
|
-
%w[10.0.ten? true]
|
|
45
|
-
].each do |input, expected|
|
|
46
|
-
it "#{input} == #{expected}" do
|
|
47
|
-
expect(Code.evaluate(input)).to eq(Code.evaluate(expected))
|
|
48
|
-
end
|
|
49
|
-
end
|
|
50
|
-
end
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require "spec_helper"
|
|
4
|
-
|
|
5
|
-
RSpec.describe Code::Object::Dictionary do
|
|
6
|
-
let(:dictionary) { 'dictionary = { first_name: "Dorian", language: :code }' }
|
|
7
|
-
|
|
8
|
-
[
|
|
9
|
-
[
|
|
10
|
-
"dictionary.select { |key| key == :first_name }",
|
|
11
|
-
"{ first_name: :Dorian }"
|
|
12
|
-
],
|
|
13
|
-
[
|
|
14
|
-
"dictionary.select { |_, value| value == :Dorian }",
|
|
15
|
-
"{ first_name: :Dorian }"
|
|
16
|
-
],
|
|
17
|
-
[
|
|
18
|
-
"dictionary.select { |_, _, index, _| index.zero? }",
|
|
19
|
-
"{ first_name: :Dorian }"
|
|
20
|
-
],
|
|
21
|
-
[
|
|
22
|
-
"dictionary.select { |_, _, _, dictionary| dictionary.two? }",
|
|
23
|
-
"dictionary"
|
|
24
|
-
],
|
|
25
|
-
[
|
|
26
|
-
"dictionary.fetch(:first_name, :last_name) { :Marié }",
|
|
27
|
-
"{ first_name: :Dorian, last_name: :Marié }"
|
|
28
|
-
],
|
|
29
|
-
["dictionary.delete(:last_name) { true }", "true"],
|
|
30
|
-
[
|
|
31
|
-
"dictionary.delete(:first_name, :language)",
|
|
32
|
-
"{ first_name: :Dorian, language: :code }"
|
|
33
|
-
],
|
|
34
|
-
%w[dictionary.any?(String) true],
|
|
35
|
-
%w[dictionary.dig(:first_name) :Dorian],
|
|
36
|
-
%w[dictionary.empty? false],
|
|
37
|
-
%w[dictionary.falsy? false],
|
|
38
|
-
%w[dictionary.fetch(:first_name) :Dorian],
|
|
39
|
-
%w[dictionary.first_name :Dorian],
|
|
40
|
-
%w[dictionary.has_key?(:first_name) true],
|
|
41
|
-
%w[dictionary.has_key?(:unknown) false],
|
|
42
|
-
%w[dictionary.has_value?(:Dorian) true],
|
|
43
|
-
%w[dictionary.has_value?(:Unknown) false],
|
|
44
|
-
%w[dictionary.key(:Dorian) :first_name],
|
|
45
|
-
%w[dictionary.key(:Unknown) nothing],
|
|
46
|
-
%w[dictionary.language :code],
|
|
47
|
-
%w[dictionary.select!(Integer) {}],
|
|
48
|
-
%w[dictionary.select(Integer) {}],
|
|
49
|
-
%w[dictionary.select(String) dictionary],
|
|
50
|
-
%w[dictionary.truthy? true],
|
|
51
|
-
["d = { a: nothing } d.compact! d", "{}"],
|
|
52
|
-
["dictionary <= dictionary", "true"],
|
|
53
|
-
["dictionary <=> dictionary", "0"],
|
|
54
|
-
["dictionary === dictionary", "true"],
|
|
55
|
-
["dictionary > { first_name: :Dorian", "true"],
|
|
56
|
-
["dictionary >= {}", "true"],
|
|
57
|
-
["dictionary.except(:first_name, :language)", "{}"],
|
|
58
|
-
["dictionary.fetch(:first_name, :language)", "dictionary"],
|
|
59
|
-
["dictionary.fetch(:unknown) { :Good }", ":Good"],
|
|
60
|
-
["dictionary.fetch_values(:first_name)", "[:Dorian]"],
|
|
61
|
-
["dictionary.fetch_values(:first_name, :language)", "[:Dorian, :code]"],
|
|
62
|
-
["dictionary.invert", "{ Dorian: :first_name, code: :language }"],
|
|
63
|
-
["dictionary.key(:Unknown) { true }", "true"],
|
|
64
|
-
["dictionary.select!(Integer) dictionary", "{}"],
|
|
65
|
-
["dictionary.select(Integer) dictionary", "dictionary"],
|
|
66
|
-
["dictionary[:first_name]", ":Dorian"],
|
|
67
|
-
["{ a: 1 }.merge(b: 2)", "{ a: 1, b: 2 }"],
|
|
68
|
-
["{ a: 1 }.merge({ a: 2 }) { |_, old, new| old + new }", "{ a: 3 }"],
|
|
69
|
-
["{ a: 1 }.merge({ a: 2 })", "{ a: 2 }"],
|
|
70
|
-
["{ a: 1 }.merge({ b: 2 })", "{ a: 1, b: 2 }"],
|
|
71
|
-
["{ a: 1, b: [2, 3] }.flatten", "[:a, 1, :b, 2, 3]"],
|
|
72
|
-
["{ a: 1, b: [2, 3] }.flatten(-1)", "[:a, 1, :b, 2, 3]"],
|
|
73
|
-
["{ a: 1, b: [2, 3] }.flatten(0)", "[[:a, 1], [:b, [2, 3]]]"],
|
|
74
|
-
["{ a: 1, b: [2, 3] }.flatten(1)", "[:a, 1, :b, [2, 3]]"],
|
|
75
|
-
["{ a: 1, b: [2, 3] }.to_list", "[[:a, 1], [:b, [2, 3]]]"],
|
|
76
|
-
["{ a: nothing }.compact", "{}"],
|
|
77
|
-
["{ a: nothing, b: 1, c: false, d: \"\" }.compact", '{ b: 1, c: false, d: "" }'],
|
|
78
|
-
["{ a: nothing, b: 1, c: false, d: \"\" }.compact(&:blank?)", "{ b: 1 }"],
|
|
79
|
-
["{ age: 31 }.delete_unless { |key| key == :age }", "{ age: 31 }"],
|
|
80
|
-
["{ age: 31 }.delete_unless(Integer)", "{ age: 31 }"],
|
|
81
|
-
["{ age: 31 }.keep_unless { |key| key == :age }", "{}"],
|
|
82
|
-
["{ age: 31 }.keep_unless(Integer)", "{}"],
|
|
83
|
-
["{ first_name: :Dorian } < dictionary", "true"],
|
|
84
|
-
["{ first_name: :Dorian }.any? { |_, value| value == :Dorian }", "true"],
|
|
85
|
-
["{ first_name: :Dorian }.delete_if { |_, value| value == :Dorian }", "{}"],
|
|
86
|
-
["{ first_name: :Dorian }.delete_if(String)", "{}"],
|
|
87
|
-
["{ first_name: :Dorian }.keep_if { |_, value| value != :Dorian }", "{}"],
|
|
88
|
-
["{ first_name: :Dorian }.keep_if(String)", "{ first_name: :Dorian }"],
|
|
89
|
-
["{} == {}", "true"],
|
|
90
|
-
['{ "name" => "Dorian" } == { name: :Dorian }', "true"]
|
|
91
|
-
].each do |input, expected|
|
|
92
|
-
it "#{input} == #{expected}" do
|
|
93
|
-
expect(Code.evaluate("#{dictionary} #{input}")).to eq(
|
|
94
|
-
Code.evaluate("#{dictionary} #{expected}")
|
|
95
|
-
)
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
end
|