code-ruby 0.2.4

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 (140) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +9 -0
  3. data/.github/workflows/rspec.yml +14 -0
  4. data/.gitignore +2 -0
  5. data/.prettierrc +3 -0
  6. data/.rspec +1 -0
  7. data/CHANGELOG.md +31 -0
  8. data/Gemfile +3 -0
  9. data/Gemfile.lock +70 -0
  10. data/LICENSE +7 -0
  11. data/README.md +103 -0
  12. data/TODO.md +1 -0
  13. data/bin/template +39 -0
  14. data/code-ruby.gemspec +22 -0
  15. data/docs/euler/1.template +14 -0
  16. data/docs/euler/2.template +16 -0
  17. data/docs/euler/3.template +16 -0
  18. data/docs/euler/4.template +11 -0
  19. data/docs/euler/5.template +14 -0
  20. data/docs/precedence.template +94 -0
  21. data/lib/code/error.rb +15 -0
  22. data/lib/code/node/base_10_decimal.rb +32 -0
  23. data/lib/code/node/base_10_integer.rb +32 -0
  24. data/lib/code/node/base_10_number.rb +19 -0
  25. data/lib/code/node/base_16_number.rb +19 -0
  26. data/lib/code/node/base_2_number.rb +19 -0
  27. data/lib/code/node/base_8_number.rb +19 -0
  28. data/lib/code/node/block.rb +17 -0
  29. data/lib/code/node/boolean.rb +22 -0
  30. data/lib/code/node/call.rb +52 -0
  31. data/lib/code/node/call_argument.rb +37 -0
  32. data/lib/code/node/chained_call.rb +38 -0
  33. data/lib/code/node/code.rb +16 -0
  34. data/lib/code/node/defined.rb +19 -0
  35. data/lib/code/node/dictionnary.rb +22 -0
  36. data/lib/code/node/dictionnary_key_value.rb +23 -0
  37. data/lib/code/node/equal.rb +36 -0
  38. data/lib/code/node/function.rb +17 -0
  39. data/lib/code/node/function_argument.rb +45 -0
  40. data/lib/code/node/group.rb +13 -0
  41. data/lib/code/node/if.rb +55 -0
  42. data/lib/code/node/if_modifier.rb +48 -0
  43. data/lib/code/node/keyword_call_argument.rb +30 -0
  44. data/lib/code/node/keyword_function_argument.rb +33 -0
  45. data/lib/code/node/list.rb +19 -0
  46. data/lib/code/node/name.rb +50 -0
  47. data/lib/code/node/negation.rb +33 -0
  48. data/lib/code/node/not_keyword.rb +13 -0
  49. data/lib/code/node/nothing.rb +12 -0
  50. data/lib/code/node/number.rb +23 -0
  51. data/lib/code/node/operation.rb +33 -0
  52. data/lib/code/node/or_keyword.rb +34 -0
  53. data/lib/code/node/power.rb +16 -0
  54. data/lib/code/node/range.rb +31 -0
  55. data/lib/code/node/regular_call_argument.rb +34 -0
  56. data/lib/code/node/regular_function_argument.rb +36 -0
  57. data/lib/code/node/rescue.rb +16 -0
  58. data/lib/code/node/statement.rb +81 -0
  59. data/lib/code/node/string.rb +17 -0
  60. data/lib/code/node/ternary.rb +26 -0
  61. data/lib/code/node/unary_minus.rb +22 -0
  62. data/lib/code/node/while.rb +42 -0
  63. data/lib/code/node.rb +14 -0
  64. data/lib/code/object/argument.rb +41 -0
  65. data/lib/code/object/boolean.rb +27 -0
  66. data/lib/code/object/decimal.rb +54 -0
  67. data/lib/code/object/dictionnary.rb +55 -0
  68. data/lib/code/object/function.rb +64 -0
  69. data/lib/code/object/integer.rb +116 -0
  70. data/lib/code/object/list.rb +217 -0
  71. data/lib/code/object/nothing.rb +23 -0
  72. data/lib/code/object/number.rb +6 -0
  73. data/lib/code/object/range.rb +158 -0
  74. data/lib/code/object/string.rb +68 -0
  75. data/lib/code/object.rb +130 -0
  76. data/lib/code/parser/addition.rb +29 -0
  77. data/lib/code/parser/and_operator.rb +28 -0
  78. data/lib/code/parser/bitwise_and.rb +28 -0
  79. data/lib/code/parser/bitwise_or.rb +29 -0
  80. data/lib/code/parser/boolean.rb +14 -0
  81. data/lib/code/parser/call.rb +90 -0
  82. data/lib/code/parser/code.rb +19 -0
  83. data/lib/code/parser/defined.rb +20 -0
  84. data/lib/code/parser/dictionnary.rb +41 -0
  85. data/lib/code/parser/equal.rb +42 -0
  86. data/lib/code/parser/equality.rb +36 -0
  87. data/lib/code/parser/function.rb +57 -0
  88. data/lib/code/parser/greater_than.rb +33 -0
  89. data/lib/code/parser/group.rb +17 -0
  90. data/lib/code/parser/if.rb +33 -0
  91. data/lib/code/parser/if_modifier.rb +28 -0
  92. data/lib/code/parser/list.rb +29 -0
  93. data/lib/code/parser/multiplication.rb +30 -0
  94. data/lib/code/parser/name.rb +89 -0
  95. data/lib/code/parser/negation.rb +19 -0
  96. data/lib/code/parser/not_keyword.rb +21 -0
  97. data/lib/code/parser/nothing.rb +17 -0
  98. data/lib/code/parser/number.rb +98 -0
  99. data/lib/code/parser/or_keyword.rb +29 -0
  100. data/lib/code/parser/or_operator.rb +28 -0
  101. data/lib/code/parser/power.rb +25 -0
  102. data/lib/code/parser/range.rb +25 -0
  103. data/lib/code/parser/rescue.rb +23 -0
  104. data/lib/code/parser/shift.rb +31 -0
  105. data/lib/code/parser/statement.rb +8 -0
  106. data/lib/code/parser/string.rb +72 -0
  107. data/lib/code/parser/ternary.rb +25 -0
  108. data/lib/code/parser/unary_minus.rb +13 -0
  109. data/lib/code/parser/while.rb +25 -0
  110. data/lib/code/parser.rb +4 -0
  111. data/lib/code-ruby.rb +11 -0
  112. data/lib/code.rb +29 -0
  113. data/lib/template/node/code_part.rb +13 -0
  114. data/lib/template/node/part.rb +19 -0
  115. data/lib/template/node/template.rb +15 -0
  116. data/lib/template/node/text_part.rb +13 -0
  117. data/lib/template/node.rb +4 -0
  118. data/lib/template/parser/template.rb +30 -0
  119. data/lib/template/parser.rb +4 -0
  120. data/lib/template/version.rb +3 -0
  121. data/lib/template-ruby.rb +11 -0
  122. data/lib/template.rb +34 -0
  123. data/spec/call_spec.rb +22 -0
  124. data/spec/code/error/type_error_spec.rb +65 -0
  125. data/spec/code/parser/boolean_spec.rb +18 -0
  126. data/spec/code/parser/call_spec.rb +66 -0
  127. data/spec/code/parser/dictionnary_spec.rb +46 -0
  128. data/spec/code/parser/function_spec.rb +32 -0
  129. data/spec/code/parser/list_spec.rb +29 -0
  130. data/spec/code/parser/name_spec.rb +15 -0
  131. data/spec/code/parser/nothing_spec.rb +19 -0
  132. data/spec/code/parser/number_spec.rb +117 -0
  133. data/spec/code/parser/string_spec.rb +30 -0
  134. data/spec/code_spec.rb +108 -0
  135. data/spec/function_spec.rb +26 -0
  136. data/spec/spec_helper.rb +3 -0
  137. data/spec/template/parser/template_spec.rb +19 -0
  138. data/spec/template_spec.rb +27 -0
  139. data/template-ruby.gemspec +24 -0
  140. metadata +266 -0
