|
68 | 68 | //! |
69 | 69 | //! The following Lua methods are available on a stack graph instance: |
70 | 70 | //! |
| 71 | +//! #### `edges` |
| 72 | +//! |
| 73 | +//! ``` lua |
| 74 | +//! let edges = graph:edges() |
| 75 | +//! ``` |
| 76 | +//! |
| 77 | +//! Returns an array containing all of the edges in the graph. |
| 78 | +//! |
71 | 79 | //! #### `file` |
72 | 80 | //! |
73 | 81 | //! ``` lua |
|
123 | 131 | //! |
124 | 132 | //! Adds a new drop scopes node to this file. |
125 | 133 | //! |
| 134 | +//! #### `edges` |
| 135 | +//! |
| 136 | +//! ``` lua |
| 137 | +//! let edges = file:edges() |
| 138 | +//! ``` |
| 139 | +//! |
| 140 | +//! Returns an array containing all of the edges starting from or leaving a node in this file. |
| 141 | +//! |
126 | 142 | //! #### `exported_scope_node` |
127 | 143 | //! |
128 | 144 | //! ``` lua |
|
266 | 282 | //! |
267 | 283 | //! Returns the local ID of this node within its file. |
268 | 284 | //! |
| 285 | +//! #### `outgoing_edges` |
| 286 | +//! |
| 287 | +//! ``` lua |
| 288 | +//! let edges = node:outgoing_edges() |
| 289 | +//! ``` |
| 290 | +//! |
| 291 | +//! Returns an array containing all of the edges leaving this node. |
| 292 | +//! |
269 | 293 | //! #### `set_debug_info` |
270 | 294 | //! |
271 | 295 | //! ``` lua |
@@ -381,12 +405,26 @@ use mlua::UserData; |
381 | 405 | use mlua::UserDataMethods; |
382 | 406 |
|
383 | 407 | use crate::arena::Handle; |
| 408 | +use crate::graph::Edge; |
384 | 409 | use crate::graph::File; |
385 | 410 | use crate::graph::Node; |
386 | 411 | use crate::graph::StackGraph; |
387 | 412 |
|
388 | 413 | impl UserData for StackGraph { |
389 | 414 | fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { |
| 415 | + methods.add_function("edges", |l, graph_ud: AnyUserData| { |
| 416 | + let graph = graph_ud.borrow::<StackGraph>()?; |
| 417 | + let mut edges = Vec::new(); |
| 418 | + for node in graph.iter_nodes() { |
| 419 | + for edge in graph.outgoing_edges(node) { |
| 420 | + let edge_ud = l.create_userdata(edge)?; |
| 421 | + edge_ud.set_user_value(graph_ud.clone())?; |
| 422 | + edges.push(edge_ud); |
| 423 | + } |
| 424 | + } |
| 425 | + Ok(edges) |
| 426 | + }); |
| 427 | + |
390 | 428 | methods.add_function("file", |l, (graph_ud, name): (AnyUserData, String)| { |
391 | 429 | let file = { |
392 | 430 | let mut graph = graph_ud.borrow_mut::<StackGraph>()?; |
@@ -476,6 +514,39 @@ impl UserData for Handle<File> { |
476 | 514 | Ok(node_ud) |
477 | 515 | }); |
478 | 516 |
|
| 517 | + methods.add_function("edges", |l, file_ud: AnyUserData| { |
| 518 | + let file = *file_ud.borrow::<Handle<File>>()?; |
| 519 | + let graph_ud = file_ud.user_value::<AnyUserData>()?; |
| 520 | + let graph = graph_ud.borrow::<StackGraph>()?; |
| 521 | + let mut edges = Vec::new(); |
| 522 | + // First find any edges from the singleton nodes _to_ a node in this file. |
| 523 | + for edge in graph.outgoing_edges(StackGraph::root_node()) { |
| 524 | + if !graph[edge.sink].file().map(|f| f == file).unwrap_or(false) { |
| 525 | + continue; |
| 526 | + } |
| 527 | + let edge_ud = l.create_userdata(edge)?; |
| 528 | + edge_ud.set_user_value(graph_ud.clone())?; |
| 529 | + edges.push(edge_ud); |
| 530 | + } |
| 531 | + for edge in graph.outgoing_edges(StackGraph::jump_to_node()) { |
| 532 | + if !graph[edge.sink].file().map(|f| f == file).unwrap_or(false) { |
| 533 | + continue; |
| 534 | + } |
| 535 | + let edge_ud = l.create_userdata(edge)?; |
| 536 | + edge_ud.set_user_value(graph_ud.clone())?; |
| 537 | + edges.push(edge_ud); |
| 538 | + } |
| 539 | + // Then find any edges _starting_ from a node in this file. |
| 540 | + for node in graph.nodes_for_file(file) { |
| 541 | + for edge in graph.outgoing_edges(node) { |
| 542 | + let edge_ud = l.create_userdata(edge)?; |
| 543 | + edge_ud.set_user_value(graph_ud.clone())?; |
| 544 | + edges.push(edge_ud); |
| 545 | + } |
| 546 | + } |
| 547 | + Ok(edges) |
| 548 | + }); |
| 549 | + |
479 | 550 | methods.add_function("exported_scope_node", |l, file_ud: AnyUserData| { |
480 | 551 | let file = *file_ud.borrow::<Handle<File>>()?; |
481 | 552 | let graph_ud = file_ud.user_value::<AnyUserData>()?; |
@@ -729,27 +800,45 @@ impl UserData for Handle<Node> { |
729 | 800 | fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { |
730 | 801 | methods.add_function( |
731 | 802 | "add_edge_from", |
732 | | - |_, (this_ud, from_ud, precedence): (AnyUserData, AnyUserData, Option<i32>)| { |
| 803 | + |l, (this_ud, from_ud, precedence): (AnyUserData, AnyUserData, Option<i32>)| { |
733 | 804 | let this = *this_ud.borrow::<Handle<Node>>()?; |
734 | 805 | let from = *from_ud.borrow::<Handle<Node>>()?; |
735 | 806 | let graph_ud = this_ud.user_value::<AnyUserData>()?; |
736 | | - let mut graph = graph_ud.borrow_mut::<StackGraph>()?; |
737 | 807 | let precedence = precedence.unwrap_or(0); |
738 | | - graph.add_edge(from, this, precedence); |
739 | | - Ok(()) |
| 808 | + { |
| 809 | + let mut graph = graph_ud.borrow_mut::<StackGraph>()?; |
| 810 | + graph.add_edge(from, this, precedence); |
| 811 | + } |
| 812 | + let edge = Edge { |
| 813 | + source: from, |
| 814 | + sink: this, |
| 815 | + precedence, |
| 816 | + }; |
| 817 | + let edge_ud = l.create_userdata(edge)?; |
| 818 | + edge_ud.set_user_value(graph_ud)?; |
| 819 | + Ok(edge_ud) |
740 | 820 | }, |
741 | 821 | ); |
742 | 822 |
|
743 | 823 | methods.add_function( |
744 | 824 | "add_edge_to", |
745 | | - |_, (this_ud, to_ud, precedence): (AnyUserData, AnyUserData, Option<i32>)| { |
| 825 | + |l, (this_ud, to_ud, precedence): (AnyUserData, AnyUserData, Option<i32>)| { |
746 | 826 | let this = *this_ud.borrow::<Handle<Node>>()?; |
747 | 827 | let to = *to_ud.borrow::<Handle<Node>>()?; |
748 | 828 | let graph_ud = this_ud.user_value::<AnyUserData>()?; |
749 | | - let mut graph = graph_ud.borrow_mut::<StackGraph>()?; |
750 | 829 | let precedence = precedence.unwrap_or(0); |
751 | | - graph.add_edge(this, to, precedence); |
752 | | - Ok(()) |
| 830 | + { |
| 831 | + let mut graph = graph_ud.borrow_mut::<StackGraph>()?; |
| 832 | + graph.add_edge(this, to, precedence); |
| 833 | + } |
| 834 | + let edge = Edge { |
| 835 | + source: this, |
| 836 | + sink: to, |
| 837 | + precedence, |
| 838 | + }; |
| 839 | + let edge_ud = l.create_userdata(edge)?; |
| 840 | + edge_ud.set_user_value(graph_ud)?; |
| 841 | + Ok(edge_ud) |
753 | 842 | }, |
754 | 843 | ); |
755 | 844 |
|
@@ -786,6 +875,19 @@ impl UserData for Handle<Node> { |
786 | 875 | Ok(graph[node].id().local_id()) |
787 | 876 | }); |
788 | 877 |
|
| 878 | + methods.add_function("outgoing_edges", |l, node_ud: AnyUserData| { |
| 879 | + let node = *node_ud.borrow::<Handle<Node>>()?; |
| 880 | + let graph_ud = node_ud.user_value::<AnyUserData>()?; |
| 881 | + let graph = graph_ud.borrow::<StackGraph>()?; |
| 882 | + let mut edges = Vec::new(); |
| 883 | + for edge in graph.outgoing_edges(node) { |
| 884 | + let edge_ud = l.create_userdata(edge)?; |
| 885 | + edge_ud.set_user_value(graph_ud.clone())?; |
| 886 | + edges.push(edge_ud); |
| 887 | + } |
| 888 | + Ok(edges) |
| 889 | + }); |
| 890 | + |
789 | 891 | methods.add_function( |
790 | 892 | "set_debug_info", |
791 | 893 | |_, (node_ud, k, v): (AnyUserData, String, String)| { |
@@ -894,3 +996,20 @@ impl UserData for Handle<Node> { |
894 | 996 | }); |
895 | 997 | } |
896 | 998 | } |
| 999 | + |
| 1000 | +impl UserData for Edge { |
| 1001 | + fn add_methods<'lua, M: UserDataMethods<'lua, Self>>(methods: &mut M) { |
| 1002 | + methods.add_meta_function(mlua::MetaMethod::ToString, |_, edge_ud: AnyUserData| { |
| 1003 | + let edge = *edge_ud.borrow::<Edge>()?; |
| 1004 | + let graph_ud = edge_ud.user_value::<AnyUserData>()?; |
| 1005 | + let graph = graph_ud.borrow::<StackGraph>()?; |
| 1006 | + let display = format!( |
| 1007 | + "{} -{}-> {}", |
| 1008 | + edge.source.display(&graph), |
| 1009 | + edge.precedence, |
| 1010 | + edge.sink.display(&graph), |
| 1011 | + ); |
| 1012 | + Ok(display) |
| 1013 | + }); |
| 1014 | + } |
| 1015 | +} |
0 commit comments