template-ruby 0.4.0 → 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 (204) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/Gemfile +2 -1
  4. data/Gemfile.lock +27 -54
  5. data/TODO +17 -0
  6. data/bin/code +56 -31
  7. data/bin/format +3 -0
  8. data/bin/template +62 -20
  9. data/bin/test +17 -0
  10. data/code-ruby.gemspec +1 -3
  11. data/docs/class.code +9 -0
  12. data/docs/euler/1.template +1 -5
  13. data/docs/euler/5.template +0 -1
  14. data/docs/meetup.code +12 -0
  15. data/docs/precedence.template +6 -39
  16. data/docs/rain.code +22 -0
  17. data/docs/slack.code +17 -0
  18. data/docs/stripe.code +7 -0
  19. data/docs/twitter.code +9 -0
  20. data/language-ruby.gemspec +18 -0
  21. data/lib/code/node/base_10.rb +29 -0
  22. data/lib/code/node/base_16.rb +13 -0
  23. data/lib/code/node/base_2.rb +13 -0
  24. data/lib/code/node/base_8.rb +13 -0
  25. data/lib/code/node/boolean.rb +7 -7
  26. data/lib/code/node/call.rb +32 -38
  27. data/lib/code/node/call_argument.rb +11 -27
  28. data/lib/code/node/chained_call.rb +10 -27
  29. data/lib/code/node/code.rb +4 -6
  30. data/lib/code/node/decimal.rb +26 -0
  31. data/lib/code/node/dictionnary.rb +20 -9
  32. data/lib/code/node/equal.rb +18 -20
  33. data/lib/code/node/function.rb +10 -7
  34. data/lib/code/node/function_parameter.rb +31 -0
  35. data/lib/code/node/if.rb +36 -32
  36. data/lib/code/node/if_modifier.rb +35 -36
  37. data/lib/code/node/list.rb +6 -8
  38. data/lib/code/node/negation.rb +5 -23
  39. data/lib/code/node/not.rb +15 -0
  40. data/lib/code/node/nothing.rb +1 -1
  41. data/lib/code/node/number.rb +14 -12
  42. data/lib/code/node/operation.rb +21 -16
  43. data/lib/code/node/power.rb +10 -6
  44. data/lib/code/node/rescue.rb +4 -3
  45. data/lib/code/node/splat.rb +15 -0
  46. data/lib/code/node/statement.rb +48 -70
  47. data/lib/code/node/string.rb +42 -16
  48. data/lib/code/node/ternary.rb +7 -9
  49. data/lib/code/node/unary_minus.rb +5 -12
  50. data/lib/code/node/while.rb +17 -24
  51. data/lib/code/node.rb +7 -8
  52. data/lib/code/object/argument.rb +2 -11
  53. data/lib/code/object/decimal.rb +45 -30
  54. data/lib/code/object/dictionnary.rb +6 -5
  55. data/lib/code/object/function.rb +20 -23
  56. data/lib/code/object/global.rb +11 -6
  57. data/lib/code/object/integer.rb +73 -30
  58. data/lib/code/object/list.rb +40 -34
  59. data/lib/code/object/range.rb +18 -17
  60. data/lib/code/object/ruby_function.rb +12 -6
  61. data/lib/code/object/string.rb +22 -12
  62. data/lib/code/object.rb +82 -24
  63. data/lib/code/parser/addition.rb +12 -20
  64. data/lib/code/parser/and_operator.rb +9 -20
  65. data/lib/code/parser/bitwise_and.rb +9 -20
  66. data/lib/code/parser/bitwise_or.rb +12 -20
  67. data/lib/code/parser/boolean.rb +10 -7
  68. data/lib/code/parser/call.rb +92 -60
  69. data/lib/code/parser/chained_call.rb +47 -0
  70. data/lib/code/parser/class.rb +45 -0
  71. data/lib/code/parser/code.rb +17 -10
  72. data/lib/code/parser/dictionnary.rb +56 -30
  73. data/lib/code/parser/equal.rb +87 -35
  74. data/lib/code/parser/equality.rb +23 -24
  75. data/lib/code/parser/equality_lower.rb +9 -0
  76. data/lib/code/parser/function.rb +67 -42
  77. data/lib/code/parser/greater.rb +25 -0
  78. data/lib/code/parser/group.rb +13 -8
  79. data/lib/code/parser/if.rb +51 -21
  80. data/lib/code/parser/if_modifier.rb +43 -16
  81. data/lib/code/parser/list.rb +32 -19
  82. data/lib/code/parser/multiplication.rb +15 -20
  83. data/lib/code/parser/name.rb +96 -84
  84. data/lib/code/parser/negation.rb +20 -9
  85. data/lib/code/parser/not_keyword.rb +14 -12
  86. data/lib/code/parser/nothing.rb +13 -8
  87. data/lib/code/parser/number.rb +124 -68
  88. data/lib/code/parser/operation.rb +35 -0
  89. data/lib/code/parser/or_keyword.rb +12 -20
  90. data/lib/code/parser/or_operator.rb +9 -20
  91. data/lib/code/parser/power.rb +32 -14
  92. data/lib/code/parser/range.rb +9 -17
  93. data/lib/code/parser/rescue.rb +29 -13
  94. data/lib/code/parser/shift.rb +11 -21
  95. data/lib/code/parser/splat.rb +31 -0
  96. data/lib/code/parser/statement.rb +4 -3
  97. data/lib/code/parser/string.rb +53 -62
  98. data/lib/code/parser/ternary.rb +36 -15
  99. data/lib/code/parser/unary_minus.rb +23 -5
  100. data/lib/code/parser/while.rb +26 -15
  101. data/lib/code/parser/whitespace.rb +49 -0
  102. data/lib/code/parser.rb +15 -0
  103. data/lib/code/ruby.rb +13 -12
  104. data/lib/code-ruby.rb +2 -11
  105. data/lib/code.rb +16 -13
  106. data/lib/language/atom.rb +343 -0
  107. data/lib/language/output.rb +130 -0
  108. data/lib/language/parser/absent/present.rb +8 -0
  109. data/lib/language/parser/absent.rb +6 -0
  110. data/lib/language/parser/end_of_input.rb +6 -0
  111. data/lib/language/parser/interuption.rb +38 -0
  112. data/lib/language/parser/not_end_of_input.rb +6 -0
  113. data/lib/language/parser/str/not_found.rb +16 -0
  114. data/lib/language/parser/str.rb +6 -0
  115. data/lib/language/parser.rb +53 -0
  116. data/lib/language-ruby.rb +10 -0
  117. data/lib/language.rb +80 -0
  118. data/lib/template/node/code_part.rb +1 -1
  119. data/lib/template/node/part.rb +1 -1
  120. data/lib/template/node/template.rb +1 -1
  121. data/lib/template/node/text_part.rb +1 -1
  122. data/lib/template/node.rb +1 -1
  123. data/lib/template/parser/template.rb +26 -17
  124. data/lib/template/parser.rb +15 -0
  125. data/lib/template/version.rb +1 -1
  126. data/lib/template-ruby.rb +2 -11
  127. data/lib/template.rb +6 -11
  128. data/spec/code/addition_spec.rb +13 -0
  129. data/spec/code/and_operator_spec.rb +13 -0
  130. data/spec/code/bitwise_and_spec.rb +13 -0
  131. data/spec/code/bitwise_or_spec.rb +13 -0
  132. data/spec/code/boolean_spec.rb +13 -0
  133. data/spec/code/call_spec.rb +21 -0
  134. data/spec/code/chained_call_spec.rb +16 -0
  135. data/spec/code/dictionnary_spec.rb +17 -0
  136. data/spec/code/equal_spec.rb +26 -0
  137. data/spec/code/equality_spec.rb +13 -0
  138. data/spec/code/function_spec.rb +18 -0
  139. data/spec/code/greater_spec.rb +18 -0
  140. data/spec/code/group_spec.rb +12 -0
  141. data/spec/code/if_modifier_spec.rb +20 -0
  142. data/spec/code/if_spec.rb +25 -0
  143. data/spec/code/list_spec.rb +17 -0
  144. data/spec/code/multiplication_spec.rb +18 -0
  145. data/spec/code/negation_spec.rb +20 -0
  146. data/spec/code/not_keyword_spec.rb +13 -0
  147. data/spec/code/nothing_spec.rb +17 -0
  148. data/spec/code/number_spec.rb +22 -0
  149. data/spec/code/or_keyword_spec.rb +17 -0
  150. data/spec/code/or_operator_spec.rb +16 -0
  151. data/spec/code/parser/boolean_spec.rb +5 -7
  152. data/spec/code/parser/call_spec.rb +16 -56
  153. data/spec/code/parser/chained_call.rb +17 -0
  154. data/spec/code/parser/dictionnary_spec.rb +8 -9
  155. data/spec/code/parser/function_spec.rb +5 -21
  156. data/spec/code/parser/group_spec.rb +18 -0
  157. data/spec/code/parser/list_spec.rb +9 -20
  158. data/spec/code/parser/number_spec.rb +4 -109
  159. data/spec/code/parser/string_spec.rb +9 -17
  160. data/spec/code/parser_spec.rb +23 -0
  161. data/spec/code/power_spec.rb +13 -0
  162. data/spec/code/range_spec.rb +16 -0
  163. data/spec/code/rescue_spec.rb +13 -0
  164. data/spec/code/shift_spec.rb +13 -0
  165. data/spec/code/splat_spec.rb +13 -0
  166. data/spec/code/string_spec.rb +25 -0
  167. data/spec/code/ternary_spec.rb +18 -0
  168. data/spec/code/unary_minus_spec.rb +13 -0
  169. data/spec/code/while_spec.rb +18 -0
  170. data/spec/spec_helper.rb +4 -1
  171. data/template-ruby.gemspec +2 -4
  172. metadata +112 -72
  173. data/lib/code/node/base_10_decimal.rb +0 -32
  174. data/lib/code/node/base_10_integer.rb +0 -32
  175. data/lib/code/node/base_10_number.rb +0 -19
  176. data/lib/code/node/base_16_number.rb +0 -19
  177. data/lib/code/node/base_2_number.rb +0 -19
  178. data/lib/code/node/base_8_number.rb +0 -19
  179. data/lib/code/node/block.rb +0 -17
  180. data/lib/code/node/defined.rb +0 -19
  181. data/lib/code/node/dictionnary_key_value.rb +0 -23
  182. data/lib/code/node/function_argument.rb +0 -45
  183. data/lib/code/node/group.rb +0 -13
  184. data/lib/code/node/keyword_call_argument.rb +0 -30
  185. data/lib/code/node/keyword_function_argument.rb +0 -33
  186. data/lib/code/node/name.rb +0 -28
  187. data/lib/code/node/not_keyword.rb +0 -13
  188. data/lib/code/node/or_keyword.rb +0 -34
  189. data/lib/code/node/range.rb +0 -31
  190. data/lib/code/node/regular_call_argument.rb +0 -34
  191. data/lib/code/node/regular_function_argument.rb +0 -36
  192. data/lib/code/node/string_characters.rb +0 -13
  193. data/lib/code/node/string_component.rb +0 -23
  194. data/lib/code/node/string_interpolation.rb +0 -13
  195. data/lib/code/parser/defined.rb +0 -20
  196. data/lib/code/parser/greater_than.rb +0 -33
  197. data/spec/call_spec.rb +0 -22
  198. data/spec/code/error/type_error_spec.rb +0 -63
  199. data/spec/code/parser/name_spec.rb +0 -15
  200. data/spec/code/parser/nothing_spec.rb +0 -19
  201. data/spec/code_spec.rb +0 -182
  202. data/spec/function_spec.rb +0 -26
  203. data/spec/template/parser/template_spec.rb +0 -19
  204. data/spec/template_spec.rb +0 -52
