1pub use byte_code::*;
16pub use compiler_output::*;
17use golem_wasm_ast::analysis::AnalysedExport;
18pub use ir::*;
19use std::fmt::Display;
20pub use type_with_unit::*;
21pub use worker_functions_in_rib::*;
22
23use crate::rib_compilation_error::RibCompilationError;
24use crate::type_registry::FunctionTypeRegistry;
25use crate::{Expr, GlobalVariableTypeSpec, InferredExpr, RibInputTypeInfo, RibOutputTypeInfo};
26
27mod byte_code;
28mod compiler_output;
29mod desugar;
30mod ir;
31mod type_with_unit;
32mod worker_functions_in_rib;
33
34pub fn compile(
35 expr: Expr,
36 export_metadata: &Vec<AnalysedExport>,
37) -> Result<CompilerOutput, RibError> {
38 compile_with_restricted_global_variables(expr, export_metadata, None, &vec![])
39}
40
41pub fn compile_with_restricted_global_variables(
49 expr: Expr,
50 export_metadata: &Vec<AnalysedExport>,
51 allowed_global_variables: Option<Vec<String>>,
52 global_variable_type_spec: &Vec<GlobalVariableTypeSpec>,
53) -> Result<CompilerOutput, RibError> {
54 for info in global_variable_type_spec {
55 if !info.variable_id.is_global() {
56 return Err(RibError::InternalError(format!(
57 "variable {} in the type spec is not a global variable",
58 info.variable_id
59 )));
60 }
61 }
62
63 let type_registry = FunctionTypeRegistry::from_export_metadata(export_metadata);
64 let inferred_expr = InferredExpr::from_expr(expr, &type_registry, global_variable_type_spec)?;
65
66 let function_calls_identified =
67 WorkerFunctionsInRib::from_inferred_expr(&inferred_expr, &type_registry)?;
68
69 let global_input_type_info = RibInputTypeInfo::from_expr(&inferred_expr)?;
70
71 let output_type_info = RibOutputTypeInfo::from_expr(&inferred_expr)?;
72
73 if let Some(allowed_global_variables) = &allowed_global_variables {
74 let mut un_allowed_variables = vec![];
75
76 for (name, _) in global_input_type_info.types.iter() {
77 if !allowed_global_variables.contains(name) {
78 un_allowed_variables.push(name.clone());
79 }
80 }
81
82 if !un_allowed_variables.is_empty() {
83 return Err(RibError::InvalidRibScript(format!(
84 "unexpected global variables: {}. make sure only these variables are used as global input: {}",
85 un_allowed_variables.join(", "),
86 allowed_global_variables.join(", ")
87 )));
88 }
89 }
90
91 let byte_code = RibByteCode::from_expr(&inferred_expr).map_err(|e| {
92 RibError::InternalError(format!(
93 "failed to convert inferred expression to byte code: {}",
94 e
95 ))
96 })?;
97
98 Ok(CompilerOutput {
99 worker_invoke_calls: function_calls_identified,
100 byte_code,
101 rib_input_type_info: global_input_type_info,
102 rib_output_type_info: Some(output_type_info),
103 })
104}
105
106#[derive(Debug, Clone)]
107pub enum RibError {
108 InternalError(String),
109 RibCompilationError(RibCompilationError),
110 InvalidRibScript(String),
111}
112
113impl From<RibCompilationError> for RibError {
114 fn from(err: RibCompilationError) -> Self {
115 RibError::RibCompilationError(err)
116 }
117}
118
119impl Display for RibError {
120 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
121 match self {
122 RibError::InternalError(msg) => write!(f, "rib internal error: {}", msg),
123 RibError::RibCompilationError(err) => write!(f, "{}", err),
124 RibError::InvalidRibScript(msg) => write!(f, "invalid rib script: {}", msg),
125 }
126 }
127}