take 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2637d99ba8ea1bef3aece18d26f31ed73e8585d5
4
- data.tar.gz: 82017635983468566a4e66f433e70e5d8dec765f
3
+ metadata.gz: 451dc9d6ef5b89807d396e55d0320fa2432991a1
4
+ data.tar.gz: 32ee53bde93419d3cc52adc9a41b6fbbda8a4aa9
5
5
  SHA512:
6
- metadata.gz: 52a5a3ffb71977e50388eed3e02344d0fe0caa2bdbcb117affc54409f344b4cb89e9f88d27933d4623ebdfd4f82f293c3a00e6682ebd779fab7fc37f8472ac16
7
- data.tar.gz: f25c40d35046001fed6393a98425dbb86cd7ec9c5c49bdf531d208bafaf2fb0a74319ba8ccee686b7c1779704222c4043ab88c6125c6fe43e59e350740518d71
6
+ metadata.gz: 8d8fddbd0da58bdc641c81190139ed31aeeab39d1d879bd4403997f7ac95e2378bac1007c87d4fa8d0385dad291f5a631ed7d6725d61d5cfab64535888fe7591
7
+ data.tar.gz: 32faa1c8b86163b1d3181efde2c9ac9a5992f605aeef4fbab9653d07fe0e1ea65c9b727c55911267327d1ca580a63ab53c514acf4d74c1b684273a9adc8a3db8
data/.gitignore CHANGED
@@ -12,3 +12,6 @@
12
12
  *.o
13
13
  *.a
14
14
  mkmf.log
