Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow configuring compiler with the types for certain global variables #1295

Merged
merged 9 commits into from
Feb 8, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 15 additions & 15 deletions golem-rib/src/compiler/byte_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ mod compiler_tests {
fn test_instructions_for_literal() {
let literal = Expr::Literal("hello".to_string(), InferredType::Str);
let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&literal, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&literal, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand All @@ -725,7 +725,7 @@ mod compiler_tests {
let variable_id = VariableId::local("request", 0);
let empty_registry = FunctionTypeRegistry::empty();
let expr = Expr::Identifier(variable_id.clone(), inferred_input_type);
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand All @@ -752,7 +752,7 @@ mod compiler_tests {
);

let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand Down Expand Up @@ -787,7 +787,7 @@ mod compiler_tests {

let expr = Expr::equal_to(number_f32, number_u32);
let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand Down Expand Up @@ -826,7 +826,7 @@ mod compiler_tests {

let expr = Expr::greater_than(number_f32, number_u32);
let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand Down Expand Up @@ -865,7 +865,7 @@ mod compiler_tests {

let expr = Expr::less_than(number_f32, number_u32);
let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand Down Expand Up @@ -904,7 +904,7 @@ mod compiler_tests {

let expr = Expr::greater_than_or_equal_to(number_f32, number_u32);
let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand Down Expand Up @@ -943,7 +943,7 @@ mod compiler_tests {

let expr = Expr::less_than_or_equal_to(number_f32, number_u32);
let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand Down Expand Up @@ -983,7 +983,7 @@ mod compiler_tests {
);

let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand Down Expand Up @@ -1027,7 +1027,7 @@ mod compiler_tests {
);

let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand Down Expand Up @@ -1057,7 +1057,7 @@ mod compiler_tests {
);

let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand Down Expand Up @@ -1097,7 +1097,7 @@ mod compiler_tests {
);

let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand Down Expand Up @@ -1147,7 +1147,7 @@ mod compiler_tests {
let expr = Expr::SelectField(Box::new(record), "bar_key".to_string(), InferredType::Str);

let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand Down Expand Up @@ -1194,7 +1194,7 @@ mod compiler_tests {
let expr = Expr::SelectIndex(Box::new(sequence), 1, InferredType::Str);

let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand Down Expand Up @@ -1243,7 +1243,7 @@ mod compiler_tests {
);

let empty_registry = FunctionTypeRegistry::empty();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry).unwrap();
let inferred_expr = InferredExpr::from_expr(&expr, &empty_registry, &vec![]).unwrap();

let instructions = RibByteCode::from_expr(&inferred_expr).unwrap();

Expand Down
2 changes: 1 addition & 1 deletion golem-rib/src/compiler/desugar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -574,7 +574,7 @@ mod desugar_tests {
let function_type_registry = get_function_type_registry();

let mut expr = Expr::from_text(rib_expr).unwrap();
expr.infer_types(&function_type_registry).unwrap();
expr.infer_types(&function_type_registry, &vec![]).unwrap();

let desugared_expr = match internal::last_expr(&expr) {
Expr::PatternMatch(predicate, match_arms, _) => {
Expand Down
21 changes: 17 additions & 4 deletions golem-rib/src/compiler/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub use type_with_unit::*;
pub use worker_functions_in_rib::*;

use crate::type_registry::FunctionTypeRegistry;
use crate::{Expr, InferredExpr, RibInputTypeInfo, RibOutputTypeInfo};
use crate::{Expr, GlobalVariableTypeSpec, InferredExpr, RibInputTypeInfo, RibOutputTypeInfo};

mod byte_code;
mod compiler_output;
Expand All @@ -33,19 +33,32 @@ pub fn compile(
expr: &Expr,
export_metadata: &Vec<AnalysedExport>,
) -> Result<CompilerOutput, String> {
compile_with_limited_globals(expr, export_metadata, None)
compile_with_restricted_global_variables(expr, export_metadata, None, &vec![])
}

// Rib allows global input variables, however, we can choose to fail compilation
// if they don't fall under a pre-defined set of global variables.
// There is no restriction imposed to the type of this variable.
pub fn compile_with_limited_globals(
// Also we can specify types for certain global variables and if needed be specific
// on the path. Example: All variables under the variable `path` which is under the global variable `request` can be `Str`
// Not all global variable require a type specification, and you can leave it to the compiler.
pub fn compile_with_restricted_global_variables(
expr: &Expr,
export_metadata: &Vec<AnalysedExport>,
allowed_global_variables: Option<Vec<String>>,
global_variable_type_spec: &Vec<GlobalVariableTypeSpec>,
) -> Result<CompilerOutput, String> {
for info in global_variable_type_spec {
if !info.variable_id.is_global() {
return Err(format!(
"Only global variables can have default types, but found {}",
info.variable_id
));
}
}

let type_registry = FunctionTypeRegistry::from_export_metadata(export_metadata);
let inferred_expr = InferredExpr::from_expr(expr, &type_registry)?;
let inferred_expr = InferredExpr::from_expr(expr, &type_registry, global_variable_type_spec)?;
let function_calls_identified =
WorkerFunctionsInRib::from_inferred_expr(&inferred_expr, &type_registry)?;

Expand Down
20 changes: 16 additions & 4 deletions golem-rib/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use crate::parser::block::block;
use crate::parser::type_name::TypeName;
use crate::type_registry::FunctionTypeRegistry;
use crate::{
from_string, text, type_checker, type_inference, DynamicParsedFunctionName, InferredType,
ParsedFunctionName, VariableId,
from_string, text, type_checker, type_inference, DynamicParsedFunctionName,
GlobalVariableTypeSpec, InferredType, ParsedFunctionName, VariableId,
};
use bigdecimal::{BigDecimal, FromPrimitive, ToPrimitive};
use combine::parser::char::spaces;
Expand Down Expand Up @@ -392,6 +392,14 @@ impl Expr {
)
}

pub fn bind_global_variables_type(
&self,
type_spec: &Vec<GlobalVariableTypeSpec>,
) -> Result<Self, String> {
let result_expr = type_inference::bind_global_variables_type(self, type_spec)?;
Ok(result_expr)
}

pub fn literal(value: impl AsRef<str>) -> Self {
Expr::Literal(value.as_ref().to_string(), InferredType::Str)
}
Expand Down Expand Up @@ -541,13 +549,13 @@ impl Expr {
pub fn infer_types(
&mut self,
function_type_registry: &FunctionTypeRegistry,
type_spec: &Vec<GlobalVariableTypeSpec>,
) -> Result<(), Vec<String>> {
self.infer_types_initial_phase(function_type_registry)?;
self.infer_types_initial_phase(function_type_registry, type_spec)?;
self.infer_call_arguments_type(function_type_registry)
.map_err(|x| vec![x])?;
type_inference::type_inference_fix_point(Self::inference_scan, self)
.map_err(|x| vec![x])?;

self.check_types(function_type_registry)
.map_err(|x| vec![x])?;
self.unify_types()?;
Expand All @@ -557,7 +565,11 @@ impl Expr {
pub fn infer_types_initial_phase(
&mut self,
function_type_registry: &FunctionTypeRegistry,
type_spec: &Vec<GlobalVariableTypeSpec>,
) -> Result<(), Vec<String>> {
*self = self
.bind_global_variables_type(type_spec)
.map_err(|x| vec![x])?;
self.bind_types();
self.bind_variables_of_list_comprehension();
self.bind_variables_of_list_reduce();
Expand Down
10 changes: 2 additions & 8 deletions golem-rib/src/inferred_type/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,17 +13,11 @@
// limitations under the License.

pub(crate) use flatten::*;
pub(crate) use unification_result::*;
pub(crate) use validation::*;
mod flatten;
mod unification;
mod unification_result;
mod validation;

use std::collections::HashSet;

use bincode::{Decode, Encode};
use golem_wasm_ast::analysis::*;
use std::collections::HashSet;

#[derive(Debug, Hash, Clone, Eq, PartialEq, PartialOrd, Ord, Encode, Decode)]
pub enum InferredType {
Expand Down Expand Up @@ -176,7 +170,7 @@ impl InferredType {
}

pub fn unify(&self) -> Result<InferredType, String> {
unification::unify(self)
unification::unify(self).map(|unified| unified.inferred_type())
}

pub fn unify_all_alternative_types(types: &Vec<InferredType>) -> InferredType {
Expand Down
Loading
Loading