code-ruby 4.0.0 → 4.0.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/VERSION +1 -1
  3. data/bin/code +21 -34
  4. data/lib/code/concerns/shared.rb +103 -99
  5. data/lib/code/format.rb +23 -19
  6. data/lib/code/network.rb +23 -28
  7. data/lib/code/node/call.rb +15 -9
  8. data/lib/code/node/code.rb +5 -5
  9. data/lib/code/node/function.rb +6 -1
  10. data/lib/code/node/left_operation.rb +3 -3
  11. data/lib/code/node/list.rb +10 -8
  12. data/lib/code/node/square_bracket.rb +2 -2
  13. data/lib/code/object/boolean.rb +13 -17
  14. data/lib/code/object/class.rb +33 -27
  15. data/lib/code/object/code.rb +4 -47
  16. data/lib/code/object/context.rb +8 -11
  17. data/lib/code/object/cryptography.rb +12 -6
  18. data/lib/code/object/date.rb +910 -449
  19. data/lib/code/object/decimal.rb +229 -856
  20. data/lib/code/object/dictionary.rb +116 -49
  21. data/lib/code/object/duration.rb +3 -7
  22. data/lib/code/object/function.rb +96 -54
  23. data/lib/code/object/global.rb +122 -209
  24. data/lib/code/object/html.rb +7 -13
  25. data/lib/code/object/http.rb +29 -43
  26. data/lib/code/object/ics.rb +6 -13
  27. data/lib/code/object/identifier_list.rb +16 -11
  28. data/lib/code/object/integer.rb +270 -942
  29. data/lib/code/object/json.rb +8 -28
  30. data/lib/code/object/list.rb +98 -114
  31. data/lib/code/object/nothing.rb +11 -11
  32. data/lib/code/object/number.rb +20 -10
  33. data/lib/code/object/parameter.rb +18 -9
  34. data/lib/code/object/range.rb +62 -108
  35. data/lib/code/object/smtp.rb +20 -15
  36. data/lib/code/object/string.rb +55 -29
  37. data/lib/code/object/super.rb +2 -1
  38. data/lib/code/object/time.rb +1146 -572
  39. data/lib/code/object/url.rb +4 -2
  40. data/lib/code/object.rb +119 -80
  41. data/lib/code/parser.rb +31 -92
  42. data/lib/code.rb +3 -11
  43. metadata +3 -23
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 79da8875ffac10dd65ca8098ec782caac2822a70f261e2902dd652dfd87da312
4
- data.tar.gz: 8120dd6eeaf76dd5b1d1e5ffe9114050ddf99a037b3506487e94814b7a39b794
3
+ metadata.gz: 2296ee1cc187e2213bbefbb8306efe2de92e79e21b12d8ff5f3472d5ce18eb30
4
+ data.tar.gz: ca3868cf9a4c2c58560a2c81130f633aced9c16a47af11d2386ea5c79a8ba6ce
5
5
  SHA512:
6
- metadata.gz: c7a12d5824757713528707a89ba8680e005502e83d22fd946d6a9bb45b67dca6b73d6ce684c737e8225c1feb761ac40b7feb3b8d308fc6c008e20b425ab945b3
7
- data.tar.gz: d3d3e80c38fc4eec30b929947e59d12a463ad40ceb03fd1122fbbfdc7056f33d054eb240d94472264957ea2a8a71ef8e8685a11a5da4e73f29480959239daf11
6
+ metadata.gz: 9efaa6dd86c9e6484184ab83e2d4df371f32e737e507e90e60e9151acac473ec029eeecc26e123b577343286712197430c6828de4f340ea88effa592958f451b
7
+ data.tar.gz: f16dba556195a93d2b564511a020cf6bca95c24a86534ddb063573619c214b9fbc0439842621d9ef1244cd59cbb3e3fff1544dfd9c4074e96adc5c7541e1c4ee
data/VERSION CHANGED
@@ -1 +1 @@
1
- 4.0.0
1
+ 4.0.2
data/bin/code CHANGED
@@ -3,6 +3,7 @@
3
3
 
