1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
use nando_support::HostIdx;

use crate::plans::host_target_built_ins::PredefinedTargetFunction;

pub(crate) type TaskIdx = usize;

#[derive(Clone, Debug)]
pub(crate) enum TaskIndex {
    SelfIdx,
    Idx(TaskIdx),
    // TODO we can encapsulate a universal quantifier by changing this from a usize to some kind
    // of enum
    Spawns(usize),
}

#[derive(Clone, Debug)]
pub(crate) enum PlanNodeIdx {
    Any,
    Idx(TaskIdx),
}

#[derive(Clone, Debug)]
pub(crate) enum ObjectArgumentDomain {
    Arguments,
    Objects,
    Allocations,
    NoDomain,
}

#[derive(Clone, Debug)]
pub(crate) struct ObjectArgumentRef {
    // FIXME should be able to say `spawner` / `parent` here but will do for now
    pub node_idx: TaskIndex,
    pub domain: ObjectArgumentDomain,
    pub arg_idx: usize,
}

#[derive(Clone, Debug)]
pub(crate) enum Dependency {
    ObjectDependency(ObjectArgumentRef, ObjectArgumentRef),
    ControlDependency(TaskIndex),
}

#[derive(Clone, Debug)]
pub struct HostTargetEvalCtx<'a> {
    pub hosts: &'a Vec<HostIdx>,
    pub self_idx: TaskIdx,
}

#[derive(Clone, Debug)]
pub(crate) enum HostTarget {
    NextHost,
    HostIdx(usize),
    EvalResult(PredefinedTargetFunction),
    // Owner(Vec<ObjectArgumentRef>),
    Owner(ObjectArgumentRef),
    NonOwners(ObjectArgumentRef),
}

#[derive(Clone, Debug)]
pub(crate) struct LocaticsSpecifier {
    pub target_object: ObjectArgumentRef,
    pub target_host: HostTarget,
}

#[derive(Clone, Debug)]
pub(crate) enum RangeOver {
    NoRange,
    Spawns,
    Hosts,
}

#[derive(Clone, Debug)]
pub(crate) struct RangedLocaticsSpecifier {
    pub range: RangeOver,
    pub specifier: LocaticsSpecifier,
}

#[derive(Clone, Debug, Default)]
pub(crate) struct ActionBlock {
    pub dependencies: Vec<Dependency>,
    pub ownership_transfers: Vec<LocaticsSpecifier>,
    pub moves: Vec<LocaticsSpecifier>,
    pub push_copies: Vec<RangedLocaticsSpecifier>,
}

impl ActionBlock {
    pub fn is_default(&self) -> bool {
        self.dependencies.is_empty()
            && self.ownership_transfers.is_empty()
            && self.moves.is_empty()
            && self.push_copies.is_empty()
    }
}

#[derive(Clone, Debug, Default)]
pub(crate) struct PostActionBlock {
    pub append_to_current_task: bool,
    pub action_block: ActionBlock,
}

impl PostActionBlock {
    pub fn is_default(&self) -> bool {
        self.append_to_current_task == false && self.action_block.is_default()
    }
}

#[derive(Clone, Debug)]
pub(crate) enum ActivationTarget {
    Owner(ObjectArgumentRef),
}

#[derive(Clone, Debug)]
pub(crate) struct PhysicalPlanNode {
    pub idx: PlanNodeIdx,
    pub intent_name: String,
    pub schedule_on: ActivationTarget,
    pub pre_actions: ActionBlock,
    pub post_actions: PostActionBlock,
}

#[derive(Clone, Debug, Default)]
pub(crate) struct ParsedPhysicalPlan {
    pub nodes: Vec<PhysicalPlanNode>,
}

impl ParsedPhysicalPlan {
    pub fn find_node_for_intent(
        &self,
        intent_name: &str,
        min_idx: TaskIdx,
    ) -> Option<&PhysicalPlanNode> {
        // NOTE Assumes that Any nodes follow all numbered nodes in the plan.
        let start_idx = match self.nodes.binary_search_by_key(&min_idx, |n| match n.idx {
            PlanNodeIdx::Idx(task_idx) => task_idx,
            PlanNodeIdx::Any => TaskIdx::MAX,
        }) {
            Ok(idx) => idx,
            Err(any_block_start_idx) => any_block_start_idx,
        };

        for idx in start_idx..self.nodes.len() {
            if &self.nodes[idx].intent_name == intent_name {
                return Some(&self.nodes[idx]);
            }
        }

        None
    }
}