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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 79da8875ffac10dd65ca8098ec782caac2822a70f261e2902dd652dfd87da312
|
|
4
|
+
data.tar.gz: 8120dd6eeaf76dd5b1d1e5ffe9114050ddf99a037b3506487e94814b7a39b794
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c7a12d5824757713528707a89ba8680e005502e83d22fd946d6a9bb45b67dca6b73d6ce684c737e8225c1feb761ac40b7feb3b8d308fc6c008e20b425ab945b3
|
|
7
|
+
data.tar.gz: d3d3e80c38fc4eec30b929947e59d12a463ad40ceb03fd1122fbbfdc7056f33d054eb240d94472264957ea2a8a71ef8e8685a11a5da4e73f29480959239daf11
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
4.0.0
|
data/bin/code
CHANGED
|
@@ -37,51 +37,128 @@ parsed =
|
|
|
37
37
|
abort Code::Version.to_s if parsed.options.version
|
|
38
38
|
abort parsed.help if parsed.options.help
|
|
39
39
|
|
|
40
|
+
MAX_ARGUMENT_FILES = 1000
|
|
41
|
+
|
|
40
42
|
def glob_pattern?(value)
|
|
41
43
|
value.match?(/[*?\[\]{]/)
|
|
42
44
|
end
|
|
43
45
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
+
def timeout
|
|
47
|
+
@timeout ||= @parsed_timeout
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def with_timeout(&)
|
|
51
|
+
Timeout.timeout(timeout, &)
|
|
52
|
+
rescue Timeout::Error
|
|
53
|
+
raise Code::Error, "timeout"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def append_limited(buffer, value, label: "input")
|
|
57
|
+
value = value.to_s
|
|
58
|
+
if buffer.bytesize + value.bytesize > Code::MAX_INPUT_BYTES
|
|
59
|
+
raise Code::Error, "#{label} is too large"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
buffer << value
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def read_file(path)
|
|
66
|
+
raise Code::Error, "#{path} is not a regular file" unless File.file?(path)
|
|
67
|
+
|
|
68
|
+
File.open(path, "rb") do |file|
|
|
69
|
+
data = file.read(Code::MAX_INPUT_BYTES + 1).to_s
|
|
70
|
+
Code.ensure_input_size!(data, label: path)
|
|
71
|
+
data
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def read_stdin
|
|
76
|
+
data = $stdin.read(Code::MAX_INPUT_BYTES + 1).to_s
|
|
77
|
+
Code.ensure_input_size!(data, label: "stdin")
|
|
78
|
+
data
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def expand_arguments(arguments)
|
|
82
|
+
expanded_files = []
|
|
83
|
+
remaining_arguments = []
|
|
46
84
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
85
|
+
arguments.each do |argument|
|
|
86
|
+
if glob_pattern?(argument)
|
|
87
|
+
matches = Dir.glob(argument).select { |path| File.file?(path) }
|
|
50
88
|
|
|
51
|
-
|
|
52
|
-
|
|
89
|
+
if matches.any?
|
|
90
|
+
expanded_files.concat(matches)
|
|
91
|
+
else
|
|
92
|
+
remaining_arguments << argument
|
|
93
|
+
end
|
|
53
94
|
else
|
|
54
95
|
remaining_arguments << argument
|
|
55
96
|
end
|
|
56
|
-
|
|
57
|
-
|
|
97
|
+
|
|
98
|
+
raise Code::Error, "too many input files" if expanded_files.size > MAX_ARGUMENT_FILES
|
|
58
99
|
end
|
|
100
|
+
|
|
101
|
+
[expanded_files, remaining_arguments]
|
|
59
102
|
end
|
|
60
103
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
104
|
+
begin
|
|
105
|
+
@parsed_timeout = Code.normalize_timeout!(
|
|
106
|
+
parsed.options.timeout || Code::DEFAULT_TIMEOUT
|
|
107
|
+
)
|
|
108
|
+
rescue Code::Error => e
|
|
109
|
+
abort "#{e.class}: #{e.message}"
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
begin
|
|
113
|
+
input =
|
|
114
|
+
with_timeout do
|
|
115
|
+
buffer = +""
|
|
116
|
+
option_input = parsed.options.input.to_s
|
|
117
|
+
expanded_argument_files, remaining_arguments =
|
|
118
|
+
expand_arguments(parsed.arguments)
|
|
119
|
+
|
|
120
|
+
if option_input.present? && File.exist?(option_input)
|
|
121
|
+
append_limited(buffer, read_file(option_input))
|
|
122
|
+
else
|
|
123
|
+
append_limited(buffer, option_input)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
append_limited(buffer, remaining_arguments.join(" "))
|
|
127
|
+
|
|
128
|
+
input_files = parsed.files + expanded_argument_files
|
|
129
|
+
raise Code::Error, "too many input files" if input_files.size > MAX_ARGUMENT_FILES
|
|
130
|
+
|
|
131
|
+
input_files.each.with_index do |file, index|
|
|
132
|
+
append_limited(buffer, "\n\n") if index.positive?
|
|
133
|
+
append_limited(buffer, read_file(file), label: file)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
buffer
|
|
137
|
+
end
|
|
138
|
+
rescue Code::Error => e
|
|
139
|
+
abort "#{e.class}: #{e.message}"
|
|
140
|
+
end
|
|
68
141
|
|
|
69
142
|
profile = parsed.options.profile || parsed.options.profiler
|
|
70
143
|
require "ruby-prof" if profile
|
|
71
144
|
|
|
72
145
|
RubyProf.start if profile
|
|
73
146
|
|
|
74
|
-
|
|
147
|
+
begin
|
|
148
|
+
input = with_timeout { read_stdin } if input.empty?
|
|
149
|
+
rescue Code::Error => e
|
|
150
|
+
abort "#{e.class}: #{e.message}"
|
|
151
|
+
end
|
|
75
152
|
|
|
76
153
|
if parsed.options.parse
|
|
77
154
|
begin
|
|
78
|
-
pp Code
|
|
155
|
+
pp Code.parse(input, timeout: timeout)
|
|
79
156
|
rescue StandardError => e
|
|
80
157
|
warn e.message
|
|
81
158
|
end
|
|
82
159
|
elsif parsed.options.format
|
|
83
160
|
begin
|
|
84
|
-
print(Code.format(input, timeout:
|
|
161
|
+
print(Code.format(input, timeout: timeout))
|
|
85
162
|
rescue Code::Error => e
|
|
86
163
|
warn "#{e.class}: #{e.message}"
|
|
87
164
|
end
|
|
@@ -93,7 +170,7 @@ else
|
|
|
93
170
|
output: $stdout,
|
|
94
171
|
error: $stderr,
|
|
95
172
|
input: $stdin,
|
|
96
|
-
timeout:
|
|
173
|
+
timeout: timeout
|
|
97
174
|
)
|
|
98
175
|
)
|
|
99
176
|
rescue Code::Error => e
|
data/lib/code/concerns/shared.rb
CHANGED
|
@@ -3,14 +3,122 @@
|
|
|
3
3
|
class Code
|
|
4
4
|
module Concerns
|
|
5
5
|
module Shared
|
|
6
|
-
attr_accessor :raw, :
|
|
6
|
+
attr_accessor :raw, :functions
|
|
7
|
+
|
|
8
|
+
COMPOUND_ASSIGNMENT_OPERATORS = [
|
|
9
|
+
"+=",
|
|
10
|
+
"-=",
|
|
11
|
+
"*=",
|
|
12
|
+
"/=",
|
|
13
|
+
"%=",
|
|
14
|
+
"<<=",
|
|
15
|
+
">>=",
|
|
16
|
+
"&=",
|
|
17
|
+
"|=",
|
|
18
|
+
"^=",
|
|
19
|
+
"||=",
|
|
20
|
+
"&&="
|
|
21
|
+
].freeze
|
|
22
|
+
SHARED_OPERATORS = [
|
|
23
|
+
"documentation",
|
|
24
|
+
"present?",
|
|
25
|
+
"blank?",
|
|
26
|
+
"presence",
|
|
27
|
+
"presence_in",
|
|
28
|
+
"is_a?",
|
|
29
|
+
"is_an?",
|
|
30
|
+
"kind_of?",
|
|
31
|
+
"instance_of?",
|
|
32
|
+
"new",
|
|
33
|
+
"!",
|
|
34
|
+
"not",
|
|
35
|
+
"!=",
|
|
36
|
+
"different",
|
|
37
|
+
"&&",
|
|
38
|
+
"and",
|
|
39
|
+
"+",
|
|
40
|
+
"self",
|
|
41
|
+
"..",
|
|
42
|
+
"inclusive_range",
|
|
43
|
+
"...",
|
|
44
|
+
"exclusive_range",
|
|
45
|
+
"==",
|
|
46
|
+
"equal",
|
|
47
|
+
"equal?",
|
|
48
|
+
"same_object?",
|
|
49
|
+
">",
|
|
50
|
+
"greater",
|
|
51
|
+
">=",
|
|
52
|
+
"greater_or_equal",
|
|
53
|
+
"<=>",
|
|
54
|
+
"compare",
|
|
55
|
+
"<",
|
|
56
|
+
"less",
|
|
57
|
+
"<=",
|
|
58
|
+
"less_or_equal",
|
|
59
|
+
"===",
|
|
60
|
+
"strict_equal",
|
|
61
|
+
"!==",
|
|
62
|
+
"strict_different",
|
|
63
|
+
"falsy?",
|
|
64
|
+
"truthy?",
|
|
65
|
+
"true?",
|
|
66
|
+
"false?",
|
|
67
|
+
"||",
|
|
68
|
+
"or",
|
|
69
|
+
"to_boolean",
|
|
70
|
+
"to_class",
|
|
71
|
+
"to_date",
|
|
72
|
+
"to_decimal",
|
|
73
|
+
"to_dictionary",
|
|
74
|
+
"to_duration",
|
|
75
|
+
"to_integer",
|
|
76
|
+
"to_list",
|
|
77
|
+
"to_nothing",
|
|
78
|
+
"to_range",
|
|
79
|
+
"to_string",
|
|
80
|
+
"inspect",
|
|
81
|
+
"to_time",
|
|
82
|
+
"as_json",
|
|
83
|
+
"duplicate",
|
|
84
|
+
"deep_duplicate",
|
|
85
|
+
"to_parameter",
|
|
86
|
+
"to_json",
|
|
87
|
+
"functions",
|
|
88
|
+
"instance_functions",
|
|
89
|
+
"class_functions",
|
|
90
|
+
"respond_to?",
|
|
91
|
+
"send",
|
|
92
|
+
"itself",
|
|
93
|
+
"tap",
|
|
94
|
+
"then",
|
|
95
|
+
"name",
|
|
96
|
+
"nothing?",
|
|
97
|
+
"something?"
|
|
98
|
+
].freeze
|
|
99
|
+
OPERATOR_METHOD_ALIASES = {
|
|
100
|
+
"[]" => "get",
|
|
101
|
+
"at" => "get",
|
|
102
|
+
"length" => "size",
|
|
103
|
+
"member?" => "include?",
|
|
104
|
+
"key?" => "has_key?",
|
|
105
|
+
"value?" => "has_value?",
|
|
106
|
+
"filter" => "select",
|
|
107
|
+
"filter!" => "select!"
|
|
108
|
+
}.freeze
|
|
7
109
|
|
|
8
110
|
def call(**args)
|
|
9
111
|
code_operator = args.fetch(:operator, nil).to_code
|
|
10
112
|
code_arguments = args.fetch(:arguments, []).to_code
|
|
11
113
|
code_value = code_arguments.code_first
|
|
12
114
|
|
|
115
|
+
dynamic_result = code_dynamic_call(code_operator, **args)
|
|
116
|
+
return dynamic_result if dynamic_result
|
|
117
|
+
|
|
13
118
|
case code_operator.to_s
|
|
119
|
+
when "documentation"
|
|
120
|
+
sig(args)
|
|
121
|
+
code_documentation
|
|
14
122
|
when "present?"
|
|
15
123
|
sig(args)
|
|
16
124
|
code_present?
|
|
@@ -23,6 +131,12 @@ class Code
|
|
|
23
131
|
when "presence_in"
|
|
24
132
|
sig(args) { Object::List }
|
|
25
133
|
code_presence_in(code_value)
|
|
134
|
+
when "is_a?", "is_an?", "kind_of?"
|
|
135
|
+
sig(args) { Object::Class }
|
|
136
|
+
code_is_a?(code_value)
|
|
137
|
+
when "instance_of?"
|
|
138
|
+
sig(args) { Object::Class }
|
|
139
|
+
code_instance_of?(code_value)
|
|
26
140
|
when "new"
|
|
27
141
|
sig(args) { Object.repeat }
|
|
28
142
|
code_new(*code_arguments.raw)
|
|
@@ -44,13 +158,16 @@ class Code
|
|
|
44
158
|
when "...", "exclusive_range"
|
|
45
159
|
sig(args) { Object }
|
|
46
160
|
code_exclusive_range(code_value)
|
|
47
|
-
when "==", "equal"
|
|
161
|
+
when "==", "equal", "equal?"
|
|
48
162
|
sig(args) { Object }
|
|
49
163
|
code_equal(code_value)
|
|
50
|
-
when "
|
|
164
|
+
when "same_object?"
|
|
165
|
+
sig(args) { Object }
|
|
166
|
+
code_same_object?(code_value)
|
|
167
|
+
when ">", "greater"
|
|
51
168
|
sig(args) { Object }
|
|
52
169
|
code_greater(code_value)
|
|
53
|
-
when ">=", "
|
|
170
|
+
when ">=", "greater_or_equal"
|
|
54
171
|
sig(args) { Object }
|
|
55
172
|
code_greater_or_equal(code_value)
|
|
56
173
|
when "<=>", "compare"
|
|
@@ -74,6 +191,12 @@ class Code
|
|
|
74
191
|
when "truthy?"
|
|
75
192
|
sig(args)
|
|
76
193
|
code_truthy?
|
|
194
|
+
when "true?"
|
|
195
|
+
sig(args)
|
|
196
|
+
code_true?
|
|
197
|
+
when "false?"
|
|
198
|
+
sig(args)
|
|
199
|
+
code_false?
|
|
77
200
|
when "||", "or"
|
|
78
201
|
sig(args) { Object }
|
|
79
202
|
code_or(code_value)
|
|
@@ -136,9 +259,30 @@ class Code
|
|
|
136
259
|
else
|
|
137
260
|
code_to_json
|
|
138
261
|
end
|
|
139
|
-
when "
|
|
262
|
+
when "functions"
|
|
263
|
+
sig(args)
|
|
264
|
+
code_functions
|
|
265
|
+
when "instance_functions"
|
|
140
266
|
sig(args)
|
|
141
|
-
|
|
267
|
+
code_instance_functions
|
|
268
|
+
when "class_functions"
|
|
269
|
+
sig(args)
|
|
270
|
+
code_class_functions
|
|
271
|
+
when "respond_to?"
|
|
272
|
+
sig(args) { Object }
|
|
273
|
+
code_respond_to?(code_value)
|
|
274
|
+
when "send"
|
|
275
|
+
sig(args) { [Object, Object.repeat] }
|
|
276
|
+
code_send(*code_arguments.raw, **args)
|
|
277
|
+
when "itself"
|
|
278
|
+
sig(args)
|
|
279
|
+
code_itself
|
|
280
|
+
when "tap"
|
|
281
|
+
sig(args) { Object::Function }
|
|
282
|
+
code_tap(code_value, **args)
|
|
283
|
+
when "then"
|
|
284
|
+
sig(args) { Object::Function }
|
|
285
|
+
code_then(code_value, **args)
|
|
142
286
|
when "name"
|
|
143
287
|
sig(args)
|
|
144
288
|
code_name
|
|
@@ -154,6 +298,9 @@ class Code
|
|
|
154
298
|
if code_operator.to_s == "="
|
|
155
299
|
code_context = args.fetch(:context)
|
|
156
300
|
code_context.code_set(self, code_value)
|
|
301
|
+
elsif setter_operator?(code_operator)
|
|
302
|
+
code_dynamic_functions.code_set(code_operator.to_s.chop, code_value)
|
|
303
|
+
return code_value
|
|
157
304
|
else
|
|
158
305
|
code_context = args.fetch(:context).code_lookup!(self)
|
|
159
306
|
code_context.code_set(
|
|
@@ -336,7 +483,7 @@ class Code
|
|
|
336
483
|
self.class.new(self)
|
|
337
484
|
end
|
|
338
485
|
|
|
339
|
-
def code_deep_duplicate
|
|
486
|
+
def code_deep_duplicate(_seen = {})
|
|
340
487
|
self.class.new(self)
|
|
341
488
|
end
|
|
342
489
|
|
|
@@ -352,16 +499,30 @@ class Code
|
|
|
352
499
|
Object::Nothing.new
|
|
353
500
|
end
|
|
354
501
|
|
|
355
|
-
def code_fetch(
|
|
356
|
-
|
|
502
|
+
def code_fetch(key)
|
|
503
|
+
code_dynamic_functions.code_fetch(key)
|
|
357
504
|
end
|
|
358
505
|
|
|
359
|
-
def code_set(
|
|
360
|
-
|
|
506
|
+
def code_set(key, value)
|
|
507
|
+
code_dynamic_functions.code_set(key, value)
|
|
361
508
|
end
|
|
362
509
|
|
|
363
|
-
def code_get(
|
|
364
|
-
|
|
510
|
+
def code_get(key)
|
|
511
|
+
code_dynamic_functions.code_get(key)
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
def code_has_key?(key)
|
|
515
|
+
code_dynamic_functions.code_has_key?(key)
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
def code_dynamic_call(operator, **args)
|
|
519
|
+
return nil unless code_dynamic_functions.code_has_key?(operator).truthy?
|
|
520
|
+
|
|
521
|
+
stored_value = code_dynamic_functions.code_fetch(operator)
|
|
522
|
+
return stored_value.call(**args, operator: nil, bound_self: self) if stored_value.is_a?(Object::Function)
|
|
523
|
+
|
|
524
|
+
sig(args)
|
|
525
|
+
stored_value
|
|
365
526
|
end
|
|
366
527
|
|
|
367
528
|
def code_to_parameter
|
|
@@ -404,6 +565,14 @@ class Code
|
|
|
404
565
|
Object::Boolean.new(truthy?)
|
|
405
566
|
end
|
|
406
567
|
|
|
568
|
+
def code_true?
|
|
569
|
+
Object::Boolean.new(self == Object::Boolean.new(true))
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
def code_false?
|
|
573
|
+
Object::Boolean.new(self == Object::Boolean.new(false) || nothing?)
|
|
574
|
+
end
|
|
575
|
+
|
|
407
576
|
def code_to_boolean
|
|
408
577
|
Object::Boolean.new(self)
|
|
409
578
|
end
|
|
@@ -460,8 +629,83 @@ class Code
|
|
|
460
629
|
Object::String.new(name.to_s.split("::")[2..].join("::"))
|
|
461
630
|
end
|
|
462
631
|
|
|
463
|
-
def
|
|
464
|
-
Object
|
|
632
|
+
def code_documentation
|
|
633
|
+
Object.documentation_for(self.class)
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
def code_functions
|
|
637
|
+
Object.sorted_dictionary(
|
|
638
|
+
code_instance_functions.code_merge(code_class_functions).raw
|
|
639
|
+
)
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
def code_instance_functions
|
|
643
|
+
Object.sorted_dictionary(
|
|
644
|
+
Object.documented_functions_for(self.class, :instance).code_merge(
|
|
645
|
+
dynamic_functions_documentation
|
|
646
|
+
).raw
|
|
647
|
+
)
|
|
648
|
+
end
|
|
649
|
+
|
|
650
|
+
def code_class_functions
|
|
651
|
+
dynamic_functions_documentation
|
|
652
|
+
end
|
|
653
|
+
|
|
654
|
+
def code_respond_to?(operator)
|
|
655
|
+
code_operator = operator.to_code
|
|
656
|
+
|
|
657
|
+
Object::Boolean.new(code_respond_to_operator?(code_operator))
|
|
658
|
+
end
|
|
659
|
+
|
|
660
|
+
def code_is_a?(klass)
|
|
661
|
+
code_klass = klass.to_code
|
|
662
|
+
|
|
663
|
+
Object::Boolean.new(is_a?(code_klass.raw))
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
def code_instance_of?(klass)
|
|
667
|
+
code_klass = klass.to_code
|
|
668
|
+
|
|
669
|
+
Object::Boolean.new(instance_of?(code_klass.raw))
|
|
670
|
+
end
|
|
671
|
+
|
|
672
|
+
def code_same_object?(other)
|
|
673
|
+
code_other = other.to_code
|
|
674
|
+
|
|
675
|
+
Object::Boolean.new(equal?(code_other))
|
|
676
|
+
end
|
|
677
|
+
|
|
678
|
+
def code_itself
|
|
679
|
+
self
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
def code_send(operator, *arguments, **globals)
|
|
683
|
+
code_operator = operator.to_code
|
|
684
|
+
|
|
685
|
+
call(
|
|
686
|
+
**globals,
|
|
687
|
+
arguments: Object::List.new(arguments),
|
|
688
|
+
operator: code_operator
|
|
689
|
+
)
|
|
690
|
+
end
|
|
691
|
+
|
|
692
|
+
def code_tap(function, **globals)
|
|
693
|
+
code_function = function.to_code
|
|
694
|
+
code_function.call(
|
|
695
|
+
**globals,
|
|
696
|
+
arguments: Object::List.new([self]),
|
|
697
|
+
operator: nil
|
|
698
|
+
)
|
|
699
|
+
self
|
|
700
|
+
end
|
|
701
|
+
|
|
702
|
+
def code_then(function, **globals)
|
|
703
|
+
code_function = function.to_code
|
|
704
|
+
code_function.call(
|
|
705
|
+
**globals,
|
|
706
|
+
arguments: Object::List.new([self]),
|
|
707
|
+
operator: nil
|
|
708
|
+
)
|
|
465
709
|
end
|
|
466
710
|
|
|
467
711
|
def present?
|
|
@@ -489,6 +733,78 @@ class Code
|
|
|
489
733
|
|
|
490
734
|
code_list.code_include?(self).truthy? ? self : Object::Nothing.new
|
|
491
735
|
end
|
|
736
|
+
|
|
737
|
+
def code_documentable_functions
|
|
738
|
+
Object::Dictionary.new(
|
|
739
|
+
code_dynamic_functions.raw.merge(dictionary_attributes)
|
|
740
|
+
)
|
|
741
|
+
end
|
|
742
|
+
|
|
743
|
+
private
|
|
744
|
+
|
|
745
|
+
def setter_operator?(operator)
|
|
746
|
+
!COMPOUND_ASSIGNMENT_OPERATORS.include?(operator.to_s)
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
def code_respond_to_operator?(operator)
|
|
750
|
+
operator_name = operator.to_s
|
|
751
|
+
|
|
752
|
+
SHARED_OPERATORS.include?(operator_name) ||
|
|
753
|
+
code_operator_method_defined?(operator_name) ||
|
|
754
|
+
code_functions.code_has_key?(operator).truthy?
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
def code_operator_method_defined?(operator_name)
|
|
758
|
+
method_name = :"code_#{OPERATOR_METHOD_ALIASES.fetch(operator_name, operator_name)}"
|
|
759
|
+
return false unless respond_to?(method_name)
|
|
760
|
+
|
|
761
|
+
method(method_name).owner != Shared
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
def code_dynamic_functions
|
|
765
|
+
@functions = Object::Dictionary.new if @functions.blank?
|
|
766
|
+
|
|
767
|
+
@functions
|
|
768
|
+
end
|
|
769
|
+
|
|
770
|
+
def dynamic_functions_documentation
|
|
771
|
+
Object.sorted_dictionary(
|
|
772
|
+
code_documentable_functions.raw.to_h do |key, value|
|
|
773
|
+
name = key.to_s
|
|
774
|
+
[
|
|
775
|
+
name,
|
|
776
|
+
Object::Dictionary.new(
|
|
777
|
+
"name" => Object::String.new(name),
|
|
778
|
+
"description" => Object::String.new(
|
|
779
|
+
dynamic_function_description(value)
|
|
780
|
+
),
|
|
781
|
+
"examples" => Object::List.new(dynamic_function_examples(value)),
|
|
782
|
+
"function" => value
|
|
783
|
+
)
|
|
784
|
+
]
|
|
785
|
+
end
|
|
786
|
+
)
|
|
787
|
+
end
|
|
788
|
+
|
|
789
|
+
def dictionary_attributes
|
|
790
|
+
return {} unless is_a?(Object::Dictionary)
|
|
791
|
+
|
|
792
|
+
raw
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
def dynamic_function_description(value)
|
|
796
|
+
code_value = value.to_code
|
|
797
|
+
return "" unless code_value.is_a?(Object::Function)
|
|
798
|
+
|
|
799
|
+
code_value.documentation.code_get("description").to_s
|
|
800
|
+
end
|
|
801
|
+
|
|
802
|
+
def dynamic_function_examples(value)
|
|
803
|
+
code_value = value.to_code
|
|
804
|
+
return [] unless code_value.is_a?(Object::Function)
|
|
805
|
+
|
|
806
|
+
code_value.documentation.code_get("examples").to_code.code_to_list.raw
|
|
807
|
+
end
|
|
492
808
|
end
|
|
493
809
|
end
|
|
494
810
|
end
|
data/lib/code/format.rb
CHANGED
|
@@ -207,13 +207,17 @@ class Code
|
|
|
207
207
|
end
|
|
208
208
|
|
|
209
209
|
def escape_string_text(text)
|
|
210
|
-
text
|
|
210
|
+
text
|
|
211
|
+
.gsub("\\", "\\\\")
|
|
212
|
+
.gsub('"', '\"')
|
|
213
|
+
.gsub("{", "\\{")
|
|
211
214
|
end
|
|
212
215
|
|
|
213
216
|
def format_string_literal(content, components:, indent:, allow_split:)
|
|
214
217
|
literal = %("#{content}")
|
|
215
218
|
return literal if literal.length <= string_inline_limit(indent)
|
|
216
219
|
return literal unless allow_split
|
|
220
|
+
return literal if content.include?("\\")
|
|
217
221
|
|
|
218
222
|
split_string_literal(components, indent: indent)
|
|
219
223
|
end
|
|
@@ -380,6 +384,14 @@ class Code
|
|
|
380
384
|
return format_code_inline(Array(argument), indent: 0)
|
|
381
385
|
end
|
|
382
386
|
|
|
387
|
+
if argument.key?(:operator)
|
|
388
|
+
return argument[:operator].to_s unless argument.key?(:value)
|
|
389
|
+
|
|
390
|
+
value = format_code_inline(argument[:value], indent: 0)
|
|
391
|
+
|
|
392
|
+
return "#{argument[:operator]}#{value}"
|
|
393
|
+
end
|
|
394
|
+
|
|
383
395
|
value = format_code_inline(argument[:value], indent: 0)
|
|
384
396
|
return value unless argument.key?(:name)
|
|
385
397
|
|
|
@@ -423,6 +435,8 @@ class Code
|
|
|
423
435
|
parameter[:spread]
|
|
424
436
|
elsif parameter.key?(:block)
|
|
425
437
|
parameter[:block]
|
|
438
|
+
elsif parameter.key?(:blocks)
|
|
439
|
+
parameter[:blocks]
|
|
426
440
|
else
|
|
427
441
|
""
|
|
428
442
|
end
|