liquidscript 0.11.0.rc1 → 0.11.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 (36) hide show
  1. checksums.yaml +4 -4
  2. data/lib/liquidscript.rb +1 -1
  3. data/lib/liquidscript/cli.rb +1 -1
  4. data/lib/liquidscript/compiler/base.rb +7 -0
  5. data/lib/liquidscript/compiler/base/blank.rb +7 -0
  6. data/lib/liquidscript/compiler/icr/classes.rb +46 -30
  7. data/lib/liquidscript/compiler/icr/directives.rb +42 -4
  8. data/lib/liquidscript/compiler/icr/expressions.rb +40 -6
  9. data/lib/liquidscript/compiler/icr/functions.rb +7 -11
  10. data/lib/liquidscript/compiler/icr/groups.rb +2 -1
  11. data/lib/liquidscript/compiler/icr/helpers.rb +8 -0
  12. data/lib/liquidscript/compiler/icr/literals.rb +9 -4
  13. data/lib/liquidscript/errors.rb +9 -8
  14. data/lib/liquidscript/generator/javascript/exceptions.rb +5 -1
  15. data/lib/liquidscript/generator/javascript/literals.rb +33 -1
  16. data/lib/liquidscript/generator/javascript/metas.rb +14 -1
  17. data/lib/liquidscript/generator/javascript/objects.rb +3 -0
  18. data/lib/liquidscript/icr/code.rb +43 -2
  19. data/lib/liquidscript/icr/context.rb +163 -85
  20. data/lib/liquidscript/icr/representable.rb +1 -1
  21. data/lib/liquidscript/icr/set.rb +43 -81
  22. data/lib/liquidscript/icr/variable.rb +17 -0
  23. data/lib/liquidscript/scanner/base.rb +11 -1
  24. data/lib/liquidscript/scanner/base/lexer.rb +3 -2
  25. data/lib/liquidscript/scanner/liquidscript/main.rb +36 -34
  26. data/lib/liquidscript/version.rb +1 -1
  27. data/spec/fixtures/class.compile.yml +0 -2
  28. data/spec/fixtures/function.generate.yml +14 -1
  29. data/spec/fixtures/literals.generate.yml +3 -1
  30. data/spec/liquidscript/compiler/icr_spec.rb +1 -1
  31. data/spec/liquidscript/icr/context_spec.rb +2 -2
  32. data/spec/liquidscript/icr/set_spec.rb +4 -4
  33. data/vendor/assets/javascripts/liquidscript.js +103 -0
  34. data/vendor/assets/javascripts/liquidscript.liq +29 -0
  35. data/vendor/assets/javascripts/promise.liq +67 -0
  36. metadata +7 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3659bbe0464cee916b09fbfb082e40cbd630c63b
4
- data.tar.gz: c7708c7a59d1b5ac56edecc2babcd545b21d8321
3
+ metadata.gz: 6c88d468f4ac01f88dc94196315f2b19f107eaa4
4
+ data.tar.gz: e7a78f612a4563d8e61f9700e24e6fb032e85d37
5
5
  SHA512:
6
- metadata.gz: b0fb9dc4ef32911b666bc9914f64ae198e79be36f6dfad11814671717227d9e5b04b9cfd17868caa3ce40af91a81fe90a17e7333d1ecc4ff8eeb5a5391040364
7
- data.tar.gz: 4323533b81a1fba55e715b89a5ffa3b8b369c8c46dce386fdf190fda4d4cb8ccf7204e406960848e7ad23a70ffdc765c74d156eb31b27e576d60a0ad7b8259a4
6
+ metadata.gz: 7fe74221dd6cffe7c26eaaa42a6c5f7fb9133624016fd983cdf03d0e5ebeb95790c4ef7ab552a61a1ab9ddd7c8946c2d96c18994516abf48ec249bc8d22a69fd
7
+ data.tar.gz: e223f22fca8701f39dcb1b55ce1e8328ce35f749406033a0e907d8c4c5dc6b8e2c5d143d2750ee192fc0ed63d85d76491c6dca54cb76d3872bbf70a3592c3ead
@@ -12,7 +12,7 @@ end
12
12
 
13
13
  module Liquidscript
14
14
  def self.compile(data, options = {})
15
- scanner = Scanner::Liquidscript.new(data)
15
+ scanner = Scanner::Liquidscript.new(data, options[:file])
16
16
  if options[:tokens]
17
17
  return scanner.each.to_a.to_sexp
18
18
  end
@@ -48,7 +48,7 @@ module Liquidscript
48
48
 
49
49
  def perform_compiliation(file, out)
