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
@@ -5,7 +5,8 @@ class Code
5
5
  class Function < Object
6
6
  CLASS_DOCUMENTATION = {
7
7
  name: "Function",
8
- description: "stores a callable block with parameters, captured context, and documentation.",
8
+ description:
9
+ "stores a callable block with parameters, captured context, and documentation.",
9
10
  examples: [
10
11
  "Function.new",
11
12
  "((value) => { value + 1 }).call(1)",
@@ -15,16 +16,28 @@ class Code
15
16
  INSTANCE_FUNCTIONS = {
16
17
  "call" => {
17
18
  name: "call",
18
- description: "evaluates the function body with the provided arguments.",
19
+ description:
20
+ "evaluates the function body with the provided arguments.",
19
21
  examples: [
20
22
  "((value) => { value + 1 }).call(1)",
21
23
  "((name:) => { name }).call(name: :ada)",
22
24
  "((a, b = 2) => { a + b }).call(3)"
23
25
  ]
24
26
  },
27
+ "new" => {
28
+ name: "new",
29
+ description:
30
+ "evaluates the function body as a constructor with the provided arguments.",
31
+ examples: [
32
+ "Widget = () => { self.name = :widget return(self) } Widget.new.name",
33
+ "User = (name:) => { self.name = name return(self) } User.new(name: :ada).name",
34
+ "Counter = () => { self.count = 0 return(self) } Counter.new.count"
35
+ ]
36
+ },
25
37
  "extend" => {
26
38
  name: "extend",
27
- description: "creates a child function that can call the receiver through super.",
39
+ description:
40
+ "creates a child function that can call the receiver through super.",
28
41
  examples: [
29
42
  "Base = () => { self.name = :base } Child = Base.extend(() => { super() }) Child().name",
30
43
  "Base = () => { 1 } Child = Base.extend(() => { super() }) Child()",
@@ -33,7 +46,8 @@ class Code
33
46
  },
34
47
  "documentation" => {
35
48
  name: "documentation",
36
- description: "returns or replaces the function documentation dictionary.",
49
+ description:
50
+ "returns or replaces the function documentation dictionary.",
37
51
  examples: [
38
52
  "f = () => { 1 } f.documentation",
39
53
  "f = () => { 1 } f.documentation(description: \"returns one\", examples: [\"f()\"])",
@@ -51,7 +65,8 @@ class Code
51
65
  },
52
66
  "parameters" => {
53
67
  name: "parameters",
54
- description: "returns a list of parameter descriptors for the function.",
68
+ description:
69
+ "returns a list of parameter descriptors for the function.",
55
70
  examples: [
56
71
  "((name) => { name }).parameters.first.name",
57
72
  "((name = :a) => { name }).parameters.first.default",
@@ -76,8 +91,12 @@ class Code
76
91
  end
77
92
 
78
93
  attr_accessor :documentation
79
- attr_reader :code_parameters, :code_body, :definition_context,
80
- :instance_functions, :parent
94
+ attr_reader :code_parameters,
95
+ :code_body,
96
+ :definition_context,
97
+ :definition_object,
98
+ :instance_functions,
99
+ :parent
81
100
 
82
101
  def initialize(*args, parent: nil, functions: nil, **_kargs, &_block)
83
102
  @code_parameters =
@@ -89,15 +108,17 @@ class Code
89
108
 
90
109
  @code_body = Code.new(args.second.presence)
91
110
  @definition_context = args.third if args.third.is_a?(Context)
111
+ @definition_object = args.fourth if args.fourth.is_a?(Object)
92
112
  @parent = parent.to_code
93
113
  self.functions = functions.to_code
94
114
  self.functions = Dictionary.new if self.functions.nothing?
95
115
  @instance_functions = Dictionary.new
96
- self.documentation = Dictionary.new(
97
- "name" => String.new(""),
98
- "description" => String.new(""),
99
- "examples" => List.new
100
- )
116
+ self.documentation =
117
+ Dictionary.new(
118
+ "name" => String.new(""),
119
+ "description" => String.new(""),
120
+ "examples" => List.new
121
+ )
101
122
 
102
123
  self.raw = List.new([code_parameters, code_body])
103
124
  end
@@ -107,8 +128,11 @@ class Code
107
128
  code_arguments = args.fetch(:arguments, List.new).to_code
108
129
  code_value = code_arguments.code_first
109
130
  globals = multi_fetch(args, *GLOBALS)
131
+ operator_name = code_operator.to_s
132
+ operator_name = "" if operator_name == "new" &&
133
+ code_has_key?(code_operator).falsy?
110
134
 
111
- case code_operator.to_s
135
+ case operator_name
112
136
  when "", "call"
113
137
  sig(args) { signature_for_call }
114
138
  code_call(
@@ -162,6 +186,7 @@ class Code
162
186
  )
163
187
  code_arguments = arguments.to_code
164
188
  code_context = Context.new({}, definition_context || globals[:context])
189
+ evaluation_object = definition_object || globals.fetch(:previous_object)
165
190
  code_self = bound_self.to_code
166
191
  if (code_self.nil? || code_self.nothing?) && parent.is_a?(Class)
167
192
  code_self = parent.code_call(*arguments, **globals)
@@ -186,7 +211,9 @@ class Code
186
211
  end
187
212
 
188
213
  captures_function_arguments =
189
- code_parameters.raw.any? { |parameter| parameter.block? || parameter.blocks? }
214
+ code_parameters.raw.any? do |parameter|
215
+ parameter.block? || parameter.blocks?
216
+ end
190
217
  reserved_function_arguments =
191
218
  captures_function_arguments ? code_arguments.raw.grep(Function) : []
192
219
  code_block_argument =
@@ -206,16 +233,20 @@ class Code
206
233
  end
207
234
  )
208
235
  elsif code_parameter.keyword_splat?
209
- code_arguments.raw.grep(Dictionary).inject(Dictionary.new) do |memo, argument|
210
- memo.code_merge!(argument)
211
- end
236
+ code_arguments
237
+ .raw
238
+ .grep(Dictionary)
239
+ .inject(Dictionary.new) do |memo, argument|
240
+ memo.code_merge!(argument)
241
+ end
212
242
  elsif code_parameter.block?
213
243
  code_block_argument.to_code
214
244
  elsif code_parameter.blocks?
215
245
  Object::List.new(
216
- code_arguments.raw.grep(Function).reject do |argument|
217
- argument == code_block_argument
218
- end
246
+ code_arguments
247
+ .raw
248
+ .grep(Function)
249
+ .reject { |argument| argument == code_block_argument }
219
250
  )
220
251
  elsif code_parameter.keyword?
221
252
  code_arguments
@@ -239,7 +270,8 @@ class Code
239
270
  code_default.code_evaluate(
240
271
  **globals,
241
272
  context: code_context,
242
- trusted_evaluation: true
273
+ object: evaluation_object,
274
+ previous_object: evaluation_object
243
275
  )
244
276
  else
245
277
  code_default
@@ -247,17 +279,20 @@ class Code
247
279
  end
248
280
 
249
281
  code_name = code_parameter.code_name
250
- code_context.code_set(code_name, code_argument) unless code_name.blank?
282
+ unless code_name.blank?
283
+ code_context.code_set(code_name, code_argument)
284
+ end
251
285
  end
252
286
 
253
- code_body.code_evaluate(
254
- **globals,
255
- constructing_literal_classes: constructing_literal_classes,
256
- context: code_context,
257
- trusted_evaluation: true
258
- ).tap do
259
- persist_instance_functions(code_self)
260
- end
287
+ code_body
288
+ .code_evaluate(
289
+ **globals,
290
+ constructing_literal_classes: constructing_literal_classes,
291
+ context: code_context,
292
+ object: evaluation_object,
293
+ previous_object: evaluation_object
294
+ )
295
+ .tap { persist_instance_functions(code_self) }
261
296
  rescue Error::Return => e
262
297
  persist_instance_functions(code_self)
263
298
  e.code_value
@@ -318,32 +353,33 @@ class Code
318
353
  def code_extend(function)
319
354
  code_function = function.to_code
320
355
 
321
- Function.new(
322
- code_function.code_parameters,
323
- code_function.code_body.raw,
324
- code_function.definition_context,
325
- parent: self,
326
- functions: functions.code_deep_duplicate
327
- ).tap do |extended_function|
328
- extended_function.instance_functions.code_merge!(instance_functions)
329
- end
356
+ Function
357
+ .new(
358
+ code_function.code_parameters,
359
+ code_function.code_body.raw,
360
+ code_function.definition_context,
361
+ code_function.definition_object,
362
+ parent: self,
363
+ functions: functions.code_deep_duplicate
364
+ )
365
+ .tap do |extended_function|
366
+ extended_function.instance_functions.code_merge!(instance_functions)
367
+ end
330
368
  end
331
369
 
332
- def code_deep_duplicate(seen = {})
333
- seen.compare_by_identity unless seen.compare_by_identity?
334
- return seen[self] if seen.key?(self)
335
-
370
+ def code_deep_duplicate
336
371
  duplicate = Function.new
337
- seen[self] = duplicate
338
372
 
339
373
  duplicate.code_replace(
340
- code_parameters: code_parameters.code_deep_duplicate(seen),
341
- code_body: code_body.code_deep_duplicate(seen),
342
- definition_context: definition_context&.code_deep_duplicate(seen),
343
- parent: parent.is_a?(Function) ? parent.code_deep_duplicate(seen) : parent,
344
- functions: functions.code_deep_duplicate(seen),
345
- instance_functions: instance_functions.code_deep_duplicate(seen),
346
- documentation: documentation.code_deep_duplicate(seen)
374
+ code_parameters: code_parameters.code_deep_duplicate,
375
+ code_body: code_body.code_deep_duplicate,
376
+ definition_context: definition_context&.code_deep_duplicate,
377
+ definition_object: definition_object,
378
+ parent:
379
+ parent.is_a?(Function) ? parent.code_deep_duplicate : parent,
380
+ functions: functions.code_deep_duplicate,
381
+ instance_functions: instance_functions.code_deep_duplicate,
382
+ documentation: documentation.code_deep_duplicate
347
383
  )
348
384
  duplicate
349
385
  end
@@ -355,11 +391,13 @@ class Code
355
391
  parent:,
356
392
  functions:,
357
393
  instance_functions:,
358
- documentation:
394
+ documentation:,
395
+ definition_object: nil
359
396
  )
360
397
  @code_parameters = code_parameters
361
398
  @code_body = code_body
362
399
  @definition_context = definition_context
400
+ @definition_object = definition_object
363
401
  @parent = parent
364
402
  self.functions = functions
365
403
  @instance_functions = instance_functions
@@ -381,7 +419,9 @@ class Code
381
419
  end
382
420
 
383
421
  Object.sorted_dictionary(
384
- parent_functions.code_merge(function_dictionary_for(instance_functions)).raw
422
+ parent_functions.code_merge(
423
+ function_dictionary_for(instance_functions)
424
+ ).raw
385
425
  )
386
426
  end
387
427
 
@@ -440,7 +480,9 @@ class Code
440
480
  def persist_instance_functions(code_self)
441
481
  return unless code_self.is_a?(Object)
442
482
 
443
- instance_functions.code_merge!(documentable_instance_functions(code_self))
483
+ instance_functions.code_merge!(
484
+ documentable_instance_functions(code_self)
485
+ )
444
486
  end
445
487
 
446
488
  def documentable_instance_functions(code_self)