code-ruby 0.3.1 → 0.5.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 (206) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/CHANGELOG.md +5 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +28 -55
  6. data/TODO +17 -0
  7. data/bin/code +56 -31
  8. data/bin/format +3 -0
  9. data/bin/template +62 -20
  10. data/bin/test +17 -0
  11. data/code-ruby.gemspec +1 -6
  12. data/docs/class.code +9 -0
  13. data/docs/euler/1.template +1 -5
  14. data/docs/euler/5.template +0 -1
  15. data/docs/meetup.code +12 -0
  16. data/docs/precedence.template +6 -39
  17. data/docs/rain.code +22 -0
  18. data/docs/slack.code +17 -0
  19. data/docs/stripe.code +7 -0
  20. data/docs/twitter.code +9 -0
  21. data/language-ruby.gemspec +18 -0
  22. data/lib/code/error.rb +3 -0
  23. data/lib/code/node/base_10.rb +29 -0
  24. data/lib/code/node/base_16.rb +13 -0
  25. data/lib/code/node/base_2.rb +13 -0
  26. data/lib/code/node/base_8.rb +13 -0
  27. data/lib/code/node/boolean.rb +7 -7
  28. data/lib/code/node/call.rb +32 -37
  29. data/lib/code/node/call_argument.rb +11 -27
  30. data/lib/code/node/chained_call.rb +10 -25
  31. data/lib/code/node/code.rb +4 -6
  32. data/lib/code/node/decimal.rb +26 -0
  33. data/lib/code/node/dictionnary.rb +20 -9
  34. data/lib/code/node/equal.rb +18 -20
  35. data/lib/code/node/function.rb +10 -7
  36. data/lib/code/node/function_parameter.rb +31 -0
  37. data/lib/code/node/if.rb +36 -32
  38. data/lib/code/node/if_modifier.rb +35 -36
  39. data/lib/code/node/list.rb +6 -9
  40. data/lib/code/node/negation.rb +5 -23
  41. data/lib/code/node/not.rb +15 -0
  42. data/lib/code/node/nothing.rb +1 -1
  43. data/lib/code/node/number.rb +14 -12
  44. data/lib/code/node/operation.rb +21 -16
  45. data/lib/code/node/power.rb +10 -6
  46. data/lib/code/node/rescue.rb +4 -3
  47. data/lib/code/node/splat.rb +15 -0
  48. data/lib/code/node/statement.rb +47 -69
  49. data/lib/code/node/string.rb +41 -10
  50. data/lib/code/node/ternary.rb +7 -9
  51. data/lib/code/node/unary_minus.rb +5 -12
  52. data/lib/code/node/while.rb +17 -24
  53. data/lib/code/node.rb +7 -8
  54. data/lib/code/object/argument.rb +3 -12
  55. data/lib/code/object/decimal.rb +114 -27
  56. data/lib/code/object/dictionnary.rb +29 -12
  57. data/lib/code/object/function.rb +23 -24
  58. data/lib/code/object/global.rb +42 -0
  59. data/lib/code/object/integer.rb +142 -35
  60. data/lib/code/object/list.rb +74 -95
  61. data/lib/code/object/range.rb +38 -50
  62. data/lib/code/object/ruby_function.rb +31 -0
  63. data/lib/code/object/string.rb +36 -16
  64. data/lib/code/object.rb +114 -54
  65. data/lib/code/parser/addition.rb +12 -20
  66. data/lib/code/parser/and_operator.rb +9 -20
  67. data/lib/code/parser/bitwise_and.rb +9 -20
  68. data/lib/code/parser/bitwise_or.rb +12 -20
  69. data/lib/code/parser/boolean.rb +10 -7
  70. data/lib/code/parser/call.rb +92 -60
  71. data/lib/code/parser/chained_call.rb +47 -0
  72. data/lib/code/parser/class.rb +45 -0
  73. data/lib/code/parser/code.rb +17 -10
  74. data/lib/code/parser/dictionnary.rb +56 -30
  75. data/lib/code/parser/equal.rb +87 -35
  76. data/lib/code/parser/equality.rb +23 -24
  77. data/lib/code/parser/equality_lower.rb +9 -0
  78. data/lib/code/parser/function.rb +67 -40
  79. data/lib/code/parser/greater.rb +25 -0
  80. data/lib/code/parser/group.rb +13 -8
  81. data/lib/code/parser/if.rb +51 -21
  82. data/lib/code/parser/if_modifier.rb +43 -16
  83. data/lib/code/parser/list.rb +32 -19
  84. data/lib/code/parser/multiplication.rb +15 -20
  85. data/lib/code/parser/name.rb +96 -84
  86. data/lib/code/parser/negation.rb +20 -9
  87. data/lib/code/parser/not_keyword.rb +14 -12
  88. data/lib/code/parser/nothing.rb +13 -8
  89. data/lib/code/parser/number.rb +124 -68
  90. data/lib/code/parser/operation.rb +35 -0
  91. data/lib/code/parser/or_keyword.rb +12 -20
  92. data/lib/code/parser/or_operator.rb +9 -20
  93. data/lib/code/parser/power.rb +32 -14
  94. data/lib/code/parser/range.rb +9 -17
  95. data/lib/code/parser/rescue.rb +29 -13
  96. data/lib/code/parser/shift.rb +11 -21
  97. data/lib/code/parser/splat.rb +31 -0
  98. data/lib/code/parser/statement.rb +4 -3
  99. data/lib/code/parser/string.rb +53 -62
  100. data/lib/code/parser/ternary.rb +36 -15
  101. data/lib/code/parser/unary_minus.rb +23 -5
  102. data/lib/code/parser/while.rb +26 -15
  103. data/lib/code/parser/whitespace.rb +49 -0
  104. data/lib/code/parser.rb +15 -0
  105. data/lib/code/ruby.rb +162 -0
  106. data/lib/code-ruby.rb +2 -5
  107. data/lib/code.rb +24 -7
  108. data/lib/language/atom.rb +343 -0
  109. data/lib/language/output.rb +130 -0
  110. data/lib/language/parser/absent/present.rb +8 -0
  111. data/lib/language/parser/absent.rb +6 -0
  112. data/lib/language/parser/end_of_input.rb +6 -0
  113. data/lib/language/parser/interuption.rb +38 -0
  114. data/lib/language/parser/not_end_of_input.rb +6 -0
  115. data/lib/language/parser/str/not_found.rb +16 -0
  116. data/lib/language/parser/str.rb +6 -0
  117. data/lib/language/parser.rb +53 -0
  118. data/lib/language-ruby.rb +10 -0
  119. data/lib/language.rb +80 -0
  120. data/lib/template/node/code_part.rb +1 -1
  121. data/lib/template/node/part.rb +1 -1
  122. data/lib/template/node/template.rb +1 -1
  123. data/lib/template/node/text_part.rb +1 -1
  124. data/lib/template/node.rb +1 -1
  125. data/lib/template/parser/template.rb +26 -17
  126. data/lib/template/parser.rb +15 -0
  127. data/lib/template/version.rb +1 -1
  128. data/lib/template-ruby.rb +2 -5
  129. data/lib/template.rb +23 -13
  130. data/spec/code/addition_spec.rb +13 -0
  131. data/spec/code/and_operator_spec.rb +13 -0
  132. data/spec/code/bitwise_and_spec.rb +13 -0
  133. data/spec/code/bitwise_or_spec.rb +13 -0
  134. data/spec/code/boolean_spec.rb +13 -0
  135. data/spec/code/call_spec.rb +21 -0
  136. data/spec/code/chained_call_spec.rb +16 -0
  137. data/spec/code/dictionnary_spec.rb +17 -0
  138. data/spec/code/equal_spec.rb +26 -0
  139. data/spec/code/equality_spec.rb +13 -0
  140. data/spec/code/function_spec.rb +18 -0
  141. data/spec/code/greater_spec.rb +18 -0
  142. data/spec/code/group_spec.rb +12 -0
  143. data/spec/code/if_modifier_spec.rb +20 -0
  144. data/spec/code/if_spec.rb +25 -0
  145. data/spec/code/list_spec.rb +17 -0
  146. data/spec/code/multiplication_spec.rb +18 -0
  147. data/spec/code/negation_spec.rb +20 -0
  148. data/spec/code/not_keyword_spec.rb +13 -0
  149. data/spec/code/nothing_spec.rb +17 -0
  150. data/spec/code/number_spec.rb +22 -0
  151. data/spec/code/or_keyword_spec.rb +17 -0
  152. data/spec/code/or_operator_spec.rb +16 -0
  153. data/spec/code/parser/boolean_spec.rb +5 -7
  154. data/spec/code/parser/call_spec.rb +16 -56
  155. data/spec/code/parser/chained_call.rb +17 -0
  156. data/spec/code/parser/dictionnary_spec.rb +8 -9
  157. data/spec/code/parser/function_spec.rb +5 -21
  158. data/spec/code/parser/group_spec.rb +18 -0
  159. data/spec/code/parser/list_spec.rb +9 -20
  160. data/spec/code/parser/number_spec.rb +4 -109
  161. data/spec/code/parser/string_spec.rb +9 -17
  162. data/spec/code/parser_spec.rb +23 -0
  163. data/spec/code/power_spec.rb +13 -0
  164. data/spec/code/range_spec.rb +16 -0
  165. data/spec/code/rescue_spec.rb +13 -0
  166. data/spec/code/shift_spec.rb +13 -0
  167. data/spec/code/splat_spec.rb +13 -0
  168. data/spec/code/string_spec.rb +25 -0
  169. data/spec/code/ternary_spec.rb +18 -0
  170. data/spec/code/unary_minus_spec.rb +13 -0
  171. data/spec/code/while_spec.rb +18 -0
  172. data/spec/spec_helper.rb +4 -1
  173. data/template-ruby.gemspec +2 -7
  174. metadata +113 -99
  175. data/lib/code/node/base_10_decimal.rb +0 -32
  176. data/lib/code/node/base_10_integer.rb +0 -32
  177. data/lib/code/node/base_10_number.rb +0 -19
  178. data/lib/code/node/base_16_number.rb +0 -19
  179. data/lib/code/node/base_2_number.rb +0 -19
  180. data/lib/code/node/base_8_number.rb +0 -19
  181. data/lib/code/node/block.rb +0 -17
  182. data/lib/code/node/defined.rb +0 -19
  183. data/lib/code/node/dictionnary_key_value.rb +0 -23
  184. data/lib/code/node/function_argument.rb +0 -45
  185. data/lib/code/node/group.rb +0 -13
  186. data/lib/code/node/keyword_call_argument.rb +0 -30
  187. data/lib/code/node/keyword_function_argument.rb +0 -33
  188. data/lib/code/node/name.rb +0 -55
  189. data/lib/code/node/not_keyword.rb +0 -13
  190. data/lib/code/node/or_keyword.rb +0 -34
  191. data/lib/code/node/range.rb +0 -31
  192. data/lib/code/node/regular_call_argument.rb +0 -34
  193. data/lib/code/node/regular_function_argument.rb +0 -36
  194. data/lib/code/node/string_characters.rb +0 -13
  195. data/lib/code/node/string_component.rb +0 -23
  196. data/lib/code/node/string_interpolation.rb +0 -13
  197. data/lib/code/parser/defined.rb +0 -20
  198. data/lib/code/parser/greater_than.rb +0 -33
  199. data/spec/call_spec.rb +0 -22
  200. data/spec/code/error/type_error_spec.rb +0 -63
  201. data/spec/code/parser/name_spec.rb +0 -15
  202. data/spec/code/parser/nothing_spec.rb +0 -19
  203. data/spec/code_spec.rb +0 -120
  204. data/spec/function_spec.rb +0 -26
  205. data/spec/template/parser/template_spec.rb +0 -19
  206. data/spec/template_spec.rb +0 -33