50
50
  open_files(file, out) do |infile, outfile|
51
- out = Liquidscript.compile(infile.read)
51
+ out = Liquidscript.compile(infile.read, :file => file)
52
52
  outfile.write(out)
53
53
  end
54
54
  end
@@ -47,6 +47,13 @@ module Liquidscript
47
47
  end
48
48
 
49
49
  top
50
+
51
+ rescue CompileError => e
52
+ token = peek
53
+ part = "#{File.expand_path(@scanner.metadata[:file])}" +
54
+ ":#{token.line}:#{token.column}: " +
55
+ "before #{token.type.to_s.upcase}"
56
+ raise e, e.message, [part, *e.backtrace]
50
57
  end
51
58
 
52
59
  # Checks to see if the given input compiles.
@@ -12,6 +12,13 @@ module Liquidscript
12
12
  nil
13
13
  end
14
14
 
15
+ # We are nil. Yay.
16
+ #
17
+ # @return [true]
18
+ def nil?
19
+ true
20
+ end
21
+
15
22
  # Tells Ruby that we respond to all methods.
16
23
  #
17
24
  # @return [true]
@@ -4,42 +4,50 @@ module Liquidscript
4
4
  module Classes
5
5
 
6
6
  def compile_class
7
- shift :class
8
- name = shift :identifier
9
- inherit = nil
10
- set name
11
- # Inheritance ftw!
12
- if peek?(:colon)
13
- shift :colon
14
- inherit = shift :identifier
15
- inherit = ref(inherit)
7
+ delegate_if_class do
8
+ shift :class
9
+ name = shift :identifier
10
+ inherit = nil
11
+ existed = check(name)
12
+ set(name)
13
+ # Inheritance ftw!
14
+ if peek?(:colon)
15
+ shift :colon
16
+ inherit = shift :identifier
17
+ inherit = ref(inherit)
18
+ end
19
+
20
+ @classes[name.value] =
21
+ expressions = Liquidscript::ICR::Set.new
22
+ expressions.context =
23
+ Liquidscript::ICR::Context.new.tap(&:class!)
24
+ expressions.parent = if inherit
25
+ @classes[inherit.name.to_s].tap { |t| t.parent = top }
26
+ else
27
+ top
28
+ end
29
+
30
+ @set << expressions
31
+ body = _compile_class_body(false)
32
+ expressions.context.force_defined!
33
+ out = code(:class, name, inherit, body)
34
+ @set.pop
35
+ out[:existed] = existed
36
+ out
16
37
  end
17
-
18
- new_context = Liquidscript::ICR::Context.new
19
- new_context.parents << top.context
20
- new_context.class!
21
- @classes[name.value] = new_context
22
-
23
- new_context.parents << @classes[inherit.name.to_s] if inherit
24
-
25
- top.context = new_context
26
- body = _compile_class_body(false)
27
-
28
- new_context.undefined.each do |f|
29
- raise f[1]
30
- end
31
-
32
- code :class, name, inherit, body, top.contexts.pop
33
38
  end
34
39
 
35
40
  def compile_module
36
41
  m = shift :module
37
42
  if peek? :identifier
38
- name = shift :identifier
39
- set name
40
- body = _compile_class_body(true)
41
-
42
- code :module, name, body
43
+ name = shift :identifier
44
+ existed = check(name)
45
+ set(name)
46
+ body = _compile_class_body(true)
47
+
48
+ out = code :module, name, body
49
+ out[:existed] = existed
50
+ out
43
51
  else
44
52
  value_expect _new_token(m, :identifier)
45
53
  end
@@ -86,6 +94,14 @@ module Liquidscript
86
94
  shift :colon
87
95
  item
88
96
  end
97
+
98
+ def delegate_if_class
99
+ if top.context.class?
100
+ top.context.delegate(&Proc.new)
101
+ else
102
+ yield
103
+ end
104
+ end
89
105
  end
90
106
  end
91
107
  end
@@ -40,7 +40,7 @@ module Liquidscript
40
40
 
41
41
  def directive_allow(*args)
42
42
  args.each do |a|
43
- top.context.allow(a.value.intern)
43
+ top.context.set(a.value.intern).hidden!
44
44
  end
45
45
 
46
46
  nil
@@ -48,18 +48,56 @@ module Liquidscript
48
48
 
49
49
  def directive_cvar(*args)
50
50
  args.each do |a|
51
- top.context.set(a.value.intern, :class => true).parameter!
51
+ top.context.set(a.value.intern, :class => true).hidden!
52
52
  end
53
53
 
54
54
  nil
55
55
  end
56
56
 
