deskc_evalmir/
lib.rs

1pub mod const_stmt;
2pub mod eval_mir;
3pub mod op_stmt;
4pub mod value;
5
6use std::collections::{HashMap, VecDeque};
7
8use mir::{
9    mir::{Mir, Mirs},
10    ty::ConcEffect,
11    BlockId, MirId,
12};
13use value::Value;
14
15use crate::{
16    eval_mir::{EvalMir, Handler, InnerOutput},
17    value::Closure,
18};
19
20pub fn eval_mirs(mirs: Mirs) -> EvalMirs {
21    let mir = mirs.mirs.get(mirs.entrypoint.0).cloned().unwrap();
22    EvalMirs {
23        mirs: mirs.mirs,
24        stack: vec![EvalMir {
25            mir,
26            registers: HashMap::new(),
27            parameters: HashMap::new(),
28            captured: HashMap::new(),
29            pc_block: BlockId(0),
30            pc_stmt_idx: 0,
31            return_register: None,
32            handlers: HashMap::new(),
33        }],
34    }
35}
36
37#[derive(Clone, Debug)]
38pub struct EvalMirs {
39    mirs: Vec<Mir>,
40    stack: Vec<EvalMir>,
41}
42
43impl EvalMirs {
44    pub fn eval_next(&mut self) -> Output {
45        match self.stack().eval_next() {
46            InnerOutput::Return(value) => {
47                // When top level
48                if self.stack.len() == 1 {
49                    Output::Return(value)
50                } else {
51                    self.stack.pop().unwrap();
52                    self.stack().return_or_continue_with_value(value);
53                    Output::Running
54                }
55            }
56            InnerOutput::Perform { input, effect } => {
57                let mut continuation_from_handler = VecDeque::new();
58                let handler = loop {
59                    if let Some(eval_mir) = self.stack.pop() {
60                        // find handler
61                        let handler = eval_mir.handlers.get(&effect).cloned();
62                        // push eval_mir to continuation
63                        continuation_from_handler.push_front(eval_mir);
64                        if let Some(handler) = handler {
65                            break handler;
66                        }
67                    } else {
68                        // When handler are not found, push back to continuation stack and perform
69                        self.stack.extend(continuation_from_handler);
70                        return Output::Perform { input, effect };
71                    }
72                };
73                match handler {
74                    eval_mir::Handler::Handler(Closure {
75                        mir,
76                        mut captured,
77                        // Really ignorable??
78                        handlers: _,
79                    }) => {
80                        captured.insert(effect.input.clone(), input);
81                        let eval_mir = EvalMir {
82                            mir: self.get_mir(&mir).clone(),
83                            registers: Default::default(),
84                            parameters: Default::default(),
85                            captured,
86                            pc_block: BlockId(0),
87                            pc_stmt_idx: 0,
88                            return_register: None,
89                            handlers: [(
90                                ConcEffect {
91                                    input: effect.output,
92                                    output: continuation_from_handler[0].mir.output.clone(),
93                                },
94                                Handler::Continuation(continuation_from_handler.into()),
95                            )]
96                            .into_iter()
97                            .collect(),
98                        };
99                        self.stack.push(eval_mir);
100                        Output::Running
101                    }
102                    eval_mir::Handler::Continuation(continuation) => {
103                        self.stack.extend(continuation_from_handler);
104                        self.stack.extend(continuation);
105                        // path input to continuation
106                        self.stack().return_or_continue_with_value(input);
107                        Output::Running
108                    }
109                }
110            }
111            InnerOutput::RunOther { fn_ref, parameters } => match fn_ref {
112                value::FnRef::Link(_) => todo!(),
113                value::FnRef::Closure(Closure {
114                    mir,
115                    captured,
116                    handlers,
117                }) => {
118                    let eval_mir = EvalMir {
119                        mir: self.get_mir(&mir).clone(),
120                        registers: Default::default(),
121                        parameters,
122                        captured,
123                        pc_block: Default::default(),
124                        pc_stmt_idx: Default::default(),
125                        return_register: None,
126                        handlers,
127                    };
128                    self.stack.push(eval_mir);
129                    Output::Running
130                }
131                value::FnRef::Recursion => {
132                    let eval_mir = EvalMir {
133                        mir: self.stack().mir.clone(),
134                        registers: Default::default(),
135                        parameters,
136                        captured: self.stack().captured.clone(),
137                        pc_block: Default::default(),
138                        pc_stmt_idx: Default::default(),
139                        return_register: None,
140                        handlers: self.stack().handlers.clone(),
141                    };
142                    self.stack.push(eval_mir);
143                    Output::Running
144                }
145            },
146            InnerOutput::Running => Output::Running,
147        }
148    }
149
150    pub fn stack(&mut self) -> &mut EvalMir {
151        self.stack.last_mut().unwrap()
152    }
153
154    pub fn get_mir(&self, mir_id: &MirId) -> &Mir {
155        &self.mirs[mir_id.0]
156    }
157}
158
159#[derive(Debug, Clone, PartialEq)]
160pub enum Output {
161    Return(Value),
162    Perform { input: Value, effect: ConcEffect },
163    Running,
164}