code-ruby 0.11.0 → 0.13.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 (49) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +5 -3
  4. data/Rakefile +5 -0
  5. data/bin/code +6 -0
  6. data/lib/code/node/base_10.rb +2 -2
  7. data/lib/code/node/base_16.rb +1 -5
  8. data/lib/code/node/base_2.rb +1 -5
  9. data/lib/code/node/base_8.rb +1 -5
  10. data/lib/code/node/call.rb +4 -4
  11. data/lib/code/node/code.rb +2 -1
  12. data/lib/code/node/decimal.rb +1 -4
  13. data/lib/code/node/dictionary.rb +6 -2
  14. data/lib/code/node/function.rb +3 -3
  15. data/lib/code/node/function_parameter.rb +5 -1
  16. data/lib/code/node/if.rb +2 -1
  17. data/lib/code/node/list.rb +2 -1
  18. data/lib/code/node/statement.rb +23 -23
  19. data/lib/code/node/string.rb +2 -1
  20. data/lib/code/object/argument.rb +4 -3
  21. data/lib/code/object/boolean.rb +4 -24
  22. data/lib/code/object/class.rb +3 -19
  23. data/lib/code/object/code.rb +16 -0
  24. data/lib/code/object/context.rb +6 -9
  25. data/lib/code/object/date.rb +25 -17
  26. data/lib/code/object/decimal.rb +30 -38
  27. data/lib/code/object/dictionary.rb +6 -21
  28. data/lib/code/object/duration.rb +7 -21
  29. data/lib/code/object/function.rb +29 -45
  30. data/lib/code/object/global.rb +56 -40
  31. data/lib/code/object/identifier_list.rb +0 -4
  32. data/lib/code/object/integer.rb +23 -46
  33. data/lib/code/object/json.rb +29 -0
  34. data/lib/code/object/list.rb +4 -21
  35. data/lib/code/object/nothing.rb +2 -20
  36. data/lib/code/object/parameter.rb +51 -0
  37. data/lib/code/object/range.rb +12 -27
  38. data/lib/code/object/string.rb +6 -27
  39. data/lib/code/object/time.rb +14 -24
  40. data/lib/code/object.rb +155 -15
  41. data/lib/code/parser.rb +1 -1
  42. data/lib/code/type.rb +10 -2
  43. data/lib/code/version.rb +1 -1
  44. data/lib/code-ruby.rb +6 -0
  45. data/lib/code.rb +8 -5
  46. data/spec/code/object/dictionary_spec.rb +0 -2
  47. data/spec/code_spec.rb +141 -29
  48. metadata +6 -3
  49. 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: dd20de2ab8f69a2256eb18bd2eea8cc2876d8f828cbdf7c086996934ef8b6eb7
4
+ data.tar.gz: df97885df1ee89d2e3766090980a1fd8467091b982dacf9c1505cb0684d7b466
5
5
  SHA512:
6
- metadata.gz: 996b1594dbc1192dbad2b0c64d605d9eccff6d5622437ef5974464648e5f2cd2ee57aad50fce9279f8027f1378fc7c2652106265a2fc79bbe21b224210228c9d
7
- data.tar.gz: ec405b4bc88648344f4860fb7350695aa447a5905e9a56e7230c771d5ea76e22515fe74ac0fc30771e27a9d67f4eda85b0d2475484d81a5d2c604c5a901913ae
6
+ metadata.gz: 29c23d759b84cfb83e9dbc16913d77c6e2b95b86d3a5a65e2f8571199d58c671810806ed49939fe1e1931446571681c216fa261828b07908c43aa0832dfc8177
7
+ data.tar.gz: 46cbd45a6b53094ed19e2058728cbf6e76ba2fa34d253de4e6be6083cf61a8c26d84a3d943358311321cd32fd44201a55c00ee8605f2adee8216f46a0cfe715e
data/Gemfile CHANGED
@@ -6,5 +6,6 @@ gemspec
6
6
 
7
7
  ruby "3.3.0"
8
8
 
9
+ gem "rake"
9
10
  gem "rspec"
10
11
  gem "ruby-prof"
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.13.0)
5
5
  activesupport (~> 7)
6
6
  bigdecimal (~> 3)
7
7
  json (~> 2)
@@ -27,13 +27,14 @@ GEM
27
27
  connection_pool (2.4.1)
28
28
  diff-lcs (1.5.1)
29
29
  drb (2.2.1)
30
- i18n (1.14.1)
30
+ i18n (1.14.4)
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)
37
+ rake (13.1.0)
37
38
  rspec (3.13.0)
38
39
  rspec-core (~> 3.13.0)