57
+ def directive_todo(comment)
58
+ $stderr.puts "TODO (file: #{@scanner.file}): #{comment[1]}"
59
+ nil
60
+ end
61
+
62
+ def directive_include(file)
63
+ file_name = file[1]
64
+ path = include_paths.find do |part|
65
+ File.file?(File.join(part, file_name))
66
+ end
67
+
68
+ raise LoadError,
69
+ "cannot load such file -- #{file}" unless path
70
+
71
+ full_path = File.join(path, file_name)
72
+ f = File.open(full_path)
73
+ scanner = Scanner::Liquidscript.new(f.read, full_path)
74
+ compiler = Compiler::ICR.new(scanner)
75
+ compiler.top.parent = top
76
+ compiler.top.context.delegate!
77
+ compiler.compile
78
+ end
79
+
80
+ def directive_include_path(*paths)
81
+ include_paths.push(*paths.map(&:value))
82
+ nil
83
+ end
84
+
57
85
  def directive_strict
58
86
  top.metadata[:strict] = true
59
87
 
60
88
  nil
61
89
  end
62
90
 
91
+ private
92
+
93
+ def include_paths
94
+ @_include_paths ||= [
95
+ ".",
96
+ File.expand_path("../", @scanner.metadata[:file]),
97
+ *ENV.fetch("LIQUID_PATHS", "").split(':')
98
+ ]
99
+ end
100
+
63
101
  end
64
102
 
65
103
  def self.included(receiver)
@@ -67,8 +105,8 @@ module Liquidscript
67
105
  receiver.send :include, InstanceMethods
68
106
 
69
107
  InstanceMethods.instance_methods.each do |m|
70
- if m.to_s =~ /\A_?directive_([A-Za-z0-9]+)\z/
71
- receiver.define_directive($1, m)
108
+ if m.to_s =~ /\A_?directive_([A-Za-z0-9\_]+)\z/
109
+ receiver.define_directive($1.gsub(/\_[a-z]/) { |m| m[1].upcase }, m)
72
110
  end
73
111
  end
74
112
  end
@@ -121,20 +121,29 @@ module Liquidscript
121
121
  :command => command,
122
122
  :arguments => arguments }
123
123
 
124
- @in_directive = old
125
124
 
126
- if @in_directive
125
+ out = if old
127
126
  directive
128
127
  else
129
128
  handle_directive(directive)
130
129
  end
130
+
131
+ @in_directive = old
132
+ out
131
133
  end
132
134
 
133
135
  def _compile_lparen_method
134
136
  ident = shift :identifier
135
137
 
138
+ if peek?(:equal)
139
+ shift(:equal)
140
+ v = compile_vexpression
141
+ else
142
+ v = nil
143
+ end
144
+
136
145
  if peek?(:comma, :rparen)
137
- _compile_lparen_method_final(ident)
146
+ _compile_lparen_method_final([ident, v])
138
147
  else
139
148
  out = value_expect(ref(ident))
140
149
  shift :rparen
@@ -145,12 +154,15 @@ module Liquidscript
145
154
 
146
155
  def _compile_lparen_method_final(ident = nil)
147
156
  components = [ident].compact
157
+ _build_set
158
+ set(ident[0]) if ident
148
159
 
149
- while peek?(:comma) do
150
- shift(:comma)
151
- components << shift(:identifier)
160
+ while peek?(:comma)
161
+ components << _compile_lparen_argument
152
162
  end
153
163
 
164
+ @set.pop
165
+
154
166
  shift :rparen
155
167
  compile_function_with_parameters(components)
156
168
  end
@@ -161,6 +173,28 @@ module Liquidscript
161
173
  code :expression, out
162
174
  end
163
175
 
176
+ def _compile_lparen_argument
177
+ shift(:comma)
178
+
179
+ ident = shift(:identifier)
180
+ set(ident)
181
+
182
+ erange = action do |_|
183
+ if top[:etc]
184
+ raise CompileError,
185
+ "A drain argument has already been specified!"
186
+ end
187
+
188
+ top[:etc] = ident
189
+ :etc
190
+ end
191
+
192
+ value = expect :equal => action { |_| compile_vexpression },
193
+ :erange => erange, :_ => action { nil }
194
+
195
+ [ident, value]
196
+ end
197
+
164
198
  end
165
199
  end
166
200
  end
@@ -40,15 +40,7 @@ module Liquidscript
40
40
  shift :arrow
41
41
 
42
42
  expressions = _build_set(parameters)