@@ -18,15 +18,63 @@ class Code
18
18
  def call(**args)
19
19
  operator = args.fetch(:operator, nil)
20
20
  arguments = args.fetch(:arguments, [])
21
+ value = arguments.first&.value
21
22
 
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
- elsif %w[<< >> & | ^].detect { |o| operator == o }
27
- integer_operation(operator.to_sym, arguments)
23
+ if operator == "%"
24
+ sig(arguments) { ::Code::Object::Number }
25
+ modulo(value)
28
26
  elsif operator == "+"
29
- plus(arguments)
27
+ if value
28
+ sig(arguments) { ::Code::Object }
29
+ plus(value)
30
+ else
31
+ sig(arguments)
32
+ self
33
+ end
34
+ elsif operator == "-"
35
+ if value
36
+ sig(arguments) { ::Code::Object::Number }
37
+ minus(value)
38
+ else
39
+ sig(arguments)
40
+ unary_minus
41
+ end
42
+ elsif operator == "/"
43
+ sig(arguments) { ::Code::Object::Number }
44
+ division(value)
45
+ elsif operator == "*"
46
+ sig(arguments) { ::Code::Object::Number }
47
+ multiplication(value)
48
+ elsif operator == "**"
49
+ sig(arguments) { ::Code::Object::Number }
50
+ power(value)
51
+ elsif operator == "<"
52
+ sig(arguments) { ::Code::Object::Number }
53
+ inferior(value)
54
+ elsif operator == "<="
55
+ sig(arguments) { ::Code::Object::Number }
56
+ inferior_or_equal(value)
57
+ elsif operator == ">"
58
+ sig(arguments) { ::Code::Object::Number }
59
+ superior(value)
60
+ elsif operator == ">="
61
+ sig(arguments) { ::Code::Object::Number }
62
+ superior_or_equal(value)
63
+ elsif operator == "<<"
64
+ sig(arguments) { ::Code::Object::Number }
65
+ left_shift(value)
66
+ elsif operator == ">>"
67
+ sig(arguments) { ::Code::Object::Number }
68
+ right_shift(value)
69
+ elsif operator == "&"
70
+ sig(arguments) { ::Code::Object::Number }
71
+ bitwise_and(value)
72
+ elsif operator == "|"
73
+ sig(arguments) { ::Code::Object::Number }
74
+ bitwise_or(value)
75
+ elsif operator == "^"
76
+ sig(arguments) { ::Code::Object::Number }
77
+ bitwise_xor(value)
30
78
  else
