phlex 2.4.0.beta1 → 2.4.0.beta2
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 +4 -4
- data/lib/phlex/compiler/class_compiler.rb +16 -4
- data/lib/phlex/compiler/compactor.rb +74 -0
- data/lib/phlex/compiler/file_compiler.rb +14 -8
- data/lib/phlex/compiler/method_compiler.rb +121 -133
- data/lib/phlex/compiler.rb +43 -2
- data/lib/phlex/sgml.rb +14 -0
- data/lib/phlex/version.rb +1 -1
- data/lib/phlex.rb +2 -0
- metadata +2 -2
- data/lib/phlex/compiler/compilation.rb +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 01002f30f11a82c8fce49ec63ce50cd3947c40a50d66c9fd02123c87a89f434c
|
4
|
+
data.tar.gz: 0b40acfa20d82bf9c7e6bb68c8aeca447731d56436b2876750bfc669e9ba52a4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68d5a712386d7da44bb013ee956dde702d6e9f68e1cc237aac8a706a27cbff312dfd81a03405c9330f3109b87e7ff312711cf07a2e022ae1a256d984d60062cb
|
7
|
+
data.tar.gz: 9dd429c7d0a3d0b962ca1d6b653abd79260134c743f6322e87e90d3af200b188695cf8a2e3a6588ba2d731f6227f0c1ef1bb45b1bfd37f9ae2d6b02764a93d3a
|
@@ -1,23 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Phlex::Compiler::ClassCompiler < Refract::Visitor
|
4
|
-
def initialize(
|
4
|
+
def initialize(component, path)
|
5
5
|
super()
|
6
|
-
@
|
6
|
+
@component = component
|
7
|
+
@path = path
|
7
8
|
@compiled_snippets = []
|
8
9
|
end
|
9
10
|
|
10
11
|
def compile(node)
|
11
12
|
visit(node.body)
|
12
|
-
@compiled_snippets.freeze
|
13
|
+
@compiled_snippets.compact.freeze
|
13
14
|
end
|
14
15
|
|
15
16
|
visit Refract::DefNode do |node|
|
16
17
|
return if node.name == :initialize
|
17
18
|
return if node.receiver
|
18
19
|
|
20
|
+
method = begin
|
21
|
+
Phlex::UNBOUND_INSTANCE_METHOD_METHOD.bind_call(@component, node.name)
|
22
|
+
rescue NameError
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
|
26
|
+
return unless method
|
27
|
+
path, lineno = method.source_location
|
28
|
+
return unless @path == path
|
29
|
+
return unless node.start_line == lineno
|
30
|
+
|
19
31
|
@compiled_snippets << Phlex::Compiler::MethodCompiler.new(
|
20
|
-
@
|
32
|
+
@component
|
21
33
|
).compile(node)
|
22
34
|
end
|
23
35
|
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Phlex::Compiler::Compactor < Refract::MutationVisitor
|
4
|
+
visit Refract::StatementsNode do |node|
|
5
|
+
queue = []
|
6
|
+
results = []
|
7
|
+
current_buffer = nil
|
8
|
+
nil_context = false
|
9
|
+
|
10
|
+
node.body.reverse_each { |n| queue << n }
|
11
|
+
|
12
|
+
while (child_node = queue.pop)
|
13
|
+
case child_node
|
14
|
+
when Refract::StatementsNode
|
15
|
+
child_node.body.reverse_each { |n| queue << n }
|
16
|
+
when Phlex::Compiler::Concat
|
17
|
+
if current_buffer
|
18
|
+
current_buffer << child_node.node
|
19
|
+
unless nil_context
|
20
|
+
results << Refract::NilNode.new
|
21
|
+
nil_context = true
|
22
|
+
end
|
23
|
+
else
|
24
|
+
current_buffer = [child_node.node]
|
25
|
+
results << Refract::ParenthesesNode.new(
|
26
|
+
body: Refract::StatementsNode.new(
|
27
|
+
body: [
|
28
|
+
Refract::IfNode.new(
|
29
|
+
inline: false,
|
30
|
+
predicate: Refract::LocalVariableReadNode.new(
|
31
|
+
name: :__phlex_should_render__
|
32
|
+
),
|
33
|
+
statements: Refract::StatementsNode.new(
|
34
|
+
body: [
|
35
|
+
Refract::CallNode.new(
|
36
|
+
receiver: Refract::CallNode.new(
|
37
|
+
name: :__phlex_buffer__,
|
38
|
+
),
|
39
|
+
name: :<<,
|
40
|
+
arguments: Refract::ArgumentsNode.new(
|
41
|
+
arguments: [
|
42
|
+
Refract::InterpolatedStringNode.new(
|
43
|
+
parts: current_buffer
|
44
|
+
),
|
45
|
+
]
|
46
|
+
)
|
47
|
+
),
|
48
|
+
]
|
49
|
+
)
|
50
|
+
),
|
51
|
+
Refract::NilNode.new,
|
52
|
+
]
|
53
|
+
)
|
54
|
+
)
|
55
|
+
nil_context = true
|
56
|
+
end
|
57
|
+
else
|
58
|
+
resolved = visit(child_node)
|
59
|
+
case resolved
|
60
|
+
when Refract::StatementsNode
|
61
|
+
resolved.body.reverse_each { |n| queue << n }
|
62
|
+
else
|
63
|
+
current_buffer = nil
|
64
|
+
results << resolved
|
65
|
+
nil_context = false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
node.copy(
|
71
|
+
body: results
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
@@ -3,16 +3,16 @@
|
|
3
3
|
class Phlex::Compiler::FileCompiler < Refract::Visitor
|
4
4
|
Result = Data.define(:namespace, :compiled_snippets)
|
5
5
|
|
6
|
-
def initialize(
|
6
|
+
def initialize(path)
|
7
7
|
super()
|
8
|
-
@
|
8
|
+
@path = path
|
9
9
|
@current_namespace = []
|
10
|
+
@results = []
|
10
11
|
end
|
11
12
|
|
12
13
|
def compile(node)
|
13
|
-
|
14
|
-
|
15
|
-
end
|
14
|
+
visit(node)
|
15
|
+
@results.freeze
|
16
16
|
end
|
17
17
|
|
18
18
|
visit Refract::ModuleNode do |node|
|
@@ -24,10 +24,16 @@ class Phlex::Compiler::FileCompiler < Refract::Visitor
|
|
24
24
|
visit Refract::ClassNode do |node|
|
25
25
|
@current_namespace.push(node)
|
26
26
|
|
27
|
-
|
28
|
-
|
27
|
+
namespace = @current_namespace.map do |node|
|
28
|
+
Refract::Formatter.new.format_node(node.constant_path).source
|
29
|
+
end.join("::")
|
30
|
+
|
31
|
+
const = eval(namespace, TOPLEVEL_BINDING)
|
32
|
+
|
33
|
+
if Class === const && Phlex::SGML > const
|
34
|
+
@results << Result.new(
|
29
35
|
namespace: @current_namespace.dup.freeze,
|
30
|
-
compiled_snippets: Phlex::Compiler::ClassCompiler.new(@
|
36
|
+
compiled_snippets: Phlex::Compiler::ClassCompiler.new(const, @path).compile(node)
|
31
37
|
)
|
32
38
|
else
|
33
39
|
super(node)
|
@@ -7,22 +7,20 @@ module Phlex::Compiler
|
|
7
7
|
def initialize(component)
|
8
8
|
super()
|
9
9
|
@component = component
|
10
|
-
@current_buffer = nil
|
11
10
|
@preamble = []
|
11
|
+
@optimized = false
|
12
12
|
end
|
13
13
|
|
14
14
|
def compile(node)
|
15
|
-
visit(node)
|
16
|
-
end
|
17
|
-
|
18
|
-
def around_visit(node)
|
19
|
-
result = super
|
20
|
-
|
21
|
-
# We want to clear the buffer when there’s a node that isn’t a statements node,
|
22
|
-
# but we should ignore nils, which are usually other buffers.
|
23
|
-
clear_buffer unless result in Refract::StatementsNode | nil
|
15
|
+
tree = visit(node)
|
24
16
|
|
25
|
-
|
17
|
+
if @optimized
|
18
|
+
Compactor.new.visit(
|
19
|
+
tree
|
20
|
+
)
|
21
|
+
else
|
22
|
+
nil
|
23
|
+
end
|
26
24
|
end
|
27
25
|
|
28
26
|
visit Refract::ClassNode do |node|
|
@@ -36,14 +34,49 @@ module Phlex::Compiler
|
|
36
34
|
visit Refract::DefNode do |node|
|
37
35
|
if @stack.size == 1
|
38
36
|
node.copy(
|
39
|
-
body: Refract::
|
40
|
-
|
41
|
-
|
42
|
-
|
37
|
+
body: Refract::BeginNode.new(
|
38
|
+
statements: Refract::StatementsNode.new(
|
39
|
+
body: [
|
40
|
+
Refract::StatementsNode.new(
|
41
|
+
body: @preamble
|
42
|
+
),
|
43
|
+
Refract::NilNode.new,
|
44
|
+
visit(node.body),
|
45
|
+
]
|
46
|
+
),
|
47
|
+
rescue_clause: Refract::RescueNode.new(
|
48
|
+
exceptions: [],
|
49
|
+
reference: Refract::LocalVariableTargetNode.new(
|
50
|
+
name: :__phlex_exception__
|
43
51
|
),
|
44
|
-
Refract::
|
45
|
-
|
46
|
-
|
52
|
+
statements: Refract::StatementsNode.new(
|
53
|
+
body: [
|
54
|
+
Refract::CallNode.new(
|
55
|
+
receiver: Refract::ConstantReadNode.new(
|
56
|
+
name: :Kernel
|
57
|
+
),
|
58
|
+
name: :raise,
|
59
|
+
arguments: Refract::ArgumentsNode.new(
|
60
|
+
arguments: [
|
61
|
+
Refract::CallNode.new(
|
62
|
+
name: :__map_exception__,
|
63
|
+
arguments: Refract::ArgumentsNode.new(
|
64
|
+
arguments: [
|
65
|
+
Refract::LocalVariableReadNode.new(
|
66
|
+
name: :__phlex_exception__
|
67
|
+
),
|
68
|
+
]
|
69
|
+
)
|
70
|
+
),
|
71
|
+
]
|
72
|
+
)
|
73
|
+
),
|
74
|
+
]
|
75
|
+
),
|
76
|
+
subsequent: nil
|
77
|
+
),
|
78
|
+
else_clause: nil,
|
79
|
+
ensure_clause: nil
|
47
80
|
)
|
48
81
|
)
|
49
82
|
else
|
@@ -76,11 +109,15 @@ module Phlex::Compiler
|
|
76
109
|
end
|
77
110
|
|
78
111
|
visit Refract::BlockNode do |node|
|
79
|
-
node.
|
80
|
-
|
81
|
-
|
112
|
+
if node.body
|
113
|
+
node.copy(
|
114
|
+
body: compile_block_body_node(
|
115
|
+
node.body
|
116
|
+
)
|
82
117
|
)
|
83
|
-
|
118
|
+
else
|
119
|
+
node
|
120
|
+
end
|
84
121
|
end
|
85
122
|
|
86
123
|
def compile_standard_element(node, tag)
|
@@ -88,19 +125,19 @@ module Phlex::Compiler
|
|
88
125
|
|
89
126
|
Refract::StatementsNode.new(
|
90
127
|
body: [
|
91
|
-
|
128
|
+
raw("<#{tag}"),
|
92
129
|
*(
|
93
130
|
if node.arguments
|
94
131
|
compile_phlex_attributes(node.arguments)
|
95
132
|
end
|
96
133
|
),
|
97
|
-
|
134
|
+
raw(">"),
|
98
135
|
*(
|
99
136
|
if node.block
|
100
137
|
compile_phlex_block(node.block)
|
101
138
|
end
|
102
139
|
),
|
103
|
-
|
140
|
+
raw("</#{tag}>"),
|
104
141
|
]
|
105
142
|
)
|
106
143
|
end
|
@@ -110,13 +147,13 @@ module Phlex::Compiler
|
|
110
147
|
|
111
148
|
Refract::StatementsNode.new(
|
112
149
|
body: [
|
113
|
-
|
150
|
+
raw("<#{tag}"),
|
114
151
|
*(
|
115
152
|
if node.arguments
|
116
153
|
compile_phlex_attributes(node.arguments)
|
117
154
|
end
|
118
155
|
),
|
119
|
-
|
156
|
+
raw(">"),
|
120
157
|
]
|
121
158
|
)
|
122
159
|
end
|
@@ -131,17 +168,16 @@ module Phlex::Compiler
|
|
131
168
|
end
|
132
169
|
|
133
170
|
if literal_attributes
|
134
|
-
return
|
171
|
+
return raw(
|
135
172
|
Phlex::SGML::Attributes.generate_attributes(
|
136
173
|
eval(
|
137
|
-
"{#{Refract::Formatter.new.format_node(node)}}"
|
174
|
+
"{#{Refract::Formatter.new.format_node(node).source}}",
|
175
|
+
TOPLEVEL_BINDING
|
138
176
|
)
|
139
177
|
)
|
140
178
|
)
|
141
179
|
end
|
142
180
|
|
143
|
-
clear_buffer
|
144
|
-
|
145
181
|
Refract::CallNode.new(
|
146
182
|
name: :__render_attributes__,
|
147
183
|
arguments: Refract::ArgumentsNode.new(
|
@@ -162,7 +198,7 @@ module Phlex::Compiler
|
|
162
198
|
content = node.body.body.first
|
163
199
|
case content
|
164
200
|
when Refract::StringNode, Refract::SymbolNode
|
165
|
-
return
|
201
|
+
return plain(content.unescaped)
|
166
202
|
when Refract::InterpolatedStringNode
|
167
203
|
return compile_interpolated_string_node(content)
|
168
204
|
when Refract::NilNode
|
@@ -173,7 +209,6 @@ module Phlex::Compiler
|
|
173
209
|
end
|
174
210
|
end
|
175
211
|
|
176
|
-
clear_buffer
|
177
212
|
Refract::CallNode.new(
|
178
213
|
name: :__yield_content__,
|
179
214
|
block: node
|
@@ -181,7 +216,7 @@ module Phlex::Compiler
|
|
181
216
|
end
|
182
217
|
|
183
218
|
def compile_block_body_node(node)
|
184
|
-
node => Refract::StatementsNode
|
219
|
+
node => Refract::StatementsNode | Refract::BeginNode
|
185
220
|
|
186
221
|
Refract::StatementsNode.new(
|
187
222
|
body: [
|
@@ -216,7 +251,7 @@ module Phlex::Compiler
|
|
216
251
|
body: node.parts.map do |part|
|
217
252
|
case part
|
218
253
|
when Refract::StringNode
|
219
|
-
|
254
|
+
plain(part.unescaped)
|
220
255
|
when Refract::EmbeddedVariableNode
|
221
256
|
interpolate(part.variable)
|
222
257
|
when Refract::EmbeddedStatementsNode
|
@@ -234,27 +269,27 @@ module Phlex::Compiler
|
|
234
269
|
if node.block
|
235
270
|
Refract::StatementsNode.new(
|
236
271
|
body: [
|
237
|
-
|
272
|
+
raw(" "),
|
238
273
|
compile_phlex_block(node.block),
|
239
|
-
|
274
|
+
raw(" "),
|
240
275
|
]
|
241
276
|
)
|
242
277
|
else
|
243
|
-
|
278
|
+
raw(" ")
|
244
279
|
end
|
245
280
|
end
|
246
281
|
|
247
282
|
def compile_doctype_helper(node)
|
248
283
|
node => Refract::CallNode
|
249
284
|
|
250
|
-
|
285
|
+
raw("<!doctype html>")
|
251
286
|
end
|
252
287
|
|
253
288
|
def compile_plain_helper(node)
|
254
289
|
node => Refract::CallNode
|
255
290
|
|
256
|
-
if node.arguments in [Refract::StringNode]
|
257
|
-
|
291
|
+
if node.arguments.arguments in [Refract::StringNode]
|
292
|
+
raw(node.arguments.arguments.first.unescaped)
|
258
293
|
else
|
259
294
|
node
|
260
295
|
end
|
@@ -306,51 +341,53 @@ module Phlex::Compiler
|
|
306
341
|
|
307
342
|
Refract::StatementsNode.new(
|
308
343
|
body: [
|
309
|
-
|
344
|
+
raw("<!-- "),
|
310
345
|
compile_phlex_block(node.block),
|
311
|
-
|
346
|
+
raw(" -->"),
|
312
347
|
]
|
313
348
|
)
|
314
349
|
end
|
315
350
|
|
316
351
|
def compile_raw_helper(node)
|
317
352
|
node => Refract::CallNode
|
318
|
-
|
319
353
|
node
|
320
354
|
end
|
321
355
|
|
322
|
-
private def
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
)
|
356
|
+
private def plain(value)
|
357
|
+
value => String
|
358
|
+
raw(Phlex::Escape.html_escape(value))
|
359
|
+
end
|
327
360
|
|
328
|
-
|
329
|
-
|
330
|
-
new_buffer = [
|
331
|
-
Refract::StringNode.new(
|
332
|
-
unescaped: value
|
333
|
-
),
|
334
|
-
]
|
361
|
+
private def raw(value)
|
362
|
+
value => String
|
335
363
|
|
336
|
-
|
364
|
+
buffer(
|
365
|
+
Refract::StringNode.new(
|
366
|
+
unescaped: value
|
367
|
+
)
|
368
|
+
)
|
369
|
+
end
|
337
370
|
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
name: should_render_local
|
342
|
-
),
|
371
|
+
private def interpolate(statements)
|
372
|
+
buffer(
|
373
|
+
Refract::EmbeddedStatementsNode.new(
|
343
374
|
statements: Refract::StatementsNode.new(
|
344
375
|
body: [
|
345
376
|
Refract::CallNode.new(
|
346
|
-
receiver: Refract::
|
347
|
-
|
377
|
+
receiver: Refract::ConstantPathNode.new(
|
378
|
+
parent: Refract::ConstantPathNode.new(
|
379
|
+
name: "Phlex"
|
380
|
+
),
|
381
|
+
name: "Escape"
|
348
382
|
),
|
349
|
-
name:
|
383
|
+
name: :html_escape,
|
350
384
|
arguments: Refract::ArgumentsNode.new(
|
351
385
|
arguments: [
|
352
|
-
Refract::
|
353
|
-
|
386
|
+
Refract::CallNode.new(
|
387
|
+
receiver: Refract::ParenthesesNode.new(
|
388
|
+
body: statements
|
389
|
+
),
|
390
|
+
name: :to_s
|
354
391
|
),
|
355
392
|
]
|
356
393
|
)
|
@@ -358,76 +395,27 @@ module Phlex::Compiler
|
|
358
395
|
]
|
359
396
|
)
|
360
397
|
)
|
361
|
-
end
|
362
|
-
end
|
363
|
-
|
364
|
-
private def interpolate(statements, escape: true)
|
365
|
-
embedded_statement = Refract::EmbeddedStatementsNode.new(
|
366
|
-
statements: Refract::StatementsNode.new(
|
367
|
-
body: [
|
368
|
-
Refract::CallNode.new(
|
369
|
-
receiver: Refract::ConstantPathNode.new(
|
370
|
-
parent: Refract::ConstantPathNode.new(
|
371
|
-
name: "Phlex"
|
372
|
-
),
|
373
|
-
name: "Escape"
|
374
|
-
),
|
375
|
-
name: :html_escape,
|
376
|
-
arguments: Refract::ArgumentsNode.new(
|
377
|
-
arguments: [
|
378
|
-
Refract::CallNode.new(
|
379
|
-
receiver: Refract::ParenthesesNode.new(
|
380
|
-
body: statements
|
381
|
-
),
|
382
|
-
name: :to_s
|
383
|
-
),
|
384
|
-
]
|
385
|
-
)
|
386
|
-
),
|
387
|
-
]
|
388
|
-
)
|
389
398
|
)
|
399
|
+
end
|
390
400
|
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
nil
|
395
|
-
else
|
396
|
-
new_buffer = [embedded_statement]
|
401
|
+
private def buffer(node)
|
402
|
+
@optimized = true
|
403
|
+
node => Refract::StringNode | Refract::EmbeddedStatementsNode
|
397
404
|
|
398
|
-
|
405
|
+
should_render_local
|
406
|
+
buffer_local
|
399
407
|
|
400
|
-
|
401
|
-
|
402
|
-
|
408
|
+
Refract::StatementsNode.new(
|
409
|
+
body: [
|
410
|
+
Concat.new(
|
411
|
+
node
|
403
412
|
),
|
404
|
-
|
405
|
-
|
406
|
-
Refract::CallNode.new(
|
407
|
-
receiver: Refract::CallNode.new(
|
408
|
-
name: buffer_local,
|
409
|
-
),
|
410
|
-
name: :<<,
|
411
|
-
arguments: Refract::ArgumentsNode.new(
|
412
|
-
arguments: [
|
413
|
-
Refract::InterpolatedStringNode.new(
|
414
|
-
parts: new_buffer
|
415
|
-
),
|
416
|
-
]
|
417
|
-
)
|
418
|
-
),
|
419
|
-
]
|
420
|
-
)
|
421
|
-
)
|
422
|
-
end
|
423
|
-
end
|
424
|
-
|
425
|
-
private def clear_buffer
|
426
|
-
@current_buffer = nil
|
413
|
+
]
|
414
|
+
)
|
427
415
|
end
|
428
416
|
|
429
417
|
private def output_block?(node)
|
430
|
-
node.body
|
418
|
+
node.body&.body&.any? do |child|
|
431
419
|
Refract::CallNode === child && (
|
432
420
|
standard_element?(child) ||
|
433
421
|
void_element?(child) ||
|
@@ -439,13 +427,13 @@ module Phlex::Compiler
|
|
439
427
|
end
|
440
428
|
|
441
429
|
private def static_content_block?(node)
|
442
|
-
return false unless node.body
|
430
|
+
return false unless node.body&.body&.length == 1
|
443
431
|
node.body.body.first in Refract::StringNode | Refract::InterpolatedStringNode | Refract::SymbolNode | Refract::NilNode
|
444
432
|
end
|
445
433
|
|
446
434
|
private def standard_element?(node)
|
447
435
|
if (tag = Phlex::HTML::StandardElements.__registered_elements__[node.name]) &&
|
448
|
-
(Phlex::HTML::StandardElements == @component
|
436
|
+
(Phlex::HTML::StandardElements == Phlex::UNBOUND_INSTANCE_METHOD_METHOD.bind_call(@component, node.name).owner)
|
449
437
|
|
450
438
|
tag
|
451
439
|
else
|
@@ -455,7 +443,7 @@ module Phlex::Compiler
|
|
455
443
|
|
456
444
|
private def void_element?(node)
|
457
445
|
if (tag = Phlex::HTML::VoidElements.__registered_elements__[node.name]) &&
|
458
|
-
(Phlex::HTML::VoidElements == @component
|
446
|
+
(Phlex::HTML::VoidElements == Phlex::UNBOUND_INSTANCE_METHOD_METHOD.bind_call(@component, node.name).owner)
|
459
447
|
|
460
448
|
tag
|
461
449
|
else
|
@@ -521,7 +509,7 @@ module Phlex::Compiler
|
|
521
509
|
|
522
510
|
ALLOWED_OWNERS = Set[Phlex::SGML, Phlex::HTML, Phlex::SVG]
|
523
511
|
private def own_method_without_scope?(node)
|
524
|
-
ALLOWED_OWNERS.include?(@component
|
512
|
+
ALLOWED_OWNERS.include?(Phlex::UNBOUND_INSTANCE_METHOD_METHOD.bind_call(@component, node.name).owner)
|
525
513
|
end
|
526
514
|
|
527
515
|
private def state_local
|
data/lib/phlex/compiler.rb
CHANGED
@@ -4,15 +4,56 @@ require "prism"
|
|
4
4
|
require "refract"
|
5
5
|
|
6
6
|
module Phlex::Compiler
|
7
|
+
MAP = {}
|
8
|
+
DEPENDENCIES = {}
|
9
|
+
|
7
10
|
Error = Class.new(StandardError)
|
8
11
|
|
12
|
+
Concat = Data.define(:node) do
|
13
|
+
def start_line = nil
|
14
|
+
def accept(visitor) = self
|
15
|
+
end
|
16
|
+
|
9
17
|
def self.compile(component)
|
10
18
|
path, line = Object.const_source_location(component.name)
|
11
|
-
|
19
|
+
compile_file(path)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.compile_file(path)
|
23
|
+
unless File.exist?(path)
|
24
|
+
raise ArgumentError, "Can’t compile #{path} because it doesn’t exist."
|
25
|
+
end
|
26
|
+
|
27
|
+
require(path)
|
28
|
+
|
12
29
|
source = File.read(path)
|
13
30
|
tree = Prism.parse(source).value
|
14
31
|
refract = Refract::Converter.new.visit(tree)
|
15
32
|
|
16
|
-
|
33
|
+
last_line = source.count("\n")
|
34
|
+
|
35
|
+
starting_line = last_line + 1
|
36
|
+
|
37
|
+
results = FileCompiler.new(path).compile(refract)
|
38
|
+
|
39
|
+
result = Refract::StatementsNode.new(
|
40
|
+
body: results.map do |result|
|
41
|
+
result.namespace.reverse_each.reduce(
|
42
|
+
result.compiled_snippets
|
43
|
+
) do |body, scope|
|
44
|
+
scope.copy(
|
45
|
+
body: Refract::StatementsNode.new(
|
46
|
+
body: [body]
|
47
|
+
)
|
48
|
+
)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
)
|
52
|
+
|
53
|
+
formatting_result = Refract::Formatter.new(starting_line:).format_node(result)
|
54
|
+
|
55
|
+
MAP[path] = formatting_result.source_map
|
56
|
+
|
57
|
+
eval("# frozen_string_literal: true\n#{formatting_result.source}", TOPLEVEL_BINDING, path, starting_line - 1)
|
17
58
|
end
|
18
59
|
end
|
data/lib/phlex/sgml.rb
CHANGED
@@ -481,4 +481,18 @@ class Phlex::SGML
|
|
481
481
|
path, line = instance_method(method_name).source_location
|
482
482
|
Phlex::Compiler::Method.new(self, path, line, method_name).compile
|
483
483
|
end
|
484
|
+
|
485
|
+
def __map_exception__(exception)
|
486
|
+
exception.set_backtrace(
|
487
|
+
exception.backtrace_locations.map do |loc|
|
488
|
+
if ((map = Phlex::Compiler::MAP[loc.path]) && (line = map[loc.lineno]))
|
489
|
+
"[Phlex] #{loc.path}:#{line}:#{loc.label}"
|
490
|
+
else
|
491
|
+
"#{loc.path}:#{loc.lineno}:#{loc.label}"
|
492
|
+
end
|
493
|
+
end
|
494
|
+
)
|
495
|
+
|
496
|
+
exception
|
497
|
+
end
|
484
498
|
end
|
data/lib/phlex/version.rb
CHANGED
data/lib/phlex.rb
CHANGED
@@ -27,6 +27,8 @@ module Phlex
|
|
27
27
|
CACHED_FILES = Set.new
|
28
28
|
ATTRIBUTE_CACHE = FIFO.new
|
29
29
|
|
30
|
+
UNBOUND_INSTANCE_METHOD_METHOD = Module.instance_method(:instance_method)
|
31
|
+
|
30
32
|
def self.__expand_attribute_cache__(file_path)
|
31
33
|
unless CACHED_FILES.include?(file_path)
|
32
34
|
CACHED_FILES << file_path
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: phlex
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.4.0.
|
4
|
+
version: 2.4.0.beta2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joel Drapper
|
@@ -50,7 +50,7 @@ files:
|
|
50
50
|
- lib/phlex.rb
|
51
51
|
- lib/phlex/compiler.rb
|
52
52
|
- lib/phlex/compiler/class_compiler.rb
|
53
|
-
- lib/phlex/compiler/
|
53
|
+
- lib/phlex/compiler/compactor.rb
|
54
54
|
- lib/phlex/compiler/file_compiler.rb
|
55
55
|
- lib/phlex/compiler/method_compiler.rb
|
56
56
|
- lib/phlex/csv.rb
|
@@ -1,45 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Phlex::Compiler
|
4
|
-
class Compilation
|
5
|
-
def initialize(component, path, line, source, tree)
|
6
|
-
@component = component
|
7
|
-
@path = path
|
8
|
-
@line = line
|
9
|
-
@source = source
|
10
|
-
@tree = tree
|
11
|
-
freeze
|
12
|
-
end
|
13
|
-
|
14
|
-
attr_reader :component, :line, :source, :path
|
15
|
-
|
16
|
-
def compile
|
17
|
-
result = FileCompiler.new(self).compile(@tree)
|
18
|
-
|
19
|
-
result.compiled_snippets.each do |snippet|
|
20
|
-
start_line = snippet.start_line
|
21
|
-
|
22
|
-
namespaced = result.namespace.reverse_each.reduce(snippet) do |body, scope|
|
23
|
-
start_line -= 1
|
24
|
-
|
25
|
-
scope.copy(
|
26
|
-
body: Refract::StatementsNode.new(
|
27
|
-
body: [body]
|
28
|
-
)
|
29
|
-
)
|
30
|
-
end
|
31
|
-
|
32
|
-
source = Refract::Formatter.new.format_node(namespaced)
|
33
|
-
|
34
|
-
redefine_method(
|
35
|
-
source,
|
36
|
-
start_line
|
37
|
-
)
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
def redefine_method(source, line)
|
42
|
-
eval("# frozen_string_literal: true\n#{source}", TOPLEVEL_BINDING, @path, line - 1)
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|