@@ -1,20 +1,20 @@
1
1
  class Code
2
2
  class Node
3
3
  class Boolean < Node
4
- TRUE = "true"
5
- FALSE = "false"
4
+ TRUE_KEYWORD = "true"
5
+ FALSE_KEYWORD = "false"
6
6
 
7
- def initialize(boolean)
8
- @boolean = boolean
7
+ def initialize(parsed)
8
+ @boolean = parsed
9
9
  end
10
10
 
11
11
  def evaluate(**args)
12
- if @boolean == TRUE
12
+ if @boolean == TRUE_KEYWORD
13
13
  ::Code::Object::Boolean.new(true)
14
- elsif @boolean == FALSE
14
+ elsif @boolean == FALSE_KEYWORD
15
15
  ::Code::Object::Boolean.new(false)
16
16
  else
17
- raise NotImplementedError, @boolean.inspect
17
+ raise NotImplementedError.new(@boolean)
18
18
  end
19
19
  end
20
20
  end
@@ -1,52 +1,46 @@
1
1
  class Code
2
2
  class Node
3
3
  class Call < Node
4
- def initialize(call)
5
- @left = ::Code::Node::Statement.new(call.fetch(:left))
4
+ class Block < Node
5
+ def initialize(parsed)
6
+ @parameters =
7
+ parsed
8
+ .delete(:parameters) { [] }
9
+ .map { |parameter| Node::FunctionParameter.new(parameter) }
6
10
 
