liquidscript 0.0.1

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 (72) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -0
  5. data/Gemfile +11 -0
  6. data/Guardfile +9 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +59 -0
  9. data/Rakefile +25 -0
  10. data/lib/liquidscript.rb +11 -0
  11. data/lib/liquidscript/buffer.rb +34 -0
  12. data/lib/liquidscript/compiler.rb +9 -0
  13. data/lib/liquidscript/compiler/base.rb +101 -0
  14. data/lib/liquidscript/compiler/base/action.rb +39 -0
  15. data/lib/liquidscript/compiler/base/blank.rb +24 -0
  16. data/lib/liquidscript/compiler/base/callable.rb +51 -0
  17. data/lib/liquidscript/compiler/base/helpers.rb +207 -0
  18. data/lib/liquidscript/compiler/icr.rb +40 -0
  19. data/lib/liquidscript/compiler/icr/classes.rb +59 -0
  20. data/lib/liquidscript/compiler/icr/expressions.rb +94 -0
  21. data/lib/liquidscript/compiler/icr/functions.rb +42 -0
  22. data/lib/liquidscript/compiler/icr/helpers.rb +20 -0
  23. data/lib/liquidscript/compiler/icr/literals.rb +106 -0
  24. data/lib/liquidscript/errors.rb +51 -0
  25. data/lib/liquidscript/generator.rb +11 -0
  26. data/lib/liquidscript/generator/base.rb +25 -0
  27. data/lib/liquidscript/generator/base/dsl.rb +19 -0
  28. data/lib/liquidscript/generator/base/replacements.rb +33 -0
  29. data/lib/liquidscript/generator/context.rb +7 -0
  30. data/lib/liquidscript/generator/javascript.rb +37 -0
  31. data/lib/liquidscript/generator/javascript/literals.rb +63 -0
  32. data/lib/liquidscript/generator/javascript/metas.rb +41 -0
  33. data/lib/liquidscript/generator/javascript/objects.rb +137 -0
  34. data/lib/liquidscript/icr.rb +18 -0
  35. data/lib/liquidscript/icr/code.rb +68 -0
  36. data/lib/liquidscript/icr/context.rb +94 -0
  37. data/lib/liquidscript/icr/representable.rb +39 -0
  38. data/lib/liquidscript/icr/set.rb +147 -0
  39. data/lib/liquidscript/icr/sexp.rb +41 -0
  40. data/lib/liquidscript/icr/variable.rb +68 -0
  41. data/lib/liquidscript/scanner.rb +40 -0
  42. data/lib/liquidscript/scanner/lexer.rl +106 -0
  43. data/lib/liquidscript/scanner/token.rb +37 -0
  44. data/lib/liquidscript/template.rb +16 -0
  45. data/lib/liquidscript/version.rb +5 -0
  46. data/liquidscript.gemspec +27 -0
  47. data/spec/fixtures/class.compile.yml +26 -0
  48. data/spec/fixtures/class.generate.yml +31 -0
  49. data/spec/fixtures/combination.generate.yml +33 -0
  50. data/spec/fixtures/complex.generate.yml +20 -0
  51. data/spec/fixtures/expression.generate.yml +4 -0
  52. data/spec/fixtures/function.generate.yml +11 -0
  53. data/spec/fixtures/get.generate.yml +5 -0
  54. data/spec/fixtures/literals.generate.yml +8 -0
  55. data/spec/fixtures/main.compile.yml +32 -0
  56. data/spec/fixtures/set.generate.yml +4 -0
  57. data/spec/fixtures/string.generate.yml +6 -0
  58. data/spec/lib/liquidscript/buffer_spec.rb +14 -0
  59. data/spec/lib/liquidscript/compiler/icr_spec.rb +139 -0
  60. data/spec/lib/liquidscript/generator/javascript_spec.rb +15 -0
  61. data/spec/lib/liquidscript/icr/code_spec.rb +0 -0
  62. data/spec/lib/liquidscript/icr/context_spec.rb +36 -0
  63. data/spec/lib/liquidscript/icr/set_spec.rb +59 -0
  64. data/spec/lib/liquidscript/scanner/lexer_spec.rb +58 -0
  65. data/spec/lib/liquidscript/scanner/token_spec.rb +0 -0
  66. data/spec/lib/liquidscript/scanner_spec.rb +21 -0
  67. data/spec/spec_helper.rb +30 -0
  68. data/spec/support/helpers/lexer_helper.rb +5 -0
  69. data/spec/support/matchers/be_token.rb +9 -0
  70. data/spec/support/matchers/compile.rb +41 -0
  71. data/spec/support/matchers/generate.rb +46 -0
  72. metadata +210 -0
