template-ruby 0.1.0 → 0.2.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 (124) hide show
  1. checksums.yaml +4 -4
  2. data/.editorconfig +9 -0
  3. data/.gitignore +1 -0
  4. data/.prettierrc +3 -0
  5. data/CHANGELOG.md +22 -0
  6. data/Gemfile.lock +5 -5
  7. data/README.md +10 -0
  8. data/bin/template +39 -0
  9. data/docs/euler/1.template +14 -0
  10. data/docs/euler/2.template +16 -0
  11. data/docs/euler/3.template +16 -0
  12. data/docs/euler/4.template +11 -0
  13. data/docs/euler/5.template +14 -0
  14. data/docs/precedence.template +94 -0
  15. data/lib/code/error.rb +15 -0
  16. data/lib/code/node/base_10_decimal.rb +12 -7
  17. data/lib/code/node/base_10_integer.rb +13 -4
  18. data/lib/code/node/base_10_number.rb +3 -3
  19. data/lib/code/node/base_16_number.rb +2 -2
  20. data/lib/code/node/base_2_number.rb +2 -2
  21. data/lib/code/node/base_8_number.rb +2 -2
  22. data/lib/code/node/block.rb +17 -0
  23. data/lib/code/node/boolean.rb +13 -4
  24. data/lib/code/node/call.rb +41 -8
  25. data/lib/code/node/call_argument.rb +37 -0
  26. data/lib/code/node/chained_call.rb +38 -0
  27. data/lib/code/node/code.rb +4 -7
  28. data/lib/code/node/defined.rb +19 -0
  29. data/lib/code/node/dictionnary.rb +11 -7
  30. data/lib/code/node/dictionnary_key_value.rb +3 -3
  31. data/lib/code/node/equal.rb +36 -0
  32. data/lib/code/node/function.rb +17 -0
  33. data/lib/code/node/function_argument.rb +45 -0
  34. data/lib/code/node/group.rb +13 -0
  35. data/lib/code/node/if.rb +55 -0
  36. data/lib/code/node/if_modifier.rb +48 -0
  37. data/lib/code/node/keyword_call_argument.rb +30 -0
  38. data/lib/code/node/keyword_function_argument.rb +33 -0
  39. data/lib/code/node/list.rb +10 -4
  40. data/lib/code/node/name.rb +37 -4
  41. data/lib/code/node/negation.rb +33 -0
  42. data/lib/code/node/not_keyword.rb +13 -0
  43. data/lib/code/node/nothing.rb +2 -2
  44. data/lib/code/node/number.rb +3 -3
  45. data/lib/code/node/operation.rb +33 -0
  46. data/lib/code/node/or_keyword.rb +34 -0
  47. data/lib/code/node/power.rb +16 -0
  48. data/lib/code/node/range.rb +31 -0
  49. data/lib/code/node/regular_call_argument.rb +34 -0
  50. data/lib/code/node/regular_function_argument.rb +36 -0
  51. data/lib/code/node/rescue.rb +16 -0
  52. data/lib/code/node/statement.rb +53 -3
  53. data/lib/code/node/string.rb +2 -2
  54. data/lib/code/node/ternary.rb +26 -0
  55. data/lib/code/node/unary_minus.rb +22 -0
  56. data/lib/code/node/while.rb +42 -0
  57. data/lib/code/node.rb +10 -0
  58. data/lib/code/object/argument.rb +41 -0
  59. data/lib/code/object/boolean.rb +8 -9
  60. data/lib/code/object/decimal.rb +32 -9
  61. data/lib/code/object/dictionnary.rb +33 -10
  62. data/lib/code/object/function.rb +64 -0
  63. data/lib/code/object/integer.rb +94 -7
  64. data/lib/code/object/list.rb +190 -10
  65. data/lib/code/object/nothing.rb +10 -9
  66. data/lib/code/object/number.rb +6 -0
  67. data/lib/code/object/range.rb +158 -0
  68. data/lib/code/object/string.rb +37 -7
  69. data/lib/code/object.rb +121 -2
  70. data/lib/code/parser/addition.rb +29 -0
  71. data/lib/code/parser/and_operator.rb +28 -0
  72. data/lib/code/parser/bitwise_and.rb +28 -0
  73. data/lib/code/parser/bitwise_or.rb +29 -0
  74. data/lib/code/parser/call.rb +77 -3
  75. data/lib/code/parser/code.rb +2 -1
  76. data/lib/code/parser/defined.rb +20 -0
  77. data/lib/code/parser/equal.rb +42 -0
  78. data/lib/code/parser/equality.rb +36 -0
  79. data/lib/code/parser/function.rb +57 -0
  80. data/lib/code/parser/greater_than.rb +33 -0
  81. data/lib/code/parser/group.rb +17 -0
  82. data/lib/code/parser/if.rb +33 -0
  83. data/lib/code/parser/if_modifier.rb +28 -0
  84. data/lib/code/parser/multiplication.rb +30 -0
  85. data/lib/code/parser/name.rb +44 -4
  86. data/lib/code/parser/negation.rb +19 -0
  87. data/lib/code/parser/not_keyword.rb +21 -0
  88. data/lib/code/parser/nothing.rb +2 -2
  89. data/lib/code/parser/or_keyword.rb +29 -0
  90. data/lib/code/parser/or_operator.rb +28 -0
  91. data/lib/code/parser/power.rb +25 -0
  92. data/lib/code/parser/range.rb +25 -0
  93. data/lib/code/parser/rescue.rb +23 -0
  94. data/lib/code/parser/shift.rb +31 -0
  95. data/lib/code/parser/statement.rb +1 -4
  96. data/lib/code/parser/string.rb +7 -1
  97. data/lib/code/parser/ternary.rb +25 -0
  98. data/lib/code/parser/unary_minus.rb +13 -0
  99. data/lib/code/parser/while.rb +25 -0
  100. data/lib/code.rb +5 -7
  101. data/lib/template/node/code_part.rb +2 -2
  102. data/lib/template/node/part.rb +2 -2
  103. data/lib/template/node/template.rb +4 -2
  104. data/lib/template/node/text_part.rb +1 -1
  105. data/lib/template/parser/template.rb +6 -2
  106. data/lib/template-ruby.rb +4 -0
  107. data/lib/template.rb +9 -4
  108. data/spec/call_spec.rb +22 -0
  109. data/spec/code/error/type_error_spec.rb +65 -0
  110. data/spec/code/parser/boolean_spec.rb +1 -1
  111. data/spec/code/parser/call_spec.rb +38 -11
  112. data/spec/code/parser/dictionnary_spec.rb +11 -11
  113. data/spec/code/parser/function_spec.rb +32 -0
  114. data/spec/code/parser/list_spec.rb +5 -5
  115. data/spec/code/parser/nothing_spec.rb +1 -1
  116. data/spec/code/parser/number_spec.rb +35 -35
  117. data/spec/code/parser/string_spec.rb +3 -2
  118. data/spec/code_spec.rb +75 -3
  119. data/spec/function_spec.rb +26 -0
  120. data/spec/spec_helper.rb +2 -0
  121. data/spec/template/parser/template_spec.rb +1 -1
  122. data/spec/template_spec.rb +3 -6
  123. data/template-ruby.gemspec +6 -3
  124. metadata +76 -4
