Skip to main content

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::wit_type::WitType;
16use crate::ValueAndType;
17use crate::{ComponentDependencyKey, ParsedFunctionSite, VariableId, WitTypeWithUnit};
18use serde::{Deserialize, Serialize};
19
20// To create any type, example, CreateOption, you have to feed a fully formed WitType
21#[derive(Debug, Clone, PartialEq)]
22pub enum RibIR {
23    PushLit(ValueAndType),
24    AssignVar(VariableId),
25    LoadVar(VariableId),
26    CreateAndPushRecord(WitType),
27    UpdateRecord(String),
28    PushList(WitType, usize),
29    PushTuple(WitType, usize),
30    PushSome(WitType),
31    PushNone(Option<WitType>), // In certain cases, we don't need the type info
32    PushOkResult(WitType),
33    PushErrResult(WitType),
34    PushFlag(ValueAndType), // More or less like a literal, compiler can form the value directly
35    SelectField(String),
36    SelectIndex(usize), // Kept for backward compatibility. Cannot read old SelectIndex(usize) as a SelectIndexV1
37    SelectIndexV1,
38    EqualTo,
39    GreaterThan,
40    And,
41    Or,
42    LessThan,
43    GreaterThanOrEqualTo,
44    LessThanOrEqualTo,
45    IsEmpty,
46    JumpIfFalse(InstructionId),
47    Jump(InstructionId),
48    Label(InstructionId),
49    Deconstruct,
50    CreateFunctionName(ParsedFunctionSite, FunctionReferenceType),
51    InvokeFunction(
52        ComponentDependencyKey,
53        InstanceVariable,
54        usize,
55        WitTypeWithUnit,
56    ),
57    PushVariant(String, WitType), // There is no arg size since the type of each variant case is only 1 from beginning
58    PushEnum(String, WitType),
59    Throw(String),
60    GetTag,
61    Concat(usize),
62    Plus(WitType),
63    Minus(WitType),
64    Divide(WitType),
65    Multiply(WitType),
66    Negate,
67    ToIterator,
68    CreateSink(WitType),
69    AdvanceIterator,
70    PushToSink,
71    SinkToList,
72    Length,
73    GenerateWorkerName(Option<VariableId>),
74}
75
76#[derive(Debug, Clone, PartialEq)]
77pub enum InstanceVariable {
78    WitResource(VariableId),
79    WitWorker(VariableId),
80}
81
82impl RibIR {
83    pub fn get_instruction_id(&self) -> Option<InstructionId> {
84        match self {
85            RibIR::Label(id) => Some(id.clone()),
86            _ => None,
87        }
88    }
89}
90
91#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
92pub enum FunctionReferenceType {
93    Function { function: String },
94    RawResourceConstructor { resource: String },
95    RawResourceDrop { resource: String },
96    RawResourceMethod { resource: String, method: String },
97    RawResourceStaticMethod { resource: String, method: String },
98}
99
100// Every instruction can have a unique ID, and the compiler
101// can assign this and label the start and end of byte code blocks.
102// This is more efficient than assigning index to every instruction and incrementing it
103// as we care about it only if we need to jump through instructions.
104// Jumping to an ID is simply draining the stack until we find a Label instruction with the same ID.
105#[derive(Debug, Clone, PartialEq, Hash, Eq, Serialize, Deserialize)]
106pub struct InstructionId {
107    pub index: usize,
108}
109
110impl InstructionId {
111    pub fn new(index: usize) -> Self {
112        InstructionId { index }
113    }
114
115    pub fn init() -> Self {
116        InstructionId { index: 0 }
117    }
118
119    pub fn increment(&self) -> InstructionId {
120        InstructionId {
121            index: self.index + 1,
122        }
123    }
124
125    pub fn increment_mut(&mut self) -> InstructionId {
126        self.index += 1;
127        self.clone()
128    }
129}