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.
Files changed (98) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/bin/code +97 -20
  4. data/lib/code/concerns/shared.rb +331 -15
  5. data/lib/code/format.rb +15 -1
  6. data/lib/code/network.rb +87 -0
  7. data/lib/code/node/call.rb +79 -2
  8. data/lib/code/node/call_argument.rb +14 -0
  9. data/lib/code/node/code.rb +5 -4
  10. data/lib/code/node/function_parameter.rb +7 -4
  11. data/lib/code/node/list.rb +29 -1
  12. data/lib/code/object/base_64.rb +132 -6
  13. data/lib/code/object/boolean.rb +60 -0
  14. data/lib/code/object/class.rb +138 -2
  15. data/lib/code/object/code.rb +111 -3
  16. data/lib/code/object/context.rb +57 -1
  17. data/lib/code/object/cryptography.rb +63 -0
  18. data/lib/code/object/date.rb +13339 -462
  19. data/lib/code/object/decimal.rb +1725 -0
  20. data/lib/code/object/dictionary.rb +1790 -11
  21. data/lib/code/object/duration.rb +28 -0
  22. data/lib/code/object/function.rb +261 -23
  23. data/lib/code/object/global.rb +534 -1
  24. data/lib/code/object/html.rb +179 -7
  25. data/lib/code/object/http.rb +244 -14
  26. data/lib/code/object/ics.rb +75 -13
  27. data/lib/code/object/identifier_list.rb +17 -2
  28. data/lib/code/object/integer.rb +1937 -2
  29. data/lib/code/object/json.rb +75 -1
  30. data/lib/code/object/list.rb +3383 -10
  31. data/lib/code/object/nothing.rb +53 -0
  32. data/lib/code/object/number.rb +110 -0
  33. data/lib/code/object/parameter.rb +140 -0
  34. data/lib/code/object/range.rb +576 -14
  35. data/lib/code/object/smtp.rb +95 -12
  36. data/lib/code/object/string.rb +944 -3
  37. data/lib/code/object/super.rb +10 -1
  38. data/lib/code/object/time.rb +13358 -498
  39. data/lib/code/object/url.rb +65 -0
  40. data/lib/code/object.rb +543 -0
  41. data/lib/code/parser.rb +161 -24
  42. data/lib/code-ruby.rb +3 -0
  43. data/lib/code.rb +30 -3
  44. metadata +135 -84
  45. data/.github/dependabot.yml +0 -15
  46. data/.github/workflows/ci.yml +0 -38
  47. data/.gitignore +0 -30
  48. data/.node-version +0 -1
  49. data/.npm-version +0 -1
  50. data/.prettierignore +0 -2
  51. data/.rspec +0 -1
  52. data/.rubocop.yml +0 -140
  53. data/.ruby-version +0 -1
  54. data/.tool-versions +0 -3
  55. data/AGENTS.md +0 -43
  56. data/Gemfile +0 -22
  57. data/Gemfile.lock +0 -292
  58. data/Rakefile +0 -5
  59. data/bin/bundle +0 -123
  60. data/bin/bundle-audit +0 -31
  61. data/bin/bundler-audit +0 -31
  62. data/bin/dorian +0 -31
  63. data/bin/rspec +0 -31
  64. data/bin/rubocop +0 -31
  65. data/bin/test +0 -5
  66. data/code-ruby.gemspec +0 -34
  67. data/docs/precedence.txt +0 -36
  68. data/package-lock.json +0 -14
  69. data/package.json +0 -7
  70. data/spec/bin/code_spec.rb +0 -48
  71. data/spec/code/format_spec.rb +0 -153
  72. data/spec/code/node/call_spec.rb +0 -11
  73. data/spec/code/object/boolean_spec.rb +0 -18
  74. data/spec/code/object/cryptography_spec.rb +0 -25
  75. data/spec/code/object/decimal_spec.rb +0 -50
  76. data/spec/code/object/dictionary_spec.rb +0 -98
  77. data/spec/code/object/function_spec.rb +0 -268
  78. data/spec/code/object/http_spec.rb +0 -33
  79. data/spec/code/object/ics_spec.rb +0 -50
  80. data/spec/code/object/integer_spec.rb +0 -42
  81. data/spec/code/object/list_spec.rb +0 -22
  82. data/spec/code/object/nothing_spec.rb +0 -14
  83. data/spec/code/object/range_spec.rb +0 -23
  84. data/spec/code/object/string_spec.rb +0 -26
  85. data/spec/code/parser/boolean_spec.rb +0 -11
  86. data/spec/code/parser/chained_call_spec.rb +0 -16
  87. data/spec/code/parser/dictionary_spec.rb +0 -18
  88. data/spec/code/parser/function_spec.rb +0 -16
  89. data/spec/code/parser/group_spec.rb +0 -11
  90. data/spec/code/parser/if_modifier_spec.rb +0 -18
  91. data/spec/code/parser/list_spec.rb +0 -17
  92. data/spec/code/parser/number_spec.rb +0 -11
  93. data/spec/code/parser/string_spec.rb +0 -20
  94. data/spec/code/parser_spec.rb +0 -52
  95. data/spec/code/type_spec.rb +0 -21
  96. data/spec/code_spec.rb +0 -717
  97. data/spec/spec_helper.rb +0 -21
  98. data/spec/zeitwerk/loader_spec.rb +0 -7
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Code
4
+ module Network
5
+ BLOCKED_HOSTS = %w[
6
+ localhost
7
+ localhost.localdomain
8
+ ].freeze
9
+ BLOCKED_HOST_SUFFIXES = %w[
10
+ .local
11
+ .localhost
12
+ ].freeze
13
+ BLOCKED_IP_RANGES = [
14
+ "0.0.0.0/8",
15
+ "10.0.0.0/8",
16
+ "100.64.0.0/10",
17
+ "127.0.0.0/8",
18
+ "169.254.0.0/16",
19
+ "172.16.0.0/12",
20
+ "192.0.0.0/24",
21
+ "192.168.0.0/16",
22
+ "224.0.0.0/4",
23
+ "240.0.0.0/4",
24
+ "::/128",
25
+ "::1/128",
26
+ "64:ff9b::/96",
27
+ "64:ff9b:1::/48",
28
+ "2002::/16",
29
+ "fc00::/7",
30
+ "fe80::/10",
31
+ "ff00::/8"
32
+ ].map { |range| IPAddr.new(range) }.freeze
33
+
34
+ def self.validate_public_uri!(uri, service:)
35
+ unless %w[http https].include?(uri.scheme)
36
+ raise Error, "#{service}: unsupported url scheme"
37
+ end
38
+
39
+ validate_public_host!(uri.hostname, service: service).first
40
+ end
41
+
42
+ def self.validate_public_host!(host, service:)
43
+ normalized_host = normalize_host(host)
44
+
45
+ if blocked_hostname?(normalized_host)
46
+ raise Error, "#{service}: local network requests are not allowed"
47
+ end
48
+
49
+ addresses = resolved_addresses(normalized_host)
50
+ raise Error, "#{service}: could not resolve host" if addresses.empty?
51
+
52
+ if addresses.any? { |address| blocked_address?(address) }
53
+ raise Error, "#{service}: local network requests are not allowed"
54
+ end
55
+
56
+ addresses
57
+ rescue Resolv::ResolvError, ArgumentError
58
+ raise Error, "#{service}: could not resolve host"
59
+ end
60
+
61
+ def self.blocked_address?(address)
62
+ ip = IPAddr.new(address)
63
+ ip = ip.native if ip.respond_to?(:ipv4_mapped?) && ip.ipv4_mapped?
64
+ ip = ip.native if ip.respond_to?(:ipv4_compat?) && ip.ipv4_compat?
65
+
66
+ BLOCKED_IP_RANGES.any? { |range| range.include?(ip) }
67
+ end
68
+
69
+ def self.resolved_addresses(host)
70
+ [IPAddr.new(host).to_s]
71
+ rescue ArgumentError
72
+ Resolv.getaddresses(host)
73
+ end
74
+
75
+ def self.normalize_host(host)
76
+ normalized_host = host.to_s.downcase.delete_suffix(".")
77
+ raise Error, "network: invalid host" if normalized_host.blank?
78
+
79
+ normalized_host
80
+ end
81
+
82
+ def self.blocked_hostname?(host)
83
+ BLOCKED_HOSTS.include?(host) ||
84
+ BLOCKED_HOST_SUFFIXES.any? { |suffix| host.end_with?(suffix) }
85
+ end
86
+ end
87
+ end
@@ -36,7 +36,9 @@ class Code
36
36
  arguments = []