@@ -1,16 +1,20 @@
1
1
  class Code
2
2
  class Node
3
- class Dictionnary
3
+ class Dictionnary < Node
4
4
  def initialize(key_values)
5
- @key_values =
6
- key_values.map do |key_value|
7
- ::Code::Node::DictionnaryKeyValue.new(key_value)
8
- end
5
+ if key_values.blank?
6
+ @key_values = []
7
+ else
8
+ @key_values =
9
+ key_values.map do |key_value|
10
+ ::Code::Node::DictionnaryKeyValue.new(key_value)
11
+ end
12
+ end
9
13
  end
10
14
 
11
- def evaluate(context)
15
+ def evaluate(**args)
12
16
  ::Code::Object::Dictionnary.new(
13
- @key_values.map { |key_value| key_value.evaluate(context) }.to_h
17
+ @key_values.map { |key_value| key_value.evaluate(**args) }.to_h,
14
18
  )
15
19
  end
16
20
  end
@@ -1,6 +1,6 @@
1
1
  class Code
2
2
  class Node
3
- class DictionnaryKeyValue
3
+ class DictionnaryKeyValue < Node
4
4
  def initialize(key_value)
5
5
  @key = key_value.fetch(:key)
6
6
 
@@ -15,8 +15,8 @@ class Code
15
15
  @value = ::Code::Node::Code.new(key_value.fetch(:value))
16
16
  end
17
17
 
18
- def evaluate(context)
19
- [@key.evaluate(context), @value.evaluate(context)]
18
+ def evaluate(**args)
19
+ [@key.evaluate(**args), @value.evaluate(**args)]
20
20
  end
