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
@@ -9,7 +9,7 @@ module Liquidscript
9
9
  extend Forwardable
10
10
  include Comparable
11
11
 
12
- def_delegators :to_a, :to_s, :inspect, :[], :each, :'<=>'
12
+ def_delegators :to_a, :to_s, :inspect, :[], :each, :'<=>', :length
13
13
 
14
14
 
15
15
  def to_ary
@@ -7,33 +7,50 @@ module Liquidscript
7
7
  # etc.
8
8
  class Set < Code
9
9
 
10
- # The metadata that is applied to the set.
11
- #
12
- # @return [Hash]
13
- attr_reader :metadata
14
-
15
10
  include Representable
16
11
 
17
12
  # Initialize the set.
18
13
  def initialize
19
- @metadata = {}
20
- @code = []
21
- @contexts = []
22
- @action = :exec
14
+ @context = nil
15
+ super :exec
23
16
  end
24
17
 
25
18
  #
26
19
  def context
27
- contexts.last || @metadata.fetch(:parent).context
20
+ @context || @metadata.fetch(:parent).context
21
+ end
22
+
23
+ def parent=(parent)
24
+ @metadata[:parent] = parent
25
+ if @context
26
+ @context.parent = parent.context
27
+ end
28
+
29
+ parent
28
30
  end
29
31
 
30
- def contexts
31
- @contexts
32
+ def parent
33
+ @metadata[:parent]
32
34
  end
33
35
 
34
36
  #
35
- def context=(new_context)
36
- contexts << new_context
37
+ def context=(context)
38
+ @context = context
39
+ end
40
+
41
+ # Turns the code into an array, containing the
42
+ # action and the arguments. Note that changing
43
+ # this array will not change the code.
44
+ #
45
+ # @return [Array]
46
+ def to_a
47
+ part = [@action]
48
+ part << [:_context, context] if @context
49
+ part.concat(@metadata.to_a.select { |(k, v)|
50
+ [:arguments, :heredocs, :herenum].include?(k)
51
+ }.map { |(k, v)| [:"_#{k}", v] })
52
+ part.concat(@arguments)
53
+ part
37
54
  end
38
55
 
39
56
  # Adds a code to the code list. This is just a
@@ -43,12 +60,12 @@ module Liquidscript
43
60
  # the action.
44
61
  # @param arguments the arguments for the code.
45
62
  def add(action, *arguments)
46
- @code << Code.new(action, arguments)
63
+ self << Code.new(action, arguments)
47
64
  end
48
65
 
49
66
  def <<(*v)
50
67
  v.select { |p| p }.each do |part|
51
- @code << part
68
+ @arguments << part
52
69
  end
53
70
  end
54
71
 
@@ -62,7 +79,7 @@ module Liquidscript
62
79
  #
63
80
  # @return [Array<Symbol>]
64
81
  def locals
65
- variables - parameters
82
+ variables - parameters - hidden
66
83
  end
67
84
 
68
85
  # A list of components (or arguments) that are
@@ -75,6 +92,14 @@ module Liquidscript
75
92
  context.parameters.map(&:name)
76
93
  end
77
94
 
95
+ # A list of hidden variables in the current
96
+ # context.
97
+ #
98
+ # @return [Array<Symbol>]
99
+ def hidden
100
+ context.hidden.map(&:name)
101
+ end
102
+
78
103
  # A list of _all_ variables in the current
79
104
  # scope.
80
105
  #
@@ -83,74 +108,11 @@ module Liquidscript
83
108
  context.variables.keys - context.allowed_variables
84
109
  end
85
110
 
86
- # Turns the set into an array. Includes the
87
- # metadata information and the actual internal
88
- # array.
89
- # Note that this is _not_ the array used in
90
- # {#method_missing} - that actually operates on
91
- # the internal array.
92
- #
93
- # @return [Array]
94
- def to_a
95
- part = [@action]
96
- part << [:_context, context] if contexts.any?
97
- part.concat(@metadata.to_a.map { |(m, i)| [:"_#{m}", i] })
98
- part.concat(@code)
99
- part
100
- end
101
-
102
111
  # Outputs the codes in this set.
