code-ruby 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +2 -2
  3. data/bin/code +6 -0
  4. data/lib/code/node/base_10.rb +2 -2
  5. data/lib/code/node/base_16.rb +1 -5
  6. data/lib/code/node/base_2.rb +1 -5
  7. data/lib/code/node/base_8.rb +1 -5
  8. data/lib/code/node/call.rb +4 -4
  9. data/lib/code/node/code.rb +2 -1
  10. data/lib/code/node/decimal.rb +1 -4
  11. data/lib/code/node/dictionary.rb +6 -2
  12. data/lib/code/node/function.rb +3 -3
  13. data/lib/code/node/function_parameter.rb +5 -1
  14. data/lib/code/node/if.rb +2 -1
  15. data/lib/code/node/list.rb +2 -1
  16. data/lib/code/node/statement.rb +23 -23
  17. data/lib/code/node/string.rb +2 -1
  18. data/lib/code/object/argument.rb +4 -3
  19. data/lib/code/object/boolean.rb +5 -4
  20. data/lib/code/object/class.rb +4 -3
  21. data/lib/code/object/code.rb +33 -0
  22. data/lib/code/object/context.rb +7 -5
  23. data/lib/code/object/date.rb +31 -6
  24. data/lib/code/object/decimal.rb +36 -31
  25. data/lib/code/object/dictionary.rb +4 -4
  26. data/lib/code/object/duration.rb +8 -5
  27. data/lib/code/object/function.rb +42 -26
  28. data/lib/code/object/global.rb +58 -38
  29. data/lib/code/object/integer.rb +23 -26
  30. data/lib/code/object/list.rb +5 -5
  31. data/lib/code/object/nothing.rb +2 -4
  32. data/lib/code/object/parameter.rb +43 -0
  33. data/lib/code/object/range.rb +13 -11
  34. data/lib/code/object/string.rb +7 -7
  35. data/lib/code/object/time.rb +15 -8
  36. data/lib/code/object.rb +102 -5
  37. data/lib/code/parser.rb +1 -1
  38. data/lib/code/type.rb +10 -2
  39. data/lib/code/version.rb +1 -1
  40. data/lib/code-ruby.rb +6 -0
  41. data/lib/code.rb +8 -5
  42. data/spec/code/object/dictionary_spec.rb +0 -2
  43. data/spec/code_spec.rb +122 -16
  44. metadata +4 -3
  45. data/lib/code/object/number.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 97ce31f3a36a57e14f607ded3383aa3c71866824c6e57541c70d48962c77b9ef
4
- data.tar.gz: '0229023c391084763f03d2ffbfd82af81da2d996666719a49ad169d7740c4d6c'
3
+ metadata.gz: b04f0e4774e945bbf969c0159eaf23db99d9208faa98e4ae2ed575c1a363baf9
4
+ data.tar.gz: bf3de392fa1af6540d653d35248089d49b39da4addfd539e7594e0ac66c15def
5
5
  SHA512:
6
- metadata.gz: 996b1594dbc1192dbad2b0c64d605d9eccff6d5622437ef5974464648e5f2cd2ee57aad50fce9279f8027f1378fc7c2652106265a2fc79bbe21b224210228c9d
7
- data.tar.gz: ec405b4bc88648344f4860fb7350695aa447a5905e9a56e7230c771d5ea76e22515fe74ac0fc30771e27a9d67f4eda85b0d2475484d81a5d2c604c5a901913ae
6
+ metadata.gz: 05a921e1f388872311df4f61df4dcf808cc1d4bdaccbf2bdbdd65cc58b5495edac205c003397c83254f257a9ad114b093f2470018dc12fc4d7998ae7e1feaa7d
7
+ data.tar.gz: f856f404a8bebf4d802d2d0ab427e091f5c556da3cd24c3f583a09bf646dedef086e31b933c8933f86868ec9b501d1594f8d7e5272bcdbf1a7dea9571e825cf6
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- code-ruby (0.10.4)
4
+ code-ruby (0.11.0)
5
5
  activesupport (~> 7)
6
6
  bigdecimal (~> 3)