21
21
  end
22
22
  end
@@ -0,0 +1,36 @@
1
+ class Code
2
+ class Node
3
+ class Equal < Node
4
+ def initialize(equal)
5
+ @left = equal.fetch(:left).fetch(:name)
6
+ @operator = equal.fetch(:operator)
7
+ @right = ::Code::Node::Statement.new(equal.fetch(:right))
8
+ end
9
+
10
+ def evaluate(**args)
11
+ right = @right.evaluate(**args)
12
+ context = args.fetch(:context)
13
+
14
+ if operator
15
+ if context[left]
16
+ context[left] = simple_call(context[left], operator, right, **args)
17
+ else
18
+ raise ::Code::Error::UndefinedVariable.new("#{left} is undefined")
19
+ end
20
+ else
21
+ context[left] = right
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def operator
28
+ @operator.to_s[0...-1].to_sym.presence
29
+ end
30
+
31
+ def left
32
+ ::Code::Object::String.new(@left.to_s)
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,17 @@
1
+ class Code
2
+ class Node
3
+ class Function < Node
4
+ def initialize(function)
5
+ @body = ::Code::Node::Code.new(function.fetch(:body))
6
+ @arguments = function.fetch(:arguments, [])
7
+ @arguments.map! do |argument|
8
+ ::Code::Node::FunctionArgument.new(argument)
9
+ end
10
+ end
11
+
12
+ def evaluate(**args)
13
+ ::Code::Object::Function.new(arguments: @arguments, body: @body)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,45 @@
1
+ class Code
2
+ class Node
3
+ class FunctionArgument < Node
4
+ def initialize(argument)
5
+ if argument.key?(:regular)
6
+ @argument =
7
+ ::Code::Node::RegularFunctionArgument.new(argument.fetch(:regular))
8
+ elsif argument.key?(:keyword)
9
+ @argument =
10
+ ::Code::Node::KeywordFunctionArgument.new(argument.fetch(:keyword))
11
+ else
12
+ raise NotImplementedError.new(argument.inspect)
13
+ end
14
+ end
15
+
16
+ def evaluate(**args)
17
+ @argument.evaluate(**args)
18
+ end
19
+
20
+ def splat?
21
+ @argument.splat?
22
+ end
23
+
24
+ def keyword_splat?
25
+ @argument.keyword_splat?
26
+ end
27
+
28
+ def name
29
+ @argument.name
30
+ end
31
+
32
+ def block?
33
+ @argument.block?
34
+ end
35
+
36
+ def regular?
37
+ @argument.is_a?(::Code::Node::RegularFunctionArgument)
38
+ end
39
+
40
+ def keyword?
41
+ @argument.is_a?(::Code::Node::KeywordFunctionArgument)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,13 @@
1
+ class Code
2
+ class Node
3
+ class Group < Node
4
+ def initialize(group)
5
+ @code = ::Code::Node::Code.new(group)
6
+ end
7
+
8
+ def evaluate(**args)
9
+ @code.evaluate(**args)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,55 @@
1
+ class Code
2
+ class Node
3
+ class If < Node
4
+ IF_KEYWORD = "if"
5
+ UNLESS_KEYWORD = "unless"
6
+
7
+ class Else
8
+ def initialize(else_parsed)
9
+ if else_parsed.key?(:operator)
10
+ @operator = else_parsed.fetch(:operator)
11
+ @statement =
12
+ ::Code::Node::Statement.new(else_parsed.fetch(:statement))
13
+ end
14
+
15
+ @body = ::Code::Node::Code.new(else_parsed.fetch(:body))
16
+ end
17
+
18
+ attr_reader :operator, :body, :statement
19
+ end
20
+
21
+ def initialize(if_parsed)
22
+ @if_operator = if_parsed.fetch(:if_operator)
23
+ @if_statement =
24
+ ::Code::Node::Statement.new(if_parsed.fetch(:if_statement))
25
+ @if_body = ::Code::Node::Code.new(if_parsed.fetch(:if_body))
26
+ @elses = if_parsed.fetch(:elses, [])
27
+ @elses.map! { |else_parsed| ::Code::Node::If::Else.new(else_parsed) }
28
+ end
29
+
30
+ def evaluate(**args)
31
+ if_object = @if_statement.evaluate(**args)
32
+
33
+ if @if_operator == IF_KEYWORD && if_object.truthy?
34
+ @if_body.evaluate(**args)
35
+ elsif @if_operator == UNLESS_KEYWORD && if_object.falsy?
36
+ @if_body.evaluate(**args)
37
+ else
38
+ @elses.each do |else_node|
39
+ if else_node.operator == IF_KEYWORD
40
+ else_object = else_node.statement.evaluate(**args)
41
+ return else_node.body.evaluate(**args) if else_object.truthy?
42
+ elsif else_node.operator == UNLESS_KEYWORD
43
+ else_object = else_node.statement.evaluate(**args)
44
+ return else_node.body.evaluate(**args) if else_object.falsy?
45
+ elsif else_node.operator.nil?
46
+ return else_node.body.evaluate(**args)
47
+ end
48
+ end
49
+
50
+ ::Code::Object::Nothing.new
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,48 @@
1
+ class Code
2
+ class Node
3
+ class IfModifier < Node
4
+ IF_KEYWORD = :if
5
+ UNLESS_KEYWORD = :unless
6
+ WHILE_KEYWORD = :while
7
+ UNTIL_KEYWORD = :until
8
+
9
+ def initialize(if_modifier)
10
+ @left = ::Code::Node::Statement.new(if_modifier.fetch(:left))
11
+ @operator = if_modifier.fetch(:operator)
12
+ @right = ::Code::Node::Statement.new(if_modifier.fetch(:right))
13
+ end
14
+
15
+ def evaluate(**args)
16
+ if operator == IF_KEYWORD
17
+ right = @right.evaluate(**args)
18
+
19
+ right.truthy? ? @left.evaluate(**args) : ::Code::Object::Nothing.new
20
+ elsif operator == UNLESS_KEYWORD
21
+ right = @right.evaluate(**args)
22
+
23
+ right.truthy? ? ::Code::Object::Nothing.new : @left.evaluate(**args)
24
+ elsif operator == WHILE_KEYWORD
25
+ left = ::Code::Object::Nothing.new
26
+
27
+ left = @left.evaluate(**args) while @right.evaluate(**args).truthy?
28
+
29
+ left
30
+ elsif operator == UNTIL_KEYWORD
31
+ left = ::Code::Object::Nothing.new
32
+
33
+ left = @left.evaluate(**args) until @right.evaluate(**args).truthy?
34
+
35
+ left
36
+ else
37
+ raise NotImplementedError.new(operator.inspect)
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def operator
44
+ @operator.to_sym
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,30 @@
1
+ class Code
2
+ class Node
3
+ class KeywordCallArgument < Node
4
+ def initialize(argument)
5
+ @name = argument.fetch(:name)
6
+ @value = ::Code::Node::Code.new(argument.fetch(:value))
7
+ end
8
+
9
+ def evaluate(**args)
10
+ @value.evaluate(**args)
11
+ end
12
+
13
+ def name
14
+ ::Code::Object::String.new(@name.to_s)
15
+ end
16
+
17
+ def block?
18
+ false
19
+ end
20
+
21
+ def splat?
22
+ false
23
+ end
24
+
25
+ def keyword_splat?
26
+ false
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,33 @@
1
+ class Code
2
+ class Node
3
+ class KeywordFunctionArgument < Node
4
+ def initialize(argument)
5
+ @name = argument.fetch(:name)
6
+
7
+ if argument.key?(:default)
8
+ @default = ::Code::Node::Code.new(argument.fetch(:default))
9
+ end
10
+ end
11
+
12
+ def evaluate(**args)
13
+ @default ? @default.evaluate(**args) : ::Code::Object::Nothing.new
14
+ end
15
+
16
+ def name
17
+ ::Code::Object::String.new(@name.to_s)
18
+ end
19
+
20
+ def splat?
21
+ false
22
+ end
23
+
24
+ def keyword_splat?
25
+ false
26
+ end
27
+
28
+ def block?
29
+ false
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,12 +1,18 @@
1
1
  class Code