103
112
  #
104
113
  # @return [Array<Code>]
105
114
  def codes
106
- @code
107
- end
108
-
109
- # Access either the metadata or the codes. If
110
- # the accessor is a Symbol, it access the metadata;
111
- # if it the accessor is a Numeric, it access the
112
- # codes.
113
- #
114
- # @param key [Symbol, Numeric] the key.
115
- # @return [Object]
116
- def [](key)
117
- if key.is_a? Numeric
118
- @code[key]
119
- else
120
- @metadata[key]
121
- end
122
- end
123
-
124
- # Sets something from the metadata. Unlike the
125
- # accessor, it does not distinguish between
126
- # Numeric and Symbol keys.
127
- #
128
- # @param key [Object] the key.
129
- # @param value [Object] the value.
130
- # @return [Object]
131
- def []=(key, value)
132
- @metadata[key] = value
133
- end
134
-
135
- # Tells ruby that we respond to some methods.
136
- # Passes the method name to the internal
137
- # array, asking if it responds to it.
138
- #
139
- # @param method [Symbol] the method to check.
140
- # @param include_private [Boolean] whether or not
141
- # to include private methods.
142
- # @return [Boolean] whether or not we respond
143
- # to that method.
144
- def respond_to_missing?(method, include_private = false)
145
- @code.respond_to?(method, include_private)
146
- end
147
-
148
- # For methods that we don't respond to, send
149
- # them to the interal array.
150
- #
151
- # @return [Object]
152
- def method_missing(method, *args, &block)
153
- @code.public_send(method, *args, &block)
115
+ @arguments
154
116
  end
155
117
 
156
118
  end
@@ -50,6 +50,23 @@ module Liquidscript
50
50
  self
51
51
  end
52
52
 
53
+ # Marks this variable as hidden. This variable does not show
54
+ # up as a parameter nor a class variable.
55
+ #
56
+ # @return [self]
57
+ def hidden!
58
+ @hidden = true
59
+ self
60
+ end
61
+
62
+ # WHether or not this variable is hidden.
63
+ #
64
+ # @see {#hidden!}
65
+ # @return [Boolean]
66
+ def hidden?
67
+ @hidden
68
+ end
69
+
53
70
  # Whether or not the variable is an argument to a function.
54
71
  #
55
72
  # @see {#parameter!}
@@ -17,12 +17,22 @@ module Liquidscript
17
17
 
18
18
  attr_accessor :metadata
19
19
 
20
- def initialize(source)
20
+ def initialize(source, file = nil)
21
21
  @source = source
22
22
  @scanner = StringScanner.new(@source)
23
23
  @tokens = []
24
24
  @_scan = nil
25
25
  @metadata = {}
26
+
27
+ if !file and source.respond_to?(:to_path)
28
+ file = source.to_path
29
+ end
30
+
31
+ @metadata[:file] = file || "<none>"
32
+ end
33
+
34
+ def file
35
+ @metadata[:file]
26
36
  end
27
37
 
28
38
  def contexts
@@ -40,10 +40,11 @@ module Liquidscript
40
40
  out
41
41
  end
42
42
 
43
- def error(scanner = @scanner, context = @context)
43
+ def error(scanner = @scanner, context = @context,
44
+ file = @metadata[:file])
44
45
  raise SyntaxError, "Unexpected " +
45
46
  "#{scanner.matched}#{scanner.peek(2)}".inspect +
46
- " (line: #{line}, column: #{column})"
47
+ " (line: #{line}, column: #{column}, file: #{file})"
47
48
  end
48
49
 
49
50
  private
@@ -90,45 +90,47 @@ module Liquidscript
90
90
 
91
91
  set :identifier, %r{[A-Za-z_$]([A-Za-z0-9_$-]*[A-Za-z0-9_$])?}
92
92
 
