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.
- checksums.yaml +15 -0
- data/lib/carnelian/executor.rb +303 -0
- data/lib/carnelian/runtime.rb +38 -0
- metadata +46 -0
checksums.yaml
ADDED
|
@@ -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: []
|