code-ruby 0.10.4 → 0.11.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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +1 -1
  3. data/bin/console +5 -0
  4. data/lib/code/node/base_10.rb +10 -10
  5. data/lib/code/node/base_16.rb +7 -2
  6. data/lib/code/node/base_2.rb +7 -2
  7. data/lib/code/node/base_8.rb +7 -2
  8. data/lib/code/node/boolean.rb +5 -4
  9. data/lib/code/node/call.rb +10 -16
  10. data/lib/code/node/call_argument.rb +8 -4
  11. data/lib/code/node/code.rb +3 -2
  12. data/lib/code/node/decimal.rb +8 -7
  13. data/lib/code/node/dictionary.rb +11 -8
  14. data/lib/code/node/function.rb +4 -8
  15. data/lib/code/node/function_parameter.rb +3 -3
  16. data/lib/code/node/if.rb +13 -12
  17. data/lib/code/node/left_operation.rb +10 -10
  18. data/lib/code/node/list.rb +3 -3
  19. data/lib/code/node/negation.rb +8 -4
  20. data/lib/code/node/not.rb +8 -4
  21. data/lib/code/node/nothing.rb +4 -3
  22. data/lib/code/node/number.rb +3 -3
  23. data/lib/code/node/right_operation.rb +19 -16
  24. data/lib/code/node/splat.rb +8 -4
  25. data/lib/code/node/square_bracket.rb +8 -11
  26. data/lib/code/node/statement.rb +4 -4
  27. data/lib/code/node/string.rb +13 -11
  28. data/lib/code/node/ternary.rb +8 -8
  29. data/lib/code/node/unary_minus.rb +8 -4
  30. data/lib/code/node/while.rb +15 -13
  31. data/lib/code/node.rb +1 -7
  32. data/lib/code/object/function.rb +2 -4
  33. data/lib/code/object.rb +2 -6
  34. data/lib/code/parser/code.rb +1 -1
  35. data/lib/code/parser/left_operation.rb +2 -2
  36. data/lib/code/parser/list.rb +2 -2
  37. data/lib/code/parser/right_operation.rb +2 -2
  38. data/lib/code/parser/whitespace.rb +2 -2
  39. data/lib/code/type/sig.rb +2 -2
  40. data/lib/code/type.rb +3 -3
  41. data/lib/code/version.rb +1 -1
  42. data/lib/code-ruby.rb +1 -0
  43. metadata +2 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4fb166c32bc6cf7c79dd6e1743329312c9a922efc1cfb111a00cc3d87cac9c41
4
- data.tar.gz: 284f096cf17419c0688b36d000e77350580fb7f3ce7ad3ad221e6e1589e1ab4c
3
+ metadata.gz: 97ce31f3a36a57e14f607ded3383aa3c71866824c6e57541c70d48962c77b9ef
4
+ data.tar.gz: '0229023c391084763f03d2ffbfd82af81da2d996666719a49ad169d7740c4d6c'
5
5
  SHA512:
6
- metadata.gz: 3d294d5f00bd9f474585eb25392122a355e4202b99a4d62045e5237880c7835d555b8cd43b07c3791d0471c98c32587a7491d05aab14fcbd50daf0cd2268c958
7
- data.tar.gz: 38785eb41a2a7c28a421e8d0be54bd6cda5bf042503d9b31c2c3141a163877b68433141307520ab4cf666a5762f3c0f2b66d951ba03102374eec51a6531c500b
6
+ metadata.gz: 996b1594dbc1192dbad2b0c64d605d9eccff6d5622437ef5974464648e5f2cd2ee57aad50fce9279f8027f1378fc7c2652106265a2fc79bbe21b224210228c9d
7
+ data.tar.gz: ec405b4bc88648344f4860fb7350695aa447a5905e9a56e7230c771d5ea76e22515fe74ac0fc30771e27a9d67f4eda85b0d2475484d81a5d2c604c5a901913ae
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- code-ruby (0.10.3)
4
+ code-ruby (0.10.4)
5
5
  activesupport (~> 7)
6
6
  bigdecimal (~> 3)
7
7
  json (~> 2)
data/bin/console ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative "../lib/code-ruby"
4
+
5
+ binding.irb
@@ -4,26 +4,26 @@ class Code
4
4
  class Node
5
5
  class Base10 < Node
6
6
  def initialize(parsed)
7
- @whole = parsed.delete(:whole)
7
+ return if parsed.blank?
8
+ @whole = parsed.delete(:whole).presence
8
9
 
9
10
  if parsed.key?(:exponent)
10
- @exponent = Node::Statement.new(parsed.delete(:exponent))
11
+ @exponent = Node::Statement.new(parsed.delete(:exponent).presence)
11
12
  end
12
-
13
- super(parsed)
14
13
  end
15
14
 
16
15
  def evaluate(**args)
17
- if @exponent
16
+ if @exponent && @whole
18
17
  exponent = @exponent.evaluate(**args)
19
-
20
- if exponent.is_a?(::Code::Object::Integer)
21
- ::Code::Object::Integer.new(@whole.to_i, exponent:)
18
+ if exponent.is_a?(Object::Integer)
19
+ Object::Integer.new(@whole, exponent:)
22
20
  else
23
- ::Code::Object::Decimal.new(@whole, exponent:)
21
+ Object::Decimal.new(@whole, exponent:)
24
22
  end
