seperate Project Topology Module

This commit is contained in:
Umur Ozkul 2022-08-14 16:14:14 +02:00
parent f21725d86c
commit 0c1c5c9499
4 changed files with 86 additions and 73 deletions

View File

@ -173,4 +173,3 @@ describe("project with include", () => {
runFetchBindings(project, "main")->expect->toBe("@{common: 0,x: 1,y: 2}") runFetchBindings(project, "main")->expect->toBe("@{common: 0,x: 1,y: 2}")
}) })
}) })

View File

@ -9,6 +9,7 @@ module InternalExpressionValue = ReducerInterface_InternalExpressionValue
module ProjectAccessorsT = ReducerProject_ProjectAccessors_T module ProjectAccessorsT = ReducerProject_ProjectAccessors_T
module ProjectItem = ReducerProject_ProjectItem module ProjectItem = ReducerProject_ProjectItem
module T = ReducerProject_T module T = ReducerProject_T
module Topology = ReducerProject_Topology
@genType.opaque @genType.opaque
type project = T.t type project = T.t
@ -18,59 +19,12 @@ module Private = {
type internalProject = T.Private.t type internalProject = T.Private.t
type t = T.Private.t type t = T.Private.t
let getSourceIds = (this: t): array<string> => Belt.Map.String.keysToArray(this["items"]) let getSourceIds = T.Private.getSourceIds
let getItem = T.Private.getItem
let getItem = (this: t, sourceId: string) => let getDependents = Topology.getDependents
Belt.Map.String.getWithDefault(this["items"], sourceId, ProjectItem.emptyItem) let getDependencies = Topology.getDependencies
let getRunOrder = Topology.getRunOrder
let getImmediateDependencies = (this: t, sourceId: string): ProjectItem.T.includesType => let getRunOrderFor = Topology.getRunOrderFor
getItem(this, sourceId)->ProjectItem.getImmediateDependencies
type topologicalSortState = (Belt.Map.String.t<bool>, list<string>)
let rec topologicalSortUtil = (
this: t,
sourceId: string,
state: topologicalSortState,
): topologicalSortState => {
let dependencies = getImmediateDependencies(this, sourceId)->Belt.Result.getWithDefault([])
let (visited, stack) = state
let myVisited = Belt.Map.String.set(visited, sourceId, true)
let (newVisited, newStack) = dependencies->Belt.Array.reduce((myVisited, stack), (
(currVisited, currStack),
dependency,
) => {
if !Belt.Map.String.getWithDefault(currVisited, dependency, false) {
topologicalSortUtil(this, dependency, (currVisited, currStack))
} else {
(currVisited, currStack)
}
})
(newVisited, list{sourceId, ...newStack})
}
let getTopologicalSort = (this: t): array<string> => {
let (_visited, stack) = getSourceIds(this)->Belt.Array.reduce((Belt.Map.String.empty, list{}), (
(currVisited, currStack),
currId,
) =>
if !Belt.Map.String.getWithDefault(currVisited, currId, false) {
topologicalSortUtil(this, currId, (currVisited, currStack))
} else {
(currVisited, currStack)
}
)
Belt.List.reverse(stack)->Belt.List.toArray
}
let getTopologicalSortFor = (this: t, sourceId) => {
let runOrder = getTopologicalSort(this)
let index = runOrder->Js.Array2.indexOf(sourceId)
let after = Belt.Array.sliceToEnd(runOrder, index + 1)
let before = Js.Array2.slice(runOrder, ~start=0, ~end_=index + 1)
(before, after)
}
let getRunOrder = getTopologicalSort
let createProject = () => { let createProject = () => {
let this: t = { let this: t = {
@ -81,23 +35,6 @@ module Private = {
this this
} }
let getRunOrderFor = (this: t, sourceId: string) => {
let (runOrder, _) = getTopologicalSortFor(this, sourceId)
runOrder
}
let getDependencies = (this: t, sourceId: string): array<string> => {
let runOrder = getRunOrderFor(this, sourceId)
let _ = Js.Array2.pop(runOrder)
runOrder
}
let getDependents = (this: t, sourceId: string): array<string> => {
let (_, dependents) = getTopologicalSortFor(this, sourceId)
dependents
}
let rec touchSource = (this: t, sourceId: string): unit => { let rec touchSource = (this: t, sourceId: string): unit => {
let item = this->getItem(sourceId) let item = this->getItem(sourceId)
let newItem = ProjectItem.touchSource(item) let newItem = ProjectItem.touchSource(item)
@ -245,7 +182,7 @@ module Private = {
} }
let runAll = (this: t): unit => { let runAll = (this: t): unit => {
let runOrder = getTopologicalSort(this) let runOrder = Topology.getRunOrder(this)
let initialState = (Ok(InternalExpressionValue.IEvVoid), getStdLib(this)) let initialState = (Ok(InternalExpressionValue.IEvVoid), getStdLib(this))
let _finalState = Belt.Array.reduce(runOrder, initialState, (currState, currId) => let _finalState = Belt.Array.reduce(runOrder, initialState, (currState, currId) =>
tryRunWithContinuation(this, currId, currState) tryRunWithContinuation(this, currId, currState)
@ -253,7 +190,7 @@ module Private = {
} }
let run = (this: t, sourceId: string): unit => { let run = (this: t, sourceId: string): unit => {
let runOrder = getRunOrderFor(this, sourceId) let runOrder = Topology.getRunOrderFor(this, sourceId)
let initialState = (Ok(InternalExpressionValue.IEvVoid), getStdLib(this)) let initialState = (Ok(InternalExpressionValue.IEvVoid), getStdLib(this))
let _finalState = Belt.Array.reduce(runOrder, initialState, (currState, currId) => let _finalState = Belt.Array.reduce(runOrder, initialState, (currState, currId) =>
tryRunWithContinuation(this, currId, currState) tryRunWithContinuation(this, currId, currState)

View File

@ -22,4 +22,9 @@ module Private = {
external castFromInternalProject: t => project = "%identity" external castFromInternalProject: t => project = "%identity"
external castToInternalProject: project => t = "%identity" external castToInternalProject: project => t = "%identity"
let getSourceIds = (this: t): array<string> => Belt.Map.String.keysToArray(this["items"])
let getItem = (this: t, sourceId: string) =>
Belt.Map.String.getWithDefault(this["items"], sourceId, ProjectItem.emptyItem)
} }

View File

@ -0,0 +1,72 @@
module ProjectItem = ReducerProject_ProjectItem
module T = ReducerProject_T
type t = T.Private.t
let getSourceIds = T.Private.getSourceIds
let getItem = T.Private.getItem
let getImmediateDependencies = (this: t, sourceId: string): ProjectItem.T.includesType =>
getItem(this, sourceId)->ProjectItem.getImmediateDependencies
type topologicalSortState = (Belt.Map.String.t<bool>, list<string>)
let rec topologicalSortUtil = (
this: t,
sourceId: string,
state: topologicalSortState,
): topologicalSortState => {
let dependencies = getImmediateDependencies(this, sourceId)->Belt.Result.getWithDefault([])
let (visited, stack) = state
let myVisited = Belt.Map.String.set(visited, sourceId, true)
let (newVisited, newStack) = dependencies->Belt.Array.reduce((myVisited, stack), (
(currVisited, currStack),
dependency,
) => {
if !Belt.Map.String.getWithDefault(currVisited, dependency, false) {
topologicalSortUtil(this, dependency, (currVisited, currStack))
} else {
(currVisited, currStack)
}
})
(newVisited, list{sourceId, ...newStack})
}
let getTopologicalSort = (this: t): array<string> => {
let (_visited, stack) = getSourceIds(this)->Belt.Array.reduce((Belt.Map.String.empty, list{}), (
(currVisited, currStack),
currId,
) =>
if !Belt.Map.String.getWithDefault(currVisited, currId, false) {
topologicalSortUtil(this, currId, (currVisited, currStack))
} else {
(currVisited, currStack)
}
)
Belt.List.reverse(stack)->Belt.List.toArray
}
let getTopologicalSortFor = (this: t, sourceId) => {
let runOrder = getTopologicalSort(this)
let index = runOrder->Js.Array2.indexOf(sourceId)
let after = Belt.Array.sliceToEnd(runOrder, index + 1)
let before = Js.Array2.slice(runOrder, ~start=0, ~end_=index + 1)
(before, after)
}
let getRunOrder = getTopologicalSort
let getRunOrderFor = (this: t, sourceId: string) => {
let (runOrder, _) = getTopologicalSortFor(this, sourceId)
runOrder
}
let getDependencies = (this: t, sourceId: string): array<string> => {
let runOrder = getRunOrderFor(this, sourceId)
let _ = Js.Array2.pop(runOrder)
runOrder
}
let getDependents = (this: t, sourceId: string): array<string> => {
let (_, dependents) = getTopologicalSortFor(this, sourceId)
dependents
}