liquidscript 0.4.1 → 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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/lib/liquidscript/buffer.rb +2 -2
  3. data/lib/liquidscript/compiler/icr.rb +1 -0
  4. data/lib/liquidscript/compiler/icr/classes.rb +11 -3
  5. data/lib/liquidscript/compiler/icr/expressions.rb +56 -10
  6. data/lib/liquidscript/compiler/icr/functions.rb +7 -6
  7. data/lib/liquidscript/compiler/icr/heredoc.rb +28 -0
  8. data/lib/liquidscript/compiler/icr/literals.rb +102 -9
  9. data/lib/liquidscript/errors.rb +6 -0
  10. data/lib/liquidscript/generator/base.rb +1 -1
  11. data/lib/liquidscript/generator/base/replacements.rb +2 -2
  12. data/lib/liquidscript/generator/javascript.rb +21 -0
  13. data/lib/liquidscript/generator/javascript/exceptions.rb +42 -0
  14. data/lib/liquidscript/generator/javascript/literals.rb +71 -9
  15. data/lib/liquidscript/generator/javascript/metas.rb +14 -13
  16. data/lib/liquidscript/generator/javascript/objects.rb +21 -16
  17. data/lib/liquidscript/icr/set.rb +8 -0
  18. data/lib/liquidscript/scanner/base/lexer.rb +13 -10
  19. data/lib/liquidscript/scanner/liquidscript.rb +95 -17
  20. data/lib/liquidscript/template.rb +1 -2
  21. data/lib/liquidscript/version.rb +1 -1
  22. data/liquidscript.gemspec +1 -0
  23. data/spec/fixtures/class.compile.yml +12 -1
  24. data/spec/fixtures/class.generate.yml +4 -4
  25. data/spec/fixtures/combination.generate.yml +4 -4
  26. data/spec/fixtures/complex.generate.yml +5 -5
  27. data/spec/fixtures/expression.generate.yml +1 -1
  28. data/spec/fixtures/heredoc.generate.yml +9 -0
  29. data/spec/fixtures/literals.generate.yml +9 -1
  30. data/spec/fixtures/loop.generate.yml +16 -0
  31. data/spec/fixtures/main.compile.yml +19 -15
  32. data/spec/fixtures/operator.generate.yml +10 -2
  33. data/spec/fixtures/string.compile.yml +20 -1
  34. data/spec/fixtures/string.generate.yml +1 -1
  35. data/spec/fixtures/underscore.js +28 -0
  36. data/spec/fixtures/underscore.ls +2 -1
  37. data/spec/liquidscript/compiler/icr_spec.rb +2 -0
  38. data/spec/liquidscript/node_spec.rb +21 -0
  39. data/spec/liquidscript/scanner/lexer_spec.rb +23 -2
  40. data/spec/support/matchers/compile.rb +1 -1
  41. data/spec/support/matchers/generate.rb +6 -3
  42. data/spec/support/matchers/run.rb +12 -0
  43. metadata +28 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4f11281d148fb640ffc2e0f7e8620d90db902979
4
- data.tar.gz: 8e49e850af07a8d34d44595e2f8d550eb09e5a05
3
+ metadata.gz: 6fe5335e4dfdf4f906673f081655d77b96fbca14
4
+ data.tar.gz: 5c1ff4ce91cc20fa3ede9c4fc7dfe030e752fef6
5
5
  SHA512:
6
- metadata.gz: f7e8ba8419ac72d775682a35fd5f8acea5a8210e20d2279ef508b1008470eb8f737d9226c481bd35f9ce3bfb2f980e9c191cd47e1d86afb56148f5a7ddde1cb4
7
- data.tar.gz: 05d976029b24a986e993c40604ea57bd2034bd27dde7aa376e14db6db3a1bfc65e537009fab0bcac41612e44fed250c654a37571924bac12e8f80daa023874e6
6
+ metadata.gz: 051c175bba208e2cd9154d72722a55d31a2db037a17ed87dc4b8c7e275df81c6ec344fe35bd9f7bbae431b72c9c0f4789e8dfc9d54820a302360b759a92c777b
7
+ data.tar.gz: 8f4c51719dcc4dfa40856605796694cc3bd00f579eee32fd63056126e86269fcdb302ddc217bcc1643e3191b61159255a904a50381d94f79fb88af3992cea602
@@ -13,8 +13,8 @@ module Liquidscript
13
13
  self
14
14
  end
15
15
 