31
79
  super
32
80
  end
@@ -42,34 +90,73 @@ class Code
42
90
 
43
91
  private
44
92
 
45
- def number_operation(operator, arguments)
46
- sig(arguments, ::Code::Object::Number)
47
- other = arguments.first.value
48
- ::Code::Object::Decimal.new(raw.public_send(operator, other.raw))
49
- end
50
-
51
- def integer_operation(operator, arguments)
52
- sig(arguments, ::Code::Object::Number)
53
- other = arguments.first.value
54
- ::Code::Object::Integer.new(raw.to_i.public_send(operator, other.raw.to_i))
55
- end
56
-
57
- def comparaison(operator, arguments)
58
- sig(arguments, ::Code::Object::Number)
59
- other = arguments.first.value
60
- ::Code::Object::Boolean.new(raw.public_send(operator, other.raw))
93
+ def modulo(other)
94
+ ::Code::Object::Decimal.new(raw % other.raw)
61
95
  end
62
96
 
63
- def plus(arguments)
64
- sig(arguments, ::Code::Object)
65
- other = arguments.first.value
66
-
97
+ def plus(other)
67
98
  if other.is_a?(::Code::Object::Number)
68
99
  ::Code::Object::Decimal.new(raw + other.raw)
69
100
  else
70
101
  ::Code::Object::String.new(to_s + other.to_s)
