language-ruby 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (187) 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 +55 -0
  8. data/Gemfile +8 -0
  9. data/Gemfile.lock +48 -0
  10. data/LICENSE +7 -0
  11. data/README.md +103 -0
  12. data/TODO +17 -0
  13. data/bin/code +76 -0
  14. data/bin/format +3 -0
  15. data/bin/template +85 -0
  16. data/bin/test +17 -0
  17. data/code-ruby.gemspec +17 -0
  18. data/docs/class.code +9 -0
  19. data/docs/euler/1.template +10 -0
  20. data/docs/euler/2.template +16 -0
  21. data/docs/euler/3.template +16 -0
  22. data/docs/euler/4.template +10 -0
  23. data/docs/euler/5.template +13 -0
  24. data/docs/fibonnaci.template +14 -0
  25. data/docs/meetup.code +12 -0
  26. data/docs/precedence.template +36 -0
  27. data/docs/rain.code +22 -0
  28. data/docs/slack.code +17 -0
  29. data/docs/stripe.code +7 -0
  30. data/docs/twitter.code +9 -0
  31. data/language-ruby.gemspec +18 -0
  32. data/lib/code/error.rb +18 -0
  33. data/lib/code/node/base_10.rb +29 -0
  34. data/lib/code/node/base_16.rb +13 -0
  35. data/lib/code/node/base_2.rb +13 -0
  36. data/lib/code/node/base_8.rb +13 -0
  37. data/lib/code/node/boolean.rb +22 -0
  38. data/lib/code/node/call.rb +47 -0
  39. data/lib/code/node/call_argument.rb +21 -0
  40. data/lib/code/node/chained_call.rb +23 -0
  41. data/lib/code/node/code.rb +20 -0
  42. data/lib/code/node/decimal.rb +26 -0
  43. data/lib/code/node/dictionnary.rb +33 -0
  44. data/lib/code/node/equal.rb +34 -0
  45. data/lib/code/node/function.rb +20 -0
  46. data/lib/code/node/function_parameter.rb +31 -0
  47. data/lib/code/node/if.rb +59 -0
  48. data/lib/code/node/if_modifier.rb +47 -0
  49. data/lib/code/node/list.rb +16 -0
  50. data/lib/code/node/negation.rb +15 -0
  51. data/lib/code/node/not.rb +15 -0
  52. data/lib/code/node/nothing.rb +12 -0
  53. data/lib/code/node/number.rb +25 -0
  54. data/lib/code/node/operation.rb +38 -0
  55. data/lib/code/node/power.rb +20 -0
  56. data/lib/code/node/rescue.rb +17 -0
  57. data/lib/code/node/splat.rb +15 -0
  58. data/lib/code/node/statement.rb +59 -0
  59. data/lib/code/node/string.rb +53 -0
  60. data/lib/code/node/ternary.rb +24 -0
  61. data/lib/code/node/unary_minus.rb +15 -0
  62. data/lib/code/node/while.rb +35 -0
  63. data/lib/code/node.rb +13 -0
  64. data/lib/code/object/argument.rb +32 -0
  65. data/lib/code/object/boolean.rb +27 -0
  66. data/lib/code/object/decimal.rb +162 -0
  67. data/lib/code/object/dictionnary.rb +96 -0
  68. data/lib/code/object/function.rb +64 -0
  69. data/lib/code/object/global.rb +42 -0
  70. data/lib/code/object/integer.rb +221 -0
  71. data/lib/code/object/list.rb +200 -0
  72. data/lib/code/object/nothing.rb +23 -0
  73. data/lib/code/object/number.rb +6 -0
  74. data/lib/code/object/range.rb +146 -0
  75. data/lib/code/object/ruby_function.rb +31 -0
  76. data/lib/code/object/string.rb +88 -0
  77. data/lib/code/object.rb +197 -0
  78. data/lib/code/parser/addition.rb +21 -0
  79. data/lib/code/parser/and_operator.rb +17 -0
  80. data/lib/code/parser/bitwise_and.rb +17 -0
  81. data/lib/code/parser/bitwise_or.rb +21 -0
  82. data/lib/code/parser/boolean.rb +17 -0
  83. data/lib/code/parser/call.rb +122 -0
  84. data/lib/code/parser/chained_call.rb +47 -0
  85. data/lib/code/parser/class.rb +45 -0
  86. data/lib/code/parser/code.rb +25 -0
  87. data/lib/code/parser/dictionnary.rb +67 -0
  88. data/lib/code/parser/equal.rb +94 -0
  89. data/lib/code/parser/equality.rb +35 -0
  90. data/lib/code/parser/equality_lower.rb +9 -0
  91. data/lib/code/parser/function.rb +85 -0
  92. data/lib/code/parser/greater.rb +25 -0
  93. data/lib/code/parser/group.rb +22 -0
  94. data/lib/code/parser/if.rb +63 -0
  95. data/lib/code/parser/if_modifier.rb +55 -0
  96. data/lib/code/parser/list.rb +42 -0
  97. data/lib/code/parser/multiplication.rb +25 -0
  98. data/lib/code/parser/name.rb +101 -0
  99. data/lib/code/parser/negation.rb +30 -0
  100. data/lib/code/parser/not_keyword.rb +23 -0
  101. data/lib/code/parser/nothing.rb +22 -0
  102. data/lib/code/parser/number.rb +154 -0
  103. data/lib/code/parser/operation.rb +35 -0
  104. data/lib/code/parser/or_keyword.rb +21 -0
  105. data/lib/code/parser/or_operator.rb +17 -0
  106. data/lib/code/parser/power.rb +43 -0
  107. data/lib/code/parser/range.rb +17 -0
  108. data/lib/code/parser/rescue.rb +39 -0
  109. data/lib/code/parser/shift.rb +21 -0
  110. data/lib/code/parser/splat.rb +31 -0
  111. data/lib/code/parser/statement.rb +9 -0
  112. data/lib/code/parser/string.rb +78 -0
  113. data/lib/code/parser/ternary.rb +46 -0
  114. data/lib/code/parser/unary_minus.rb +31 -0
  115. data/lib/code/parser/while.rb +36 -0
  116. data/lib/code/parser/whitespace.rb +49 -0
  117. data/lib/code/parser.rb +19 -0
  118. data/lib/code/ruby.rb +162 -0
  119. data/lib/code-ruby.rb +10 -0
  120. data/lib/code.rb +47 -0
  121. data/lib/language/atom.rb +343 -0
  122. data/lib/language/output.rb +130 -0
  123. data/lib/language/parser/absent/present.rb +8 -0
  124. data/lib/language/parser/absent.rb +6 -0
  125. data/lib/language/parser/end_of_input.rb +6 -0
  126. data/lib/language/parser/interuption.rb +38 -0
  127. data/lib/language/parser/not_end_of_input.rb +6 -0
  128. data/lib/language/parser/str/not_found.rb +16 -0
  129. data/lib/language/parser/str.rb +6 -0
  130. data/lib/language/parser.rb +53 -0
  131. data/lib/language-ruby.rb +10 -0
  132. data/lib/language.rb +80 -0
  133. data/lib/template/node/code_part.rb +13 -0
  134. data/lib/template/node/part.rb +19 -0
  135. data/lib/template/node/template.rb +15 -0
  136. data/lib/template/node/text_part.rb +13 -0
  137. data/lib/template/node.rb +4 -0
  138. data/lib/template/parser/template.rb +39 -0
  139. data/lib/template/parser.rb +19 -0
  140. data/lib/template/version.rb +3 -0
  141. data/lib/template-ruby.rb +10 -0
  142. data/lib/template.rb +50 -0
  143. data/spec/code/addition_spec.rb +13 -0
  144. data/spec/code/and_operator_spec.rb +13 -0
  145. data/spec/code/bitwise_and_spec.rb +13 -0
  146. data/spec/code/bitwise_or_spec.rb +13 -0
  147. data/spec/code/boolean_spec.rb +13 -0
  148. data/spec/code/call_spec.rb +21 -0
  149. data/spec/code/chained_call_spec.rb +16 -0
  150. data/spec/code/dictionnary_spec.rb +17 -0
  151. data/spec/code/equal_spec.rb +26 -0
  152. data/spec/code/equality_spec.rb +13 -0
  153. data/spec/code/function_spec.rb +18 -0
  154. data/spec/code/greater_spec.rb +18 -0
  155. data/spec/code/group_spec.rb +12 -0
  156. data/spec/code/if_modifier_spec.rb +20 -0
  157. data/spec/code/if_spec.rb +25 -0
  158. data/spec/code/list_spec.rb +17 -0
  159. data/spec/code/multiplication_spec.rb +18 -0
  160. data/spec/code/negation_spec.rb +20 -0
  161. data/spec/code/not_keyword_spec.rb +13 -0
  162. data/spec/code/nothing_spec.rb +17 -0
  163. data/spec/code/number_spec.rb +22 -0
  164. data/spec/code/or_keyword_spec.rb +17 -0
  165. data/spec/code/or_operator_spec.rb +16 -0
  166. data/spec/code/parser/boolean_spec.rb +16 -0
  167. data/spec/code/parser/call_spec.rb +26 -0
  168. data/spec/code/parser/chained_call.rb +17 -0
  169. data/spec/code/parser/dictionnary_spec.rb +18 -0
  170. data/spec/code/parser/function_spec.rb +16 -0
  171. data/spec/code/parser/group_spec.rb +18 -0
  172. data/spec/code/parser/list_spec.rb +18 -0
  173. data/spec/code/parser/number_spec.rb +12 -0
  174. data/spec/code/parser/string_spec.rb +21 -0
  175. data/spec/code/parser_spec.rb +23 -0
  176. data/spec/code/power_spec.rb +13 -0
  177. data/spec/code/range_spec.rb +16 -0
  178. data/spec/code/rescue_spec.rb +13 -0
  179. data/spec/code/shift_spec.rb +13 -0
  180. data/spec/code/splat_spec.rb +13 -0
  181. data/spec/code/string_spec.rb +25 -0
  182. data/spec/code/ternary_spec.rb +18 -0
  183. data/spec/code/unary_minus_spec.rb +13 -0
  184. data/spec/code/while_spec.rb +18 -0
  185. data/spec/spec_helper.rb +6 -0
  186. data/template-ruby.gemspec +19 -0
  187. metadata +284 -0