7
7
  json (~> 2)
@@ -30,7 +30,7 @@ GEM
30
30
  i18n (1.14.1)
31
31
  concurrent-ruby (~> 1.0)
32
32
  json (2.7.1)
33
- language-ruby (0.7.0)
33
+ language-ruby (0.8.0)
34
34
  zeitwerk (~> 2)
35
35
  minitest (5.22.2)
36
36
  mutex_m (0.2.0)
data/bin/code CHANGED
@@ -42,6 +42,12 @@ argv =
42
42
  "Set timeout in seconds"
43
43
  ) { |timeout| options[:timeout] = timeout.to_f }
44
44
 
45
+ opts.on(
46
+ "-z TIME_ZONE",
47
+ "--time-zone TIME_ZONE",
48
+ "Set time zone"
49
+ ) { |time_zone| Time.zone = time_zone }
50
+
45
51
  opts.on("--profile", "Profile Ruby code") do |_timeout|
46
52
  require "ruby-prof"
47
53
  options[:profile] = true
@@ -16,9 +16,9 @@ class Code
16
16
  if @exponent && @whole
17
17
  exponent = @exponent.evaluate(**args)
18
18
  if exponent.is_a?(Object::Integer)
19
- Object::Integer.new(@whole, exponent:)
19
+ Object::Integer.new(@whole, exponent)
20
20
  else
21
- Object::Decimal.new(@whole, exponent:)
21
+ Object::Decimal.new(@whole, exponent)
22
22
  end
23
23
  elsif @whole
24
24
  Object::Integer.new(@whole.to_i)
@@ -9,11 +9,7 @@ class Code
9
9
  end
10
10
 
11
11
  def evaluate(**_args)
12
- if @base_16
13
- Object::Integer.new(@base_16.to_i(16))
14
- else
15
- Object::Nothing.new
16
- end
12
+ @base_16 ? Object::Integer.new(@base_16.to_i(16)) : Object::Nothing.new
17
13
  end
18
14
  end
19
15
  end
@@ -9,11 +9,7 @@ class Code
9
9
  end
10
10
 
11
11
  def evaluate(**_args)
12
- if @base_2
13
- Object::Integer.new(@base_2.to_i(2))
14
- else
15
- Object::Nothing.new
16
- end
12
+ @base_2 ? Object::Integer.new(@base_2.to_i(2)) : Object::Nothing.new
17
13
  end
18
14
  end
19
15
  end
@@ -9,11 +9,7 @@ class Code
9
9
  end
10
10
 
11
11
  def evaluate(**_args)
12
- if @base_8
13
- Object::Integer.new(@base_8.to_i(8))
14
- else
15
- Object::Nothing.new
16
- end
12
+ @base_8 ? Object::Integer.new(@base_8.to_i(8)) : Object::Nothing.new
17
13
  end
18
14
  end
19
15
  end
@@ -13,9 +13,7 @@ class Code
13
13
  end
14
14
 
15
15
  def evaluate(**_args)
16
- Object::Argument.new(
17
- Object::Function.new(parameters: @parameters, body: @body)
18
- )
16
+ Object::Argument.new(Object::Function.new(@parameters, @body))
19
17
  end
20
18
  end
21
19
 
@@ -25,7 +23,9 @@ class Code
25
23
  @arguments = parsed.delete(:arguments).presence || []
26
24
  @arguments.map! { |argument| CallArgument.new(argument) }
27
25
 
28
- @block = Call::Block.new(parsed.delete(:block).presence) if parsed.key?(:block)
26
+ if parsed.key?(:block)
27
+ @block = Call::Block.new(parsed.delete(:block).presence)
28
+ end
29
29
  end
30
30
 
31
31
  def evaluate(**args)
@@ -5,7 +5,8 @@ class Code
5
5
  class Code < Node
6
6
  def initialize(parsed)
7
7
  return if parsed.blank?
8
- @statements = (parsed.presence || []).map { |statement| Statement.new(statement) }
8
+ @statements =
9
+ (parsed.presence || []).map { |statement| Statement.new(statement) }
9
10
  end
10
11
 