@@ -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
@@ -0,0 +1,16 @@
1
+ class Code
2
+ class Node
3
+ class Rescue < 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
+ @left.evaluate(**args)
11
+ rescue ::Code::Error
12
+ @right.evaluate(**args)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,81 @@
1
+ class Code
2
+ class Node
3
+ class Statement < Node
4
+ attr_reader :statement
5
+
6
+ def initialize(statement)
7
+ if statement.key?(:nothing)
8
+ @statement = ::Code::Node::Nothing.new
9
+ elsif statement.key?(:boolean)
10
+ @statement = ::Code::Node::Boolean.new(statement[:boolean])
11
+ elsif statement.key?(:number)
12
+ @statement = ::Code::Node::Number.new(statement[:number])
13
+ elsif statement.key?(:string)
14
+ @statement = ::Code::Node::String.new(statement[:string])
15
+ elsif statement.key?(:call)
16
+ @statement = ::Code::Node::Call.new(statement[:call])
17
+ elsif statement.key?(:name)
18
+ @statement = ::Code::Node::Name.new(statement[:name])
19
+ elsif statement.key?(:list)
20
+ @statement = ::Code::Node::List.new(statement[:list])
21
+ elsif statement.key?(:dictionnary)
22
+ @statement = ::Code::Node::Dictionnary.new(statement[:dictionnary])
23
+ elsif statement.key?(:negation)
24
+ @statement = ::Code::Node::Negation.new(statement[:negation])
25
+ elsif statement.key?(:power)
26
+ @statement = ::Code::Node::Power.new(statement[:power])
27
+ elsif statement.key?(:unary_minus)
28
+ @statement = ::Code::Node::UnaryMinus.new(statement[:unary_minus])
29
+ elsif statement.key?(:multiplication)
30
+ @statement = ::Code::Node::Operation.new(statement[:multiplication])
31
+ elsif statement.key?(:addition)
32
+ @statement = ::Code::Node::Operation.new(statement[:addition])
33
+ elsif statement.key?(:shift)
34
+ @statement = ::Code::Node::Operation.new(statement[:shift])
35
+ elsif statement.key?(:bitwise_and)
36
+ @statement = ::Code::Node::Operation.new(statement[:bitwise_and])
37
+ elsif statement.key?(:bitwise_or)
38
+ @statement = ::Code::Node::Operation.new(statement[:bitwise_or])
39
+ elsif statement.key?(:greater_than)
40
+ @statement = ::Code::Node::Operation.new(statement[:greater_than])
41
+ elsif statement.key?(:equality)
42
+ @statement = ::Code::Node::Operation.new(statement[:equality])
43
+ elsif statement.key?(:and_operator)
44
+ @statement = ::Code::Node::Operation.new(statement[:and_operator])
45
+ elsif statement.key?(:or_operator)
46
+ @statement = ::Code::Node::Operation.new(statement[:or_operator])
47
+ elsif statement.key?(:range)
48
+ @statement = ::Code::Node::Range.new(statement[:range])
49
+ elsif statement.key?(:ternary)
50
+ @statement = ::Code::Node::Ternary.new(statement[:ternary])
51
+ elsif statement.key?(:rescue)
52
+ @statement = ::Code::Node::Rescue.new(statement[:rescue])
53
+ elsif statement.key?(:equal)
54
+ @statement = ::Code::Node::Equal.new(statement[:equal])
55
+ elsif statement.key?(:defined)
56
+ @statement = ::Code::Node::Defined.new(statement[:defined])
57
+ elsif statement.key?(:not_keyword)
58
+ @statement = ::Code::Node::NotKeyword.new(statement[:not_keyword])
59
+ elsif statement.key?(:or_keyword)
60
+ @statement = ::Code::Node::OrKeyword.new(statement[:or_keyword])
61
+ elsif statement.key?(:if_modifier)
62
+ @statement = ::Code::Node::IfModifier.new(statement[:if_modifier])
63
+ elsif statement.key?(:if)
64
+ @statement = ::Code::Node::If.new(statement[:if])
65
+ elsif statement.key?(:while)
66
+ @statement = ::Code::Node::While.new(statement[:while])
67
+ elsif statement.key?(:group)
68
+ @statement = ::Code::Node::Group.new(statement[:group])
69
+ elsif statement.key?(:function)
70
+ @statement = ::Code::Node::Function.new(statement[:function])
71
+ else
72
+ raise NotImplementedError.new(statement.inspect)
73
+ end
74
+ end
75
+
76
+ def evaluate(**args)
77
+ @statement.evaluate(**args)
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,17 @@
1
+ class Code
2
+ class Node
3
+ class String < Node
4
+ def initialize(string)
5
+ @string = string
6
+ end
7
+
8
+ def evaluate(**args)
9
+ ::Code::Object::String.new(string.to_s)
10
+ end
11
+
12
+ private
13
+
14
+ attr_reader :string
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ class Code
2
+ class Node
3
+ class Ternary < Node
4
+ def initialize(ternary)
5
+ @left = ::Code::Node::Statement.new(ternary.fetch(:left))
6
+ @middle = ::Code::Node::Statement.new(ternary.fetch(:middle))
7
+
8
+ if ternary.key?(:right)
9
+ @right = ::Code::Node::Statement.new(ternary.fetch(:right))
10
+ end
11
+ end
12
+
13
+ def evaluate(**args)
14
+ left = @left.evaluate(**args)
15
+
16
+ if left.truthy?
17
+ @middle.evaluate(**args)
18
+ elsif @right
19
+ @right.evaluate(**args)
20
+ else
21
+ ::Code::Object::Nothing.new
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,22 @@
1
+ class Code
2
+ class Node
3
+ class UnaryMinus < Node
4
+ def initialize(unary_minus)
5
+ @statement = ::Code::Node::Statement.new(unary_minus)
6
+ end
7
+
8
+ def evaluate(**args)
9
+ object = @statement.evaluate(**args)
10
+
11
+ case object
12
+ when ::Code::Object::Integer
13
+ ::Code::Object::Integer.new(-object.raw)
14
+ when ::Code::Object::Decimal
15
+ ::Code::Object::Decimal.new(-object.raw)
16
+ else
17
+ ::Code::Object::Nothing.new
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,42 @@
1
+ class Code
2
+ class Node
3
+ class While < Node
4
+ WHILE_KEYWORD = :while
5
+ UNTIL_KEYWORD = :until
6
+
7
+ def initialize(while_parsed)
8
+ @operator = while_parsed.fetch(:operator)
9
+ @statement = ::Code::Node::Statement.new(while_parsed.fetch(:statement))
10
+ @body = ::Code::Node::Code.new(while_parsed.fetch(:body))
11
+ end
12
+
13
+ def evaluate(**args)
14
+ if operator == WHILE_KEYWORD
15
+ object = ::Code::Object::Nothing.new
16
+
17
+ while @statement.evaluate(**args).truthy?
18
+ object = @body.evaluate(**args)
19
+ end
20
+
21
+ object
22
+ elsif operator == UNTIL_KEYWORD
23
+ object = ::Code::Object::Nothing.new
24
+
25
+ until @statement.evaluate(**args).truthy?
26
+ object = @body.evaluate(**args)
27
+ end
28
+
29
+ object
30
+ else
31
+ raise NotImplementedError.new(operator.inspect)
32
+ end
33
+ end
34
+
35
+ private
36
+
37
+ def operator
38
+ @operator.to_sym
39
+ end
40
+ end
41
+ end
42
+ end
data/lib/code/node.rb ADDED
@@ -0,0 +1,14 @@
1
+ class Code
2
+ class Node
3
+ private
4
+
5
+ def simple_call(object, operator = nil, value = nil, **args)
6
+ object.call(
7
+ operator: operator && ::Code::Object::String.new(operator.to_s),
8
+ arguments: [value && ::Code::Object::Argument.new(value)].compact,
9
+ context: args.fetch(:context),
10
+ io: args.fetch(:io),
11
+ )
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,41 @@
1
+ class Code
2
+ class Object
3
+ class Argument < ::Code::Object
4
+ attr_reader :value, :name, :splat, :keyword_splat, :block
5
+
6
+ def initialize(
7
+ value,
8
+ name: nil,
9
+ splat: false,
10
+ keyword_splat: false,
11
+ block: false
12
+ )
13
+ @value = value
14
+ @name = name
15
+ @splat = !!splat
16
+ @keyword_splat = !!keyword_splat
17
+ @block = !!block
18
+ end
19
+
20
+ def regular?
21
+ !name
22
+ end
23
+
24
+ def keyword?
25
+ !regular?
26
+ end
27
+
28
+ def name_value
29
+ [name, value]
30
+ end
31
+
32
+ def to_s
33
+ "argument"
34
+ end
35
+
36
+ def inspect
37
+ to_s
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,27 @@
1
+ class Code
2
+ class Object
3
+ class Boolean < ::Code::Object
4
+ attr_reader :raw
5
+
6
+ def initialize(raw)
7
+ @raw = raw
8
+ end
9
+
10
+ def truthy?
11
+ raw
12
+ end
13
+
14
+ def succ
15
+ ::Code::Object::Boolean.new(!raw)
16
+ end
17
+
18
+ def to_s
19
+ raw.to_s
20
+ end
21
+
22
+ def inspect
23
+ to_s
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,54 @@
1
+ class Code
2
+ class Object
3
+ class Decimal < ::Code::Object::Number
4
+ attr_reader :raw
5
+
6
+ def initialize(decimal, exponent: nil)
7
+ @raw = BigDecimal(decimal)
8
+
9
+ if exponent
10
+ if exponent.is_a?(::Code::Object::Number)
11
+ @raw = @raw * 10**exponent.raw
12
+ else
13
+ raise ::Code::Error::TypeError.new("exponent is not a number")
14
+ end
15
+ end
16
+ end
17
+
18
+ def call(**args)
19
+ operator = args.fetch(:operator, nil)
20
+ arguments = args.fetch(:arguments, [])
21
+
22
+ if %w[% - + / * **].detect { |o| operator == o }
23
+ number_operation(operator.to_sym, arguments)
24
+ elsif %w[< <= > >=].detect { |o| operator == o }
25
+ comparaison(operator.to_sym, arguments)
26
+ else
27
+ super
28
+ end
29
+ end
30
+
31
+ def to_s
32
+ raw.to_s("F")
33
+ end
34
+
35
+ def inspect
36
+ to_s
37
+ end
38
+
39
+ private
40
+
41
+ def number_operation(operator, arguments)
42
+ sig(arguments, ::Code::Object::Number)
43
+ other = arguments.first.value
44
+ ::Code::Object::Decimal.new(raw.public_send(operator, other.raw))
45
+ end
46
+
47
+ def comparaison(operator, arguments)
48
+ sig(arguments, ::Code::Object::Number)
49
+ other = arguments.first.value
50
+ ::Code::Object::Boolean.new(raw.public_send(operator, other.raw))
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,55 @@
1
+ class Code
2
+ class Object
3
+ class Dictionnary < ::Code::Object
4
+ attr_reader :raw
5
+
6
+ def initialize(raw = {})
7
+ @raw = raw
8
+ end
9
+
10
+ def call(**args)
11
+ operator = args.fetch(:operator, nil)
12
+ arguments = args.fetch(:arguments, [])
13
+
14
+ if operator == "values"
15
+ values(arguments)
16
+ elsif key?(operator)
17
+ fetch(operator)
18
+ else
19
+ super
20
+ end
21
+ end
22
+
23
+ def fetch(key)
24
+ raw.fetch(key)
25
+ end
26
+
27
+ def [](key)
28
+ raw[key]
29
+ end
30
+
31
+ def []=(key, value)
32
+ raw[key] = value
33
+ end
34
+
35
+ def key?(key)
36
+ raw.key?(key)
37
+ end
38
+
39
+ def to_s
40
+ "{#{raw.map { |key, value| "#{key.inspect} => #{value.inspect}" }.join(", ")}}"
41
+ end
42
+
43
+ def inspect
44
+ to_s
45
+ end
46
+
47
+ private
48
+
49
+ def values(arguments)
50
+ sig(arguments)
51
+ ::Code::Object::List.new(raw.values)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,64 @@
1
+ class Code
2
+ class Object
3
+ class Function < ::Code::Object
4
+ def initialize(arguments:, body:)
5
+ @arguments = arguments
6
+ @body = body
7
+ end
8
+
9
+ def call(**args)
10
+ operator = args.fetch(:operator, nil)
11
+ arguments = args.fetch(:arguments, [])
12
+ context = args.fetch(:context)
13
+ io = args.fetch(:io)
14
+
15
+ if operator.nil?
16
+ call_function(args: arguments, context: context, io: io)
17
+ else
18
+ super
19
+ end
20
+ end
21
+
22
+ def to_s
23
+ ""
24
+ end
25
+
26
+ def inspect
27
+ "function"
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :arguments, :body
33
+
34
+ def call_function(args:, context:, io:)
35
+ new_context = context.dup
36
+ arguments.each.with_index do |argument, index|
37
+ if argument.regular?
38
+ if argument.splat?
39
+ new_context[argument.name] = ::Code::Object::List.new(
40
+ args.select(&:regular?).map(&:value),
41
+ )
42
+ elsif argument.keyword_splat?
43
+ new_context[argument.name] = ::Code::Object::Dictionnary.new(
44
+ args.select(&:keyword?).map(&:name_value).to_h,
45
+ )
46
+ else
47
+ arg = args[index]&.value
48
+ arg = argument.evaluate(context: new_context, io: io) if arg.nil?
49
+ new_context[argument.name] = arg
50
+ end
51
+ elsif argument.keyword?
52
+ arg = args.detect { |arg| arg.name == argument.name }&.value
53
+ arg = argument.evaluate(context: new_context, io: io) if arg.nil?
54
+ new_context[argument.name] = arg
55
+ else
56
+ raise NotImplementedError
57
+ end
58
+ end
59
+
60
+ body.evaluate(context: new_context, io: io)
61
+ end
62
+ end
63
+ end
64
+ end