rib/interpreter/
stack.rs

1// Copyright 2024-2025 Golem Cloud
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use crate::interpreter::interpreter_stack_value::RibInterpreterStackValue;
16use crate::{GetLiteralValue, LiteralValue};
17use golem_wasm_ast::analysis::analysed_type::{list, option, record, str, tuple, variant};
18use golem_wasm_ast::analysis::{
19    AnalysedType, NameOptionTypePair, NameTypePair, TypeEnum, TypeRecord, TypeResult,
20};
21use golem_wasm_rpc::{Value, ValueAndType};
22
23#[derive(Debug)]
24pub struct InterpreterStack {
25    pub stack: Vec<RibInterpreterStackValue>,
26}
27
28impl Default for InterpreterStack {
29    fn default() -> Self {
30        Self::new()
31    }
32}
33
34impl InterpreterStack {
35    pub fn new() -> Self {
36        InterpreterStack { stack: Vec::new() }
37    }
38
39    // Initialise a record in the stack
40    pub fn create_record(&mut self, fields: Vec<NameTypePair>) {
41        self.push_val(ValueAndType::new(
42            Value::Record(
43                vec![Value::Tuple(vec![]); fields.len()], // pre-initializing with () values, to be replaced later by UpdateRecord instructions
44            ),
45            record(fields),
46        ));
47    }
48
49    pub fn pop(&mut self) -> Option<RibInterpreterStackValue> {
50        self.stack.pop()
51    }
52
53    pub fn try_pop(&mut self) -> Result<RibInterpreterStackValue, String> {
54        self.pop()
55            .ok_or("internal error: failed to pop value from the interpreter stack".to_string())
56    }
57
58    pub fn pop_sink(&mut self) -> Option<(Vec<ValueAndType>, AnalysedType)> {
59        match self.pop() {
60            Some(RibInterpreterStackValue::Sink(vec, analysed_type)) => {
61                Some((vec.clone(), analysed_type))
62            }
63            _ => None,
64        }
65    }
66
67    pub fn pop_n(&mut self, n: usize) -> Option<Vec<RibInterpreterStackValue>> {
68        let mut results = Vec::new();
69        for _ in 0..n {
70            results.push(self.stack.pop()?);
71        }
72        Some(results)
73    }
74
75    pub fn try_pop_n(&mut self, n: usize) -> Result<Vec<RibInterpreterStackValue>, String> {
76        self.pop_n(n).ok_or(format!(
77            "internal error: failed to pop {} values from the interpreter stack",
78            n
79        ))
80    }
81
82    pub fn try_pop_n_val(&mut self, n: usize) -> Result<Vec<ValueAndType>, String> {
83        let stack_values = self.try_pop_n(n)?;
84
85        stack_values
86            .iter()
87            .map(|interpreter_result| {
88                interpreter_result.get_val().ok_or(format!(
89                    "internal error: failed to convert last {} in the stack to ValueAndType",
90                    n
91                ))
92            })
93            .collect::<Result<Vec<ValueAndType>, String>>()
94    }
95
96    pub fn try_pop_n_literals(&mut self, n: usize) -> Result<Vec<LiteralValue>, String> {
97        let values = self.try_pop_n_val(n)?;
98        values
99            .iter()
100            .map(|type_value| {
101                type_value.get_literal().ok_or(format!(
102                    "internal error: failed to convert last {} in the stack to literals {type_value:?}",
103                    n
104                ))
105            })
106            .collect::<Result<Vec<_>, String>>()
107    }
108
109    pub fn pop_str(&mut self) -> Option<String> {
110        self.pop_val().and_then(|v| match v {
111            ValueAndType {
112                value: Value::String(s),
113                ..
114            } => Some(s),
115            _ => None,
116        })
117    }
118
119    pub fn pop_val(&mut self) -> Option<ValueAndType> {
120        self.stack.pop().and_then(|v| v.get_val())
121    }
122
123    pub fn try_pop_val(&mut self) -> Result<ValueAndType, String> {
124        self.try_pop().and_then(|x| {
125            x.get_val().ok_or(
126                "internal error: failed to pop ValueAndType from the interpreter stack".to_string(),
127            )
128        })
129    }
130
131    pub fn try_pop_record(&mut self) -> Result<(Vec<Value>, TypeRecord), String> {
132        let value = self.try_pop_val()?;
133
134        match value {
135            ValueAndType {
136                value: Value::Record(field_values),
137                typ: AnalysedType::Record(typ),
138            } => Ok((field_values, typ)),
139            _ => Err("internal error: failed to pop a record from the interpreter".to_string()),
140        }
141    }
142
143    pub fn try_pop_bool(&mut self) -> Result<bool, String> {
144        self.try_pop_val().and_then(|val| {
145            val.get_literal().and_then(|x| x.get_bool()).ok_or(
146                "internal error: failed to pop boolean from the interpreter stack".to_string(),
147            )
148        })
149    }
150
151    pub fn push(&mut self, interpreter_result: RibInterpreterStackValue) {
152        self.stack.push(interpreter_result);
153    }
154
155    pub fn create_sink(&mut self, analysed_type: &AnalysedType) {
156        self.stack.push(RibInterpreterStackValue::Sink(
157            vec![],
158            analysed_type.clone(),
159        ))
160    }
161
162    pub fn push_val(&mut self, element: ValueAndType) {
163        self.stack.push(RibInterpreterStackValue::val(element));
164    }
165
166    pub fn push_to_sink(&mut self, value_and_type: ValueAndType) -> Result<(), String> {
167        let sink = self.pop();
168        // sink always followed by an iterator
169        let possible_iterator = self
170            .pop()
171            .ok_or("Failed to get the iterator before pushing to the sink")?;
172
173        if !possible_iterator.is_iterator() {
174            return Err("Expecting an the iterator before pushing to the sink".to_string());
175        }
176
177        match sink {
178            Some(RibInterpreterStackValue::Sink(mut list, analysed_type)) => {
179                list.push(value_and_type);
180                self.push(possible_iterator);
181                self.push(RibInterpreterStackValue::Sink(list, analysed_type));
182                Ok(())
183            }
184
185            a => Err(format!(
186                "internal error: failed to push values to sink {:?}",
187                a
188            )),
189        }
190    }
191
192    pub fn push_variant(
193        &mut self,
194        variant_name: String,
195        optional_variant_value: Option<Value>,
196        cases: Vec<NameOptionTypePair>,
197    ) -> Result<(), String> {
198        let case_idx = cases
199            .iter()
200            .position(|case| case.name == variant_name)
201            .ok_or(format!(
202                "internal Error: Failed to find the variant {} in the cases",
203                variant_name
204            ))? as u32;
205
206        let case_value = optional_variant_value.map(Box::new);
207        self.push_val(ValueAndType::new(
208            Value::Variant {
209                case_idx,
210                case_value,
211            },
212            variant(cases),
213        ));
214
215        Ok(())
216    }
217
218    pub fn push_enum(&mut self, enum_name: String, cases: Vec<String>) -> Result<(), String> {
219        let idx = cases.iter().position(|x| x == &enum_name).ok_or_else(|| {
220            format!(
221                "internal error: failed to find the enum {} in the cases",
222                enum_name
223            )
224        })? as u32;
225        self.push_val(ValueAndType::new(
226            Value::Enum(idx),
227            AnalysedType::Enum(TypeEnum {
228                cases: cases.into_iter().collect(),
229            }),
230        ));
231
232        Ok(())
233    }
234
235    pub fn push_some(&mut self, inner_element: Value, inner_type: &AnalysedType) {
236        self.push_val(ValueAndType {
237            value: Value::Option(Some(Box::new(inner_element))),
238            typ: option(inner_type.clone()),
239        });
240    }
241
242    // We allow untyped none to be in stack,
243    // Need to verify how strict we should be
244    // Example: ${match ok(1) { ok(value) => none }} should be allowed
245    pub fn push_none(&mut self, analysed_type: Option<AnalysedType>) {
246        self.push_val(ValueAndType {
247            value: Value::Option(None),
248            typ: option(analysed_type.unwrap_or(str())), // TODO: this used to be a "missing value in protobuf"
249        });
250    }
251
252    pub fn push_ok(
253        &mut self,
254        inner_element: Value,
255        ok_type: Option<&AnalysedType>,
256        err_type: Option<&AnalysedType>,
257    ) {
258        self.push_val(ValueAndType {
259            value: Value::Result(Ok(Some(Box::new(inner_element)))),
260            typ: AnalysedType::Result(TypeResult {
261                ok: ok_type.map(|x| Box::new(x.clone())),
262                err: err_type.map(|x| Box::new(x.clone())),
263            }),
264        });
265    }
266
267    pub fn push_err(
268        &mut self,
269        inner_element: Value,
270        ok_type: Option<&AnalysedType>,
271        err_type: Option<&AnalysedType>,
272    ) {
273        self.push_val(ValueAndType {
274            value: Value::Result(Err(Some(Box::new(inner_element)))),
275            typ: AnalysedType::Result(TypeResult {
276                ok: ok_type.map(|x| Box::new(x.clone())),
277                err: err_type.map(|x| Box::new(x.clone())),
278            }),
279        });
280    }
281
282    pub fn push_list(&mut self, values: Vec<Value>, list_elem_type: &AnalysedType) {
283        self.push_val(ValueAndType {
284            value: Value::List(values),
285            typ: list(list_elem_type.clone()),
286        });
287    }
288
289    pub fn push_tuple(&mut self, values: Vec<ValueAndType>) {
290        self.push_val(ValueAndType {
291            value: Value::Tuple(values.iter().map(|x| x.value.clone()).collect()),
292            typ: tuple(values.into_iter().map(|x| x.typ).collect()),
293        });
294    }
295}