71
102
  end
72
103
  end
104
+
105
+ def minus(other)
106
+ ::Code::Object::Decimal.new(raw - other.raw)
107
+ end
108
+
109
+ def division(other)
110
+ ::Code::Object::Decimal.new(raw / other.raw)
111
+ end
112
+
113
+ def multiplication(other)
114
+ ::Code::Object::Decimal.new(raw * other.raw)
115
+ end
116
+
117
+ def power(other)
118
+ ::Code::Object::Decimal.new(raw**other.raw)
119
+ end
120
+
121
+ def inferior(other)
122
+ ::Code::Object::Boolean.new(raw < other.raw)
123
+ end
124
+
125
+ def inferior_or_equal(other)
126
+ ::Code::Object::Boolean.new(raw <= other.raw)
127
+ end
128
+
129
+ def superior(other)
130
+ ::Code::Object::Boolean.new(raw > other.raw)
131
+ end
132
+
133
+ def superior_or_equal(other)
134
+ ::Code::Object::Boolean.new(raw >= other.raw)
135
+ end
136
+
137
+ def left_shift(other)
138
+ ::Code::Object::Integer.new(raw.to_i << other.raw.to_i)
139
+ end
140
+
141
+ def right_shift(other)
142
+ ::Code::Object::Integer.new(raw.to_i >> other.raw.to_i)
143
+ end
144
+
145
+ def bitwise_and(other)
146
+ ::Code::Object::Integer.new(raw.to_i & other.raw.to_i)
147
+ end
148
+
149
+ def bitwise_or(other)
150
+ ::Code::Object::Integer.new(raw.to_i | other.raw.to_i)
151
+ end
152
+
153
+ def bitwise_xor(other)
154
+ ::Code::Object::Integer.new(raw.to_i ^ other.raw.to_i)
155
+ end
156
+
157
+ def unary_minus
158
+ ::Code::Object::Decimal.new(-raw)
159
+ end
73
160
  end
