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
@@ -0,0 +1,53 @@
1
+ class Language
2
+ class Parser
3
+ attr_accessor :input, :buffer, :output, :root, :cursor
4
+
5
+ def initialize(root:, input:, cursor: 0, buffer: "", output: Output.new)
6
+ @root = root
7
+ @input = input
8
+ @cursor = cursor
9
+ @buffer = buffer
10
+ @output = output
11
+ end
12
+
13
+ def parse(check_end_of_input: true)
14
+ @root.parse(self)
15
+
16
+ if @cursor == @input.size || !check_end_of_input
17
+ @output.present? ? @output : Output.new(@buffer)
18
+ else
19
+ raise NotEndOfInput.new(self)
20
+ end
21
+ end
22
+
23
+ def consume(n)
24
+ if @cursor + n <= @input.size
25
+ @buffer += @input[@cursor, n]
26
+ @cursor += n
27
+ else
28
+ raise EndOfInput.new(self)
29
+ end
30
+ end
31
+
32
+ def aka(name)
33
+ if @buffer.empty?
34
+ @output = Output.new({ name => @output })
35
+ else
36
+ @output[name] = Output.new(@buffer)
37
+ @buffer = ""
38
+ end
39
+ end
40
+
41
+ def next?(string)
42
+ @input[@cursor...(@cursor + string.size)] == string
43
+ end
44
+
45
+ def buffer?
46
+ @buffer != ""
47
+ end
48
+
49
+ def output?
50
+ @output.present?
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,10 @@
1
+ require "bigdecimal"
2
+ require "stringio"
3
+ require "timeout"
4
+ require "zeitwerk"
5
+
6
+ loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
7
+ loader.ignore("#{__dir__}/template-ruby.rb")
8
+ loader.ignore("#{__dir__}/code-ruby.rb")
9
+ loader.ignore("#{__dir__}/language-ruby.rb")
10
+ loader.setup
data/lib/language.rb ADDED
@@ -0,0 +1,80 @@
1
+ class Language
2
+ def self.parse(input)
3
+ new.parse(input)
4
+ end
5
+
6
+ def self.absent
7
+ Atom::Absent.new(parent: new)
8
+ end
9
+
10
+ def self.ignore
11
+ Atom::Ignore.new(parent: new)
12
+ end
13
+
14
+ def self.maybe
15
+ Atom::Maybe.new(parent: new)
16
+ end
17
+
18
+ def self.repeat(min = 0, max = nil)
19
+ Atom::Repeat.new(parent: new, min: min, max: max)
20
+ end
21
+
22
+ def self.aka(name)
23
+ Atom::Aka.new(parent: new, name: name)
24
+ end
25
+
26
+ def self.|(other)
27
+ Atom::Or.new(left: new, right: other)
28
+ end
29
+
30
+ def self.>>(other)
31
+ Atom::And.new(left: new, right: other)
32
+ end
33
+
34
+ def self.<<(other)
35
+ Atom::And.new(left: new, right: other)
36
+ end
37
+
38
+ def self.then(&block)
39
+ Atom::Then.new(parent: new, block: block)
40
+ end
41
+
42
+ def parse(input_or_parser)
43
+ if input_or_parser.is_a?(Parser)
44
+ parser = input_or_parser
45
+ clone =
46
+ Parser.new(
47
+ root: root,
48
+ input: parser.input,
49
+ cursor: parser.cursor,
50
+ buffer: parser.buffer,
51
+ output: parser.output
52
+ )
53
+
54
+ clone.parse(check_end_of_input: false)
55
+
56
+ parser.cursor = clone.cursor
57
+ parser.buffer = clone.buffer
58
+ parser.output = clone.output
59
+ else
60
+ input = input_or_parser
61
+ Parser.new(root: root, input: input).parse
62
+ end
63
+ end
64
+
65
+ def str(string)
66
+ Atom::Str.new(string: string)
67
+ end
68
+
69
+ def any
70
+ Atom::Any.new
71
+ end
72
+
73
+ def to_s
74
+ "<#{self.class.name}>"
75
+ end
76
+
77
+ def inspect
78
+ to_s
79
+ end
80
+ end
@@ -1,6 +1,6 @@
1
1
  class Template
2
2
  class Node
3
- class CodePart
3
+ class CodePart < Node
4
4
  def initialize(code)
5
5
  @code = ::Code::Node::Code.new(code)
