hotcell 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -1
- data/.rspec +1 -0
- data/.rvmrc +1 -1
- data/.travis.yml +7 -0
- data/Gemfile +4 -1
- data/README.md +361 -2
- data/Rakefile +28 -6
- data/ext/lexerc/extconf.rb +3 -0
- data/ext/lexerc/lexerc.c +618 -0
- data/ext/lexerc/lexerc.h +20 -0
- data/ext/lexerc/lexerc.rl +167 -0
- data/hotcell.gemspec +8 -7
- data/lib/hotcell/commands/case.rb +59 -0
- data/lib/hotcell/commands/cycle.rb +38 -0
- data/lib/hotcell/commands/for.rb +70 -0
- data/lib/hotcell/commands/if.rb +51 -0
- data/lib/hotcell/commands/include.rb +21 -0
- data/lib/hotcell/commands/scope.rb +13 -0
- data/lib/hotcell/commands/unless.rb +23 -0
- data/lib/hotcell/commands.rb +13 -0
- data/lib/hotcell/config.rb +33 -6
- data/lib/hotcell/context.rb +40 -7
- data/lib/hotcell/errors.rb +37 -28
- data/lib/hotcell/extensions.rb +4 -0
- data/lib/hotcell/lexer.rb +19 -635
- data/lib/hotcell/lexerr.rb +572 -0
- data/lib/hotcell/lexerr.rl +137 -0
- data/lib/hotcell/node/assigner.rb +1 -5
- data/lib/hotcell/node/block.rb +17 -40
- data/lib/hotcell/node/command.rb +29 -22
- data/lib/hotcell/node/hasher.rb +1 -1
- data/lib/hotcell/node/summoner.rb +2 -6
- data/lib/hotcell/node/tag.rb +10 -7
- data/lib/hotcell/node.rb +12 -1
- data/lib/hotcell/parser.rb +474 -408
- data/lib/hotcell/parser.y +175 -117
- data/lib/hotcell/resolver.rb +44 -0
- data/lib/hotcell/source.rb +35 -0
- data/lib/hotcell/template.rb +15 -6
- data/lib/hotcell/version.rb +1 -1
- data/lib/hotcell.rb +15 -10
- data/spec/data/templates/simple.hc +1 -0
- data/spec/lib/hotcell/commands/case_spec.rb +39 -0
- data/spec/lib/hotcell/commands/cycle_spec.rb +29 -0
- data/spec/lib/hotcell/commands/for_spec.rb +65 -0
- data/spec/lib/hotcell/commands/if_spec.rb +35 -0
- data/spec/lib/hotcell/commands/include_spec.rb +39 -0
- data/spec/lib/hotcell/commands/scope_spec.rb +16 -0
- data/spec/lib/hotcell/commands/unless_spec.rb +23 -0
- data/spec/lib/hotcell/config_spec.rb +35 -10
- data/spec/lib/hotcell/context_spec.rb +58 -18
- data/spec/lib/hotcell/lexer_spec.rb +37 -28
- data/spec/lib/hotcell/node/block_spec.rb +28 -56
- data/spec/lib/hotcell/node/command_spec.rb +7 -31
- data/spec/lib/hotcell/node/tag_spec.rb +16 -0
- data/spec/lib/hotcell/parser_spec.rb +152 -123
- data/spec/lib/hotcell/resolver_spec.rb +28 -0
- data/spec/lib/hotcell/source_spec.rb +41 -0
- data/spec/lib/hotcell/template_spec.rb +47 -4
- data/spec/lib/hotcell_spec.rb +2 -1
- data/spec/spec_helper.rb +6 -2
- metadata +54 -24
- data/lib/hotcell/.DS_Store +0 -0
- data/lib/hotcell/lexer.rl +0 -299
- data/misc/rage.rl +0 -1999
- data/misc/unicode2ragel.rb +0 -305
data/lib/hotcell/node/block.rb
CHANGED
@@ -1,22 +1,27 @@
|
|
1
1
|
module Hotcell
|
2
2
|
class Block < Hotcell::Command
|
3
|
-
class_attribute :
|
4
|
-
self.
|
3
|
+
class_attribute :subcommands, instance_writter: false, instance_reader: false
|
4
|
+
self.subcommands = {}
|
5
5
|
|
6
|
-
def self.
|
7
|
-
if
|
8
|
-
self.
|
6
|
+
def self.subcommand name_or_hash, &block
|
7
|
+
if name_or_hash.is_a? Hash
|
8
|
+
self.subcommands = subcommands.merge(name_or_hash.stringify_keys)
|
9
9
|
else
|
10
|
-
|
10
|
+
subcommand name_or_hash => Class.new(Hotcell::Command, &block)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
def validate!
|
15
|
+
subcommands.each do |subcommand|
|
16
|
+
raise Hotcell::BlockError.new(
|
17
|
+
"Unexpected subcommand `#{subcommand.name}` for `#{name}` command",
|
18
|
+
*subcommand.position_info
|
19
|
+
) unless self.class.subcommands.key?(subcommand.name)
|
19
20
|
end
|
21
|
+
|
22
|
+
super
|
23
|
+
|
24
|
+
subcommands.each(&:validate!)
|
20
25
|
end
|
21
26
|
|
22
27
|
def subnodes
|
@@ -24,35 +29,7 @@ module Hotcell
|
|
24
29
|
end
|
25
30
|
|
26
31
|
def subcommands
|
27
|
-
subnodes.select { |node| node.is_a?(
|
28
|
-
end
|
29
|
-
|
30
|
-
def validate!
|
31
|
-
valid = subcommands.map { |subcommand| subcommand[:name] } - _subcommands == []
|
32
|
-
raise Hotcell::Errors::BlockError.new 'Invalid block syntax' unless valid
|
33
|
-
end
|
34
|
-
|
35
|
-
def process context, subnodes, *args
|
36
|
-
end
|
37
|
-
|
38
|
-
def render context
|
39
|
-
context.safe do
|
40
|
-
subnodes = render_subnodes(context)
|
41
|
-
values = render_nodes(context, children)
|
42
|
-
concat context, process(context, subnodes, *values)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def render_subnodes context
|
47
|
-
subnodes.map do |node|
|
48
|
-
if node.is_a?(Hash)
|
49
|
-
subcommand = { name: node[:name] }
|
50
|
-
subcommand.merge!(args: node[:args].render(context)) if node[:args]
|
51
|
-
subcommand
|
52
|
-
else
|
53
|
-
node.render(context)
|
54
|
-
end
|
55
|
-
end
|
32
|
+
subnodes.select { |node| node.is_a?(Hotcell::Command) }
|
56
33
|
end
|
57
34
|
end
|
58
35
|
end
|
data/lib/hotcell/node/command.rb
CHANGED
@@ -1,22 +1,39 @@
|
|
1
1
|
module Hotcell
|
2
2
|
class Command < Hotcell::Node
|
3
|
-
|
3
|
+
class_attribute :_validations
|
4
|
+
self._validations = {}
|
4
5
|
|
5
|
-
def
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
if klass = Hotcell.commands[name]
|
13
|
-
klass.new name, *children, options
|
6
|
+
def self.validate_arguments_count options
|
7
|
+
arguments_count = case options
|
8
|
+
when Hash
|
9
|
+
Range.new(options[:min].to_i,
|
10
|
+
options[:max].present? ? options[:max].to_i : Float::INFINITY)
|
11
|
+
when Range
|
12
|
+
options
|
14
13
|
else
|
15
|
-
|
14
|
+
options.to_i
|
16
15
|
end
|
16
|
+
|
17
|
+
self._validations = _validations.merge(arguments_count: arguments_count)
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_arguments_count!
|
21
|
+
return unless _validations.key?(:arguments_count)
|
22
|
+
|
23
|
+
args_count = children.count
|
24
|
+
valid_args_count = _validations[:arguments_count]
|
25
|
+
|
26
|
+
valid = valid_args_count.is_a?(Integer) ?
|
27
|
+
args_count == valid_args_count : valid_args_count.include?(args_count)
|
28
|
+
|
29
|
+
raise Hotcell::ArgumentError.new(
|
30
|
+
"Wrond number of arguments for `#{name}` (#{args_count} for #{valid_args_count})",
|
31
|
+
*position_info
|
32
|
+
) unless valid
|
17
33
|
end
|
18
34
|
|
19
35
|
def validate!
|
36
|
+
validate_arguments_count!
|
20
37
|
end
|
21
38
|
|
22
39
|
def process context, *args
|
@@ -24,17 +41,7 @@ module Hotcell
|
|
24
41
|
|
25
42
|
def render context
|
26
43
|
context.safe do
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def concat context, result
|
32
|
-
context[assign] = result if assign
|
33
|
-
case mode
|
34
|
-
when :normal
|
35
|
-
result
|
36
|
-
else
|
37
|
-
''
|
44
|
+
process(context, *render_children(context))
|
38
45
|
end
|
39
46
|
end
|
40
47
|
end
|
data/lib/hotcell/node/hasher.rb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
module Hotcell
|
2
2
|
class Summoner < Hotcell::Node
|
3
|
-
def
|
4
|
-
|
5
|
-
end
|
6
|
-
|
7
|
-
def process context, object, method, *arguments
|
8
|
-
(object.to_manipulator || context).manipulator_invoke(method, *arguments)
|
3
|
+
def process context, target = nil, *arguments
|
4
|
+
(target ? target.to_manipulator : context).manipulator_invoke(name, *arguments)
|
9
5
|
end
|
10
6
|
end
|
11
7
|
end
|
data/lib/hotcell/node/tag.rb
CHANGED
@@ -13,13 +13,16 @@ module Hotcell
|
|
13
13
|
|
14
14
|
def render context
|
15
15
|
context.safe do
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
16
|
+
concat context, process(context, *render_children(context))
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def concat context, result
|
21
|
+
case mode
|
22
|
+
when :normal
|
23
|
+
result
|
24
|
+
else
|
25
|
+
''
|
23
26
|
end
|
24
27
|
end
|
25
28
|
end
|
data/lib/hotcell/node.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module Hotcell
|
2
2
|
class Node
|
3
3
|
attr_accessor :name, :children, :options
|
4
|
+
attr_reader :position, :source
|
4
5
|
|
5
6
|
def self.build *args
|
6
7
|
new(*args).optimize
|
@@ -9,9 +10,15 @@ module Hotcell
|
|
9
10
|
def initialize name, *args
|
10
11
|
@name = name
|
11
12
|
@options = args.extract_options!
|
13
|
+
@source = @options.delete(:source)
|
14
|
+
@position = @options.delete(:position)
|
12
15
|
@children = args
|
13
16
|
end
|
14
17
|
|
18
|
+
def position_info
|
19
|
+
source.info(position).values_at(:line, :column)
|
20
|
+
end
|
21
|
+
|
15
22
|
def optimize
|
16
23
|
self
|
17
24
|
end
|
@@ -21,7 +28,7 @@ module Hotcell
|
|
21
28
|
end
|
22
29
|
|
23
30
|
def render context
|
24
|
-
process context, *
|
31
|
+
process context, *render_children(context)
|
25
32
|
end
|
26
33
|
|
27
34
|
def process context, *values
|
@@ -34,6 +41,10 @@ module Hotcell
|
|
34
41
|
end
|
35
42
|
end
|
36
43
|
|
44
|
+
def render_children context
|
45
|
+
render_nodes context, children
|
46
|
+
end
|
47
|
+
|
37
48
|
def == other
|
38
49
|
other.is_a?(self.class) &&
|
39
50
|
name == other.name &&
|