16
- def block(str)
17
- append str.gsub(/^[ \t]+/, '')
16
+ def block(indent, str)
17
+ append str.gsub(/^[ \t]{#{indent*2}}/, '')
18
18
  end
19
19
 
20
20
  def set_join!(to)
@@ -3,6 +3,7 @@ require "liquidscript/compiler/icr/functions"
3
3
  require "liquidscript/compiler/icr/literals"
4
4
  require "liquidscript/compiler/icr/classes"
5
5
  require "liquidscript/compiler/icr/helpers"
6
+ require "liquidscript/compiler/icr/heredoc"
6
7
 
7
8
  module Liquidscript
8
9
  module Compiler
@@ -6,10 +6,18 @@ module Liquidscript
6
6
  def compile_class
7
7
  shift :class
8
8
  name = shift :identifier
9
+ inherit = nil
9
10
  set name
11
+ # Inheritance ftw!
12
+ if peek?(:colon)
13
+ shift :colon
14
+ inherit = shift :identifier
15
+ ref inherit
16
+ end
17
+
10
18
  body = _compile_class_body(false)
11
19
 
12
- code :class, name, body
20
+ code :class, name, inherit, body
13
21
  end
14
22
 
15
23
  def compile_module
@@ -22,7 +30,7 @@ module Liquidscript
22
30
  end
23
31
 
24
32
  def _compile_class_body(mod = false)
25
- shift :lbrack
33
+ shift :lbrace
26
34
 
27
35
  components = []
28
36
 
@@ -34,7 +42,7 @@ module Liquidscript
34
42
  end
35
43
 
36
44
  loop do
37
- expect :newline, :rbrack => action.end_loop,
45
+ expect :newline, :rbrace => action.end_loop,
38
46
  :comma => action.shift,
39
47
  :module => action { components << compile_module },
40
48
  :class => action { components << compile_class },
@@ -8,7 +8,8 @@ module Liquidscript
8
8
  #
9
9
  # @return [ICR::Code]
10
10
  def compile_expression
11
- expect :if, :unless, :class, :module, :_ => :vexpression
11
+ expect :if, :unless, :class, :module, :loop, :for,
12
+ :while, :action, :try, :_ => :vexpression
12
13
  end
13
14
 
14
15
  # Compiles an expression that returns a value.
@@ -19,11 +20,19 @@ module Liquidscript
19
20
  :istring, :lparen,
20
21
  :sstring, :operator,
21
22
  :keyword, :unop,
23
+ :regex,
22
24
  :newline,
23
25
  :istring_begin,
24
- :lbrack => :object,
25
- :lbrace => :array,
26
- :arrow => :function
26
+ :iheredoc_begin,
27
+ :lbrace => :object,
28
+ :lbrack => :array,
29
+ :arrow => :function,
30
+ [
31
+ :heredoc_ref, :iheredoc_ref
32
+ ] => :href,
33
+ [
34
+ :heredoc, :iheredoc
35
+ ] => :heredoc
27
36
 
28
37
  if peek? :binop
29
38
  compile_binop(out)
@@ -120,9 +129,9 @@ module Liquidscript
120
129
  shift :lparen
121
130
  conditional = compile_vexpression
122
131
  shift :rparen
123
- shift :lbrack
132
+ shift :lbrace
124
133
 
125
- body = collect_compiles(:expression, :rbrack)
134
+ body = collect_compiles(:expression, :rbrace)
126
135
 
127
136
  if peek?(:elsif, :else)
128
137
  code key, conditional, body, expect(:elsif, :else)
@@ -137,21 +146,58 @@ module Liquidscript
137
146
  shift :lparen
138
147
  conditional = compile_vexpression
139
148
  shift :rparen
140
- shift :lbrack
149
+ shift :lbrace
141
150
 
142
- body = collect_compiles(:expression, :rbrack)
151
+ body = collect_compiles(:expression, :rbrace)
143
152
  code :unless, conditional, body
144
153
  end
145
154
 
146
155
  def compile_else
147
156
  shift :else
148
- shift :lbrack
157
+ shift :lbrace
149
158
 
150
- body = collect_compiles(:expression, :rbrack)
159
+ body = collect_compiles(:expression, :rbrace)
151
160
 
152
161
  code :else, body
153
162
  end
154
163
 
164
+ def compile_try
165
+ shift :try
166
+ shift :lbrace
167
+ try_body = collect_compiles(:expression, :rbrace)
168
+
169
+ next_part = if peek?(:catch)
170
+ _compile_catch
171
+ elsif peek?(:finally)
172
+ _compile_finally
173
+ end
174
+
175
+ code :try, try_body, next_part
176
+ end
177
+
178
+ def _compile_catch
179
+ shift :catch
180
+ shift :lparen
181
+ var = shift :identifier
182
+ shift :rparen
183
+ shift :lbrace
184
+ catch_body = collect_compiles(:expression, :rbrace)
185
+
186
+ next_part = if peek?(:finally)
187
+ _compile_finally
188
+ end
189
+
190
+ code :catch, var, catch_body, next_part
191
+ end
192
+
193
+ def _compile_finally
194
+ shift :finally
195
+ shift :lbrace
196
+ finally_body = collect_compiles(:expression, :rbrace)
197
+
198
+ code :finally, finally_body
199
+ end
200
+
155
201
  end
156
202
  end
157
203
  end
@@ -7,16 +7,17 @@ module Liquidscript
7
7
  shift :prop
8
8
 
9
9
  property = action do |ident|
10
- code :property, prop, ident
10
+ code :property, prop, (ident.value || ident.type)
11
11
  end
12
12
 
13
13
  # Just in case there is a property named 'class' or 'module'
14
- code = expect [:identifier, :class, :module] => property
14
+ v = expect [:identifier, :class, :module] => property
15
15
 
16
- expect :lparen => action { compile_call(code) },
17
- :equal => action { compile_assignment(code) },
18
- :prop => action { compile_property(code) },
19
- :_ => action { code }
16
+ expect :lparen => action { compile_call(v) },
17
+ :equal => action { compile_assignment(v) },
18
+ :prop => action { compile_property(v) },
19
+ :unop => action { |o| code :op, v, o },
20
+ :_ => action { v }
20
21
  end
21
22
 
22
23
  def compile_call(subject)
@@ -0,0 +1,28 @@
1
+ module Liquidscript
2
+ module Compiler
3
+ class ICR < Base
4
+ class Heredoc
5
+
6
+ attr_reader :name
7
+ attr_accessor :body
8
+
9
+ include Liquidscript::ICR::Representable
10
+
11
+ def initialize(name, interpolate)
12
+ @name = name
13
+ @interpolate = interpolate
14
+ @body = []
15
+ end
16
+
17
+ def interpolate?
18
+ !!@interpolate
19
+ end
20
+
21
+ def to_a
22
+ [:heredoc, @name, @body]
23
+ end
24
+
25
+ end
26
+ end
27
+ end
28
+ end
@@ -7,17 +7,110 @@ module Liquidscript
7
7
  code :number, pop.value
8
8
  end
9
9
 
10
+ def compile_action
11
+ code :action, shift(:action)
12
+ end
13
+
14
+ def compile_while
15
+ shift :while
16
+ shift :lparen
17
+ conditional = compile_vexpression
18
+ shift :rparen
19
+ shift :lbrace
20
+ body = collect_compiles(:expression, :rbrace)
21
+ code :while, conditional, body
22
+ end
23
+
24
+ def compile_for
25
+ shift :for
26
+ shift :lparen
27
+ if peek?(:identifier)
28
+ ident = shift :identifier
29
+ if peek?(:identifier)
30
+ _compile_for_in(ident)
31
+ else
32
+ _compile_for_seg(compile_identifier(ident))
33
+ end
34
+ else
35
+ compile_for_seg compile_vexpression
36
+ end
37
+ end
38
+
39
+ def _compile_for_in(ident)
40
+ content = shift :identifier
41
+ unless content.value == "in"
42
+ raise CompileError, "Expected `in', got #{content.value}"
43
+ end
44
+
45
+ obj = shift :identifier
46
+ shift :rparen
47
+ shift :lbrace
48
+
49
+ set ident
50
+ body = collect_compiles(:expression, :rbrace)
51
+ code :for_in, ident, ref(obj), body
52
+ end
53
+
54
+ def _compile_for_seg(first)
55
+ shift :comma
56
+ second = compile_vexpression
57
+ shift :comma
58
+ third = compile_vexpression
59
+ shift :rparen
60
+ shift :lbrace
61
+
62
+ body = collect_compiles(:expression, :rbrace)
63
+ code :for_seg, first, second, third, body
64
+ end
65
+
10
66
  def compile_identifier(identifier)
11
67
  default = action do
12
68
  code :get, ref(identifier)
13
69
  end
14
70
 
15
- expect :equal => action { compile_assignment(identifier) },
16
- :prop => action { compile_property(identifier) },
17
- :lparen => action { compile_call(identifier) },
71
+ expect :equal => action { compile_assignment(identifier) },
72
+ :prop => action { compile_property(identifier) },
73
+ :lparen => action { compile_call(identifier) },
74
+ :unop => action { |o| code :op, ref(identifier), o },
18
75
  :_ => default
19
76
  end
20
77
 
78
+ def compile_regex
79
+ code :regex, shift(:regex)
80
+ end
81
+
82
+ def compile_href
83
+ ref = shift :heredoc_ref, :iheredoc_ref
84
+ heredoc = Heredoc.new(ref.value, ref.type == :iheredoc_ref)
85
+ top[:heredocs] ||= []
86
+ top[:herenum] ||= 0
87
+ top[:heredocs] << heredoc
88
+ code :href, heredoc
89
+ end
90
+
91
+ def compile_heredoc
92
+ h = shift(:heredoc, :iheredoc)
93
+
94
+ top[:heredocs][top[:herenum]].body = [h]
95
+ top[:herenum] += 1
96
+ nil
97
+ end
98
+
99
+ def compile_iheredoc_begin
100
+ start = shift :iheredoc_begin
101
+ contents = [start]
102
+
103
+ loop do
104
+ contents << compile_vexpression
105
+ contents << shift(:iheredoc)
106
+ peek?(:istring_begin)
107
+ end
108
+
109
+ top[:heredocs][top[:herenum]].body = contents
110
+ top[:herenum] += 1
111
+ nil
112
+ end
113
+
21
114
  def compile_istring_begin
22
115
  start = shift :istring_begin
23
116
  contents = [start]
@@ -49,9 +142,9 @@ module Liquidscript
49
142
  end
50
143
 
51
144
  def compile_object
52
- shift :lbrack
145
+ shift :lbrace
53
146
 
54
- objects = collect_compiles :rbrack,
147
+ objects = collect_compiles :rbrace,
55
148
  :comma => action.shift,
56
149
  :newline => action.shift do
57
150
  [compile_object_key, compile_vexpression]
@@ -61,9 +154,9 @@ module Liquidscript
61
154
  end
62
155
 
63
156
  def compile_array
64
- shift :lbrace
157
+ shift :lbrack
65
158
 
66
- parts = collect_compiles(:vexpression, :rbrace,
159
+ parts = collect_compiles(:vexpression, :rbrack,
67
160
  :comma => action.shift)
68
161
 
69
162
  code :array, parts
@@ -89,7 +182,7 @@ module Liquidscript
89
182
 
90
183
  def compile_function_with_parameters(parameters)
91
184
  shift :arrow
92
- shift :lbrack
185
+ shift :lbrace
93
186
 
94
187
  expressions = Liquidscript::ICR::Set.new
95
188
  expressions.context = Liquidscript::ICR::Context.new
@@ -107,7 +200,7 @@ module Liquidscript
107
200
  end
108
201
 
109
202
  loop do
110
- expect :rbrack => action.end_loop,
203
+ expect :rbrace => action.end_loop,
111
204
  :_ => expression
112
205
  end
113
206
 
@@ -49,4 +49,10 @@ module Liquidscript
49
49
  end
50
50
  end
51
51
 
52
+ class NoContextError < SyntaxError
53
+ def initialize(context)
54
+ super "Could not find context named #{context.inspect}"
55
+ end
56
+ end
57
+
52
58
  end
@@ -13,7 +13,7 @@ module Liquidscript
13
13
  end
14
14
 
15
15
  def generate
16
- replace(@top, {}).to_s
16
+ replace(@top).to_s
17
17
  end
18
18
 
19
19
  def buffer
@@ -8,12 +8,12 @@ module Liquidscript
8
8
  #
9
9
  # @param code [ICR::Code, #type]
10
10
  # @param context [Hash]
11
- def replace(code, context = {})
11
+ def replace(code)
12
12
  send(:"generate_#{code.type}",
13
13
  code)
14
14
 
15
15
  rescue NoMethodError => e
16
- if e.name == :"_generate_code_#{code.type}"
16
+ if e.name == :"generate_#{code.type}"
17
17
  raise InvalidCodeError.new(code.type)
18
18
  else
19
19
  raise
@@ -1,6 +1,7 @@
1
1
  require "liquidscript/generator/javascript/literals"
2
2
  require "liquidscript/generator/javascript/metas"
3
3
  require "liquidscript/generator/javascript/objects"
4
+ require "liquidscript/generator/javascript/exceptions"
4
5
 
5
6
  module Liquidscript
6
7
  module Generator
@@ -27,11 +28,31 @@ module Liquidscript
27
28
  include Literals
28
29
  include Metas
29
30
  include Objects
31
+ include Exceptions
30
32
 
31
33
  def initialize(top)
32
34
  @modules = []
35
+ @indent = 0
33
36
  super
34
37
  end
38
+
39
+ def indent_level
40
+ " " * @indent
41
+ end
42
+
43
+ def indent!
44
+ @indent += 1
45
+ end
46
+
47
+ def unindent!
48
+ @indent -= 1
49
+ end
50
+
51
+ def insert_into(area, buffer)
52
+ area.inject(buffer) do |m, c|
53
+ m << indent_level << replace(c) << ";\n"
54
+ end
55
+ end
35
56
  end
36
57
  end
37
58
  end