stackr_rs/interpreter/
evaluate.rs

1use super::*;
2
3impl<State> Interpreter<State> {
4    /// Resets the program counter and clears the program and program debug locations but preserves RAM and stack.
5    #[allow(dead_code)]
6    pub fn reset_program(&mut self) {
7        self.program_counter = 0;
8        self.program.clear();
9        self.program_debug_locations.clear();
10    }
11
12    /// Load a program into the interpreter.
13    pub(crate) fn load_program(&mut self, code: &str, path: Option<PathBuf>) -> Result<(), Err> {
14        let mut location = Location::new(path);
15
16        let mut maybe_make_word = |buffer: &mut String, word_location: &Location| {
17            if !buffer.is_empty() {
18                let word = buffer.trim();
19                let location = word_location.clone();
20                self.program_debug_locations.push(location);
21
22                // Try to parse number
23                let instruction = if let Ok(number) = word.parse::<Number>() {
24                    Instruction::PushNumber(number)
25                } else if word.starts_with('"') {
26                    // Remove the first and last character
27                    let mut word = word.to_string();
28                    word.remove(0);
29                    word.pop();
30                    Instruction::PushString(word)
31                } else {
32                    Instruction::Address(self.get_address(word))
33                };
34                self.program.push(instruction);
35                *buffer = String::new();
36            }
37        };
38
39        let mut buffer = String::new();
40        let mut word_location = location.clone();
41        let mut making_string = false;
42        let mut made_string = false;
43
44        for c in code.chars() {
45            if c == '"' {
46                if !making_string {
47                    making_string = true;
48                } else {
49                    let last_char = buffer.chars().last();
50                    if last_char != Some('\\') {
51                        making_string = false;
52                        made_string = true;
53                        buffer.push(c);
54                    }
55                }
56            }
57            if !making_string && c.is_whitespace() || made_string {
58                made_string = false;
59                maybe_make_word(&mut buffer, &word_location);
60            } else {
61                // set word location to current location if buffer is empty
62                // as this is the first character of the word
63                if buffer.is_empty() {
64                    word_location = location.clone();
65                }
66                buffer.push(c);
67            }
68
69            // Update location
70            if c == '\n' {
71                location.new_line();
72            } else {
73                location.next();
74            }
75        }
76
77        if making_string {
78            return Err(("Unclosed string".into(), word_location));
79        }
80
81        // Handle case if buffer is not empty
82        maybe_make_word(&mut buffer, &word_location);
83
84        Ok(())
85    }
86
87    /// Execute the program.
88    pub(crate) fn execute(&mut self) -> Result<(), Err> {
89        while self.program_counter < self.program.len() {
90            let instruction = self.program[self.program_counter].clone();
91            self.execute_instruction(instruction)?;
92            self.program_counter += 1;
93        }
94
95        Ok(())
96    }
97
98    /// Execute an instruction.
99    pub(crate) fn execute_instruction(&mut self, instruction: Instruction) -> Result<(), Err> {
100        match instruction {
101            Instruction::PushString(string) => self.push_string(string),
102            Instruction::PushNumber(number) => self.push_number(number),
103            Instruction::Address(address) => {
104                // If we are in read mode, we only want to push the address if it is not the end of the read mode
105                if self.read_mode != ReadMode::Off && address != self.address_cache.read_mode_end {
106                    if self.read_mode == ReadMode::SingleWord {
107                        self.read_mode = ReadMode::Off;
108
109                        // Only insert a new address if it is not already in the ram
110                        if !self.ram.contains_key(&address) {
111                            let variable_location = self.next_address;
112                            self.next_address = self.next_address.next();
113                            self.ram
114                                .insert(address, RamValue::Address(variable_location));
115                        }
116                    } else {
117                        self.push_address(address);
118                    }
119                } else {
120                    // Get address contents from memory and execute
121                    let contents = self.ram.get(&address).ok_or((
122                        format!("Address not found: {}", self.get_name(address)),
123                        self.location(),
124                    ))?;
125                    let ops_to_execute = match contents {
126                        RamValue::Compiled(ops) => Some(ops.clone()),
127                        RamValue::BuiltIn(method) => {
128                            method(self)?;
129                            None
130                        }
131                        RamValue::Value(value) => {
132                            self.stack.push(StackValue::Value(value.clone()));
133                            None
134                        }
135                        RamValue::Address(address) => {
136                            self.stack.push(address.into());
137                            None
138                        }
139                    };
140                    if let Some(ops) = ops_to_execute {
141                        for op in ops {
142                            self.execute_instruction(op)?;
143                        }
144                    }
145                }
146            }
147        }
148        Ok(())
149    }
150}