4
4
  require_relative "../lib/code-ruby"
5
5
  require "dorian/arguments"
6
+ require "pp"
6
7
 
7
8
  parsed =
8
9
  Dorian::Arguments.parse(
@@ -37,8 +38,6 @@ parsed =
37
38
  abort Code::Version.to_s if parsed.options.version
38
39
  abort parsed.help if parsed.options.help
39
40
 
40
- MAX_ARGUMENT_FILES = 1000
41
-
42
41
  def glob_pattern?(value)
43
42
  value.match?(/[*?\[\]{]/)
44
43
  end
@@ -47,35 +46,22 @@ def timeout
47
46
  @timeout ||= @parsed_timeout
48
47
  end
49
48
 
50
- def with_timeout(&)
51
- Timeout.timeout(timeout, &)
49
+ def with_timeout(&block)
50
+ Timeout.timeout(timeout, &block)
52
51
  rescue Timeout::Error
53
52
  raise Code::Error, "timeout"
54
53
  end
55
54
 
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
55
  def read_file(path)
66
56
  raise Code::Error, "#{path} is not a regular file" unless File.file?(path)
67
57
 
68
58
  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
59
+ file.read.to_s
72
60
  end
73
61
  end
74
62
 
75
63
  def read_stdin
76
- data = $stdin.read(Code::MAX_INPUT_BYTES + 1).to_s
77
- Code.ensure_input_size!(data, label: "stdin")
78
- data
64
+ $stdin.read.to_s
79
65
  end
80
66
 
81
67
  def expand_arguments(arguments)
@@ -94,17 +80,14 @@ def expand_arguments(arguments)
94
80
  else
95
81
  remaining_arguments << argument
96
82
  end
97
-
98
- raise Code::Error, "too many input files" if expanded_files.size > MAX_ARGUMENT_FILES
99
83
  end
100
84
 
101
85
  [expanded_files, remaining_arguments]
102
86
  end
103
87
 
104
88
  begin
105
- @parsed_timeout = Code.normalize_timeout!(
106
- parsed.options.timeout || Code::DEFAULT_TIMEOUT
107
- )
89
+ @parsed_timeout =
90
+ Code.normalize_timeout!(parsed.options.timeout || Code::DEFAULT_TIMEOUT)
108
91
  rescue Code::Error => e
109
92
  abort "#{e.class}: #{e.message}"
110
93
  end
@@ -117,20 +100,20 @@ begin
117
100
  expanded_argument_files, remaining_arguments =
118
101
  expand_arguments(parsed.arguments)
119
102
 
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
103
+ buffer <<
104
+ if option_input.present? && File.exist?(option_input)
105
+ read_file(option_input)
106
+ else
107
+ option_input
108
+ end
125
109
 
126
- append_limited(buffer, remaining_arguments.join(" "))
110
+ buffer << remaining_arguments.join(" ")
127
111
 
128
112
  input_files = parsed.files + expanded_argument_files
129
- raise Code::Error, "too many input files" if input_files.size > MAX_ARGUMENT_FILES
130
113
 
131
114
  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)
115
+ buffer << "\n\n" if index.positive?
116
+ buffer << read_file(file)
134
117
  end
135
118
 
136
119
  buffer
@@ -152,7 +135,11 @@ end
152
135
 
153
136
  if parsed.options.parse
154
137
  begin
155
- pp Code.parse(input, timeout: timeout)
138
+ output = StringIO.new
139
+ with_timeout { PP.pp(Code.parse(input, timeout: timeout), output) }
140
+ print output.string
141
+ rescue SystemStackError
142
+ warn "timeout"
156
143
  rescue StandardError => e
157
144
  warn e.message
158
145
  end
@@ -5,96 +5,96 @@ class Code
5
5
  module Shared
6
6
  attr_accessor :raw, :functions
7
7
 
8
- COMPOUND_ASSIGNMENT_OPERATORS = [
9
- "+=",
10
- "-=",
11
- "*=",
12
- "/=",
13
- "%=",
14
- "<<=",
15
- ">>=",
16
- "&=",
17
- "|=",
18
- "^=",
19
- "||=",
20
- "&&="
8
+ COMPOUND_ASSIGNMENT_OPERATORS = %w[
9
+ +=
10
+ -=
11
+ *=
12
+ /=
13
+ %=
14
+ <<=
15
+ >>=
16
+ &=
17
+ |=
18
+ ^=
19
+ ||=
20
+ &&=
21
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?"
22
+ SHARED_OPERATORS = %w[
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
98
  ].freeze
99
99
  OPERATOR_METHOD_ALIASES = {
100
100
  "[]" => "get",
@@ -483,7 +483,7 @@ class Code
483
483
  self.class.new(self)
484
484
  end
485
485
 
486
- def code_deep_duplicate(_seen = {})
486
+ def code_deep_duplicate
487
487
  self.class.new(self)
488
488
  end
489
489
 
@@ -519,7 +519,9 @@ class Code
519
519
  return nil unless code_dynamic_functions.code_has_key?(operator).truthy?
520
520
 
521
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)
522
+ if stored_value.is_a?(Object::Function)
523
+ return stored_value.call(**args, operator: nil, bound_self: self)
524
+ end
523
525
 
524
526
  sig(args)
525
527
  stored_value
@@ -641,9 +643,10 @@ class Code
641
643
 
642
644
  def code_instance_functions
643
645
  Object.sorted_dictionary(
644
- Object.documented_functions_for(self.class, :instance).code_merge(
645
- dynamic_functions_documentation
646
- ).raw
646
+ Object
647
+ .documented_functions_for(self.class, :instance)
648
+ .code_merge(dynamic_functions_documentation)
649
+ .raw
647
650
  )
648
651
  end
649
652
 
@@ -755,7 +758,8 @@ class Code
755
758
  end
756
759
 
757
760
  def code_operator_method_defined?(operator_name)
758
- method_name = :"code_#{OPERATOR_METHOD_ALIASES.fetch(operator_name, operator_name)}"
761
+ method_name =
762
+ :"code_#{OPERATOR_METHOD_ALIASES.fetch(operator_name, operator_name)}"
759
763
  return false unless respond_to?(method_name)
760
764
 
761
765
  method(method_name).owner != Shared
@@ -775,10 +779,10 @@ class Code
775
779
  name,
776
780
  Object::Dictionary.new(
777
781
  "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
+ "description" =>
783
+ Object::String.new(dynamic_function_description(value)),
784
+ "examples" =>
785
+ Object::List.new(dynamic_function_examples(value)),
782
786
  "function" => value
783
787
  )
784
788
  ]
data/lib/code/format.rb CHANGED
@@ -207,10 +207,7 @@ class Code
207
207
  end
208
208
 
209
209
  def escape_string_text(text)
210
- text
211
- .gsub("\\", "\\\\")
212
- .gsub('"', '\"')
213
- .gsub("{", "\\{")
210
+ text.gsub("\\", "\\\\").gsub('"', '\"').gsub("{", "\\{")
214
211
  end
215
212
 
216
213
  def format_string_literal(content, components:, indent:, allow_split:)
@@ -335,7 +332,7 @@ class Code
335
332
  def format_dictionary_statement_code(statement_code)
336
333
  key =
337
334
  format_dictionary_statement_key(statement_code[:statement]) ||
338
- format_nested_statement(statement_code[:statement], indent: 0)
335
+ format_nested_statement(statement_code[:statement], indent: 0)
339
336
  return key unless statement_code.key?(:code)
340
337
 
341
338
  value = format_code_inline(statement_code[:code], indent: 0)
@@ -477,14 +474,17 @@ class Code
477
474
  first_line, *rest = right.lines(chomp: true)
478
475
  if multiline_operand_statement?(other[:statement]) ||
479
476
  !BOOLEAN_WORD_OPERATORS.include?(operator)
480
- ["#{expression} #{operator} #{first_line.lstrip}", *rest].join("\n")
477
+ ["#{expression} #{operator} #{first_line.lstrip}", *rest].join(
478
+ "\n"
479
+ )
481
480
  else
482
481
  [
483
482
  "#{expression}\n#{INDENT * (indent + 1)}#{operator} #{first_line.lstrip}",
484
483
  *rest
485
484
  ].join("\n")
486
485
  end
487
- elsif expression.include?("\n") || candidate.length > MAX_LINE_LENGTH
486
+ elsif expression.include?("\n") ||
487
+ candidate.length > MAX_LINE_LENGTH
488
488
  right_lines =
489
489
  if right.include?("\n")
490
490
  right.lines(chomp: true).map(&:lstrip)
@@ -521,10 +521,9 @@ class Code
521
521
  return false if expression.lstrip.start_with?("(")
522
522
 
523
523
  continuation_lines =
524
- expression
525
- .lines(chomp: true)[1..]
526
- .to_a
527
- .reject { |line| line.strip.empty? || line.strip.match?(/\A[\])}]+\z/) }
524
+ expression.lines(chomp: true)[1..].to_a.reject do |line|
525
+ line.strip.empty? || line.strip.match?(/\A[\])}]+\z/)
526
+ end
528
527
 