6
6
  end
@@ -1,6 +1,6 @@
1
1
  class Template
2
2
  class Node
3
- class Part
3
+ class Part < Node
4
4
  def initialize(part)
5
5
  if part.key?(:text)
6
6
  @part = ::Template::Node::TextPart.new(part[:text])
@@ -1,6 +1,6 @@
1
1
  class Template
2
2
  class Node
3
- class Template
3
+ class Template < Node
4
4
  def initialize(parts)
5
5
  @parts = parts.map { |part| ::Template::Node::Part.new(part) }
6
6
  end
@@ -1,6 +1,6 @@
1
1
  class Template
2
2
  class Node
3
- class TextPart
3
+ class TextPart < Node
4
4
  def initialize(text)
5
5
  @text = text
6
6
  end
data/lib/template/node.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  class Template
2
- class Node
2
+ class Node < ::Code::Node
3
3
  end
4
4
  end
@@ -1,30 +1,39 @@
1
1
  class Template
2
2
  class Parser
3
- class Template < Parslet::Parser
4
- rule(:code) { ::Code::Parser::Code.new }
3
+ class Template < Language
4
+ def code
5
+ ::Code::Parser::Code
6
+ end
7
+
8
+ def opening_curly_bracket
9
+ str("{")
10
+ end
5
11
 
6
- rule(:left_curly_bracket) { str("{") }
7
- rule(:right_curly_bracket) { str("}") }
8
- rule(:escape) { str("\\") }
12
+ def closing_curly_bracket
13
+ str("}")
14
+ end
9
15
 
10
- rule(:text_part) do
11
- (
12
- (escape.ignore >> left_curly_bracket) |
13
- (left_curly_bracket.absent? >> any)
14
- ).repeat(1)
16
+ def backslash
17
+ str("\\")
15
18
  end
16
19
 
17
- rule(:code_part) do
18
- left_curly_bracket.ignore >> code >>
19
- (right_curly_bracket.ignore | any.absent?)
20
+ def code_part
21
+ opening_curly_bracket << code << (closing_curly_bracket | any.absent)
20
22
  end
21
23
 
22
- rule(:template) do
23
- (text_part.as(:text) | code_part.as(:code)).repeat(1) |
24
- str("").as(:text).repeat(1, 1)
24
+ def text_character
25
+ (backslash.ignore << opening_curly_bracket) |
26
+ (opening_curly_bracket.absent << any)
25
27
  end
26
28
 
27
- root(:template)
29
+ def text_part
30
+ text_character.repeat(1)
31
+ end
32
+
33
+ def root
34
+ (code_part.aka(:code) | text_part.aka(:text)).repeat |
35
+ str("").aka(:text).repeat(1, 1)
36
+ end
28
37
  end
29
38
  end
30
39
  end
@@ -1,4 +1,19 @@
1
1
  class Template
2
2
  class Parser
3
+ def initialize(input)
4
+ @input = input
5
+ end
6
+
7
+ def self.parse(input)
8
+ new(input).parse
9
+ end
10
+
11
+ def parse
12
+ ::Template::Parser::Template.parse(input)
13
+ end
14
+
15
+ private
16
+
17
+ attr_reader :input
3
18
  end
4
19
  end
@@ -1,3 +1,3 @@
1
1
  require_relative "../template"
2
2
 
3
- Template::Version = Gem::Version.new("0.4.0")
3
+ Template::Version = Gem::Version.new("0.5.0")
data/lib/template-ruby.rb CHANGED
@@ -1,19 +1,10 @@
1
- require "parslet"
2
- require "zeitwerk"
3
1
  require "bigdecimal"
4
- require "active_support"
5
- require "active_support/core_ext/object/blank"
6
- require "active_support/core_ext/object/deep_dup"
7
2
  require "stringio"
8
3
  require "timeout"
4
+ require "zeitwerk"
9
5
 
10
6
  loader = Zeitwerk::Loader.for_gem(warn_on_extra_files: false)
11
7
  loader.ignore("#{__dir__}/template-ruby.rb")
12
8
  loader.ignore("#{__dir__}/code-ruby.rb")
9
+ loader.ignore("#{__dir__}/language-ruby.rb")
13
10
  loader.setup