@@ -0,0 +1,106 @@
1
+ module Liquidscript
2
+ module Compiler
3
+ class ICR < Base
4
+ module Literals
5
+
6
+ def compile_number
7
+ code :number, pop.value
8
+ end
9
+
10
+ def compile_identifier(identifier)
11
+ default = action do
12
+ code :get, ref(identifier)
13
+ end
14
+
15
+ expect :equal => action { compile_assignment(identifier) },
16
+ :prop => action { compile_property(identifier) },
17
+ :lparen => action { compile_call(identifier) },
18
+ :_ => default
19
+ end
20
+
21
+ def compile_dstring
22
+ code :dstring, pop.value[1..-2]
23
+ end
24
+
25
+ def compile_sstring
26
+ code :sstring, pop.value[1..-1]
27
+ end
28
+
29
+ def compile_keyword
30
+ code :keyword, shift(:keyword), compile_expression
31
+ end
32
+
33
+ def compile_object
34
+ shift :lbrack
35
+
36
+ objects = []
37
+ compile_object = action do
38
+ objects << [compile_object_key, compile_expression]
39
+ end
40
+
41
+ loop do
42
+ expect :rbrack => action.end_loop,
43
+ :comma => action.shift,
44
+ [:identifier, :dstring] => compile_object
45
+ end
46
+
47
+ code :object, objects
48
+ end
49
+
50
+ def compile_array
51
+ shift :lbrace
52
+
53
+ parts = []
54
+ compile_part = action { parts << compile_expression }
55
+
56
+ loop do
57
+ expect :rbrace => action.end_loop,
58
+ :comma => action.shift,
59
+ :_ => compile_part
60
+ end
61
+
62
+ code :array, parts
63
+ end
64
+
65
+ def compile_object_key
66
+ key = shift :identifier, :dstring
67
+ shift :colon
68
+
69
+ key
70
+ end
71
+
72
+ def compile_function
73
+ compile_function_with_parameters([])
74
+ end
75
+
76
+ def compile_function_with_parameters(parameter)
77
+ shift :arrow
78
+ shift :lbrack
79
+
80
+ expressions = Liquidscript::ICR::Set.new
81
+ expressions.context = Liquidscript::ICR::Context.new
82
+ expressions.context.parent = top.context
83
+ expressions[:arguments] = parameter
84
+ @set << expressions
85
+
86
+ parameter.each do |parameter|
87
+ set(parameter).parameter!
88
+ end
89
+
90
+
91
+ expression = action do
92
+ expressions << compile_expression
93
+ end
94
+
95
+ loop do
96
+ expect :rbrack => action.end_loop,
97
+ :_ => expression
98
+ end
99
+
100
+ code :function, @set.pop
101
+ end
102
+
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,51 @@
1
+ module Liquidscript
2
+
3
+ class Error < ::StandardError; end
4
+
5
+ class SyntaxError < Error; end
6
+ class CompileError < Error; end
7
+ class GeneratorError < Error; end
8
+
9
+ class UnexpectedEndError < CompileError; end
10
+ class InvalidReferenceError < CompileError
11
+
12
+ def initialize(name)
13
+ super "No variable named #{name}"
14
+ end
15
+ end
16
+ class UnexpectedError < CompileError
17
+ def initialize(expected, got)
18
+ @expected = expected
19
+ @got = got
20
+
21
+ super build_error_message
22
+ end
23
+
24
+ private
25
+
26
+ def build_error_message
27
+ str = "Expected one of %{expected}, got %{type}"
28
+ hash = {
29
+ :expected => @expected.map { |e| e.to_s.upcase }.join(', ')
30
+ }
31
+
32
+ if @got.is_a? Symbol
33
+ hash[:type] = @got.to_s.upcase
34
+ else
35
+ str << " (line %{line}, column %{column})"
36
+ hash.merge! :type => @got.type.to_s.upcase,
37
+ :line => @got.line,
38
+ :column => @got.column
39
+ end
40
+
41
+ sprintf(str, hash)
42
+ end
43
+ end
44
+
45
+ class InvalidCodeError < GeneratorError
46
+ def initialize(code)
47
+ super "Could not generate code for `#{code.to_s.upcase}`"
48
+ end
49
+ end
50
+
51
+ end
@@ -0,0 +1,11 @@
1
+ require "hashie"
2
+ require "liquidscript/generator/base"
3
+ require "liquidscript/generator/context"
4
+ require "liquidscript/generator/javascript"
5
+
6
+ module Liquidscript
7
+
8
+ module Generator
9
+
10
+ end
11
+ end
@@ -0,0 +1,25 @@
1
+ require "liquidscript/generator/base/dsl"
2
+ require "liquidscript/generator/base/replacements"
3
+
4
+ module Liquidscript
5
+ module Generator
6
+
7
+ class Base
8
+
9
+ include Replacements
10
+
11
+ def initialize(top)
12
+ @top = top
13
+ end
14
+
15
+ def generate
16
+ replace(@top, {}).to_s
17
+ end
18
+
19
+ def buffer
20
+ Buffer.new
21
+ end
22
+
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,19 @@
1
+ module Liquidscript
2
+ module Generator
3
+ class Base
4
+ module DSL
5
+ module ClassMethods
6
+
7
+ def to_generate(code, &block)
8
+ define_method(:"generate_#{code}", &block)
9
+ protected :"generate_#{code}"
10
+ end
11
+ end
12
+
13
+ def self.included(base)
14
+ base.extend ClassMethods
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,33 @@
1
+ module Liquidscript
2
+ module Generator
3
+ class Base
4
+ module Replacements
5
+
6
+ # Replace a code with a string. This uses the replacement
7
+ # definitions that are a part of the class.
8
+ #
9
+ # @param code [ICR::Code, #type]
10
+ # @param context [Hash]
11
+ def replace(code, context = {})
12
+ send(:"generate_#{code.type}",
13
+ code)
14
+
15
+ rescue NoMethodError => e
16
+ if e.name == :"_generate_code_#{code.type}"
17
+ raise InvalidCodeError.new(code.type)
18
+ else
19
+ raise
20
+ end
21
+ end
22
+
23
+ # Access to the replacements method on the class.
24
+ #
25
+ # @see [ClassMethods#replacements]
26
+ # @return [Hash]
27
+ def replacements
28
+ self.class.replacements
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,7 @@
1
+ module Liquidscript
2
+ module Generator
3
+ class Context < Hashie::Mash
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,37 @@
1
+ require "liquidscript/generator/javascript/literals"
2
+ require "liquidscript/generator/javascript/metas"
3
+ require "liquidscript/generator/javascript/objects"
4
+
5
+ module Liquidscript
6
+ module Generator
7
+
8
+ # A list of all of the possible codes for javascript:
9
+ #
10
+ # - `:set` ✔
11
+ # - `:get` ✔
12
+ # - `:exec` ✔
13
+ # - `:expression` ✔
14
+ # - `:class` ✔
15
+ # - `:module` ✔
16
+ # - `:property` ✔
17
+ # - `:call` ✔
18
+ # - `:number` ✔
19
+ # - `:sstring` ✔
20
+ # - `:dstring` ✔
21
+ # - `:object` ✔
22
+ # - `:array` ✔
23
+ # - `:function` ✔
24
+ #
25
+ # Each one of these must have a generate function.
26
+ class Javascript < Base
27
+ include Literals
28
+ include Metas
29
+ include Objects
30
+
31
+ def initialize(top)
32
+ @modules = []
33
+ super
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,63 @@
1
+ module Liquidscript
2
+ module Generator
3
+ class Javascript < Base
4
+ module Literals
5
+
6
+ def generate_number(code)
7
+
8
+ "#{code.first}"
9
+ end
10
+
11
+ def generate_dstring(code)
12
+
13
+ "\"#{code.first.gsub(/"/, '\\"')}\""
14
+ end
15
+
16
+ def generate_sstring(code)
17
+
18
+ "'#{code.first.gsub(/'/, "\\'")}'"
19
+ end
20
+
21
+ def generate_keyword(code)
22
+ " #{code[1].value} #{replace(code[2])}"
23
+ end
24
+
25
+ def generate_object(code)
26
+
27
+ object = buffer
28
+ object.set_join! ', '
29
+
30
+ code[1].inject(object) do |buf, part|
31
+ buf << "\"#{part[0].value}\": #{replace(part[1])}"
32
+ end
33
+
34
+ "{#{object}}"
35
+ end
36
+
37
+ def generate_array(code)
38
+
39
+ array = buffer
40
+ array.set_join! ', '
41
+
42
+ code[1].inject(array) do |a, p|
43
+ a << replace(p)
44
+ end
45
+
46
+ "[#{array}]"
47
+ end
48
+
49
+ def generate_function(code)
50
+
51
+ function = buffer
52
+
53
+ function <<
54
+ "function(" <<
55
+ code[1].parameters.join(',') <<
56
+ ') {' <<
57
+ replace(code[1]) <<
58
+ '}'
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,41 @@
1
+ module Liquidscript
2
+ module Generator
3
+ class Javascript
4
+ module Metas
5
+
6
+ def generate_exec(code)
7
+
8
+ exec = buffer
9
+ exec << _exec_context(code)
10
+ code.codes.inject(exec) do |m, c|
11
+ m << replace(c)
12
+ m
13
+ end
14
+ end
15
+
16
+ def generate_set(code)
17
+ case code[1].type
18
+ when :variable
19
+ "#{code[1].name} = #{replace code[2]};"
20
+ when :property
21
+ "#{replace code[1]} = #{replace code[2]};"
22
+ end
23
+ end
24
+
25
+ def generate_get(code)
26
+
27
+ "#{code[1].name}"
28
+ end
29
+
30
+ protected
31
+
32
+ def _exec_context(code)
33
+
34
+ unless code.locals.empty?
35
+ "var #{code.locals.join(',')}; "
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,137 @@
1
+ module Liquidscript
2
+ module Generator
3
+ class Javascript
4
+ module Objects
5
+
6
+ def generate_expression(code)
7
+ "(#{replace(code[1].first)})"
8
+ end
9
+
10
+ def generate_call(code)
11
+ call = buffer
12
+ args = buffer
13
+ args.set_join! ','
14
+
15
+ case code[1].type
16
+ when :identifier
17
+ call << "#{code[1].value}"
18
+ else
19
+ call << "#{replace(code[1])}"
20
+ end
21
+
22
+ code[2..-1].inject(args) do |b, arg|
23
+ b << replace(arg)
24
+ end
25
+
26
+ call << "(" << args << ")"
27
+ end
28
+
29
+ def generate_property(code)
30
+ prop = buffer
31
+
32
+ case code[1].type
33
+ when :identifier
34
+ prop << code[1].value
35
+ when :variable
36
+ prop << code[1].name
37
+ else
38
+ prop << replace(code[1])
39
+ end
40
+
41
+ prop << "." << code[2].value
42
+ end
43
+
44
+ def generate_class(code)
45
+ body = buffer
46
+ class_name = code[1].value
47
+
48
+ in_module(class_name) do |last_module|
49
+ body <<
50
+ "#{class_name} = function #{class_name}(){" <<
51
+ "if(this.initialize) {" <<
52
+ "this.initialize.apply(this, arguments);" <<
53
+ "}};"
54
+
55
+ code[2].each do |(k, v)|
56
+ case k.type
57
+ when :identifier
58
+ body <<
59
+ "#{class_name}.prototype.#{k.value} =" <<
60
+ replace(v) << ";"
61
+ when :dstring
62
+ body <<
63
+ "#{class_name}.prototype[#{k.value}] =" <<
64
+ replace(v) << ";"
65
+ when :prop
66
+ if k[1].name != :this
67
+ raise InvalidCodeError.new(v[1].name)
68
+ end
69
+
70
+ body <<
71
+ "#{class_name}.#{k[2].value} = " <<
72
+ replace(v) << ";"
73
+ end
74
+ end
75
+
76
+ if last_module
77
+ body <<
78
+ "#{last_module}.#{class_name} = " <<
79
+ "#{class_name};"
80
+ end
81
+
82
+ end
83
+
84
+ body
85
+ end
86
+
87
+ def generate_module(code)
88
+ body = buffer
89
+ module_name = code[1].value
90
+
91
+ in_module(module_name) do |last_module|
92
+ body << "#{module_name} = {};"
93
+
94
+ code[2].each do |part|
95
+ k = part[0]
96
+ v = part[1]
97
+ case k
98
+ when :identifier
99
+ body <<
100
+ "#{module_name}.#{k.value} = " <<
101
+ replace(v) << ";"
102
+ when :dstring
103
+ body <<
104
+ "#{module_name}[#{k.value}] = " <<
105
+ replace(v) << ";"
106
+ when :class
107
+ body << generate_class(part)
108
+ end
109
+ end
110
+
111
+ if last_module
112
+ body <<
113
+ "#{last_module}.#{module_name} = " <<
114
+ "#{module_name};"
115
+ end
116
+ end
117
+
118
+ body
119
+ end
120
+
121
+ protected
122
+
123
+ def current_module
124
+ @modules.last
125
+ end
126
+
127
+ def in_module(module_name)
128
+ @modules << module_name
129
+ out = yield @modules[-2]
130
+ @modules.pop
131
+ out
132
+ end
133
+
134
+ end
135
+ end
136
+ end
137
+ end