carnelian 1.0.0

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.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZjA1NjdhYmM1YWRmNDczNjEyYzA5OWU2M2RkZWYxNDAxY2Y3ZWFkMg==
5
+ data.tar.gz: !binary |-
6
+ MDYyNDQ4OThmOWIxNzZhM2Q1YzhlM2YzYzUzNjFkNjAwYTAxMGM0Nw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ OGIwNDJhMWFlOGE1NmI5YmFiYTBjMjcyZmRmYWIxYWQ5N2JmYWUxMzcwYjJj
10
+ ODQ2NGI4Y2MzMzVlOTM0NDA0ZjJhYWFmNjdlOTNlMTA1YjY2OWIwNmEwZTAw
11
+ NTE4MzZhOWI0OWY2ZmEyM2VmZjVlMTIwNGI2YThmMTAxZjlmMjg=
12
+ data.tar.gz: !binary |-
13
+ NTc2MmFiMjc3NjY5N2U5ODhhYjNhZTgxYjE1ZjRjN2JkZGJkNWExYWU4MDI3
14
+ MTFhOGYyMWQ1NDE0ZGM0MzQ5ZWU0ZGM3MWIyOGM4ZTFlZTNkOWE5ODJhOTU0
15
+ M2VlZDljMGQ2MzFmY2YzYjcwYzMwMzEyN2YyOWNhNGQ2OGQ3N2Y=
@@ -0,0 +1,303 @@
1
+ # ----------------------------------------------------------------------------------------------
2
+ # Copyright (c) Mårten Rånge.
3
+ # ----------------------------------------------------------------------------------------------
4
+ # This source code is subject to terms and conditions of the Microsoft Public License. A
5
+ # copy of the license can be found in the License.html file at the root of this distribution.
6
+ # If you cannot locate the Microsoft Public License, please send an email to
7
+ # dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
8
+ # by the terms of the Microsoft Public License.
9
+ # ----------------------------------------------------------------------------------------------
10
+ # You must not remove this notice, or any other, from this software.
11
+ # ----------------------------------------------------------------------------------------------
12
+
13
+ require 'ostruct'
14
+
15
+ module CarnelianExecutor
16
+ class CarnelianError < RuntimeError
17
+ end
18
+
19
+ module Details
20
+ def self.make_match (match, &processor)
21
+ os = OpenStruct.new
22
+ os.match = match
23
+ os.processor = processor
24
+ return os
25
+ end
26
+
27
+ def self.make_template_write_line (lines, line, begin_tag, end_tag)
28
+
29
+ length = line.length
30
+ if length > 0 then
31
+ is_inside_tag = false
32
+ current_index = 0
33
+ next_index = 0
34
+ current_tag = begin_tag
35
+
36
+ while current_index < length
37
+ next_index = line.index current_tag, current_index
38
+
39
+ effective_index = next_index || length
40
+
41
+ if !is_inside_tag then
42
+ slice = line.slice current_index, (effective_index - current_index)
43
+ slice.gsub! /(\\|\')/, '\\\\\1'
44
+
45
+ if slice.length > 0 then
46
+ l = "document.write '"
47
+ l << slice
48
+ l << "'"
49
+ lines << l
50
+ end
51
+
52
+ current_index = effective_index + begin_tag.length
53
+ current_tag = end_tag
54
+ else
55
+ slice = line.slice current_index, (effective_index - current_index)
56
+ l = "document.write ("
57
+ l << slice
58
+ l << ")"
59
+ lines << l
60
+
61
+ current_index = effective_index + end_tag.length
62
+ current_tag = begin_tag
63
+ end
64
+
65
+ is_inside_tag = !is_inside_tag
66
+ end
67
+ end
68
+
69
+ lines << "document.new_line"
70
+ end
71
+
72
+ $match_metaprogram = make_match (/^@@@ metaprogram\s*$/) \
73
+ do |line_context, metaprogram|
74
+ if line_context.line_no > 1 then
75
+ failure = "%s(%d) : metaprogram line must appear at first line" %
76
+ [
77
+ line_context.file_name ,
78
+ line_context.line_no ,
79
+ ]
80
+ metaprogram.failures << failure
81
+ else
82
+ line_context.is_metaprogram = true
83
+ end
84
+ end
85
+ $match_include = make_match (/^@@@ include\s+(?<file>\S+)\s*$/) \
86
+ do |line_context, metaprogram|
87
+ filename = line_context.match_data["file"]
88
+ seen_files = line_context.seen_files
89
+ read_metaprogram_impl filename,seen_files,metaprogram
90
+ end
91
+ $match_require = make_match (/^@@@ require\s+(?<require>\S+)\s*$/) \
92
+ do |line_context, metaprogram|
93
+ metaprogram.requires << line_context.match_data["require"]
94
+ end
95
+ $match_extension = make_match (/^@@@ extension\s+(?<extension>\S+)\s*$/) \
96
+ do |line_context, metaprogram|
97
+ if (metaprogram.extension || "") == "" then
98
+ metaprogram.extension = line_context.match_data["extension"]
99
+ end
100
+ end
101
+ $match_inject_tokens = make_match (/^@@@ inject_tokens\s+(?<begin_tag>\S+)\s+(?<end_tag>\S+)\s*$/) \
102
+ do |line_context, metaprogram|
103
+ line_context.begin_tag = line_context.match_data["begin_tag"]
104
+ line_context.end_tag = line_context.match_data["end_tag"]
105
+ end
106
+ $match_template_line = make_match (/^@@\>(?<line>.*)$/) \
107
+ do |line_context, metaprogram|
108
+ metaprogram.template_lines << line_context.match_data["line"]
109
+ end
110
+ $match_program_line = make_match (/^@@\+(?<line>.*)$/) \
111
+ do |line_context, metaprogram|
112
+ metaprogram.program_lines << line_context.match_data["line"]
113
+ end
114
+ $match_escaped_line = make_match (/^\\(?<line>@@.*)$/) \
115
+ do |line_context, metaprogram|
116
+ make_template_write_line metaprogram.template_lines, line_context.match_data["line"], line_context.begin_tag, line_context.end_tag
117
+ end
118
+ $match_normal_line = make_match (/^(?<line>.*)$/) \
119
+ do |line_context, metaprogram|
120
+ make_template_write_line metaprogram.template_lines, line_context.match_data["line"], line_context.begin_tag, line_context.end_tag
121
+ end
122
+ $match_unmatched_line = make_match (/.*/) \
123
+ do |line_context, metaprogram|
124
+ metaprogram.template_lines << "document.write 'UNMATCHED INPUT LINE'"
125
+ metaprogram.template_lines << "document.new_line"
126
+ end
127
+
128
+ $matches =
129
+ [
130
+ $match_metaprogram ,
131
+ $match_include ,
132
+ $match_require ,
133
+ $match_extension ,
134
+ $match_inject_tokens ,
135
+ $match_template_line ,
136
+ $match_program_line ,
137
+ $match_escaped_line ,
138
+ $match_normal_line ,
139
+ $match_unmatched_line ,
140
+ ]
141
+
142
+ def self.read_metaprogram_impl (filename, seen_files, metaprogram)
143
+
144
+ realpath = File.realpath filename
145
+
146
+ # Is this file already processed?
147
+ return if seen_files.key? realpath
148
+
149
+ seen_files.store realpath, true
150
+
151
+ line_context = OpenStruct.new
152
+ line_context.begin_tag = "@@="
153
+ line_context.end_tag = "=@@"
154
+ line_context.file_name = realpath
155
+ line_context.line_no = 0
156
+ line_context.is_metaprogram = false
157
+ line_context.seen_files = seen_files
158
+ line_context.match_data = nil
159
+ line_context.line = ""
160
+
161
+
162
+ lines = []
163
+
164
+ File.open (realpath) do |file|
165
+ lines = file.readlines
166
+ end
167
+
168
+ for line in lines
169
+
170
+ line_context.line_no += 1
171
+ line_context.line = line
172
+
173
+ for match in $matches
174
+ line_context.match_data = match.match.match line
175
+ if line_context.match_data != nil then
176
+ match.processor.call line_context, metaprogram
177
+ break
178
+ end
179
+ end
180
+
181
+ end
182
+
183
+ unless line_context.is_metaprogram then
184
+ failure = "%s(1) : No metaprogram line discovered" %
185
+ [
186
+ line_context.file_name ,
187
+ ]
188
+ metaprogram.failures << failure
189
+ end
190
+
191
+ return
192
+ end
193
+
194
+ def self.read_metaprogram (filename)
195
+ seen_files = {}
196
+
197
+ metaprogram = OpenStruct.new
198
+ metaprogram.extension = ""
199
+ metaprogram.template_lines = []
200
+ metaprogram.program_lines = []
201
+ metaprogram.requires = ["carnelian/runtime"]
202
+ metaprogram.failures = []
203
+
204
+ read_metaprogram_impl filename, seen_files, metaprogram
205
+
206
+ metaprogram.requires.uniq!
207
+ metaprogram.requires.sort!
208
+ metaprogram.failures.uniq!
209
+
210
+ return metaprogram
211
+ end
212
+
213
+ def self.build_metaprogram (filename)
214
+ metaprogram = read_metaprogram filename
215
+
216
+ if metaprogram.failures.length > 0 then
217
+ raise CarnelianError, "Failures detected: " + metaprogram.failures.join(', ')
218
+ end
219
+
220
+
221
+ lines = []
222
+ for req in metaprogram.requires
223
+ line = 'require \''
224
+ line << req
225
+ line << '\''
226
+ lines << line
227
+ end
228
+
229
+ for line in metaprogram.program_lines
230
+ lines << line
231
+ end
232
+
233
+ lines << "def generate_document (document)"
234
+ for line in metaprogram.template_lines
235
+ l = " "
236
+ l << line
237
+ lines << l
238
+ end
239
+ lines << "end"
240
+
241
+ lines << %q{
242
+ document = CarnelianRuntime.create_document
243
+
244
+ generate_document document
245
+
246
+ document.get_lines
247
+ }
248
+ metaprogram.metaprogram = lines.join "\n"
249
+
250
+ metaprogram
251
+ end
252
+
253
+ def self.execute_metaprogram (filename)
254
+ metaprogram = build_metaprogram filename
255
+
256
+ lines = TOPLEVEL_BINDING.eval metaprogram.metaprogram
257
+
258
+ metaprogram.result = lines.join "\n"
259
+
260
+ metaprogram
261
+ end
262
+
263
+ end
264
+
265
+ def self.build_metaprogram (filename)
266
+ metaprogram = Details.build_metaprogram filename
267
+
268
+ metaprogram.metaprogram
269
+ end
270
+
271
+ def self.build_metaprogram_to_file (filename,output_filename=nil)
272
+ extension = File.extname filename
273
+ basename = File.basename filename, extension
274
+
275
+ metaprogram = Details.build_metaprogram filename
276
+
277
+ outname = output_filename || ("%s.rb" % [basename])
278
+
279
+ File.open outname, "w" do |file|
280
+ file.write metaprogram.metaprogram
281
+ end
282
+ end
283
+
284
+ def self.execute_metaprogram (filename)
285
+ metaprogram = Details.execute_metaprogram filename
286
+
287
+ metaprogram.result
288
+ end
289
+
290
+ def self.execute_metaprogram_to_file (filename,output_filename=nil)
291
+ extension = File.extname filename
292
+ basename = File.basename filename, extension
293
+
294
+ metaprogram = Details.execute_metaprogram filename
295
+
296
+ new_extension = metaprogram.extension == "" ? "txt" : metaprogram.extension
297
+ outname = output_filename || ("%s.%s" % [basename, new_extension])
298
+
299
+ File.open outname, "w" do |file|
300
+ file.write metaprogram.result
301
+ end
302
+ end
303
+ end
@@ -0,0 +1,38 @@
1
+ # ----------------------------------------------------------------------------------------------
2
+ # Copyright (c) Mårten Rånge.
3
+ # ----------------------------------------------------------------------------------------------
4
+ # This source code is subject to terms and conditions of the Microsoft Public License. A
5
+ # copy of the license can be found in the License.html file at the root of this distribution.
6
+ # If you cannot locate the Microsoft Public License, please send an email to
7
+ # dlr@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
8
+ # by the terms of the Microsoft Public License.
9
+ # ----------------------------------------------------------------------------------------------
10
+ # You must not remove this notice, or any other, from this software.
11
+ # ----------------------------------------------------------------------------------------------
12
+
13
+ module CarnelianRuntime
14
+ class Document
15
+ def initialize ()
16
+ @current_line = ""
17
+ @lines = []
18
+ end
19
+
20
+ def write (value)
21
+ @current_line << value.to_s
22
+ end
23
+
24
+ def new_line ()
25
+ @lines << @current_line
26
+ @current_line = ""
27
+ end
28
+
29
+ def get_lines ()
30
+ return @lines
31
+ end
32
+ end
33
+
34
+ def self.create_document
35
+ Document.new
36
+ end
37
+
38
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: carnelian
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Mårten Rånge
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-09 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Carnelian is code generation tool written in ruby. It's inspired by T4,
14
+ a product shipped with Microsoft VisualStudio
15
+ email: marten_range@hotmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/carnelian/executor.rb
21
+ - lib/carnelian/runtime.rb
22
+ homepage: https://github.com/mrange/carnelian
23
+ licenses:
24
+ - MS-PL
25
+ metadata: {}
26
+ post_install_message:
27
+ rdoc_options: []
28
+ require_paths:
29
+ - lib
30
+ required_ruby_version: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ required_rubygems_version: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ requirements: []
41
+ rubyforge_project:
42
+ rubygems_version: 2.2.2
43
+ signing_key:
44
+ specification_version: 4
45
+ summary: Carnelian is code generation tool
46
+ test_files: []