529
528
  return false if continuation_lines.empty?
530
529
 
@@ -578,10 +577,7 @@ class Code
578
577
  first_line = first_line.lstrip
579
578
  return "#{left} #{operator} #{first_line}" if rest.empty?
580
579
 
581
- return [
582
- "#{left} #{operator} #{first_line}",
583
- *rest
584
- ].join("\n")
580
+ return ["#{left} #{operator} #{first_line}", *rest].join("\n")
585
581
  end
586
582
 
587
583
  "#{left} #{operator} #{right}"
@@ -594,7 +590,9 @@ class Code
594
590
  if nested_operator == "="
595
591
  left = format_nested_statement(nested[:left], indent: indent)
596
592
  right = format_nested_statement(nested[:right], indent: indent)
597
- return "#{left} #{nested_operator} #{group_multiline_expression(right, indent: indent)}"
593
+ return(
594
+ "#{left} #{nested_operator} #{group_multiline_expression(right, indent: indent)}"
595
+ )
598
596
  end
599
597
  end
600
598
 
@@ -724,7 +722,8 @@ class Code
724
722
  Array(while_statement[:parameters]).map do |parameter|
725
723
  format_parameter(parameter, indent: indent)
726
724
  end
727
- header = parameters.empty? ? "loop {" : "loop { |#{parameters.join(", ")}|"
725
+ header =
726
+ parameters.empty? ? "loop {" : "loop { |#{parameters.join(", ")}|"
728
727
 