37
37
 
38
38
  (@arguments || []).each do |argument|
39
- if argument.keyword?
39
+ if argument.expansion?
40
+ append_expanded_argument(arguments, argument, **args)
41
+ elsif argument.keyword?
40
42
  if arguments.last.is_a?(Object::Dictionary)
41
43
  arguments.last.code_merge!(argument.evaluate(**args))
42
44
  else
@@ -51,7 +53,17 @@ class Code
51
53
 
52
54
  name = Object::String.new(@name)
53
55
 
54
- args.fetch(:object).call(
56
+ object = args.fetch(:object)
57
+ dynamic_result = object.code_dynamic_call(
58
+ name,
59
+ operator: name,
60
+ arguments: Object::List.new(arguments),
61
+ explicit_arguments: @explicit_arguments,
62
+ **args
63
+ )
64
+ return dynamic_result if dynamic_result
65
+
66
+ object.call(
55
67
  operator: name,
56
68
  arguments: Object::List.new(arguments),
57
69
  explicit_arguments: @explicit_arguments,
@@ -62,6 +74,71 @@ class Code
62
74
  def resolve(**_args)
63
75
  Object::String.new(@name)
64
76
  end
77
+
78
+ private
79
+
80
+ def append_expanded_argument(arguments, argument, **args)
81
+ value =
82
+ if argument.value?
83
+ argument.evaluate(**args)
84
+ else
85
+ default_forwarded_argument(argument.operator, args.fetch(:context))
86
+ end
87
+ return if value.nil?
88
+
89
+ case argument.operator
90
+ when "*", "&&"
91
+ value.to_code.code_to_list.raw.each { |item| arguments << item }
92
+ when "**"
93
+ dictionary = value.to_code.code_to_dictionary
94
+ if arguments.last.is_a?(Object::Dictionary)
95
+ arguments.last.code_merge!(dictionary)
96
+ else
97
+ arguments << dictionary
98
+ end
99
+ when "&"
100
+ code_value = value.to_code
101
+ arguments << if code_value.is_a?(Object::Function) ||
102
+ code_value.nothing?
103
+ code_value
104
+ else
105
+ code_value.call(operator: "&", **args)
106
+ end
107
+ when "..."
108
+ expanded_arguments(value, args.fetch(:context)).each do |item|
109
+ arguments << item
110
+ end
111
+ end
112
+ end
113
+
114
+ def default_forwarded_argument(operator, context)
115
+ case operator
116
+ when "*"
117
+ context_fetch(context, "arguments") || Object::List.new
118
+ when "**"
119
+ context_fetch(context, "keyword_arguments")
120
+ when "&"
121
+ context_fetch(context, "block")
122
+ when "&&"
123
+ context_fetch(context, "blocks") || Object::List.new
124
+ when "..."
125
+ context_fetch(context, "rest") || Object::List.new
126
+ end
127
+ end
128
+
129
+ def context_fetch(context, name)
130
+ context.code_lookup!(name).code_fetch(name)
131
+ rescue Error
132
+ nil
133
+ end
134
+
135
+ def expanded_arguments(value, context)
136
+ if value.nothing?
137
+ context.code_lookup!("rest").code_fetch("rest").code_to_list.raw
138
+ else
139
+ value.to_code.code_to_list.raw
140
+ end
141
+ end
65
142
  end
66
143
  end
67
144
  end
@@ -6,8 +6,10 @@ class Code
6
6
  def initialize(parsed)
7
7
  return if parsed.blank?
8
8
 
9
+ @has_value = parsed[:value].present?
9
10
  @value = Node::Code.new(parsed.delete(:value).presence)
10
11
  @name = parsed.delete(:name).presence
12
+ @operator = parsed.delete(:operator).presence
11
13
  end
12
14
 
13
15
  def evaluate(**args)
@@ -20,10 +22,22 @@ class Code
20
22
  end
21
23
  end
22
24
 
25
+ def operator
26
+ @operator.to_s
27
+ end
28
+
29
+ def expansion?
30
+ operator.present?
31
+ end
32
+
23
33
  def keyword?
24
34
  !!@name
25
35
  end
26
36
 
37
+ def value?
38
+ !!@has_value
39
+ end
40
+
27
41
  def regular?
28
42
  !keyword?
29
43
  end
@@ -19,13 +19,13 @@ class Code
19
19
  args.merge(global_control_flow_root: false)
20
20
  else
21
21
  args
22
- end
22
+ end
23
23
  last = Object::Nothing.new
24
+ root_object = args.fetch(:root_object, args.fetch(:object))
24
25
 
25
26
  begin
26
27
  (@statements || []).each do |statement|
27
- last =
28
- statement.evaluate(**statement_args, object: Object::Global.new)
28
+ last = statement.evaluate(**statement_args, object: root_object)
29
29
  end
30
30
  rescue Error::Retry
31
31
  retry if control_flow_scope == :group
@@ -48,9 +48,10 @@ class Code
48
48
 
49
49
  def resolve(**args)
50
50
  last = Object::Nothing.new
51
+ root_object = args.fetch(:root_object, args.fetch(:object))
51
52
 
52
53
  (@statements || []).each do |statement|
53
- last = statement.resolve(**args, object: Object::Global.new)
54
+ last = statement.resolve(**args, object: root_object)
54
55
  end
55
56
 
56
57
  last
@@ -8,15 +8,13 @@ class Code
8
8
  def initialize(parsed)
9
9
  return if parsed.blank?
10
10
 
11
- @name =
12
- parsed.delete(:name).presence || parsed[:regular_splat].presence ||
13
- parsed[:keyword_splat].presence || parsed[:spread].presence ||
14
- parsed[:block].presence
11
+ @name = parsed.delete(:name).presence
15
12
  @keyword = parsed.delete(:keyword).present?
16
13
  @regular_splat = parsed.delete(:regular_splat).present?
17
14
  @keyword_splat = parsed.delete(:keyword_splat).present?
18
15
  @spread = parsed.delete(:spread).present?
19
16
  @block = parsed.delete(:block).present?
17
+ @blocks = parsed.delete(:blocks).present?
20
18
  @default = Code.new(parsed.delete(:default)) if parsed.key?(:default)
21
19
  end
22
20
 
@@ -48,6 +46,10 @@ class Code
48
46
  !!@block
49
47
  end
50
48
 
49
+ def blocks?
50
+ !!@blocks
51
+ end
52
+
51
53
  def to_h
52
54
  {
53
55
  name: name,
@@ -57,6 +59,7 @@ class Code
57
59
  keyword_splat?: keyword_splat?,
58
60
  spread?: spread?,
59
61
  block?: block?,
62
+ blocks?: blocks?,
60
63
  default: default
61
64
  }
62
65
  end
@@ -11,9 +11,37 @@ class Code
11
11
  end
12
12
 
13
13
  def evaluate(**args)
14
- ::Code::Object::List.new(
14
+ list = ::Code::Object::List.new(
15
15
  (@elements || []).map { |element| element.evaluate(**args) }
16
16
  )
17
+ constructor = literal_constructor(args.fetch(:context), "List")
18
+ return list unless constructor
19
+ return list if Array(args[:constructing_literal_classes]).include?(
20
+ ::Code::Object::List
21
+ )
22
+
23
+ constructor.call(
24
+ **args,
25
+ constructing_literal_classes:
26
+ Array(args[:constructing_literal_classes]) +
27
+ [::Code::Object::List],
28
+ operator: nil,
29
+ arguments: ::Code::Object::List.new([list]),
30
+ explicit_arguments: true
31
+ )
32
+ end
33
+
34
+ private
35
+
36
+ def literal_constructor(context, name)
37
+ return unless context.code_has_key?(name).truthy?
38
+
39
+ constructor = context.code_fetch(name)
40
+ return unless constructor.is_a?(::Code::Object::Function)
41
+ return unless constructor.parent.is_a?(::Code::Object::Class)
42
+ return unless constructor.parent.raw == ::Code::Object::List
43
+
44
+ constructor
17
45
  end
18
46
  end
19
47
  end
@@ -3,28 +3,154 @@
3
3
  class Code
4
4
  class Object
5
5
  class Base64 < Object
6
+ CLASS_DOCUMENTATION = {
7
+ name: "Base64",
8
+ description: "encodes and decodes strings with base64 text formats.",
9
+ examples: [
10
+ "Base64.encode(:hello)",
11
+ "Base64.decode(Base64.encode(:hello))",
12
+ "Base64.urlsafe_decode(Base64.urlsafe_encode(\"???\"))"
13
+ ]
14
+ }.freeze
15
+ CLASS_FUNCTIONS = {
16
+ "encode" => {
17
+ name: "encode",
18
+ description: "returns base64 text with line breaks for a string.",
19
+ examples: [
20
+ "Base64.encode(:hello)",
21
+ "Base64.encode(:hello_world)",
22
+ "Base64.encode(\"123\")"
23
+ ]
24
+ },
25
+ "encode_64" => {
26
+ name: "encode_64",
27
+ description: "returns base64 text with line breaks for a string.",
28
+ examples: [
29
+ "Base64.encode_64(:hello)",
30
+ "Base64.encode_64(:hello_world)",
31
+ "Base64.encode_64(\"123\")"
32
+ ]
33
+ },
34
+ "decode" => {
35
+ name: "decode",
36
+ description: "returns a string decoded from base64 text.",
37
+ examples: [
38
+ "Base64.decode(\"aGVsbG8=\")",
39
+ "Base64.decode(Base64.encode(:hello))",
40
+ "Base64.decode(\"MTIz\")"
41
+ ]
42
+ },
43
+ "decode_64" => {
44
+ name: "decode_64",
45
+ description: "returns a string decoded from base64 text.",
46
+ examples: [
47
+ "Base64.decode_64(\"aGVsbG8=\")",
48
+ "Base64.decode_64(Base64.encode(:hello))",
49
+ "Base64.decode_64(\"MTIz\")"
50
+ ]
51
+ },
52
+ "strict_encode" => {
53
+ name: "strict_encode",
54
+ description: "returns base64 text without line breaks for a string.",
55
+ examples: [
56
+ "Base64.strict_encode(:hello)",
57
+ "Base64.strict_encode(:hello_world)",
58
+ "Base64.strict_encode(\"123\")"
59
+ ]
60
+ },
61
+ "strict_encode_64" => {
62
+ name: "strict_encode_64",
63
+ description: "returns base64 text without line breaks for a string.",
64
+ examples: [
65
+ "Base64.strict_encode_64(:hello)",
66
+ "Base64.strict_encode_64(:hello_world)",
67
+ "Base64.strict_encode_64(\"123\")"
68
+ ]
69
+ },
70
+ "strict_decode" => {
71
+ name: "strict_decode",
72
+ description: "returns a string decoded from strict base64 text.",
73
+ examples: [
74
+ "Base64.strict_decode(\"aGVsbG8=\")",
75
+ "Base64.strict_decode(Base64.strict_encode(:hello))",
76
+ "Base64.strict_decode(\"MTIz\")"
77
+ ]
78
+ },
79
+ "strict_decode_64" => {
80
+ name: "strict_decode_64",
81
+ description: "returns a string decoded from strict base64 text.",
82
+ examples: [
83
+ "Base64.strict_decode_64(\"aGVsbG8=\")",
84
+ "Base64.strict_decode_64(Base64.strict_encode(:hello))",
85
+ "Base64.strict_decode_64(\"MTIz\")"
86
+ ]
87
+ },
88
+ "urlsafe_encode" => {
89
+ name: "urlsafe_encode",
90
+ description: "returns url-safe base64 text for a string.",
91
+ examples: [
92
+ "Base64.urlsafe_encode(:hello)",
93
+ "Base64.urlsafe_encode(\">>>\")",
94
+ "Base64.urlsafe_encode(\"???\")"
95
+ ]
96
+ },
97
+ "url_safe_encode_64" => {
98
+ name: "url_safe_encode_64",
99
+ description: "returns url-safe base64 text for a string.",
100
+ examples: [
101
+ "Base64.url_safe_encode_64(:hello)",
102
+ "Base64.url_safe_encode_64(\">>>\")",
103
+ "Base64.url_safe_encode_64(\"???\")"
104
+ ]
105
+ },
106
+ "urlsafe_decode" => {
107
+ name: "urlsafe_decode",
108
+ description: "returns a string decoded from url-safe base64 text.",
109
+ examples: [
110
+ "Base64.urlsafe_decode(\"aGVsbG8=\")",
111
+ "Base64.urlsafe_decode(\"Pj4-\")",
112
+ "Base64.urlsafe_decode(\"Pz8_\")"
113
+ ]
114
+ },
115
+ "url_safe_decode_64" => {
116
+ name: "url_safe_decode_64",
117
+ description: "returns a string decoded from url-safe base64 text.",
118
+ examples: [
119
+ "Base64.url_safe_decode_64(\"aGVsbG8=\")",
120
+ "Base64.url_safe_decode_64(\"Pj4-\")",
121
+ "Base64.url_safe_decode_64(\"Pz8_\")"
122
+ ]
123
+ }
124
+ }.freeze
125
+
126
+ def self.function_documentation(scope)
127
+ return CLASS_FUNCTIONS if scope == :class
128
+
129
+ {}
130
+ end
131
+
6
132
  def self.call(**args)
7
133
  code_operator = args.fetch(:operator, nil).to_code
8
134
  code_arguments = args.fetch(:arguments, []).to_code
9
135
  code_value = code_arguments.code_first
10
136
 
11
137
  case code_operator.to_s
12
- when "encode"
138
+ when "encode", "encode_64"
13
139
  sig(args) { String }
14
140
  code_encode(code_value)
15
- when "decode"
141
+ when "decode", "decode_64"
16
142
  sig(args) { String }
17
143
  code_decode(code_value)
18
- when "strict_encode"
144
+ when "strict_encode", "strict_encode_64"
19
145
  sig(args) { String }
20
146
  code_strict_encode(code_value)
21
- when "strict_decode"
147
+ when "strict_decode", "strict_decode_64"
22
148
  sig(args) { String }
23
149
  code_strict_decode(code_value)
24
- when "urlsafe_encode"
150
+ when "urlsafe_encode", "url_safe_encode_64"
25
151
  sig(args) { String }
26
152
  code_urlsafe_encode(code_value)
27
- when "urlsafe_decode"
153
+ when "urlsafe_decode", "url_safe_decode_64"
28
154
  sig(args) { String }
29
155
  code_urlsafe_decode(code_value)
30
156
  else
@@ -3,6 +3,66 @@
3
3
  class Code
4
4
  class Object
5
5
  class Boolean < ::Code::Object
6
+ CLASS_DOCUMENTATION = {
7
+ name: "Boolean",
8
+ description: "represents true or false.",
9
+ examples: [
10
+ "Boolean",
11
+ "Boolean.new(true)",
12
+ "Boolean.new(false)"
13
+ ]
14
+ }.freeze
15
+ INSTANCE_FUNCTIONS = {
16
+ "&" => {
17
+ name: "&",
18
+ description: "returns true when both booleans are true.",
19
+ examples: ["true & true", "true & false", "false & false"]
20
+ },
21
+ "bitwise_and" => {
22
+ name: "bitwise_and",
23
+ description: "returns true when both booleans are true.",
24
+ examples: [
25
+ "true.bitwise_and(true)",
26
+ "true.bitwise_and(false)",
27
+ "false.bitwise_and(false)"
28
+ ]
29
+ },
30
+ "|" => {
31
+ name: "|",
32
+ description: "returns true when either boolean is true.",
33
+ examples: ["true | false", "false | true", "false | false"]
34
+ },
35
+ "bitwise_or" => {
36
+ name: "bitwise_or",
37
+ description: "returns true when either boolean is true.",
38
+ examples: [
39
+ "true.bitwise_or(false)",
40
+ "false.bitwise_or(true)",
41
+ "false.bitwise_or(false)"
42
+ ]
43
+ },
44
+ "^" => {
45
+ name: "^",
46
+ description: "returns true when exactly one boolean is true.",
47
+ examples: ["true ^ false", "true ^ true", "false ^ false"]
48
+ },
49
+ "bitwise_xor" => {
50
+ name: "bitwise_xor",
51
+ description: "returns true when exactly one boolean is true.",
52
+ examples: [
53
+ "true.bitwise_xor(false)",
54
+ "true.bitwise_xor(true)",
55
+ "false.bitwise_xor(false)"
56
+ ]
57
+ }
58
+ }.freeze
59
+
60
+ def self.function_documentation(scope)
61
+ return INSTANCE_FUNCTIONS if scope == :instance
62
+
63
+ {}
64
+ end
65
+
6
66
  def initialize(*args, **_kargs, &_block)
7
67
  self.raw =
8
68
  (args.first.is_an?(Object) ? args.first.truthy? : !!args.first)