2
2
  class Node
3
- class List
3
+ class List < Node
4
4
  def initialize(codes)
5
- @codes = codes.map { |code| ::Code::Node::Code.new(code[:code]) }
5
+ @codes =
6
+ codes
7
+ .map do |code|
8
+ code.fetch(:code).presence &&
9
+ ::Code::Node::Code.new(code.fetch(:code))
10
+ end
11
+ .compact
6
12
  end
7
13
 
8
- def evaluate(context)
9
- ::Code::Object::List.new(@codes.map { |code| code.evaluate(context) })
14
+ def evaluate(**args)
15
+ ::Code::Object::List.new(@codes.map { |code| code.evaluate(**args) })
10
16
  end
11
17
  end
12
18
  end
@@ -1,17 +1,50 @@
1
1
  class Code
2
2
  class Node
3
- class Name
3
+ class Name < Node
4
4
  def initialize(name)
5
5
  @name = name
6
6
  end
7
7
 
8
- def evaluate(context)
9
- context.fetch(::Code::Object::String.new(name.to_s))
8
+ def evaluate(**args)
9
+ context = args.fetch(:context)
10
+ arguments = args.fetch(:arguments, [])
11
+ object = args.fetch(:object, nil)
12
+ io = args.fetch(:io)
13
+
14
+ if object
15
+ object.call(
16
+ context: context,
17
+ operator: name,
18
+ arguments: arguments,
19
+ io: io,
20
+ )
21
+ elsif context.key?(name)
22
+ object = context[name]
23
+
24
+ if object.is_a?(::Code::Object::Function)
25
+ object.call(
26
+ context: context,
27
+ operator: nil,
28
+ arguments: arguments,
29
+ io: io,
30
+ )
31
+ else
32
+ object
33
+ end
34
+ elsif name == "puts"
35
+ arguments.each { |argument| io.puts argument.value }
36
+
37
+ ::Code::Object::Nothing.new
38
+ else
39
+ raise ::Code::Error::Undefined.new("#{name} undefined")
40
+ end
10
41
  end