729
728
  return "#{INDENT * indent}#{header}\n#{body}\n#{INDENT * indent}}"
730
729
  end
@@ -757,7 +756,9 @@ class Code
757
756
  others = Array(operation[:others])
758
757
 
759
758
  return false if others.empty?
760
- return false unless others.all? { |other| compact_operator?(other[:operator]) }
759
+ unless others.all? { |other| compact_operator?(other[:operator]) }
760
+ return false
761
+ end
761
762
 
762
763
  return multiline_operand_statement?(operation[:first])
763
764
  end
@@ -785,7 +786,10 @@ class Code
785
786
 
786
787
  def indent_lines(value, indent)
787
788
  prefix = INDENT * indent
788
- value.split("\n").map { |line| line.empty? ? "" : "#{prefix}#{line}" }.join("\n")
789
+ value
790
+ .split("\n")
791
+ .map { |line| line.empty? ? "" : "#{prefix}#{line}" }
792
+ .join("\n")
789
793
  end
790
794
 
791
795
  def statement_separator(inline:, indent: nil)
data/lib/code/network.rb CHANGED
@@ -2,34 +2,29 @@
2
2
 
3
3
  class Code
4
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
5
+ BLOCKED_HOSTS = %w[localhost localhost.localdomain].freeze
6
+ BLOCKED_HOST_SUFFIXES = %w[.local .localhost].freeze
7
+ BLOCKED_IP_RANGES =
8
+ %w[
9
+ 0.0.0.0/8
10
+ 10.0.0.0/8
11
+ 100.64.0.0/10
12
+ 127.0.0.0/8
13
+ 169.254.0.0/16
14
+ 172.16.0.0/12
15
+ 192.0.0.0/24
16
+ 192.168.0.0/16
17
+ 224.0.0.0/4
18
+ 240.0.0.0/4
19
+ ::/128
20
+ ::1/128
21
+ 64:ff9b::/96
22
+ 64:ff9b:1::/48
23
+ 2002::/16
24
+ fc00::/7
25
+ fe80::/10
26
+ ff00::/8
27
+ ].map { |range| IPAddr.new(range) }.freeze
33
28
 
