Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Sources/PNDependencyGraph/PNCompilationError.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import Foundation

public enum PNCompilationError: Error {
/// Indicates that the graph contains a cycle and cannot be compiled.
case cycle
}
1 change: 1 addition & 0 deletions Sources/PNDependencyGraph/PNCompiledGraph.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation

/// A compiled dependency graph.
public final class PNCompiledGraph {
let nodes: [PNNode]
init(nodes newNodes: [PNNode]) {
Expand Down
27 changes: 23 additions & 4 deletions Sources/PNDependencyGraph/PNDependencyGraph.swift
Original file line number Diff line number Diff line change
@@ -1,27 +1,46 @@
import Foundation

public enum PNCompilationError: Error {
case cycle
}

/// The main class for building and compiling dependency graphs.
///
/// This class provides methods to add nodes, define dependencies between them,
/// and compile the graph into a topologically sorted order.
public final class PNGraph {
/// A dictionary of all nodes in the graph, keyed by their identifiers.
private var nodes: [String: PNNode] = [:]

/// Adds a new node to the graph with the specified identifier.
///
/// If a node with this identifier already exists, it is returned instead of creating a new one.
///
/// - Parameter identifier: A unique identifier for the node.
/// - Returns: The node associated with the provided identifier.
public func add(identifier: String) -> PNNode {
if let existing = nodes[identifier] { return existing }
let node = PNNode(identifier: identifier)
nodes[identifier] = node
return node
}

/// Initializes an empty dependency graph.
public init() {

}

/// Retrieves a node from the graph by its identifier.
///
/// - Parameter identifier: The identifier of the node to retrieve.
/// - Returns: The node with the specified identifier, or `nil` if not found.
public func get(identifier: String) -> PNNode? {
nodes[identifier]
}

/// Compiles the dependency graph into a topologically sorted order.
///
/// This method performs a depth-first search to detect cycles and generate an execution order.
/// If a cycle is detected, it throws `PNCompilationError.cycle`.
///
/// - Returns: A compiled graph containing nodes in topological order.
/// - Throws: `PNCompilationError.cycle` if the graph contains a cycle.
public func compile() throws -> PNCompiledGraph {
var visited: Set<String> = []
var visiting: Set<String> = []
Expand Down
Loading