mplex 0.0.3

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 (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
+