rib/compiler/
ir.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::{AnalysedTypeWithUnit, ComponentDependencyKey, ParsedFunctionSite, VariableId};
16use bincode::{Decode, Encode};
17use golem_wasm_ast::analysis::AnalysedType;
18use golem_wasm_rpc::ValueAndType;
19use serde::{Deserialize, Serialize};
20
21// To create any type, example, CreateOption, you have to feed a fully formed AnalysedType
22#[derive(Debug, Clone, PartialEq, Encode, Decode)]
23pub enum RibIR {
24    PushLit(ValueAndType),
25    AssignVar(VariableId),
26    LoadVar(VariableId),
27    CreateAndPushRecord(AnalysedType),
28    UpdateRecord(String),
29    PushList(AnalysedType, usize),
30    PushTuple(AnalysedType, usize),
31    PushSome(AnalysedType),
32    PushNone(Option<AnalysedType>), // In certain cases, we don't need the type info
33    PushOkResult(AnalysedType),
34    PushErrResult(AnalysedType),
35    PushFlag(ValueAndType), // More or less like a literal, compiler can form the value directly
36    SelectField(String),
37    SelectIndex(usize), // Kept for backward compatibility. Cannot read old SelectIndex(usize) as a SelectIndexV1
38    SelectIndexV1,
39    EqualTo,
40    GreaterThan,
41    And,
42    Or,
43    LessThan,
44    GreaterThanOrEqualTo,
45    LessThanOrEqualTo,
46    IsEmpty,
47    JumpIfFalse(InstructionId),
48    Jump(InstructionId),
49    Label(InstructionId),
50    Deconstruct,
51    CreateFunctionName(ParsedFunctionSite, FunctionReferenceType),
52    InvokeFunction(
53        ComponentDependencyKey,
54        InstanceVariable,
55        usize,
56        AnalysedTypeWithUnit,
57    ),
58    PushVariant(String, AnalysedType), // There is no arg size since the type of each variant case is only 1 from beginning
59    PushEnum(String, AnalysedType),
60    Throw(String),
61    GetTag,
62    Concat(usize),
63    Plus(AnalysedType),
64    Minus(AnalysedType),
65    Divide(AnalysedType),
66    Multiply(AnalysedType),
67    Negate,
68    ToIterator,
69    CreateSink(AnalysedType),
70    AdvanceIterator,
71    PushToSink,
72    SinkToList,
73    Length,
74    GenerateWorkerName(Option<VariableId>),
75}
76
77#[derive(Debug, Clone, PartialEq, Encode, Decode)]
78pub enum InstanceVariable {
79    WitResource(VariableId),
80    WitWorker(VariableId),
81}
82
83impl RibIR {
84    pub fn get_instruction_id(&self) -> Option<InstructionId> {
85        match self {
86            RibIR::Label(id) => Some(id.clone()),
87            _ => None,
88        }
89    }
90}
91
92#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode)]
93pub enum FunctionReferenceType {
94    Function {
95        function: String,
96    },
97    RawResourceConstructor {
98        resource: String,
99    },
100    RawResourceDrop {
101        resource: String,
102    },
103    RawResourceMethod {
104        resource: String,
105        method: String,
106    },
107    RawResourceStaticMethod {
108        resource: String,
109        method: String,
110    },
111    IndexedResourceConstructor {
112        resource: String,
113        arg_size: usize,
114    },
115    IndexedResourceMethod {
116        resource: String,
117        arg_size: usize,
118        method: String,
119    },
120    IndexedResourceStaticMethod {
121        resource: String,
122        arg_size: usize,
123        method: String,
124    },
125    IndexedResourceDrop {
126        resource: String,
127        arg_size: usize,
128    },
129}
130
131// Every instruction can have a unique ID, and the compiler
132// can assign this and label the start and end of byte code blocks.
133// This is more efficient than assigning index to every instruction and incrementing it
134// as we care about it only if we need to jump through instructions.
135// Jumping to an ID is simply draining the stack until we find a Label instruction with the same ID.
136#[derive(Debug, Clone, PartialEq, Hash, Eq, Serialize, Deserialize, Encode, Decode)]
137pub struct InstructionId {
138    pub index: usize,
139}
140
141impl InstructionId {
142    pub fn new(index: usize) -> Self {
143        InstructionId { index }
144    }
145
146    pub fn init() -> Self {
147        InstructionId { index: 0 }
148    }
149
150    pub fn increment(&self) -> InstructionId {
151        InstructionId {
152            index: self.index + 1,
153        }
154    }
155
156    pub fn increment_mut(&mut self) -> InstructionId {
157        self.index += 1;
158        self.clone()
159    }
160}
161
162#[cfg(feature = "protobuf")]
163mod protobuf {
164    use crate::{
165        AnalysedTypeWithUnit, ComponentDependencyKey, FunctionReferenceType, InstanceVariable,
166        InstructionId, ParsedFunctionSite, RibIR, VariableId,
167    };
168    use golem_api_grpc::proto::golem::rib::rib_ir::Instruction;
169    use golem_api_grpc::proto::golem::rib::{
170        And, ConcatInstruction, CreateFunctionNameInstruction, EqualTo, GetTag, GreaterThan,
171        GreaterThanOrEqualTo, InvokeFunctionInstruction, IsEmpty, JumpInstruction, LessThan,
172        LessThanOrEqualTo, Negate, Or, PushListInstruction, PushNoneInstruction,
173        PushTupleInstruction, RibIr as ProtoRibIR, WitResource,
174    };
175    use golem_wasm_ast::analysis::{AnalysedType, TypeStr};
176
177    impl TryFrom<golem_api_grpc::proto::golem::rib::FunctionReferenceType> for FunctionReferenceType {
178        type Error = String;
179        fn try_from(
180            value: golem_api_grpc::proto::golem::rib::FunctionReferenceType,
181        ) -> Result<Self, Self::Error> {
182            let value = value.r#type.ok_or("Missing type".to_string())?;
183            let function_reference_type = match value {
184                golem_api_grpc::proto::golem::rib::function_reference_type::Type::Function(name) => FunctionReferenceType::Function {
185                    function: name.name
186                },
187                golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceConstructor(name) =>
188                    FunctionReferenceType::RawResourceConstructor {
189                        resource: name.resource_name
190                    },
191                golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceDrop(name) => FunctionReferenceType::RawResourceDrop {
192                    resource: name.resource_name
193                },
194                golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceMethod(raw_resource_method) => {
195                    let resource = raw_resource_method.resource_name;
196                    let method = raw_resource_method.method_name;
197                    FunctionReferenceType::RawResourceMethod { resource, method }
198                }
199                golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceStaticMethod(raw_resource_static_method) => {
200                    let resource = raw_resource_static_method.resource_name;
201                    let method = raw_resource_static_method.method_name;
202                    FunctionReferenceType::RawResourceStaticMethod { resource, method }
203                }
204                golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceConstructor(indexed_resource_constructor) => {
205                    let resource = indexed_resource_constructor.resource_name;
206                    let arg_size = indexed_resource_constructor.arg_size;
207                    FunctionReferenceType::IndexedResourceConstructor { resource, arg_size: arg_size as usize }
208                }
209                golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceMethod(indexed_resource_method) => {
210                    let resource = indexed_resource_method.resource_name;
211                    let arg_size = indexed_resource_method.arg_size;
212                    let method = indexed_resource_method.method_name;
213                    FunctionReferenceType::IndexedResourceMethod { resource, arg_size: arg_size as usize, method }
214                }
215                golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceStaticMethod(indexed_resource_static_method) => {
216                    let resource = indexed_resource_static_method.resource_name;
217                    let arg_size = indexed_resource_static_method.arg_size;
218                    let method = indexed_resource_static_method.method_name;
219                    FunctionReferenceType::IndexedResourceStaticMethod { resource, arg_size: arg_size as usize, method }
220                }
221                golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceDrop(indexed_resource_drop) => {
222                    let resource = indexed_resource_drop.resource_name;
223                    let arg_size = indexed_resource_drop.arg_size;
224                    FunctionReferenceType::IndexedResourceDrop { resource, arg_size: arg_size as usize }
225                }
226            };
227            Ok(function_reference_type)
228        }
229    }
230
231    impl From<FunctionReferenceType> for golem_api_grpc::proto::golem::rib::FunctionReferenceType {
232        fn from(value: FunctionReferenceType) -> Self {
233            match value {
234                FunctionReferenceType::Function { function } => golem_api_grpc::proto::golem::rib::FunctionReferenceType {
235                    r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::Function(golem_api_grpc::proto::golem::rib::Function {
236                        name: function
237                    }))
238                },
239                FunctionReferenceType::RawResourceConstructor { resource } => golem_api_grpc::proto::golem::rib::FunctionReferenceType {
240                    r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceConstructor(golem_api_grpc::proto::golem::rib::RawResourceConstructor {
241                        resource_name: resource
242                    }))
243                },
244                FunctionReferenceType::RawResourceDrop { resource } => golem_api_grpc::proto::golem::rib::FunctionReferenceType {
245                    r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceDrop(golem_api_grpc::proto::golem::rib::RawResourceDrop {
246                        resource_name: resource
247                    }))
248                },
249                FunctionReferenceType::RawResourceMethod { resource, method } => golem_api_grpc::proto::golem::rib::FunctionReferenceType {
250                    r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceMethod(golem_api_grpc::proto::golem::rib::RawResourceMethod {
251                        resource_name: resource,
252                        method_name: method,
253                    }))
254                },
255                FunctionReferenceType::RawResourceStaticMethod { resource, method } => golem_api_grpc::proto::golem::rib::FunctionReferenceType {
256                    r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceStaticMethod(golem_api_grpc::proto::golem::rib::RawResourceStaticMethod {
257                        resource_name: resource,
258                        method_name: method,
259                    }))
260                },
261                FunctionReferenceType::IndexedResourceConstructor { resource, arg_size } => golem_api_grpc::proto::golem::rib::FunctionReferenceType {
262                    r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceConstructor(golem_api_grpc::proto::golem::rib::IndexedResourceConstructor {
263                        resource_name: resource,
264                        arg_size: arg_size as u32,
265                    }))
266                },
267                FunctionReferenceType::IndexedResourceMethod { resource, arg_size, method } => golem_api_grpc::proto::golem::rib::FunctionReferenceType {
268                    r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceMethod(golem_api_grpc::proto::golem::rib::IndexedResourceMethod {
269                        resource_name: resource,
270                        arg_size: arg_size as u32,
271                        method_name: method,
272                    }))
273                },
274                FunctionReferenceType::IndexedResourceStaticMethod { resource, arg_size, method } => golem_api_grpc::proto::golem::rib::FunctionReferenceType {
275                    r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceStaticMethod(golem_api_grpc::proto::golem::rib::IndexedResourceStaticMethod {
276                        resource_name: resource,
277                        arg_size: arg_size as u32,
278                        method_name: method,
279                    }))
280                },
281                FunctionReferenceType::IndexedResourceDrop { resource, arg_size } => golem_api_grpc::proto::golem::rib::FunctionReferenceType {
282                    r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceDrop(golem_api_grpc::proto::golem::rib::IndexedResourceDrop {
283                        resource_name: resource,
284                        arg_size: arg_size as u32,
285                    }))
286                }
287            }
288        }
289    }
290
291    impl TryFrom<ProtoRibIR> for RibIR {
292        type Error = String;
293
294        fn try_from(value: ProtoRibIR) -> Result<Self, Self::Error> {
295            let instruction = value
296                .instruction
297                .ok_or_else(|| "Missing instruction".to_string())?;
298
299            match instruction {
300                Instruction::GenerateWorkerName(generate_worker_name) => {
301                    let variable_id = generate_worker_name
302                        .variable_id
303                        .map(VariableId::try_from)
304                        .transpose()?;
305
306                    Ok(RibIR::GenerateWorkerName(variable_id))
307                }
308                Instruction::PushLit(value) => Ok(RibIR::PushLit(
309                    value
310                        .try_into()
311                        .map_err(|_| "Failed to convert PushLit".to_string())?,
312                )),
313                Instruction::AssignVar(value) => Ok(RibIR::AssignVar(
314                    value
315                        .try_into()
316                        .map_err(|_| "Failed to convert AssignVar".to_string())?,
317                )),
318                Instruction::LoadVar(value) => Ok(RibIR::LoadVar(
319                    value
320                        .try_into()
321                        .map_err(|_| "Failed to convert LoadVar".to_string())?,
322                )),
323                Instruction::CreateAndPushRecord(value) => {
324                    Ok(RibIR::CreateAndPushRecord((&value).try_into().map_err(
325                        |_| "Failed to convert CreateAndPushRecord".to_string(),
326                    )?))
327                }
328                Instruction::Plus(value) => {
329                    Ok(RibIR::Plus((&value).try_into().map_err(|_| {
330                        "Failed to convert CreateAndPushRecord".to_string()
331                    })?))
332                }
333                Instruction::Multiply(value) => {
334                    Ok(RibIR::Multiply((&value).try_into().map_err(|_| {
335                        "Failed to convert CreateAndPushRecord".to_string()
336                    })?))
337                }
338                Instruction::Minus(value) => {
339                    Ok(RibIR::Minus((&value).try_into().map_err(|_| {
340                        "Failed to convert CreateAndPushRecord".to_string()
341                    })?))
342                }
343                Instruction::Divide(value) => {
344                    Ok(RibIR::Divide((&value).try_into().map_err(|_| {
345                        "Failed to convert CreateAndPushRecord".to_string()
346                    })?))
347                }
348
349                Instruction::UpdateRecord(value) => Ok(RibIR::UpdateRecord(value)),
350                Instruction::PushList(value) => Ok(RibIR::PushList(
351                    value
352                        .list_type
353                        .ok_or("List type not present".to_string())
354                        .and_then(|t| {
355                            (&t).try_into()
356                                .map_err(|_| "Failed to convert AnalysedType".to_string())
357                        })?,
358                    value.list_size as usize,
359                )),
360                Instruction::CreateSome(value) => Ok(RibIR::PushSome(
361                    (&value)
362                        .try_into()
363                        .map_err(|_| "Failed to convert CreateSome".to_string())?,
364                )),
365                Instruction::CreateNone(value) => match value.none_type {
366                    Some(v) => {
367                        let optional_type = (&v)
368                            .try_into()
369                            .map_err(|_| "Failed to convert AnalysedType".to_string());
370                        Ok(RibIR::PushNone(Some(optional_type?)))
371                    }
372                    None => Ok(RibIR::PushNone(None)),
373                },
374                Instruction::CreateOkResult(value) => {
375                    Ok(RibIR::PushOkResult((&value).try_into().map_err(|_| {
376                        "Failed to convert CreateOkResult".to_string()
377                    })?))
378                }
379                Instruction::CreateErrResult(value) => {
380                    Ok(RibIR::PushErrResult((&value).try_into().map_err(|_| {
381                        "Failed to convert CreateErrResult".to_string()
382                    })?))
383                }
384                Instruction::Length(_) => Ok(RibIR::Length),
385                Instruction::SelectField(value) => Ok(RibIR::SelectField(value)),
386                Instruction::SelectIndex(value) => Ok(RibIR::SelectIndex(value as usize)),
387                Instruction::SelectIndexV1(_) => Ok(RibIR::SelectIndexV1),
388                Instruction::EqualTo(_) => Ok(RibIR::EqualTo),
389                Instruction::GreaterThan(_) => Ok(RibIR::GreaterThan),
390                Instruction::LessThan(_) => Ok(RibIR::LessThan),
391                Instruction::GreaterThanOrEqualTo(_) => Ok(RibIR::GreaterThanOrEqualTo),
392                Instruction::LessThanOrEqualTo(_) => Ok(RibIR::LessThanOrEqualTo),
393                Instruction::And(_) => Ok(RibIR::And),
394                Instruction::IsEmpty(_) => Ok(RibIR::IsEmpty),
395                Instruction::Or(_) => Ok(RibIR::Or),
396                Instruction::JumpIfFalse(value) => Ok(RibIR::JumpIfFalse(InstructionId::new(
397                    value.instruction_id as usize,
398                ))),
399                Instruction::Jump(value) => Ok(RibIR::Jump(InstructionId::new(
400                    value.instruction_id as usize,
401                ))),
402                Instruction::Label(value) => Ok(RibIR::Label(InstructionId::new(
403                    value.instruction_id as usize,
404                ))),
405                Instruction::Deconstruct(_) => Ok(RibIR::Deconstruct),
406                Instruction::InvokeFunction(invoke_function_instruction) => {
407                    let return_type = match invoke_function_instruction.return_type {
408                        Some(return_type) => {
409                            let analysed_type = (&return_type)
410                                .try_into()
411                                .map_err(|_| "Failed to convert AnalysedType".to_string())?;
412
413                            AnalysedTypeWithUnit::Type(analysed_type)
414                        }
415                        None => AnalysedTypeWithUnit::Unit,
416                    };
417
418                    let instance_variable: InstanceVariable = invoke_function_instruction
419                        .instance_variable
420                        .ok_or("Missing instance_variable".to_string())
421                        .and_then(|iv| {
422                            match iv.kind.ok_or("Missing instance_variable kind".to_string())? {
423                                golem_api_grpc::proto::golem::rib::instance_variable::Kind::Resource(wit_resource) => {
424                                    let variable_id = wit_resource.variable_id.ok_or(
425                                        "Missing variable_id in WitResource".to_string(),
426                                    )?.try_into()
427                                        .map_err(|_| "Failed to convert VariableId".to_string())?;
428                                    Ok(InstanceVariable::WitResource(variable_id))
429                                }
430                                golem_api_grpc::proto::golem::rib::instance_variable::Kind::Worker(wit_worker) => {
431                                    let variable_id = wit_worker.variable_id.ok_or(
432                                        "Missing variable_id in WitWorker".to_string(),
433                                    )?.try_into()
434                                        .map_err(|_| "Failed to convert VariableId".to_string())?;
435
436                                    Ok(InstanceVariable::WitWorker(variable_id))
437                                }
438                            }
439                        })?;
440
441                    let component_dependency_key_proto = invoke_function_instruction
442                        .component
443                        .ok_or("Missing component_dependency_key".to_string())?;
444
445                    let component_dependency_key =
446                        ComponentDependencyKey::try_from(component_dependency_key_proto)
447                            .map_err(|_| "Failed to convert ComponentDependencyKey".to_string())?;
448
449                    Ok(RibIR::InvokeFunction(
450                        component_dependency_key,
451                        instance_variable,
452                        invoke_function_instruction.argument_count as usize,
453                        return_type,
454                    ))
455                }
456                Instruction::VariantConstruction(variant_construction) => {
457                    let variant_type = variant_construction
458                        .return_type
459                        .ok_or("Missing return_type for variant construction".to_string())?;
460
461                    let analysed_variant_type = (&variant_type)
462                        .try_into()
463                        .map_err(|_| "Failed to convert AnalysedType".to_string())?;
464
465                    Ok(RibIR::PushVariant(
466                        variant_construction.variant_name,
467                        analysed_variant_type,
468                    ))
469                }
470                Instruction::EnumConstruction(enum_construction) => {
471                    let enum_type = enum_construction
472                        .return_type
473                        .ok_or("Missing return_type for enum construction".to_string())?;
474
475                    let analysed_enum_type = (&enum_type)
476                        .try_into()
477                        .map_err(|_| "Failed to convert AnalysedType".to_string())?;
478
479                    Ok(RibIR::PushEnum(
480                        enum_construction.enum_name,
481                        analysed_enum_type,
482                    ))
483                }
484                Instruction::Throw(value) => Ok(RibIR::Throw(value)),
485                Instruction::PushFlag(flag) => Ok(RibIR::PushFlag(
486                    flag.try_into()
487                        .map_err(|_| "Failed to convert PushFlag".to_string())?,
488                )),
489                Instruction::GetTag(_) => Ok(RibIR::GetTag),
490                Instruction::PushTuple(tuple_instruction) => {
491                    let tuple_type = tuple_instruction
492                        .tuple_type
493                        .ok_or("Missing tuple_type".to_string())
494                        .and_then(|t| {
495                            (&t).try_into()
496                                .map_err(|_| "Failed to convert AnalysedType".to_string())
497                        })?;
498
499                    Ok(RibIR::PushTuple(
500                        tuple_type,
501                        tuple_instruction.tuple_size as usize,
502                    ))
503                }
504                Instruction::Negate(_) => Ok(RibIR::Negate),
505                Instruction::Concat(concat_instruction) => {
506                    Ok(RibIR::Concat(concat_instruction.arg_size as usize))
507                }
508                Instruction::CreateFunctionName(instruction) => {
509                    let parsed_site = instruction.site.ok_or("Missing site".to_string())?;
510                    let parsed_function_site = ParsedFunctionSite::try_from(parsed_site)?;
511
512                    let reference_type = instruction
513                        .function_reference_details
514                        .ok_or("Missing reference_type".to_string())?;
515                    let function_reference_type = reference_type.try_into()?;
516
517                    Ok(RibIR::CreateFunctionName(
518                        parsed_function_site,
519                        function_reference_type,
520                    ))
521                }
522                Instruction::ListToIterator(_) => Ok(RibIR::ToIterator),
523                Instruction::CreateSink(create_sink) => {
524                    let result = create_sink
525                        .list_type
526                        .ok_or("Sink list type not present".to_string())
527                        .and_then(|t| {
528                            (&t).try_into()
529                                .map_err(|_| "Failed to convert AnalysedType".to_string())
530                        })?;
531
532                    Ok(RibIR::CreateSink(result))
533                }
534                Instruction::AdvanceIterator(_) => Ok(RibIR::AdvanceIterator),
535                Instruction::SinkToList(_) => Ok(RibIR::SinkToList),
536                Instruction::PushToSink(_) => Ok(RibIR::PushToSink),
537            }
538        }
539    }
540
541    impl TryFrom<RibIR> for ProtoRibIR {
542        type Error = String;
543
544        fn try_from(value: RibIR) -> Result<Self, Self::Error> {
545            let instruction = match value {
546                RibIR::GenerateWorkerName(variable_id) => {
547                    let variable_id_proto = variable_id.map(|v| v.into());
548
549                    Instruction::GenerateWorkerName(
550                        golem_api_grpc::proto::golem::rib::GenerateWorkerName {
551                            variable_id: variable_id_proto,
552                        },
553                    )
554                }
555                RibIR::PushLit(value) => Instruction::PushLit(value.into()),
556                RibIR::And => Instruction::And(And {}),
557                RibIR::IsEmpty => Instruction::IsEmpty(IsEmpty {}),
558                RibIR::Or => Instruction::Or(Or {}),
559                RibIR::AssignVar(value) => Instruction::AssignVar(value.into()),
560                RibIR::LoadVar(value) => Instruction::LoadVar(value.into()),
561                RibIR::CreateAndPushRecord(value) => {
562                    Instruction::CreateAndPushRecord((&value).into())
563                }
564                RibIR::Plus(value) => Instruction::Plus((&value).into()),
565                RibIR::Minus(value) => Instruction::Minus((&value).into()),
566                RibIR::Multiply(value) => Instruction::Multiply((&value).into()),
567                RibIR::Divide(value) => Instruction::Divide((&value).into()),
568                RibIR::UpdateRecord(value) => Instruction::UpdateRecord(value),
569                RibIR::PushList(value, arg_size) => Instruction::PushList(PushListInstruction {
570                    list_type: Some((&value).into()),
571                    list_size: arg_size as u64,
572                }),
573                RibIR::PushSome(value) => Instruction::CreateSome((&value).into()),
574                RibIR::PushNone(value) => {
575                    let push_none_instruction = PushNoneInstruction {
576                        none_type: value.map(|t| (&t).into()),
577                    };
578                    Instruction::CreateNone(push_none_instruction)
579                }
580                RibIR::PushOkResult(value) => Instruction::CreateOkResult((&value).into()),
581                RibIR::PushErrResult(value) => Instruction::CreateErrResult((&value).into()),
582                RibIR::SelectField(value) => Instruction::SelectField(value),
583                RibIR::SelectIndex(value) => Instruction::SelectIndex(value as u64),
584                RibIR::EqualTo => Instruction::EqualTo(EqualTo {}),
585                RibIR::GreaterThan => Instruction::GreaterThan(GreaterThan {}),
586                RibIR::LessThan => Instruction::LessThan(LessThan {}),
587                RibIR::Length => Instruction::Length(golem_api_grpc::proto::golem::rib::Length {}),
588                RibIR::SelectIndexV1 => {
589                    Instruction::SelectIndexV1(golem_api_grpc::proto::golem::rib::SelectIndexV1 {})
590                }
591                RibIR::GreaterThanOrEqualTo => {
592                    Instruction::GreaterThanOrEqualTo(GreaterThanOrEqualTo {})
593                }
594                RibIR::LessThanOrEqualTo => Instruction::LessThanOrEqualTo(LessThanOrEqualTo {}),
595                RibIR::JumpIfFalse(value) => Instruction::JumpIfFalse(JumpInstruction {
596                    instruction_id: value.index as u64,
597                }),
598                RibIR::Jump(value) => Instruction::Jump(JumpInstruction {
599                    instruction_id: value.index as u64,
600                }),
601                RibIR::Label(value) => Instruction::Label(JumpInstruction {
602                    instruction_id: value.index as u64,
603                }),
604                RibIR::Deconstruct => {
605                    Instruction::Deconstruct((&AnalysedType::Str(TypeStr)).into())
606                } //TODO; remove type in deconstruct from protobuf
607                RibIR::InvokeFunction(
608                    component_dependency_key,
609                    worker_name_presence,
610                    arg_count,
611                    return_type,
612                ) => {
613                    let typ = match return_type {
614                        AnalysedTypeWithUnit::Unit => None,
615                        AnalysedTypeWithUnit::Type(analysed_type) => {
616                            let typ =
617                                golem_wasm_ast::analysis::protobuf::Type::from(&analysed_type);
618                            Some(typ)
619                        }
620                    };
621
622                    let instance_variable = match worker_name_presence {
623                        InstanceVariable::WitResource(variable_id) => {
624                            golem_api_grpc::proto::golem::rib::InstanceVariable {
625                                kind: Some(
626                                    golem_api_grpc::proto::golem::rib::instance_variable::Kind::Resource(
627                                        WitResource {
628                                            variable_id: Some(variable_id.into()),
629                                        },
630                                    ),
631                                ),
632                            }
633                        }
634                        InstanceVariable::WitWorker(variable_id) => {
635                            golem_api_grpc::proto::golem::rib::InstanceVariable {
636                                kind: Some(
637                                    golem_api_grpc::proto::golem::rib::instance_variable::Kind::Worker(
638                                        golem_api_grpc::proto::golem::rib::WitWorker {
639                                            variable_id: Some(variable_id.into()),
640                                        },
641                                    ),
642                                ),
643                            }
644                        }
645                    };
646
647                    let component_dependency_key =
648                        golem_api_grpc::proto::golem::rib::ComponentDependencyKey::from(
649                            component_dependency_key,
650                        );
651
652                    Instruction::InvokeFunction(InvokeFunctionInstruction {
653                        component: Some(component_dependency_key),
654                        argument_count: arg_count as u64,
655                        return_type: typ,
656                        instance_variable: Some(instance_variable),
657                    })
658                }
659                RibIR::PushVariant(name, return_type) => {
660                    let typ = golem_wasm_ast::analysis::protobuf::Type::from(&return_type);
661
662                    Instruction::VariantConstruction(
663                        golem_api_grpc::proto::golem::rib::VariantConstructionInstruction {
664                            variant_name: name,
665                            return_type: Some(typ),
666                        },
667                    )
668                }
669                RibIR::PushEnum(name, return_type) => {
670                    let typ = golem_wasm_ast::analysis::protobuf::Type::from(&return_type);
671
672                    Instruction::EnumConstruction(
673                        golem_api_grpc::proto::golem::rib::EnumConstructionInstruction {
674                            enum_name: name,
675                            return_type: Some(typ),
676                        },
677                    )
678                }
679                RibIR::Throw(msg) => Instruction::Throw(msg),
680                RibIR::PushFlag(flag) => Instruction::PushFlag(flag.into()),
681                RibIR::GetTag => Instruction::GetTag(GetTag {}),
682                RibIR::PushTuple(analysed_type, size) => {
683                    let typ = golem_wasm_ast::analysis::protobuf::Type::from(&analysed_type);
684
685                    Instruction::PushTuple(PushTupleInstruction {
686                        tuple_type: Some(typ),
687                        tuple_size: size as u64,
688                    })
689                }
690                RibIR::Concat(concat) => Instruction::Concat(ConcatInstruction {
691                    arg_size: concat as u64,
692                }),
693                RibIR::Negate => Instruction::Negate(Negate {}),
694                RibIR::CreateFunctionName(site, reference_type) => {
695                    Instruction::CreateFunctionName(CreateFunctionNameInstruction {
696                        site: Some(site.into()),
697                        function_reference_details: Some(reference_type.into()),
698                    })
699                }
700
701                RibIR::ToIterator => Instruction::ListToIterator(
702                    golem_api_grpc::proto::golem::rib::ListToIterator {},
703                ),
704                RibIR::CreateSink(analysed_type) => {
705                    Instruction::CreateSink(golem_api_grpc::proto::golem::rib::CreateSink {
706                        list_type: Some((&analysed_type).into()),
707                    })
708                }
709                RibIR::AdvanceIterator => Instruction::AdvanceIterator(
710                    golem_api_grpc::proto::golem::rib::AdvanceIterator {},
711                ),
712                RibIR::PushToSink => {
713                    Instruction::PushToSink(golem_api_grpc::proto::golem::rib::PushToSink {})
714                }
715                RibIR::SinkToList => {
716                    Instruction::SinkToList(golem_api_grpc::proto::golem::rib::SinkToList {})
717                }
718            };
719
720            Ok(ProtoRibIR {
721                instruction: Some(instruction),
722            })
723        }
724    }
725}