23
+ elsif @whole
24
+ Object::Integer.new(@whole.to_i)
25
25
  else
26
- ::Code::Object::Integer.new(@whole.to_i)
26
+ Object::Nothing.new
27
27
  end
28
28
  end
29
29
  end
@@ -4,11 +4,16 @@ class Code
4
4
  class Node
5
5
  class Base16 < Node
6
6
  def initialize(parsed)
7
- @base_16 = parsed
7
+ return if parsed.blank?
8
+ @base_16 = parsed.presence
8
9
  end
9
10
 
10
11
  def evaluate(**_args)
11
- ::Code::Object::Integer.new(@base_16.to_i(16))
12
+ if @base_16
13
+ Object::Integer.new(@base_16.to_i(16))
14
+ else
15
+ Object::Nothing.new
16
+ end
12
17
  end
13
18
  end
14
19
  end
@@ -4,11 +4,16 @@ class Code
4
4
  class Node
5
5
  class Base2 < Node
6
6
  def initialize(parsed)
7
- @base_2 = parsed
7
+ return if parsed.blank?
8
+ @base_2 = parsed.presence
8
9
  end
9
10
 
10
11
  def evaluate(**_args)
11
- ::Code::Object::Integer.new(@base_2.to_i(2))
12
+ if @base_2
13
+ Object::Integer.new(@base_2.to_i(2))
14
+ else
15
+ Object::Nothing.new
16
+ end
12
17
  end
13
18
  end
14
19
  end
@@ -4,11 +4,16 @@ class Code
4
4
  class Node
5
5
  class Base8 < Node
6
6
  def initialize(parsed)
7
- @base_8 = parsed
7
+ return if parsed.blank?
8
+ @base_8 = parsed.presence
8
9
  end
9
10
 
10
11
  def evaluate(**_args)
11
- ::Code::Object::Integer.new(@base_8.to_i(8))
12
+ if @base_8
13
+ Object::Integer.new(@base_8.to_i(8))
14
+ else
15
+ Object::Nothing.new
16
+ end
12
17
  end
13
18
  end
14
19
  end
@@ -7,16 +7,17 @@ class Code
7
7
  FALSE_KEYWORD = "false"
8
8
 
9
9
  def initialize(parsed)
10
- @boolean = parsed
10
+ return if parsed.blank?
11
+ @boolean = parsed.presence
11
12
  end
12
13
 
13
14
  def evaluate(**_args)
14
15
  if @boolean == TRUE_KEYWORD
15
- ::Code::Object::Boolean.new(true)
16
+ Object::Boolean.new(true)
16
17
  elsif @boolean == FALSE_KEYWORD
17
- ::Code::Object::Boolean.new(false)
18
+ Object::Boolean.new(false)
18
19
  else
19
- raise NotImplementedError, @boolean
20
+ Object::Nothing.new
20
21
  end
21
22
  end
22
23
  end
@@ -5,14 +5,11 @@ class Code
5
5
  class Call < Node
6
6
  class Block < Node
7
7
  def initialize(parsed)
8
- @parameters =
9
- parsed
10
- .delete(:parameters) { [] }
11
- .map { |parameter| FunctionParameter.new(parameter) }
8
+ return if parsed.blank?
9
+ @parameters = parsed.delete(:parameters) { [] }.presence || []
10
+ @parameters.map! { |parameter| FunctionParameter.new(parameter) }
12
11
 
13
- @body = Code.new(parsed.delete(:body))
14
-
15
- super(parsed)
12
+ @body = Code.new(parsed.delete(:body).presence)
16
13
  end
17
14
 
18
15
  def evaluate(**_args)
@@ -23,21 +20,18 @@ class Code
23
20
  end
24
21
 
25
22
  def initialize(parsed)
26
- @name = parsed.delete(:name)
27
- @arguments =
28
- parsed
29
- .delete(:arguments) { [] }
30
- .map { |argument| CallArgument.new(argument) }
31
-
32
- @block = Call::Block.new(parsed.delete(:block)) if parsed.key?(:block)
23
+ return if parsed.blank?
24
+ @name = parsed.delete(:name).presence
25
+ @arguments = parsed.delete(:arguments).presence || []
26
+ @arguments.map! { |argument| CallArgument.new(argument) }
33
27
 
34
- super(parsed)
28
+ @block = Call::Block.new(parsed.delete(:block).presence) if parsed.key?(:block)
35
29
  end
36
30
 
37
31
  def evaluate(**args)
38
32
  arguments = []
39
33
 
40
- @arguments.each do |argument|
34
+ (@arguments || []).each do |argument|
41
35
  if argument.keyword?
42
36
  if arguments.last&.value.is_a?(Object::Dictionary)