14
-
15
- class Hash
16
- def multi_fetch(*keys)
17
- keys.map { |key| [key, fetch(key)] }.to_h
18
- end
19
- end
data/lib/template.rb CHANGED
@@ -4,9 +4,7 @@ class Template
4
4
  def initialize(input, io: StringIO.new, timeout: DEFAULT_TIMEOUT, ruby: {})
5
5
  @input = input
6
6
  @parsed =
7
- Timeout.timeout(timeout) do
8
- ::Template::Parser::Template.new.parse(@input)
9
- end
7
+ Timeout.timeout(timeout) { ::Template::Parser.parse(@input).to_raw }
10
8
  @io = io
11
9
  @timeout = timeout || DEFAULT_TIMEOUT
12
10
  @ruby = ::Code::Ruby.to_code(ruby || {})
@@ -24,19 +22,16 @@ class Template
24
22
 
25
23
  def render(context = "")
26
24
  Timeout.timeout(timeout) do
27
- if context.present?
28
- context = ::Code.evaluate(
29
- context,
30
- timeout: timeout,
31
- io: io,
32
- ruby: ruby
33
- )
25
+ if context != ""
26
+ context = ::Code.evaluate(context, timeout: timeout, io: io, ruby: ruby)
34
27
  else
35
28
  context = ::Code::Object::Dictionnary.new
36
29
  end
37
30
 
38
31
  if !context.is_a?(::Code::Object::Dictionnary)
39
- raise ::Code::Template::IncompatibleContext.new("context must be a dictionnary")
32
+ raise ::Code::Template::IncompatibleContext.new(
33
+ "context must be a dictionnary"
34
+ )
40
35
  end
41
36
 