11
42
 
12
43
  private
13
44
 
14
- attr_reader :name
45
+ def name
46
+ ::Code::Object::String.new(@name.to_s)
47
+ end
15
48
  end
16
49
  end
17
50
  end
@@ -0,0 +1,33 @@
1
+ class Code
2
+ class Node
3
+ class Negation < Node
4
+ EXCLAMATION_POINT = "!"
5
+ PLUS = "+"
6
+
7
+ def initialize(negation)
8
+ @operator = negation.fetch(:operator)
9
+ @statement = ::Code::Node::Statement.new(negation.fetch(:statement))
10
+ end
11
+
12
+ def evaluate(**args)
13
+ object = @statement.evaluate(**args)
14
+
15
+ if operator == EXCLAMATION_POINT
16
+ if object.truthy?
17
+ ::Code::Object::Boolean.new(false)
18
+ else
19
+ ::Code::Object::Boolean.new(true)
20
+ end
21
+ elsif operator == PLUS
22
+ object
23
+ else
24
+ raise NotImplementedError.new(operator)
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :operator
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,13 @@
1
+ class Code
2
+ class Node
3
+ class NotKeyword < Node
4
+ def initialize(not_keyword)
5
+ @statement = ::Code::Node::Statement.new(not_keyword)
6
+ end
7
+
8
+ def evaluate(**args)
9
+ ::Code::Object::Boolean.new(!@statement.evaluate(**args).truthy?)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -1,10 +1,10 @@
1
1
  class Code
2
2
  class Node
3
- class Nothing
3
+ class Nothing < Node
4
4
  def initialize
5
5
  end
6
6
 
7
- def evaluate(_context)
7
+ def evaluate(**args)
8
8
  ::Code::Object::Nothing.new
9
9
  end
10
10
  end
@@ -1,6 +1,6 @@
1
1
  class Code
2
2
  class Node
3
- class Number
3
+ class Number < Node
4
4
  def initialize(number)
5
5
  if number.key?(:base_2)
6
6
  @number = ::Code::Node::Base2Number.new(number[:base_2])
@@ -15,8 +15,8 @@ class Code
15
15
  end
16
16
  end
17
17
 
18
- def evaluate(context)
19
- @number.evaluate(context)
18
+ def evaluate(**args)
19
+ @number.evaluate(**args)
20
20
  end
21
21
  end
22
22
  end