43
37
  arguments.last.value.code_set(
@@ -4,15 +4,19 @@ class Code
4
4
  class Node
5
5
  class CallArgument < Node
6
6
  def initialize(parsed)
7
- @value = Node::Code.new(parsed.delete(:value))
8
- @name = parsed.delete(:name)
7
+ return if parsed.blank?
8
+ @value = Node::Code.new(parsed.delete(:value).presence)
9
+ @name = parsed.delete(:name).presence
9
10
  end
10
11
 
11
12
  def evaluate(**args)
12
13
  if @name
13
- Object::Argument.new(@value.evaluate(**args), name:)
14
+ Object::Argument.new(
15
+ @value&.evaluate(**args) || Object::Nothing.new,
16
+ name:
17
+ )
14
18
  else
15
- Object::Argument.new(@value.evaluate(**args))
19
+ Object::Argument.new(@value&.evaluate(**args) || Object::Nothing.new)
16
20
  end
17
21
  end
18
22
 
@@ -4,13 +4,14 @@ class Code
4
4
  class Node
5
5
  class Code < Node
6
6
  def initialize(parsed)
7
- @statements = parsed.map { |statement| Statement.new(statement) }
7
+ return if parsed.blank?
8
+ @statements = (parsed.presence || []).map { |statement| Statement.new(statement) }
8
9
  end
9
10
 
10
11
  def evaluate(**args)
11
12
  last = Object::Nothing.new
12
13
 
13
- @statements.each do |statement|
14
+ (@statements || []).each do |statement|
14
15
  last = statement.evaluate(**args.merge(object: Object::Global.new))
15
16
  end
16
17
 
@@ -4,23 +4,24 @@ class Code
4
4
  class Node
5
5
  class Decimal < Node
6
6
  def initialize(parsed)
7
- @decimal = parsed.delete(:decimal)
7
+ return if parsed.blank?
8
+ @decimal = parsed.delete(:decimal).presence
8
9
 
9
10
  if parsed.key?(:exponent)
10
- @exponent = Node::Statement.new(parsed.delete(:exponent))
11
+ @exponent = Statement.new(parsed.delete(:exponent).presence)
11
12
  end
12
-
13
- super(parsed)
14
13
  end
15
14
 
16
15
  def evaluate(**args)
17
- if @exponent
18
- ::Code::Object::Decimal.new(
16
+ if @exponent && @decimal
17
+ Object::Decimal.new(
19
18
  @decimal,
20
19
  exponent: @exponent.evaluate(**args)
21
20
  )
21
+ elsif @decimal
22
+ Object::Decimal.new(@decimal)
22
23
  else
23
- ::Code::Object::Decimal.new(@decimal)
24
+ Object::Nothing.new
24
25
  end
25
26
  end
26
27
  end
@@ -5,17 +5,20 @@ class Code
5
5
  class Dictionary < Node
6
6
  class KeyValue < Node
7
7
  def initialize(parsed)
8
+ return if parsed.blank?
8
9
  if parsed.key?(:statement)
9
- @key = Node::Statement.new(parsed.delete(:statement))
10
+ @key = Node::Statement.new(parsed.delete(:statement).presence)
10
11
  elsif parsed.key?(:name)
11
- @key = Node::String.new([{ text: parsed.delete(:name) }])
12
+ @key = Node::String.new([{ text: parsed.delete(:name).presence }])
12
13
  end
13
14
 
14
- @value = Node::Code.new(parsed.delete(:value)) if parsed[:value]
15
+ if parsed[:value].presence
16
+ @value = Node::Code.new(parsed.delete(:value).presence)
17
+ end
15
18
  end
16
19
 
17
20
  def evaluate(**args)
18
- key = @key.evaluate(**args)
21
+ key = @key&.evaluate(**args) || Object::Nothing.new
19
22
 
20
23
  if @value
21
24
  value = @value.evaluate(**args)
@@ -27,14 +30,14 @@ class Code
27
30
  end
28
31
 
29
32
  def initialize(parsed)
30
- parsed = [] if parsed == ""
31
- @key_values =
32
- parsed.map { |key_value| Node::Dictionary::KeyValue.new(key_value) }
33
+ return if parsed.blank?
34
+ @key_values = parsed.presence || []
35
+ @key_values.map! { |key_value| Node::Dictionary::KeyValue.new(key_value) }
33
36
  end
34
37
 
35
38
  def evaluate(**args)
36
39
  ::Code::Object::Dictionary.new(
37
- @key_values.map { |key_value| key_value.evaluate(**args) }.to_h
40
+ (@key_values || []).map { |key_value| key_value.evaluate(**args) }.to_h
38
41
  )
39
42
  end
40
43
  end
@@ -4,15 +4,11 @@ class Code
4
4
  class Node
5
5
  class Function < Node
6
6
  def initialize(parsed)
7
- @parameters = parsed.delete(:parameters) { [] }
8
- @parameters = [] if @parameters.empty?
7
+ return if parsed.blank?
8
+ @parameters = parsed.delete(:parameters).presence || []
9
+ @parameters.map! { |parameter| Node::FunctionParameter.new(parameter) }
9
10
 
10
- @parameters =
11
- @parameters.map { |parameter| Node::FunctionParameter.new(parameter) }
12
-
13
- @body = Node::Code.new(parsed.delete(:body))
14
-
15
- super(parsed)
11
+ @body = Node::Code.new(parsed.delete(:body).presence)
16
12
  end
17
13
 
18
14
  def evaluate(**_args)
@@ -4,9 +4,9 @@ class Code
4
4
  class Node
5
5
  class FunctionParameter < Node
6
6
  def initialize(parsed)
7
- @name = parsed.delete(:name)
8
- @keyword = !parsed.delete(:keyword).nil?
9
- super(parsed)
7
+ return if parsed.blank?
8
+ @name = parsed.delete(:name).presence
9
+ @keyword = parsed.delete(:keyword).present?
10
10
  end
11
11
 
12
12
  def name
data/lib/code/node/if.rb CHANGED
@@ -12,22 +12,23 @@ class Code
12
12
  attr_reader :operator, :statement, :body
13
13
 
14
14
  def initialize(parsed)
15
- @operator = parsed.delete(:operator)
16
- @body = Node::Code.new(parsed.delete(:body))
15
+ return if parsed.blank?
16
+ @operator = parsed.delete(:operator).presence
17
+ @body = Node::Code.new(parsed.delete(:body).presence)
17
18
 
18
- return unless parsed.key?(:statement)
19
-
20
- @statement = Node::Statement.new(parsed.delete(:statement))
19
+ if parsed.key?(:statement)
20
+ @statement = Node::Statement.new(parsed.delete(:statement).presence)
21
+ end
21
22
  end
22
23
  end
23
24
 
24
25
  def initialize(parsed)
25
- @first_operator = parsed.delete(:first_operator)
26
- @first_statement = Node::Statement.new(parsed.delete(:first_statement))
27
- @first_body = Node::Code.new(parsed.delete(:first_body))
28
- @elses =
29
- parsed.delete(:elses) { [] }.map { |elses| Node::If::Else.new(elses) }
30
- super(parsed)
26
+ return if parsed.blank?
27
+ @first_operator = parsed.delete(:first_operator).presence
28
+ @first_statement = Node::Statement.new(parsed.delete(:first_statement).presence)
29
+ @first_body = Node::Code.new(parsed.delete(:first_body).presence)
30
+ @elses = (parsed.delete(:elses).presence || [])
31
+ @elses.map! { |elses| Node::If::Else.new(elses) }
31
32
  end
32
33
 
33
34
  def evaluate(**args)
@@ -38,7 +39,7 @@ class Code
38
39
  @first_statement.evaluate(**args).falsy?
39
40
  @first_body.evaluate(**args)
40
41
  else
41
- @elses.each do |elses|
42
+ (@elses || []).each do |elses|
42
43
  if elses.operator == ELSIF_KEYWORD &&
43
44
  elses.statement.evaluate(**args).truthy?
44
45
  return elses.body.evaluate(**args)
@@ -10,8 +10,9 @@ class Code
10
10
  attr_reader :operator, :statement
11
11
 
12
12
  def initialize(parsed)
13
- @operator = parsed.delete(:operator)
14
- @statement = Statement.new(parsed.delete(:statement))
13
+ return if parsed.blank?
14
+ @operator = parsed.delete(:operator).presence
15
+ @statement = Statement.new(parsed.delete(:statement).presence)
15
16
  end
16
17
 
17
18
  def call?
@@ -20,15 +21,14 @@ class Code
20
21
  end
21
22
 
22
23
  def initialize(parsed)
23
- @first = Statement.new(parsed.delete(:first))
24
- @others =
25
- parsed.delete(:others).map { |operator| Operator.new(operator) }
26
-
27
- super(parsed)
24
+ return if parsed.blank?
25
+ @first = Statement.new(parsed.delete(:first).presence)
26
+ @others = parsed.delete(:others).presence || []
27
+ @others.map! { |operator| Operator.new(operator) }
28
28
  end
29
29
 
30
30
  def evaluate(**args)
31
- first = @first.evaluate(**args)
31
+ first = @first&.evaluate(**args) || Object::Nothing.new
32
32
 
33
33
  @others.reduce(first) do |left, right|
34
34
  if right.call?
@@ -46,11 +46,11 @@ class Code
46
46
  end
47
47
 
48
48
  def resolve(**args)
49
- first = @first.resolve(**args)
49
+ first = @first&.resolve(**args) || Object::Nothing.new
50
50
 
51
51
  list = Object::IdentifierList.new([first])
52
52
 
53
- @others.each do |other|
53
+ (@others || []).each do |other|
54
54
  list.code_append(
55
55
  other.statement.resolve(**args, object: list.code_last)
56
56
  )
@@ -4,13 +4,13 @@ class Code
4
4
  class Node
5
5
  class List < Node
6
6
  def initialize(parsed)
7
- parsed = [] if parsed == ""
8
- @elements = parsed.map { |element| Node::Code.new(element) }
7
+ return if parsed.blank?
8
+ @elements = (parsed.presence || []).map { |element| Node::Code.new(element) }
9
9
  end
10
10
 
11
11
  def evaluate(**args)
12
12
  ::Code::Object::List.new(
13
- @elements.map { |element| element.evaluate(**args) }
13
+ (@elements || []).map { |element| element.evaluate(**args) }
14
14
  )
15
15
  end
16
16
  end
@@ -4,13 +4,17 @@ class Code
4
4
  class Node
5
5
  class Negation < Node
6
6
  def initialize(parsed)
7
- @operator = parsed.delete(:operator)
8
- @right = Node::Statement.new(parsed.delete(:right))
9
- super(parsed)
7
+ return if parsed.blank?
8
+ @operator = parsed.delete(:operator).presence
9
+ @right = Node::Statement.new(parsed.delete(:right).presence)
10
10
  end
11
11
 
12
12
  def evaluate(**args)
13
- @right.evaluate(**args).call(operator: @operator, arguments: [], **args)
13
+ if @right
14
+ @right.evaluate(**args).call(operator: @operator, **args)
15
+ else
16
+ Object::Nothing.new
17
+ end
14
18
  end
15
19
  end
16
20
  end
data/lib/code/node/not.rb CHANGED
@@ -4,13 +4,17 @@ class Code
4
4
  class Node
5
5
  class Not < Node
6
6
  def initialize(parsed)
7
- @operator = parsed.delete(:operator)
8
- @right = Node::Statement.new(parsed.delete(:right))
9
- super(parsed)
7
+ return if parsed.blank?
8
+ @operator = parsed.delete(:operator).presence
9
+ @right = Node::Statement.new(parsed.delete(:right).presence)
10
10
  end
11
11
 
12
12
  def evaluate(**args)
13
- @right.evaluate(**args).call(operator: @operator, arguments: [], **args)
13
+ if @right
14
+ @right.evaluate(**args).call(operator: @operator, **args)
15
+ else
16
+ Object::Nothing.new
17
+ end
14
18
  end
15
19
  end
16
20
  end
@@ -3,12 +3,13 @@
3
3
  class Code
4
4
  class Node
5
5
  class Nothing < Node
6
- def initialize(nothing)
7
- @nothing = nothing
6
+ def initialize(parsed)
7
+ return if parsed.blank?
8
+ @nothing = parsed.presence
8
9
  end
9
10
 
10
11
  def evaluate(**_args)
11
- ::Code::Object::Nothing.new
12
+ Object::Nothing.new
12
13
  end
13
14
  end
14
15
  end
@@ -4,6 +4,8 @@ class Code
4
4
  class Node
5
5
  class Number < Node
6
6
  def initialize(parsed)
7
+ return if parsed.blank?
8
+
7
9
  if parsed.key?(:decimal)
8
10
  @statement = Node::Decimal.new(parsed.delete(:decimal))
9
11
  elsif parsed.key?(:base_16)
@@ -15,12 +17,10 @@ class Code
15
17
  elsif parsed.key?(:base_2)
16
18
  @statement = Node::Base2.new(parsed.delete(:base_2))
17
19
  end
18
-
19
- super(parsed)
20
20
  end
21
21
 
22
22
  def evaluate(**args)
23
- @statement.evaluate(**args)
23
+ @statement&.evaluate(**args) || Object::Nothing.new
24
24
  end
25
25
  end
26
26
  end
@@ -6,23 +6,22 @@ class Code
6
6
  EQUAL = "="
7
7
 
8
8
  def initialize(parsed)
9
- @left = Statement.new(parsed.delete(:left))
10
- @operator = parsed.delete(:operator)
11
- @right = Statement.new(parsed.delete(:right))
12
-
13
- super(parsed)
9
+ return if parsed.blank?
10
+ @left = Statement.new(parsed.delete(:left).presence)
11
+ @operator = parsed.delete(:operator).presence
12
+ @right = Statement.new(parsed.delete(:right).presence)
14
13
  end
15
14
 
16
15
  def evaluate(**args)
17
16
  case @operator
18
17
  when "if"
19
- if @right.evaluate(**args).truthy?
20
- @left.evaluate(**args)
18
+ if (@right&.evaluate(**args) || Object::Nothing.new).truthy?
19
+ @left&.evaluate(**args) || Object::Nothing.new
21
20
  else
22
21
  Object::Nothing.new
23
22
  end
24
23
  when "unless"
25
- if @right.evaluate(**args).truthy?
24
+ if (@right&.evaluate(**args) || Object::Nothing.new).truthy?
26
25
  Object::Nothing.new
27
26
  else
28
27
  @left.evaluate(**args)
@@ -30,24 +29,28 @@ class Code
30
29
  when "while"
31
30
  left = Object::Nothing.new
32
31
 
33
- left = @left.evaluate(**args) while @right.evaluate(**args).truthy?
32
+ while (@right&.evaluate(**args) || Object::Nothing.new).truthy?
33
+ left = @left&.evaluate(**args) || Object::Nothing.new
34
+ end
34
35
 
35
36
  left
36
37
  when "until"
37
38
  left = Object::Nothing.new
38
39
 
39
- left = @left.evaluate(**args) while @right.evaluate(**args).falsy?
40
+ while (@right&.evaluate(**args) || Object::Nothing.new).falsy?
41
+ left = @left&.evaluate(**args) || Object::Nothing.new
42
+ end
40
43
 
41
44
  left
42
45
  when "rescue"
43
46
  begin
44
- @left.evaluate(**args)
47
+ @left&.evaluate(**args) || Object::Nothing.new
45
48
  rescue Error
46
- @right.evaluate(**args)
49
+ @right&.evaluate(**args) || Object::Nothing.new
47
50
  end
48
51
  when /=$/
49
- right = @right.evaluate(**args)
50
- left = @left.resolve(**args)
52
+ right = @right&.evaluate(**args) || Object::Nothing.new
53
+ left = @left&.resolve(**args) || Object::Nothing.new
51
54
 
52
55
  left.call(
53
56
  operator: @operator,
@@ -55,8 +58,8 @@ class Code
55
58
  **args
56
59
  )
57
60
  else
58
- right = @right.evaluate(**args)
59
- left = @left.evaluate(**args)
61
+ right = @right&.evaluate(**args) || Object::Nothing.new
62
+ left = @left&.evaluate(**args) || Object::Nothing.new
60
63
 
61
64
  left.call(
62
65
  operator: @operator,
@@ -4,13 +4,17 @@ class Code
4
4
  class Node
5
5
  class Splat < Node
6
6
  def initialize(parsed)
7
- @operator = parsed.delete(:operator)
8
- @right = Node::Statement.new(parsed.delete(:right))
9
- super(parsed)
7
+ return if parsed.blank?
8
+ @operator = parsed.delete(:operator).presence
9
+ @right = Node::Statement.new(parsed.delete(:right).presence)
10
10
  end
11
11
 
12
12
  def evaluate(**args)
13
- @right.evaluate(**args).call(operator: @operator, arguments: [], **args)
13
+ if @right
14
+ @right.evaluate(**args).call(operator: @operator, **args)
15
+ else
16
+ Object::Nothing.new
17
+ end
14
18
  end
15
19
  end
16
20
  end
@@ -4,29 +4,26 @@ class Code
4
4
  class Node
5
5
  class SquareBracket < Node
6
6
  def initialize(parsed)
7
- @left = Node::Statement.new(parsed.delete(:left))
8
- @statements =
9
- parsed
10
- .delete(:statements)
11
- .map { |statement| Node::Statement.new(statement) }
12
-
13
- super(parsed)
7
+ return if parsed.blank?
8
+ @left = Node::Statement.new(parsed.delete(:left).presence)
9
+ @statements = parsed.delete(:statements).presence || []
10
+ @statements.map! { |statement| Node::Statement.new(statement) }
14
11
  end
15
12
 
16
13
  def evaluate(**args)
17
- left = @left.evaluate(**args)
14
+ left = @left&.evaluate(**args) || Object::Nothing.new
18
15
 
19
- @statements.reduce(left) do |object, statement|
16
+ (@statements || []).reduce(left) do |object, statement|
20
17
  object.code_fetch(statement.evaluate(**args))
21
18
  end
22
19
  end
23
20
 
24
21
  def resolve(**args)
25
- left = @left.resolve(**args)
22
+ left = @left&.resolve(**args) || Object::Nothing.new
26
23
 
27
24
  list = Object::IdentifierList.new([left])
28
25
 
29
- @statements.each do |statement|
26
+ (@statements || []).each do |statement|
30
27
  list.code_append(statement.evaluate(**args))
31
28
  end
32
29
 
@@ -4,6 +4,8 @@ class Code
4
4
  class Node
5
5
  class Statement < Node
6
6
  def initialize(parsed)
7
+ return if parsed.blank?
8
+
7
9
  if parsed.key?(:nothing)
8
10
  @statement = Node::Nothing.new(parsed.delete(:nothing))
9
11
  elsif parsed.key?(:boolean)
@@ -51,16 +53,14 @@ class Code
51
53
  elsif parsed.key?(:square_bracket)
52
54
  @statement = Node::SquareBracket.new(parsed.delete(:square_bracket))
53
55
  end
54
-
55
- super(parsed)
56
56
  end
57
57
 
58
58
  def evaluate(**args)
59
- @statement.evaluate(**args)
59
+ @statement&.evaluate(**args) || Object::Nothing.new
60
60
  end
61
61
 
62
62
  def resolve(**args)
63
- @statement.resolve(**args)
63
+ @statement&.resolve(**args) || Object::Nothing.new
64
64
  end
65
65
  end
66
66
  end
@@ -6,22 +6,25 @@ class Code
6
6
  class Part < Node
7
7
  class Code < Node
8
8
  def initialize(parsed)
9
- @code = Node::Code.new(parsed)
9
+ return if parsed.blank?
10
+ @code = Node::Code.new(parsed.presence)
10
11
  end
11
12
 
12
13
  def evaluate(**args)
13
- @code.evaluate(**args)
14
+ @code&.evaluate(**args) || Object::Nothing.new
14
15
  end
15
16
  end
16
17
 
17
18
  class Text < Node
18
19
  def initialize(parsed)
20
+ return if parsed.blank?
19
21
  @text = parsed
20
22
  end
21
23
 
22
24
  def evaluate(**_args)
23
25
  ::Code::Object::String.new(
24
26
  @text
27
+ .to_s
25
28
  .gsub('\n', "\n")
26
29
  .gsub('\r', "\r")
27
30
  .gsub('\t', "\t")
@@ -34,29 +37,28 @@ class Code
34
37
  end
35
38
 
36
39
  def initialize(parsed)
40
+ return if parsed.blank?
41
+
37
42
  if parsed.key?(:text)
38
- @part = Node::String::Part::Text.new(parsed.delete(:text))
43
+ @part = Node::String::Part::Text.new(parsed.delete(:text).presence)
39
44
  elsif parsed.key?(:code)
40
- @part = Node::String::Part::Code.new(parsed.delete(:code))
45
+ @part = Node::String::Part::Code.new(parsed.delete(:code).presence)
41
46
  end
42
-
43
- super(parsed)
44
47
  end
45
48
 
46
49
  def evaluate(**args)
47
- @part.evaluate(**args)
50
+ @part&.evaluate(**args) || Object::Nothing.new
48
51
  end
49
52
  end
50
53
 
51
54
  def initialize(parsed)
52
- parsed = [] if parsed == ""
53
-
54
- @parts = parsed.map { |part| Node::String::Part.new(part) }
55
+ return if parsed.blank?
56
+ @parts = (parsed.presence || []).map { |part| Node::String::Part.new(part) }
55
57
  end
56
58
 
57
59
  def evaluate(**args)
58
60
  ::Code::Object::String.new(
59
- @parts.map { |part| part.evaluate(**args) }.map(&:to_s).join
61
+ (@parts || []).map { |part| part.evaluate(**args) }.map(&:to_s).join
60
62
  )
61
63
  end
62
64
  end
@@ -4,17 +4,17 @@ class Code
4
4
  class Node
5
5
  class Ternary < Node
6
6
  def initialize(parsed)
7
- @left = Node::Statement.new(parsed.delete(:left))
8
- @middle = Node::Statement.new(parsed.delete(:middle))
9
- @right = Node::Statement.new(parsed.delete(:right)) if parsed.key?(
10
- :right
11
- )
12
- super(parsed)
7
+ return if parsed.blank?
8
+ @left = Node::Statement.new(parsed.delete(:left).presence)
9
+ @middle = Node::Statement.new(parsed.delete(:middle).presence)
10
+ if parsed.key?(:right)
11
+ @right = Node::Statement.new(parsed.delete(:right).presence)
12
+ end
13
13
  end
14
14
 
15
15
  def evaluate(**args)
16
- if @left.evaluate(**args).truthy?
17
- @middle.evaluate(**args)
16
+ if (@left&.evaluate(**args) || Object::Nothing.new).truthy?
17
+ @middle&.evaluate(**args) || Object::Nothing.new
18
18
  elsif @right
19
19
  @right.evaluate(**args)
20
20
  else
@@ -4,13 +4,17 @@ class Code
4
4
  class Node
5
5
  class UnaryMinus < Node
6
6
  def initialize(parsed)
7
- @operator = parsed.delete(:operator)
8
- @right = Node::Statement.new(parsed.delete(:right))
9
- super(parsed)
7
+ return if parsed.blank?
8
+ @operator = parsed.delete(:operator).presence
9
+ @right = Node::Statement.new(parsed.delete(:right).presence)
10
10
  end
11
11
 
12
12
  def evaluate(**args)
13
- @right.evaluate(**args).call(operator: @operator, arguments: [], **args)
13
+ if @right
14
+ @right.evaluate(**args).call(operator: @operator, **args)
15
+ else
16
+ Object::Nothing.new
17
+ end
14
18
  end
15
19
  end
16
20
  end
@@ -8,12 +8,12 @@ class Code
8
8
  LOOP_KEYWORD = "loop"
9
9
 
10
10
  def initialize(parsed)
11
- @operator = parsed.delete(:operator)
12
- @statement = Statement.new(parsed.delete(:statement)) if parsed[
13
- :statement
14
- ]
15
- @body = Code.new(parsed.delete(:body))
16
- super(parsed)
11
+ return if parsed.blank?
12
+ @operator = parsed.delete(:operator).presence
13
+ if parsed.key?(:statement)
14
+ @statement = Statement.new(parsed.delete(:statement))
15
+ end
16
+ @body = Code.new(parsed.delete(:body).presence)
17
17
  end
18
18
 
19
19
  def evaluate(**args)
@@ -21,22 +21,24 @@ class Code
21
21
  when WHILE_KEYWORD
22
22
  last = Object::Nothing.new
23
23
 
24
- last = @body.evaluate(**args) while @statement.evaluate(
25
- **args
26
- ).truthy?
24
+ while (@statement&.evaluate(**args) || Object::Nothing.new).truthy?
25
+ last = @body&.evaluate(**args) || Object::Nothing.new
26
+ end
27
27
 
28
28
  last
29
29
  when UNTIL_KEYWORD
30
30
  last = Object::Nothing.new
31
31
 
32
- last = @body.evaluate(**args) while @statement.evaluate(**args).falsy?
32
+ while (@statement&.evaluate(**args) || Object::Nothing.new).falsy?
33
+ last = @body&.evaluate(**args) || Object::Nothing.new
34
+ end
33
35
 
34
36
  last
35
37
  when LOOP_KEYWORD
36
- loop { @body.evaluate(**args) }
37
- raise NotImplementedError
38
+ loop { @body&.evaluate(**args) || Object::Nothing.new }
39
+ Object::Nothing.new
38
40
  else
39
- raise NotImplementedError, @operator
41
+ Object::Nothing.new
40
42
  end
41
43
  rescue Error::Break => e
42
44
  e.value || Object::Nothing.new
data/lib/code/node.rb CHANGED
@@ -2,14 +2,8 @@
2
2
 
3
3
  class Code
4
4
  class Node
5
- def initialize(parsed)
6
- return if parsed.nil? || parsed.empty?
7
-
8
- raise NotImplementedError, "#{self.class.name}: #{parsed.inspect}"
9
- end
10
-
11
5
  def evaluate(**_args)
12
- raise NotImplementedError, "#{self.class.name}#evaluate"
6
+ Object::Nothing.new
13
7
  end
14
8
 
15
9
  def resolve(...)
@@ -6,8 +6,8 @@ class Code
6
6
  attr_reader :parameters, :body
7
7
 
8
8
  def initialize(parameters:, body:)
9
- @parameters = parameters
10
- @body = body
9
+ @parameters = parameters.presence || []
10
+ @body = body.presence || Node::Code.new
11
11
  end
12
12
 
13
13
  def self.name
@@ -57,8 +57,6 @@ class Code
57
57
  &.value
58
58
  argument = parameter.evaluate(**globals) if argument.nil?
59
59
  context.code_set(parameter.name, argument)
60
- else
61
- raise NotImplementedError
62
60
  end
63
61
  end
64
62
 
data/lib/code/object.rb CHANGED
@@ -292,10 +292,6 @@ class Code
292
292
  end
293
293
 
294
294
  def hash
295
- unless respond_to?(:raw)
296
- raise NotImplementedError, "#{self.class.name}#hash"
297
- end
298
-
299
295
  [self.class, raw].hash
300
296
  end
301
297
 
@@ -309,7 +305,7 @@ class Code
309
305
  end
310
306
 
311
307
  def to_s
312
- raise NotImplementedError, "#{self.class.name}#to_s"
308
+ raw.to_s
313
309
  end
314
310
 
315
311
  def inspect
@@ -325,7 +321,7 @@ class Code
325
321
  end
326
322
 
327
323
  def as_json(...)
328
- raise NotImplementedError, "#{self.class}#as_json"
324
+ raw.as_json
329
325
  end
330
326
  end
331
327
  end
@@ -20,7 +20,7 @@ class Code
20
20
  end
21
21
 
22
22
  def root
23
- present | whitespace?.aka(:whitespace).then { [] }
23
+ present | whitespace?
24
24
  end
25
25
  end
26
26
  end
@@ -4,7 +4,7 @@ class Code
4
4
  class Parser
5
5
  class LeftOperation < Language
6
6
  def statement
7
- raise NotImplementedError
7
+ Statement
8
8
  end
9
9
 
10
10
  def whitespace
@@ -16,7 +16,7 @@ class Code
16
16
  end
17
17
 
18
18
  def operator
19
- raise NotImplementedError
19
+ str("")
20
20
  end
21
21
 
22
22
  def right_statement
@@ -32,8 +32,8 @@ class Code
32
32
  end
33
33
 
34
34
  def element
35
- (whitespace? << code_present << (whitespace? << comma).maybe) |
36
- (whitespace? << code << whitespace? << comma)
35
+ (whitespace? << code_present << (whitespace? << comma.ignore).maybe) |
36
+ (whitespace? << code << whitespace? << comma.ignore)
37
37
  end
38
38
 
39
39
  def root
@@ -4,7 +4,7 @@ class Code
4
4
  class Parser
5
5
  class RightOperation < Language
6
6
  def statement
7
- raise NotImplementedError
7
+ Statement
8
8
  end
9
9
 
10
10
  def whitespace
@@ -16,7 +16,7 @@ class Code
16
16
  end
17
17
 
18
18
  def operator
19
- raise NotImplementedError
19
+ str("")
20
20
  end
21
21
 
22
22
  def right_statement
@@ -37,14 +37,14 @@ class Code
37
37
  end
38
38
 
39
39
  def without_newline
40
- (space | multi_line_comment).repeat(1)
40
+ (space | multi_line_comment).repeat(1).ignore
41
41
  end
42
42
 
43
43
  def root
44
44
  (
45
45
  space | newline | hash_comment | double_slash_comment |
46
46
  multi_line_comment
47
- ).repeat(1) | any.absent
47
+ ).repeat(1).ignore | any.absent
48
48
  end
49
49
  end
50
50
  end
data/lib/code/type/sig.rb CHANGED
@@ -40,11 +40,11 @@ class Code
40
40
  end
41
41
 
42
42
  def actual_arguments
43
- args[:arguments].map(&:value)
43
+ args.fetch(:arguments, []).map(&:value)
44
44
  end
45
45
 
46
46
  def operator
47
- args[:operator] || "call"
47
+ args.fetch(:operator, nil) || "call"
48
48
  end
49
49
 
50
50
  def function
data/lib/code/type.rb CHANGED
@@ -3,11 +3,11 @@
3
3
  class Code
4
4
  class Type
5
5
  def name
6
- raise NotImplementedError, "#{self.class}#name"
6
+ "Type"
7
7
  end
8
8
 
9
- def valid?(argument)
10
- raise NotImplementedError, "#{self.class}#valid?"
9
+ def valid?(_argument)
10
+ false
11
11
  end
12
12
 
13
13
  def valid_for?(expected:, actual:)
data/lib/code/version.rb CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  require_relative "../code"
4
4
 
5
- Code::Version = Gem::Version.new("0.10.4")
5
+ Code::Version = Gem::Version.new("0.11.0")
data/lib/code-ruby.rb CHANGED
@@ -4,6 +4,7 @@ require "active_support"
4
4
  require "active_support/core_ext/date/conversions"
5
5
  require "active_support/core_ext/numeric/time"
6
6
  require "active_support/core_ext/object/json"
7
+ require "active_support/core_ext/object/blank"
7
8
  require "bigdecimal"
8
9
  require "json"
9
10
  require "language-ruby"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: code-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.4
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dorian Marié
@@ -95,6 +95,7 @@ files:
95
95
  - Gemfile.lock
96
96
  - README.md
97
97
  - bin/code
98
+ - bin/console
98
99
  - code-ruby.gemspec
99
100
  - lib/code-ruby.rb
100
101
  - lib/code.rb