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
use std::fmt::{Display, Write};

use crate::object::ClosureFunction;

use super::super::bytecode::errors::FrameError;
use super::super::bytecode::instruction::Instruction;

/// Stack Frame of function.
///
/// * cf - Compiled function closure
/// * bp - base pointer aka bp (stack index of return)
/// * ic - instruction counter (same as program counter) aka ic
pub struct Frame {
    /// * cf - Compiled function closure
    cf: ClosureFunction,
    /// * bp - base pointer aka bp (stack index of return)
    bp: usize,
    /// * ic - instruction counter (same as program counter) aka ic
    ic: usize,
}

impl Frame {
    /// Creates a new [`Frame`].
    /// * `fun`- Compiled function closure
    /// * `base_ptr` - base pointer aka bp (stack index of return)
    pub fn new(fun: ClosureFunction, base_ptr: usize) -> Self {
        Self {
            cf: fun,
            bp: base_ptr,
            ic: 0,
        }
    }

    /// Returns the rext instruction of this [`Frame`]
    /// by reading instruction from [`Self::cf`],
    ///
    /// # Errors [`FrameError::InnerError`]
    ///
    /// This function will return an error if failed to read instruction
    pub fn rext_instruction(&self) -> Result<Instruction, FrameError> {
        Ok(self.cf.fun.instructions.read_instruction(self.ic)?)
    }

    /// Sets the ic of this [`Frame`].
    pub fn set_ic(&mut self, tgt: usize) {
        self.ic = tgt
    }
    /// Add ic with given `offset`
    pub fn add_ic(&mut self, offset: usize) {
        self.ic += offset
    }

    /// Returns the ic of this [`Frame`]
    pub fn ic(&self) -> usize {
        #![allow(dead_code)]
        self.ic
    }

    /// Returns the bp of this [`Frame`].
    pub fn bp(&self) -> usize {
        self.bp
    }

    /// Returns the is runnable of this [`Frame`].
    pub fn is_runnable(&self) -> bool {
        self.ic < self.cf.fun.instructions.length()
    }

    /// Returns a reference to the get closure ref of this [`Frame`].
    pub fn get_closure_ref(&self) -> &ClosureFunction {
        &self.cf
    }
}

impl Display for Frame {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let mut buf = String::new();
        buf += &format!("<FRAME> IC : {}, BP : {}\n", self.ic, self.bp);
        buf += "\nINSTRUCTIONS\n";
        buf += &self.cf.fun.instructions.to_string_with_highlight(self.ic);

        f.write_str(buf.as_str())
    }
}