11
12
  def evaluate(**args)
@@ -14,10 +14,7 @@ class Code
14
14
 
15
15
  def evaluate(**args)
16
16
  if @exponent && @decimal
17
- Object::Decimal.new(
18
- @decimal,
19
- exponent: @exponent.evaluate(**args)
20
- )
17
+ Object::Decimal.new(@decimal, @exponent.evaluate(**args))
21
18
  elsif @decimal
22
19
  Object::Decimal.new(@decimal)
23
20
  else
@@ -32,12 +32,16 @@ class Code
32
32
  def initialize(parsed)
33
33
  return if parsed.blank?
34
34
  @key_values = parsed.presence || []
35
- @key_values.map! { |key_value| Node::Dictionary::KeyValue.new(key_value) }
35
+ @key_values.map! do |key_value|
36
+ Node::Dictionary::KeyValue.new(key_value)
37
+ end
36
38
  end
37
39
 
38
40
  def evaluate(**args)
39
41
  ::Code::Object::Dictionary.new(
40
- (@key_values || []).map { |key_value| key_value.evaluate(**args) }.to_h
42
+ (@key_values || [])
43
+ .map { |key_value| key_value.evaluate(**args) }
44
+ .to_h
41
45
  )
42
46
  end
43
47
  end
@@ -6,13 +6,13 @@ class Code
6
6
  def initialize(parsed)
7
7
  return if parsed.blank?
8
8
  @parameters = parsed.delete(:parameters).presence || []
9
- @parameters.map! { |parameter| Node::FunctionParameter.new(parameter) }
9
+ @parameters.map! { |parameter| FunctionParameter.new(parameter) }
10
10
 
11
- @body = Node::Code.new(parsed.delete(:body).presence)
11
+ @body = Code.new(parsed.delete(:body).presence)
12
12
  end
13
13
 
14
14
  def evaluate(**_args)
15
- ::Code::Object::Function.new(parameters: @parameters, body: @body)
15
+ Object::Function.new(@parameters, @body)
16
16
  end
17
17
  end
18
18
  end
@@ -10,7 +10,7 @@ class Code
10
10
  end
11
11
 
12
12
  def name
13
- ::Code::Object::String.new(@name)
13
+ Object::String.new(@name)
14
14
  end
15
15
 
16
16
  def regular?
@@ -28,6 +28,10 @@ class Code
28
28
  def keyword_splat?
29
29
  false
30
30
  end
31
+
32
+ def default
33
+ nil
34
+ end
31
35
  end
32
36
  end
33
37
  end
data/lib/code/node/if.rb CHANGED
@@ -25,7 +25,8 @@ class Code
25
25
  def initialize(parsed)
26
26
  return if parsed.blank?
27
27
  @first_operator = parsed.delete(:first_operator).presence
28
- @first_statement = Node::Statement.new(parsed.delete(:first_statement).presence)
28
+ @first_statement =
29
+ Node::Statement.new(parsed.delete(:first_statement).presence)
29
30
  @first_body = Node::Code.new(parsed.delete(:first_body).presence)
30
31
  @elses = (parsed.delete(:elses).presence || [])
31
32
  @elses.map! { |elses| Node::If::Else.new(elses) }
@@ -5,7 +5,8 @@ class Code
5
5
  class List < Node
6
6
  def initialize(parsed)
7
7
  return if parsed.blank?
8
- @elements = (parsed.presence || []).map { |element| Node::Code.new(element) }
8
+ @elements =
9
+ (parsed.presence || []).map { |element| Node::Code.new(element) }
9
10
  end
10
11
 
11
12
  def evaluate(**args)
@@ -7,51 +7,51 @@ class Code
7
7
  return if parsed.blank?
8
8
 
9
9
  if parsed.key?(:nothing)
10
- @statement = Node::Nothing.new(parsed.delete(:nothing))
10
+ @statement = Nothing.new(parsed.delete(:nothing))
11
11
  elsif parsed.key?(:boolean)
12
- @statement = Node::Boolean.new(parsed.delete(:boolean))
12
+ @statement = Boolean.new(parsed.delete(:boolean))
13
13
  elsif parsed.key?(:group)