15
+ .project
16
+ .project.rb
17
+ test.*
@@ -0,0 +1,12 @@
1
+ module Take
2
+ class Unit
3
+ module AST
4
+ class After < Node
5
+
6
+ def after?
7
+ true
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Take
2
+ class Unit
3
+ module AST
4
+ class Before < Node
5
+
6
+ def before?
7
+ true
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ module Take
2
+ class Unit
3
+ module AST
4
+ class Block < Node
5
+ attribute :body, String
6
+
7
+ def block?
8
+ true
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,12 @@
1
+ module Take
2
+ class Unit
3
+ module AST
4
+ class Group < Node
5
+
6
+ def group?
7
+ true
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,20 @@
1
+ require "virtus"
2
+
3
+ module Take
4
+ class Unit
5
+ module AST
6
+ class Node
7
+
8
+ include Virtus.model
9
+
10
+ attribute :children, Array[Node], default: proc { [] }
11
+ attribute :name, String
12
+ attribute :source, Source
13
+
14
+ [:block?, :group?, :parent?, :test?, :before?, :after?, :prefix?].each do |m|
15
+ define_method(m) { false }
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,12 @@
1
+ module Take
2
+ class Unit
3
+ module AST
4
+ class Parent < Node
5
+
6
+ def parent?
7
+ true
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,12 @@
1
+ module Take
2
+ class Unit
3
+ module AST
4
+ class Prefix < Node
5
+
6
+ def prefix?
7
+ true
8
+ end
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,15 @@
1
+ require "virtus"
2
+
3
+ module Take
4
+ class Unit
5
+ module AST
6
+ class Source
7
+ include Virtus.model
8
+
9
+ attribute :file, String
10
+ attribute :line, Integer
11
+ attribute :column, Integer
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require "take/unit/ast/source"
2
+ require "take/unit/ast/node"
3
+ require "take/unit/ast/group"
4
+ require "take/unit/ast/test"
5
+ require "take/unit/ast/block"
6
+ require "take/unit/ast/parent"
7
+ require "take/unit/ast/after"
8
+ require "take/unit/ast/before"
9
+ require "take/unit/ast/prefix"
10
+
11
+ module Take
12
+ class Unit
13
+ module AST
14
+
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,119 @@
1
+ module Take
2
+ class Unit
3
+ class Compiler
4
+
5
+ include PredictMatch
6
+
7
+ attr_reader :parent
8
+
9
+ def initialize(file, tokens)
10
+ @file = file
11
+ @tokens = tokens
12
+ @enum = tokens.each
13
+ @parent = nil
14
+ end
15
+
16
+ def compile
17
+ @parent ||= begin
18
+ @parent = AST::Parent.new(name: @file.
19
+ gsub(/\..*\z/, "").gsub(/[\W]/, "_"))
20
+ while peek do
21
+ @parent.children << compile_group
22
+ end
23
+
24
+ @parent.source = sourcify([0, 0])
25
+ @parent
26
+ end
27
+ end
28
+
29
+ def compile_group
30
+ group = match(:group)
31
+ node = AST::Group.new(name: group[1], source: sourcify(group))
32
+
33
+ until peek == :group_end
34
+ part = compile_part
35
+ node.children << part if part
36
+ end
37
+
38
+ match(:group_end)
39
+
40
+ node
41
+ end
42
+
43
+ def compile_part
44
+ predict :group => :group,
45
+ :test => :test,
46
+ :before => :before,
47
+ :after => :after,
48
+ :prefix => :prefix,
49
+ :macro => :macro
50
+ end
51
+
52
+ def compile_test
53
+ test = match(:test)
54
+ body = match(:block)
55
+ AST::Test.new(name: test[1],
56
+ children: [AST::Block.new({
57
+ body: body[1],
58
+ source: sourcify(body)
59
+ })],
60
+ source: sourcify(test))
61
+ end
62
+
63
+ def compile_before
64
+ before = match(:before)
65
+ body = match(:block)
66
+
67
+ AST::Before.new(name: before[1],
68
+ children: [AST::Block.new({
69
+ body: body[1],
70
+ source: sourcify(body)
71
+ })],
72
+ source: sourcify(before))
73
+ end
74
+
75
+ def compile_after
76
+ after = match(:after)
77
+ body = match(:block)
78
+
79
+ AST::After.new(name: after[1],
80
+ children: [AST::Block.new({
81
+ body: body[1],
82
+ source: sourcify(body)
83
+ })],
84
+ source: sourcify(after))
85
+ end
86
+
87
+ def compile_prefix
88
+ prefix = match(:prefix)
89
+ body = match(:block)
90
+
91
+ @parent.children << AST::Prefix.new(
92
+ name: prefix[1],
93
+ children: [AST::Block.new({
94
+ body: body[1],
95
+ source: sourcify(body)
96
+ })],
97
+ source: sourcify(prefix))
98
+
99
+ nil
100
+ end
101
+
102
+ def compile_macro
103
+
104
+ end
105
+
106
+ private
107
+
108
+ def input
109
+ @enum
110
+ end
111
+
112
+ def sourcify(token)
113
+ hash = Hash[[:line, :column].zip(token[-2..-1])]
114
+ hash.merge(file: @file)
115
+ end
116
+
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,136 @@
1
+ module Take
2
+ class Unit
3
+ class Generator
4
+
5
+ def initialize(parent, options)
6
+ @parent = parent
7
+ @groups = [@parent]
8
+ @options = options
9
+ end
10
+
11
+ def generate
12
+ @output ||= begin
13
+ @output = ""
14
+ walk(@parent)
15
+ @output
16
+ end
17
+ end
18
+
19
+ def write_file
20
+ File.open("#{@parent.name}.c", "w") do |f|
21
+ f.write generate
22
+ end
23
+ end
24
+
25
+ def walk(node, *opts)
26
+ case
27
+ when node.group?
28
+ walk_group(node, *opts)
29
+ when node.test?
30
+ walk_test(node, *opts)
31
+ when node.block?
32
+ walk_block(node, *opts)
33
+ when node.parent?
34
+ walk_parent(node, *opts)
35
+ when node.before?
36
+ walk_before(node, *opts)
37
+ when node.after?
38
+ walk_after(node, *opts)
39
+ when node.prefix?
40
+ walk_prefix(node, *opts)
41
+ else
42
+ raise ArgumentError, "Invalid argument given: #{node.class} (#{node})"
43
+ end
44
+ end
45
+
46
+ def walk_group(node)
47
+ @groups << node
48
+ group.children.select(&:test?).
49
+ each { |child| walk(child) }
50
+
51
+ @output << "// group #{group_name}\n"
52
+ @output << "void group_#{group_name}()\n{\n"
53
+ befores.each { |child| walk(child) }
54
+ @output << group.children.select(&:test?).
55
+ map { |child| " test_#{group_name(child)}();" }.
56
+ join("\n")
57
+ @output << "\n"
58
+ afters.each { |child| walk(child) }
59
+ @output << "}\n\n"
60
+ @groups.pop
61
+ end
62
+
63
+ def walk_test(node)
64
+ @output << "void test_#{group_name(node)}()\n{\n"
65
+ node.children.select(&:block?).each { |child| walk(child) }
66
+ @output << "}\n\n"
67
+ end
68
+
69
+ def walk_block(node, indent = 2)
70
+ @output << "#line \"#{node.source.file}\" #{node.source.line + 2}"
71
+ lines = node.body.each_line
72
+ deindent = if scan = node.body.scan(/^[ \t]*(?=\S)/).min
73
+ scan.size
74
+ else
75
+ 0
76
+ end
77
+
78
+ body = lines.map { |l| l.gsub(/^[ \t]{#{deindent}}/, "") }.
79
+ map { |l| (" " * indent) << l }.join("").rstrip.gsub(/^[ \t]+$/, "")
80
+
81
+ @output << body << "\n"
82
+ reset
83
+ end
84
+
85
+ def walk_parent(node)
86
+ node.children.select(&:prefix?).each { |child| walk(child) }
87
+ node.children.reject(&:prefix?).each { |child| walk(child) }
88
+ end
89
+
90
+ def walk_node(node)
91
+ if node.name
92
+ @output << "// #{node.class.name.gsub(/\A.*::/, "").downcase} #{node.name}\n"
93
+ end
94
+
95
+ node.children.each { |child| walk(child) }
96
+ @output << "\n"
97
+ end
98
+
99
+ def walk_prefix(node)
100
+ @output << "// prefix #{node.name}\n"
101
+ node.children.select(&:block?).each { |child| walk(child, 0) }
102
+ @output << "\n"
103
+ end
104
+
105
+ alias_method :walk_before, :walk_node
106
+ alias_method :walk_after, :walk_node
107
+
108
+ private
109
+
110
+ def group
111
+ @groups.last
112
+ end
113
+
114
+ def line
115
+ @output.count("\n") + 2
116
+ end
117
+
118
+ def reset
119
+ @output << "#line \"#{@parent.name}.c\" #{line}\n"
120
+ end
121
+
122
+ def befores
123
+ @groups.map(&:children).flatten.select(&:before?)
124
+ end
125
+
126
+ def afters
127
+ @groups.map(&:children).flatten.select(&:after?)
128
+ end
129
+
130
+ def group_name(test = nil)
131
+ [*@groups[1..-1], test].compact.map(&:name).
132
+ map { |n| n.gsub(/[\W]/, "_") }.join("_")
133
+ end
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,51 @@
1
+ module Take
2
+ class Unit
3
+ module PredictMatch
4
+
5
+ # Makes a prediction based on a set of actions. If the peek token
6
+ # doesn't have an action, it will try the special action `:_`, and
7
+ # then give up. If it finds a corresponding action either time, it
8
+ # will run the action.
9
+ #
10
+ # @param actions [Hash<Symbol => Symbol>]
11
+ # @return [Object] the result of the compiliation.
12
+ def predict(*params, actions)
13
+
14
+ action = actions.fetch(peek) do
15
+ actions.fetch(:_)
16
+ end
17
+
18
+ if action.respond_to?(:call)
19
+ action.call(*params)
20
+ else
21
+ send(:"compile_#{action}", *params)
22
+ end
23
+ end
24
+
25
+ # Matches the next token of the input. If it is not of the
26
+ # expected type, it raises a SyntaxError. Otherwise, it returns
27
+ # the token.
28
+ #
29
+ # @param name [Symbol] the token to match.
30
+ # @return [Array] the token.
31
+ # @raise SyntaxError if the peeked token is invalid.
32
+ def match(name)
33
+ if name == peek
34
+ input.next
35
+ else
36
+ raise SyntaxError, "Unexpected token #{peek}"
37
+ end
38
+ end
39
+
40
+ # Returns the type of the next token.
41
+ #
42
+ # @return [Symbol] the type of the next token.
43
+ def peek
44
+ input.peek[0]
45
+ rescue StopIteration
46
+ nil
47
+ end
48
+
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,149 @@
1
+ require "strscan"
2
+
3
+ module Take
4
+ class Unit
5
+ class Scanner
6
+
7
+ attr_reader :tokens
8
+
9
+ def initialize(input)
10
+ @input = "\n" << input
11
+ @scanner = StringScanner.new(input)
12
+ end
13
+
14
+ def scan
15
+ @tokens ||= begin
16
+ @tokens = []
17
+ until @scanner.eos?
18
+ scan_group_body { error! }
19
+ end
20
+ @tokens
21
+ end
22
+ end
23
+
24
+ def scan_group_body
25
+ pre_scan
26
+ scan_nested or
27
+ scan_group or
28
+ scan_body or
29
+ scan_whitespace or
30
+ yield
31
+ end
32
+
33
+ def scan_nested
34
+ if scan_group(/group/)
35
+ scan_whitespace
36
+ @scanner.scan(/\{/) or error!
37
+ loop do
38
+ scan_group_body do
39
+ if @scanner.scan(/\}/)
40
+ pre_scan
41
+ return emit(:group_end)
42
+ else
43
+ error!
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ def scan_group(scan = /macro|test|before|after|prefix/)
51
+ if @scanner.scan(scan)
52
+ group_type = @scanner[0]
53
+ @scanner.scan(/ ([A-Za-z0-9_.-]+)\(/) or error!
54
+ group_name = @scanner[1]
55
+
56
+ @scanner.scan(/\s*\;/)
57
+
58
+ emit group_type.intern,
59
+ group_name,
60
+ _scan_arguments(/\s*\)/, /,\s+/)
61
+ end
62
+ end
63
+
64
+ def scan_body
65
+ if @scanner.check(/\s*\{/)
66
+ emit :block, _scan_block
67
+ end
68
+ end
69
+
70
+ def scan_whitespace(newlines = true)
71
+ if newlines
72
+ @scanner.scan(/\s+/)
73
+ else
74
+ @scanner.scan(/[ \t]+/)
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def pre_scan
81
+ @pos = @scanner.pos
82
+ end
83
+
84
+ def line
85
+ @input[0..@pos].count("\n")
86
+ end
87
+
88
+ def column
89
+ last_newline = @input[0..@pos].rindex("\n") || 0
90
+ @pos - last_newline
91
+ end
92
+
93
+ def emit(*args)
94
+ @tokens << args.concat([line, column])
95
+ true
96
+ end
97
+
98
+ def _scan_block
99
+ brack = 1
100
+ body = @scanner.scan(/\s*\{/)
101
+ scan_for = %r{
102
+ (
103
+ (?: " ( \\\\ | \\" | [^"] )* "? )
104
+ | (?: ' ( \\\\ | \\' | [^'] )* '? )
105
+ | (?: // .*? \n )
106
+ | (?: \# .*? \n )
107
+ | (?: /\* [\s\S]+? \*/ )
108
+ | (?: \} )
109
+ | (?: \{ )
110
+ )
111
+ }x
112
+
113
+ until brack.zero?
114
+ if part = @scanner.scan_until(scan_for)
115
+ body << part
116
+
117
+
118
+ if @scanner[1] == "}"
119
+ brack -= 1
120
+ elsif @scanner[1] == "{"
121
+ brack += 1
122
+ end
123
+ else
124
+ @scanner.scan(/(.+)/m)
125
+ error!
126
+ end
127
+ end
128
+
129
+ body.gsub(/\A\n*/, "").gsub(/\A\s*\{([\s\S]*)\}\z/, "\\1")
130
+ end
131
+
132
+ def _scan_arguments(ending, seperator)
133
+ arguments = []
134
+ until @scanner.scan(ending)
135
+ @scanner.scan(/(&?[A-Za-z0-9_-]+)/)
136
+ arguments << @scanner[1]
137
+ @scanner.scan(seperator) or @scanner.check(ending) or error!
138
+ end
139
+
140
+ arguments
141
+ end
142
+
143
+ def error!
144
+ p @tokens
145
+ raise SyntaxError, "Unexpected `#{@scanner.check(/./)}' on line #{line} (column #{column})"
146
+ end
147
+ end
148
+ end
149
+ end
data/lib/take/unit.rb ADDED
@@ -0,0 +1,20 @@
1
+ require "take/unit/predict_match"
2
+ require "take/unit/ast"
3
+ require "take/unit/compiler"
4
+ require "take/unit/scanner"
5
+ require "take/unit/generator"
6
+
7
+ module Take
8
+
9
+ # A unit test. This is used to generate c files for tests.
10
+ class Unit
11
+
12
+ def create(file)
13
+ file = File.open(file, "r")
14
+ scanner = Scanner.new(file.read)
15
+ compiler = Compiler.new(file.path, scanner.scan)
16
+ generator = Generator.new(compiler.compile).generate
17
+ end
18
+
19
+ end
20
+ end
data/lib/take/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Take
2
- VERSION = "0.0.1".freeze
2
+ VERSION = "0.0.2".freeze
3
3
  end
data/lib/take.rb CHANGED
@@ -1,4 +1,6 @@
1
1
  require "take/version"
2
+ require "take/unit"
3
+ require "take/project"
2
4
 
3
5
  module Take
4
6
  # Your code goes here...
data/take.gemspec CHANGED
@@ -20,4 +20,5 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_development_dependency "bundler", "~> 1.6"
22
22
  spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_dependency "virtus", "~> 1.0"
23
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: take
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jeremy Rodi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-07-31 00:00:00.000000000 Z
11
+ date: 2014-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: virtus
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.0'
41
55
  description: Manage your C projects better.
42
56
  email:
43
57
  - redjazz96@gmail.com
@@ -51,8 +65,20 @@ files:
51
65
  - README.md
52
66
  - Rakefile
53
67
  - lib/take.rb
54
- - lib/take/project.rb
55
- - lib/take/project/builder.rb
68
+ - lib/take/unit.rb
69
+ - lib/take/unit/ast.rb
70
+ - lib/take/unit/ast/after.rb
71
+ - lib/take/unit/ast/before.rb
72
+ - lib/take/unit/ast/block.rb
73
+ - lib/take/unit/ast/group.rb
74
+ - lib/take/unit/ast/node.rb
75
+ - lib/take/unit/ast/parent.rb
76
+ - lib/take/unit/ast/prefix.rb
77
+ - lib/take/unit/ast/source.rb
78
+ - lib/take/unit/compiler.rb
79
+ - lib/take/unit/generator.rb
80
+ - lib/take/unit/predict_match.rb
81
+ - lib/take/unit/scanner.rb
56
82
  - lib/take/version.rb
57
83
  - take.gemspec
58
84
  homepage: ''
File without changes
data/lib/take/project.rb DELETED
@@ -1,22 +0,0 @@
1
-
2
- module Take
3
-
4
- # Handles project information for a specific project. Tends to represent
5
- # an entire directory.
6
- class Project
7
-
8
- # The name of the project. This is normally guessed from the directory
9
- # name.
10
- #
11
- # @return [String]
12
- attr_accessor :name
13
-
14
- # Initialize the project.
15
- def initialize(name = nil, &block)
16
- raise ArgumentError, "Projects require blocks" unless block_given?
17
- @block = block
18
- @name = name
19
- end
20
-
21
- end
22
- end