+107
-142
src/ast.rs
+107
-142
src/ast.rs
···
13
13
use tree_sitter::Language;
14
14
use tree_sitter::Query;
15
15
16
-
use crate::Context;
17
-
use crate::DisplayWithContext;
18
16
use crate::Identifier;
19
17
use crate::Location;
20
18
···
73
71
ForIn(ForIn),
74
72
}
75
73
76
-
impl DisplayWithContext for Statement {
77
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
74
+
impl std::fmt::Display for Statement {
75
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
78
76
match self {
79
-
Statement::DeclareImmutable(stmt) => stmt.fmt(f, ctx),
80
-
Statement::DeclareMutable(stmt) => stmt.fmt(f, ctx),
81
-
Statement::Assign(stmt) => stmt.fmt(f, ctx),
82
-
Statement::CreateGraphNode(stmt) => stmt.fmt(f, ctx),
83
-
Statement::AddGraphNodeAttribute(stmt) => stmt.fmt(f, ctx),
84
-
Statement::CreateEdge(stmt) => stmt.fmt(f, ctx),
85
-
Statement::AddEdgeAttribute(stmt) => stmt.fmt(f, ctx),
86
-
Statement::Scan(stmt) => stmt.fmt(f, ctx),
87
-
Statement::Print(stmt) => stmt.fmt(f, ctx),
88
-
Statement::If(stmt) => stmt.fmt(f, ctx),
89
-
Statement::ForIn(stmt) => stmt.fmt(f, ctx),
77
+
Self::DeclareImmutable(stmt) => stmt.fmt(f),
78
+
Self::DeclareMutable(stmt) => stmt.fmt(f),
79
+
Self::Assign(stmt) => stmt.fmt(f),
80
+
Self::CreateGraphNode(stmt) => stmt.fmt(f),
81
+
Self::AddGraphNodeAttribute(stmt) => stmt.fmt(f),
82
+
Self::CreateEdge(stmt) => stmt.fmt(f),
83
+
Self::AddEdgeAttribute(stmt) => stmt.fmt(f),
84
+
Self::Scan(stmt) => stmt.fmt(f),
85
+
Self::Print(stmt) => stmt.fmt(f),
86
+
Self::If(stmt) => stmt.fmt(f),
87
+
Self::ForIn(stmt) => stmt.fmt(f),
90
88
}
91
89
}
92
90
}
···
106
104
}
107
105
}
108
106
109
-
impl DisplayWithContext for AddEdgeAttribute {
110
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
111
-
write!(
112
-
f,
113
-
"attr ({} -> {})",
114
-
self.source.display_with(ctx),
115
-
self.sink.display_with(ctx),
116
-
)?;
107
+
impl std::fmt::Display for AddEdgeAttribute {
108
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
109
+
write!(f, "attr ({} -> {})", self.source, self.sink)?;
117
110
for attr in &self.attributes {
118
-
write!(f, " {}", attr.display_with(ctx))?;
111
+
write!(f, " {}", attr)?;
119
112
}
120
113
write!(f, " at {}", self.location)
121
114
}
···
135
128
}
136
129
}
137
130
138
-
impl DisplayWithContext for AddGraphNodeAttribute {
139
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
140
-
write!(f, "attr ({})", self.node.display_with(ctx),)?;
131
+
impl std::fmt::Display for AddGraphNodeAttribute {
132
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
133
+
write!(f, "attr ({})", self.node)?;
141
134
for attr in &self.attributes {
142
-
write!(f, " {}", attr.display_with(ctx),)?;
135
+
write!(f, " {}", attr)?;
143
136
}
144
137
write!(f, " at {}", self.location)
145
138
}
···
159
152
}
160
153
}
161
154
162
-
impl DisplayWithContext for Assign {
163
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
155
+
impl std::fmt::Display for Assign {
156
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
164
157
write!(
165
158
f,
166
159
"set {} = {} at {}",
167
-
self.variable.display_with(ctx),
168
-
self.value.display_with(ctx),
169
-
self.location,
160
+
self.variable, self.value, self.location,
170
161
)
171
162
}
172
163
}
···
178
169
pub value: Expression,
179
170
}
180
171
181
-
impl DisplayWithContext for Attribute {
182
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
183
-
write!(
184
-
f,
185
-
"{} = {}",
186
-
self.name.display_with(ctx),
187
-
self.value.display_with(ctx),
188
-
)
172
+
impl std::fmt::Display for Attribute {
173
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
174
+
write!(f, "{} = {}", self.name, self.value)
189
175
}
190
176
}
191
177
···
203
189
}
204
190
}
205
191
206
-
impl DisplayWithContext for CreateEdge {
207
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
192
+
impl std::fmt::Display for CreateEdge {
193
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
208
194
write!(
209
195
f,
210
196
"edge {} -> {} at {}",
211
-
self.source.display_with(ctx),
212
-
self.sink.display_with(ctx),
213
-
self.location,
197
+
self.source, self.sink, self.location,
214
198
)
215
199
}
216
200
}
···
228
212
}
229
213
}
230
214
231
-
impl DisplayWithContext for CreateGraphNode {
232
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
233
-
write!(
234
-
f,
235
-
"node {} at {}",
236
-
self.node.display_with(ctx),
237
-
self.location
238
-
)
215
+
impl std::fmt::Display for CreateGraphNode {
216
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
217
+
write!(f, "node {} at {}", self.node, self.location)
239
218
}
240
219
}
241
220
···
253
232
}
254
233
}
255
234
256
-
impl DisplayWithContext for DeclareImmutable {
257
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
235
+
impl std::fmt::Display for DeclareImmutable {
236
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
258
237
write!(
259
238
f,
260
239
"let {} = {} at {}",
261
-
self.variable.display_with(ctx),
262
-
self.value.display_with(ctx),
263
-
self.location,
240
+
self.variable, self.value, self.location,
264
241
)
265
242
}
266
243
}
···
279
256
}
280
257
}
281
258
282
-
impl DisplayWithContext for DeclareMutable {
283
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
259
+
impl std::fmt::Display for DeclareMutable {
260
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
284
261
write!(
285
262
f,
286
263
"var {} = {} at {}",
287
-
self.variable.display_with(ctx),
288
-
self.value.display_with(ctx),
289
-
self.location,
264
+
self.variable, self.value, self.location,
290
265
)
291
266
}
292
267
}
···
304
279
}
305
280
}
306
281
307
-
impl DisplayWithContext for Print {
308
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
282
+
impl std::fmt::Display for Print {
283
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
309
284
write!(f, "print")?;
310
285
for val in &self.values {
311
-
write!(f, " {},", val.display_with(ctx),)?;
286
+
write!(f, " {},", val)?;
312
287
}
313
288
write!(f, " at {}", self.location)
314
289
}
···
328
303
}
329
304
}
330
305
331
-
impl DisplayWithContext for Scan {
332
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
333
-
write!(
334
-
f,
335
-
"scan {} {{ ... }} at {}",
336
-
self.value.display_with(ctx),
337
-
self.location
338
-
)
306
+
impl std::fmt::Display for Scan {
307
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
308
+
write!(f, "scan {} {{ ... }} at {}", self.value, self.location)
339
309
}
340
310
}
341
311
···
355
325
}
356
326
}
357
327
358
-
impl DisplayWithContext for ScanArm {
359
-
fn fmt(&self, f: &mut fmt::Formatter, _ctx: &Context) -> fmt::Result {
328
+
impl std::fmt::Display for ScanArm {
329
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
360
330
write!(f, "{:?} {{ ... }}", self.regex.as_str())
361
331
}
362
332
}
···
374
344
}
375
345
}
376
346
377
-
impl DisplayWithContext for If {
378
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
347
+
impl std::fmt::Display for If {
348
+
fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
379
349
let mut first = true;
380
350
for arm in &self.arms {
381
351
if first {
382
352
first = false;
383
-
write!(f, "if {} {{ ... }}", arm.conditions.display_with(ctx))?;
353
+
write!(f, "if {} {{ ... }}", DisplayConditions(&arm.conditions))?;
384
354
} else {
385
355
if !arm.conditions.is_empty() {
386
-
write!(f, " elif {} {{ ... }}", arm.conditions.display_with(ctx))?;
356
+
write!(f, " elif {} {{ ... }}", DisplayConditions(&arm.conditions))?;
387
357
} else {
388
358
write!(f, " else {{ ... }}")?;
389
359
}
···
401
371
pub location: Location,
402
372
}
403
373
374
+
struct DisplayConditions<'a>(&'a Vec<Condition>);
375
+
404
376
#[derive(Debug, PartialEq, Eq)]
405
377
pub enum Condition {
406
378
Some {
···
417
389
},
418
390
}
419
391
420
-
impl DisplayWithContext for Vec<Condition> {
421
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
392
+
impl std::fmt::Display for DisplayConditions<'_> {
393
+
fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
422
394
let mut first = true;
423
-
for condition in self.iter() {
395
+
for condition in self.0.iter() {
424
396
if first {
425
397
first = false;
426
-
write!(f, "{}", condition.display_with(ctx))?;
398
+
write!(f, "{}", condition)?;
427
399
} else {
428
-
write!(f, ", {}", condition.display_with(ctx))?;
400
+
write!(f, ", {}", condition)?;
429
401
}
430
402
}
431
403
Ok(())
432
404
}
433
405
}
434
406
435
-
impl DisplayWithContext for Condition {
436
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
407
+
impl std::fmt::Display for Condition {
408
+
fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
437
409
match self {
438
410
Condition::Some { value, .. } => {
439
-
write!(f, "some {}", value.display_with(ctx))
411
+
write!(f, "some {}", value)
440
412
}
441
413
Condition::None { value, .. } => {
442
-
write!(f, "none {}", value.display_with(ctx))
414
+
write!(f, "none {}", value)
443
415
}
444
416
Condition::Bool { value, .. } => {
445
-
write!(f, "{}", value.display_with(ctx))
417
+
write!(f, "{}", value)
446
418
}
447
419
}
448
420
}
···
463
435
}
464
436
}
465
437
466
-
impl DisplayWithContext for ForIn {
467
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
438
+
impl std::fmt::Display for ForIn {
439
+
fn fmt(&self, f: &mut fmt::Formatter) -> std::fmt::Result {
468
440
write!(
469
441
f,
470
442
"for {} in {} {{ ... }} at {}",
471
-
self.variable.display_with(ctx),
472
-
self.value.display_with(ctx),
473
-
self.location,
443
+
self.variable, self.value, self.location,
474
444
)
475
445
}
476
446
}
···
482
452
Unscoped(UnscopedVariable),
483
453
}
484
454
485
-
impl DisplayWithContext for Variable {
486
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
455
+
impl std::fmt::Display for Variable {
456
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
487
457
match self {
488
-
Variable::Scoped(variable) => variable.fmt(f, ctx),
489
-
Variable::Unscoped(variable) => variable.fmt(f, ctx),
458
+
Variable::Scoped(variable) => variable.fmt(f),
459
+
Variable::Unscoped(variable) => variable.fmt(f),
490
460
}
491
461
}
492
462
}
···
505
475
}
506
476
}
507
477
508
-
impl DisplayWithContext for ScopedVariable {
509
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
510
-
write!(
511
-
f,
512
-
"{}.{}",
513
-
self.scope.display_with(ctx),
514
-
self.name.display_with(ctx),
515
-
)
478
+
impl std::fmt::Display for ScopedVariable {
479
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
480
+
write!(f, "{}.{}", self.scope, self.name)
516
481
}
517
482
}
518
483
···
529
494
}
530
495
}
531
496
532
-
impl DisplayWithContext for UnscopedVariable {
533
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
534
-
write!(f, "{}", self.name.display_with(ctx))
497
+
impl std::fmt::Display for UnscopedVariable {
498
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
499
+
write!(f, "{}", self.name)
535
500
}
536
501
}
537
502
···
558
523
RegexCapture(RegexCapture),
559
524
}
560
525
561
-
impl DisplayWithContext for Expression {
562
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
526
+
impl std::fmt::Display for Expression {
527
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
563
528
match self {
564
529
Expression::FalseLiteral => write!(f, "false"),
565
530
Expression::NullLiteral => write!(f, "#null"),
566
531
Expression::TrueLiteral => write!(f, "true"),
567
-
Expression::IntegerConstant(expr) => expr.fmt(f, ctx),
568
-
Expression::StringConstant(expr) => expr.fmt(f, ctx),
569
-
Expression::List(expr) => expr.fmt(f, ctx),
570
-
Expression::Set(expr) => expr.fmt(f, ctx),
571
-
Expression::Capture(expr) => expr.fmt(f, ctx),
572
-
Expression::Variable(expr) => expr.fmt(f, ctx),
573
-
Expression::Call(expr) => expr.fmt(f, ctx),
574
-
Expression::RegexCapture(expr) => expr.fmt(f, ctx),
532
+
Expression::IntegerConstant(expr) => expr.fmt(f),
533
+
Expression::StringConstant(expr) => expr.fmt(f),
534
+
Expression::List(expr) => expr.fmt(f),
535
+
Expression::Set(expr) => expr.fmt(f),
536
+
Expression::Capture(expr) => expr.fmt(f),
537
+
Expression::Variable(expr) => expr.fmt(f),
538
+
Expression::Call(expr) => expr.fmt(f),
539
+
Expression::RegexCapture(expr) => expr.fmt(f),
575
540
}
576
541
}
577
542
}
···
589
554
}
590
555
}
591
556
592
-
impl DisplayWithContext for Call {
593
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
594
-
write!(f, "({}", self.function.display_with(ctx))?;
557
+
impl std::fmt::Display for Call {
558
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
559
+
write!(f, "({}", self.function)?;
595
560
for arg in &self.parameters {
596
-
write!(f, " {}", arg.display_with(ctx))?;
561
+
write!(f, " {}", arg)?;
597
562
}
598
563
write!(f, ")")
599
564
}
···
619
584
}
620
585
}
621
586
622
-
impl DisplayWithContext for Capture {
623
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
624
-
write!(f, "@{}", self.name.display_with(ctx))
587
+
impl std::fmt::Display for Capture {
588
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
589
+
write!(f, "@{}", self.name)
625
590
}
626
591
}
627
592
···
637
602
}
638
603
}
639
604
640
-
impl DisplayWithContext for IntegerConstant {
641
-
fn fmt(&self, f: &mut fmt::Formatter, _ctx: &Context) -> fmt::Result {
605
+
impl std::fmt::Display for IntegerConstant {
606
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
642
607
write!(f, "{}", self.value)
643
608
}
644
609
}
···
655
620
}
656
621
}
657
622
658
-
impl DisplayWithContext for ListComprehension {
659
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
623
+
impl std::fmt::Display for ListComprehension {
624
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
660
625
write!(f, "[")?;
661
626
let mut first = true;
662
627
for elem in &self.elements {
663
628
if first {
664
-
write!(f, "{}", elem.display_with(ctx))?;
629
+
write!(f, "{}", elem)?;
665
630
first = false;
666
631
} else {
667
-
write!(f, ", {}", elem.display_with(ctx))?;
632
+
write!(f, ", {}", elem)?;
668
633
}
669
634
}
670
635
write!(f, "]")
···
683
648
}
684
649
}
685
650
686
-
impl DisplayWithContext for RegexCapture {
687
-
fn fmt(&self, f: &mut fmt::Formatter, _ctx: &Context) -> fmt::Result {
651
+
impl std::fmt::Display for RegexCapture {
652
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
688
653
write!(f, "${}", self.match_index)
689
654
}
690
655
}
···
701
666
}
702
667
}
703
668
704
-
impl DisplayWithContext for SetComprehension {
705
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
669
+
impl std::fmt::Display for SetComprehension {
670
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
706
671
write!(f, "{{")?;
707
672
let mut first = true;
708
673
for elem in &self.elements {
709
674
if first {
710
-
write!(f, "{}", elem.display_with(ctx))?;
675
+
write!(f, "{}", elem)?;
711
676
first = false;
712
677
} else {
713
-
write!(f, ", {}", elem.display_with(ctx))?;
678
+
write!(f, ", {}", elem)?;
714
679
}
715
680
}
716
681
write!(f, "}}")
···
729
694
}
730
695
}
731
696
732
-
impl DisplayWithContext for StringConstant {
733
-
fn fmt(&self, f: &mut fmt::Formatter, _ctx: &Context) -> fmt::Result {
697
+
impl std::fmt::Display for StringConstant {
698
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
734
699
write!(f, "{:?}", self.value)
735
700
}
736
701
}
+8
-10
src/bin/tree-sitter-graph/main.rs
+8
-10
src/bin/tree-sitter-graph/main.rs
···
16
16
use tree_sitter_config::Config;
17
17
use tree_sitter_graph::ast::File;
18
18
use tree_sitter_graph::functions::Functions;
19
-
use tree_sitter_graph::Context;
20
19
use tree_sitter_graph::Variables;
21
20
use tree_sitter_loader::Loader;
22
21
···
68
67
let tree = parser
69
68
.parse(&source, None)
70
69
.ok_or_else(|| anyhow!("Could not parse {}", source_path.display()))?;
71
-
let mut ctx = Context::new();
72
-
let file = File::from_str(language, &mut ctx, &tsg)
73
-
.with_context(|| anyhow!("Error parsing TSG file {}", tsg_path.display()))?;
74
-
let mut functions = Functions::stdlib(&mut ctx);
70
+
let file = File::from_str(language, &tsg)
71
+
.with_context(|| format!("Error parsing TSG file {}", tsg_path.display()))?;
72
+
let mut functions = Functions::stdlib();
75
73
let globals = Variables::new();
76
74
let graph = if lazy {
77
-
file.execute_lazy(&mut ctx, &tree, &source, &mut functions, &globals)
75
+
file.execute_lazy(&tree, &source, &mut functions, &globals)
78
76
} else {
79
-
file.execute(&mut ctx, &tree, &source, &mut functions, &globals)
77
+
file.execute(&tree, &source, &mut functions, &globals)
80
78
}
81
-
.with_context(|| anyhow!("Could not execute TSG file {}", tsg_path.display()))?;
79
+
.with_context(|| format!("Could not execute TSG file {}", tsg_path.display()))?;
82
80
let json = matches.is_present("json");
83
81
if json {
84
-
graph.display_json(&ctx);
82
+
graph.display_json();
85
83
} else if !quiet {
86
-
print!("{}", graph.display_with(&ctx));
84
+
print!("{}", graph.pretty_print());
87
85
}
88
86
Ok(())
89
87
}
+11
-23
src/checker.rs
+11
-23
src/checker.rs
···
18
18
use crate::variables::VariableError;
19
19
use crate::variables::VariableMap;
20
20
use crate::variables::Variables;
21
-
use crate::Context;
22
-
use crate::DisplayWithContext as _;
23
21
use crate::Location;
24
22
25
23
#[derive(Debug, Error)]
···
40
38
41
39
/// Checker context
42
40
struct CheckContext<'a> {
43
-
ctx: &'a Context,
44
41
locals: &'a mut dyn Variables<ExpressionResult>,
45
42
file_query: &'a Query,
46
43
stanza_index: usize,
···
51
48
// File
52
49
53
50
impl ast::File {
54
-
pub fn check(&mut self, ctx: &Context) -> Result<(), CheckError> {
51
+
pub fn check(&mut self) -> Result<(), CheckError> {
55
52
let file_query = self.query.as_ref().unwrap();
56
53
for (index, stanza) in self.stanzas.iter_mut().enumerate() {
57
-
stanza.check(ctx, file_query, index)?;
54
+
stanza.check(file_query, index)?;
58
55
}
59
56
Ok(())
60
57
}
···
64
61
// Stanza
65
62
66
63
impl ast::Stanza {
67
-
fn check(
68
-
&mut self,
69
-
ctx: &Context,
70
-
file_query: &Query,
71
-
stanza_index: usize,
72
-
) -> Result<(), CheckError> {
64
+
fn check(&mut self, file_query: &Query, stanza_index: usize) -> Result<(), CheckError> {
73
65
let mut locals = VariableMap::new();
74
66
let mut ctx = CheckContext {
75
-
ctx,
76
67
locals: &mut locals,
77
68
file_query,
78
69
stanza_index,
···
197
188
198
189
let mut arm_locals = VariableMap::new_child(ctx.locals);
199
190
let mut arm_ctx = CheckContext {
200
-
ctx: ctx.ctx,
201
191
locals: &mut arm_locals,
202
192
file_query: ctx.file_query,
203
193
stanza_index: ctx.stanza_index,
···
230
220
231
221
let mut arm_locals = VariableMap::new_child(ctx.locals);
232
222
let mut arm_ctx = CheckContext {
233
-
ctx: ctx.ctx,
234
223
locals: &mut arm_locals,
235
224
file_query: ctx.file_query,
236
225
stanza_index: ctx.stanza_index,
···
280
269
281
270
let mut loop_locals = VariableMap::new_child(ctx.locals);
282
271
let mut loop_ctx = CheckContext {
283
-
ctx: ctx.ctx,
284
272
locals: &mut loop_locals,
285
273
file_query: ctx.file_query,
286
274
stanza_index: ctx.stanza_index,
···
380
368
381
369
impl ast::Capture {
382
370
fn check(&mut self, ctx: &mut CheckContext) -> Result<ExpressionResult, CheckError> {
383
-
let name = ctx.ctx.resolve(self.name);
371
+
let name = self.name.to_string();
384
372
self.stanza_capture_index = ctx
385
373
.stanza_query
386
-
.capture_index_for_name(name)
387
-
.ok_or_else(|| CheckError::UndefinedSyntaxCapture(name.to_string(), self.location))?
374
+
.capture_index_for_name(&name)
375
+
.ok_or_else(|| CheckError::UndefinedSyntaxCapture(name.clone(), self.location))?
388
376
as usize;
389
-
self.file_capture_index = ctx.file_query.capture_index_for_name(name).unwrap() as usize;
377
+
self.file_capture_index = ctx.file_query.capture_index_for_name(&name).unwrap() as usize;
390
378
self.quantifier =
391
379
ctx.file_query.capture_quantifiers(ctx.stanza_index)[self.file_capture_index];
392
380
Ok(ExpressionResult {
···
470
458
value.is_local = false;
471
459
}
472
460
ctx.locals
473
-
.add(self.name, value, mutable)
474
-
.map_err(|e| CheckError::Variable(e, format!("{}", self.name.display_with(ctx.ctx))))
461
+
.add(self.name.clone(), value, mutable)
462
+
.map_err(|e| CheckError::Variable(e, format!("{}", self.name)))
475
463
}
476
464
477
465
fn check_set(
···
486
474
// assignments, and can assume non-local to be sound.
487
475
value.is_local = false;
488
476
ctx.locals
489
-
.set(self.name, value)
490
-
.map_err(|e| CheckError::Variable(e, format!("{}", self.name.display_with(ctx.ctx))))
477
+
.set(self.name.clone(), value)
478
+
.map_err(|e| CheckError::Variable(e, format!("{}", self.name)))
491
479
}
492
480
493
481
fn check_get(&mut self, ctx: &mut CheckContext) -> Result<ExpressionResult, CheckError> {
+48
-90
src/execution.rs
+48
-90
src/execution.rs
···
40
40
use crate::ast::UnscopedVariable;
41
41
use crate::ast::Variable;
42
42
use crate::functions::Functions;
43
-
use crate::graph::DisplayWithGraph;
44
43
use crate::graph::Graph;
45
-
use crate::graph::GraphNodeRef;
46
44
use crate::graph::SyntaxNodeRef;
47
45
use crate::graph::Value;
48
46
pub use crate::variables::Globals;
49
47
use crate::variables::VariableMap;
50
48
use crate::variables::Variables;
51
-
use crate::Context;
52
-
use crate::DisplayWithContext;
53
49
54
50
impl File {
55
51
/// Executes this graph DSL file against a source file. You must provide the parsed syntax
···
57
53
/// provide the set of functions and global variables that are available during execution.
58
54
pub fn execute<'tree>(
59
55
&self,
60
-
ctx: &Context,
61
56
tree: &'tree Tree,
62
57
source: &'tree str,
63
58
functions: &mut Functions,
64
59
globals: &Globals,
65
60
) -> Result<Graph<'tree>, ExecutionError> {
66
61
let mut graph = Graph::new();
67
-
self.execute_into(ctx, &mut graph, tree, source, functions, globals)?;
62
+
self.execute_into(&mut graph, tree, source, functions, globals)?;
68
63
Ok(graph)
69
64
}
70
65
···
75
70
/// “pre-seed” the graph with some predefined nodes and/or edges before executing the DSL file.
76
71
pub fn execute_into<'tree>(
77
72
&self,
78
-
ctx: &Context,
79
73
graph: &mut Graph<'tree>,
80
74
tree: &'tree Tree,
81
75
source: &'tree str,
···
92
86
let mut cursor = QueryCursor::new();
93
87
for stanza in &self.stanzas {
94
88
stanza.execute(
95
-
ctx,
96
89
tree,
97
90
source,
98
91
graph,
···
177
170
}
178
171
179
172
struct ExecutionContext<'a, 'g, 's, 'tree> {
180
-
ctx: &'a Context,
181
173
source: &'tree str,
182
174
graph: &'a mut Graph<'tree>,
183
175
functions: &'a mut Functions,
···
208
200
impl Stanza {
209
201
fn execute<'l, 's, 'tree>(
210
202
&self,
211
-
ctx: &Context,
212
203
tree: &'tree Tree,
213
204
source: &'tree str,
214
205
graph: &mut Graph<'tree>,
···
224
215
for mat in matches {
225
216
locals.clear();
226
217
let mut exec = ExecutionContext {
227
-
ctx,
228
218
source,
229
219
graph,
230
220
functions,
···
238
228
for statement in &self.statements {
239
229
statement
240
230
.execute(&mut exec)
241
-
.with_context(|| format!("Executing {}", statement.display_with(exec.ctx)))?;
231
+
.with_context(|| format!("Executing {}", statement))?;
242
232
}
243
233
}
244
234
Ok(())
···
294
284
295
285
impl AddGraphNodeAttribute {
296
286
fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
297
-
let node = self.node.evaluate_as_node(exec)?;
287
+
let node = self.node.evaluate(exec)?.into_graph_node_ref()?;
298
288
for attribute in &self.attributes {
299
289
let value = attribute.value.evaluate(exec)?;
300
290
exec.graph[node]
301
291
.attributes
302
-
.add(attribute.name, value)
292
+
.add(attribute.name.clone(), value)
303
293
.map_err(|_| {
304
294
ExecutionError::DuplicateAttribute(format!(
305
295
" {} on graph node ({}) in {}",
306
-
attribute.name.display_with(exec.ctx),
307
-
node.display_with(exec.graph),
308
-
self.display_with(exec.ctx),
296
+
attribute.name, node, self,
309
297
))
310
298
})?;
311
299
}
···
315
303
316
304
impl CreateEdge {
317
305
fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
318
-
let source = self.source.evaluate_as_node(exec)?;
319
-
let sink = self.sink.evaluate_as_node(exec)?;
320
-
let ctx = exec.ctx;
306
+
let source = self.source.evaluate(exec)?.into_graph_node_ref()?;
307
+
let sink = self.sink.evaluate(exec)?.into_graph_node_ref()?;
321
308
if let Err(_) = exec.graph[source].add_edge(sink) {
322
309
Err(ExecutionError::DuplicateEdge(format!(
323
310
"({} -> {}) in {}",
324
-
source.display_with(exec.graph),
325
-
sink.display_with(exec.graph),
326
-
self.display_with(ctx)
311
+
source, sink, self,
327
312
)))?;
328
313
}
329
314
Ok(())
···
332
317
333
318
impl AddEdgeAttribute {
334
319
fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
335
-
let source = self.source.evaluate_as_node(exec)?;
336
-
let sink = self.sink.evaluate_as_node(exec)?;
320
+
let source = self.source.evaluate(exec)?.into_graph_node_ref()?;
321
+
let sink = self.sink.evaluate(exec)?.into_graph_node_ref()?;
337
322
for attribute in &self.attributes {
338
323
let value = attribute.value.evaluate(exec)?;
339
324
let edge = match exec.graph[source].get_edge_mut(sink) {
340
325
Some(edge) => Ok(edge),
341
326
None => Err(ExecutionError::UndefinedEdge(format!(
342
327
"({} -> {}) in {}",
343
-
source.display_with(exec.graph),
344
-
sink.display_with(exec.graph),
345
-
self.display_with(exec.ctx)
328
+
source, sink, self,
346
329
))),
347
330
}?;
348
-
edge.attributes.add(attribute.name, value).map_err(|_| {
349
-
ExecutionError::DuplicateAttribute(format!(
350
-
" {} on edge ({} -> {}) in {}",
351
-
attribute.name.display_with(exec.ctx),
352
-
source.display_with(exec.graph),
353
-
sink.display_with(exec.graph),
354
-
self.display_with(exec.ctx),
355
-
))
356
-
})?;
331
+
edge.attributes
332
+
.add(attribute.name.clone(), value)
333
+
.map_err(|_| {
334
+
ExecutionError::DuplicateAttribute(format!(
335
+
" {} on edge ({} -> {}) in {}",
336
+
attribute.name, source, sink, self,
337
+
))
338
+
})?;
357
339
}
358
340
Ok(())
359
341
}
···
361
343
362
344
impl Scan {
363
345
fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
364
-
let match_string = self.value.evaluate(exec)?.into_string(exec.graph)?;
346
+
let match_string = self.value.evaluate(exec)?.into_string()?;
365
347
366
348
let mut i = 0;
367
349
let mut matches = Vec::new();
···
400
382
401
383
let mut arm_locals = VariableMap::new_child(exec.locals);
402
384
let mut arm_exec = ExecutionContext {
403
-
ctx: exec.ctx,
404
385
source: exec.source,
405
386
graph: exec.graph,
406
387
functions: exec.functions,
···
415
396
for statement in &arm.statements {
416
397
statement
417
398
.execute(&mut arm_exec)
418
-
.with_context(|| format!("Executing {}", statement.display_with(arm_exec.ctx)))
399
+
.with_context(|| format!("Executing {}", statement))
419
400
.with_context(|| {
420
401
format!(
421
402
"Matching {} with arm \"{}\" {{ ... }}",
···
438
419
eprint!("{}", expr.value);
439
420
} else {
440
421
let value = value.evaluate(exec)?;
441
-
eprint!("{}", value.display_with(exec.graph));
422
+
eprint!("{}", value);
442
423
}
443
424
}
444
425
eprintln!();
···
456
437
if result {
457
438
let mut arm_locals = VariableMap::new_child(exec.locals);
458
439
let mut arm_exec = ExecutionContext {
459
-
ctx: exec.ctx,
460
440
source: exec.source,
461
441
graph: exec.graph,
462
442
functions: exec.functions,
···
482
462
match self {
483
463
Condition::Some { value, .. } => Ok(!value.evaluate(exec)?.is_null()),
484
464
Condition::None { value, .. } => Ok(value.evaluate(exec)?.is_null()),
485
-
Condition::Bool { value, .. } => Ok(value.evaluate(exec)?.into_bool(exec.graph)?),
465
+
Condition::Bool { value, .. } => Ok(value.evaluate(exec)?.into_boolean()?),
486
466
}
487
467
}
488
468
}
489
469
490
470
impl ForIn {
491
471
fn execute(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
492
-
let values = self.value.evaluate(exec)?.into_list(exec.graph)?;
472
+
let values = self.value.evaluate(exec)?.into_list()?;
493
473
let mut loop_locals = VariableMap::new_child(exec.locals);
494
474
for value in values {
495
475
loop_locals.clear();
496
476
let mut loop_exec = ExecutionContext {
497
-
ctx: exec.ctx,
498
477
source: exec.source,
499
478
graph: exec.graph,
500
479
functions: exec.functions,
···
530
509
Expression::RegexCapture(expr) => expr.evaluate(exec),
531
510
}
532
511
}
533
-
534
-
fn evaluate_as_node(
535
-
&self,
536
-
exec: &mut ExecutionContext,
537
-
) -> Result<GraphNodeRef, ExecutionError> {
538
-
let node = self.evaluate(exec)?;
539
-
match node {
540
-
Value::GraphNode(node) => Ok(node),
541
-
_ => Err(ExecutionError::ExpectedGraphNode(format!(
542
-
" {}, got {}",
543
-
self.display_with(exec.ctx),
544
-
node.display_with(exec.graph)
545
-
))),
546
-
}
547
-
}
548
512
}
549
513
550
514
impl IntegerConstant {
···
599
563
exec.function_parameters.push(parameter);
600
564
}
601
565
exec.functions.call(
602
-
exec.ctx,
603
-
self.function,
566
+
&self.function,
604
567
exec.graph,
605
568
exec.source,
606
569
&mut exec
···
612
575
613
576
impl RegexCapture {
614
577
fn evaluate(&self, exec: &mut ExecutionContext) -> Result<Value, ExecutionError> {
615
-
let capture = exec.current_regex_captures.get(self.match_index).ok_or(
616
-
ExecutionError::UndefinedRegexCapture(format!("{}", self.display_with(exec.ctx))),
617
-
)?;
578
+
let capture = exec
579
+
.current_regex_captures
580
+
.get(self.match_index)
581
+
.ok_or(ExecutionError::UndefinedRegexCapture(format!("{}", self)))?;
618
582
Ok(Value::String(capture.clone()))
619
583
}
620
584
}
···
662
626
_ => {
663
627
return Err(ExecutionError::InvalidVariableScope(format!(
664
628
" got {}",
665
-
scope.display_with(exec.graph)
629
+
scope
666
630
)))
667
631
}
668
632
};
···
672
636
} else {
673
637
Err(ExecutionError::UndefinedVariable(format!(
674
638
"{} on node {}",
675
-
self.display_with(exec.ctx),
676
-
scope.display_with(exec.graph)
639
+
self, scope,
677
640
)))
678
641
}
679
642
}
···
690
653
_ => {
691
654
return Err(ExecutionError::InvalidVariableScope(format!(
692
655
" got {}",
693
-
scope.display_with(exec.graph)
656
+
scope
694
657
)))
695
658
}
696
659
};
697
660
let variables = exec.scoped.get(scope);
698
-
variables.add(self.name, value, mutable).map_err(|_| {
699
-
ExecutionError::DuplicateVariable(format!(" {}", self.display_with(exec.ctx)))
700
-
})
661
+
variables
662
+
.add(self.name.clone(), value, mutable)
663
+
.map_err(|_| ExecutionError::DuplicateVariable(format!(" {}", self)))
701
664
}
702
665
703
666
fn set(&self, exec: &mut ExecutionContext, value: Value) -> Result<(), ExecutionError> {
···
707
670
_ => {
708
671
return Err(ExecutionError::InvalidVariableScope(format!(
709
672
" got {}",
710
-
scope.display_with(exec.graph)
673
+
scope,
711
674
)))
712
675
}
713
676
};
714
677
let variables = exec.scoped.get(scope);
715
-
variables.set(self.name, value).map_err(|_| {
716
-
ExecutionError::DuplicateVariable(format!(" {}", self.display_with(exec.ctx)))
717
-
})
678
+
variables
679
+
.set(self.name.clone(), value)
680
+
.map_err(|_| ExecutionError::DuplicateVariable(format!(" {}", self)))
718
681
}
719
682
}
720
683
···
725
688
} else {
726
689
exec.locals.get(&self.name)
727
690
}
728
-
.ok_or_else(|| {
729
-
ExecutionError::UndefinedVariable(format!("{}", self.display_with(exec.ctx)))
730
-
})
691
+
.ok_or_else(|| ExecutionError::UndefinedVariable(format!("{}", self)))
731
692
}
732
693
733
694
fn add(
···
739
700
if exec.globals.get(&self.name).is_some() {
740
701
return Err(ExecutionError::DuplicateVariable(format!(
741
702
" global {}",
742
-
self.display_with(exec.ctx)
703
+
self,
743
704
)));
744
705
}
745
-
exec.locals.add(self.name, value, mutable).map_err(|_| {
746
-
ExecutionError::DuplicateVariable(format!(" local {}", self.display_with(exec.ctx)))
747
-
})
706
+
exec.locals
707
+
.add(self.name.clone(), value, mutable)
708
+
.map_err(|_| ExecutionError::DuplicateVariable(format!(" local {}", self)))
748
709
}
749
710
750
711
fn set(&self, exec: &mut ExecutionContext, value: Value) -> Result<(), ExecutionError> {
751
712
if exec.globals.get(&self.name).is_some() {
752
713
return Err(ExecutionError::CannotAssignImmutableVariable(format!(
753
714
" global {}",
754
-
self.display_with(exec.ctx)
715
+
self,
755
716
)));
756
717
}
757
-
exec.locals.set(self.name, value).map_err(|_| {
718
+
exec.locals.set(self.name.clone(), value).map_err(|_| {
758
719
if exec.locals.get(&self.name).is_some() {
759
-
ExecutionError::CannotAssignImmutableVariable(format!(
760
-
"{}",
761
-
self.display_with(exec.ctx)
762
-
))
720
+
ExecutionError::CannotAssignImmutableVariable(format!("{}", self))
763
721
} else {
764
-
ExecutionError::UndefinedVariable(format!("{}", self.display_with(exec.ctx)))
722
+
ExecutionError::UndefinedVariable(format!("{}", self))
765
723
}
766
724
})
767
725
}
+41
-51
src/functions.rs
+41
-51
src/functions.rs
···
12
12
use crate::execution::ExecutionError;
13
13
use crate::graph::Graph;
14
14
use crate::graph::Value;
15
-
use crate::Context;
16
-
use crate::DisplayWithContext;
17
15
use crate::Identifier;
18
16
19
17
/// The implementation of a function that can be called from the graph DSL.
···
42
40
/// # use tree_sitter_graph::graph::Value;
43
41
/// # use tree_sitter_graph::ExecutionError;
44
42
/// # fn main() -> Result<(), ExecutionError> {
45
-
/// # let graph = Graph::new();
46
43
/// # let param_vec = vec![Value::String("test".to_string()), Value::Integer(42)];
47
44
/// # let mut params = param_vec.into_iter();
48
-
/// let first_param = params.param()?.into_string(&graph)?;
49
-
/// let second_param = params.param()?.into_integer(&graph)?;
45
+
/// let first_param = params.param()?.into_string()?;
46
+
/// let second_param = params.param()?.as_integer()?;
50
47
/// // etc
51
48
/// params.finish()?;
52
49
/// # Ok(())
···
99
96
100
97
/// Returns the standard library of functions, as defined in the [language
101
98
/// reference][`crate::reference::functions`].
102
-
pub fn stdlib(ctx: &mut Context) -> Functions {
99
+
pub fn stdlib() -> Functions {
103
100
let mut functions = Functions::new();
104
101
// general functions
105
-
functions.add(ctx.add_identifier("is-null"), stdlib::IsNull);
102
+
functions.add(Identifier::from("is-null"), stdlib::IsNull);
106
103
// tree functions
107
104
functions.add(
108
-
ctx.add_identifier("named-child-index"),
105
+
Identifier::from("named-child-index"),
109
106
stdlib::syntax::NamedChildIndex,
110
107
);
108
+
functions.add(Identifier::from("source-text"), stdlib::syntax::SourceText);
109
+
functions.add(Identifier::from("start-row"), stdlib::syntax::StartRow);
111
110
functions.add(
112
-
ctx.add_identifier("source-text"),
113
-
stdlib::syntax::SourceText,
114
-
);
115
-
functions.add(ctx.add_identifier("start-row"), stdlib::syntax::StartRow);
116
-
functions.add(
117
-
ctx.add_identifier("start-column"),
111
+
Identifier::from("start-column"),
118
112
stdlib::syntax::StartColumn,
119
113
);
120
-
functions.add(ctx.add_identifier("end-row"), stdlib::syntax::EndRow);
121
-
functions.add(ctx.add_identifier("end-column"), stdlib::syntax::EndColumn);
122
-
functions.add(ctx.add_identifier("node-type"), stdlib::syntax::NodeType);
114
+
functions.add(Identifier::from("end-row"), stdlib::syntax::EndRow);
115
+
functions.add(Identifier::from("end-column"), stdlib::syntax::EndColumn);
116
+
functions.add(Identifier::from("node-type"), stdlib::syntax::NodeType);
123
117
functions.add(
124
-
ctx.add_identifier("named-child-count"),
118
+
Identifier::from("named-child-count"),
125
119
stdlib::syntax::NamedChildCount,
126
120
);
127
121
// graph functions
128
-
functions.add(ctx.add_identifier("node"), stdlib::graph::Node);
122
+
functions.add(Identifier::from("node"), stdlib::graph::Node);
129
123
// boolean functions
130
-
functions.add(ctx.add_identifier("not"), stdlib::bool::Not);
131
-
functions.add(ctx.add_identifier("and"), stdlib::bool::And);
132
-
functions.add(ctx.add_identifier("or"), stdlib::bool::Or);
124
+
functions.add(Identifier::from("not"), stdlib::bool::Not);
125
+
functions.add(Identifier::from("and"), stdlib::bool::And);
126
+
functions.add(Identifier::from("or"), stdlib::bool::Or);
133
127
// math functions
134
-
functions.add(ctx.add_identifier("plus"), stdlib::math::Plus);
128
+
functions.add(Identifier::from("plus"), stdlib::math::Plus);
135
129
// string functions
136
-
functions.add(ctx.add_identifier("replace"), stdlib::string::Replace);
130
+
functions.add(Identifier::from("replace"), stdlib::string::Replace);
137
131
functions
138
132
}
139
133
···
148
142
/// Calls a named function, returning an error if there is no function with that name.
149
143
pub fn call(
150
144
&mut self,
151
-
ctx: &Context,
152
-
name: Identifier,
145
+
name: &Identifier,
153
146
graph: &mut Graph,
154
147
source: &str,
155
148
parameters: &mut dyn Parameters,
156
149
) -> Result<Value, ExecutionError> {
157
150
let function = self
158
151
.functions
159
-
.get_mut(&name)
160
-
.ok_or(ExecutionError::UndefinedFunction(format!(
161
-
"{}",
162
-
name.display_with(ctx)
163
-
)))?;
152
+
.get_mut(name)
153
+
.ok_or(ExecutionError::UndefinedFunction(format!("{}", name)))?;
164
154
function.call(graph, source, parameters)
165
155
}
166
156
}
···
212
202
_source: &str,
213
203
parameters: &mut dyn Parameters,
214
204
) -> Result<Value, ExecutionError> {
215
-
let node = graph[parameters.param()?.into_syntax_node_ref(graph)?];
205
+
let node = graph[parameters.param()?.into_syntax_node_ref()?];
216
206
parameters.finish()?;
217
207
let parent = match node.parent() {
218
208
Some(parent) => parent,
···
240
230
source: &str,
241
231
parameters: &mut dyn Parameters,
242
232
) -> Result<Value, ExecutionError> {
243
-
let node = graph[parameters.param()?.into_syntax_node_ref(graph)?];
233
+
let node = graph[parameters.param()?.into_syntax_node_ref()?];
244
234
parameters.finish()?;
245
235
Ok(Value::String(source[node.byte_range()].to_string()))
246
236
}
···
257
247
_source: &str,
258
248
parameters: &mut dyn Parameters,
259
249
) -> Result<Value, ExecutionError> {
260
-
let node = graph[parameters.param()?.into_syntax_node_ref(graph)?];
250
+
let node = graph[parameters.param()?.into_syntax_node_ref()?];
261
251
parameters.finish()?;
262
252
Ok(Value::Integer(node.start_position().row as u32))
263
253
}
···
275
265
_source: &str,
276
266
parameters: &mut dyn Parameters,
277
267
) -> Result<Value, ExecutionError> {
278
-
let node = graph[parameters.param()?.into_syntax_node_ref(graph)?];
268
+
let node = graph[parameters.param()?.into_syntax_node_ref()?];
279
269
parameters.finish()?;
280
270
Ok(Value::Integer(node.start_position().column as u32))
281
271
}
···
292
282
_source: &str,
293
283
parameters: &mut dyn Parameters,
294
284
) -> Result<Value, ExecutionError> {
295
-
let node = graph[parameters.param()?.into_syntax_node_ref(graph)?];
285
+
let node = graph[parameters.param()?.into_syntax_node_ref()?];
296
286
parameters.finish()?;
297
287
Ok(Value::Integer(node.end_position().row as u32))
298
288
}
···
309
299
_source: &str,
310
300
parameters: &mut dyn Parameters,
311
301
) -> Result<Value, ExecutionError> {
312
-
let node = graph[parameters.param()?.into_syntax_node_ref(graph)?];
302
+
let node = graph[parameters.param()?.into_syntax_node_ref()?];
313
303
parameters.finish()?;
314
304
Ok(Value::Integer(node.end_position().column as u32))
315
305
}
···
326
316
_source: &str,
327
317
parameters: &mut dyn Parameters,
328
318
) -> Result<Value, ExecutionError> {
329
-
let node = graph[parameters.param()?.into_syntax_node_ref(graph)?];
319
+
let node = graph[parameters.param()?.into_syntax_node_ref()?];
330
320
parameters.finish()?;
331
321
Ok(Value::String(node.kind().to_string()))
332
322
}
···
344
334
_source: &str,
345
335
parameters: &mut dyn Parameters,
346
336
) -> Result<Value, ExecutionError> {
347
-
let node = graph[parameters.param()?.into_syntax_node_ref(graph)?];
337
+
let node = graph[parameters.param()?.into_syntax_node_ref()?];
348
338
parameters.finish()?;
349
339
Ok(Value::Integer(node.named_child_count() as u32))
350
340
}
···
380
370
impl Function for Not {
381
371
fn call(
382
372
&mut self,
383
-
graph: &mut Graph,
373
+
_graph: &mut Graph,
384
374
_source: &str,
385
375
parameters: &mut dyn Parameters,
386
376
) -> Result<Value, ExecutionError> {
387
-
let result = !parameters.param()?.into_bool(graph)?;
377
+
let result = !parameters.param()?.as_boolean()?;
388
378
parameters.finish()?;
389
379
Ok(result.into())
390
380
}
···
396
386
impl Function for And {
397
387
fn call(
398
388
&mut self,
399
-
graph: &mut Graph,
389
+
_graph: &mut Graph,
400
390
_source: &str,
401
391
parameters: &mut dyn Parameters,
402
392
) -> Result<Value, ExecutionError> {
403
393
let mut result = true;
404
394
while let Ok(parameter) = parameters.param() {
405
-
result &= parameter.into_bool(graph)?;
395
+
result &= parameter.as_boolean()?;
406
396
}
407
397
Ok(result.into())
408
398
}
···
414
404
impl Function for Or {
415
405
fn call(
416
406
&mut self,
417
-
graph: &mut Graph,
407
+
_graph: &mut Graph,
418
408
_source: &str,
419
409
parameters: &mut dyn Parameters,
420
410
) -> Result<Value, ExecutionError> {
421
411
let mut result = false;
422
412
while let Ok(parameter) = parameters.param() {
423
-
result |= parameter.into_bool(graph)?;
413
+
result |= parameter.as_boolean()?;
424
414
}
425
415
Ok(result.into())
426
416
}
···
436
426
impl Function for Plus {
437
427
fn call(
438
428
&mut self,
439
-
graph: &mut Graph,
429
+
_graph: &mut Graph,
440
430
_source: &str,
441
431
parameters: &mut dyn Parameters,
442
432
) -> Result<Value, ExecutionError> {
443
433
let mut result = 0;
444
434
while let Ok(parameter) = parameters.param() {
445
-
result += parameter.into_integer(graph)?;
435
+
result += parameter.as_integer()?;
446
436
}
447
437
Ok(Value::Integer(result))
448
438
}
···
458
448
impl Function for Replace {
459
449
fn call(
460
450
&mut self,
461
-
graph: &mut Graph,
451
+
_graph: &mut Graph,
462
452
_source: &str,
463
453
parameters: &mut dyn Parameters,
464
454
) -> Result<Value, ExecutionError> {
465
-
let text = parameters.param()?.into_string(graph)?;
466
-
let pattern = parameters.param()?.into_string(graph)?;
455
+
let text = parameters.param()?.into_string()?;
456
+
let pattern = parameters.param()?.into_string()?;
467
457
let pattern = Regex::new(&pattern).map_err(ExecutionError::other)?;
468
-
let replacement = parameters.param()?.into_string(graph)?;
458
+
let replacement = parameters.param()?.into_string()?;
469
459
parameters.finish()?;
470
460
Ok(Value::String(
471
461
pattern.replace_all(&text, replacement).to_string(),
+176
-303
src/graph.rs
+176
-303
src/graph.rs
···
7
7
8
8
//! Defines data types for the graphs produced by the graph DSL
9
9
10
+
use std::borrow::Borrow;
10
11
use std::collections::hash_map::Entry;
11
12
use std::collections::BTreeSet;
12
13
use std::collections::HashMap;
13
14
use std::fmt;
15
+
use std::hash::Hash;
14
16
use std::ops::Index;
15
17
use std::ops::IndexMut;
16
18
17
-
use smallvec::SmallVec;
18
-
use tree_sitter::Node;
19
-
20
-
use serde::ser;
21
19
use serde::ser::SerializeMap;
22
20
use serde::ser::SerializeSeq;
21
+
use serde::Serialize;
22
+
use serde::Serializer;
23
23
use serde_json;
24
+
use smallvec::SmallVec;
25
+
use tree_sitter::Node;
24
26
25
27
use crate::execution::ExecutionError;
26
-
use crate::Context;
27
28
use crate::Identifier;
28
29
29
30
/// A graph produced by executing a graph DSL file. Graphs include a lifetime parameter to ensure
30
31
/// that they don't outlive the tree-sitter syntax tree that they are generated from.
31
32
#[derive(Default)]
32
33
pub struct Graph<'tree> {
33
-
syntax_nodes: HashMap<SyntaxNodeRef, Node<'tree>>,
34
+
syntax_nodes: HashMap<SyntaxNodeID, Node<'tree>>,
34
35
graph_nodes: Vec<GraphNode>,
35
36
}
36
37
···
48
49
/// The graph won't contain _every_ syntax node in the parsed syntax tree; it will only contain
49
50
/// those nodes that are referenced at some point during the execution of the graph DSL file.
50
51
pub fn add_syntax_node(&mut self, node: Node<'tree>) -> SyntaxNodeRef {
51
-
let index = SyntaxNodeRef(node.id() as SyntaxNodeID);
52
-
self.syntax_nodes.insert(index, node);
53
-
index
52
+
let index = node.id() as SyntaxNodeID;
53
+
let node_ref = SyntaxNodeRef {
54
+
index,
55
+
kind: node.kind(),
56
+
position: node.start_position(),
57
+
};
58
+
self.syntax_nodes.entry(index).or_insert(node);
59
+
node_ref
54
60
}
55
61
56
62
/// Adds a new graph node to the graph, returning a graph DSL reference to it.
···
61
67
GraphNodeRef(index)
62
68
}
63
69
64
-
/// fmt::Displays the contents of this graph.
65
-
pub fn display_with<'a>(&'a self, ctx: &'a Context) -> impl fmt::Display + 'a {
66
-
struct DisplayGraph<'a, 'tree>(&'a Graph<'tree>, &'a Context);
70
+
/// Pretty-prints the contents of this graph.
71
+
pub fn pretty_print<'a>(&'a self) -> impl fmt::Display + 'a {
72
+
struct DisplayGraph<'a, 'tree>(&'a Graph<'tree>);
67
73
68
74
impl<'a, 'tree> fmt::Display for DisplayGraph<'a, 'tree> {
69
75
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
70
76
let graph = self.0;
71
-
let ctx = self.1;
72
77
for (node_index, node) in graph.graph_nodes.iter().enumerate() {
73
-
write!(
74
-
f,
75
-
"node {}\n{}",
76
-
node_index,
77
-
node.attributes.display_with(ctx, graph)
78
-
)?;
78
+
write!(f, "node {}\n{}", node_index, node.attributes)?;
79
79
for (sink, edge) in &node.outgoing_edges {
80
-
write!(
81
-
f,
82
-
"edge {} -> {}\n{}",
83
-
node_index,
84
-
*sink,
85
-
edge.attributes.display_with(ctx, graph)
86
-
)?;
80
+
write!(f, "edge {} -> {}\n{}", node_index, *sink, edge.attributes)?;
87
81
}
88
82
}
89
83
Ok(())
90
84
}
91
85
}
92
86
93
-
DisplayGraph(self, ctx)
87
+
DisplayGraph(self)
94
88
}
95
89
96
-
pub fn display_json<'a>(&'a self, ctx: &'a Context) -> () {
97
-
// TODO: move this all into a new module
98
-
struct InContext<'a, T>(&'a T, &'a Context);
99
-
100
-
impl<'a> Context {
101
-
fn with<T>(&'a self, t: &'a T) -> InContext<'a, T> {
102
-
InContext(t, self)
103
-
}
104
-
}
105
-
106
-
impl<'a, 'tree> ser::Serialize for InContext<'a, Graph<'tree>> {
107
-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
108
-
where
109
-
S: serde::Serializer,
110
-
{
111
-
let graph = self.0;
112
-
let ctx = self.1;
113
-
let mut seq = serializer.serialize_seq(Some(graph.graph_nodes.len()))?;
114
-
for (node_index, node) in graph.graph_nodes.iter().enumerate() {
115
-
seq.serialize_element(&ctx.with(&(node_index, node)))?;
116
-
}
117
-
seq.end()
118
-
}
119
-
}
120
-
121
-
impl<'a> ser::Serialize for InContext<'a, (usize, &'a GraphNode)> {
122
-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
123
-
where
124
-
S: serde::Serializer,
125
-
{
126
-
let node_index = self.0 .0;
127
-
let node = self.0 .1;
128
-
let ctx = self.1;
129
-
// serializing as a map instead of a struct so we don't have to encode a struct name
130
-
let mut map = serializer.serialize_map(None)?;
131
-
map.serialize_entry("id", &node_index)?;
132
-
map.serialize_entry("edges", &ctx.with(&node.outgoing_edges))?;
133
-
map.serialize_entry("attrs", &ctx.with(&node.attributes))?;
134
-
map.end()
135
-
}
136
-
}
137
-
138
-
impl<'a> ser::Serialize for InContext<'a, SmallVec<[(GraphNodeID, Edge); 8]>> {
139
-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
140
-
where
141
-
S: serde::Serializer,
142
-
{
143
-
let elems = self.0;
144
-
let ctx = self.1;
145
-
let mut seq = serializer.serialize_seq(Some(elems.len()))?;
146
-
for (_, (id, edge)) in elems.iter().enumerate() {
147
-
seq.serialize_element(&ctx.with(&(id, edge)))?;
148
-
}
149
-
seq.end()
150
-
}
151
-
}
152
-
153
-
impl<'a> ser::Serialize for InContext<'a, (&'a GraphNodeID, &'a Edge)> {
154
-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
155
-
where
156
-
S: serde::Serializer,
157
-
{
158
-
let sink = self.0 .0;
159
-
let edge = self.0 .1;
160
-
let ctx = self.1;
161
-
let mut map = serializer.serialize_map(None)?;
162
-
map.serialize_entry("sink", &sink)?;
163
-
map.serialize_entry("attrs", &ctx.with(&edge.attributes))?;
164
-
map.end()
165
-
}
166
-
}
167
-
168
-
impl<'a> ser::Serialize for InContext<'a, Attributes> {
169
-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
170
-
where
171
-
S: serde::Serializer,
172
-
{
173
-
let attrs = self.0;
174
-
let ctx = self.1;
175
-
let mut map = serializer.serialize_map(None)?;
176
-
for (_, (key, value)) in attrs.values.iter().enumerate() {
177
-
map.serialize_entry(&ctx.with(key), &ctx.with(value))?;
178
-
}
179
-
map.end()
180
-
}
181
-
}
182
-
183
-
impl<'a> ser::Serialize for InContext<'a, Identifier> {
184
-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
185
-
where
186
-
S: serde::Serializer,
187
-
{
188
-
let identifier = self.0;
189
-
let ctx = self.1;
190
-
let symbol = ctx.identifiers.resolve(identifier.0).unwrap();
191
-
serializer.serialize_str(symbol)
192
-
}
193
-
}
194
-
195
-
impl<'a> ser::Serialize for InContext<'a, Value> {
196
-
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
197
-
where
198
-
S: serde::Serializer,
199
-
{
200
-
let value = self.0;
201
-
let ctx = self.1;
202
-
match value {
203
-
Value::Null => serializer.serialize_none(),
204
-
Value::Boolean(bool) => serializer.serialize_bool(*bool),
205
-
Value::Integer(integer) => serializer.serialize_u32(*integer),
206
-
Value::String(string) => serializer.serialize_str(string),
207
-
// FIXME: there's no way to distinguish sets and lists, so we can't roundtrip accurately
208
-
Value::List(list) => {
209
-
serializer.collect_seq(list.iter().map(|value| ctx.with(value)))
210
-
}
211
-
Value::Set(set) => {
212
-
serializer.collect_seq(set.iter().map(|value| ctx.with(value)))
213
-
}
214
-
// FIXME: we don't distinguish between syntax tree node IDs, graph node IDs, and integers
215
-
Value::SyntaxNode(node) => serializer.serialize_u32(node.0),
216
-
Value::GraphNode(node) => serializer.serialize_u32(node.0),
217
-
}
218
-
}
219
-
}
220
-
221
-
let json_graph = ctx.with(self);
222
-
let s = serde_json::to_string_pretty(&json_graph).unwrap();
90
+
pub fn display_json(&self) {
91
+
let s = serde_json::to_string_pretty(self).unwrap();
223
92
print!("{}", s)
224
93
}
225
94
···
236
105
237
106
impl<'tree> Index<SyntaxNodeRef> for Graph<'tree> {
238
107
type Output = Node<'tree>;
239
-
fn index(&self, index: SyntaxNodeRef) -> &Node<'tree> {
240
-
&self.syntax_nodes[&index]
108
+
fn index(&self, node_ref: SyntaxNodeRef) -> &Node<'tree> {
109
+
&self.syntax_nodes[&node_ref.index]
241
110
}
242
111
}
243
112
···
251
120
impl<'tree> IndexMut<GraphNodeRef> for Graph<'_> {
252
121
fn index_mut(&mut self, index: GraphNodeRef) -> &mut GraphNode {
253
122
&mut self.graph_nodes[index.0 as usize]
123
+
}
124
+
}
125
+
126
+
impl<'tree> Serialize for Graph<'tree> {
127
+
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
128
+
let mut seq = serializer.serialize_seq(Some(self.graph_nodes.len()))?;
129
+
for (node_index, node) in self.graph_nodes.iter().enumerate() {
130
+
seq.serialize_element(&SerializeGraphNode(node_index, node))?;
131
+
}
132
+
seq.end()
254
133
}
255
134
}
256
135
···
317
196
}
318
197
}
319
198
199
+
struct SerializeGraphNode<'a>(usize, &'a GraphNode);
200
+
201
+
impl<'a> Serialize for SerializeGraphNode<'a> {
202
+
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
203
+
let node_index = self.0;
204
+
let node = self.1;
205
+
// serializing as a map instead of a struct so we don't have to encode a struct name
206
+
let mut map = serializer.serialize_map(None)?;
207
+
map.serialize_entry("id", &node_index)?;
208
+
map.serialize_entry("edges", &SerializeGraphNodeEdges(&node.outgoing_edges))?;
209
+
map.serialize_entry("attrs", &node.attributes)?;
210
+
map.end()
211
+
}
212
+
}
213
+
214
+
struct SerializeGraphNodeEdges<'a>(&'a SmallVec<[(GraphNodeID, Edge); 8]>);
215
+
216
+
impl<'a> Serialize for SerializeGraphNodeEdges<'a> {
217
+
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
218
+
let edges = self.0;
219
+
let mut seq = serializer.serialize_seq(Some(edges.len()))?;
220
+
for element in edges {
221
+
seq.serialize_element(&SerializeGraphNodeEdge(&element))?;
222
+
}
223
+
seq.end()
224
+
}
225
+
}
226
+
227
+
struct SerializeGraphNodeEdge<'a>(&'a (GraphNodeID, Edge));
228
+
229
+
impl<'a> Serialize for SerializeGraphNodeEdge<'a> {
230
+
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
231
+
let wrapped = &self.0;
232
+
let sink = &wrapped.0;
233
+
let edge = &wrapped.1;
234
+
let mut map = serializer.serialize_map(None)?;
235
+
map.serialize_entry("sink", sink)?;
236
+
map.serialize_entry("attrs", &edge.attributes)?;
237
+
map.end()
238
+
}
239
+
}
240
+
320
241
/// An edge between two nodes in a graph
321
242
pub struct Edge {
322
243
/// The set of attributes associated with this edge
···
360
281
}
361
282
362
283
/// Returns the value of a particular attribute, if it exists.
363
-
pub fn get(&self, name: Identifier) -> Option<&Value> {
364
-
self.values.get(&name)
284
+
pub fn get<Q>(&self, name: &Q) -> Option<&Value>
285
+
where
286
+
Q: ?Sized + Eq + Hash,
287
+
Identifier: Borrow<Q>,
288
+
{
289
+
self.values.get(name.borrow())
365
290
}
366
-
367
-
/// fmt::Displays the contents of this attribute set.
368
-
pub fn display_with<'a>(
369
-
&'a self,
370
-
ctx: &'a Context,
371
-
graph: &'a Graph,
372
-
) -> impl fmt::Display + 'a {
373
-
struct DisplayAttributes<'a, 'tree>(&'a Attributes, &'a Context, &'a Graph<'tree>);
374
-
375
-
impl<'a, 'tree> fmt::Display for DisplayAttributes<'a, 'tree> {
376
-
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
377
-
let attributes = self.0;
378
-
let ctx = self.1;
379
-
let graph = self.2;
291
+
}
380
292
381
-
let mut keys = attributes
382
-
.values
383
-
.keys()
384
-
.map(|k| (ctx.resolve(*k), k))
385
-
.collect::<Vec<_>>();
386
-
keys.sort_by(|a, b| a.0.cmp(b.0));
387
-
for (name, key) in &keys {
388
-
let value = &attributes.values[key];
389
-
write!(f, " {}: {}\n", name, value.display_with(graph),)?;
390
-
}
391
-
Ok(())
392
-
}
293
+
impl std::fmt::Display for Attributes {
294
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
295
+
let mut keys = self.values.keys().collect::<Vec<_>>();
296
+
keys.sort_by(|a, b| a.cmp(b));
297
+
for key in &keys {
298
+
let value = &self.values[*key];
299
+
write!(f, " {}: {}\n", key, value)?;
393
300
}
301
+
Ok(())
302
+
}
303
+
}
394
304
395
-
DisplayAttributes(self, ctx, graph)
305
+
impl Serialize for Attributes {
306
+
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
307
+
let mut map = serializer.serialize_map(None)?;
308
+
for (key, value) in &self.values {
309
+
map.serialize_entry(key, value)?;
310
+
}
311
+
map.end()
396
312
}
397
313
}
398
314
···
414
330
415
331
impl Value {
416
332
/// Check if this value is null
417
-
pub fn is_null(self) -> bool {
333
+
pub fn is_null(&self) -> bool {
418
334
match self {
419
335
Value::Null => true,
420
336
_ => false,
421
337
}
422
338
}
339
+
423
340
/// Coerces this value into a boolean, returning an error if it's some other type of value.
424
-
pub fn into_bool(self, graph: &Graph) -> Result<bool, ExecutionError> {
341
+
pub fn into_boolean(self) -> Result<bool, ExecutionError> {
425
342
match self {
426
343
Value::Boolean(value) => Ok(value),
427
-
_ => Err(ExecutionError::ExpectedBoolean(format!(
428
-
"got {}",
429
-
self.display_with(graph)
430
-
))),
344
+
_ => Err(ExecutionError::ExpectedBoolean(format!("got {}", self))),
431
345
}
432
346
}
433
347
434
-
pub fn as_bool(&self, graph: &Graph) -> Result<bool, ExecutionError> {
348
+
pub fn as_boolean(&self) -> Result<bool, ExecutionError> {
435
349
match self {
436
350
Value::Boolean(value) => Ok(*value),
437
-
_ => Err(ExecutionError::ExpectedBoolean(format!(
438
-
"got {}",
439
-
self.display_with(graph)
440
-
))),
351
+
_ => Err(ExecutionError::ExpectedBoolean(format!("got {}", self))),
441
352
}
442
353
}
443
354
444
355
/// Coerces this value into an integer, returning an error if it's some other type of value.
445
-
pub fn into_integer(self, graph: &Graph) -> Result<u32, ExecutionError> {
356
+
pub fn into_integer(self) -> Result<u32, ExecutionError> {
446
357
match self {
447
358
Value::Integer(value) => Ok(value),
448
-
_ => Err(ExecutionError::ExpectedInteger(format!(
449
-
"got {}",
450
-
self.display_with(graph)
451
-
))),
359
+
_ => Err(ExecutionError::ExpectedInteger(format!("got {}", self))),
452
360
}
453
361
}
454
362
455
-
pub fn as_integer(&self, graph: &Graph) -> Result<u32, ExecutionError> {
363
+
pub fn as_integer(&self) -> Result<u32, ExecutionError> {
456
364
match self {
457
365
Value::Integer(value) => Ok(*value),
458
-
_ => Err(ExecutionError::ExpectedInteger(format!(
459
-
"got {}",
460
-
self.display_with(graph)
461
-
))),
366
+
_ => Err(ExecutionError::ExpectedInteger(format!("got {}", self))),
462
367
}
463
368
}
464
369
465
370
/// Coerces this value into a string, returning an error if it's some other type of value.
466
-
pub fn into_string(self, graph: &Graph) -> Result<String, ExecutionError> {
371
+
pub fn into_string(self) -> Result<String, ExecutionError> {
467
372
match self {
468
373
Value::String(value) => Ok(value),
469
-
_ => Err(ExecutionError::ExpectedString(format!(
470
-
"got {}",
471
-
self.display_with(graph)
472
-
))),
374
+
_ => Err(ExecutionError::ExpectedString(format!("got {}", self))),
473
375
}
474
376
}
475
377
476
-
pub fn as_string(&self, graph: &Graph) -> Result<&str, ExecutionError> {
378
+
pub fn as_str(&self) -> Result<&str, ExecutionError> {
477
379
match self {
478
380
Value::String(value) => Ok(value),
479
-
_ => Err(ExecutionError::ExpectedString(format!(
480
-
"got {}",
481
-
self.display_with(graph)
482
-
))),
381
+
_ => Err(ExecutionError::ExpectedString(format!("got {}", self))),
483
382
}
484
383
}
485
384
486
385
/// Coerces this value into a list, returning an error if it's some other type of value.
487
-
pub fn into_list(self, graph: &Graph) -> Result<Vec<Value>, ExecutionError> {
386
+
pub fn into_list(self) -> Result<Vec<Value>, ExecutionError> {
488
387
match self {
489
388
Value::List(values) => Ok(values),
490
-
_ => Err(ExecutionError::ExpectedList(format!(
491
-
"got {}",
492
-
self.display_with(graph)
493
-
))),
389
+
_ => Err(ExecutionError::ExpectedList(format!("got {}", self))),
494
390
}
495
391
}
496
392
497
-
pub fn as_list(&self, graph: &Graph) -> Result<&Vec<Value>, ExecutionError> {
393
+
pub fn as_list(&self) -> Result<&Vec<Value>, ExecutionError> {
498
394
match self {
499
395
Value::List(values) => Ok(values),
500
-
_ => Err(ExecutionError::ExpectedList(format!(
501
-
"got {}",
502
-
self.display_with(graph)
503
-
))),
396
+
_ => Err(ExecutionError::ExpectedList(format!("got {}", self))),
504
397
}
505
398
}
506
399
507
400
/// Coerces this value into a graph node reference, returning an error if it's some other type
508
401
/// of value.
509
-
pub fn into_graph_node_ref<'a, 'tree>(
510
-
self,
511
-
graph: &'a Graph<'tree>,
512
-
) -> Result<GraphNodeRef, ExecutionError> {
402
+
pub fn into_graph_node_ref<'a, 'tree>(self) -> Result<GraphNodeRef, ExecutionError> {
513
403
match self {
514
404
Value::GraphNode(node) => Ok(node),
515
-
_ => Err(ExecutionError::ExpectedGraphNode(format!(
516
-
"got {}",
517
-
self.display_with(graph)
518
-
))),
405
+
_ => Err(ExecutionError::ExpectedGraphNode(format!("got {}", self))),
519
406
}
520
407
}
521
408
522
-
pub fn as_graph_node_ref<'a, 'tree>(
523
-
&self,
524
-
graph: &'a Graph<'tree>,
525
-
) -> Result<GraphNodeRef, ExecutionError> {
409
+
pub fn as_graph_node_ref<'a, 'tree>(&self) -> Result<GraphNodeRef, ExecutionError> {
526
410
match self {
527
411
Value::GraphNode(node) => Ok(*node),
528
-
_ => Err(ExecutionError::ExpectedGraphNode(format!(
529
-
"got {}",
530
-
self.display_with(graph)
531
-
))),
412
+
_ => Err(ExecutionError::ExpectedGraphNode(format!("got {}", self))),
532
413
}
533
414
}
534
415
535
416
/// Coerces this value into a syntax node reference, returning an error if it's some other type
536
417
/// of value.
537
-
pub fn into_syntax_node_ref<'a, 'tree>(
538
-
self,
539
-
graph: &'a Graph<'tree>,
540
-
) -> Result<SyntaxNodeRef, ExecutionError> {
418
+
pub fn into_syntax_node_ref<'a, 'tree>(self) -> Result<SyntaxNodeRef, ExecutionError> {
541
419
match self {
542
420
Value::SyntaxNode(node) => Ok(node),
543
-
_ => Err(ExecutionError::ExpectedSyntaxNode(format!(
544
-
"got {}",
545
-
self.display_with(graph)
546
-
))),
421
+
_ => Err(ExecutionError::ExpectedSyntaxNode(format!("got {}", self))),
547
422
}
548
423
}
549
424
···
554
429
self,
555
430
graph: &'a Graph<'tree>,
556
431
) -> Result<&'a Node<'tree>, ExecutionError> {
557
-
Ok(&graph[self.into_syntax_node_ref(graph)?])
432
+
Ok(&graph[self.into_syntax_node_ref()?])
558
433
}
559
434
560
-
pub fn as_syntax_node_ref<'a, 'tree>(
561
-
&self,
562
-
graph: &'a Graph<'tree>,
563
-
) -> Result<SyntaxNodeRef, ExecutionError> {
435
+
pub fn as_syntax_node_ref<'a, 'tree>(&self) -> Result<SyntaxNodeRef, ExecutionError> {
564
436
match self {
565
437
Value::SyntaxNode(node) => Ok(*node),
566
-
_ => Err(ExecutionError::ExpectedSyntaxNode(format!(
567
-
"got {}",
568
-
self.display_with(graph)
569
-
))),
438
+
_ => Err(ExecutionError::ExpectedSyntaxNode(format!("got {}", self))),
570
439
}
571
440
}
572
441
}
···
601
470
}
602
471
}
603
472
604
-
impl DisplayWithGraph for Value {
605
-
fn fmt(&self, f: &mut fmt::Formatter, graph: &Graph) -> fmt::Result {
473
+
impl std::fmt::Display for Value {
474
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
606
475
match self {
607
476
Value::Null => write!(f, "#null"),
608
477
Value::Boolean(value) => {
···
619
488
let mut first = true;
620
489
for element in value {
621
490
if first {
622
-
write!(f, "{}", element.display_with(graph))?;
491
+
write!(f, "{}", element)?;
623
492
first = false;
624
493
} else {
625
-
write!(f, ", {}", element.display_with(graph))?;
494
+
write!(f, ", {}", element)?;
626
495
}
627
496
}
628
497
write!(f, "]")
···
632
501
let mut first = true;
633
502
for element in value {
634
503
if first {
635
-
write!(f, "{}", element.display_with(graph))?;
504
+
write!(f, "{}", element)?;
636
505
first = false;
637
506
} else {
638
-
write!(f, ", {}", element.display_with(graph))?;
507
+
write!(f, ", {}", element)?;
639
508
}
640
509
}
641
510
write!(f, "}}")
642
511
}
643
-
Value::SyntaxNode(node) => node.fmt(f, graph),
644
-
Value::GraphNode(node) => node.fmt(f, graph),
512
+
Value::SyntaxNode(node) => node.fmt(f),
513
+
Value::GraphNode(node) => node.fmt(f),
514
+
}
515
+
}
516
+
}
517
+
518
+
impl Serialize for Value {
519
+
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
520
+
match self {
521
+
Value::Null => serializer.serialize_none(),
522
+
Value::Boolean(value) => serializer.serialize_bool(*value),
523
+
Value::Integer(value) => serializer.serialize_u32(*value),
524
+
Value::String(value) => serializer.serialize_str(value),
525
+
// FIXME: there's no way to distinguish sets and lists, so we can't roundtrip accurately
526
+
Value::List(list) => serializer.collect_seq(list),
527
+
Value::Set(set) => serializer.collect_seq(set),
528
+
// FIXME: we don't distinguish between syntax tree node IDs, graph node IDs, and integers
529
+
Value::SyntaxNode(node) => serializer.serialize_u32(node.index),
530
+
Value::GraphNode(node) => serializer.serialize_u32(node.0),
645
531
}
646
532
}
647
533
}
648
534
649
535
/// A reference to a syntax node in a graph
650
536
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
651
-
pub struct SyntaxNodeRef(SyntaxNodeID);
537
+
pub struct SyntaxNodeRef {
538
+
index: SyntaxNodeID,
539
+
kind: &'static str,
540
+
position: tree_sitter::Point,
541
+
}
652
542
653
543
impl From<SyntaxNodeRef> for Value {
654
544
fn from(value: SyntaxNodeRef) -> Value {
···
656
546
}
657
547
}
658
548
659
-
impl DisplayWithGraph for SyntaxNodeRef {
660
-
fn fmt(&self, f: &mut fmt::Formatter, graph: &Graph) -> fmt::Result {
661
-
let node = graph[*self];
662
-
write!(f, "{}", format_node(&node))
549
+
impl std::fmt::Display for SyntaxNodeRef {
550
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
551
+
write!(
552
+
f,
553
+
"[syntax node {} ({}, {})]",
554
+
self.kind,
555
+
self.position.row + 1,
556
+
self.position.column + 1,
557
+
)
663
558
}
664
559
}
665
560
666
-
pub fn format_node(node: &Node) -> String {
667
-
format!(
668
-
"[syntax node {} ({}, {})]",
669
-
node.kind(),
670
-
node.start_position().row + 1,
671
-
node.start_position().column + 1
672
-
)
673
-
}
674
-
675
561
/// A reference to a graph node
676
562
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
677
563
pub struct GraphNodeRef(GraphNodeID);
678
564
565
+
impl GraphNodeRef {
566
+
/// Returns the index of the graph node that this reference refers to.
567
+
pub fn index(self) -> usize {
568
+
self.0 as usize
569
+
}
570
+
}
571
+
679
572
impl From<GraphNodeRef> for Value {
680
573
fn from(value: GraphNodeRef) -> Value {
681
574
Value::GraphNode(value)
682
575
}
683
576
}
684
577
685
-
impl DisplayWithGraph for GraphNodeRef {
686
-
fn fmt(&self, f: &mut fmt::Formatter, _graph: &Graph) -> fmt::Result {
578
+
impl std::fmt::Display for GraphNodeRef {
579
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
687
580
write!(f, "[graph node {}]", self.0)
688
581
}
689
582
}
690
-
691
-
/// Trait to Display with a given Context
692
-
pub trait DisplayWithGraph
693
-
where
694
-
Self: Sized,
695
-
{
696
-
fn fmt<'tree>(&self, f: &mut fmt::Formatter, graph: &Graph<'tree>) -> fmt::Result;
697
-
698
-
fn display_with<'a, 'tree>(&'a self, graph: &'a Graph<'tree>) -> Box<dyn fmt::Display + 'a> {
699
-
struct Impl<'a, 'tree, T: DisplayWithGraph>(&'a T, &'a Graph<'tree>);
700
-
701
-
impl<'a, 'tree, T: DisplayWithGraph> fmt::Display for Impl<'a, 'tree, T> {
702
-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
703
-
self.0.fmt(f, self.1)
704
-
}
705
-
}
706
-
707
-
Box::new(Impl(self, graph))
708
-
}
709
-
}
+32
-104
src/lazy_execution.rs
+32
-104
src/lazy_execution.rs
···
13
13
use log::{debug, trace};
14
14
15
15
use std::collections::HashMap;
16
-
use std::fmt;
17
16
18
17
use tree_sitter::CaptureQuantifier::One;
19
18
use tree_sitter::QueryCursor;
···
25
24
use crate::execution::ExecutionError;
26
25
use crate::functions::Functions;
27
26
use crate::graph;
28
-
use crate::graph::DisplayWithGraph as _;
29
27
use crate::graph::Graph;
30
28
use crate::variables::Globals;
31
29
use crate::variables::VariableMap;
32
30
use crate::variables::Variables;
33
-
use crate::Context;
34
-
use crate::DisplayWithContext as _;
35
31
use crate::Identifier;
36
32
37
33
use statements::*;
···
44
40
/// provide the set of functions and global variables that are available during execution.
45
41
pub fn execute_lazy<'tree>(
46
42
&self,
47
-
ctx: &Context,
48
43
tree: &'tree Tree,
49
44
source: &'tree str,
50
45
functions: &mut Functions,
51
46
globals: &Globals,
52
47
) -> Result<Graph<'tree>, ExecutionError> {
53
48
let mut graph = Graph::new();
54
-
self.execute_lazy_into(ctx, &mut graph, tree, source, functions, globals)?;
49
+
self.execute_lazy_into(&mut graph, tree, source, functions, globals)?;
55
50
Ok(graph)
56
51
}
57
52
···
62
57
/// “pre-seed” the graph with some predefined nodes and/or edges before executing the DSL file.
63
58
pub fn execute_lazy_into<'tree>(
64
59
&self,
65
-
ctx: &Context,
66
60
graph: &mut Graph<'tree>,
67
61
tree: &'tree Tree,
68
62
source: &'tree str,
···
85
79
for mat in matches {
86
80
let stanza = &self.stanzas[mat.pattern_index];
87
81
stanza.execute_lazy(
88
-
ctx,
89
82
source,
90
83
&mat,
91
84
graph,
···
103
96
for graph_stmt in &lazy_graph {
104
97
graph_stmt
105
98
.evaluate(&mut EvaluationContext {
106
-
ctx,
107
99
source,
108
100
graph,
109
101
functions,
···
112
104
function_parameters: &mut function_parameters,
113
105
prev_element_debug_info: &mut prev_element_debug_info,
114
106
})
115
-
.with_context(|| format!("Executing {}", graph_stmt.display_with(ctx, &graph)))?;
107
+
.with_context(|| format!("Executing {}", graph_stmt))?;
116
108
}
117
109
118
110
Ok(())
···
121
113
122
114
/// Context for execution, which executes stanzas to build the lazy graph
123
115
struct ExecutionContext<'a, 'g, 'tree> {
124
-
ctx: &'a Context,
125
116
source: &'tree str,
126
117
graph: &'a mut Graph<'tree>,
127
118
functions: &'a mut Functions,
···
138
129
139
130
/// Context for evaluation, which evalautes the lazy graph to build the actual graph
140
131
pub(self) struct EvaluationContext<'a, 'tree> {
141
-
pub ctx: &'a Context,
142
132
pub source: &'tree str,
143
133
pub graph: &'a mut Graph<'tree>,
144
134
pub functions: &'a mut Functions,
···
158
148
impl ast::Stanza {
159
149
fn execute_lazy<'l, 'g, 'q, 'tree>(
160
150
&self,
161
-
ctx: &Context,
162
151
source: &'tree str,
163
152
mat: &QueryMatch<'_, 'tree>,
164
153
graph: &mut Graph<'tree>,
···
174
163
let current_regex_captures = vec![];
175
164
locals.clear();
176
165
let mut exec = ExecutionContext {
177
-
ctx,
178
166
source,
179
167
graph,
180
168
functions,
···
189
177
prev_element_debug_info,
190
178
};
191
179
let node = query_capture_value(self.full_match_file_capture_index, One, &mat, exec.graph);
192
-
debug!(
193
-
"match {} at {}",
194
-
node.display_with(exec.graph),
195
-
self.location
196
-
);
180
+
debug!("match {} at {}", node, self.location);
197
181
trace!("{{");
198
182
for statement in &self.statements {
199
183
statement
200
184
.execute_lazy(&mut exec)
201
-
.with_context(|| format!("Executing {}", statement.display_with(exec.ctx)))?;
185
+
.with_context(|| format!("Executing {}", statement))?;
202
186
}
203
187
trace!("}}");
204
188
Ok(())
···
290
274
291
275
impl ast::Scan {
292
276
fn execute_lazy(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
293
-
let match_string = self.value.evaluate_eager(exec)?.into_string(exec.graph)?;
277
+
let match_string = self.value.evaluate_eager(exec)?.into_string()?;
294
278
295
279
let mut i = 0;
296
280
let mut matches = Vec::new();
···
329
313
330
314
let mut arm_locals = VariableMap::new_child(exec.locals);
331
315
let mut arm_exec = ExecutionContext {
332
-
ctx: exec.ctx,
333
316
source: exec.source,
334
317
graph: exec.graph,
335
318
functions: exec.functions,
···
347
330
for statement in &arm.statements {
348
331
statement
349
332
.execute_lazy(&mut arm_exec)
350
-
.with_context(|| format!("Executing {}", statement.display_with(arm_exec.ctx)))
333
+
.with_context(|| format!("Executing {}", statement))
351
334
.with_context(|| {
352
335
format!(
353
336
"Matching {} with arm \"{}\" {{ ... }}",
···
390
373
if result {
391
374
let mut arm_locals = VariableMap::new_child(exec.locals);
392
375
let mut arm_exec = ExecutionContext {
393
-
ctx: exec.ctx,
394
376
source: exec.source,
395
377
graph: exec.graph,
396
378
functions: exec.functions,
···
421
403
match self {
422
404
Self::Some { value, .. } => Ok(!value.evaluate_eager(exec)?.is_null()),
423
405
Self::None { value, .. } => Ok(value.evaluate_eager(exec)?.is_null()),
424
-
Self::Bool { value, .. } => Ok(value.evaluate_eager(exec)?.into_bool(exec.graph)?),
406
+
Self::Bool { value, .. } => Ok(value.evaluate_eager(exec)?.into_boolean()?),
425
407
}
426
408
}
427
409
}
428
410
429
411
impl ast::ForIn {
430
412
fn execute_lazy(&self, exec: &mut ExecutionContext) -> Result<(), ExecutionError> {
431
-
let values = self.value.evaluate_eager(exec)?.into_list(exec.graph)?;
413
+
let values = self.value.evaluate_eager(exec)?.into_list()?;
432
414
let mut loop_locals = VariableMap::new_child(exec.locals);
433
415
for value in values {
434
416
loop_locals.clear();
435
417
let mut loop_exec = ExecutionContext {
436
-
ctx: exec.ctx,
437
418
source: exec.source,
438
419
graph: exec.graph,
439
420
functions: exec.functions,
···
478
459
// only be called on expressions that are local (i.e., `is_local = true` in the checker).
479
460
fn evaluate_eager(&self, exec: &mut ExecutionContext) -> Result<graph::Value, ExecutionError> {
480
461
self.evaluate_lazy(exec)?.evaluate(&mut EvaluationContext {
481
-
ctx: exec.ctx,
482
462
source: exec.source,
483
463
graph: exec.graph,
484
464
functions: exec.functions,
···
540
520
for parameter in &self.parameters {
541
521
parameters.push(parameter.evaluate_lazy(exec)?);
542
522
}
543
-
Ok(LazyCall::new(self.function, parameters).into())
523
+
Ok(LazyCall::new(self.function.clone(), parameters).into())
544
524
}
545
525
}
546
526
···
588
568
impl ast::ScopedVariable {
589
569
fn evaluate_lazy(&self, exec: &mut ExecutionContext) -> Result<LazyValue, ExecutionError> {
590
570
let scope = self.scope.evaluate_lazy(exec)?;
591
-
let value = LazyScopedVariable::new(scope, self.name);
571
+
let value = LazyScopedVariable::new(scope, self.name.clone());
592
572
Ok(value.into())
593
573
}
594
574
···
601
581
if mutable {
602
582
return Err(ExecutionError::CannotDefineMutableScopedVariable(format!(
603
583
"{}",
604
-
self.display_with(exec.ctx)
584
+
self
605
585
)));
606
586
}
607
587
let scope = self.scope.evaluate_lazy(exec)?;
608
-
let variable = exec
609
-
.store
610
-
.add(value, self.location.into(), exec.ctx, exec.graph);
588
+
let variable = exec.store.add(value, self.location.into());
611
589
exec.scoped_store.add(
612
590
scope,
613
-
self.name,
591
+
self.name.clone(),
614
592
variable.into(),
615
593
self.location.into(),
616
-
exec.ctx,
617
594
)
618
595
}
619
596
620
597
fn set_lazy(
621
598
&self,
622
-
exec: &mut ExecutionContext,
599
+
_exec: &mut ExecutionContext,
623
600
_value: LazyValue,
624
601
) -> Result<(), ExecutionError> {
625
602
Err(ExecutionError::CannotAssignScopedVariable(format!(
626
603
"{}",
627
-
self.display_with(exec.ctx)
604
+
self
628
605
)))
629
606
}
630
607
}
···
636
613
} else {
637
614
exec.locals.get(&self.name).map(|value| value.clone())
638
615
}
639
-
.ok_or_else(|| {
640
-
ExecutionError::UndefinedVariable(format!("{}", self.display_with(exec.ctx)))
641
-
})
616
+
.ok_or_else(|| ExecutionError::UndefinedVariable(format!("{}", self)))
642
617
}
643
618
}
644
619
···
652
627
if exec.globals.get(&self.name).is_some() {
653
628
return Err(ExecutionError::DuplicateVariable(format!(
654
629
" global {}",
655
-
self.display_with(exec.ctx)
630
+
self
656
631
)));
657
632
}
658
-
let value = exec
659
-
.store
660
-
.add(value, self.location.into(), exec.ctx, exec.graph);
633
+
let value = exec.store.add(value, self.location.into());
661
634
exec.locals
662
-
.add(self.name, value.into(), mutable)
663
-
.map_err(|_| {
664
-
ExecutionError::DuplicateVariable(format!(" local {}", self.display_with(exec.ctx)))
665
-
})
635
+
.add(self.name.clone(), value.into(), mutable)
636
+
.map_err(|_| ExecutionError::DuplicateVariable(format!(" local {}", self)))
666
637
}
667
638
668
639
fn set_lazy(
···
673
644
if exec.globals.get(&self.name).is_some() {
674
645
return Err(ExecutionError::CannotAssignImmutableVariable(format!(
675
646
" global {}",
676
-
self.display_with(exec.ctx)
647
+
self
677
648
)));
678
649
}
679
-
let value = exec
680
-
.store
681
-
.add(value, self.location.into(), exec.ctx, exec.graph);
682
-
exec.locals.set(self.name, value.into()).map_err(|_| {
683
-
if exec.locals.get(&self.name).is_some() {
684
-
ExecutionError::CannotAssignImmutableVariable(format!(
685
-
"{}",
686
-
self.display_with(exec.ctx)
687
-
))
688
-
} else {
689
-
ExecutionError::UndefinedVariable(format!("{}", self.display_with(exec.ctx)))
690
-
}
691
-
})
650
+
let value = exec.store.add(value, self.location.into());
651
+
exec.locals
652
+
.set(self.name.clone(), value.into())
653
+
.map_err(|_| {
654
+
if exec.locals.get(&self.name).is_some() {
655
+
ExecutionError::CannotAssignImmutableVariable(format!("{}", self))
656
+
} else {
657
+
ExecutionError::UndefinedVariable(format!("{}", self))
658
+
}
659
+
})
692
660
}
693
661
}
694
662
695
663
impl ast::Attribute {
696
664
fn evaluate_lazy(&self, exec: &mut ExecutionContext) -> Result<LazyAttribute, ExecutionError> {
697
665
let value = self.value.evaluate_lazy(exec)?;
698
-
let attribute = LazyAttribute::new(self.name, value);
666
+
let attribute = LazyAttribute::new(self.name.clone(), value);
699
667
Ok(attribute)
700
668
}
701
669
}
702
-
703
-
/// Trait to Display with a given Context and Graph
704
-
pub trait DisplayWithContextAndGraph
705
-
where
706
-
Self: Sized,
707
-
{
708
-
fn fmt<'tree>(
709
-
&self,
710
-
f: &mut fmt::Formatter,
711
-
ctx: &Context,
712
-
graph: &Graph<'tree>,
713
-
) -> fmt::Result;
714
-
715
-
fn display_with<'a, 'tree>(
716
-
&'a self,
717
-
ctx: &'a Context,
718
-
graph: &'a Graph<'tree>,
719
-
) -> Box<dyn fmt::Display + 'a> {
720
-
struct Impl<'a, 'tree, T: DisplayWithContextAndGraph>(&'a T, &'a Context, &'a Graph<'tree>);
721
-
722
-
impl<'a, 'tree, T: DisplayWithContextAndGraph> fmt::Display for Impl<'a, 'tree, T> {
723
-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
724
-
self.0.fmt(f, self.1, self.2)
725
-
}
726
-
}
727
-
728
-
Box::new(Impl(self, ctx, graph))
729
-
}
730
-
}
731
-
732
-
impl<T: DisplayWithContextAndGraph> DisplayWithContextAndGraph for Box<T> {
733
-
fn fmt<'tree>(
734
-
&self,
735
-
f: &mut fmt::Formatter,
736
-
ctx: &Context,
737
-
graph: &Graph<'tree>,
738
-
) -> fmt::Result {
739
-
self.as_ref().fmt(f, ctx, graph)
740
-
}
741
-
}
+45
-62
src/lazy_execution/statements.rs
+45
-62
src/lazy_execution/statements.rs
···
13
13
use std::fmt;
14
14
15
15
use crate::execution::ExecutionError;
16
-
use crate::graph::DisplayWithGraph;
17
-
use crate::graph::Graph;
18
-
use crate::Context;
19
-
use crate::DisplayWithContext as _;
20
16
use crate::Identifier;
21
17
22
18
use super::store::DebugInfo;
23
19
use super::values::*;
24
-
use super::DisplayWithContextAndGraph;
25
20
use super::EvaluationContext;
26
21
use super::GraphElementKey;
27
22
···
36
31
37
32
impl LazyStatement {
38
33
pub(super) fn evaluate(&self, exec: &mut EvaluationContext) -> Result<(), ExecutionError> {
39
-
debug!("eval {}", self.display_with(exec.ctx, exec.graph));
34
+
debug!("eval {}", self);
40
35
trace!("{{");
41
36
let result = match self {
42
37
Self::AddGraphNodeAttribute(stmt) => stmt.evaluate(exec),
···
73
68
}
74
69
}
75
70
76
-
impl DisplayWithContextAndGraph for LazyStatement {
77
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context, graph: &Graph) -> fmt::Result {
71
+
impl fmt::Display for LazyStatement {
72
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78
73
match self {
79
-
Self::AddGraphNodeAttribute(stmt) => stmt.fmt(f, ctx, graph),
80
-
Self::CreateEdge(stmt) => stmt.fmt(f, ctx, graph),
81
-
Self::AddEdgeAttribute(stmt) => stmt.fmt(f, ctx, graph),
82
-
Self::Print(stmt) => stmt.fmt(f, ctx, graph),
74
+
Self::AddGraphNodeAttribute(stmt) => stmt.fmt(f),
75
+
Self::CreateEdge(stmt) => stmt.fmt(f),
76
+
Self::AddEdgeAttribute(stmt) => stmt.fmt(f),
77
+
Self::Print(stmt) => stmt.fmt(f),
83
78
}
84
79
}
85
80
}
···
110
105
for attribute in &self.attributes {
111
106
let value = attribute.value.evaluate(exec)?;
112
107
let prev_debug_info = exec.prev_element_debug_info.insert(
113
-
GraphElementKey::NodeAttribute(node, attribute.name),
108
+
GraphElementKey::NodeAttribute(node, attribute.name.clone()),
114
109
self.debug_info,
115
110
);
116
111
exec.graph[node]
117
112
.attributes
118
-
.add(attribute.name, value)
113
+
.add(attribute.name.clone(), value)
119
114
.map_err(|_| {
120
115
ExecutionError::DuplicateAttribute(format!(
121
116
"{} on {} at {} and {}",
122
-
attribute.name.display_with(exec.ctx),
123
-
node.display_with(exec.graph),
117
+
attribute.name,
118
+
node,
124
119
prev_debug_info.unwrap(),
125
120
self.debug_info,
126
121
))
···
130
125
}
131
126
}
132
127
133
-
impl DisplayWithContextAndGraph for LazyAddGraphNodeAttribute {
134
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context, graph: &Graph) -> fmt::Result {
135
-
write!(f, "attr ({})", self.node.display_with(ctx, graph))?;
128
+
impl fmt::Display for LazyAddGraphNodeAttribute {
129
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
130
+
write!(f, "attr ({})", self.node)?;
136
131
for attr in &self.attributes {
137
-
write!(f, " {}", attr.display_with(ctx, graph))?;
132
+
write!(f, " {}", attr)?;
138
133
}
139
134
write!(f, " at {}", self.debug_info)
140
135
}
···
166
161
if let Err(_) = exec.graph[source].add_edge(sink) {
167
162
Err(ExecutionError::DuplicateEdge(format!(
168
163
"({} -> {}) at {} and {}",
169
-
source.display_with(exec.graph),
170
-
sink.display_with(exec.graph),
164
+
source,
165
+
sink,
171
166
prev_debug_info.unwrap(),
172
167
self.debug_info,
173
168
)))?;
···
176
171
}
177
172
}
178
173
179
-
impl DisplayWithContextAndGraph for LazyCreateEdge {
180
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context, graph: &Graph) -> fmt::Result {
174
+
impl fmt::Display for LazyCreateEdge {
175
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
181
176
write!(
182
177
f,
183
178
"edge {} -> {} at {}",
184
-
self.source.display_with(ctx, graph),
185
-
self.sink.display_with(ctx, graph),
186
-
self.debug_info,
179
+
self.source, self.sink, self.debug_info,
187
180
)
188
181
}
189
182
}
···
221
214
Some(edge) => Ok(edge),
222
215
None => Err(ExecutionError::UndefinedEdge(format!(
223
216
"({} -> {}) at {}",
224
-
source.display_with(exec.graph),
225
-
sink.display_with(exec.graph),
226
-
self.debug_info,
217
+
source, sink, self.debug_info,
227
218
))),
228
219
}?;
229
220
let prev_debug_info = exec.prev_element_debug_info.insert(
230
-
GraphElementKey::EdgeAttribute(source, sink, attribute.name),
221
+
GraphElementKey::EdgeAttribute(source, sink, attribute.name.clone()),
231
222
self.debug_info,
232
223
);
233
-
edge.attributes.add(attribute.name, value).map_err(|_| {
234
-
ExecutionError::DuplicateAttribute(format!(
235
-
"{} on edge ({} -> {}) at {} and {}",
236
-
attribute.name.display_with(exec.ctx),
237
-
source.display_with(exec.graph),
238
-
sink.display_with(exec.graph),
239
-
prev_debug_info.unwrap(),
240
-
self.debug_info,
241
-
))
242
-
})?;
224
+
edge.attributes
225
+
.add(attribute.name.clone(), value)
226
+
.map_err(|_| {
227
+
ExecutionError::DuplicateAttribute(format!(
228
+
"{} on edge ({} -> {}) at {} and {}",
229
+
attribute.name,
230
+
source,
231
+
sink,
232
+
prev_debug_info.unwrap(),
233
+
self.debug_info,
234
+
))
235
+
})?;
243
236
}
244
237
Ok(())
245
238
}
246
239
}
247
240
248
-
impl DisplayWithContextAndGraph for LazyAddEdgeAttribute {
249
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context, graph: &Graph) -> fmt::Result {
250
-
write!(
251
-
f,
252
-
"attr ({} -> {})",
253
-
self.source.display_with(ctx, graph),
254
-
self.sink.display_with(ctx, graph),
255
-
)?;
241
+
impl fmt::Display for LazyAddEdgeAttribute {
242
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243
+
write!(f, "attr ({} -> {})", self.source, self.sink,)?;
256
244
for attr in &self.attributes {
257
-
write!(f, " {}", attr.display_with(ctx, graph),)?;
245
+
write!(f, " {}", attr,)?;
258
246
}
259
247
write!(f, " at {}", self.debug_info)
260
248
}
···
287
275
LazyPrintArgument::Text(string) => eprint!("{}", string),
288
276
LazyPrintArgument::Value(value) => {
289
277
let value = value.evaluate(exec)?;
290
-
eprint!("{}", value.display_with(exec.graph));
278
+
eprint!("{}", value);
291
279
}
292
280
}
293
281
}
···
296
284
}
297
285
}
298
286
299
-
impl DisplayWithContextAndGraph for LazyPrint {
300
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context, graph: &Graph) -> fmt::Result {
287
+
impl fmt::Display for LazyPrint {
288
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
301
289
write!(f, "print")?;
302
290
let mut first = true;
303
291
for argument in &self.arguments {
···
308
296
}
309
297
match argument {
310
298
LazyPrintArgument::Text(string) => write!(f, "\"{}\"", string)?,
311
-
LazyPrintArgument::Value(value) => write!(f, "{}", value.display_with(ctx, graph))?,
299
+
LazyPrintArgument::Value(value) => write!(f, "{}", value)?,
312
300
};
313
301
}
314
302
write!(f, " at {}", self.debug_info)
···
328
316
}
329
317
}
330
318
331
-
impl DisplayWithContextAndGraph for LazyAttribute {
332
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context, graph: &Graph) -> fmt::Result {
333
-
write!(
334
-
f,
335
-
"{} = {}",
336
-
self.name.display_with(ctx),
337
-
self.value.display_with(ctx, graph),
338
-
)
319
+
impl fmt::Display for LazyAttribute {
320
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
321
+
write!(f, "{} = {}", self.name, self.value,)
339
322
}
340
323
}
+26
-53
src/lazy_execution/store.rs
+26
-53
src/lazy_execution/store.rs
···
19
19
20
20
use crate::execution::ExecutionError;
21
21
use crate::graph;
22
-
use crate::graph::DisplayWithGraph;
23
-
use crate::graph::Graph;
24
22
use crate::graph::SyntaxNodeRef;
25
23
use crate::parser::Location;
26
-
use crate::Context;
27
-
use crate::DisplayWithContext;
28
24
use crate::Identifier;
29
25
30
26
use super::values::*;
31
-
use super::DisplayWithContextAndGraph;
32
27
use super::EvaluationContext;
33
28
34
29
/// Variable that points to a thunk in the store
···
50
45
}
51
46
}
52
47
53
-
impl DisplayWithContextAndGraph for LazyVariable {
54
-
fn fmt(&self, f: &mut fmt::Formatter, _ctx: &Context, _graph: &Graph) -> fmt::Result {
48
+
impl fmt::Display for LazyVariable {
49
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
55
50
write!(f, "(load {})", self.store_location)
56
51
}
57
52
}
···
69
64
}
70
65
}
71
66
72
-
pub(super) fn add(
73
-
&mut self,
74
-
value: LazyValue,
75
-
debug_info: DebugInfo,
76
-
ctx: &Context,
77
-
graph: &Graph,
78
-
) -> LazyVariable {
67
+
pub(super) fn add(&mut self, value: LazyValue, debug_info: DebugInfo) -> LazyVariable {
79
68
let store_location = self.elements.len();
80
69
let variable = LazyVariable::new(store_location);
81
-
trace!(
82
-
"store {} = {}",
83
-
store_location,
84
-
value.display_with(ctx, graph)
85
-
);
70
+
trace!("store {} = {}", store_location, value);
86
71
self.elements.push(Thunk::new(value, debug_info));
87
72
variable
88
73
}
···
94
79
) -> Result<graph::Value, ExecutionError> {
95
80
let variable = &self.elements[variable.store_location];
96
81
let debug_info = variable.debug_info;
97
-
let value = variable.force(exec).with_context(|| {
98
-
format!(
99
-
"via {} at {}",
100
-
(*variable.state.borrow()).display_with(exec.ctx, exec.graph),
101
-
debug_info
102
-
)
103
-
})?;
82
+
let value = variable
83
+
.force(exec)
84
+
.with_context(|| format!("via {} at {}", (*variable.state.borrow()), debug_info))?;
104
85
Ok(value)
105
86
}
106
87
}
···
123
104
name: Identifier,
124
105
value: LazyValue,
125
106
debug_info: DebugInfo,
126
-
ctx: &Context,
127
107
) -> Result<(), ExecutionError> {
128
108
let values = self
129
109
.variables
130
-
.entry(name)
110
+
.entry(name.clone())
131
111
.or_insert_with(|| Cell::new(ScopedValues::new()));
132
112
match values.replace(ScopedValues::Forcing) {
133
113
ScopedValues::Unforced(mut pairs) => {
···
136
116
Ok(())
137
117
}
138
118
ScopedValues::Forcing => Err(ExecutionError::RecursivelyDefinedScopedVariable(
139
-
format!("{}", name.display_with(ctx)),
119
+
format!("{}", name),
140
120
)),
141
121
ScopedValues::Forced(map) => {
142
122
values.replace(ScopedValues::Forced(map));
143
123
Err(ExecutionError::VariableScopesAlreadyForced(format!(
144
124
"{}",
145
-
name.display_with(ctx)
125
+
name
146
126
)))
147
127
}
148
128
}
···
150
130
151
131
pub(super) fn evaluate(
152
132
&self,
153
-
scope: SyntaxNodeRef,
154
-
name: Identifier,
133
+
scope: &SyntaxNodeRef,
134
+
name: &Identifier,
155
135
exec: &mut EvaluationContext,
156
136
) -> Result<LazyValue, ExecutionError> {
157
-
let values = match self.variables.get(&name) {
137
+
let values = match self.variables.get(name) {
158
138
Some(v) => v,
159
139
None => {
160
140
return Err(ExecutionError::UndefinedScopedVariable(format!(
161
141
"{}.{}",
162
-
scope.display_with(exec.graph),
163
-
name.display_with(exec.ctx),
142
+
scope, name,
164
143
)));
165
144
}
166
145
};
···
175
154
Some(_) => {
176
155
return Err(ExecutionError::DuplicateVariable(format!(
177
156
"{}.{} set at {} and {}",
178
-
node.display_with(exec.graph),
179
-
name.display_with(exec.ctx),
157
+
node,
158
+
name,
180
159
prev_debug_info.unwrap(),
181
160
debug_info,
182
161
)));
···
188
167
.get(&scope)
189
168
.ok_or(ExecutionError::UndefinedScopedVariable(format!(
190
169
"{}.{}",
191
-
scope.display_with(exec.graph),
192
-
name.display_with(exec.ctx),
170
+
scope, name,
193
171
)))?
194
172
.clone();
195
173
values.replace(ScopedValues::Forced(map));
196
174
Ok(result)
197
175
}
198
-
ScopedValues::Forcing => {
199
-
Err(ExecutionError::RecursivelyDefinedScopedVariable(format!(
200
-
"_.{} requested on {}",
201
-
name.display_with(exec.ctx),
202
-
scope.display_with(exec.graph)
203
-
)))
204
-
}
176
+
ScopedValues::Forcing => Err(ExecutionError::RecursivelyDefinedScopedVariable(
177
+
format!("_.{} requested on {}", name, scope),
178
+
)),
205
179
ScopedValues::Forced(map) => {
206
180
let result = map
207
181
.get(&scope)
208
182
.ok_or(ExecutionError::UndefinedScopedVariable(format!(
209
183
"{}.{}",
210
-
scope.display_with(exec.graph),
211
-
name.display_with(exec.ctx),
184
+
scope, name,
212
185
)))?
213
186
.clone();
214
187
values.replace(ScopedValues::Forced(map));
···
242
215
Forced(graph::Value),
243
216
}
244
217
245
-
impl DisplayWithContextAndGraph for ThunkState {
246
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context, graph: &Graph) -> fmt::Result {
218
+
impl fmt::Display for ThunkState {
219
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
247
220
match self {
248
-
Self::Unforced(value) => write!(f, "?{{{}}}", value.display_with(ctx, graph)),
221
+
Self::Unforced(value) => write!(f, "?{{{}}}", value),
249
222
Self::Forcing => write!(f, "~{{?}}"),
250
-
Self::Forced(value) => write!(f, "!{{{}}}", value.display_with(graph)),
223
+
Self::Forced(value) => write!(f, "!{{{}}}", value),
251
224
}
252
225
}
253
226
}
···
262
235
263
236
fn force(&self, exec: &mut EvaluationContext) -> Result<graph::Value, ExecutionError> {
264
237
let state = self.state.replace(ThunkState::Forcing);
265
-
trace!("force {}", state.display_with(exec.ctx, exec.graph));
238
+
trace!("force {}", state);
266
239
let value = match state {
267
240
ThunkState::Unforced(value) => {
268
241
// it is important that we do not hold a borrow of self.forced_values when executing self.value.evaluate
+29
-51
src/lazy_execution/values.rs
+29
-51
src/lazy_execution/values.rs
···
13
13
use std::fmt;
14
14
15
15
use crate::execution::ExecutionError;
16
-
use crate::graph::DisplayWithGraph;
17
-
use crate::graph::Graph;
18
16
use crate::graph::GraphNodeRef;
19
17
use crate::graph::SyntaxNodeRef;
20
18
use crate::graph::Value;
21
-
use crate::Context;
22
-
use crate::DisplayWithContext;
23
19
use crate::Identifier;
24
20
25
21
use super::store::*;
26
-
use super::DisplayWithContextAndGraph;
27
22
use super::EvaluationContext;
28
23
29
24
/// Lazy values
···
123
118
124
119
impl LazyValue {
125
120
pub(super) fn evaluate(&self, exec: &mut EvaluationContext) -> Result<Value, ExecutionError> {
126
-
trace!("eval {} {{", self.display_with(exec.ctx, exec.graph));
121
+
trace!("eval {} {{", self);
127
122
let ret = match self {
128
123
Self::Value(value) => Ok(value.clone()),
129
124
Self::List(expr) => expr.evaluate(exec),
···
132
127
Self::ScopedVariable(expr) => expr.evaluate(exec),
133
128
Self::Call(expr) => expr.evaluate(exec),
134
129
}?;
135
-
trace!("}} = {}", ret.display_with(exec.graph));
130
+
trace!("}} = {}", ret);
136
131
Ok(ret)
137
132
}
138
133
···
143
138
let node = self.evaluate(exec)?;
144
139
match node {
145
140
Value::GraphNode(node) => Ok(node),
146
-
_ => Err(ExecutionError::ExpectedGraphNode(format!(
147
-
" got {}",
148
-
node.display_with(exec.graph)
149
-
))),
141
+
_ => Err(ExecutionError::ExpectedGraphNode(format!(" got {}", node))),
150
142
}
151
143
}
152
144
···
157
149
let node = self.evaluate(exec)?;
158
150
match node {
159
151
Value::SyntaxNode(node) => Ok(node),
160
-
_ => Err(ExecutionError::ExpectedSyntaxNode(format!(
161
-
" got {}",
162
-
node.display_with(exec.graph)
163
-
))),
152
+
_ => Err(ExecutionError::ExpectedSyntaxNode(format!(" got {}", node))),
164
153
}
165
154
}
166
155
}
167
156
168
-
impl DisplayWithContextAndGraph for LazyValue {
169
-
fn fmt<'tree>(
170
-
&self,
171
-
f: &mut fmt::Formatter,
172
-
ctx: &Context,
173
-
graph: &Graph<'tree>,
174
-
) -> fmt::Result {
157
+
impl fmt::Display for LazyValue {
158
+
fn fmt<'tree>(&self, f: &mut fmt::Formatter) -> fmt::Result {
175
159
match self {
176
-
Self::Value(value) => write!(f, "{}", value.display_with(graph)),
177
-
Self::List(expr) => expr.fmt(f, ctx, graph),
178
-
Self::Set(expr) => expr.fmt(f, ctx, graph),
179
-
Self::Variable(expr) => expr.fmt(f, ctx, graph),
180
-
Self::ScopedVariable(expr) => expr.fmt(f, ctx, graph),
181
-
Self::Call(expr) => expr.fmt(f, ctx, graph),
160
+
Self::Value(value) => write!(f, "{}", value),
161
+
Self::List(expr) => expr.fmt(f),
162
+
Self::Set(expr) => expr.fmt(f),
163
+
Self::Variable(expr) => expr.fmt(f),
164
+
Self::ScopedVariable(expr) => expr.fmt(f),
165
+
Self::Call(expr) => expr.fmt(f),
182
166
}
183
167
}
184
168
}
···
201
185
fn resolve<'a>(&self, exec: &'a mut EvaluationContext) -> Result<LazyValue, ExecutionError> {
202
186
let scope = self.scope.as_ref().evaluate_as_syntax_node(exec)?;
203
187
let scoped_store = &exec.scoped_store;
204
-
scoped_store.evaluate(scope, self.name, exec)
188
+
scoped_store.evaluate(&scope, &self.name, exec)
205
189
}
206
190
207
191
pub(super) fn evaluate(&self, exec: &mut EvaluationContext) -> Result<Value, ExecutionError> {
···
210
194
}
211
195
}
212
196
213
-
impl DisplayWithContextAndGraph for LazyScopedVariable {
214
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context, graph: &Graph) -> fmt::Result {
215
-
write!(
216
-
f,
217
-
"(scoped {} '{})",
218
-
self.scope.display_with(ctx, graph),
219
-
self.name.display_with(ctx),
220
-
)
197
+
impl fmt::Display for LazyScopedVariable {
198
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
199
+
write!(f, "(scoped {} '{})", self.scope, self.name,)
221
200
}
222
201
}
223
202
···
242
221
}
243
222
}
244
223
245
-
impl DisplayWithContextAndGraph for LazyList {
246
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context, graph: &Graph) -> fmt::Result {
224
+
impl fmt::Display for LazyList {
225
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
247
226
write!(f, "(list")?;
248
227
let mut first = true;
249
228
for elem in &self.elements {
250
229
if first {
251
230
first = false;
252
-
write!(f, "{}", elem.display_with(ctx, graph))?;
231
+
write!(f, "{}", elem)?;
253
232
} else {
254
-
write!(f, " {}", elem.display_with(ctx, graph))?;
233
+
write!(f, " {}", elem)?;
255
234
}
256
235
}
257
236
write!(f, ")")
···
279
258
}
280
259
}
281
260
282
-
impl DisplayWithContextAndGraph for LazySet {
283
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context, graph: &Graph) -> fmt::Result {
261
+
impl fmt::Display for LazySet {
262
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
284
263
write!(f, "(set")?;
285
264
let mut first = true;
286
265
for elem in &self.elements {
287
266
if first {
288
267
first = false;
289
-
write!(f, "{}", elem.display_with(ctx, graph))?;
268
+
write!(f, "{}", elem)?;
290
269
} else {
291
-
write!(f, " {}", elem.display_with(ctx, graph))?;
270
+
write!(f, " {}", elem)?;
292
271
}
293
272
}
294
273
write!(f, ")")
···
317
296
}
318
297
319
298
exec.functions.call(
320
-
exec.ctx,
321
-
self.function,
299
+
&self.function,
322
300
exec.graph,
323
301
exec.source,
324
302
&mut exec
···
328
306
}
329
307
}
330
308
331
-
impl DisplayWithContextAndGraph for LazyCall {
332
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context, graph: &Graph) -> fmt::Result {
333
-
write!(f, "(call '{}", self.function.display_with(ctx))?;
309
+
impl fmt::Display for LazyCall {
310
+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
311
+
write!(f, "(call '{}", self.function)?;
334
312
for arg in &self.arguments {
335
-
write!(f, " {}", arg.display_with(ctx, graph))?;
313
+
write!(f, " {}", arg)?;
336
314
}
337
315
write!(f, ")")
338
316
}
+47
-46
src/lib.rs
+47
-46
src/lib.rs
···
42
42
pub use parser::Location;
43
43
pub use parser::ParseError;
44
44
45
-
use string_interner::symbol::SymbolU32;
46
-
use string_interner::StringInterner;
45
+
use std::borrow::Borrow;
46
+
use std::hash::Hash;
47
+
use std::ops::Deref;
48
+
use std::rc::Rc;
47
49
48
-
use std::fmt;
50
+
use serde::Serialize;
51
+
use serde::Serializer;
49
52
50
53
/// An identifier that appears in a graph DSL file or in the graph that is produced as an output.
51
-
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
52
-
pub struct Identifier(SymbolU32);
54
+
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
55
+
pub struct Identifier(Rc<String>);
53
56
54
-
impl DisplayWithContext for Identifier {
55
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
56
-
write!(f, "{}", ctx.identifiers.resolve(self.0).unwrap())
57
+
impl Identifier {
58
+
pub fn as_str(&self) -> &str {
59
+
self.0.as_str()
60
+
}
61
+
62
+
pub fn into_string(mut self) -> String {
63
+
Rc::make_mut(&mut self.0);
64
+
Rc::try_unwrap(self.0).unwrap()
57
65
}
58
66
}
59
67
60
-
/// A context in which graph DSL files are executed.
61
-
#[derive(Default)]
62
-
pub struct Context {
63
-
identifiers: StringInterner,
68
+
impl Borrow<str> for Identifier {
69
+
fn borrow(&self) -> &str {
70
+
self.as_str()
71
+
}
64
72
}
65
73
66
-
impl Context {
67
-
/// Creates a new, empty execution context.
68
-
pub fn new() -> Context {
69
-
Context::default()
74
+
impl Deref for Identifier {
75
+
type Target = str;
76
+
fn deref(&self) -> &str {
77
+
self.as_str()
70
78
}
79
+
}
71
80
72
-
/// Adds an identifier to the context.
73
-
#[inline(always)]
74
-
pub fn add_identifier<T: AsRef<str>>(&mut self, identifier: T) -> Identifier {
75
-
Identifier(self.identifiers.get_or_intern(identifier))
81
+
impl std::fmt::Display for Identifier {
82
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
83
+
self.0.fmt(f)
76
84
}
85
+
}
77
86
78
-
/// Returns the [`Identifier`][] instance for an identifier, if it has already been added to
79
-
/// the context. Returns `None` otherwise.
80
-
#[inline(always)]
81
-
pub fn get_identifier<T: AsRef<str>>(&self, identifier: T) -> Option<Identifier> {
82
-
self.identifiers.get(identifier).map(Identifier)
87
+
impl From<&str> for Identifier {
88
+
fn from(value: &str) -> Identifier {
89
+
Identifier(Rc::new(String::from(value)))
83
90
}
91
+
}
84
92
85
-
pub fn resolve(&self, identifier: Identifier) -> &str {
86
-
self.identifiers.resolve(identifier.0).unwrap()
93
+
impl Hash for Identifier {
94
+
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
95
+
self.0.hash(state);
87
96
}
88
97
}
89
98
90
-
/// Trait to Display with a given Context
91
-
pub trait DisplayWithContext
92
-
where
93
-
Self: Sized,
94
-
{
95
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result;
96
-
97
-
fn display_with<'a>(&'a self, ctx: &'a Context) -> Box<dyn fmt::Display + 'a> {
98
-
struct Impl<'a, T: DisplayWithContext>(&'a T, &'a Context);
99
+
impl PartialEq<str> for Identifier {
100
+
fn eq(&self, other: &str) -> bool {
101
+
self.as_str() == other
102
+
}
103
+
}
99
104
100
-
impl<'a, T: DisplayWithContext> fmt::Display for Impl<'a, T> {
101
-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
102
-
self.0.fmt(f, self.1)
103
-
}
104
-
}
105
-
106
-
Box::new(Impl(self, ctx))
105
+
impl<'a> PartialEq<&'a str> for Identifier {
106
+
fn eq(&self, other: &&'a str) -> bool {
107
+
self.as_str() == *other
107
108
}
108
109
}
109
110
110
-
impl<T: DisplayWithContext> DisplayWithContext for Box<T> {
111
-
fn fmt(&self, f: &mut fmt::Formatter, ctx: &Context) -> fmt::Result {
112
-
self.as_ref().fmt(f, ctx)
111
+
impl Serialize for Identifier {
112
+
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
113
+
serializer.serialize_str(self.as_str())
113
114
}
114
115
}
+50
-83
src/parser.rs
+50
-83
src/parser.rs
···
17
17
use tree_sitter::QueryError;
18
18
19
19
use crate::ast;
20
-
use crate::Context;
21
20
use crate::Identifier;
22
21
23
22
pub const FULL_MATCH: &str = "__tsg__full_match";
24
23
25
24
impl ast::File {
26
25
/// Parses a graph DSL file, returning a new `File` instance.
27
-
pub fn from_str(
28
-
language: Language,
29
-
ctx: &mut Context,
30
-
source: &str,
31
-
) -> Result<Self, ParseError> {
26
+
pub fn from_str(language: Language, source: &str) -> Result<Self, ParseError> {
32
27
let mut file = ast::File::new(language);
33
28
#[allow(deprecated)]
34
-
file.parse(ctx, source)?;
35
-
file.check(ctx)?;
29
+
file.parse(source)?;
30
+
file.check()?;
36
31
Ok(file)
37
32
}
38
33
···
40
35
#[deprecated(
41
36
note = "Parsing multiple times into the same `File` instance is unsound. Use `File::from_str` instead."
42
37
)]
43
-
pub fn parse(&mut self, ctx: &mut Context, content: &str) -> Result<(), ParseError> {
44
-
Parser::new(ctx, content).parse_into_file(self)
38
+
pub fn parse(&mut self, content: &str) -> Result<(), ParseError> {
39
+
Parser::new(content).parse_into_file(self)
45
40
}
46
41
}
47
42
···
72
67
UnexpectedLiteral(String, Location),
73
68
#[error(transparent)]
74
69
Check(#[from] crate::checker::CheckError),
70
+
#[error(transparent)]
71
+
Other(#[from] anyhow::Error),
72
+
}
73
+
74
+
impl ParseError {
75
+
/// Wraps an existing [`std::error::Error`][] as an execution error
76
+
pub fn other<E>(err: E) -> ParseError
77
+
where
78
+
E: Into<anyhow::Error>,
79
+
{
80
+
Self::Other(err.into())
81
+
}
75
82
}
76
83
77
84
/// The location of a graph DSL entity within its file
···
99
106
}
100
107
101
108
struct Parser<'a> {
102
-
ctx: &'a mut Context,
103
109
source: &'a str,
104
110
chars: Peekable<Chars<'a>>,
105
111
offset: usize,
106
112
location: Location,
107
113
query_source: String,
108
-
// Keywords
109
-
attr_keyword: Identifier,
110
-
edge_keyword: Identifier,
111
-
false_keyword: Identifier,
112
-
for_keyword: Identifier,
113
-
if_keyword: Identifier,
114
-
let_keyword: Identifier,
115
-
node_keyword: Identifier,
116
-
null_keyword: Identifier,
117
-
print_keyword: Identifier,
118
-
scan_keyword: Identifier,
119
-
set_keyword: Identifier,
120
-
true_keyword: Identifier,
121
-
var_keyword: Identifier,
122
114
}
123
115
124
116
fn is_ident_start(c: char) -> bool {
···
130
122
}
131
123
132
124
impl<'a> Parser<'a> {
133
-
fn new(ctx: &'a mut Context, source: &'a str) -> Parser<'a> {
125
+
fn new(source: &'a str) -> Parser<'a> {
134
126
let chars = source.chars().peekable();
135
127
let query_source = String::with_capacity(source.len());
136
-
// Keywords
137
-
let attr_keyword = ctx.add_identifier("attr");
138
-
let edge_keyword = ctx.add_identifier("edge");
139
-
let false_keyword = ctx.add_identifier("false");
140
-
let for_keyword = ctx.add_identifier("for");
141
-
let if_keyword = ctx.add_identifier("if");
142
-
let let_keyword = ctx.add_identifier("let");
143
-
let node_keyword = ctx.add_identifier("node");
144
-
let null_keyword = ctx.add_identifier("null");
145
-
let print_keyword = ctx.add_identifier("print");
146
-
let scan_keyword = ctx.add_identifier("scan");
147
-
let set_keyword = ctx.add_identifier("set");
148
-
let true_keyword = ctx.add_identifier("true");
149
-
let var_keyword = ctx.add_identifier("var");
150
128
Parser {
151
-
ctx,
152
129
source,
153
130
chars,
154
131
offset: 0,
155
132
location: Location::default(),
156
133
query_source,
157
-
// Keywords
158
-
attr_keyword,
159
-
edge_keyword,
160
-
false_keyword,
161
-
for_keyword,
162
-
let_keyword,
163
-
if_keyword,
164
-
node_keyword,
165
-
null_keyword,
166
-
print_keyword,
167
-
scan_keyword,
168
-
set_keyword,
169
-
true_keyword,
170
-
var_keyword,
171
134
}
172
135
}
173
136
}
174
137
175
-
impl Parser<'_> {
138
+
impl<'a> Parser<'a> {
176
139
fn peek(&mut self) -> Result<char, ParseError> {
177
140
self.chars
178
141
.peek()
···
331
294
Ok(statements)
332
295
}
333
296
297
+
fn parse_name(&mut self, within: &'static str) -> Result<&'a str, ParseError> {
298
+
let start = self.offset;
299
+
let ch = self.next()?;
300
+
if !is_ident_start(ch) {
301
+
return Err(ParseError::UnexpectedCharacter(ch, within, self.location));
302
+
}
303
+
self.consume_while(is_ident);
304
+
let end = self.offset;
305
+
Ok(&self.source[start..end])
306
+
}
307
+
334
308
fn parse_statement(&mut self) -> Result<ast::Statement, ParseError> {
335
309
let keyword_location = self.location;
336
-
let keyword = self.parse_identifier("keyword")?;
310
+
let keyword = self.parse_name("keyword")?;
337
311
self.consume_whitespace();
338
-
if keyword == self.let_keyword {
312
+
if keyword == "let" {
339
313
let variable = self.parse_variable()?;
340
314
self.consume_whitespace();
341
315
self.consume_token("=")?;
···
347
321
location: keyword_location,
348
322
}
349
323
.into())
350
-
} else if keyword == self.var_keyword {
324
+
} else if keyword == "var" {
351
325
let variable = self.parse_variable()?;
352
326
self.consume_whitespace();
353
327
self.consume_token("=")?;
···
359
333
location: keyword_location,
360
334
}
361
335
.into())
362
-
} else if keyword == self.set_keyword {
336
+
} else if keyword == "set" {
363
337
let variable = self.parse_variable()?;
364
338
self.consume_whitespace();
365
339
self.consume_token("=")?;
···
371
345
location: keyword_location,
372
346
}
373
347
.into())
374
-
} else if keyword == self.node_keyword {
348
+
} else if keyword == "node" {
375
349
let node = self.parse_variable()?;
376
350
Ok(ast::CreateGraphNode {
377
351
node,
378
352
location: keyword_location,
379
353
}
380
354
.into())
381
-
} else if keyword == self.edge_keyword {
355
+
} else if keyword == "edge" {
382
356
let source = self.parse_expression()?;
383
357
self.consume_whitespace();
384
358
self.consume_token("->")?;
···
390
364
location: keyword_location,
391
365
}
392
366
.into())
393
-
} else if keyword == self.attr_keyword {
367
+
} else if keyword == "attr" {
394
368
self.consume_token("(")?;
395
369
self.consume_whitespace();
396
370
let node_or_source = self.parse_expression()?;
···
425
399
}
426
400
.into())
427
401
}
428
-
} else if keyword == self.print_keyword {
402
+
} else if keyword == "print" {
429
403
let mut values = vec![self.parse_expression()?];
430
404
self.consume_whitespace();
431
405
while self.try_peek() == Some(',') {
···
440
414
location: keyword_location,
441
415
}
442
416
.into())
443
-
} else if keyword == self.scan_keyword {
417
+
} else if keyword == "scan" {
444
418
let value = self.parse_expression()?;
445
419
self.consume_whitespace();
446
420
self.consume_token("{")?;
···
467
441
location: keyword_location,
468
442
}
469
443
.into())
470
-
} else if keyword == self.if_keyword {
444
+
} else if keyword == "if" {
471
445
let mut arms = Vec::new();
472
446
473
447
// if
···
520
494
location: keyword_location,
521
495
}
522
496
.into())
523
-
} else if keyword == self.for_keyword {
497
+
} else if keyword == "for" {
524
498
self.consume_whitespace();
525
499
let variable = match self.parse_variable()? {
526
500
ast::Variable::Unscoped(variable) => Ok(variable),
···
543
517
.into())
544
518
} else {
545
519
Err(ParseError::UnexpectedKeyword(
546
-
self.ctx.resolve(keyword).into(),
520
+
keyword.into(),
547
521
keyword_location,
548
522
))
549
523
}
···
590
564
}
591
565
592
566
fn parse_identifier(&mut self, within: &'static str) -> Result<Identifier, ParseError> {
593
-
let start = self.offset;
594
-
let ch = self.next()?;
595
-
if !is_ident_start(ch) {
596
-
return Err(ParseError::UnexpectedCharacter(ch, within, self.location));
597
-
}
598
-
self.consume_while(is_ident);
599
-
let end = self.offset;
600
-
Ok(self.ctx.add_identifier(&self.source[start..end]))
567
+
let content = self.parse_name(within)?;
568
+
Ok(Identifier::from(content))
601
569
}
602
570
603
571
fn parse_string(&mut self) -> Result<String, ParseError> {
···
727
695
}
728
696
self.consume_while(is_ident);
729
697
let end = self.offset;
730
-
let name = &self.source[start + 1..end];
731
-
let name = self.ctx.add_identifier(name);
698
+
let name = Identifier::from(&self.source[start + 1..end]);
732
699
Ok(ast::Capture {
733
700
name,
734
701
quantifier: Zero, // set in checker
···
751
718
fn parse_literal(&mut self) -> Result<ast::Expression, ParseError> {
752
719
let literal_location = self.location;
753
720
self.consume_token("#")?;
754
-
let literal = self.parse_identifier("literal")?;
755
-
if literal == self.false_keyword {
721
+
let literal = self.parse_name("literal")?;
722
+
if literal == "false" {
756
723
return Ok(ast::Expression::FalseLiteral);
757
-
} else if literal == self.null_keyword {
724
+
} else if literal == "null" {
758
725
return Ok(ast::Expression::NullLiteral);
759
-
} else if literal == self.true_keyword {
726
+
} else if literal == "true" {
760
727
return Ok(ast::Expression::TrueLiteral);
761
728
} else {
762
729
Err(ParseError::UnexpectedLiteral(
763
-
self.ctx.resolve(literal).into(),
730
+
literal.into(),
764
731
literal_location,
765
732
))
766
733
}
+13
-9
src/variables.rs
+13
-9
src/variables.rs
···
16
16
#[derive(Debug, Error)]
17
17
pub enum VariableError {
18
18
#[error("Cannot assign immutable variable")]
19
-
CannotAssignImmutableVariable(Identifier),
19
+
CannotAssignImmutableVariable(String),
20
20
#[error("Variable already defined")]
21
-
VariableAlreadyDefined(Identifier),
21
+
VariableAlreadyDefined(String),
22
22
#[error("Undefined variable")]
23
-
UndefinedVariable(Identifier),
23
+
UndefinedVariable(String),
24
24
}
25
25
26
26
/// An environment of named variables
···
82
82
v.insert(variable);
83
83
Ok(())
84
84
}
85
-
Occupied(_) => Err(VariableError::VariableAlreadyDefined(name)),
85
+
Occupied(o) => Err(VariableError::VariableAlreadyDefined(o.key().to_string())),
86
86
}
87
87
}
88
88
89
89
fn set(&mut self, name: Identifier, value: V) -> Result<(), VariableError> {
90
90
match self.values.entry(name) {
91
-
Vacant(_) => self
91
+
Vacant(v) => self
92
92
.parent
93
93
.as_mut()
94
-
.map(|parent| parent.set(name, value))
95
-
.unwrap_or(Err(VariableError::UndefinedVariable(name))),
94
+
.map(|parent| parent.set(v.key().clone(), value))
95
+
.unwrap_or(Err(VariableError::UndefinedVariable(
96
+
v.into_key().to_string(),
97
+
))),
96
98
Occupied(mut o) => {
97
99
let mut variable = o.get_mut();
98
100
if variable.mutable {
99
101
variable.value = value;
100
102
Ok(())
101
103
} else {
102
-
Err(VariableError::CannotAssignImmutableVariable(name))
104
+
Err(VariableError::CannotAssignImmutableVariable(
105
+
o.key().to_string(),
106
+
))
103
107
}
104
108
}
105
109
}
···
107
111
108
112
fn get(&self, name: &Identifier) -> Option<&V> {
109
113
self.values
110
-
.get(&name)
114
+
.get(name)
111
115
.map(|v| &v.value)
112
116
.or_else(|| self.parent.as_ref().map(|p| p.get(name)).flatten())
113
117
}
+7
-8
tests/it/execution.rs
+7
-8
tests/it/execution.rs
···
9
9
use tree_sitter::Parser;
10
10
use tree_sitter_graph::ast::File;
11
11
use tree_sitter_graph::functions::Functions;
12
-
use tree_sitter_graph::Context;
13
12
use tree_sitter_graph::ExecutionError;
13
+
use tree_sitter_graph::Identifier;
14
14
use tree_sitter_graph::Variables;
15
15
16
16
fn init_log() {
···
27
27
let mut parser = Parser::new();
28
28
parser.set_language(tree_sitter_python::language()).unwrap();
29
29
let tree = parser.parse(python_source, None).unwrap();
30
-
let mut ctx = Context::new();
31
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, dsl_source)
32
-
.expect("Cannot parse file");
33
-
let mut functions = Functions::stdlib(&mut ctx);
30
+
let file =
31
+
File::from_str(tree_sitter_python::language(), dsl_source).expect("Cannot parse file");
32
+
let mut functions = Functions::stdlib();
34
33
let mut globals = Variables::new();
35
34
globals
36
-
.add(ctx.add_identifier("filename"), "test.py".into())
35
+
.add(Identifier::from("filename"), "test.py".into())
37
36
.map_err(|_| ExecutionError::DuplicateVariable("filename".into()))?;
38
-
let graph = file.execute(&ctx, &tree, python_source, &mut functions, &mut globals)?;
39
-
let result = graph.display_with(&ctx).to_string();
37
+
let graph = file.execute(&tree, python_source, &mut functions, &mut globals)?;
38
+
let result = graph.pretty_print().to_string();
40
39
Ok(result)
41
40
}
42
41
+12
-14
tests/it/graph.rs
+12
-14
tests/it/graph.rs
···
9
9
use tree_sitter::Parser;
10
10
use tree_sitter_graph::graph::Graph;
11
11
use tree_sitter_graph::graph::Value;
12
-
use tree_sitter_graph::Context;
12
+
use tree_sitter_graph::Identifier;
13
13
14
14
#[test]
15
15
fn can_overwrite_attributes() {
16
-
let mut ctx = Context::new();
17
16
let mut graph = Graph::new();
18
17
let node = graph.add_graph_node();
19
18
let attrs = &mut graph[node].attributes;
20
-
let name = ctx.add_identifier("name");
21
-
attrs.add(name, "node0").unwrap();
22
-
attrs.add(name, "overwritten").unwrap_err();
23
-
assert_eq!(*attrs.get(name).unwrap(), Value::from("overwritten"));
19
+
let name = Identifier::from("name");
20
+
attrs.add(name.clone(), "node0").unwrap();
21
+
attrs.add(name.clone(), "overwritten").unwrap_err();
22
+
assert_eq!(*attrs.get(&name).unwrap(), Value::from("overwritten"));
24
23
}
25
24
26
25
#[test]
···
55
54
parser.set_language(tree_sitter_python::language()).unwrap();
56
55
let tree = parser.parse(python_source, None).unwrap();
57
56
58
-
let mut ctx = Context::new();
59
57
let mut graph = Graph::new();
60
58
let root = graph.add_syntax_node(tree.root_node());
61
59
let node0 = graph.add_graph_node();
62
60
graph[node0]
63
61
.attributes
64
-
.add(ctx.add_identifier("name"), "node0")
62
+
.add(Identifier::from("name"), "node0")
65
63
.unwrap();
66
64
graph[node0]
67
65
.attributes
68
-
.add(ctx.add_identifier("source"), root)
66
+
.add(Identifier::from("source"), root)
69
67
.unwrap();
70
68
let node1 = graph.add_graph_node();
71
69
graph[node1]
72
70
.attributes
73
-
.add(ctx.add_identifier("name"), "node1")
71
+
.add(Identifier::from("name"), "node1")
74
72
.unwrap();
75
73
let node2 = graph.add_graph_node();
76
74
graph[node2]
77
75
.attributes
78
-
.add(ctx.add_identifier("name"), "node2")
76
+
.add(Identifier::from("name"), "node2")
79
77
.unwrap();
80
78
graph[node2]
81
79
.attributes
82
-
.add(ctx.add_identifier("parent"), node1)
80
+
.add(Identifier::from("parent"), node1)
83
81
.unwrap();
84
82
let edge01 = graph[node0]
85
83
.add_edge(node1)
86
84
.unwrap_or_else(|_| unreachable!());
87
85
edge01
88
86
.attributes
89
-
.add(ctx.add_identifier("precedence"), 14)
87
+
.add(Identifier::from("precedence"), 14)
90
88
.unwrap();
91
89
assert_eq!(
92
-
graph.display_with(&ctx).to_string(),
90
+
graph.pretty_print().to_string(),
93
91
indoc! {r#"
94
92
node 0
95
93
name: "node0"
+6
-8
tests/it/lazy_execution.rs
+6
-8
tests/it/lazy_execution.rs
···
9
9
use tree_sitter::Parser;
10
10
use tree_sitter_graph::ast::File;
11
11
use tree_sitter_graph::functions::Functions;
12
-
use tree_sitter_graph::Context;
13
12
use tree_sitter_graph::ExecutionError;
14
13
use tree_sitter_graph::Variables;
15
14
···
27
26
let mut parser = Parser::new();
28
27
parser.set_language(tree_sitter_python::language()).unwrap();
29
28
let tree = parser.parse(python_source, None).unwrap();
30
-
let mut ctx = Context::new();
31
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, dsl_source)
32
-
.expect("Cannot parse file");
33
-
let mut functions = Functions::stdlib(&mut ctx);
29
+
let file =
30
+
File::from_str(tree_sitter_python::language(), dsl_source).expect("Cannot parse file");
31
+
let mut functions = Functions::stdlib();
34
32
let mut globals = Variables::new();
35
33
globals
36
-
.add(ctx.add_identifier("filename"), "test.py".into())
34
+
.add("filename".into(), "test.py".into())
37
35
.map_err(|_| ExecutionError::DuplicateVariable("filename".into()))?;
38
-
let graph = file.execute_lazy(&mut ctx, &tree, python_source, &mut functions, &globals)?;
39
-
let result = graph.display_with(&ctx).to_string();
36
+
let graph = file.execute_lazy(&tree, python_source, &mut functions, &globals)?;
37
+
let result = graph.pretty_print().to_string();
40
38
Ok(result)
41
39
}
42
40
+88
-127
tests/it/parser.rs
+88
-127
tests/it/parser.rs
···
8
8
use tree_sitter::CaptureQuantifier::*;
9
9
10
10
use tree_sitter_graph::ast::*;
11
-
use tree_sitter_graph::Context;
11
+
use tree_sitter_graph::Identifier;
12
12
use tree_sitter_graph::Location;
13
13
14
14
#[test]
15
15
fn can_parse_blocks() {
16
-
let mut ctx = Context::new();
17
16
let source = r#"
18
17
(function_definition
19
18
name: (identifier) @cap1) @cap2
···
27
26
set @cap2.var1 = loc1
28
27
}
29
28
"#;
30
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
31
-
.expect("Cannot parse file");
29
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
32
30
33
-
let loc1 = ctx.add_identifier("loc1");
34
-
let precedence = ctx.add_identifier("precedence");
35
-
let pop = ctx.add_identifier("pop");
36
-
let prop1 = ctx.add_identifier("prop1");
37
-
let push = ctx.add_identifier("push");
38
-
let cap2 = ctx.add_identifier("cap2");
39
-
let var1 = ctx.add_identifier("var1");
31
+
let loc1 = Identifier::from("loc1");
32
+
let precedence = Identifier::from("precedence");
33
+
let pop = Identifier::from("pop");
34
+
let prop1 = Identifier::from("prop1");
35
+
let push = Identifier::from("push");
36
+
let cap2 = Identifier::from("cap2");
37
+
let var1 = Identifier::from("var1");
40
38
41
39
let statements = file
42
40
.stanzas
···
48
46
vec![vec![
49
47
CreateGraphNode {
50
48
node: UnscopedVariable {
51
-
name: loc1,
49
+
name: loc1.clone(),
52
50
location: Location { row: 4, column: 15 }
53
51
}
54
52
.into(),
···
60
58
scope: Box::new(
61
59
Capture {
62
60
quantifier: One,
63
-
name: cap2,
61
+
name: cap2.clone(),
64
62
file_capture_index: 1,
65
63
stanza_capture_index: 1,
66
64
location: Location { row: 5, column: 15 }
67
65
}
68
66
.into()
69
67
),
70
-
name: prop1,
68
+
name: prop1.clone(),
71
69
location: Location { row: 5, column: 21 }
72
70
}
73
71
.into(),
···
79
77
scope: Box::new(
80
78
Capture {
81
79
quantifier: One,
82
-
name: cap2,
80
+
name: cap2.clone(),
83
81
file_capture_index: 1,
84
82
stanza_capture_index: 1,
85
83
location: Location { row: 6, column: 15 }
86
84
}
87
85
.into()
88
86
),
89
-
name: prop1,
87
+
name: prop1.clone(),
90
88
location: Location { row: 6, column: 21 }
91
89
}
92
90
.into(),
93
91
sink: UnscopedVariable {
94
-
name: loc1,
92
+
name: loc1.clone(),
95
93
location: Location { row: 6, column: 30 },
96
94
}
97
95
.into(),
···
103
101
scope: Box::new(
104
102
Capture {
105
103
quantifier: One,
106
-
name: cap2,
104
+
name: cap2.clone(),
107
105
file_capture_index: 1,
108
106
stanza_capture_index: 1,
109
107
location: Location { row: 7, column: 16 }
110
108
}
111
109
.into()
112
110
),
113
-
name: prop1,
111
+
name: prop1.clone(),
114
112
location: Location { row: 7, column: 22 },
115
113
}
116
114
.into(),
117
115
sink: UnscopedVariable {
118
-
name: loc1.into(),
116
+
name: loc1.clone(),
119
117
location: Location { row: 7, column: 31 },
120
118
}
121
119
.into(),
···
131
129
scope: Box::new(
132
130
Capture {
133
131
quantifier: One,
134
-
name: cap2,
132
+
name: cap2.clone(),
135
133
file_capture_index: 1,
136
134
stanza_capture_index: 1,
137
135
location: Location { row: 8, column: 16 }
138
136
}
139
137
.into()
140
138
),
141
-
name: prop1,
139
+
name: prop1.clone(),
142
140
location: Location { row: 8, column: 22 },
143
141
}
144
142
.into(),
145
143
attributes: vec![
146
144
Attribute {
147
-
name: push,
145
+
name: push.clone(),
148
146
value: String::from("str2").into(),
149
147
},
150
148
Attribute {
151
-
name: pop,
152
-
value: Expression::TrueLiteral
149
+
name: pop.clone(),
150
+
value: Expression::TrueLiteral,
153
151
},
154
152
],
155
153
location: Location { row: 8, column: 10 },
···
160
158
scope: Box::new(
161
159
Capture {
162
160
quantifier: One,
163
-
name: cap2,
161
+
name: cap2.clone(),
164
162
file_capture_index: 1,
165
163
stanza_capture_index: 1,
166
164
location: Location { row: 9, column: 14 }
167
165
}
168
166
.into()
169
167
),
170
-
name: var1,
168
+
name: var1.clone(),
171
169
location: Location { row: 9, column: 20 },
172
170
}
173
171
.into(),
174
172
value: UnscopedVariable {
175
-
name: loc1,
173
+
name: loc1.clone(),
176
174
location: Location { row: 9, column: 27 },
177
175
}
178
176
.into(),
···
184
182
scope: Box::new(
185
183
Capture {
186
184
quantifier: One,
187
-
name: cap2,
185
+
name: cap2.clone(),
188
186
file_capture_index: 1,
189
187
stanza_capture_index: 1,
190
188
location: Location {
···
194
192
}
195
193
.into()
196
194
),
197
-
name: var1,
195
+
name: var1.clone(),
198
196
location: Location {
199
197
row: 10,
200
198
column: 20
···
202
200
}
203
201
.into(),
204
202
value: UnscopedVariable {
205
-
name: loc1,
203
+
name: loc1.clone(),
206
204
location: Location {
207
205
row: 10,
208
206
column: 27
···
221
219
222
220
#[test]
223
221
fn can_parse_literals() {
224
-
let mut ctx = Context::new();
225
222
let source = r#"
226
223
(identifier)
227
224
{
···
230
227
let t = #true
231
228
}
232
229
"#;
233
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
234
-
.expect("Cannot parse file");
230
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
235
231
236
-
let f = ctx.add_identifier("f");
237
-
let n = ctx.add_identifier("n");
238
-
let t = ctx.add_identifier("t");
232
+
let f = Identifier::from("f");
233
+
let n = Identifier::from("n");
234
+
let t = Identifier::from("t");
239
235
240
236
let statements = file
241
237
.stanzas
···
247
243
vec![vec![
248
244
DeclareImmutable {
249
245
variable: UnscopedVariable {
250
-
name: f,
246
+
name: f.clone(),
251
247
location: Location { row: 3, column: 14 }
252
248
}
253
249
.into(),
···
257
253
.into(),
258
254
DeclareImmutable {
259
255
variable: UnscopedVariable {
260
-
name: n,
256
+
name: n.clone(),
261
257
location: Location { row: 4, column: 14 }
262
258
}
263
259
.into(),
···
267
263
.into(),
268
264
DeclareImmutable {
269
265
variable: UnscopedVariable {
270
-
name: t,
266
+
name: t.clone(),
271
267
location: Location { row: 5, column: 14 }
272
268
}
273
269
.into(),
···
281
277
282
278
#[test]
283
279
fn can_parse_strings() {
284
-
let mut ctx = Context::new();
285
280
let source = r#"
286
281
(identifier)
287
282
{
288
283
let loc1 = "\"abc,\ndef\\"
289
284
}
290
285
"#;
291
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
292
-
.expect("Cannot parse file");
286
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
293
287
294
-
let loc1 = ctx.add_identifier("loc1");
288
+
let loc1 = Identifier::from("loc1");
295
289
296
290
let statements = file
297
291
.stanzas
···
302
296
statements,
303
297
vec![vec![DeclareImmutable {
304
298
variable: UnscopedVariable {
305
-
name: loc1,
299
+
name: loc1.clone(),
306
300
location: Location { row: 3, column: 14 }
307
301
}
308
302
.into(),
···
315
309
316
310
#[test]
317
311
fn can_parse_lists() {
318
-
let mut ctx = Context::new();
319
312
let source = r#"
320
313
(identifier)
321
314
{
···
324
317
let list3 = ["hello", "world",]
325
318
}
326
319
"#;
327
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
328
-
.expect("Cannot parse file");
320
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
329
321
330
-
let list1 = ctx.add_identifier("list1");
331
-
let list2 = ctx.add_identifier("list2");
332
-
let list3 = ctx.add_identifier("list3");
322
+
let list1 = Identifier::from("list1");
323
+
let list2 = Identifier::from("list2");
324
+
let list3 = Identifier::from("list3");
333
325
334
326
let statements = file
335
327
.stanzas
···
341
333
vec![vec![
342
334
DeclareImmutable {
343
335
variable: UnscopedVariable {
344
-
name: list1,
336
+
name: list1.clone(),
345
337
location: Location { row: 3, column: 14 }
346
338
}
347
339
.into(),
···
358
350
.into(),
359
351
DeclareImmutable {
360
352
variable: UnscopedVariable {
361
-
name: list2,
353
+
name: list2.clone(),
362
354
location: Location { row: 4, column: 14 }
363
355
}
364
356
.into(),
···
368
360
.into(),
369
361
DeclareImmutable {
370
362
variable: UnscopedVariable {
371
-
name: list3,
363
+
name: list3.clone(),
372
364
location: Location { row: 5, column: 14 }
373
365
}
374
366
.into(),
···
394
386
395
387
#[test]
396
388
fn can_parse_sets() {
397
-
let mut ctx = Context::new();
398
389
let source = r#"
399
390
(identifier)
400
391
{
···
403
394
let set3 = {"hello", "world",}
404
395
}
405
396
"#;
406
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
407
-
.expect("Cannot parse file");
397
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
408
398
409
-
let set1 = ctx.add_identifier("set1");
410
-
let set2 = ctx.add_identifier("set2");
411
-
let set3 = ctx.add_identifier("set3");
399
+
let set1 = Identifier::from("set1");
400
+
let set2 = Identifier::from("set2");
401
+
let set3 = Identifier::from("set3");
412
402
413
403
let statements = file
414
404
.stanzas
···
420
410
vec![vec![
421
411
DeclareImmutable {
422
412
variable: UnscopedVariable {
423
-
name: set1,
413
+
name: set1.clone(),
424
414
location: Location { row: 3, column: 14 }
425
415
}
426
416
.into(),
···
437
427
.into(),
438
428
DeclareImmutable {
439
429
variable: UnscopedVariable {
440
-
name: set2,
430
+
name: set2.clone(),
441
431
location: Location { row: 4, column: 14 }
442
432
}
443
433
.into(),
···
447
437
.into(),
448
438
DeclareImmutable {
449
439
variable: UnscopedVariable {
450
-
name: set3,
440
+
name: set3.clone(),
451
441
location: Location { row: 5, column: 14 }
452
442
}
453
443
.into(),
···
473
463
474
464
#[test]
475
465
fn can_parse_print() {
476
-
let mut ctx = Context::new();
477
466
let source = r#"
478
467
(identifier)
479
468
{
480
469
print "x =", 5
481
470
}
482
471
"#;
483
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
484
-
.expect("Cannot parse file");
472
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
485
473
486
474
let statements = file
487
475
.stanzas
···
506
494
507
495
#[test]
508
496
fn cannot_parse_nullable_regex() {
509
-
let mut ctx = Context::new();
510
497
let source = r#"
511
498
(module) @root
512
499
{
···
517
504
node n
518
505
}
519
506
"#;
520
-
if let Ok(_) = File::from_str(tree_sitter_python::language(), &mut ctx, source) {
507
+
if let Ok(_) = File::from_str(tree_sitter_python::language(), source) {
521
508
panic!("Parse succeeded unexpectedly");
522
509
}
523
510
}
524
511
525
512
#[test]
526
513
fn can_parse_star_capture() {
527
-
let mut ctx = Context::new();
528
514
let source = r#"
529
515
(module (_)* @stmts)
530
516
{
531
517
print @stmts
532
518
}
533
519
"#;
534
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
535
-
.expect("Cannot parse file");
520
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
536
521
537
-
let stmts = ctx.add_identifier("stmts");
522
+
let stmts = Identifier::from("stmts");
538
523
539
524
let statements = file
540
525
.stanzas
···
560
545
561
546
#[test]
562
547
fn can_parse_star_multiple_capture() {
563
-
let mut ctx = Context::new();
564
548
let source = r#"
565
549
(module (_) @stmt * @stmts)
566
550
{
···
568
552
print @stmts
569
553
}
570
554
"#;
571
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
572
-
.expect("Cannot parse file");
555
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
573
556
574
-
let stmt = ctx.add_identifier("stmt");
575
-
let stmts = ctx.add_identifier("stmts");
557
+
let stmt = Identifier::from("stmt");
558
+
let stmts = Identifier::from("stmts");
576
559
577
560
let statements = file
578
561
.stanzas
···
612
595
613
596
#[test]
614
597
fn can_parse_plus_capture() {
615
-
let mut ctx = Context::new();
616
598
let source = r#"
617
599
(module (_)+ @stmts)
618
600
{
619
601
print @stmts
620
602
}
621
603
"#;
622
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
623
-
.expect("Cannot parse file");
604
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
624
605
625
-
let stmts = ctx.add_identifier("stmts");
606
+
let stmts = Identifier::from("stmts");
626
607
627
608
let statements = file
628
609
.stanzas
···
648
629
649
630
#[test]
650
631
fn can_parse_optional_capture() {
651
-
let mut ctx = Context::new();
652
632
let source = r#"
653
633
(module (_)? @stmt)
654
634
{
655
635
print @stmt
656
636
}
657
637
"#;
658
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
659
-
.expect("Cannot parse file");
638
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
660
639
661
-
let stmt = ctx.add_identifier("stmt");
640
+
let stmt = Identifier::from("stmt");
662
641
663
642
let statements = file
664
643
.stanzas
···
684
663
685
664
#[test]
686
665
fn can_parse_parent_optional_capture() {
687
-
let mut ctx = Context::new();
688
666
let source = r#"
689
667
(module (_) @stmt) ?
690
668
{
691
669
print @stmt
692
670
}
693
671
"#;
694
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
695
-
.expect("Cannot parse file");
672
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
696
673
697
-
let stmt = ctx.add_identifier("stmt");
674
+
let stmt = Identifier::from("stmt");
698
675
699
676
let statements = file
700
677
.stanzas
···
720
697
721
698
#[test]
722
699
fn can_parse_alternative_capture() {
723
-
let mut ctx = Context::new();
724
700
let source = r#"
725
701
(module [(_) (_) @stmt])
726
702
{
727
703
print @stmt
728
704
}
729
705
"#;
730
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
731
-
.expect("Cannot parse file");
706
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
732
707
733
-
let stmt = ctx.add_identifier("stmt");
708
+
let stmt = Identifier::from("stmt");
734
709
735
710
let statements = file
736
711
.stanzas
···
756
731
757
732
#[test]
758
733
fn can_parse_nested_plus_and_optional_capture() {
759
-
let mut ctx = Context::new();
760
734
let source = r#"
761
735
(module (_)+ @stmt) ?
762
736
{
763
737
print @stmt
764
738
}
765
739
"#;
766
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
767
-
.expect("Cannot parse file");
740
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
768
741
769
-
let stmt = ctx.add_identifier("stmt");
742
+
let stmt = Identifier::from("stmt");
770
743
771
744
let statements = file
772
745
.stanzas
···
792
765
793
766
#[test]
794
767
fn can_parse_if() {
795
-
let mut ctx = Context::new();
796
768
let source = r#"
797
769
(module (pass_statement)? @x)
798
770
{
···
801
773
}
802
774
}
803
775
"#;
804
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
805
-
.expect("Cannot parse file");
776
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
806
777
807
-
let x = ctx.add_identifier("x");
778
+
let x = Identifier::from("x");
808
779
809
780
let statements = file
810
781
.stanzas
···
844
815
845
816
#[test]
846
817
fn can_parse_if_elif() {
847
-
let mut ctx = Context::new();
848
818
let source = r#"
849
819
(module (pass_statement)? @x)
850
820
{
···
855
825
}
856
826
}
857
827
"#;
858
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
859
-
.expect("Cannot parse file");
828
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
860
829
861
-
let x = ctx.add_identifier("x");
830
+
let x = Identifier::from("x");
862
831
863
832
let statements = file
864
833
.stanzas
···
873
842
conditions: vec![Condition::None {
874
843
value: Capture {
875
844
quantifier: ZeroOrOne,
876
-
name: x,
845
+
name: x.clone(),
877
846
file_capture_index: 0,
878
847
stanza_capture_index: 0,
879
848
location: Location { row: 3, column: 18 },
···
896
865
conditions: vec![Condition::Some {
897
866
value: Capture {
898
867
quantifier: ZeroOrOne,
899
-
name: x,
868
+
name: x.clone(),
900
869
file_capture_index: 0,
901
870
stanza_capture_index: 0,
902
871
location: Location { row: 5, column: 22 },
···
923
892
924
893
#[test]
925
894
fn can_parse_if_else() {
926
-
let mut ctx = Context::new();
927
895
let source = r#"
928
896
(module (pass_statement)? @x)
929
897
{
···
934
902
}
935
903
}
936
904
"#;
937
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
938
-
.expect("Cannot parse file");
905
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
939
906
940
-
let x = ctx.add_identifier("x");
907
+
let x = Identifier::from("x");
941
908
942
909
let statements = file
943
910
.stanzas
···
991
958
992
959
#[test]
993
960
fn cannot_parse_if_some_list_capture() {
994
-
let mut ctx = Context::new();
995
961
let source = r#"
996
962
(module (_)+ @xs) @root
997
963
{
···
1000
966
}
1001
967
}
1002
968
"#;
1003
-
if let Ok(_) = File::from_str(tree_sitter_python::language(), &mut ctx, source) {
969
+
if let Ok(_) = File::from_str(tree_sitter_python::language(), source) {
1004
970
panic!("Parse succeeded unexpectedly");
1005
971
}
1006
972
}
1007
973
1008
974
#[test]
1009
975
fn can_parse_for_in() {
1010
-
let mut ctx = Context::new();
1011
976
let source = r#"
1012
977
(module (_)* @xs)
1013
978
{
···
1016
981
}
1017
982
}
1018
983
"#;
1019
-
let file = File::from_str(tree_sitter_python::language(), &mut ctx, source)
1020
-
.expect("Cannot parse file");
984
+
let file = File::from_str(tree_sitter_python::language(), source).expect("Cannot parse file");
1021
985
1022
-
let xs = ctx.add_identifier("xs");
1023
-
let x = ctx.add_identifier("x");
986
+
let xs = Identifier::from("xs");
987
+
let x = Identifier::from("x");
1024
988
1025
989
let statements = file
1026
990
.stanzas
···
1031
995
statements,
1032
996
vec![vec![ForIn {
1033
997
variable: UnscopedVariable {
1034
-
name: x,
998
+
name: x.clone(),
1035
999
location: Location { row: 3, column: 14 }
1036
1000
},
1037
1001
value: Capture {
1038
1002
quantifier: ZeroOrMore,
1039
-
name: xs,
1003
+
name: xs.clone(),
1040
1004
file_capture_index: 0,
1041
1005
stanza_capture_index: 0,
1042
1006
location: Location { row: 3, column: 19 },
···
1044
1008
.into(),
1045
1009
statements: vec![Print {
1046
1010
values: vec![UnscopedVariable {
1047
-
name: x,
1011
+
name: x.clone(),
1048
1012
location: Location { row: 4, column: 18 },
1049
1013
}
1050
1014
.into()],
···
1059
1023
1060
1024
#[test]
1061
1025
fn cannot_parse_for_in_optional_capture() {
1062
-
let mut ctx = Context::new();
1063
1026
let source = r#"
1064
1027
(module (_)? @xs) @root
1065
1028
{
···
1068
1031
}
1069
1032
}
1070
1033
"#;
1071
-
if let Ok(_) = File::from_str(tree_sitter_python::language(), &mut ctx, source) {
1034
+
if let Ok(_) = File::from_str(tree_sitter_python::language(), source) {
1072
1035
panic!("Parse succeeded unexpectedly");
1073
1036
}
1074
1037
}
1075
1038
1076
1039
#[test]
1077
1040
fn cannot_parse_scan_of_nonlocal_call_expression() {
1078
-
let mut ctx = Context::new();
1079
1041
let source = r#"
1080
1042
(function_definition
1081
1043
name: (identifier) @name)
···
1088
1050
}
1089
1051
}
1090
1052
"#;
1091
-
if let Ok(_) = File::from_str(tree_sitter_python::language(), &mut ctx, source) {
1053
+
if let Ok(_) = File::from_str(tree_sitter_python::language(), source) {
1092
1054
panic!("Parse succeeded unexpectedly");
1093
1055
}
1094
1056
}
1095
1057
1096
1058
#[test]
1097
1059
fn cannot_parse_scan_of_nonlocal_variable() {
1098
-
let mut ctx = Context::new();
1099
1060
let source = r#"
1100
1061
(function_definition
1101
1062
name: (identifier) @name)
···
1109
1070
}
1110
1071
}
1111
1072
"#;
1112
-
if let Ok(_) = File::from_str(tree_sitter_python::language(), &mut ctx, source) {
1073
+
if let Ok(_) = File::from_str(tree_sitter_python::language(), source) {
1113
1074
panic!("Parse succeeded unexpectedly");
1114
1075
}
1115
1076
}