14
- @statement = Node::Code.new(parsed.delete(:group))
14
+ @statement = Code.new(parsed.delete(:group))
15
15
  elsif parsed.key?(:call)
16
- @statement = Node::Call.new(parsed.delete(:call))
16
+ @statement = Call.new(parsed.delete(:call))
17
17
  elsif parsed.key?(:number)
18
- @statement = Node::Number.new(parsed.delete(:number))
18
+ @statement = Number.new(parsed.delete(:number))
19
19
  elsif parsed.key?(:string)
20
- @statement = Node::String.new(parsed.delete(:string))
20
+ @statement = String.new(parsed.delete(:string))
21
21
  elsif parsed.key?(:list)
22
- @statement = Node::List.new(parsed.delete(:list))
22
+ @statement = List.new(parsed.delete(:list))
23
23
  elsif parsed.key?(:dictionnary)
24
- @statement = Node::Dictionary.new(parsed.delete(:dictionnary))
24
+ @statement = Dictionary.new(parsed.delete(:dictionnary))
25
25
  elsif parsed.key?(:chained_call)
26
- @statement = Node::ChainedCall.new(parsed.delete(:chained_call))
26
+ @statement = ChainedCall.new(parsed.delete(:chained_call))
27
27
  elsif parsed.key?(:left_operation)
28
- @statement = Node::LeftOperation.new(parsed.delete(:left_operation))
28
+ @statement = LeftOperation.new(parsed.delete(:left_operation))
29
29
  elsif parsed.key?(:right_operation)
30
- @statement = Node::RightOperation.new(parsed.delete(:right_operation))
30
+ @statement = RightOperation.new(parsed.delete(:right_operation))
31
31
  elsif parsed.key?(:function)
32
- @statement = Node::Function.new(parsed.delete(:function))
32
+ @statement = Function.new(parsed.delete(:function))
33
33
  elsif parsed.key?(:negation)
34
- @statement = Node::Negation.new(parsed.delete(:negation))
34
+ @statement = Negation.new(parsed.delete(:negation))
35
35
  elsif parsed.key?(:power)
36
- @statement = Node::Power.new(parsed.delete(:power))
36
+ @statement = Power.new(parsed.delete(:power))
37
37
  elsif parsed.key?(:unary_minus)
38
- @statement = Node::UnaryMinus.new(parsed.delete(:unary_minus))
38
+ @statement = UnaryMinus.new(parsed.delete(:unary_minus))
39
39
  elsif parsed.key?(:ternary)
40
- @statement = Node::Ternary.new(parsed.delete(:ternary))
40
+ @statement = Ternary.new(parsed.delete(:ternary))
41
41
  elsif parsed.key?(:rescue)
42
- @statement = Node::Rescue.new(parsed.delete(:rescue))
42
+ @statement = Rescue.new(parsed.delete(:rescue))
43
43
  elsif parsed.key?(:not)
44
- @statement = Node::Not.new(parsed.delete(:not))
44
+ @statement = Not.new(parsed.delete(:not))
45
45
  elsif parsed.key?(:if_modifier)
46
- @statement = Node::IfModifier.new(parsed.delete(:if_modifier))
46
+ @statement = IfModifier.new(parsed.delete(:if_modifier))
47
47
  elsif parsed.key?(:if)
48
- @statement = Node::If.new(parsed.delete(:if))
48
+ @statement = If.new(parsed.delete(:if))
49
49
  elsif parsed.key?(:while)
50
- @statement = Node::While.new(parsed.delete(:while))
50
+ @statement = While.new(parsed.delete(:while))
51
51
  elsif parsed.key?(:splat)
52
- @statement = Node::Splat.new(parsed.delete(:splat))
52
+ @statement = Splat.new(parsed.delete(:splat))
53
53
  elsif parsed.key?(:square_bracket)
54
- @statement = Node::SquareBracket.new(parsed.delete(:square_bracket))
54
+ @statement = SquareBracket.new(parsed.delete(:square_bracket))
55
55
  end
56
56
  end
57
57
 