7
- @arguments = call.fetch(:arguments, [])
8
- @arguments.map! { |argument| ::Code::Node::CallArgument.new(argument) }
11
+ @body = Node::Code.new(parsed.delete(:body))
9
12
 
10
- if call.key?(:right)
11
- @right =
12
- call
13
- .fetch(:right)
14
- .map { |right| ::Code::Node::ChainedCall.new(right) }
13
+ super(parsed)
15
14
  end
16
15
 
17
- if call.key?(:block)
18
- @block = ::Code::Node::Block.new(call.fetch(:block))
16
+ def evaluate(**args)
17
+ ::Code::Object::Argument.new(
18
+ ::Code::Object::Function.new(parameters: @parameters, body: @body)
19
+ )
19
20
  end
20
21
  end
21
22
 
22
- def evaluate(**args)
23
- if @right
24
- left = @left.evaluate(**args)
25
-
26
- @right.reduce(left) do |acc, element|
27
- element.evaluate(**args.merge(object: acc))
28
- end
29
- else
30
- arguments =
31
- @arguments.map do |argument|
32
- ::Code::Object::Argument.new(
33
- argument.evaluate(**args),
34
- name: argument.name,
35
- splat: argument.splat?,
36
- keyword_splat: argument.keyword_splat?,
37
- block: argument.block?,
38
- )
39
- end
40
-
41
- if @block
42
- arguments << ::Code::Object::Argument.new(
43
- @block.evaluate(**args),
44
- block: true,
45
- )
46
- end
47
-
48
- @left.evaluate(**args.merge(arguments: arguments))
23
+ def initialize(parsed)
24
+ @name = parsed.delete(:name)
25
+ @arguments =
26
+ parsed
27
+ .delete(:arguments) { [] }
28
+ .map { |argument| Node::CallArgument.new(argument) }
29
+
30
+ if parsed.key?(:block)
31
+ @block = Node::Call::Block.new(parsed.delete(:block))
49
32
  end
