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
@@ -11,20 +11,22 @@ class Code
11
11
  end
12
12
 
13
13
  def evaluate(**args)
14
- list = ::Code::Object::List.new(
15
- (@elements || []).map { |element| element.evaluate(**args) }
16
- )
14
+ list =
15
+ ::Code::Object::List.new(
16
+ (@elements || []).map { |element| element.evaluate(**args) }
17
+ )
17
18
  constructor = literal_constructor(args.fetch(:context), "List")
18
19
  return list unless constructor
19
- return list if Array(args[:constructing_literal_classes]).include?(
20
- ::Code::Object::List
21
- )
20
+ if Array(args[:constructing_literal_classes]).include?(
21
+ ::Code::Object::List
22
+ )
23
+ return list
24
+ end
22
25
 
23
26
  constructor.call(
24
27
  **args,
25
28
  constructing_literal_classes:
26
- Array(args[:constructing_literal_classes]) +
27
- [::Code::Object::List],
29
+ Array(args[:constructing_literal_classes]) + [::Code::Object::List],
28
30
  operator: nil,
29
31
  arguments: ::Code::Object::List.new([list]),
30
32
  explicit_arguments: true
@@ -13,7 +13,7 @@ class Code
13
13
 
14
14
  def evaluate(**args)
15
15
  left = @left&.evaluate(**args) || Object::Nothing.new
16
- index_args = args.merge(object: args.fetch(:previous_object, args.fetch(:object)))
16
+ index_args = args.merge(object: args.fetch(:previous_object))
17
17
 
18
18
  (@statements || []).reduce(left) do |object, statement|
19
19
  object.code_fetch(statement.evaluate(**index_args))
@@ -30,7 +30,7 @@ class Code
30
30
  Object::IdentifierList.new([left])
31
31
  end
32
32
 
33
- index_args = args.merge(object: args.fetch(:previous_object, args.fetch(:object)))
33
+ index_args = args.merge(object: args.fetch(:previous_object))
34
34
 
35
35
  (@statements || []).each do |statement|
36
36
  list.code_append(statement.evaluate(**index_args))
@@ -6,11 +6,7 @@ class Code
6
6
  CLASS_DOCUMENTATION = {
7
7
  name: "Boolean",
8
8
  description: "represents true or false.",
9
- examples: [
10
- "Boolean",
11
- "Boolean.new(true)",
12
- "Boolean.new(false)"
13
- ]
9
+ examples: %w[Boolean Boolean.new(true) Boolean.new(false)]
14
10
  }.freeze
15
11
  INSTANCE_FUNCTIONS = {
16
12
  "&" => {
@@ -21,10 +17,10 @@ class Code
21
17
  "bitwise_and" => {
22
18
  name: "bitwise_and",
23
19
  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)"
20
+ examples: %w[
21
+ true.bitwise_and(true)
22
+ true.bitwise_and(false)
23
+ false.bitwise_and(false)
28
24
  ]
29
25
  },
30
26
  "|" => {
@@ -35,10 +31,10 @@ class Code
35
31
  "bitwise_or" => {
36
32
  name: "bitwise_or",
37
33
  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)"
34
+ examples: %w[
35
+ true.bitwise_or(false)
36
+ false.bitwise_or(true)
37
+ false.bitwise_or(false)
42
38
  ]
43
39
  },
44
40
  "^" => {
@@ -49,10 +45,10 @@ class Code
49
45
  "bitwise_xor" => {
50
46
  name: "bitwise_xor",
51
47
  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)"
48
+ examples: %w[
49
+ true.bitwise_xor(false)
50
+ true.bitwise_xor(true)
51
+ false.bitwise_xor(false)
56
52
  ]
57
53
  }
58
54
  }.freeze
@@ -5,58 +5,63 @@ class Code
5
5
  class Class < Object
6
6
  CLASS_DOCUMENTATION = {
7
7
  name: "Class",
8
- description: "wraps a value constructor and documents its class and instance functions.",
9
- examples: [
10
- "Class",
11
- "Class.new(String)",
12
- "Class.documentation.name"
13
- ]
8
+ description:
9
+ "wraps a value constructor and documents its class and instance functions.",
10
+ examples: %w[Class Class.new(String) Class.documentation.name]
14
11
  }.freeze
15
12
  INSTANCE_FUNCTIONS = {
16
13
  "documentation" => {
17
14
  name: "documentation",
18
15
  description: "returns documentation for this class.",
19
- examples: [
20
- "Class.documentation.description",
21
- "List.documentation.name",
22
- "Dictionary.documentation.name"
16
+ examples: %w[
17
+ Class.documentation.description
18
+ List.documentation.name
19
+ Dictionary.documentation.name
23
20
  ]
24
21
  },
25
22
  "functions" => {
26
23
  name: "functions",
27
- description: "returns documented class functions available on this class.",
28
- examples: [
29
- "Class.functions.keys.include?(:new)",
30
- "List.functions.keys.include?(:new)",
31
- "Dictionary.functions.keys.include?(:from_entries)"
24
+ description:
25
+ "returns documented class functions available on this class.",
26
+ examples: %w[
27
+ Class.functions.keys.include?(:new)
28
+ List.functions.keys.include?(:new)
29
+ Dictionary.functions.keys.include?(:from_entries)
32
30
  ]
33
31
  },
34
32
  "instance_functions" => {
35
33
  name: "instance_functions",
36
- description: "returns documented functions available on values built by this class.",
37
- examples: [
38
- "Class.instance_functions.keys.include?(:documentation)",
39
- "List.instance_functions.keys.include?(:map)",
40
- "String.instance_functions.keys.include?(:upcase)"
34
+ description:
35
+ "returns documented functions available on values built by this class.",
36
+ examples: %w[
37
+ Class.instance_functions.keys.include?(:documentation)
38
+ List.instance_functions.keys.include?(:map)
39
+ String.instance_functions.keys.include?(:upcase)
41
40
  ]
42
41
  },
43
42
  "class_functions" => {
44
43
  name: "class_functions",
45
- description: "returns documented class functions available on this class.",
46
- examples: [
47
- "Class.class_functions.keys.include?(:new)",
48
- "List.class_functions.keys.include?(:new)",
49
- "Dictionary.class_functions.keys.include?(:from_entries)"
44
+ description:
45
+ "returns documented class functions available on this class.",
46
+ examples: %w[
47
+ Class.class_functions.keys.include?(:new)
48
+ List.class_functions.keys.include?(:new)
49
+ Dictionary.class_functions.keys.include?(:from_entries)
50
50
  ]
51
51
  },
52
52
  "call" => {
53
53
  name: "call",
54
54
  description: "returns a new value by calling this class constructor.",
55
- examples: ["Class.call(String)", "List.call([1, 2])", "String.call(:hello)"]
55
+ examples: [
56
+ "Class.call(String)",
57
+ "List.call([1, 2])",
58
+ "String.call(:hello)"
59
+ ]
56
60
  },
57
61
  "extend" => {
58
62
  name: "extend",
59
- description: "returns a function that builds a value from this class before running the body.",
63
+ description:
64
+ "returns a function that builds a value from this class before running the body.",
60
65
  examples: [
61
66
  "Widget = Dictionary.extend(() => { self.name = :widget self }) Widget().fetch(:name)",
62
67
  "Person = Dictionary.extend((name) => { self.name = name self }) Person(:Ada).fetch(:name)",
@@ -130,6 +135,7 @@ class Code
130
135
  code_function.code_parameters,
131
136
  code_function.code_body.raw,
132
137
  code_function.definition_context,
138
+ code_function.definition_object,
133
139
  parent: self
134
140
  )
135
141
  end
@@ -42,37 +42,9 @@ class Code
42
42
  {}
43
43
  end
44
44
 
45
- class ScopedObject < Object
46
- def call(**args)
47
- code_operator = args.fetch(:operator, nil).to_code
48
- code_context = args.fetch(:context).to_code
49
-
50
- code_context = code_context.code_lookup!(code_operator)
51
- code_result = code_context.code_fetch(code_operator)
52
-
53
- if code_result.is_a?(Super) ||
54
- (
55
- code_result.is_a?(Function) &&
56
- args.fetch(:explicit_arguments, false)
57
- )
58
- code_result.call(**args, operator: nil)
59
- else
60
- sig(args)
61
- code_result
62
- end
63
- end
64
- end
65
-
66
- attr_reader :trusted
67
-
68
45
  def initialize(*args, **_kargs, &_block)
69
- @trusted = args.first.is_a?(Node::Code)
70
46
  self.raw =
71
- if trusted
72
- args.first
73
- else
74
- Node::Code.new(::Code.parse(args.first.to_s))
75
- end
47
+ (args.first.is_a?(Node::Code) ? args.first : Node::Code.new(::Code.parse(args.first.to_s)))
76
48
  end
77
49
 
78
50
  def self.code_evaluate(*args, **globals)
@@ -107,28 +79,13 @@ class Code
107
79
  end
108
80
  end
109
81
 
110
- def code_evaluate(trusted_evaluation: false, **globals)
111
- raw.evaluate(
112
- **evaluation_globals(
113
- globals,
114
- trusted_evaluation: trusted_evaluation
115
- )
116
- )
82
+ def code_evaluate(**globals)
83
+ raw.evaluate(**globals)
117
84
  end
118
85
 
119
- def code_deep_duplicate(_seen = {})
86
+ def code_deep_duplicate
120
87
  self.class.new(raw)
121
88
  end
122
-
123
- private
124
-
125
- def evaluation_globals(globals, trusted_evaluation:)
126
- return globals if trusted && trusted_evaluation
127
-
128
- object = ScopedObject.new
129
-
130
- globals.merge(context: Context.new, object: object, root_object: object)
131
- end
132
89
  end
133
90
  end
134
91
  end
@@ -5,7 +5,8 @@ class Code
5
5
  class Context < Dictionary
6
6
  CLASS_DOCUMENTATION = {
7
7
  name: "Context",
8
- description: "stores scoped identifier values used while evaluating code.",
8
+ description:
9
+ "stores scoped identifier values used while evaluating code.",
9
10
  examples: [
10
11
  "context",
11
12
  "Context.new(a: 1)",
@@ -15,7 +16,8 @@ class Code
15
16
  INSTANCE_FUNCTIONS = {
16
17
  "lookup!" => {
17
18
  name: "lookup!",
18
- description: "returns the context that defines an identifier or raises when it is missing.",
19
+ description:
20
+ "returns the context that defines an identifier or raises when it is missing.",
19
21
  examples: [
20
22
  "Context.new(a: 1).lookup!(:a)",
21
23
  "Context.new({ a: 1 }, Context.new(b: 2)).lookup!(:b)",
@@ -65,20 +67,15 @@ class Code
65
67
  Context.new(raw.merge(other.raw), parent || other.parent)
66
68
  end
67
69
 
68
- def code_deep_duplicate(seen = {})
69
- seen.compare_by_identity unless seen.compare_by_identity?
70
- return seen[self] if seen.key?(self)
71
-
70
+ def code_deep_duplicate
72
71
  duplicate = Context.new
73
- seen[self] = duplicate
74
-
75
72
  raw.each do |key, value|
76
73
  duplicate.code_set(
77
- key.code_deep_duplicate(seen),
78
- value.code_deep_duplicate(seen)
74
+ key.code_deep_duplicate,
75
+ value.code_deep_duplicate
79
76
  )
80
77
  end
81
- duplicate.parent = parent&.code_deep_duplicate(seen)
78
+ duplicate.parent = parent
82
79
  duplicate
83
80
  end
84
81
 
@@ -5,7 +5,8 @@ class Code
5
5
  class Cryptography < Object
6
6
  CLASS_DOCUMENTATION = {
7
7
  name: "Cryptography",
8
- description: "computes md5, sha1, sha256, sha384, and sha512 message digests in hex, digest, or base64 format.",
8
+ description:
9
+ "computes md5, sha1, sha256, sha384, and sha512 message digests in hex, digest, or base64 format.",
9
10
  examples: [
10
11
  "Cryptography.md5(:hello)",
11
12
  "Cryptography.sha256(:hello, format: :hex)",
@@ -15,7 +16,8 @@ class Code
15
16
  CLASS_FUNCTIONS = {
16
17
  "md5" => {
17
18
  name: "md5",
18
- description: "returns an md5 message digest as hex text by default, with digest and base64 formats available.",
19
+ description:
20
+ "returns an md5 message digest as hex text by default, with digest and base64 formats available.",
19
21
  examples: [
20
22
  "Cryptography.md5(:hello)",
21
23
  "Cryptography.md5(:hello, format: :hex)",
@@ -24,7 +26,8 @@ class Code
24
26
  },
25
27
  "sha1" => {
26
28
  name: "sha1",
27
- description: "returns a sha1 message digest as hex text by default, with digest and base64 formats available.",
29
+ description:
30
+ "returns a sha1 message digest as hex text by default, with digest and base64 formats available.",
28
31
  examples: [
29
32
  "Cryptography.sha1(:hello)",
30
33
  "Cryptography.sha1(:hello, format: :hex)",
@@ -33,7 +36,8 @@ class Code
33
36
  },
34
37
  "sha256" => {
35
38
  name: "sha256",
36
- description: "returns a sha256 message digest as hex text by default, with digest and base64 formats available.",
39
+ description:
40
+ "returns a sha256 message digest as hex text by default, with digest and base64 formats available.",
37
41
  examples: [
38
42
  "Cryptography.sha256(:hello)",
39
43
  "Cryptography.sha256(:hello, format: :hex)",
@@ -42,7 +46,8 @@ class Code
42
46
  },
43
47
  "sha384" => {
44
48
  name: "sha384",
45
- description: "returns a sha384 message digest as hex text by default, with digest and base64 formats available.",
49
+ description:
50
+ "returns a sha384 message digest as hex text by default, with digest and base64 formats available.",
46
51
  examples: [
47
52
  "Cryptography.sha384(:hello)",
48
53
  "Cryptography.sha384(:hello, format: :hex)",
@@ -51,7 +56,8 @@ class Code
51
56
  },
52
57
  "sha512" => {
53
58
  name: "sha512",
54
- description: "returns a sha512 message digest as hex text by default, with digest and base64 formats available.",
59
+ description:
60
+ "returns a sha512 message digest as hex text by default, with digest and base64 formats available.",
55
61
  examples: [
56
62
  "Cryptography.sha512(:hello)",
57
63
  "Cryptography.sha512(:hello, format: :hex)",