@@ -53,7 +53,8 @@ class Code
53
53
 
54
54
  def initialize(parsed)
55
55
  return if parsed.blank?
56
- @parts = (parsed.presence || []).map { |part| Node::String::Part.new(part) }
56
+ @parts =
57
+ (parsed.presence || []).map { |part| Node::String::Part.new(part) }
57
58
  end
58
59
 
59
60
  def evaluate(**args)
@@ -5,9 +5,10 @@ class Code
5
5
  class Argument < Object
6
6
  attr_reader :value, :name
7
7
 
8
- def initialize(value, name: nil)
9
- @value = value
10
- @name = name
8
+ def initialize(*args, **_kargs, &_block)
9
+ @value = args.first.presence || Nothing.new
10
+ @name = args.second.present? ? String.new(args.second) : nil
11
+ super
11
12
  end
12
13
 
13
14
  def keyword?
@@ -3,10 +3,11 @@
3
3
  class Code
4
4
  class Object
5
5
  class Boolean < ::Code::Object
6
- attr_reader :raw
7
-
8
- def initialize(raw)
9
- @raw = (raw.is_a?(Object) ? raw.truthy? : !!raw)
6
+ def initialize(*args, **_kargs, &_block)
7
+ raw = args.first || Nothing.new
8
+ raw = raw.raw if raw.is_a?(Object)
9
+ @raw = !!raw
10
+ super
10
11
  end
11
12
 
12
13
  def self.name
@@ -3,11 +3,12 @@
3
3
  class Code
4
4
  class Object
5
5
  class Class < Object
6
- attr_reader :raw
7
-
8
- def initialize(raw)
6
+ def initialize(*args, **_kargs, &_block)
7
+ raw = args.first || Nothing.new
9
8
  raw = raw.raw if raw.is_a?(Class)
9
+ raw = raw.class if raw.is_an?(Object)
10
10
  @raw = raw
11
+ super
11
12
  end
12
13
 
13
14
  def call(...)
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Code
4
+ class Object
5
+ class Code < Object
6
+ def initialize(*args, **_kargs, &_block)
7
+ raw = args.first.presence || Nothing.new
8
+ @raw = raw.is_a?(Node) ? raw : Node::Code.new(::Code.parse(raw.to_s))
9
+ super
10
+ end
11
+
12
+ def self.name
13
+ "Code"
14
+ end
15
+
16
+ def evaluate(...)
17
+ raw.evaluate(...)
18
+ end
19
+
20
+ def inspect
21
+ "code"
22
+ end
23
+
24
+ def to_s
25
+ "code"
26
+ end
27
+
28
+ def as_json(...)
29
+ "code".as_json(...)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -5,10 +5,12 @@ class Code
5
5
  class Context < Dictionary
6
6
  attr_reader :parent
7
7
 
8
- def initialize(raw = {}, parent: nil)
9
- raw = raw.raw if raw.is_a?(Dictionary)
8
+ def initialize(*args, **_kargs, &_block)
9
+ raw = args.first || Dictionary.new
10
+ raw = raw.raw if raw.is_a?(Object)
10
11
  @raw = raw.to_h
11
- @parent = parent
12
+ @parent = Context.new(args.second) if args.second
13
+ super
12
14
  end
13
15
 
14
16
  def self.name
@@ -21,12 +23,12 @@ class Code
21
23
  elsif parent?
22
24
  parent.lookup!(identifier)
23
25
  else
24
- raise Code::Error::Undefined, "#{identifier} is not defined"
26
+ raise Error::Undefined, "#{identifier} is not defined"
25
27
  end
26
28
  end
27
29
 
28
30
  def merge(other)
29
- Context.new(raw.merge(other.raw), parent: parent || other.parent)
31
+ Context.new(raw.merge(other.raw), parent || other.parent)
30
32
  end
31
33
 
32
34
  def parent?
@@ -3,11 +3,12 @@
3
3
  class Code
4
4
  class Object
5
5
  class Date < Object