33
+
34
+ super(parsed)
35
+ end
36
+
37
+ def evaluate(**args)
38
+ arguments = @arguments.map { |argument| argument.evaluate(**args) }
39
+ arguments << @block.evaluate(**args) if @block
40
+
41
+ name = ::Code::Object::String.new(@name)
42
+
43
+ args.fetch(:object).call(operator: name, arguments: arguments, **args)
50
44
  end
51
45
  end
52
46
  end
@@ -1,36 +1,20 @@
1
1
  class Code
2
2
  class Node
3
3
  class CallArgument < Node
4
- def initialize(argument)
5
- if argument.key?(:regular)
6
- @argument =
7
- ::Code::Node::RegularCallArgument.new(argument.fetch(:regular))
8
- elsif argument.key?(:keyword)
9
- @argument =
10
- ::Code::Node::KeywordCallArgument.new(argument.fetch(:keyword))
11
- else
12
- raise NotImplementedError.new(argument.inspect)
13
- end
4
+ def initialize(parsed)
5
+ @value = Node::Code.new(parsed.delete(:value))
6
+ @name = parsed.delete(:name)
14
7
  end
15
8
 
16
9
  def evaluate(**args)
17
- @argument.evaluate(**args)
18
- end
19
-
20
- def name
21
- @argument.name
22
- end
23
-
24
- def block?
25
- @argument.block?
26
- end
27
-
28
- def splat?
29
- @argument.splat?
30
- end
31
-
32
- def keyword_splat?
33
- @argument.keyword_splat?
10
+ if @name
11
+ ::Code::Object::Argument.new(
12
+ @value.evaluate(**args),
13
+ name: ::Code::Object::String.new(@name)
14
+ )
15
+ else
16
+ ::Code::Object::Argument.new(@value.evaluate(**args))
17
+ end
34
18
  end
35
19
  end
36
20
  end
@@ -1,39 +1,22 @@
1
1
  class Code
2
2
  class Node
3
3
  class ChainedCall < Node