74
161
  end
75
162
  end
@@ -10,20 +10,36 @@ class Code
10
10
  def call(**args)
11
11
  operator = args.fetch(:operator, nil)
12
12
  arguments = args.fetch(:arguments, [])
13
- context = args.fetch(:context)
14
- io = args.fetch(:io)
13
+ globals = multi_fetch(args, *::Code::GLOBALS)
14
+ value = arguments.first&.value
15
15
 
16
16
  if operator == "values"
17
- values(arguments)
17
+ sig(arguments)
18
+ values
19
+ elsif operator == "keys"
20
+ sig(arguments)
21
+ keys
18
22
  elsif operator == "each"
19
- each(arguments, context: context, io: io)
23
+ sig(arguments) { ::Code::Object::Function }
24
+ each(value, **globals)
20
25
  elsif key?(operator)
21
- fetch(operator)
26
+ result = fetch(operator)
27
+
28
+ if result.is_a?(::Code::Object::Function)
29
+ result.call(**args.merge(operator: nil))
30
+ else
31
+ sig(arguments)
32
+ result
33
+ end
22
34
  else
23
35
  super
24
36
  end
25
37
  end
26
38
 
39
+ def merge(other)
40
+ ::Code::Object::Dictionnary.new(raw.merge(other.raw))
41
+ end
42
+
27
43
  def fetch(key)
28
44
  raw.fetch(key)
29
45
  end
@@ -54,24 +70,25 @@ class Code
54
70
 
55
71
  private
56
72
 
57
- def values(arguments)
58
- sig(arguments)
73
+ def keys
74
+ ::Code::Object::List.new(raw.keys)
75
+ end
76
+
77
+ def values
59
78
  ::Code::Object::List.new(raw.values)
60
79
  end
61
80
 
62
- def each(arguments, context:, io:)
63
- sig(arguments, ::Code::Object::Function)
64
- argument = arguments.first.value
81
+ def each(argument, **globals)
65
82
  raw.each do |key, value|
66
83
  argument.call(
67
84
  arguments: [
68
85
  ::Code::Object::Argument.new(key),
69
86
  ::Code::Object::Argument.new(value)
70
87
  ],
71
- context: context,
72
- io: io,
88
+ **globals
73
89
  )
74
90
  end
91
+
75
92
  self
76
93
  end
77
94
  end
@@ -1,19 +1,18 @@
1
1
  class Code
2
2
  class Object
3
3
  class Function < ::Code::Object
4
- def initialize(arguments:, body:)
5
- @arguments = arguments
4
+ def initialize(parameters:, body:)
5
+ @parameters = parameters
6
6
  @body = body
7
7
  end
8
8
 
9
9
  def call(**args)
10
10
  operator = args.fetch(:operator, nil)
11
11
  arguments = args.fetch(:arguments, [])
12
- context = args.fetch(:context)
13
- io = args.fetch(:io)
12
+ globals = multi_fetch(args, *::Code::GLOBALS)
14
13
 
