mplex 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README.md +157 -0
  2. data/bin/mplex +101 -0
  3. data/lib/mplex.rb +99 -0
  4. metadata +69 -0
@@ -0,0 +1,157 @@
1
+ mplex
2
+ =====
3
+ http://github.com/frsyuki/mplex/
4
+
5
+ ## Overview
6
+
7
+ mplex is an Extended Metaprogramming Library.
8
+
9
+
10
+ ## Requirements
11
+
12
+ - ruby >= 1.8
13
+
14
+
15
+ ## Installation
16
+
17
+ Use ./configure or rubygems.
18
+
19
+ Install using ./configure:
20
+ ./bootstrap
21
+ ./configure
22
+ make
23
+ make install
24
+
25
+ Install using rubygems:
26
+ gem build mplex.gemspec
27
+ gem install mplex-*.gem
28
+
29
+
30
+ ## Usage
31
+
32
+ Usage: mplex [options] input...
33
+ -c file context ruby script
34
+ -o file output file
35
+ -r library load library
36
+ -x print ruby script
37
+
38
+
39
+ ## Example
40
+
41
+ ### Simple
42
+ %0.upto(4) do |num|
43
+ class Test[%num%] {
44
+ public:
45
+ %num.times do |i|
46
+ int member{{i}};
47
+ %end
48
+
49
+ %if num % 2 == 0
50
+ int even;
51
+ %end
52
+ };
53
+ %end
54
+
55
+ "{{...}}" is same as "[%...%]".
56
+
57
+ ### Simple with advanced syntax
58
+
59
+ %0.upto(4) do |num|
60
+ class Test[%num%] {
61
+ public:
62
+ int member{{i}}; %|i| num.times
63
+ int even; %> if num % 2 == 0
64
+ };
65
+ %end
66
+
67
+ ### Macro
68
+
69
+ %def abc(ns)
70
+ namespace [%ns%] {
71
+ % %w[A B C].each do |a|
72
+ % yield a
73
+ % end
74
+ }
75
+ %end
76
+
77
+ %abc("name") do |a|
78
+ void func[%a%]();
79
+ %end
80
+
81
+ ### Context script
82
+
83
+ rpc.rb:
84
+ {
85
+ "Get" => {
86
+ "std::string" => "key",
87
+ "uint32_t" => "flags",
88
+ },
89
+
90
+ "Put" => {
91
+ "std::string" => "key",
92
+ "std::string" => "value",
93
+ },
94
+ }
95
+
96
+ rpc.hmpl:
97
+ %self.each_pair do |name, args|
98
+ void [%name%]( [%args.map {|type,name| "#{type} #{name}" }.join(", ")%] );
99
+ %end
100
+
101
+ run:
102
+ mplex -c rpc.rb rpc.hmpl -o rpc.h
103
+
104
+ ### Makefile
105
+
106
+ source tree:
107
+ README
108
+ src/
109
+ src/subdir/
110
+ src/Makefile.am
111
+ src/mplex # put mplex script here
112
+ src/myapp.hmpl # myapp.hmpl -> myapp.h
113
+ src/myapp.ccmpl # myapp.ccmpl -> myapp.cc
114
+
115
+ Makefile.am:
116
+ MPLEX = ruby $(abs_srcdir)/mplex
117
+ export MPLEX
118
+
119
+ PREP_SOURCE = myapp.hmpl myapp.ccmpl
120
+ PREP_TARGET = $(PREP_SOURCE:mpl=)
121
+ EXTRA_DIST = $(PREP_SOURCE)
122
+
123
+ %.h: %.hmpl
124
+ $(MPLEX) $< -o $@
125
+
126
+ %.cc: %.ccmpl
127
+ $(MPLEX) $< -o $@
128
+
129
+ prep: $(PREP_TARGET)
130
+ cd subdir && $(MAKE) prep
131
+
132
+ prepc:
133
+ rm -f $(PREP_TARGET)
134
+ cd subdir && $(MAKE) prepc
135
+
136
+ ## License
137
+
138
+ Copyright (c) 2009-2010 FURUHASHI Sadayuki
139
+
140
+ Permission is hereby granted, free of charge, to any person obtaining a copy
141
+ of this software and associated documentation files (the "Software"), to deal
142
+ in the Software without restriction, including without limitation the rights
143
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
144
+ copies of the Software, and to permit persons to whom the Software is
145
+ furnished to do so, subject to the following conditions:
146
+
147
+ The above copyright notice and this permission notice shall be included in
148
+ all copies or substantial portions of the Software.
149
+
150
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
151
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
152
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
153
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
154
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
155
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
156
+ THE SOFTWARE.
157
+
@@ -0,0 +1,101 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Mplex: Extended Metaprogramming Library
4
+ #
5
+ # Copyright (c) 2009-2010 FURUHASHI Sadayuki
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
8
+ # of this software and associated documentation files (the "Software"), to deal
9
+ # in the Software without restriction, including without limitation the rights
10
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ # copies of the Software, and to permit persons to whom the Software is
12
+ # furnished to do so, subject to the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be included in
15
+ # all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23
+ # THE SOFTWARE.
24
+ #
25
+
26
+ require 'mplex'
27
+ require 'optparse'
28
+
29
+ op = OptionParser.new
30
+ op.banner += " input..."
31
+
32
+ finputs = "-"
33
+ foutput = "-"
34
+ fctx = nil
35
+ libs = []
36
+ script = false
37
+
38
+ op.on("-c file", "context ruby script") {|v| fctx = v }
39
+ op.on("-o file", "output file") {|v| foutput = v }
40
+ op.on("-r library", "load library") {|v| libs << v }
41
+ op.on("-x", "print ruby script") {|v| script = true }
42
+
43
+ (class<<self;self;end).module_eval {
44
+ define_method(:usage) {
45
+ puts op.to_s
46
+ puts $! unless $!.to_s.empty?
47
+ exit 1
48
+ }
49
+ }
50
+
51
+ begin
52
+ op.parse!(ARGV)
53
+
54
+ usage if ARGV.empty?
55
+
56
+ finputs = ARGV
57
+
58
+ raise "multiple stdin" if (finputs + [fctx]).count("-") >= 2
59
+
60
+ rescue
61
+ usage
62
+ end
63
+
64
+ def fread(path)
65
+ path == "-" ? $stdin.read : File.read(path)
66
+ end
67
+
68
+ def fname(path)
69
+ path == "-" ? "(stdin)" : path
70
+ end
71
+
72
+ libs.each {|lib| require lib }
73
+
74
+ inputs = finputs.map {|f| [fread(f), fname(f)] }
75
+
76
+ result = ""
77
+ if script
78
+ inputs.each {|src, name|
79
+ result.concat Mplex.script(src)
80
+ }
81
+
82
+ else
83
+ if fctx
84
+ b = nil; Object.instance_eval { b = binding }
85
+ ctx = eval("lambda{#{fread(fctx)}}.call", b, fname(fctx))
86
+ end
87
+ ctx ||= Object.new
88
+
89
+ inputs.each {|src, name|
90
+ Mplex.result(src, ctx, name, result)
91
+ }
92
+ end
93
+
94
+ if foutput == "-"
95
+ $stdout.write(result)
96
+ else
97
+ File.open(foutput, "w") {|f|
98
+ f.write result
99
+ }
100
+ end
101
+
@@ -0,0 +1,99 @@
1
+ #
2
+ # Mplex: Extended Metaprogramming Library
3
+ #
4
+ # Copyright (c) 2009-2010 FURUHASHI Sadayuki
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
7
+ # of this software and associated documentation files (the "Software"), to deal
8
+ # in the Software without restriction, including without limitation the rights
9
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
+ # copies of the Software, and to permit persons to whom the Software is
11
+ # furnished to do so, subject to the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be included in
14
+ # all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
+ # THE SOFTWARE.
23
+ #
24
+
25
+ class Mplex
26
+ def initialize(src, fname = "(mplex)")
27
+ @script = self.class.compile(src)
28
+ b = nil; Object.new.instance_eval { b = binding }
29
+ @proc = eval("Proc.new{#{@script}}", b, fname)
30
+ end
31
+ attr_reader :script
32
+
33
+ def result(context = nil, output = "")
34
+ self.class.with_context(context, output) {|ctx|
35
+ ctx.instance_eval(&@proc)
36
+ }
37
+ end
38
+
39
+ def self.result(src, context = nil, fname = "(mplex)", output = "")
40
+ with_context(context, output) {|ctx|
41
+ ctx.instance_eval(compile(src), fname)
42
+ }
43
+ end
44
+
45
+ def self.file(fname, context = nil)
46
+ self.result(File.read(fname), context, fname)
47
+ end
48
+
49
+ def self.write(fname, outfname, context = nil)
50
+ out = self.result(File.read(fname), context, fname)
51
+ File.open(outfname, "w") {|f| f.write(out) }
52
+ out
53
+ end
54
+
55
+ def self.script(src)
56
+ compile(src)
57
+ end
58
+
59
+ private
60
+ def self.with_context(context, output, &block)
61
+ context ||= Object.new
62
+ save = context.instance_variable_get(:@_mplexout)
63
+ context.instance_variable_set(:@_mplexout, output)
64
+ block.call(context)
65
+ context.instance_variable_set(:@_mplexout, save)
66
+ output
67
+ end
68
+
69
+ def self.compile(src)
70
+ # MPLEX_COMPILE_BEGIN
71
+ o = ""
72
+ k = false
73
+ src.each_line {|t|
74
+ (k = false; o << "\n"; next) if k && t == "__END__\n"
75
+ (o << t; next) if k
76
+ (k = true; o << "\n"; next) if t == "__BEGIN__\n"
77
+
78
+ c, l = t.split(/^[ \t]*%/,2)
79
+ (o << l; next) if l
80
+
81
+ c, a, b = t.split(/[ \t]*\%\|([a-z0-9\,\*\&\(\)]*)\|/,2)
82
+ t = "[%:#{b.strip} do |#{a}|%]#{c+"\n"}[%:end%]" if b
83
+
84
+ c, q = t.split(/[ \t]*\%\>/,2)
85
+ t = "[%:(%]#{c+"\n"}[%:)#{q.strip}%]" if q
86
+
87
+ s = t.split(/(?:\[\%(\:?.*?)\%\]|\{\{(\:?.*?\}*)\}\})/m)
88
+ s.each_with_index {|m,i|
89
+ (o << "#{m[1..-1]};"; next) if m[0] == ?: && i % 2 == 1
90
+ (o << "@_mplexout.concat((#{m}).to_s);"; next) if i % 2 == 1
91
+ o << "@_mplexout.concat(#{m.dump});" unless m.empty?
92
+ }
93
+ o << "\n"
94
+ }
95
+ o << "@_mplexout"
96
+ # MPLEX_COMPILE_END
97
+ end
98
+ end
99
+
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mplex
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 3
10
+ version: 0.0.3
11
+ platform: ruby
12
+ authors:
13
+ - FURUHASHI Sadayuki
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-20 00:00:00 +09:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description:
23
+ email: frsyuki@users.sourceforge.jp
24
+ executables:
25
+ - mplex
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - bin/mplex
32
+ - lib/mplex.rb
33
+ - README.md
34
+ has_rdoc: true
35
+ homepage: http://github.com/frsyuki/mplex
36
+ licenses: []
37
+
38
+ post_install_message:
39
+ rdoc_options: []
40
+
41
+ require_paths:
42
+ - lib
43
+ required_ruby_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ">="
47
+ - !ruby/object:Gem::Version
48
+ hash: 3
49
+ segments:
50
+ - 0
51
+ version: "0"
52
+ required_rubygems_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ hash: 3
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ requirements: []
62
+
63
+ rubyforge_project:
64
+ rubygems_version: 1.3.7
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: mplex
68
+ test_files: []
69
+