fork of https://github.com/tree-sitter/tree-sitter-graph

Support adding edges and adding attributes with the same value multiple times

Changed files
+145 -28
src
tests
+8
CHANGELOG.md
··· 5 5 The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 6 6 and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 7 7 8 + ## Unreleased 9 + 10 + ### DSL 11 + 12 + #### Added 13 + 14 + - Support adding an edge multiple times, or setting an attribute multiple times with the same value. Previously these would raise runtime errors. 15 + 8 16 ## v0.11.1 -- 2024-03-06 9 17 10 18 Updated the `tree-sitter` dependency to include the required minimal patch version.
-1
src/execution/lazy.rs
··· 165 165 #[derive(Debug, Clone, Hash, PartialEq, Eq)] 166 166 pub(super) enum GraphElementKey { 167 167 NodeAttribute(graph::GraphNodeRef, Identifier), 168 - Edge(graph::GraphNodeRef, graph::GraphNodeRef), 169 168 EdgeAttribute(graph::GraphNodeRef, graph::GraphNodeRef, Identifier), 170 169 } 171 170
+1 -17
src/execution/lazy/statements.rs
··· 226 226 .sink 227 227 .evaluate_as_graph_node(exec) 228 228 .with_context(|| "Evaluating edge sink".to_string().into())?; 229 - let prev_debug_info = exec 230 - .prev_element_debug_info 231 - .insert(GraphElementKey::Edge(source, sink), self.debug_info.clone()); 232 229 let edge = match exec.graph[source].add_edge(sink) { 233 - Ok(edge) => edge, 234 - Err(_) => { 235 - return Err(ExecutionError::DuplicateEdge(format!( 236 - "({} -> {})", 237 - source, sink, 238 - ))) 239 - .with_context(|| { 240 - ( 241 - prev_debug_info.unwrap().into(), 242 - self.debug_info.clone().into(), 243 - ) 244 - .into() 245 - }); 246 - } 230 + Ok(edge) | Err(edge) => edge, 247 231 }; 248 232 edge.attributes = self.attributes.clone(); 249 233 Ok(())
+1 -7
src/execution/strict.rs
··· 334 334 let source = self.source.evaluate(exec)?.into_graph_node_ref()?; 335 335 let sink = self.sink.evaluate(exec)?.into_graph_node_ref()?; 336 336 let edge = match exec.graph[source].add_edge(sink) { 337 - Ok(edge) => edge, 338 - Err(_) => { 339 - return Err(ExecutionError::DuplicateEdge(format!( 340 - "({} -> {}) in {}", 341 - source, sink, self, 342 - )))? 343 - } 337 + Ok(edge) | Err(edge) => edge, 344 338 }; 345 339 self.add_debug_attrs(&mut edge.attributes, exec.config)?; 346 340 Ok(())
+7 -3
src/graph.rs
··· 275 275 276 276 /// Adds an attribute to this attribute set. If there was already an attribute with the same 277 277 /// name, replaces its value and returns `Err`. 278 - pub fn add<V: Into<Value>>(&mut self, name: Identifier, value: V) -> Result<(), ()> { 278 + pub fn add<V: Into<Value>>(&mut self, name: Identifier, value: V) -> Result<(), Value> { 279 279 match self.values.entry(name) { 280 280 Entry::Occupied(mut o) => { 281 - o.insert(value.into()); 282 - Err(()) 281 + let value = value.into(); 282 + if o.get() != &value { 283 + Err(o.insert(value.into())) 284 + } else { 285 + Ok(()) 286 + } 283 287 } 284 288 Entry::Vacant(v) => { 285 289 v.insert(value.into());
+64
tests/it/execution.rs
··· 1008 1008 "#}, 1009 1009 ); 1010 1010 } 1011 + 1012 + #[test] 1013 + fn can_add_edge_twice() { 1014 + check_execution( 1015 + indoc! { r#" 1016 + pass 1017 + "#}, 1018 + indoc! {r#" 1019 + (module) { 1020 + node n1; 1021 + node n2; 1022 + edge n1 -> n2; 1023 + edge n1 -> n2; 1024 + } 1025 + "#}, 1026 + indoc! {r#" 1027 + node 0 1028 + edge 0 -> 1 1029 + node 1 1030 + "#}, 1031 + ); 1032 + } 1033 + 1034 + #[test] 1035 + fn can_set_node_attribute_value_twice() { 1036 + check_execution( 1037 + indoc! { r#" 1038 + pass 1039 + "#}, 1040 + indoc! {r#" 1041 + (module) { 1042 + node n; 1043 + attr (n) foo = #true; 1044 + } 1045 + "#}, 1046 + indoc! {r#" 1047 + node 0 1048 + foo: #true 1049 + "#}, 1050 + ); 1051 + } 1052 + 1053 + #[test] 1054 + fn cannot_change_attribute_value() { 1055 + check_execution( 1056 + indoc! { r#" 1057 + pass 1058 + "#}, 1059 + indoc! {r#" 1060 + (module) { 1061 + node n1; 1062 + node n2; 1063 + edge n1 -> n2; 1064 + attr (n1 -> n2) foo = #true; 1065 + } 1066 + "#}, 1067 + indoc! {r#" 1068 + node 0 1069 + edge 0 -> 1 1070 + foo: #true 1071 + node 1 1072 + "#}, 1073 + ); 1074 + }
+64
tests/it/lazy_execution.rs
··· 1527 1527 "#}, 1528 1528 ); 1529 1529 } 1530 + 1531 + #[test] 1532 + fn can_add_edge_twice() { 1533 + check_execution( 1534 + indoc! { r#" 1535 + pass 1536 + "#}, 1537 + indoc! {r#" 1538 + (module) { 1539 + node n1; 1540 + node n2; 1541 + edge n1 -> n2; 1542 + edge n1 -> n2; 1543 + } 1544 + "#}, 1545 + indoc! {r#" 1546 + node 0 1547 + edge 0 -> 1 1548 + node 1 1549 + "#}, 1550 + ); 1551 + } 1552 + 1553 + #[test] 1554 + fn can_set_node_attribute_value_twice() { 1555 + check_execution( 1556 + indoc! { r#" 1557 + pass 1558 + "#}, 1559 + indoc! {r#" 1560 + (module) { 1561 + node n; 1562 + attr (n) foo = #true; 1563 + } 1564 + "#}, 1565 + indoc! {r#" 1566 + node 0 1567 + foo: #true 1568 + "#}, 1569 + ); 1570 + } 1571 + 1572 + #[test] 1573 + fn cannot_change_attribute_value() { 1574 + check_execution( 1575 + indoc! { r#" 1576 + pass 1577 + "#}, 1578 + indoc! {r#" 1579 + (module) { 1580 + node n1; 1581 + node n2; 1582 + edge n1 -> n2; 1583 + attr (n1 -> n2) foo = #true; 1584 + } 1585 + "#}, 1586 + indoc! {r#" 1587 + node 0 1588 + edge 0 -> 1 1589 + foo: #true 1590 + node 1 1591 + "#}, 1592 + ); 1593 + }