6
- attr_reader :raw
7
-
8
- def initialize(date)
9
- date = date.raw if date.is_a?(Date)
10
- @raw = date.to_date
6
+ def initialize(*args, **_kargs, &_block)
7
+ raw = args.map(&:to_s).join("-").presence || ::Date.current.to_s
8
+ @raw = ::Date.parse(raw)
9
+ super
10
+ rescue ::Date::Error
11
+ raise Error, "#{raw.inspect} is an invalid date"
11
12
  end
12
13
 
13
14
  def self.name
@@ -21,14 +22,38 @@ class Code
21
22
  when "tomorrow"
22
23
  sig(args)
23
24
  code_tomorrow
25
+ when "yesterday"
26
+ sig(args)
27
+ code_yesterday
28
+ when "today"
29
+ sig(args)
30
+ code_today
31
+ when "now"
32
+ sig(args)
33
+ code_now
24
34
  else
25
35
  super
26
36
  end
27
37
  end
28
38
 
39
+ def self.code_now
40
+ ::Time.zone ||= Time::DEFAULT_ZONE
41
+ new(::Time.zone.now.beginning_of_day)
42
+ end
43
+
44
+ def self.code_today
45
+ ::Time.zone ||= Time::DEFAULT_ZONE
46
+ new(::Time.zone.now.beginning_of_day)
47
+ end
48
+
29
49
  def self.code_tomorrow
30
50
  ::Time.zone ||= Time::DEFAULT_ZONE
31
- new(::Time.zone.tomorrow)
51
+ new(::Time.zone.tomorrow.beginning_of_day)
52
+ end
53
+
54
+ def self.code_yesterday
55
+ ::Time.zone ||= Time::DEFAULT_ZONE
56
+ new(::Time.zone.yesterday.beginning_of_day)
32
57
  end
33
58
 
34
59
  def inspect
@@ -2,19 +2,16 @@
2
2
 
3
3
  class Code
4
4
  class Object
5
- class Decimal < ::Code::Object::Number
6
- attr_reader :raw
7
-
8
- def initialize(decimal, exponent: nil)
9
- decimal = decimal.raw if decimal.is_a?(Decimal)
10
- @raw = BigDecimal(decimal)
11
-
12
- return unless exponent
13
- unless exponent.is_a?(Number)
14
- raise ::Code::Error::TypeError, "exponent is not a number"
15
- end
16
-
17
- @raw *= 10**exponent.raw
5
+ class Decimal < Object
6
+ def initialize(*args, **_kargs, &_block)
7
+ decimal = args.first || "0"
8
+ exponent = args.second || "0"
9
+ decimal = decimal.raw if decimal.is_an?(Object)
10
+ exponent = exponent.raw if exponent.is_an?(Object)
11
+ @raw = decimal.to_d * 10**exponent.to_d
12
+ super
13
+ rescue FloatDomainError => e
14
+ raise Error, "#{decimal.inspect} * 10**#{exponent.inspect} is invalid"
18
15
  end
19
16
 
20
17
  def self.name
@@ -28,49 +25,49 @@ class Code
28
25
 
29
26
  case operator.to_s
30
27
  when "%", "modulo"
31
- sig(args) { Number }
28
+ sig(args) { Integer | Decimal }
32
29
  code_modulo(value)
33
30
  when "&", "bitwise_and"
34
- sig(args) { Number }
31
+ sig(args) { Integer | Decimal }
35
32
  code_bitwise_and(value)
36
33
  when "*", "multiplication"
37
- sig(args) { Number }
34
+ sig(args) { Integer | Decimal }
38
35
  code_multiplication(value)
39
36
  when "**", "power"
40
- sig(args) { Number }
37
+ sig(args) { Integer | Decimal }
41
38
  code_power(value)
42
39
  when "+", "plus"
43
40
  sig(args) { Object.maybe }
44
41
  value ? code_plus(value) : self
45
42
  when "-", "minus"
46
- sig(args) { Number.maybe }
43
+ sig(args) { (Integer | Decimal).maybe }
47
44
  value ? code_minus(value) : code_unary_minus
48
45
  when "/", "division"
49
- sig(args) { Number }
46
+ sig(args) { Integer | Decimal }
50
47
  code_division(value)