34
29
  def self.validate_public_uri!(uri, service:)
35
30
  unless %w[http https].include?(uri.scheme)
@@ -14,7 +14,12 @@ class Code
14
14
  end
15
15
 
16
16
  def evaluate(**args)
17
- Object::Function.new(@parameters, @body, args.fetch(:context))
17
+ Object::Function.new(
18
+ @parameters,
19
+ @body,
20
+ args.fetch(:context),
21
+ args.fetch(:previous_object)
22
+ )
18
23
  end
19
24
  end
20
25
 
@@ -54,13 +59,14 @@ class Code
54
59
  name = Object::String.new(@name)
55
60
 
56
61
  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
- )
62
+ dynamic_result =
63
+ object.code_dynamic_call(
64
+ name,
65
+ operator: name,
66
+ arguments: Object::List.new(arguments),
67
+ explicit_arguments: @explicit_arguments,
68
+ **args
69
+ )
64
70
  return dynamic_result if dynamic_result
65
71
 
66
72
  object.call(
@@ -99,7 +105,7 @@ class Code
99
105
  when "&"
100
106
  code_value = value.to_code
101
107
  arguments << if code_value.is_a?(Object::Function) ||
102
- code_value.nothing?
108
+ code_value.nothing?
103
109
  code_value
104
110
  else
105
111
  code_value.call(operator: "&", **args)
@@ -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
+ object = args.fetch(:previous_object)
25
25
 
26
26
  begin
27
27
  (@statements || []).each do |statement|
28
- last = statement.evaluate(**statement_args, object: root_object)
28
+ last = statement.evaluate(**statement_args, object: object)
29
29
  end
30
30
  rescue Error::Retry
31
31
  retry if control_flow_scope == :group
@@ -48,10 +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
+ object = args.fetch(:previous_object)
52
52
 
53
53
  (@statements || []).each do |statement|
54
- last = statement.resolve(**args, object: root_object)
54
+ last = statement.resolve(**args, object: object)
55
55
  end
56
56
 
57
57
  last
@@ -13,7 +13,12 @@ class Code
13
13
  end
14
14
 
15
15
  def evaluate(**args)
16
- Object::Function.new(@parameters, @body, args.fetch(:context))
16
+ Object::Function.new(
17
+ @parameters,
18
+ @body,
19
+ args.fetch(:context),
20
+ args.fetch(:previous_object)
21
+ )
17
22
  end
18
23
  end
19
24
  end
@@ -54,7 +54,7 @@ class Code
54
54
  right.statement.evaluate(
55
55
  **args,
56
56
  object: left,
57
- previous_object: args.fetch(:object)
57
+ previous_object: args.fetch(:previous_object)
58
58
  )
59
59
  elsif right.safe_call?
60
60
  if left.is_an?(Object::Nothing)
@@ -63,7 +63,7 @@ class Code
63
63
  right.statement.evaluate(
64
64
  **args,
65
65
  object: left,
66
- previous_object: args.fetch(:object)
66
+ previous_object: args.fetch(:previous_object)
67
67
  )
68
68
  end
69
69
  elsif (right.or? && left.truthy?) || (right.and? && left.falsy?)
@@ -88,7 +88,7 @@ class Code
88
88
  other.statement.resolve(
89
89
  **args,
90
90
  object: list.code_last,
91
- previous_object: args.fetch(:object)
91
+ previous_object: args.fetch(:previous_object)
92
92
  )
93
93
 
94
94
  if resolved.is_a?(Object::IdentifierList)