93
- on("class") { emit :class }
94
- on("module") { emit :module }
95
- on("if") { emit :if }
96
- on("unless") { emit :unless }
97
- on("elsif") { emit :elsif }
98
- on("else") { emit :else }
99
- on("for") { emit :for }
100
- on("while") { emit :while }
101
- on("try") { emit :try }
102
- on("catch") { emit :catch }
103
- on("finally") { emit :finally }
104
- on("return") { emit :return }
105
- on(:number) { |m| emit :number, m }
106
- on(:string) { |m| emit :sstring, m }
107
- on(:keywords) { |m| emit :keyword, m }
108
- on(:actions) { |m| emit :action, m }
109
- on(:binops) { |m| emit :binop, m }
110
- on(:preunops) { |m| emit :preunop, m }
111
- on(:unops) { |m| emit :unop, m }
93
+ on("class") { emit :class }
94
+ on("module") { emit :module }
95
+ on("if") { emit :if }
96
+ on("unless") { emit :unless }
97
+ on("elsif") { emit :elsif }
98
+ on("else") { emit :else }
99
+ on("for") { emit :for }
100
+ on("while") { emit :while }
101
+ on("try") { emit :try }
102
+ on("catch") { emit :catch }
103
+ on("finally") { emit :finally }
104
+ on("return") { emit :return }
105
+ on("nil") { emit :keyword, "null" }
106
+ on(:number) { |m| emit :number, m }
107
+ on(:string) { |m| emit :sstring, m }
108
+ on(:keywords) { |m| emit :keyword, m }
109
+ on(:actions) { |m| emit :action, m }
110
+ on(:binops) { |m| emit :binop, m }
111
+ on(:preunops) { |m| emit :preunop, m }
112
+ on(:unops) { |m| emit :unop, m }
112
113
  on(%r{<<([A-Z]+)}, :heredoc)
113
114
  on(%r{<<-([A-Z]+)}, :iheredoc)
114
115
  on(%r{r/((?:.|\/)*)/([gimy]*)}, :regex)
115
116
  on(%r{"} => :istring)
116
117
  on("///" => :block_regex)
117
- on("->") { emit :arrow }
118
- on("=") { emit :equal }
119
- on("{") { emit :lbrace }
120
- on("(") { emit :lparen }
121
- on("[") { emit :lbrack }
122
- on("}") { emit :rbrace }
123
- on(")") { emit :rparen }
124
- on("]") { emit :rbrack }
125
- on(":") { emit :colon }
126
- on("..") { emit :range }
127
- on(".") { emit :prop }
128
- on(",") { emit :comma }
129
- on("-") { emit :minus }
130
- on("+") { emit :plus }
131
- on("\n") { line! }
118
+ on("->") { emit :arrow }
119
+ on("=") { emit :equal }
120
+ on("{") { emit :lbrace }
121
+ on("(") { emit :lparen }
122
+ on("[") { emit :lbrack }
123
+ on("}") { emit :rbrace }
124
+ on(")") { emit :rparen }
125
+ on("]") { emit :rbrack }
126
+ on(":") { emit :colon }
127
+ on("..") { emit :range }
128
+ on("...") { emit :erange }
129
+ on(".") { emit :prop }
130
+ on(",") { emit :comma }
131
+ on("-") { emit :minus }
132
+ on("+") { emit :plus }
133
+ on("\n") { line! }
132
134
  on(:identifier, :identifier)
133
135
  on(%r{!\[\s*([A-Za-z]+)\s*(.*?)\s*\]\n}, :directive)
134
136
 
@@ -1,5 +1,5 @@
1
1
  module Liquidscript
2
2
 
3
3
  # The current version of liquidscript.
4
- VERSION = "0.11.0.rc1".freeze
4
+ VERSION = "0.11.0".freeze
5
5
  end
@@ -30,11 +30,9 @@ compiled:
30
30
  - []
31
31
  - - :_arguments
32
32
  - []
33
- - - :test
34
33
  - - :class
35
34
  - - :identifier
36
35
  - AnotherClass
37
36
  - - :_variable
38
37
  - :SomeClass
39
38
  - []
40
- - []
@@ -6,8 +6,12 @@ data: |
6
6
  test = 0..console
7
7
  }
8
8
 
9
+ another_function = (a, b = a, c...)-> {
10
+ console.log()
11
+ }
12
+
9
13
  compiled: |
10
- var some_function;
14
+ var some_function, another_function;
11
15
  console = 2;
12
16
 
13
17
  some_function = function() {
@@ -26,3 +30,12 @@ compiled: |
26
30
  return t === undefined ? out : out.reverse();
27
31
  })(0, console);