43
-
44
- if peek?(:lbrace)
45
- shift :lbrace
46
- collect_compiles(:rbrace) do
47
- expressions << compile_expression
48
- end
49
- else
50
- expressions << compile_expression
51
- end
43
+ expressions.push(*_compile_block)
52
44
 
53
45
  code :function, @set.pop
54
46
  end
@@ -58,12 +50,16 @@ module Liquidscript
58
50
  def _build_set(parameters = [])
59
51
  expressions = Liquidscript::ICR::Set.new
60
52
  expressions.context = Liquidscript::ICR::Context.new
61
- expressions.context.parents << top.context
53
+ expressions.context.parent = top.context
62
54
  expressions[:arguments] = parameters
63
55
  @set << expressions
64
56
 
65
57
  parameters.each do |parameter|
66
- set(parameter).parameter!
58
+ if parameter[1] == :etc
59
+ set(parameter[0]).hidden!
60
+ else
61
+ set(parameter[0]).parameter!
62
+ end
67
63
  end
68
64
 
69
65
  expressions
@@ -54,7 +54,8 @@ module Liquidscript
54
54
 
55
55
  def compile_catch
56
56
  _compile_group(:catch, false, [:finally]) do
57
- shift :identifier
57
+ ident = shift :identifier
58
+ set(ident).hidden!
58
59
  end
59
60
  end
60
61
 
@@ -11,6 +11,13 @@ module Liquidscript
11
11
  top.context.set(literal.value.intern)
12
12
  end
13
13
 
14
+ def check(literal)
15
+ top.context.get(literal.value.intern,
16
+ :dry_run => true)
17
+ rescue InvalidReferenceError
18
+ false
19
+ end
20
+
14
21
  def code(type, *args)
15
22
  Liquidscript::ICR::Code.new type, *args
16
23
  end
@@ -31,6 +38,7 @@ module Liquidscript
31
38
  :prop => action { compile_property(v) },
32
39
  :lbrack => action { compile_access(v) },
33
40
  :range => action { |_| compile_range(v) },
41
+ :erange => action { |_| compile_erange(v) },
34
42
  [:binop,
35
43
  :minus,
36
44
  :plus] => action { compile_binop(v) },
@@ -6,13 +6,14 @@ module Liquidscript
6
6
  def compile_number
7
7
  n = shift(:number)
8
8
 
9
- if peek?(:range)
10
- shift(:range)
9
+ if peek?(:range, :erange)
10
+ range = shift(:range, :erange)
11
11
 
12
12
  if peek?(:number)
13
- code :nrange, n.value, shift(:number).value
13
+ type = :"n#{range.type}"
14
+ code(type, n.value, shift(:number).value)
14
15
  else
15
- compile_range(code(:number, n.value))
16
+ send(:"compile_#{range.type}", code(:number, n.value))
16
17
  end
17
18
  else
18
19
  code :number, n.value
@@ -27,6 +28,10 @@ module Liquidscript
27
28
  code :range, subject, compile_vexpression
28
29
  end
29
30
 
31
+ def compile_erange(subject)
32
+ code :erange, subject, compile_vexpression
33
+ end
34
+
30
35
  def compile_while
31
36
  shift :while
32
37
  shift :lparen
@@ -26,7 +26,7 @@ module Liquidscript
26
26
  class UnexpectedError < CompileError
27
27
  def initialize(expected, got)
28
28
  @expected = expected
29
- @got = got
29
+ @got = got
30
30
 
31
31
  super build_error_message
32
32
  end
@@ -34,24 +34,25 @@ module Liquidscript
34
34
  private
35
35
 
36
36
  def build_error_message
37
- str = "Expected one of %{expected}, got %{type}(%{value})"
37
+ str = "Expected one of %{expected}, got %{type}(%{value}) "
38
38
  hash = {
39
- :expected => @expected.map { |e| e.to_s.upcase }.join(', ')
39
+ :expected => @expected.map { |e| ns(e) }.join(', ')
40
40
  }
41
41
 
42
42
  if @got.is_a? Symbol
43
- hash[:type] = @got.to_s.upcase
43
+ hash[:type] = ns(@got)
44
44
  hash[:value] = ""
45
45
  else
46
- str << " (line %{line}, column %{column})"
47
- hash.merge! :type => @got.type.to_s.upcase,
48
- :line => @got.line,
49
- :column => @got.column,
46
+ hash.merge! :type => ns(@got.type),
50
47
  :value => @got.value
51
48
  end
52
49
 
53
50
  sprintf(str, hash)
54
51
  end
52
+
53
+ def ns(sym)
54
+ sym.to_s.upcase
55
+ end
55
56
  end
56
57
 
57
58
  class InvalidCodeError < GeneratorError