4
- def initialize(chained_call)
5
- @name = ::Code::Node::Name.new(chained_call.fetch(:name))
4
+ def initialize(parsed)
5
+ @first = Node::Statement.new(parsed.delete(:first))
6
+ @others =
7
+ parsed
8
+ .delete(:others)
9
+ .map { |operator| Node::Statement.new(operator) }
6
10
 
7
- @arguments = chained_call.fetch(:arguments, [])
8
- @arguments.map! { |argument| ::Code::Node::CallArgument.new(argument) }
9
-
10
- if chained_call.key?(:block)
11
- @block = ::Code::Node::Block.new(chained_call.fetch(:block))
12
- end
11
+ super(parsed)
13
12
  end
14
13
 
15
14
  def evaluate(**args)
16
- arguments =
17
- @arguments.map do |argument|
18
- ::Code::Object::Argument.new(
19
- argument.evaluate(
20
- **args.merge(object: ::Code::Object::Global.new),
21
- ),
22
- name: argument.name,
23
- splat: argument.splat?,
24
- keyword_splat: argument.keyword_splat?,
25
- block: argument.block?,
26
- )
27
- end
15
+ first = @first.evaluate(**args)
28
16
 
29
- if @block
30
- arguments << ::Code::Object::Argument.new(
31
- @block.evaluate(**args.merge(object: ::Code::Object::Global.new)),
32
- block: true,
33
- )
17
+ @others.reduce(first) do |acc, element|
18
+ element.evaluate(**args.merge(object: acc))
34
19
  end
35
-
36
- @name.evaluate(**args.merge(arguments: arguments))
37
20
  end
38
21
  end
39
22
  end
@@ -1,18 +1,16 @@
1
1
  class Code
2
2
  class Node
3
3
  class Code < Node
4
- def initialize(statements)
5
- statements = [] if statements.to_s.blank?
6
-
7
- @statements =
8
- statements.map { |statement| ::Code::Node::Statement.new(statement) }
4
+ def initialize(parsed)
5
+ @statements = parsed.map { |statement| Node::Statement.new(statement) }
9
6
  end
10
7
 
11
8
  def evaluate(**args)
12
9
  last = ::Code::Object::Nothing.new
13
10
 
14
11
  @statements.each do |statement|
15
- last = statement.evaluate(**args)
12
+ last =
13
+ statement.evaluate(**args.merge(object: ::Code::Object::Global.new))
16
14
  end
17
15
 
18
16
  last
@@ -0,0 +1,26 @@
1
+ class Code
2
+ class Node
3
+ class Decimal < Node
4
+ def initialize(parsed)
5
+ @decimal = parsed.delete(:decimal)
6
+
7
+ if parsed.key?(:exponent)
8
+ @exponent = Node::Statement.new(parsed.delete(:exponent))
9
+ end
10
+
11
+ super(parsed)
12
+ end
13
+
14
+ def evaluate(**args)
15
+ if @exponent
16
+ ::Code::Object::Decimal.new(
17
+ @decimal,
18
+ exponent: @exponent.evaluate(**args)
19
+ )
20
+ else
21
+ ::Code::Object::Decimal.new(@decimal)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -1,20 +1,31 @@
1
1
  class Code
2
2
  class Node
3
3
  class Dictionnary < Node
4
- def initialize(key_values)
5
- if key_values.blank?
6
- @key_values = []
7
- else
8
- @key_values =
9
- key_values.map do |key_value|
10
- ::Code::Node::DictionnaryKeyValue.new(key_value)
11
- end
4
+ class KeyValue < Node
5
+ def initialize(parsed)
6
+ if parsed.key?(:statement)
7
+ @key = Node::Statement.new(parsed.delete(:statement))
8
+ elsif parsed.key?(:name)
9
+ @key = Node::String.new([{ text: parsed.delete(:name) }])
10
+ end
11
+
12
+ @value = Node::Code.new(parsed.delete(:value))
13
+ end
14
+
15
+ def evaluate(**args)
16
+ [@key.evaluate(**args), @value.evaluate(**args)]
12
17
  end
13
18
  end
14
19
 
20
+ def initialize(parsed)
21
+ parsed = [] if parsed == ""
22
+ @key_values =
23
+ parsed.map { |key_value| Node::Dictionnary::KeyValue.new(key_value) }
24
+ end
25
+
15
26
  def evaluate(**args)