28
32
  };
33
+
34
+ another_function = function(a, b) {
35
+ if(b == null) {
36
+ b = a;
37
+ }
38
+ c = [].slice.call(arguments, 2);
39
+
40
+ return console.log();
41
+ };
@@ -3,6 +3,7 @@ data: |
3
3
  test = [1, 2]
4
4
  range = 0x1..0x9
5
5
  range2 = 10..1
6
+ range3 = 10...1
6
7
  regex = r/^\/test/
7
8
  block = ///
8
9
  ^test # comment
@@ -10,11 +11,12 @@ data: |
10
11
  regex == block
11
12
 
12
13
  compiled: |
13
- var object, test, range, range2, regex, block;
14
+ var object, test, range, range2, range3, regex, block;
14
15
  object = { "hello": "world" };
15
16
  test = [1, 2];
16
17
  range = [0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9];
17
18
  range2 = [10, 9, 8, 7, 6, 5, 4, 3, 2, 1];
19
+ range3 = [9, 8, 7, 6, 5, 4, 3, 2, 1];
18
20
  regex = /^\/test/;
19
21
  block = /^test/;
20
22
  regex === block;
@@ -114,7 +114,7 @@ describe Compiler::ICR do
114
114
  [:_context, []], [:function,
115
115
  [:exec,
116
116
  [:_context, [:test]],
117
- [:_arguments, [[:identifier, "test"]]],
117
+ [:_arguments, [[[:identifier, "test"], nil]]],
118
118
  [:number, "2"]
119
119
  ]
120
120
  ]])
@@ -18,13 +18,13 @@ describe ICR::Context do
18
18
 
19
19
  let(:parent) do
20
20
  parent = double("parent")
21
- expect(parent).to receive(:get).once.with(:foo).and_return(:test)
21
+ expect(parent).to receive(:get).once.with(:foo, {}).and_return(:test)
22
22
  parent
23
23
  end
24
24
 
25
25
  subject do
26
26
  context = ICR::Context.new
27
- context.parents << parent
27
+ context.parent = parent
28
28
  context
29
29
  end
30
30
 
@@ -13,12 +13,12 @@ describe ICR::Set do
13
13
  context "with metadata" do
14
14
  subject do
15
15
  set = ICR::Set.new
16
- set.metadata.merge! :hello => "world"
16
+ set.metadata.merge! :arguments => "world"
17
17
  set
18
18
  end
19
19
 
20
20
  specify { expect(subject.to_a).to have(2).items }
21
- specify { expect(subject.to_a).to eq [:exec, [:_hello, "world"]] }
21
+ specify { expect(subject.to_a).to eq [:exec, [:_arguments, "world"]] }
22
22
 
23
23
  end
24
24
 
@@ -37,13 +37,13 @@ describe ICR::Set do
37
37
  context "with both" do
38
38
  subject do
39
39
  set = ICR::Set.new
40
- set.metadata.merge! :hello => "world"
40
+ set.metadata.merge! :arguments => "world"
41
41
  set << "test"
42
42
  set
43
43
  end
44
44
 
45
45
  specify { expect(subject.to_a).to have(3).items }
46
- specify { expect(subject.to_a).to eq [:exec, [:_hello, "world"], "test"] }
46
+ specify { expect(subject.to_a).to eq [:exec, [:_arguments, "world"], "test"] }
47
47
 
48
48
  end
49
49
  end