rib/interpreter/
env.rs

1// Copyright 2024-2025 Golem Cloud
2//
3// Licensed under the Golem Source License v1.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://license.golem.cloud/LICENSE
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::{
17    ComponentDependencyKey, EvaluatedFnArgs, EvaluatedFqFn, EvaluatedWorkerName, InstructionId,
18    RibComponentFunctionInvoke, RibInput, VariableId,
19};
20use golem_wasm_ast::analysis::AnalysedType;
21use golem_wasm_rpc::ValueAndType;
22use std::collections::HashMap;
23use std::fmt::Debug;
24use std::sync::Arc;
25
26pub struct InterpreterEnv {
27    pub env: HashMap<EnvironmentKey, RibInterpreterStackValue>,
28    pub call_worker_function_async: Arc<dyn RibComponentFunctionInvoke + Sync + Send>,
29}
30
31impl Debug for InterpreterEnv {
32    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33        f.debug_struct("InterpreterEnv")
34            .field("env", &self.env.iter())
35            .finish()
36    }
37}
38
39impl Default for InterpreterEnv {
40    fn default() -> Self {
41        InterpreterEnv {
42            env: HashMap::new(),
43            call_worker_function_async: Arc::new(internal::NoopRibFunctionInvoke),
44        }
45    }
46}
47
48impl InterpreterEnv {
49    pub async fn invoke_worker_function_async(
50        &self,
51        component_dependency_key: ComponentDependencyKey,
52        instruction_id: &InstructionId,
53        worker_name: String,
54        function_name: String,
55        args: Vec<ValueAndType>,
56        return_type: Option<AnalysedType>,
57    ) -> Result<Option<ValueAndType>, Box<dyn std::error::Error + Send + Sync>> {
58        self.call_worker_function_async
59            .invoke(
60                component_dependency_key,
61                instruction_id,
62                EvaluatedWorkerName(worker_name),
63                EvaluatedFqFn(function_name),
64                EvaluatedFnArgs(args),
65                return_type,
66            )
67            .await
68    }
69
70    pub fn from_input(env: &RibInput) -> Self {
71        let env = env
72            .input
73            .clone()
74            .into_iter()
75            .map(|(k, v)| {
76                (
77                    EnvironmentKey::from_global(k),
78                    RibInterpreterStackValue::Val(v),
79                )
80            })
81            .collect();
82
83        InterpreterEnv {
84            env,
85            call_worker_function_async: Arc::new(internal::NoopRibFunctionInvoke),
86        }
87    }
88
89    pub fn from(
90        input: &RibInput,
91        call_worker_function_async: &Arc<dyn RibComponentFunctionInvoke + Sync + Send>,
92    ) -> Self {
93        let mut env = Self::from_input(input);
94        env.call_worker_function_async = call_worker_function_async.clone();
95        env
96    }
97
98    pub fn insert(&mut self, key: EnvironmentKey, value: RibInterpreterStackValue) {
99        self.env.insert(key, value);
100    }
101
102    pub fn lookup(&self, key: &EnvironmentKey) -> Option<&RibInterpreterStackValue> {
103        self.env.get(key)
104    }
105}
106
107#[derive(Debug, Hash, Eq, PartialEq, Clone)]
108pub struct EnvironmentKey {
109    pub variable_id: VariableId,
110}
111
112impl EnvironmentKey {
113    pub fn from(variable_id: VariableId) -> Self {
114        EnvironmentKey { variable_id }
115    }
116
117    pub fn from_global(key: String) -> Self {
118        EnvironmentKey {
119            variable_id: VariableId::global(key),
120        }
121    }
122}
123
124mod internal {
125    use crate::interpreter::env::RibComponentFunctionInvoke;
126    use crate::{
127        ComponentDependencyKey, EvaluatedFnArgs, EvaluatedFqFn, EvaluatedWorkerName, InstructionId,
128        RibFunctionInvokeResult,
129    };
130    use async_trait::async_trait;
131    use golem_wasm_ast::analysis::AnalysedType;
132
133    pub(crate) struct NoopRibFunctionInvoke;
134
135    #[async_trait]
136    impl RibComponentFunctionInvoke for NoopRibFunctionInvoke {
137        async fn invoke(
138            &self,
139            _component_info: ComponentDependencyKey,
140            _instruction_id: &InstructionId,
141            _worker_name: EvaluatedWorkerName,
142            _function_name: EvaluatedFqFn,
143            _args: EvaluatedFnArgs,
144            _return_type: Option<AnalysedType>,
145        ) -> RibFunctionInvokeResult {
146            Ok(None)
147        }
148    }
149}