16
27
  ::Code::Object::Dictionnary.new(
17
- @key_values.map { |key_value| key_value.evaluate(**args) }.to_h,
28
+ @key_values.map { |key_value| key_value.evaluate(**args) }.to_h
18
29
  )
19
30
  end
20
31
  end
@@ -1,35 +1,33 @@
1
1
  class Code
2
2
  class Node
3
3
  class Equal < Node
4
- def initialize(equal)
5
- @left = equal.fetch(:left).fetch(:name)
6
- @operator = equal.fetch(:operator)
7
- @right = ::Code::Node::Statement.new(equal.fetch(:right))
4
+ def initialize(parsed)
5
+ @operator = parsed.delete(:operator)
6
+ @left = parsed.delete(:left)
7
+ @right = Node::Statement.new(parsed.delete(:right))
8
+ super(parsed)
8
9
  end
9
10
 
10
11
  def evaluate(**args)
11
12
  right = @right.evaluate(**args)
13
+ left = ::Code::Object::String.new(@left)
12
14
  context = args.fetch(:context)
13
15
 
14
- if operator
15
- if context[left]
16
- context[left] = simple_call(context[left], operator, right, **args)
17
- else
18
- raise ::Code::Error::UndefinedVariable.new("#{left} is undefined")
19
- end
20
- else
16
+ if @operator == ""
21
17
  context[left] = right
22
- end
23
- end
24
-
25
- private
18
+ else
19
+ if context[left].nil?
20
+ raise ::Code::Error::Undefined.new("#{left} is not defined")
21
+ end
26
22
 
27
- def operator
28
- @operator.to_s[0...-1].to_sym.presence
29
- end
23
+ context[left] = context.fetch(left).call(
24
+ operator: @operator,
25
+ arguments: [::Code::Object::Argument.new(right)],
26
+ **args
27
+ )
28
+ end
30
29
 
31
- def left
32
- ::Code::Object::String.new(@left.to_s)
30
+ args[:context][left]
33
31
  end
34
32
  end
35
33
  end
@@ -1,16 +1,19 @@
1
1
  class Code
2
2
  class Node
3
3
  class Function < Node
4
- def initialize(function)
5
- @body = ::Code::Node::Code.new(function.fetch(:body))
6
- @arguments = function.fetch(:arguments, [])
7
- @arguments.map! do |argument|
8
- ::Code::Node::FunctionArgument.new(argument)
9
- end
4
+ def initialize(parsed)
5
+ @parameters =
6
+ parsed
7
+ .delete(:parameters) { [] }
8
+ .map { |parameter| Node::FunctionParameter.new(parameter) }
9
+
10
+ @body = Node::Code.new(parsed.delete(:body))
11
+
12
+ super(parsed)
10
13
  end
11
14
 
12
15
  def evaluate(**args)
13
- ::Code::Object::Function.new(arguments: @arguments, body: @body)
16
+ ::Code::Object::Function.new(parameters: @parameters, body: @body)
14
17
  end
15
18
  end
16
19
  end
@@ -0,0 +1,31 @@
1
+ class Code
2
+ class Node
3
+ class FunctionParameter < Node
4
+ def initialize(parsed)
5
+ @name = parsed.delete(:name)
6
+ @keyword = !!parsed.delete(:keyword)
7
+ super(parsed)
8
+ end
9
+
10
+ def name
11
+ ::Code::Object::String.new(@name)
12
+ end
13
+
14
+ def regular?
15
+ !@keyword
16
+ end
17
+
18
+ def keyword?
19
+ !!@keyword
20
+ end
21
+
22
+ def regular_splat?
23
+ false
24
+ end
25
+
26
+ def keyword_splat?
27
+ false
28
+ end
29
+ end
30
+ end
31
+ end
data/lib/code/node/if.rb CHANGED
@@ -3,47 +3,51 @@ class Code
3
3
  class If < Node
4
4
  IF_KEYWORD = "if"
5
5
  UNLESS_KEYWORD = "unless"
6
+ ELSIF_KEYWORD = "elsif"
7
+ ELSE_KEYWORD = "else"
6
8
 
7
- class Else
8
- def initialize(else_parsed)
9
- if else_parsed.key?(:operator)
10
- @operator = else_parsed.fetch(:operator)
11
- @statement =
12
- ::Code::Node::Statement.new(else_parsed.fetch(:statement))
13
- end
9
+ class Else < Node
10
+ attr_reader :operator, :statement, :body
14
11
 
