#![allow(non_camel_case_types)]
use std::convert::TryInto;
use libc::c_char;
use crate::arena::Handle;
use crate::graph::File;
use crate::graph::Node;
use crate::graph::NodeID;
use crate::graph::StackGraph;
use crate::graph::Symbol;
use crate::partial::PartialPath;
use crate::partial::PartialPathEdge;
use crate::partial::PartialPathEdgeList;
use crate::partial::PartialPaths;
use crate::partial::PartialScopeStack;
use crate::partial::PartialScopedSymbol;
use crate::partial::PartialSymbolStack;
use crate::paths::Path;
use crate::paths::PathEdge;
use crate::paths::PathEdgeList;
use crate::paths::Paths;
use crate::paths::ScopeStack;
use crate::paths::ScopedSymbol;
use crate::paths::SymbolStack;
use crate::stitching::Database;
use crate::stitching::ForwardPartialPathStitcher;
use crate::stitching::PathStitcher;
pub struct sg_stack_graph {
pub inner: StackGraph,
}
#[no_mangle]
pub extern "C" fn sg_stack_graph_new() -> *mut sg_stack_graph {
Box::into_raw(Box::new(sg_stack_graph {
inner: StackGraph::new(),
}))
}
#[no_mangle]
pub extern "C" fn sg_stack_graph_free(graph: *mut sg_stack_graph) {
drop(unsafe { Box::from_raw(graph) })
}
pub struct sg_path_arena {
pub inner: Paths,
}
#[no_mangle]
pub extern "C" fn sg_path_arena_new() -> *mut sg_path_arena {
Box::into_raw(Box::new(sg_path_arena {
inner: Paths::new(),
}))
}
#[no_mangle]
pub extern "C" fn sg_path_arena_free(paths: *mut sg_path_arena) {
drop(unsafe { Box::from_raw(paths) })
}
pub struct sg_partial_path_arena {
pub inner: PartialPaths,
}
#[no_mangle]
pub extern "C" fn sg_partial_path_arena_new() -> *mut sg_partial_path_arena {
Box::into_raw(Box::new(sg_partial_path_arena {
inner: PartialPaths::new(),
}))
}
#[no_mangle]
pub extern "C" fn sg_partial_path_arena_free(partials: *mut sg_partial_path_arena) {
drop(unsafe { Box::from_raw(partials) })
}
pub struct sg_partial_path_database {
pub inner: Database,
}
#[no_mangle]
pub extern "C" fn sg_partial_path_database_new() -> *mut sg_partial_path_database {
Box::into_raw(Box::new(sg_partial_path_database {
inner: Database::new(),
}))
}
#[no_mangle]
pub extern "C" fn sg_partial_path_database_free(db: *mut sg_partial_path_database) {
drop(unsafe { Box::from_raw(db) })
}
pub const SG_LIST_EMPTY_HANDLE: u32 = 0xffffffff;
#[repr(C)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum sg_deque_direction {
SG_DEQUE_FORWARDS,
SG_DEQUE_BACKWARDS,
}
impl Default for sg_deque_direction {
fn default() -> sg_deque_direction {
sg_deque_direction::SG_DEQUE_FORWARDS
}
}
#[repr(C)]
pub struct sg_symbol {
pub symbol: *const c_char,
pub symbol_len: usize,
}
pub type sg_symbol_handle = u32;
#[repr(C)]
pub struct sg_symbols {
pub symbols: *const sg_symbol,
pub count: usize,
}
#[no_mangle]
pub extern "C" fn sg_stack_graph_symbols(graph: *const sg_stack_graph) -> sg_symbols {
let graph = unsafe { &(*graph).inner };
sg_symbols {
symbols: graph.symbols.as_ptr() as *const sg_symbol,
count: graph.symbols.len(),
}
}
#[no_mangle]
pub extern "C" fn sg_stack_graph_add_symbols(
graph: *mut sg_stack_graph,
count: usize,
symbols: *const c_char,
lengths: *const usize,
handles_out: *mut sg_symbol_handle,
) {
let graph = unsafe { &mut (*graph).inner };
let mut symbols = symbols as *const u8;
let lengths = unsafe { std::slice::from_raw_parts(lengths, count) };
let handles_out = unsafe {
std::slice::from_raw_parts_mut(handles_out as *mut Option<Handle<Symbol>>, count)
};
for i in 0..count {
let symbol = unsafe { std::slice::from_raw_parts(symbols, lengths[i]) };
handles_out[i] = match std::str::from_utf8(symbol) {
Ok(symbol) => Some(graph.add_symbol(symbol)),
Err(_) => None,
};
unsafe { symbols = symbols.add(lengths[i]) };
}
}
#[repr(C)]
pub struct sg_file {
pub name: *const c_char,
pub name_len: usize,
}
pub type sg_file_handle = u32;
impl Into<Handle<File>> for sg_file_handle {
fn into(self) -> Handle<File> {
unsafe { std::mem::transmute(self) }
}
}
#[repr(C)]
pub struct sg_files {
pub files: *const sg_file,
pub count: usize,
}
#[no_mangle]
pub extern "C" fn sg_stack_graph_files(graph: *const sg_stack_graph) -> sg_files {
let graph = unsafe { &(*graph).inner };
sg_files {
files: graph.files.as_ptr() as *const sg_file,
count: graph.files.len(),
}
}
#[no_mangle]
pub extern "C" fn sg_stack_graph_add_files(
graph: *mut sg_stack_graph,
count: usize,
files: *const c_char,
lengths: *const usize,
handles_out: *mut sg_file_handle,
) {
let graph = unsafe { &mut (*graph).inner };
let mut files = files as *const u8;
let lengths = unsafe { std::slice::from_raw_parts(lengths, count) };
let handles_out =
unsafe { std::slice::from_raw_parts_mut(handles_out as *mut Option<Handle<File>>, count) };
for i in 0..count {
let file = unsafe { std::slice::from_raw_parts(files, lengths[i]) };
handles_out[i] = match std::str::from_utf8(file) {
Ok(file) => Some(graph.get_or_create_file(file)),
Err(_) => None,
};
unsafe { files = files.add(lengths[i]) };
}
}
#[repr(C)]
#[derive(Clone, Copy, Default, Eq, PartialEq)]
pub struct sg_node_id {
pub file: sg_file_handle,
pub local_id: u32,
}
impl sg_node_id {
fn is_empty(self) -> bool {
self.file == 0 && self.local_id == 0
}
}
impl Into<NodeID> for sg_node_id {
fn into(self) -> NodeID {
unsafe { std::mem::transmute(self) }
}
}
pub const SG_ROOT_NODE_ID: u32 = 1;
pub const SG_JUMP_TO_NODE_ID: u32 = 2;
#[repr(C)]
#[derive(Clone)]
pub struct sg_node {
pub kind: sg_node_kind,
pub id: sg_node_id,
pub symbol: sg_symbol_handle,
pub scope: sg_node_id,
pub is_clickable: bool,
}
impl Into<Node> for sg_node {
fn into(self) -> Node {
unsafe { std::mem::transmute(self) }
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub enum sg_node_kind {
SG_NODE_KIND_DROP_SCOPES,
SG_NODE_KIND_EXPORTED_SCOPE,
SG_NODE_KIND_INTERNAL_SCOPE,
SG_NODE_KIND_JUMP_TO,
SG_NODE_KIND_POP_SCOPED_SYMBOL,
SG_NODE_KIND_POP_SYMBOL,
SG_NODE_KIND_PUSH_SCOPED_SYMBOL,
SG_NODE_KIND_PUSH_SYMBOL,
SG_NODE_KIND_ROOT,
}
pub type sg_node_handle = u32;
impl Into<Handle<Node>> for sg_node_handle {
fn into(self) -> Handle<Node> {
unsafe { std::mem::transmute(self) }
}
}
pub const SG_ROOT_NODE_HANDLE: sg_node_handle = 1;
pub const SG_JUMP_TO_NODE_HANDLE: sg_node_handle = 2;
#[repr(C)]
pub struct sg_nodes {
pub nodes: *const sg_node,
pub count: usize,
}
#[no_mangle]
pub extern "C" fn sg_stack_graph_nodes(graph: *const sg_stack_graph) -> sg_nodes {
let graph = unsafe { &(*graph).inner };
sg_nodes {
nodes: graph.nodes.as_ptr() as *const sg_node,
count: graph.nodes.len(),
}
}
#[no_mangle]
pub extern "C" fn sg_stack_graph_get_or_create_nodes(
graph: *mut sg_stack_graph,
count: usize,
nodes: *const sg_node,
handles_out: *mut sg_node_handle,
) {
let graph = unsafe { &mut (*graph).inner };
let nodes = unsafe { std::slice::from_raw_parts(nodes, count) };
let handles_out =
unsafe { std::slice::from_raw_parts_mut(handles_out as *mut Option<Handle<Node>>, count) };
for i in 0..count {
let node_id = nodes[i].id;
handles_out[i] = validate_node(graph, &nodes[i])
.map(|node| graph.get_or_create_node(node_id.into(), node));
}
}
fn validate_node_id(graph: &StackGraph, node_id: sg_node_id) -> Option<()> {
if node_id.file == 0 || node_id.file >= (graph.files.len() as u32) {
return None;
}
Some(())
}
fn validate_node(graph: &StackGraph, node: &sg_node) -> Option<Node> {
if matches!(
&node.kind,
sg_node_kind::SG_NODE_KIND_JUMP_TO | sg_node_kind::SG_NODE_KIND_ROOT
) {
return None;
}
validate_node_id(graph, node.id)?;
if (node.symbol != 0)
!= matches!(
&node.kind,
sg_node_kind::SG_NODE_KIND_POP_SCOPED_SYMBOL
| sg_node_kind::SG_NODE_KIND_POP_SYMBOL
| sg_node_kind::SG_NODE_KIND_PUSH_SCOPED_SYMBOL
| sg_node_kind::SG_NODE_KIND_PUSH_SYMBOL
)
{
return None;
}
if (node.scope.is_empty())
== matches!(&node.kind, sg_node_kind::SG_NODE_KIND_PUSH_SCOPED_SYMBOL)
{
return None;
}
Some(node.clone().into())
}
#[repr(C)]
pub struct sg_edge {
pub source: sg_node_handle,
pub sink: sg_node_handle,
pub precedence: i32,
}
#[no_mangle]
pub extern "C" fn sg_stack_graph_add_edges(
graph: *mut sg_stack_graph,
count: usize,
edges: *const sg_edge,
) {
let graph = unsafe { &mut (*graph).inner };
let edges = unsafe { std::slice::from_raw_parts(edges, count) };
for i in 0..count {
let source = unsafe { std::mem::transmute(edges[i].source) };
let sink = unsafe { std::mem::transmute(edges[i].sink) };
graph.add_edge(source, sink, edges[i].precedence);
}
}
#[repr(C)]
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct sg_scoped_symbol {
pub symbol: sg_symbol_handle,
pub scopes: sg_scope_stack,
}
impl Into<ScopedSymbol> for sg_scoped_symbol {
fn into(self) -> ScopedSymbol {
unsafe { std::mem::transmute(self) }
}
}
#[repr(C)]
#[derive(Clone, Copy, Default, Eq, PartialEq)]
pub struct sg_symbol_stack {
pub cells: sg_symbol_stack_cell_handle,
pub length: u32,
}
impl From<SymbolStack> for sg_symbol_stack {
fn from(stack: SymbolStack) -> sg_symbol_stack {
unsafe { std::mem::transmute(stack) }
}
}
pub type sg_symbol_stack_cell_handle = u32;
#[repr(C)]
pub struct sg_symbol_stack_cell {
pub head: sg_scoped_symbol,
pub tail: sg_symbol_stack_cell_handle,
}
#[repr(C)]
pub struct sg_symbol_stack_cells {
pub cells: *const sg_symbol_stack_cell,
pub count: usize,
}
#[no_mangle]
pub extern "C" fn sg_path_arena_symbol_stack_cells(
paths: *const sg_path_arena,
) -> sg_symbol_stack_cells {
let paths = unsafe { &(*paths).inner };
sg_symbol_stack_cells {
cells: paths.symbol_stacks.as_ptr() as *const sg_symbol_stack_cell,
count: paths.symbol_stacks.len(),
}
}
#[no_mangle]
pub extern "C" fn sg_path_arena_add_symbol_stacks(
paths: *mut sg_path_arena,
count: usize,
mut symbols: *const sg_scoped_symbol,
lengths: *const usize,
out: *mut sg_symbol_stack,
) {
let paths = unsafe { &mut (*paths).inner };
let lengths = unsafe { std::slice::from_raw_parts(lengths, count) };
let out = unsafe { std::slice::from_raw_parts_mut(out, count) };
for i in 0..count {
let length = lengths[i];
let symbols_slice = unsafe { std::slice::from_raw_parts(symbols, length) };
let mut stack = SymbolStack::empty();
for j in (0..length).rev() {
let symbol = symbols_slice[j].into();
stack.push_front(paths, symbol);
}
out[i] = stack.into();
unsafe { symbols = symbols.add(length) };
}
}
#[repr(C)]
#[derive(Clone, Copy, Default, Eq, PartialEq)]
pub struct sg_scope_stack {
pub cells: sg_scope_stack_cell_handle,
pub length: u32,
}
impl From<ScopeStack> for sg_scope_stack {
fn from(stack: ScopeStack) -> sg_scope_stack {
unsafe { std::mem::transmute(stack) }
}
}
pub type sg_scope_stack_cell_handle = u32;
#[repr(C)]
pub struct sg_scope_stack_cell {
pub head: sg_node_handle,
pub tail: sg_scope_stack_cell_handle,
}
#[repr(C)]
pub struct sg_scope_stack_cells {
pub cells: *const sg_scope_stack_cell,
pub count: usize,
}
#[no_mangle]
pub extern "C" fn sg_path_arena_scope_stack_cells(
paths: *const sg_path_arena,
) -> sg_scope_stack_cells {
let paths = unsafe { &(*paths).inner };
sg_scope_stack_cells {
cells: paths.scope_stacks.as_ptr() as *const sg_scope_stack_cell,
count: paths.scope_stacks.len(),
}
}
#[no_mangle]
pub extern "C" fn sg_path_arena_add_scope_stacks(
paths: *mut sg_path_arena,
count: usize,
mut scopes: *const sg_node_handle,
lengths: *const usize,
out: *mut sg_scope_stack,
) {
let paths = unsafe { &mut (*paths).inner };
let lengths = unsafe { std::slice::from_raw_parts(lengths, count) };
let out = unsafe { std::slice::from_raw_parts_mut(out, count) };
for i in 0..count {
let length = lengths[i];
let scopes_slice = unsafe { std::slice::from_raw_parts(scopes, length) };
let mut stack = ScopeStack::empty();
for j in (0..length).rev() {
let node = scopes_slice[j].into();
stack.push_front(paths, node);
}
out[i] = stack.into();
unsafe { scopes = scopes.add(length) };
}
}
#[repr(C)]
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct sg_path_edge {
pub source_node_id: sg_node_id,
pub precedence: i32,
}
impl Into<PathEdge> for sg_path_edge {
fn into(self) -> PathEdge {
unsafe { std::mem::transmute(self) }
}
}
#[repr(C)]
#[derive(Clone, Copy, Default, Eq, PartialEq)]
pub struct sg_path_edge_list {
pub cells: sg_path_edge_list_cell_handle,
pub direction: sg_deque_direction,
pub length: u32,
}
impl From<PathEdgeList> for sg_path_edge_list {
fn from(edges: PathEdgeList) -> sg_path_edge_list {
unsafe { std::mem::transmute(edges) }
}
}
pub type sg_path_edge_list_cell_handle = u32;
#[repr(C)]
pub struct sg_path_edge_list_cell {
pub head: sg_path_edge,
pub tail: sg_path_edge_list_cell_handle,
pub reversed: sg_path_edge_list_cell_handle,
}
#[repr(C)]
pub struct sg_path_edge_list_cells {
pub cells: *const sg_path_edge_list_cell,
pub count: usize,
}
#[no_mangle]
pub extern "C" fn sg_path_arena_path_edge_list_cells(
paths: *const sg_path_arena,
) -> sg_path_edge_list_cells {
let paths = unsafe { &(*paths).inner };
sg_path_edge_list_cells {
cells: paths.path_edges.as_ptr() as *const sg_path_edge_list_cell,
count: paths.path_edges.len(),
}
}
#[no_mangle]
pub extern "C" fn sg_path_arena_add_path_edge_lists(
paths: *mut sg_path_arena,
count: usize,
mut edges: *const sg_path_edge,
lengths: *const usize,
out: *mut sg_path_edge_list,
) {
let paths = unsafe { &mut (*paths).inner };
let lengths = unsafe { std::slice::from_raw_parts(lengths, count) };
let out = unsafe { std::slice::from_raw_parts_mut(out, count) };
for i in 0..count {
let length = lengths[i];
let edges_slice = unsafe { std::slice::from_raw_parts(edges, length) };
let mut list = PathEdgeList::empty();
for j in 0..length {
let edge: PathEdge = edges_slice[j].into();
list.push_back(paths, edge);
}
let _ = list.iter(paths);
out[i] = list.into();
unsafe { edges = edges.add(length) };
}
}
#[repr(C)]
pub struct sg_path {
pub start_node: sg_node_handle,
pub end_node: sg_node_handle,
pub symbol_stack: sg_symbol_stack,
pub scope_stack: sg_scope_stack,
pub edges: sg_path_edge_list,
}
#[derive(Default)]
pub struct sg_path_list {
paths: Vec<Path>,
}
#[no_mangle]
pub extern "C" fn sg_path_list_new() -> *mut sg_path_list {
Box::into_raw(Box::new(sg_path_list::default()))
}
#[no_mangle]
pub extern "C" fn sg_path_list_free(path_list: *mut sg_path_list) {
drop(unsafe { Box::from_raw(path_list) });
}
#[no_mangle]
pub extern "C" fn sg_path_list_count(path_list: *const sg_path_list) -> usize {
let path_list = unsafe { &*path_list };
path_list.paths.len()
}
#[no_mangle]
pub extern "C" fn sg_path_list_paths(path_list: *const sg_path_list) -> *const sg_path {
let path_list = unsafe { &*path_list };
path_list.paths.as_ptr() as *const _
}
#[no_mangle]
pub extern "C" fn sg_path_arena_find_all_complete_paths(
graph: *const sg_stack_graph,
paths: *mut sg_path_arena,
starting_node_count: usize,
starting_nodes: *const sg_node_handle,
path_list: *mut sg_path_list,
) {
let graph = unsafe { &(*graph).inner };
let paths = unsafe { &mut (*paths).inner };
let starting_nodes = unsafe { std::slice::from_raw_parts(starting_nodes, starting_node_count) };
let path_list = unsafe { &mut *path_list };
paths.find_all_paths(
graph,
starting_nodes.iter().copied().map(sg_node_handle::into),
|graph, _paths, path| {
if path.is_complete(graph) {
path_list.paths.push(path);
}
},
);
}
pub type sg_symbol_stack_variable = u32;
#[repr(C)]
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct sg_partial_scoped_symbol {
pub symbol: sg_symbol_handle,
pub scopes: sg_partial_scope_stack,
}
impl Into<PartialScopedSymbol> for sg_partial_scoped_symbol {
fn into(self) -> PartialScopedSymbol {
unsafe { std::mem::transmute(self) }
}
}
#[repr(C)]
#[derive(Clone, Copy, Default, Eq, PartialEq)]
pub struct sg_partial_symbol_stack {
pub cells: sg_partial_symbol_stack_cell_handle,
pub direction: sg_deque_direction,
pub length: u32,
pub variable: sg_symbol_stack_variable,
}
impl From<PartialSymbolStack> for sg_partial_symbol_stack {
fn from(stack: PartialSymbolStack) -> sg_partial_symbol_stack {
unsafe { std::mem::transmute(stack) }
}
}
pub type sg_partial_symbol_stack_cell_handle = u32;
#[repr(C)]
pub struct sg_partial_symbol_stack_cell {
pub head: sg_partial_scoped_symbol,
pub tail: sg_partial_symbol_stack_cell_handle,
pub reversed: sg_partial_symbol_stack_cell_handle,
}
#[repr(C)]
pub struct sg_partial_symbol_stack_cells {
pub cells: *const sg_partial_symbol_stack_cell,
pub count: usize,
}
#[no_mangle]
pub extern "C" fn sg_partial_path_arena_partial_symbol_stack_cells(
partials: *const sg_partial_path_arena,
) -> sg_partial_symbol_stack_cells {
let partials = unsafe { &(*partials).inner };
sg_partial_symbol_stack_cells {
cells: partials.partial_symbol_stacks.as_ptr() as *const sg_partial_symbol_stack_cell,
count: partials.partial_symbol_stacks.len(),
}
}
#[no_mangle]
pub extern "C" fn sg_partial_path_arena_add_partial_symbol_stacks(
partials: *mut sg_partial_path_arena,
count: usize,
mut symbols: *const sg_partial_scoped_symbol,
lengths: *const usize,
variables: *const sg_symbol_stack_variable,
out: *mut sg_partial_symbol_stack,
) {
let partials = unsafe { &mut (*partials).inner };
let lengths = unsafe { std::slice::from_raw_parts(lengths, count) };
let variables = unsafe { std::slice::from_raw_parts(variables, count) };
let out = unsafe { std::slice::from_raw_parts_mut(out, count) };
for i in 0..count {
let length = lengths[i];
let symbols_slice = unsafe { std::slice::from_raw_parts(symbols, length) };
let mut stack = if variables[i] == 0 {
PartialSymbolStack::empty()
} else {
PartialSymbolStack::from_variable(variables[i].try_into().unwrap())
};
for j in 0..length {
let symbol = symbols_slice[j].into();
stack.push_back(partials, symbol);
}
let _ = stack.iter(partials);
out[i] = stack.into();
unsafe { symbols = symbols.add(length) };
}
}
pub type sg_scope_stack_variable = u32;
#[repr(C)]
#[derive(Clone, Copy, Default, Eq, PartialEq)]
pub struct sg_partial_scope_stack {
pub cells: sg_partial_scope_stack_cell_handle,
pub direction: sg_deque_direction,
pub length: u32,
pub variable: sg_scope_stack_variable,
}
impl From<PartialScopeStack> for sg_partial_scope_stack {
fn from(stack: PartialScopeStack) -> sg_partial_scope_stack {
unsafe { std::mem::transmute(stack) }
}
}
pub type sg_partial_scope_stack_cell_handle = u32;
#[repr(C)]
pub struct sg_partial_scope_stack_cell {
pub head: sg_node_handle,
pub tail: sg_path_edge_list_cell_handle,
pub reversed: sg_path_edge_list_cell_handle,
}
#[repr(C)]
pub struct sg_partial_scope_stack_cells {
pub cells: *const sg_partial_scope_stack_cell,
pub count: usize,
}
#[no_mangle]
pub extern "C" fn sg_partial_path_arena_partial_scope_stack_cells(
partials: *const sg_partial_path_arena,
) -> sg_partial_scope_stack_cells {
let partials = unsafe { &(*partials).inner };
sg_partial_scope_stack_cells {
cells: partials.partial_scope_stacks.as_ptr() as *const sg_partial_scope_stack_cell,
count: partials.partial_scope_stacks.len(),
}
}
#[no_mangle]
pub extern "C" fn sg_partial_path_arena_add_partial_scope_stacks(
partials: *mut sg_partial_path_arena,
count: usize,
mut scopes: *const sg_node_handle,
lengths: *const usize,
variables: *const sg_scope_stack_variable,
out: *mut sg_partial_scope_stack,
) {
let partials = unsafe { &mut (*partials).inner };
let lengths = unsafe { std::slice::from_raw_parts(lengths, count) };
let variables = unsafe { std::slice::from_raw_parts(variables, count) };
let out = unsafe { std::slice::from_raw_parts_mut(out, count) };
for i in 0..count {
let length = lengths[i];
let scopes_slice = unsafe { std::slice::from_raw_parts(scopes, length) };
let mut stack = if variables[i] == 0 {
PartialScopeStack::empty()
} else {
PartialScopeStack::from_variable(variables[i].try_into().unwrap())
};
for j in 0..length {
let node = scopes_slice[j].into();
stack.push_back(partials, node);
}
let _ = stack.iter_scopes(partials);
out[i] = stack.into();
unsafe { scopes = scopes.add(length) };
}
}
#[repr(C)]
#[derive(Clone, Copy, Eq, PartialEq)]
pub struct sg_partial_path_edge {
pub source_node_id: sg_node_id,
pub precedence: i32,
}
impl Into<PartialPathEdge> for sg_partial_path_edge {
fn into(self) -> PartialPathEdge {
unsafe { std::mem::transmute(self) }
}
}
#[repr(C)]
#[derive(Clone, Copy, Default, Eq, PartialEq)]
pub struct sg_partial_path_edge_list {
pub cells: sg_partial_path_edge_list_cell_handle,
pub direction: sg_deque_direction,
pub length: u32,
}
impl From<PartialPathEdgeList> for sg_partial_path_edge_list {
fn from(edges: PartialPathEdgeList) -> sg_partial_path_edge_list {
unsafe { std::mem::transmute(edges) }
}
}
pub type sg_partial_path_edge_list_cell_handle = u32;
#[repr(C)]
pub struct sg_partial_path_edge_list_cell {
pub head: sg_partial_path_edge,
pub tail: sg_partial_path_edge_list_cell_handle,
pub reversed: sg_partial_path_edge_list_cell_handle,
}
#[repr(C)]
pub struct sg_partial_path_edge_list_cells {
pub cells: *const sg_partial_path_edge_list_cell,
pub count: usize,
}
#[no_mangle]
pub extern "C" fn sg_partial_path_arena_partial_path_edge_list_cells(
partials: *const sg_partial_path_arena,
) -> sg_partial_path_edge_list_cells {
let partials = unsafe { &(*partials).inner };
sg_partial_path_edge_list_cells {
cells: partials.partial_path_edges.as_ptr() as *const sg_partial_path_edge_list_cell,
count: partials.partial_path_edges.len(),
}
}
#[no_mangle]
pub extern "C" fn sg_partial_path_arena_add_partial_path_edge_lists(
partials: *mut sg_partial_path_arena,
count: usize,
mut edges: *const sg_partial_path_edge,
lengths: *const usize,
out: *mut sg_partial_path_edge_list,
) {
let partials = unsafe { &mut (*partials).inner };
let lengths = unsafe { std::slice::from_raw_parts(lengths, count) };
let out = unsafe { std::slice::from_raw_parts_mut(out, count) };
for i in 0..count {
let length = lengths[i];
let edges_slice = unsafe { std::slice::from_raw_parts(edges, length) };
let mut list = PartialPathEdgeList::empty();
for j in 0..length {
let edge: PartialPathEdge = edges_slice[j].into();
list.push_back(partials, edge);
}
let _ = list.iter(partials);
out[i] = list.into();
unsafe { edges = edges.add(length) };
}
}
#[repr(C)]
#[derive(Clone, Copy)]
pub struct sg_partial_path {
pub start_node: sg_node_handle,
pub end_node: sg_node_handle,
pub symbol_stack_precondition: sg_partial_symbol_stack,
pub symbol_stack_postcondition: sg_partial_symbol_stack,
pub scope_stack_precondition: sg_partial_scope_stack,
pub scope_stack_postcondition: sg_partial_scope_stack,
pub edges: sg_partial_path_edge_list,
}
impl Into<PartialPath> for sg_partial_path {
fn into(self) -> PartialPath {
unsafe { std::mem::transmute(self) }
}
}
#[derive(Default)]
pub struct sg_partial_path_list {
partial_paths: Vec<PartialPath>,
}
#[no_mangle]
pub extern "C" fn sg_partial_path_list_new() -> *mut sg_partial_path_list {
Box::into_raw(Box::new(sg_partial_path_list::default()))
}
#[no_mangle]
pub extern "C" fn sg_partial_path_list_free(partial_path_list: *mut sg_partial_path_list) {
drop(unsafe { Box::from_raw(partial_path_list) });
}
#[no_mangle]
pub extern "C" fn sg_partial_path_list_count(
partial_path_list: *const sg_partial_path_list,
) -> usize {
let partial_path_list = unsafe { &*partial_path_list };
partial_path_list.partial_paths.len()
}
#[no_mangle]
pub extern "C" fn sg_partial_path_list_paths(
partial_path_list: *const sg_partial_path_list,
) -> *const sg_partial_path {
let partial_path_list = unsafe { &*partial_path_list };
partial_path_list.partial_paths.as_ptr() as *const _
}
#[no_mangle]
pub extern "C" fn sg_partial_path_arena_find_partial_paths_in_file(
graph: *const sg_stack_graph,
partials: *mut sg_partial_path_arena,
file: sg_file_handle,
partial_path_list: *mut sg_partial_path_list,
) {
let graph = unsafe { &(*graph).inner };
let partials = unsafe { &mut (*partials).inner };
let file = file.into();
let partial_path_list = unsafe { &mut *partial_path_list };
partials.find_all_partial_paths_in_file(graph, file, |graph, partials, mut path| {
if !path.is_complete_as_possible(graph) {
return;
}
if !path.is_productive(partials) {
return;
}
path.ensure_both_directions(partials);
partial_path_list.partial_paths.push(path);
});
}
pub type sg_partial_path_handle = u32;
#[repr(C)]
pub struct sg_partial_paths {
pub paths: *const sg_partial_path,
pub count: usize,
}
#[no_mangle]
pub extern "C" fn sg_partial_path_database_partial_paths(
db: *const sg_partial_path_database,
) -> sg_partial_paths {
let db = unsafe { &(*db).inner };
sg_partial_paths {
paths: db.partial_paths.as_ptr() as *const sg_partial_path,
count: db.partial_paths.len(),
}
}
#[no_mangle]
pub extern "C" fn sg_partial_path_database_add_partial_paths(
graph: *const sg_stack_graph,
partials: *mut sg_partial_path_arena,
db: *mut sg_partial_path_database,
count: usize,
paths: *const sg_partial_path,
out: *mut sg_partial_path_handle,
) {
let graph = unsafe { &(*graph).inner };
let partials = unsafe { &mut (*partials).inner };
let db = unsafe { &mut (*db).inner };
let paths = unsafe { std::slice::from_raw_parts(paths, count) };
let out = unsafe { std::slice::from_raw_parts_mut(out as *mut Handle<PartialPath>, count) };
for i in 0..count {
out[i] = db.add_partial_path(graph, partials, paths[i].into());
}
}
#[repr(C)]
pub struct sg_forward_path_stitcher {
pub previous_phase_paths: *const sg_path,
pub previous_phase_paths_length: usize,
}
#[repr(C)]
struct ForwardPathStitcher {
previous_phase_paths: *const Path,
previous_phase_paths_length: usize,
stitcher: PathStitcher,
}
impl ForwardPathStitcher {
fn new(stitcher: PathStitcher, paths: &mut Paths) -> ForwardPathStitcher {
let mut this = ForwardPathStitcher {
previous_phase_paths: std::ptr::null(),
previous_phase_paths_length: 0,
stitcher,
};
this.update_previous_phase_paths(paths);
this
}
fn update_previous_phase_paths(&mut self, paths: &mut Paths) {
for path in self.stitcher.previous_phase_paths_slice_mut() {
let _ = path.edges.iter(paths);
}
let slice = self.stitcher.previous_phase_paths_slice();
self.previous_phase_paths = slice.as_ptr();
self.previous_phase_paths_length = slice.len();
}
}
#[no_mangle]
pub extern "C" fn sg_forward_path_stitcher_new(
graph: *const sg_stack_graph,
paths: *mut sg_path_arena,
partials: *mut sg_partial_path_arena,
db: *mut sg_partial_path_database,
count: usize,
starting_nodes: *const sg_node_handle,
) -> *mut sg_forward_path_stitcher {
let graph = unsafe { &(*graph).inner };
let paths = unsafe { &mut (*paths).inner };
let partials = unsafe { &mut (*partials).inner };
let db = unsafe { &mut (*db).inner };
let starting_nodes = unsafe { std::slice::from_raw_parts(starting_nodes, count) };
let stitcher = PathStitcher::new(
graph,
paths,
partials,
db,
starting_nodes.iter().copied().map(sg_node_handle::into),
);
Box::into_raw(Box::new(ForwardPathStitcher::new(stitcher, paths))) as *mut _
}
#[no_mangle]
pub extern "C" fn sg_forward_path_stitcher_process_next_phase(
graph: *const sg_stack_graph,
paths: *mut sg_path_arena,
partials: *mut sg_partial_path_arena,
db: *mut sg_partial_path_database,
stitcher: *mut sg_forward_path_stitcher,
) {
let graph = unsafe { &(*graph).inner };
let paths = unsafe { &mut (*paths).inner };
let partials = unsafe { &mut (*partials).inner };
let db = unsafe { &mut (*db).inner };
let stitcher = unsafe { &mut *(stitcher as *mut ForwardPathStitcher) };
stitcher
.stitcher
.process_next_phase(graph, paths, partials, db);
stitcher.update_previous_phase_paths(paths);
}
#[no_mangle]
pub extern "C" fn sg_forward_path_stitcher_free(stitcher: *mut sg_forward_path_stitcher) {
drop(unsafe { Box::from_raw(stitcher as *mut ForwardPathStitcher) });
}
#[repr(C)]
pub struct sg_forward_partial_path_stitcher {
pub previous_phase_partial_paths: *const sg_partial_path,
pub previous_phase_partial_paths_length: usize,
}
#[repr(C)]
struct InternalForwardPartialPathStitcher {
previous_phase_partial_paths: *const PartialPath,
previous_phase_partial_paths_length: usize,
stitcher: ForwardPartialPathStitcher,
}
impl InternalForwardPartialPathStitcher {
fn new(
stitcher: ForwardPartialPathStitcher,
partials: &mut PartialPaths,
) -> InternalForwardPartialPathStitcher {
let mut this = InternalForwardPartialPathStitcher {
previous_phase_partial_paths: std::ptr::null(),
previous_phase_partial_paths_length: 0,
stitcher,
};
this.update_previous_phase_partial_paths(partials);
this
}
fn update_previous_phase_partial_paths(&mut self, partials: &mut PartialPaths) {
for path in self.stitcher.previous_phase_partial_paths_slice_mut() {
path.ensure_both_directions(partials);
}
let slice = self.stitcher.previous_phase_partial_paths_slice();
self.previous_phase_partial_paths = slice.as_ptr();
self.previous_phase_partial_paths_length = slice.len();
}
}
#[no_mangle]
pub extern "C" fn sg_forward_partial_path_stitcher_new(
graph: *const sg_stack_graph,
partials: *mut sg_partial_path_arena,
db: *mut sg_partial_path_database,
count: usize,
starting_nodes: *const sg_node_handle,
) -> *mut sg_forward_partial_path_stitcher {
let graph = unsafe { &(*graph).inner };
let partials = unsafe { &mut (*partials).inner };
let db = unsafe { &mut (*db).inner };
let starting_nodes = unsafe { std::slice::from_raw_parts(starting_nodes, count) };
let stitcher = ForwardPartialPathStitcher::new(
graph,
partials,
db,
starting_nodes.iter().copied().map(sg_node_handle::into),
);
Box::into_raw(Box::new(InternalForwardPartialPathStitcher::new(
stitcher, partials,
))) as *mut _
}
#[no_mangle]
pub extern "C" fn sg_forward_partial_path_stitcher_process_next_phase(
graph: *const sg_stack_graph,
partials: *mut sg_partial_path_arena,
db: *mut sg_partial_path_database,
stitcher: *mut sg_forward_partial_path_stitcher,
) {
let graph = unsafe { &(*graph).inner };
let partials = unsafe { &mut (*partials).inner };
let db = unsafe { &mut (*db).inner };
let stitcher = unsafe { &mut *(stitcher as *mut InternalForwardPartialPathStitcher) };
stitcher.stitcher.process_next_phase(graph, partials, db);
stitcher.update_previous_phase_partial_paths(partials);
}
#[no_mangle]
pub extern "C" fn sg_forward_partial_path_stitcher_free(
stitcher: *mut sg_forward_partial_path_stitcher,
) {
drop(unsafe { Box::from_raw(stitcher as *mut InternalForwardPartialPathStitcher) });
}