51
48
  when "<", "inferior"
52
- sig(args) { Number }
49
+ sig(args) { Integer | Decimal }
53
50
  code_inferior(value)
54
51
  when "<<", "left_shift"
55
- sig(args) { Number }
52
+ sig(args) { Integer | Decimal }
56
53
  code_left_shift(value)
57
54
  when "<=", "inferior_or_equal"
58
- sig(args) { Number }
55
+ sig(args) { Integer | Decimal }
59
56
  code_inferior_or_equal(value)
60
57
  when "<=>", "compare"
61
- sig(args) { Number }
58
+ sig(args) { Integer | Decimal }
62
59
  code_compare(value)
63
60
  when ">", "superior"
64
- sig(args) { Number }
61
+ sig(args) { Integer | Decimal }
65
62
  code_superior(value)
66
63
  when ">=", "superior_or_equal"
67
- sig(args) { Number }
64
+ sig(args) { Integer | Decimal }
68
65
  code_superior_or_equal(value)
69
66
  when ">>", "right_shift"
70
- sig(args) { Number }
67
+ sig(args) { Integer | Decimal }
71
68
  code_right_shift(value)
72
69
  when "^", "bitwise_xor"
73
- sig(args) { Number }
70
+ sig(args) { Integer | Decimal }
74
71
  code_bitwise_xor(value)
75
72
  when "abs"
76
73
  sig(args)
@@ -136,7 +133,7 @@ class Code
136
133
  sig(args)
137
134
  code_zero?
138
135
  when "|", "bitwise_or"
139
- sig(args) { Number }
136
+ sig(args) { Integer | Decimal }
140
137
  code_bitwise_or(value)
141
138
  else
142
139
  super
@@ -226,7 +223,7 @@ class Code
226
223
  end
227
224
 
228
225
  def code_plus(other)
229
- if other.is_a?(Number)
226
+ if other.is_an?(Integer) || other.is_a?(Decimal)
230
227
  Decimal.new(raw + other.raw)
231
228
  else
232
229
  String.new(to_s + other.to_s)
@@ -307,12 +304,20 @@ class Code
307
304
  to_s
308
305
  end
309
306
 
307
+ def whole?
308
+ whole == raw
309
+ end
310
+
311
+ def whole
312
+ raw.round
313
+ end
314
+
310
315
  def to_s
311
- raw.to_s("F")
316
+ whole? ? raw.to_i.to_s : raw.to_s("F")
312
317
  end
313
318
 
314
319
  def as_json(...)
315
- raw.as_json(...)
320
+ whole? ? whole.as_json(...) : raw.as_json(...)
316
321
  end
317
322
  end
318
323
  end
@@ -3,11 +3,11 @@
3
3
  class Code
4
4
  class Object
5
5
  class Dictionary < ::Code::Object
6
- attr_reader :raw
7
-
8
- def initialize(raw = {})
9
- raw = raw.raw if raw.is_a?(Dictionary)
6
+ def initialize(*args, **_kargs, &_block)
7
+ raw = args.first || {}
8
+ raw = raw.raw if raw.is_a?(Object)
10
9
  @raw = raw.to_h
10
+ super
11
11
  end
12
12
 
13
13
  def self.name
@@ -3,11 +3,14 @@
3
3
  class Code
4
4
  class Object
5
5
  class Duration < Object
6
- attr_reader :raw
7
-
8
- def initialize(duration)
9
- duration = duration.raw if duration.is_a?(Duration)
10
- @raw = duration
6
+ def initialize(*args, **_kargs, &_block)
7
+ raw = args.first || 0.seconds
8
+ raw = raw.raw if raw.is_an?(Object)
9
+ raw = raw.iso8601 if raw.is_an?(::ActiveSupport::Duration)
10
+ @raw = ::ActiveSupport::Duration.parse(raw.to_s)
11
+ super
12
+ rescue ::ActiveSupport::Duration::ISO8601Parser::ParsingError
13
+ raise Error, "#{raw.inspect} is not a valid duration"
11
14
  end
12
15
 
13
16
  def self.name