15
- @body = ::Code::Node::Code.new(else_parsed.fetch(:body))
16
- end
12
+ def initialize(parsed)
13
+ @operator = parsed.delete(:operator)
14
+ @body = Node::Code.new(parsed.delete(:body))
17
15
 
18
- attr_reader :operator, :body, :statement
16
+ if parsed.key?(:statement)
17
+ @statement = Node::Statement.new(parsed.delete(:statement))
18
+ end
19
+ end
19
20
  end
20
21
 
21
- def initialize(if_parsed)
22
- @if_operator = if_parsed.fetch(:if_operator)
23
- @if_statement =
24
- ::Code::Node::Statement.new(if_parsed.fetch(:if_statement))
25
- @if_body = ::Code::Node::Code.new(if_parsed.fetch(:if_body))
26
- @elses = if_parsed.fetch(:elses, [])
27
- @elses.map! { |else_parsed| ::Code::Node::If::Else.new(else_parsed) }
22
+ def initialize(parsed)
23
+ @first_operator = parsed.delete(:first_operator)
24
+ @first_statement = Node::Statement.new(parsed.delete(:first_statement))
25
+ @first_body = Node::Code.new(parsed.delete(:first_body))
26
+ @elses =
27
+ parsed.delete(:elses) { [] }.map { |elses| Node::If::Else.new(elses) }
28
+ super(parsed)
28
29
  end
29
30
 
30
31
  def evaluate(**args)
31
- if_object = @if_statement.evaluate(**args)
32
-
33
- if @if_operator == IF_KEYWORD && if_object.truthy?
34
- @if_body.evaluate(**args)
35
- elsif @if_operator == UNLESS_KEYWORD && if_object.falsy?
36
- @if_body.evaluate(**args)
32
+ if @first_operator == IF_KEYWORD &&
33
+ @first_statement.evaluate(**args).truthy?
34
+ @first_body.evaluate(**args)
35
+ elsif @first_operator == UNLESS_KEYWORD &&
36
+ @first_statement.evaluate(**args).falsy?
37
+ @first_body.evaluate(**args)
37
38
  else
38
- @elses.each do |else_node|
39
- if else_node.operator == IF_KEYWORD
40
- else_object = else_node.statement.evaluate(**args)
41
- return else_node.body.evaluate(**args) if else_object.truthy?
42
- elsif else_node.operator == UNLESS_KEYWORD
43
- else_object = else_node.statement.evaluate(**args)
44
- return else_node.body.evaluate(**args) if else_object.falsy?
45
- elsif else_node.operator.nil?
46
- return else_node.body.evaluate(**args)
39
+ @elses.each do |elses|
40
+ if elses.operator == ELSIF_KEYWORD &&
41
+ elses.statement.evaluate(**args).truthy?
42
+ return elses.body.evaluate(**args)
43
+ elsif elses.operator == IF_KEYWORD &&
44
+ elses.statement.evaluate(**args).truthy?
45
+ return elses.body.evaluate(**args)
46
+ elsif elses.operator == UNLESS_KEYWORD &&
47
+ elses.statement.evaluate(**args).falsy?
48
+ return elses.body.evaluate(**args)
49
+ elsif elses.operator == ELSE_KEYWORD
50
+ return elses.body.evaluate(**args)
47
51
  end
48
52
  end
49
53
 
@@ -1,48 +1,47 @@
1
1
  class Code
2
2
  class Node
3
3
  class IfModifier < Node
4
- IF_KEYWORD = :if
5
- UNLESS_KEYWORD = :unless
6
- WHILE_KEYWORD = :while
7
- UNTIL_KEYWORD = :until
8
-
9
- def initialize(if_modifier)
10
- @left = ::Code::Node::Statement.new(if_modifier.fetch(:left))
11
- @operator = if_modifier.fetch(:operator)
12
- @right = ::Code::Node::Statement.new(if_modifier.fetch(:right))
4
+ IF_KEYWORD = "if"
5
+ UNLESS_KEYWORD = "unless"
6
+ WHILE_KEYWORD = "while"
7
+ UNTIL_KEYWORD = "until"
8
+
9
+ def initialize(parsed)
10
+ @operator = parsed.delete(:operator)
11
+ @left = Node::Statement.new(parsed.delete(:left))
12
+ @right = Node::Statement.new(parsed.delete(:right))
13
+ super(parsed)
13
14
  end
