language-ruby 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 (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