@@ -0,0 +1,33 @@
1
+ class Code
2
+ class Node
3
+ class Operation < Node
4
+ class Operation
5
+ attr_reader :operator, :statement
6
+
7
+ def initialize(operation)
8
+ @operator = operation.fetch(:operator).to_s
9
+ @statement = ::Code::Node::Statement.new(operation.fetch(:statement))
10
+ end
11
+ end
12
+
13
+ def initialize(operation)
14
+ @first = ::Code::Node::Statement.new(operation.fetch(:first))
15
+ @rest = operation.fetch(:rest)
16
+ @rest.map! do |operation|
17
+ ::Code::Node::Operation::Operation.new(operation)
18
+ end
19
+ end
20
+
21
+ def evaluate(**args)
22
+ object = @first.evaluate(**args)
23
+
24
+ @rest.each do |operation|
25
+ other = operation.statement.evaluate(**args)
26
+ object = simple_call(object, operation.operator, other, **args)
27
+ end
28
+
29
+ object
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,34 @@
1
+ class Code
2
+ class Node
3
+ class OrKeyword < Node
4
+ OR_KEYWORD = "or"
5
+ AND_KEYWORD = "and"
6
+
7
+ def initialize(or_keyword)
8
+ @first = ::Code::Node::Statement.new(or_keyword.fetch(:first))
9
+ @rest = or_keyword.fetch(:rest)
10
+ @rest.map! do |operation|
11
+ ::Code::Node::Operation::Operation.new(operation)
12
+ end
13
+ end
14
+
15
+ def evaluate(**args)
16
+ object = @first.evaluate(**args)
17
+
18
+ @rest.each do |operation|
19
+ if operation.operator == OR_KEYWORD
20
+ return object if object.truthy?
21
+ elsif operation.operator == AND_KEYWORD
22
+ return object unless object.truthy?
23
+ else
24
+ raise NotImplementedError.new(operation.operator.inspect)
25
+ end
26
+
27
+ object = operation.statement.evaluate(**args)
28
+ end
29
+
30
+ object
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,16 @@
1
+ class Code
2
+ class Node
3
+ class Power < Node
4
+ def initialize(power)
5
+ @left = ::Code::Node::Statement.new(power.fetch(:left))
6
+ @right = ::Code::Node::Statement.new(power.fetch(:right))
7
+ end
8
+
9
+ def evaluate(**args)
10
+ right = @right.evaluate(**args)
11
+ left = @left.evaluate(**args)
12
+ simple_call(left, :**, right, **args)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,31 @@
1
+ class Code
2
+ class Node
3
+ class Range < Node
4
+ INCLUSIVE_RANGE = ".."
5
+ EXCLUSIVE_RANGE = "..."
6
+
7
+ def initialize(range)
8
+ @left = ::Code::Node::Statement.new(range.fetch(:left))
9
+ @operator = range.fetch(:operator)
10
+ @right = ::Code::Node::Statement.new(range.fetch(:right))
11
+ end
12
+
13
+ def evaluate(**args)
14
+ left = @left.evaluate(**args)
15
+ right = @right.evaluate(**args)
16
+
17
+ if operator == INCLUSIVE_RANGE
18
+ ::Code::Object::Range.new(left, right, exclude_end: false)
19
+ elsif operator == EXCLUSIVE_RANGE
20
+ ::Code::Object::Range.new(left, right, exclude_end: true)
21
+ else
22
+ raise NotImplementedError.new(operator)
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :operator
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,34 @@
1
+ class Code
2
+ class Node
3
+ class RegularCallArgument < Node
4
+ def initialize(argument)
5
+ @splat = argument.key?(:splat)
6
+ @keyword_splat = argument.key?(:keyword_splat)
7
+ @block = argument.key?(:block)
8
+ @value = ::Code::Node::Code.new(argument.fetch(:value))
9
+ end
10
+
11
+ def evaluate(**args)
12
+ object = @value.evaluate(**args)
13
+
14
+ block? ? simple_call(object, :to_function, **args) : object
15
+ end
16
+
17
+ def block?
18
+ @block
19
+ end
20
+
21
+ def splat?
22
+ @splat
23
+ end
24
+
25
+ def keyword_splat?
26
+ @keyword_splat
27
+ end
28
+
29
+ def name
30
+ nil
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,36 @@
1
+ class Code
2
+ class Node
3
+ class RegularFunctionArgument < Node
4
+ def initialize(argument)
5
+ @block = argument.key?(:block)
6
+ @splat = argument.key?(:splat)
7
+ @keyword_splat = argument.key?(:keyword_splat)
8
+ @name = argument.fetch(:name)
9
+
10
+ if argument.key?(:default)
11
+ @default = ::Code::Node::Code.new(argument.fetch(:default))
12
+ end
13
+ end
14
+
15
+ def evaluate(**args)
16
+ @default ? @default.evaluate(**args) : ::Code::Object::Nothing.new
17
+ end
18
+
19
+ def name
20
+ ::Code::Object::String.new(@name.to_s)
21
+ end
22
+
23
+ def splat?
24
+ @splat
25
+ end
26
+
27
+ def keyword_splat?
28
+ @keyword_splat
29
+ end
30
+
31
+ def block?
32
+ @block
33
+ end
34
+ end
35
+ end
36
+ end