14
15
 
15
16
  def evaluate(**args)
16
- if operator == IF_KEYWORD
17
- right = @right.evaluate(**args)
18
-
19
- right.truthy? ? @left.evaluate(**args) : ::Code::Object::Nothing.new
20
- elsif operator == UNLESS_KEYWORD
21
- right = @right.evaluate(**args)
22
-
23
- right.truthy? ? ::Code::Object::Nothing.new : @left.evaluate(**args)
24
- elsif operator == WHILE_KEYWORD
25
- left = ::Code::Object::Nothing.new
26
-
27
- left = @left.evaluate(**args) while @right.evaluate(**args).truthy?
28
-
29
- left
30
- elsif operator == UNTIL_KEYWORD
31
- left = ::Code::Object::Nothing.new
32
-
33
- left = @left.evaluate(**args) until @right.evaluate(**args).truthy?
34
-
35
- left
17
+ if @operator == IF_KEYWORD
18
+ if @right.evaluate(**args).truthy?
19
+ @left.evaluate(**args)
20
+ else
21
+ ::Code::Object::Nothing.new
22
+ end
23
+ elsif @operator == UNLESS_KEYWORD
24
+ if @right.evaluate(**args).falsy?
25
+ @left.evaluate(**args)
26
+ else
27
+ ::Code::Object::Nothing.new
28
+ end
29
+ elsif @operator == WHILE_KEYWORD
30
+ last = ::Code::Object::Nothing.new
31
+
32
+ last = @left.evaluate(**args) while @right.evaluate(**args).truthy?
33
+
34
+ last
35
+ elsif @operator == UNTIL_KEYWORD
36
+ last = ::Code::Object::Nothing.new
37
+
38
+ last = @left.evaluate(**args) while @right.evaluate(**args).falsy?
39
+
40
+ last
36
41
  else
37
- raise NotImplementedError.new(operator.inspect)
42
+ raise NotImplementedError.new(@operator)
38
43
  end
39
44
  end
40
-
41
- private
42
-
43
- def operator
44
- @operator.to_sym
45
- end
46
45
  end
47
46
  end
48
47
  end
@@ -1,17 +1,15 @@
1
1
  class Code
2
2
  class Node
3
3
  class List < Node
4
- def initialize(codes)
5
- if codes.to_s.blank?
6
- @codes = []
7
- else
8
- @codes =
9
- codes.map { |code| ::Code::Node::Code.new(code.fetch(:code)) }
10
- end
4
+ def initialize(parsed)
5
+ parsed = [] if parsed == ""
6
+ @elements = parsed.map { |element| Node::Code.new(element) }
11
7
  end
12
8
 
13
9
  def evaluate(**args)
14
- ::Code::Object::List.new(@codes.map { |code| code.evaluate(**args) })
10
+ ::Code::Object::List.new(
11
+ @elements.map { |element| element.evaluate(**args) }
12
+ )
15
13
  end
16
14
  end
17
15
  end
@@ -1,33 +1,15 @@
1
1
  class Code
2
2
  class Node
3
3
  class Negation < Node
4
- EXCLAMATION_POINT = "!"
5
- PLUS = "+"
6
-
7
- def initialize(negation)
8
- @operator = negation.fetch(:operator)
9
- @statement = ::Code::Node::Statement.new(negation.fetch(:statement))
4
+ def initialize(parsed)
5
+ @operator = parsed.delete(:operator)
6
+ @right = Node::Statement.new(parsed.delete(:right))
7
+ super(parsed)
10
8
  end
11
9
 
12
10
  def evaluate(**args)
13
- object = @statement.evaluate(**args)
14
-
15
- if operator == EXCLAMATION_POINT
16
- if object.truthy?
17
- ::Code::Object::Boolean.new(false)
18
- else
19
- ::Code::Object::Boolean.new(true)
20
- end
21
- elsif operator == PLUS
22
- object
23
- else
24
- raise NotImplementedError.new(operator)
25
- end
11
+ @right.evaluate(**args).call(operator: @operator, arguments: [], **args)
26
12
  end
27
-
28
- private
29
-
30
- attr_reader :operator
31
13
  end
32
14
  end
33
15
  end
@@ -0,0 +1,15 @@
1
+ class Code
2
+ class Node
3
+ class Not < 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