42
37
  context = context.merge(ruby)
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "function" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [["1 + 2", "3"], ["2 - 1", "1"], ["a = 2 - 1 a", "1"]].each do |input, output|
8
+ context input do
9
+ let(:input) { input }
10
+ it { expect(subject).to eq(output) }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "and operator" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [["true && false", "false"], ["true && true", "true"]].each do |input, output|
8
+ context input do
9
+ let(:input) { input }
10
+ it { expect(subject).to eq(output) }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "bitwise and" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [["1 & 1", "1"]].each do |input, output|
8
+ context input do
9
+ let(:input) { input }
10
+ it { expect(subject).to eq(output) }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "bitwise or" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [["1 | 2", "3"], ["1 ^ 2", "3"]].each do |input, output|
8
+ context input do
9
+ let(:input) { input }
10
+ it { expect(subject).to eq(output) }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "boolean" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [%w[true true], %w[false false]].each do |input, output|
8
+ context input do
9
+ let(:input) { input }
10
+ it { expect(subject).to eq(output) }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "call" do
4
+ let(:timeout) { 0 }
5
+
6
+ context "inspecting the io" do
7
+ let(:io) { StringIO.new }
8
+
9
+ subject do
10
+ Code.evaluate(input, io: io, timeout: timeout)
11
+ io.string
12
+ end
13
+
14
+ [["puts(true)", "true\n"], %w[print(false) false]].each do |input, output|
15
+ context input do
16
+ let(:input) { input }
17
+ it { expect(subject).to eq(output) }
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,16 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "chained call" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [
8
+ ["[1, 2, 3].select { |n| n.even? }", "[2]"],
9
+ ["[1, 2, 3].select { |n| n.even? }.select { |n| n.odd? }", "[]"]
10
+ ].each do |input, output|
11
+ context input do
12
+ let(:input) { input }
13
+ it { expect(subject).to eq(output) }
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,17 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "dictionnary" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [
8
+ %w[{} {}],
9
+ ["{ a: 1, b: 2, c: 3 }", '{"a" => 1, "b" => 2, "c" => 3}'],
10
+ ['{ "first_name": "Dorian" }', '{"first_name" => "Dorian"}']
11
+ ].each do |input, output|
12
+ context input do
13
+ let(:input) { input }
14
+ it { expect(subject).to eq(output) }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "function" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [
8
+ ["a = 1 a", "1"],
9
+ ["a = 1 a += 1 a", "2"],
10
+ ["a = 1 a -= 1 a", "0"],
11
+ ["a = 1 a *= 2 a", "2"],
12
+ ["a = 1 a /= 2 a", "0.5"],
13
+ ["a = 10 a %= 2 a", "0"],
14
+ ["a = 1 a >>= 1 a", "0"],
15
+ ["a = 1 a <<= 1 a", "2"],
16
+ ["a = 1 a |= 2 a", "3"],
17
+ ["a = 1 a ^= 2 a", "3"],
18
+ ["a = false a ||= true a", "true"],
19
+ ["a = false a &&= true a", "false"]
20
+ ].each do |input, output|
21
+ context input do
22
+ let(:input) { input }
23
+ it { expect(subject).to eq(output) }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "while" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [["1 == 1", "true"], ["1 == 1 and 2 == 2", "true"]].each do |input, output|
8
+ context input do
9
+ let(:input) { input }
10
+ it { expect(subject).to eq(output) }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "function" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [
8
+ ["even? = (i) => { i.even? } even?(2)", "true"],
9
+ ["even? = (i:) => { i.even? } even?(i: 2)", "true"],
10
+ ["add = (a, b) => { a + b } add(1, 2)", "3"],
11
+ ["minus = (a:, b:) => { a - b } minus(b: 1, a: 2)", "1"]
12
+ ].each do |input, output|
13
+ context input do
14
+ let(:input) { input }
15
+ it { expect(subject).to eq(output) }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "greater" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [
8
+ ["1 > 2", "false"],
9
+ ["1 < 2", "true"],
10
+ ["1 <= 1", "true"],
11
+ ["1 >= 1", "true"]
12
+ ].each do |input, output|
13
+ context input do
14
+ let(:input) { input }
15
+ it { expect(subject).to eq(output) }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,12 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "group" do
4
+ subject { Code.evaluate(input).to_s }
5
+
6
+ [["(true false)", "false"]].each do |input, output|
7
+ context input do
8
+ let(:input) { input }
9
+ it { expect(subject).to eq(output) }
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "if modifier" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [
8
+ ["1 if true", "1"],
9
+ ["1 if false", ""],
10
+ ["1 unless true", ""],
11
+ ["1 unless false", "1"],
12
+ ["a = 0 a += 1 while a < 10 a", "10"],
13
+ ["a = 0 a += 1 until a > 10 a", "11"]
14
+ ].each do |input, output|
15
+ context input do
16
+ let(:input) { input }
17
+ it { expect(subject).to eq(output) }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,25 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "if" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [
8
+ ["if true 1", "1"],
9
+ ["unless false 1", "1"],
10
+ ["if false 1", ""],
11
+ ["unless true 1", ""],
12
+ ["if false 1 else 2", "2"],
13
+ ["if false 1 elsif true 2", "2"],
14
+ ["if false 1 elsif false 2", ""],
15
+ ["if false 1 else if true 2", "2"],
16
+ ["if false 1 else if false 2", ""],
17
+ ["if false 1 else unless false 2", "2"],
18
+ ["if false 1 else unless true 2", ""]
19
+ ].each do |input, output|
20
+ context input do
21
+ let(:input) { input }
22
+ it { expect(subject).to eq(output) }
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,17 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "list" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [
8
+ ["[]", "[]"],
9
+ ["[1, 2, 3]", "[1, 2, 3]"],
10
+ ["[[true]]", "[[true]]"]
11
+ ].each do |input, output|
12
+ context input do
13
+ let(:input) { input }
14
+ it { expect(subject).to eq(output) }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,18 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "multiplication" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [
8
+ ["2 * 3", "6"],
9
+ ["2 * 3 + 2", "8"],
10
+ ["2 / 4", "0.5"],
11
+ ["4 % 3", "1"]
12
+ ].each do |input, output|
13
+ context input do
14
+ let(:input) { input }
15
+ it { expect(subject).to eq(output) }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,20 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "function" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [
8
+ %w[!false true],
9
+ %w[!!true true],
10
+ %w[!!1 true],
11
+ %w[+1 1],
12
+ %w[+1.0 1.0],
13
+ %w[+true true]
14
+ ].each do |input, output|
15
+ context input do
16
+ let(:input) { input }
17
+ it { expect(subject).to eq(output) }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,13 @@
1
+ require "spec_helper"
2
+
3
+ RSpec.describe "not keyword" do
4
+ let(:timeout) { 0 }
5
+ subject { Code.evaluate(input, timeout: timeout).to_s }
6
+
7
+ [["not true", "false"], ["not not false", "false"]].each do |input, output|
8
+ context input do
9
+ let(:input) { input }
10
+ it { expect(subject).to eq(output) }
11
+ end
12
+ end
13
+ end