15
- if operator.nil?
16
- call_function(args: arguments, context: context, io: io)
14
+ if operator.nil? || operator == "call"
15
+ call_function(args: arguments, globals: globals)
17
16
  else
18
17
  super
19
18
  end
@@ -29,36 +28,36 @@ class Code
29
28
 
30
29
  private
31
30
 
32
- attr_reader :arguments, :body
31
+ attr_reader :parameters, :body
33
32
 
34
- def call_function(args:, context:, io:)
35
- new_context = context.deep_dup
33
+ def call_function(args:, globals:)
34
+ new_context = deep_dup(globals[:context])
36
35
 
37
- arguments.each.with_index do |argument, index|
38
- if argument.regular?
39
- if argument.splat?
40
- new_context[argument.name] = ::Code::Object::List.new(
41
- args.select(&:regular?).map(&:value),
36
+ parameters.each.with_index do |parameter, index|
37
+ if parameter.regular?
38
+ if parameter.regular_splat?
39
+ new_context[parameter.name] = ::Code::Object::List.new(
40
+ args.select(&:regular?).map(&:value)
42
41
  )
43
- elsif argument.keyword_splat?
44
- new_context[argument.name] = ::Code::Object::Dictionnary.new(
45
- args.select(&:keyword?).map(&:name_value).to_h,
42
+ elsif parameter.keyword_splat?
43
+ new_context[parameter.name] = ::Code::Object::Dictionnary.new(
44
+ args.select(&:keyword?).map(&:name_value).to_h
46
45
  )
47
46
  else
48
47
  arg = args[index]&.value
49
- arg = argument.evaluate(context: new_context, io: io) if arg.nil?
50
- new_context[argument.name] = arg
48
+ arg = parameter.evaluate(**globals) if arg.nil?
49
+ new_context[parameter.name] = arg
51
50
  end
52
- elsif argument.keyword?
53
- arg = args.detect { |arg| arg.name == argument.name }&.value
54
- arg = argument.evaluate(context: new_context, io: io) if arg.nil?
55
- new_context[argument.name] = arg
51
+ elsif parameter.keyword?
52
+ arg = args.detect { |arg| arg.name == parameter.name }&.value
53
+ arg = parameter.evaluate(**globals) if arg.nil?
54
+ new_context[parameter.name] = arg
56
55
  else
57
56
  raise NotImplementedError
58
57
  end
59
58
  end
60
59
 
61
- body.evaluate(context: new_context, io: io)
60
+ body.evaluate(**globals, context: new_context)
62
61
  end
63
62
  end
64
63
  end
@@ -0,0 +1,42 @@
1
+ class Code
2
+ class Object
3
+ class Global < ::Code::Object
4
+ def call(**args)
5
+ operator = args.fetch(:operator, nil)
6
+ arguments = args.fetch(:arguments, [])
7
+ context = args.fetch(:context)
8
+ io = args.fetch(:io)
9
+ globals = multi_fetch(args, *::Code::GLOBALS)
10
+ value = arguments.first&.value
11
+
12
+ if operator == "print"
13
+ io.print(*arguments.map(&:value))
14
+ ::Code::Object::Nothing.new
15
+ elsif operator == "puts"
16
+ io.puts(*arguments.map(&:value))
17
+ ::Code::Object::Nothing.new
18
+ elsif operator == "context"
19
+ sig(arguments) { ::Code::Object::String }
20
+ context[value] || ::Code::Object::Nothing.new
21
+ elsif operator == "evaluate"
22
+ sig(arguments) { ::Code::Object::String }
23
+ Code.evaluate(value.raw)
24
+ else
25
+ result = context[operator]
26
+
27
+ if result && result.is_a?(::Code::Object::Function)
28
+ result.call(**args.merge(operator: nil))
29
+ elsif result
30
+ result
31
+ else
32
+ raise ::Code::Error::Undefined.new("#{operator} is not defined")
33
+ end
34
+ end
35
+ end
36
+
37
+ def to_s
38
+ "global"
39
+ end
40
+ end
41
+ end
42
+ end
@@ -18,21 +18,73 @@ class Code
18
18
  def call(**args)
19
19
  operator = args.fetch(:operator, nil)
20
20
  arguments = args.fetch(:arguments, [])
21
+ globals = multi_fetch(args, *::Code::GLOBALS)
22
+ value = arguments.first&.value
21
23
 
22
24
  if operator == "even?"
23
- even?(arguments)
25
+ sig(arguments)
26
+ even?
27
+ elsif operator == "odd?"
28
+ sig(arguments)
29
+ odd?
30
+ elsif operator == "times"
31
+ sig(arguments) { ::Code::Object::Function }
32
+ times(value, **globals)
24
33
  elsif operator == "*"
25
- multiplication(arguments)
34
+ sig(arguments) { [[::Code::Object::Number, ::Code::Object::String]] }
35
+ multiplication(value)
26
36
  elsif operator == "/"
27
- division(arguments)
37
+ sig(arguments) { ::Code::Object::Number }
38
+ division(value)
28
39
  elsif operator == "+"
29
- plus(arguments)
30
- elsif %w[% - **].detect { |o| operator == o }
31
- integer_or_decimal_operation(operator.to_sym, arguments)
32
- elsif %w[> >= < <=].detect { |o| operator == o }
33
- comparaison(operator.to_sym, arguments)
34
- elsif %w[<< >> & | ^].detect { |o| operator == o }
35
- integer_operation(operator.to_sym, arguments)
40
+ if value
41
+ sig(arguments) { ::Code::Object }
42
+ plus(value)
43
+ else
44
+ sig(arguments)
45
+ self
46
+ end
47
+ elsif operator == "%"
48
+ sig(arguments) { ::Code::Object::Number }
49
+ modulo(value)
50
+ elsif operator == "-"
51
+ if value
52
+ sig(arguments) { ::Code::Object::Number }
53
+ minus(value)
54
+ else
55
+ sig(arguments)
56
+ unary_minus
57
+ end
58
+ elsif operator == "**"
59
+ sig(arguments) { ::Code::Object::Number }
60
+ power(value)
61
+ elsif operator == "<"
62
+ sig(arguments) { ::Code::Object::Number }
63
+ inferior(value)
64
+ elsif operator == "<="
65
+ sig(arguments) { ::Code::Object::Number }
66
+ inferior_or_equal(value)
67
+ elsif operator == ">"
68
+ sig(arguments) { ::Code::Object::Number }
69
+ superior(value)
70
+ elsif operator == ">="
71
+ sig(arguments) { ::Code::Object::Number }
72
+ superior_or_equal(value)
73
+ elsif operator == "<<"
74
+ sig(arguments) { ::Code::Object::Number }
75
+ left_shift(value)
76
+ elsif operator == ">>"
77
+ sig(arguments) { ::Code::Object::Number }
78
+ right_shift(value)
79
+ elsif operator == "&"
80
+ sig(arguments) { ::Code::Object::Number }
81
+ bitwise_and(value)
82
+ elsif operator == "|"
83
+ sig(arguments) { ::Code::Object::Number }
84
+ bitwise_or(value)
85
+ elsif operator == "^"
86
+ sig(arguments) { ::Code::Object::Number }
87
+ bitwise_xor(value)
36
88
  else
37
89
  super
38
90
  end
@@ -42,6 +94,10 @@ class Code
42
94
  ::Code::Object::Integer.new(raw + 1)
43
95
  end
44
96
 
97
+ def +(other)
98
+ ::Code::Object::Integer.new(raw + other.raw)
99
+ end
100
+
45
101
  def to_s
46
102
  raw.to_s
47
103
  end
@@ -52,14 +108,15 @@ class Code
52
108
 
53
109
  private
54
110
 
55
- def even?(arguments)
56
- sig(arguments)
111
+ def even?
57
112
  ::Code::Object::Boolean.new(raw.even?)
58
113
  end
59
114
 
60
- def multiplication(arguments)
61
- sig(arguments, [::Code::Object::Number, ::Code::Object::String])
62
- other = arguments.first.value
115
+ def odd?
116
+ ::Code::Object::Boolean.new(raw.odd?)
117
+ end
118
+
119
+ def multiplication(other)
63
120
  if other.is_a?(::Code::Object::Integer)
64
121
  ::Code::Object::Integer.new(raw * other.raw)
65
122
  elsif other.is_a?(::Code::Object::Decimal)
@@ -69,10 +126,7 @@ class Code
69
126
  end
70
127
  end
71
128
 
72
- def plus(arguments)
73
- sig(arguments, ::Code::Object)
74
- other = arguments.first.value
75
-
129
+ def plus(other)
76
130
  if other.is_a?(::Code::Object::Integer)
77
131
  ::Code::Object::Integer.new(raw + other.raw)
78
132
  elsif other.is_a?(::Code::Object::Decimal)
@@ -82,32 +136,85 @@ class Code
82
136
  end
83
137
  end
84
138
 
85
- def division(arguments)
86
- sig(arguments, ::Code::Object::Number)
87
- other = arguments.first.value
139
+ def division(other)
88
140
  ::Code::Object::Decimal.new(BigDecimal(raw) / other.raw)
89
141
  end
90
142
 
91
- def integer_or_decimal_operation(operator, arguments)
92
- sig(arguments, ::Code::Object::Number)
93
- other = arguments.first.value
143
+ def modulo(other)
144
+ if other.is_a?(::Code::Object::Integer)
145
+ ::Code::Object::Integer.new(raw % other.raw)
146
+ else
147
+ ::Code::Object::Decimal.new(raw % other.raw)
148
+ end
149
+ end
150
+
151
+ def minus(other)
94
152
  if other.is_a?(::Code::Object::Integer)
95
- ::Code::Object::Integer.new(raw.public_send(operator, other.raw))
153
+ ::Code::Object::Integer.new(raw - other.raw)
96
154
  else
97
- ::Code::Object::Decimal.new(raw.public_send(operator, other.raw))
155
+ ::Code::Object::Decimal.new(raw - other.raw)
98
156
  end
99
157
  end
100
158
 
101
- def integer_operation(operator, arguments)
102
- sig(arguments, ::Code::Object::Number)
103
- other = arguments.first.value
104
- ::Code::Object::Integer.new(raw.to_i.public_send(operator, other.raw.to_i))
159
+ def unary_minus
160
+ ::Code::Object::Integer.new(-raw)
161
+ end
162
+
163
+ def power(other)
164
+ if other.is_a?(::Code::Object::Integer)
165
+ ::Code::Object::Integer.new(raw**other.raw)
166
+ else
167
+ ::Code::Object::Decimal.new(raw**other.raw)
168
+ end
105
169
  end
106
170
 
107
- def comparaison(operator, arguments)
108
- sig(arguments, ::Code::Object::Number)
109
- other = arguments.first.value
110
- ::Code::Object::Boolean.new(raw.public_send(operator, other.raw))
171
+ def inferior(other)
172
+ ::Code::Object::Boolean.new(raw < other.raw)
173
+ end
174
+
175
+ def inferior_or_equal(other)
176
+ ::Code::Object::Boolean.new(raw <= other.raw)
177
+ end
178
+
179
+ def superior(other)
180
+ ::Code::Object::Boolean.new(raw > other.raw)
181
+ end
182
+
183
+ def superior_or_equal(other)
184
+ ::Code::Object::Boolean.new(raw >= other.raw)
185
+ end
186
+
187
+ def left_shift(other)
188
+ ::Code::Object::Integer.new(raw << other.raw.to_i)
189
+ end
190
+
191
+ def right_shift(other)
192
+ ::Code::Object::Integer.new(raw >> other.raw.to_i)
193
+ end
194
+
195
+ def bitwise_and(other)
196
+ ::Code::Object::Integer.new(raw & other.raw.to_i)
197
+ end
198
+
199
+ def bitwise_or(other)
200
+ ::Code::Object::Integer.new(raw | other.raw.to_i)
201
+ end
202
+
203
+ def bitwise_xor(other)
204
+ ::Code::Object::Integer.new(raw ^ other.raw.to_i)
205
+ end
206
+
207
+ def times(argument, **globals)
208
+ raw.times do |element|
209
+ argument.call(
210
+ arguments: [
211
+ ::Code::Object::Argument.new(::Code::Object::Integer.new(element))
212
+ ],
213
+ **globals
214
+ )
215
+ end
216
+
217
+ self
111
218
  end
112
219
  end
113
220
  end