liquidscript 0.11.0.rc1 → 0.11.0

Sign up to get free protection for your applications and to get access to all the features.
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