39
40
  rspec-expectations (~> 3.13.0)
@@ -58,6 +59,7 @@ PLATFORMS
58
59
 
59
60
  DEPENDENCIES
60
61
  code-ruby!
62
+ rake
61
63
  rspec
62
64
  ruby-prof
63
65
 
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rspec/core/rake_task"
4
+
5
+ RSpec::Core::RakeTask.new(:default) { |task| task.verbose = false }
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
+ @raw = List.new([@value, @name])
11
12
  end
12
13
 
13
14
  def keyword?
@@ -3,14 +3,10 @@
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)
10
- end
11
-
12
- def self.name
13
- "Boolean"
6
+ def initialize(*args, **_kargs, &_block)
7
+ raw = args.first || Nothing.new
8
+ raw = raw.raw if raw.is_a?(Object)
9
+ @raw = !!raw
14
10
  end
15
11
 
16
12
  def call(**args)
@@ -45,25 +41,9 @@ class Code
45
41
  Boolean.new(raw ^ value.raw)
46
42
  end
47
43
 
48
- def inspect
49
- to_s
50
- end
51
-
52
- def succ
53
- Boolean.new(!raw)
54
- end
55
-
56
- def to_s
57
- raw.to_s
58
- end
59
-
60
44
  def truthy?
61
45
  raw
62
46
  end
63
-
64
- def as_json(...)
65
- raw.as_json(...)
66
- end
67
47
  end
68
48
  end
69
49
  end
@@ -3,32 +3,16 @@
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
11
  end
12
12
 
13
13
  def call(...)
14
14
  raw.call(...)
15
15
  end
16
-
17
- def to_s
18
- raw.name
19
- end
20
-
21
- def inspect
22
- to_s
23
- end
24
-
25
- def self.name
26
- "Class"
27
- end
28
-
29
- def as_json(...)
30
- raw.name.as_json(...)
31
- end
32
16
  end
33
17
  end
34
18
  end
@@ -0,0 +1,16 @@
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
+ end
10
+
11
+ def evaluate(...)
12
+ raw.evaluate(...)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -5,14 +5,11 @@ 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
- end
13
-
14
- def self.name
15
- "Context"
12
+ @parent = Context.new(args.second) if args.second
16
13
  end
17
14
 
18
15
  def lookup!(identifier)
@@ -21,12 +18,12 @@ class Code
21
18
  elsif parent?
22
19
  parent.lookup!(identifier)
23
20
  else
24
- raise Code::Error::Undefined, "#{identifier} is not defined"
21
+ raise Error::Undefined, "#{identifier} is not defined"
25
22
  end
26
23
  end
27
24
 
28
25
  def merge(other)
29
- Context.new(raw.merge(other.raw), parent: parent || other.parent)
26
+ Context.new(raw.merge(other.raw), parent || other.parent)
30
27
  end
31
28
 
32
29
  def parent?
@@ -3,15 +3,11 @@
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
11
- end
12
-
13
- def self.name
14
- "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
+ rescue ::Date::Error
10
+ raise Error, "#{raw.inspect} is an invalid date"
15
11
  end
16
12
 
17
13
  def self.call(**args)
@@ -21,26 +17,38 @@ class Code
21
17
  when "tomorrow"
22
18
  sig(args)
23
19
  code_tomorrow
20
+ when "yesterday"
21
+ sig(args)
22
+ code_yesterday
23
+ when "today"
24
+ sig(args)
25
+ code_today
26
+ when "now"
27
+ sig(args)
28
+ code_now
24
29
  else
25
30
  super
26
31
  end
27
32
  end
28
33
 
29
- def self.code_tomorrow
34
+ def self.code_now
30
35
  ::Time.zone ||= Time::DEFAULT_ZONE
31
- new(::Time.zone.tomorrow)
36
+ new(::Time.zone.now.beginning_of_day)
32
37
  end
33
38
 
34
- def inspect
35
- to_s
39
+ def self.code_today
40
+ ::Time.zone ||= Time::DEFAULT_ZONE
41
+ new(::Time.zone.now.beginning_of_day)
36
42
  end
37
43
 
38
- def to_s
39
- raw.to_s
44
+ def self.code_tomorrow
45
+ ::Time.zone ||= Time::DEFAULT_ZONE
46
+ new(::Time.zone.tomorrow.beginning_of_day)
40
47
  end
41
48
 
42
- def as_json(...)
43
- raw.as_json(...)
49
+ def self.code_yesterday
50
+ ::Time.zone ||= Time::DEFAULT_ZONE
51
+ new(::Time.zone.yesterday.beginning_of_day)
44
52
  end
45
53
  end
46
54
  end