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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/Gemfile +11 -0
- data/Guardfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +59 -0
- data/Rakefile +25 -0
- data/lib/liquidscript.rb +11 -0
- data/lib/liquidscript/buffer.rb +34 -0
- data/lib/liquidscript/compiler.rb +9 -0
- data/lib/liquidscript/compiler/base.rb +101 -0
- data/lib/liquidscript/compiler/base/action.rb +39 -0
- data/lib/liquidscript/compiler/base/blank.rb +24 -0
- data/lib/liquidscript/compiler/base/callable.rb +51 -0
- data/lib/liquidscript/compiler/base/helpers.rb +207 -0
- data/lib/liquidscript/compiler/icr.rb +40 -0
- data/lib/liquidscript/compiler/icr/classes.rb +59 -0
- data/lib/liquidscript/compiler/icr/expressions.rb +94 -0
- data/lib/liquidscript/compiler/icr/functions.rb +42 -0
- data/lib/liquidscript/compiler/icr/helpers.rb +20 -0
- data/lib/liquidscript/compiler/icr/literals.rb +106 -0
- data/lib/liquidscript/errors.rb +51 -0
- data/lib/liquidscript/generator.rb +11 -0
- data/lib/liquidscript/generator/base.rb +25 -0
- data/lib/liquidscript/generator/base/dsl.rb +19 -0
- data/lib/liquidscript/generator/base/replacements.rb +33 -0
- data/lib/liquidscript/generator/context.rb +7 -0
- data/lib/liquidscript/generator/javascript.rb +37 -0
- data/lib/liquidscript/generator/javascript/literals.rb +63 -0
- data/lib/liquidscript/generator/javascript/metas.rb +41 -0
- data/lib/liquidscript/generator/javascript/objects.rb +137 -0
- data/lib/liquidscript/icr.rb +18 -0
- data/lib/liquidscript/icr/code.rb +68 -0
- data/lib/liquidscript/icr/context.rb +94 -0
- data/lib/liquidscript/icr/representable.rb +39 -0
- data/lib/liquidscript/icr/set.rb +147 -0
- data/lib/liquidscript/icr/sexp.rb +41 -0
- data/lib/liquidscript/icr/variable.rb +68 -0
- data/lib/liquidscript/scanner.rb +40 -0
- data/lib/liquidscript/scanner/lexer.rl +106 -0
- data/lib/liquidscript/scanner/token.rb +37 -0
- data/lib/liquidscript/template.rb +16 -0
- data/lib/liquidscript/version.rb +5 -0
- data/liquidscript.gemspec +27 -0
- data/spec/fixtures/class.compile.yml +26 -0
- data/spec/fixtures/class.generate.yml +31 -0
- data/spec/fixtures/combination.generate.yml +33 -0
- data/spec/fixtures/complex.generate.yml +20 -0
- data/spec/fixtures/expression.generate.yml +4 -0
- data/spec/fixtures/function.generate.yml +11 -0
- data/spec/fixtures/get.generate.yml +5 -0
- data/spec/fixtures/literals.generate.yml +8 -0
- data/spec/fixtures/main.compile.yml +32 -0
- data/spec/fixtures/set.generate.yml +4 -0
- data/spec/fixtures/string.generate.yml +6 -0
- data/spec/lib/liquidscript/buffer_spec.rb +14 -0
- data/spec/lib/liquidscript/compiler/icr_spec.rb +139 -0
- data/spec/lib/liquidscript/generator/javascript_spec.rb +15 -0
- data/spec/lib/liquidscript/icr/code_spec.rb +0 -0
- data/spec/lib/liquidscript/icr/context_spec.rb +36 -0
- data/spec/lib/liquidscript/icr/set_spec.rb +59 -0
- data/spec/lib/liquidscript/scanner/lexer_spec.rb +58 -0
- data/spec/lib/liquidscript/scanner/token_spec.rb +0 -0
- data/spec/lib/liquidscript/scanner_spec.rb +21 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/support/helpers/lexer_helper.rb +5 -0
- data/spec/support/matchers/be_token.rb +9 -0
- data/spec/support/matchers/compile.rb +41 -0
- data/spec/support/matchers/generate.rb +46 -0
- metadata +210 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d8099fbffde0b4c86f743c1eeb2f7945876bda79
|
4
|
+
data.tar.gz: 61440eea14db6d81cff6245c03916e58092f310e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d58710b0697834bfa1501061adc3d9d0492206d71c24d8886a769e451dadff2e41bdcc527d8629fb4522ff92cb2a9e423ee96eb1559d7fc5370c04a3bbfd3262
|
7
|
+
data.tar.gz: 9552101c9846bde2f34eebedcf1e4dcd1fa4da268c3e563331e2872ad0d9d5d21ea82296c79044265cdc0f01023fb3333542c99ed52d312cb30e9b40fed3afa9
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Jeremy Rodi
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# Liquidscript
|
2
|
+
|
3
|
+
[](https://travis-ci.org/redjazz96/liquidscript) [](https://coveralls.io/r/redjazz96/liquidscript?branch=master) [](https://codeclimate.com/github/redjazz96/liquidscript)
|
4
|
+
|
5
|
+
A javascript-based language that compiles to javascript.
|
6
|
+
|
7
|
+
## Installation
|
8
|
+
|
9
|
+
Add this line to your application's Gemfile:
|
10
|
+
|
11
|
+
gem 'liquidscript'
|
12
|
+
|
13
|
+
And then execute:
|
14
|
+
|
15
|
+
$ bundle
|
16
|
+
|
17
|
+
Or install it yourself as:
|
18
|
+
|
19
|
+
$ gem install liquidscript
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
To use liquidscript:
|
24
|
+
|
25
|
+
```
|
26
|
+
TODO: usage example
|
27
|
+
```
|
28
|
+
|
29
|
+
The language of liquidscript:
|
30
|
+
|
31
|
+
```coffeescript
|
32
|
+
# This is an object.
|
33
|
+
|
34
|
+
{
|
35
|
+
test: "hello",
|
36
|
+
|
37
|
+
# Note here that a single-quoted string does not have an ending
|
38
|
+
# delimiter. This is on purpose.
|
39
|
+
foo: 'bar # ' # syntax highlighting fix
|
40
|
+
}
|
41
|
+
```
|
42
|
+
|
43
|
+
```coffeescript
|
44
|
+
# This is a function
|
45
|
+
|
46
|
+
func = ()-> {
|
47
|
+
console.log("hello world")
|
48
|
+
}
|
49
|
+
|
50
|
+
func()
|
51
|
+
```
|
52
|
+
|
53
|
+
## Contributing
|
54
|
+
|
55
|
+
1. Fork it ( http://github.com/redjazz96/liquidscript/fork )
|
56
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
57
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
58
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
59
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new('spec')
|
6
|
+
|
7
|
+
namespace :ls do
|
8
|
+
rule '.rb' => ['.rl'] do |t|
|
9
|
+
sh "ragel -R #{t.source}"
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Builds the ragel parser."
|
13
|
+
task :ragel => ["lib/liquidscript/scanner/lexer.rb"]
|
14
|
+
|
15
|
+
desc "Opens up a pry session."
|
16
|
+
task :pry => [:ragel] do
|
17
|
+
require "pry"
|
18
|
+
require File.expand_path("../lib/liquidscript", __FILE__)
|
19
|
+
Pry.start
|
20
|
+
end
|
21
|
+
|
22
|
+
task :clean do
|
23
|
+
File.unlink("lib/liquidscript/scanner/lexer.rb")
|
24
|
+
end
|
25
|
+
end
|
data/lib/liquidscript.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require "forwardable"
|
2
|
+
require "liquidscript/icr"
|
3
|
+
require "liquidscript/errors"
|
4
|
+
require "liquidscript/version"
|
5
|
+
require "liquidscript/scanner"
|
6
|
+
require "liquidscript/compiler"
|
7
|
+
require "liquidscript/generator"
|
8
|
+
|
9
|
+
module Liquidscript
|
10
|
+
# Your code goes here...
|
11
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module Liquidscript
|
2
|
+
class Buffer
|
3
|
+
|
4
|
+
def initialize(*args)
|
5
|
+
@_buf = args
|
6
|
+
@_cache = nil
|
7
|
+
@_join = ''
|
8
|
+
end
|
9
|
+
|
10
|
+
def append(*a)
|
11
|
+
@_cache = nil
|
12
|
+
@_buf.push(*a)
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def set_join!(to)
|
17
|
+
@_join = to
|
18
|
+
end
|
19
|
+
|
20
|
+
alias_method :<<, :append
|
21
|
+
alias_method :push, :append
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
@_cache ||= begin
|
25
|
+
@_buf.join @_join
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def inspect
|
30
|
+
to_s.inspect
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,101 @@
|
|
1
|
+
require "liquidscript/compiler/base/blank"
|
2
|
+
require "liquidscript/compiler/base/action"
|
3
|
+
require "liquidscript/compiler/base/helpers"
|
4
|
+
require "liquidscript/compiler/base/callable"
|
5
|
+
|
6
|
+
module Liquidscript
|
7
|
+
module Compiler
|
8
|
+
class Base
|
9
|
+
|
10
|
+
include Helpers
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
# Initializes the compiler.
|
14
|
+
#
|
15
|
+
# @param scanner [Scanner, #each] the scanner. Used to
|
16
|
+
# manage the tokens. This could be stubbed out, if
|
17
|
+
# the #each function returns an Enumerator, which yields
|
18
|
+
# {Scanner::Token}s.
|
19
|
+
def initialize(scanner)
|
20
|
+
@scanner = scanner.each
|
21
|
+
@action = Action.new
|
22
|
+
reset!
|
23
|
+
end
|
24
|
+
|
25
|
+
# Returns the top set. If the variable @top isn't set by the
|
26
|
+
# inheriting class, then it defaults to the value of an array.
|
27
|
+
#
|
28
|
+
# @return [Array, #push]
|
29
|
+
def top
|
30
|
+
@top ||= []
|
31
|
+
end
|
32
|
+
|
33
|
+
# Begins the compiliation. Continues until the iterator raises
|
34
|
+
# a `StopIteration` error, and then returns the top set with
|
35
|
+
# {#top}.
|
36
|
+
#
|
37
|
+
# @raise [CompileError] if there's an error compiling.
|
38
|
+
# @raise [UnexpectedEndError] if the top {Array} isn't the topmost
|
39
|
+
# set.
|
40
|
+
# @return [Array] the topmost set.
|
41
|
+
def compile
|
42
|
+
# We're using this cool property of Base::Blank such that it
|
43
|
+
# will return a nil to any method call.
|
44
|
+
while !peek.is_a?(Blank) do
|
45
|
+
top.push compile_start
|
46
|
+
end
|
47
|
+
|
48
|
+
top
|
49
|
+
end
|
50
|
+
|
51
|
+
# Checks to see if the given input compiles.
|
52
|
+
#
|
53
|
+
# @see [#compile]
|
54
|
+
# @return [Boolean] if it compiles.
|
55
|
+
def compile?
|
56
|
+
compile
|
57
|
+
true
|
58
|
+
rescue CompileError
|
59
|
+
false
|
60
|
+
ensure
|
61
|
+
reset!
|
62
|
+
end
|
63
|
+
|
64
|
+
def scanner_nil
|
65
|
+
@_blank ||= Blank.new
|
66
|
+
end
|
67
|
+
|
68
|
+
# Pops the next argument off of the scanner. If the call
|
69
|
+
# raises a {StopIteration} error, it returns the value of
|
70
|
+
# {#scanner_nil} instead.
|
71
|
+
#
|
72
|
+
# @return [#type?, Blank]
|
73
|
+
def pop
|
74
|
+
@scanner.next
|
75
|
+
rescue StopIteration
|
76
|
+
scanner_nil
|
77
|
+
end
|
78
|
+
|
79
|
+
# Peeks at the next argument on the scanner. If the call
|
80
|
+
# raises a {StopIteration} error, it returns the value of
|
81
|
+
# {#scanner_nil} instead.
|
82
|
+
#
|
83
|
+
# @return [#type, Blank]
|
84
|
+
def peek
|
85
|
+
@scanner.peek
|
86
|
+
rescue StopIteration
|
87
|
+
scanner_nil
|
88
|
+
end
|
89
|
+
|
90
|
+
# Resets the state of the compiler.
|
91
|
+
#
|
92
|
+
# @return [void]
|
93
|
+
def reset!
|
94
|
+
@scanner.rewind
|
95
|
+
end
|
96
|
+
|
97
|
+
alias_method :rewind, :reset!
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Liquidscript
|
2
|
+
module Compiler
|
3
|
+
class Base
|
4
|
+
|
5
|
+
# Used to construct blocks that are used with {#expect}. It's
|
6
|
+
# primarily syntaxic sugar, and DRYness.
|
7
|
+
class Action
|
8
|
+
|
9
|
+
# Returns a block that returns true, and takes no arguments.
|
10
|
+
# This is for {#expect}, when you don't want the token to be
|
11
|
+
# shifted, and you don't want the loop to end (if applicable).
|
12
|
+
#
|
13
|
+
# @return [Proc]
|
14
|
+
def nothing
|
15
|
+
@_nothing ||= proc { true }
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns a block that returns the first argument given to it.
|
19
|
+
# This is for {#expect}, when you want to shift the token, and
|
20
|
+
# you don't want the loop to end (if applicable). Also used
|
21
|
+
# internally for {Helpers#shift}.
|
22
|
+
#
|
23
|
+
# @return [Proc]
|
24
|
+
def shift
|
25
|
+
@_shift ||= proc { |_| _ }
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns a block that returns false, and takes one argument.
|
29
|
+
# This is for {#expect}, when you want to shift the token, and
|
30
|
+
# you want the loop to end (if applicable).
|
31
|
+
#
|
32
|
+
# @return [Proc]
|
33
|
+
def end_loop
|
34
|
+
@_end_loop ||= proc { |_| false }
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Liquidscript
|
2
|
+
module Compiler
|
3
|
+
class Base
|
4
|
+
|
5
|
+
# Responds to all methods with `nil`.
|
6
|
+
class Blank
|
7
|
+
|
8
|
+
# Respond to all methods, with `nil`.
|
9
|
+
#
|
10
|
+
# @return [nil]
|
11
|
+
def method_missing(*_, &block)
|
12
|
+
nil
|
13
|
+
end
|
14
|
+
|
15
|
+
# Tells Ruby that we respond to all methods.
|
16
|
+
#
|
17
|
+
# @return [true]
|
18
|
+
def respond_to_missing?(_, __)
|
19
|
+
true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Liquidscript
|
2
|
+
module Compiler
|
3
|
+
class Base
|
4
|
+
class Callable
|
5
|
+
|
6
|
+
# Initialize the callable.
|
7
|
+
#
|
8
|
+
# @param bind [Object] the object that holds the method (if
|
9
|
+
# this represents a method call).
|
10
|
+
# @param block [Symbol, Block] if it's a Symbol, it represents
|
11
|
+
# a method on bind; otherwise, it's a pure block.
|
12
|
+
def initialize(bind, block)
|
13
|
+
@bind = bind
|
14
|
+
@block = if block.is_a? Symbol
|
15
|
+
:"compile_#{block}"
|
16
|
+
else
|
17
|
+
block
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Calls the thing that this represents. If this represents a
|
22
|
+
# method call, it calls the method with the given arguments;
|
23
|
+
# otherwise, it calls {#call} on the block.
|
24
|
+
#
|
25
|
+
# @param args [Object] passed to the call.
|
26
|
+
# @return [Object] the result of the call.
|
27
|
+
def call(*args)
|
28
|
+
if @block.is_a? Symbol
|
29
|
+
@bind.public_send(@block, *args)
|
30
|
+
elsif @block.respond_to?(:call)
|
31
|
+
@block.call(*args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# How many arguments the call can take. If this represents a
|
36
|
+
# block that has tricks enabled, then this isn't an issue; if
|
37
|
+
# it's a method call, however, it becomes important.
|
38
|
+
#
|
39
|
+
# @return [Numeric] the number of arguments it can take.
|
40
|
+
def arity
|
41
|
+
if @block.is_a? Symbol
|
42
|
+
@bind.method(@block).arity
|
43
|
+
else
|
44
|
+
@block.arity
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|