code-ruby 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
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