code-ruby 0.3.1 → 0.5.0

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