@@ -0,0 +1,17 @@
1
+ class Code
2
+ class Node
3
+ class Rescue < Node
4
+ def initialize(parsed)
5
+ @left = Node::Statement.new(parsed.delete(:left))
6
+ @right = Node::Statement.new(parsed.delete(:right))
7
+ super(parsed)
8
+ end
9
+
10
+ def evaluate(**args)
11
+ @left.evaluate(**args)
12
+ rescue ::Code::Error
13
+ @right.evaluate(**args)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ class Code
2
+ class Node
3
+ class Splat < Node
4
+ def initialize(parsed)
5
+ @operator = parsed.delete(:operator)
6
+ @right = Node::Statement.new(parsed.delete(:right))
7
+ super(parsed)
8
+ end
9
+
10
+ def evaluate(**args)
11
+ @right.evaluate(**args).call(operator: @operator, arguments: [], **args)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,59 @@
1
+ class Code
2
+ class Node
3
+ class Statement < Node
4
+ def initialize(parsed)
5
+ if parsed.key?(:nothing)
6
+ @statement = Node::Nothing.new(parsed.delete(:nothing))
7
+ elsif parsed.key?(:boolean)
8
+ @statement = Node::Boolean.new(parsed.delete(:boolean))
9
+ elsif parsed.key?(:group)
10
+ @statement = Node::Code.new(parsed.delete(:group))
11
+ elsif parsed.key?(:call)
12
+ @statement = Node::Call.new(parsed.delete(:call))
13
+ elsif parsed.key?(:number)
14
+ @statement = Node::Number.new(parsed.delete(:number))
15
+ elsif parsed.key?(:string)
16
+ @statement = Node::String.new(parsed.delete(:string))
17
+ elsif parsed.key?(:list)
18
+ @statement = Node::List.new(parsed.delete(:list))
19
+ elsif parsed.key?(:dictionnary)
20
+ @statement = Node::Dictionnary.new(parsed.delete(:dictionnary))
21
+ elsif parsed.key?(:chained_call)
22
+ @statement = Node::ChainedCall.new(parsed.delete(:chained_call))
23
+ elsif parsed.key?(:operation)
24
+ @statement = Node::Operation.new(parsed.delete(:operation))
25
+ elsif parsed.key?(:equal)
26
+ @statement = Node::Equal.new(parsed.delete(:equal))
27
+ elsif parsed.key?(:function)
28
+ @statement = Node::Function.new(parsed.delete(:function))
29
+ elsif parsed.key?(:negation)
30
+ @statement = Node::Negation.new(parsed.delete(:negation))
31
+ elsif parsed.key?(:power)
32
+ @statement = Node::Power.new(parsed.delete(:power))
33
+ elsif parsed.key?(:unary_minus)
34
+ @statement = Node::UnaryMinus.new(parsed.delete(:unary_minus))
35
+ elsif parsed.key?(:ternary)
36
+ @statement = Node::Ternary.new(parsed.delete(:ternary))
37
+ elsif parsed.key?(:rescue)
38
+ @statement = Node::Rescue.new(parsed.delete(:rescue))
39
+ elsif parsed.key?(:not)
40
+ @statement = Node::Not.new(parsed.delete(:not))
41
+ elsif parsed.key?(:if_modifier)
42
+ @statement = Node::IfModifier.new(parsed.delete(:if_modifier))
43
+ elsif parsed.key?(:if)
44
+ @statement = Node::If.new(parsed.delete(:if))
45
+ elsif parsed.key?(:while)
46
+ @statement = Node::While.new(parsed.delete(:while))
47
+ elsif parsed.key?(:splat)
48
+ @statement = Node::Splat.new(parsed.delete(:splat))
49
+ end
50
+
51
+ super(parsed)
52
+ end
53
+
54
+ def evaluate(**args)
55
+ @statement.evaluate(**args)
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,53 @@
1
+ class Code
2
+ class Node
3
+ class String < Node
4
+ class Part < Node
5
+ class Code < Node
6
+ def initialize(parsed)
7
+ @code = Node::Code.new(parsed)
8
+ end
9
+
10
+ def evaluate(**args)
11
+ @code.evaluate(**args)
12
+ end
13
+ end
14
+
15
+ class Text < Node
16
+ def initialize(parsed)
17
+ @text = parsed
18
+ end
19
+
20
+ def evaluate(**args)
21
+ ::Code::Object::String.new(@text)
22
+ end
23
+ end
24
+
25
+ def initialize(parsed)
26
+ if parsed.key?(:text)
27
+ @part = Node::String::Part::Text.new(parsed.delete(:text))
28
+ elsif parsed.key?(:code)
29
+ @part = Node::String::Part::Code.new(parsed.delete(:code))
30
+ end
31
+
32
+ super(parsed)
33
+ end
34
+
35
+ def evaluate(**args)
36
+ @part.evaluate(**args)
37
+ end
38
+ end
39
+
40
+ def initialize(parsed)
41
+ parsed = [] if parsed == ""
42
+
43
+ @parts = parsed.map { |part| Node::String::Part.new(part) }
44
+ end
45
+
46
+ def evaluate(**args)
47
+ ::Code::Object::String.new(
48
+ @parts.map { |part| part.evaluate(**args) }.map(&:to_s).join
49
+ )
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,24 @@
1
+ class Code
2
+ class Node
3
+ class Ternary < Node
4
+ def initialize(parsed)
5
+ @left = Node::Statement.new(parsed.delete(:left))
6
+ @middle = Node::Statement.new(parsed.delete(:middle))
7
+ if parsed.key?(:right)
8
+ @right = Node::Statement.new(parsed.delete(:right))
9
+ end
10
+ super(parsed)
11
+ end
12
+
13
+ def evaluate(**args)
14
+ if @left.evaluate(**args).truthy?
15
+ @middle.evaluate(**args)
16
+ elsif @right
17
+ @right.evaluate(**args)
18
+ else
19
+ ::Code::Object::Nothing.new
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,15 @@
1
+ class Code
2
+ class Node
3
+ class UnaryMinus < Node
4
+ def initialize(parsed)
5
+ @operator = parsed.delete(:operator)
6
+ @right = Node::Statement.new(parsed.delete(:right))
7
+ super(parsed)
8
+ end
9
+
10
+ def evaluate(**args)
11
+ @right.evaluate(**args).call(operator: @operator, arguments: [], **args)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ class Code
2
+ class Node
3
+ class While < Node
4
+ WHILE_KEYWORD = "while"
5
+ UNTIL_KEYWORD = "until"
6
+
7
+ def initialize(parsed)
8
+ @operator = parsed.delete(:operator)
9
+ @statement = Node::Statement.new(parsed.delete(:statement))
10
+ @body = Node::Code.new(parsed.delete(:body))
11
+ super(parsed)
12
+ end
13
+
14
+ def evaluate(**args)
15
+ if @operator == WHILE_KEYWORD
16
+ last = ::Code::Object::Nothing.new
17
+
18
+ while @statement.evaluate(**args).truthy?
19
+ last = @body.evaluate(**args)
20
+ end
21
+
22
+ last
23
+ elsif @operator == UNTIL_KEYWORD
24
+ last = ::Code::Object::Nothing.new
25
+
26
+ last = @body.evaluate(**args) while @statement.evaluate(**args).falsy?
27
+
28
+ last
29
+ else
30
+ raise NotImplementedError.new(@operator)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
data/lib/code/node.rb ADDED
@@ -0,0 +1,13 @@
1
+ class Code
2
+ class Node
3
+ def initialize(parsed)
4
+ if parsed.any?
5
+ raise NotImplementedError.new(self.class.name + ": " + parsed.inspect)
6
+ end
7
+ end
8
+
9
+ def evaluate(**args)
10
+ raise NotImplementedError.new(self.class.name + "#evaluate")
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,32 @@
1
+ class Code
2
+ class Object
3
+ class Argument
4
+ attr_reader :value, :name
5
+
6
+ def initialize(value, name: nil)
7
+ @value = value
8
+ @name = name
9
+ end
10
+
11
+ def regular?
12
+ !name
13
+ end
14
+
15
+ def keyword?
16
+ !regular?
17
+ end
18
+
19
+ def name_value
20
+ [name, value]
21
+ end
22
+
23
+ def to_s
24
+ "<Argument #{value.inspect}>"
25
+ end
26
+
27
+ def inspect
28
+ to_s
29
+ end
30
+ end
31
+ end
32
+ 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,162 @@
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
+ value = arguments.first&.value
22
+
23
+ if operator == "%"
24
+ sig(arguments) { ::Code::Object::Number }
25
+ modulo(value)
26
+ elsif operator == "+"
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)
78
+ else
79
+ super
80
+ end
81
+ end
82
+
83
+ def to_s
84
+ raw.to_s("F")
85
+ end
86
+
87
+ def inspect
88
+ to_s
89
+ end
90
+
91
+ private
92
+
93
+ def modulo(other)
94
+ ::Code::Object::Decimal.new(raw % other.raw)
95
+ end
96
+
97
+ def plus(other)
98
+ if other.is_a?(::Code::Object::Number)
99
+ ::Code::Object::Decimal.new(raw + other.raw)
100
+ else
101
+ ::Code::Object::String.new(to_s + other.to_s)
102
+ end
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
160
+ end
161
+ end
162
+ end
@@ -0,0 +1,96 @@
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
+ globals = multi_fetch(args, *::Code::GLOBALS)
14
+ value = arguments.first&.value
15
+
16
+ if operator == "values"
17
+ sig(arguments)
18
+ values
19
+ elsif operator == "keys"
20
+ sig(arguments)
21
+ keys
22
+ elsif operator == "each"
23
+ sig(arguments) { ::Code::Object::Function }
24
+ each(value, **globals)
25
+ elsif key?(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
34
+ else
35
+ super
36
+ end
37
+ end
38
+
39
+ def merge(other)
40
+ ::Code::Object::Dictionnary.new(raw.merge(other.raw))
41
+ end
42
+
43
+ def fetch(key)
44
+ raw.fetch(key)
45
+ end
46
+
47
+ def [](key)
48
+ raw[key]
49
+ end
50
+
51
+ def []=(key, value)
52
+ raw[key] = value
53
+ end
54
+
55
+ def key?(key)
56
+ raw.key?(key)
57
+ end
58
+
59
+ def deep_dup
60
+ ::Code::Object::Dictionnary.new(raw.deep_dup)
61
+ end
62
+
63
+ def to_s
64
+ "{#{raw.map { |key, value| "#{key.inspect} => #{value.inspect}" }.join(", ")}}"
65
+ end
66
+
67
+ def inspect
68
+ to_s
69
+ end
70
+
71
+ private
72
+
73
+ def keys
74
+ ::Code::Object::List.new(raw.keys)
75
+ end
76
+
77
+ def values
78
+ ::Code::Object::List.new(raw.values)
79
+ end
80
+
81
+ def each(argument, **globals)
82
+ raw.each do |key, value|
83
+ argument.call(
84
+ arguments: [
85
+ ::Code::Object::Argument.new(key),
86
+ ::Code::Object::Argument.new(value)
87
+ ],
88
+ **globals
89
+ )
90
+ end
91
+
92
+ self
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,64 @@
1
+ class Code
2
+ class Object
3
+ class Function < ::Code::Object
4
+ def initialize(parameters:, body:)
5
+ @parameters = parameters
6
+ @body = body
7
+ end
8
+
9
+ def call(**args)
10
+ operator = args.fetch(:operator, nil)
11
+ arguments = args.fetch(:arguments, [])
12
+ globals = multi_fetch(args, *::Code::GLOBALS)
13
+
14
+ if operator.nil? || operator == "call"
15
+ call_function(args: arguments, globals: globals)
16
+ else
17
+ super
18
+ end
19
+ end
20
+
21
+ def to_s
22
+ ""
23
+ end
24
+
25
+ def inspect
26
+ "function"
27
+ end
28
+
29
+ private
30
+
31
+ attr_reader :parameters, :body
32
+
33
+ def call_function(args:, globals:)
34
+ new_context = deep_dup(globals[:context])
35
+
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)
41
+ )
42
+ elsif parameter.keyword_splat?
43
+ new_context[parameter.name] = ::Code::Object::Dictionnary.new(
44
+ args.select(&:keyword?).map(&:name_value).to_h
45
+ )
46
+ else
47
+ arg = args[index]&.value
48
+ arg = parameter.evaluate(**globals) if arg.nil?
49
+ new_context[parameter.name] = arg
50
+ end
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
55
+ else
56
+ raise NotImplementedError
57
+ end
58
+ end
59
+
60
+ body.evaluate(**globals, context: new_context)
61
+ end
62
+ end
63
+ end
64
+ 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