From 68e651db9e030494a058fe441b6cc2c2f6c85a7e Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Fri, 20 Sep 2024 20:07:43 +1000 Subject: [PATCH 01/27] Support dynamic resource parameters in Rib --- golem-rib/src/call_type.rs | 4 +- golem-rib/src/compiler/byte_code.rs | 173 +++++++++--- golem-rib/src/compiler/ir.rs | 18 +- golem-rib/src/expr.rs | 14 +- golem-rib/src/function_name.rs | 166 +++++++++++- golem-rib/src/interpreter/env.rs | 4 +- golem-rib/src/interpreter/rib_interpreter.rs | 215 ++++++++++++++- golem-rib/src/interpreter/stack.rs | 7 + golem-rib/src/parser/call.rs | 254 ++++++++++-------- golem-rib/src/text/mod.rs | 8 + golem-rib/src/text/writer.rs | 9 + .../src/worker_bridge_execution/mod.rs | 2 +- .../src/worker_bridge_request_executor.rs | 2 +- 13 files changed, 714 insertions(+), 162 deletions(-) diff --git a/golem-rib/src/call_type.rs b/golem-rib/src/call_type.rs index f0ef76e7d..7bae88a88 100644 --- a/golem-rib/src/call_type.rs +++ b/golem-rib/src/call_type.rs @@ -12,14 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::ParsedFunctionName; +use crate::{DynamicParsedFunctionName, ParsedFunctionName}; use bincode::{Decode, Encode}; use std::convert::TryFrom; use std::fmt::Display; #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] pub enum CallType { - Function(ParsedFunctionName), + Function(DynamicParsedFunctionName), VariantConstructor(String), EnumConstructor(String), } diff --git a/golem-rib/src/compiler/byte_code.rs b/golem-rib/src/compiler/byte_code.rs index 8b970b987..7e7112dac 100644 --- a/golem-rib/src/compiler/byte_code.rs +++ b/golem-rib/src/compiler/byte_code.rs @@ -84,7 +84,10 @@ impl From for ProtoRibByteCode { mod internal { use crate::compiler::desugar::desugar_pattern_match; - use crate::{AnalysedTypeWithUnit, Expr, InferredType, InstructionId, RibIR}; + use crate::{ + AnalysedTypeWithUnit, DynamicParsedFunctionReference, Expr, FunctionReferenceType, + InferredType, InstructionId, ParsedFunctionName, ParsedFunctionReference, RibIR, + }; use golem_wasm_ast::analysis::AnalysedType; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; @@ -235,43 +238,144 @@ mod internal { )?)); } - Expr::Call(invocation_name, arguments, inferred_type) => { - for expr in arguments.iter().rev() { - stack.push(ExprState::from_expr(expr)); - } - - match invocation_name { - CallType::Function(parsed_function_name) => { - let function_result_type = if inferred_type.is_unit() { - AnalysedTypeWithUnit::Unit - } else { - AnalysedTypeWithUnit::Type(convert_to_analysed_type_for( - expr, - inferred_type, - )?) - }; - - instructions.push(RibIR::InvokeFunction( - parsed_function_name.clone(), - arguments.len(), - function_result_type, - )); + Expr::Call(invocation_name, arguments, inferred_type) => match invocation_name { + CallType::Function(parsed_function_name) => { + let function_result_type = if inferred_type.is_unit() { + AnalysedTypeWithUnit::Unit + } else { + AnalysedTypeWithUnit::Type(convert_to_analysed_type_for( + expr, + inferred_type, + )?) + }; + + let site = parsed_function_name.site.clone(); + + match &parsed_function_name.function { + DynamicParsedFunctionReference::Function { function } => { + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::Function(function.clone()), + )) + } + + DynamicParsedFunctionReference::RawResourceConstructor { resource } => { + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::RawResourceConstructor(resource.clone()), + )) + } + DynamicParsedFunctionReference::RawResourceDrop { resource } => { + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::RawResourceDrop(resource.clone()), + )) + } + DynamicParsedFunctionReference::RawResourceMethod { resource, method } => { + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::RawResourceMethod( + resource.clone(), + method.clone(), + ), + )) + } + DynamicParsedFunctionReference::RawResourceStaticMethod { + resource, + method, + } => instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::RawResourceStaticMethod( + resource.clone(), + method.clone(), + ), + )), + DynamicParsedFunctionReference::IndexedResourceConstructor { + resource, + resource_params, + } => { + for param in resource_params { + stack.push(ExprState::from_expr(¶m.0)); + } + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::IndexedResourceConstructor( + resource.clone(), + resource_params.len(), + ), + )) + } + DynamicParsedFunctionReference::IndexedResourceMethod { + resource, + resource_params, + method, + } => { + for param in resource_params { + stack.push(ExprState::from_expr(¶m.0)); + } + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::IndexedResourceMethod( + resource.clone(), + resource_params.len(), + method.clone(), + ), + )) + } + DynamicParsedFunctionReference::IndexedResourceStaticMethod { + resource, + resource_params, + method, + } => { + for param in resource_params { + stack.push(ExprState::from_expr(¶m.0)); + } + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::IndexedResourceStaticMethod( + resource.clone(), + resource_params.len(), + method.clone(), + ), + )) + } + DynamicParsedFunctionReference::IndexedResourceDrop { + resource, + resource_params, + } => { + for param in resource_params { + stack.push(ExprState::from_expr(¶m.0)); + } + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::IndexedResourceDrop( + resource.clone(), + resource_params.len(), + ), + )) + } } - CallType::VariantConstructor(variant_name) => { - instructions.push(RibIR::PushVariant( - variant_name.clone(), - convert_to_analysed_type_for(expr, inferred_type)?, - )); - } - CallType::EnumConstructor(enmum_name) => { - instructions.push(RibIR::PushEnum( - enmum_name.clone(), - convert_to_analysed_type_for(expr, inferred_type)?, - )); + for expr in arguments.iter().rev() { + stack.push(ExprState::from_expr(expr)); } + + instructions.push(RibIR::InvokeFunction(arguments.len(), function_result_type)); } - } + + CallType::VariantConstructor(variant_name) => { + instructions.push(RibIR::PushVariant( + variant_name.clone(), + convert_to_analysed_type_for(expr, inferred_type)?, + )); + } + CallType::EnumConstructor(enmum_name) => { + instructions.push(RibIR::PushEnum( + enmum_name.clone(), + convert_to_analysed_type_for(expr, inferred_type)?, + )); + } + }, Expr::Flags(flag_values, inferred_type) => match inferred_type { InferredType::Flags(all_flags) => { @@ -380,6 +484,7 @@ mod internal { stack.push(ExprState::from_ir(RibIR::Label(else_ending_id.clone()))); } } + #[cfg(test)] mod compiler_tests { use super::*; diff --git a/golem-rib/src/compiler/ir.rs b/golem-rib/src/compiler/ir.rs index efb7c0d5c..5c4d73f82 100644 --- a/golem-rib/src/compiler/ir.rs +++ b/golem-rib/src/compiler/ir.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{AnalysedTypeWithUnit, ParsedFunctionName, VariableId}; +use crate::{AnalysedTypeWithUnit, ParsedFunctionName, ParsedFunctionSite, VariableId}; use bincode::{Decode, Encode}; use golem_api_grpc::proto::golem::rib::rib_ir::Instruction; use golem_api_grpc::proto::golem::rib::{ @@ -51,7 +51,8 @@ pub enum RibIR { Jump(InstructionId), Label(InstructionId), Deconstruct, - InvokeFunction(ParsedFunctionName, usize, AnalysedTypeWithUnit), + CreateFunctionName(ParsedFunctionSite, FunctionReferenceType), + InvokeFunction(usize, AnalysedTypeWithUnit), PushVariant(String, AnalysedType), // There is no arg size since the type of each variant case is only 1 from beginning PushEnum(String, AnalysedType), Throw(String), @@ -60,6 +61,19 @@ pub enum RibIR { Negate, } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode)] +pub enum FunctionReferenceType { + Function(String), + RawResourceConstructor(String), + RawResourceDrop(String), + RawResourceMethod(String, String), + RawResourceStaticMethod(String, String), + IndexedResourceConstructor(String, usize), + IndexedResourceMethod(String, usize, String), + IndexedResourceStaticMethod(String, usize, String), + IndexedResourceDrop(String, usize), +} + // Every instruction can have a unique ID, and the compiler // can assign this and label the start and end of byte code blocks. // This is more efficient than assigning index to every instruction and incrementing it diff --git a/golem-rib/src/expr.rs b/golem-rib/src/expr.rs index 3b7d6cf08..b65d5b9c7 100644 --- a/golem-rib/src/expr.rs +++ b/golem-rib/src/expr.rs @@ -17,7 +17,7 @@ use crate::function_name::ParsedFunctionName; use crate::parser::rib_expr::rib_program; use crate::parser::type_name::TypeName; use crate::type_registry::FunctionTypeRegistry; -use crate::{text, type_inference, InferredType, VariableId}; +use crate::{text, type_inference, DynamicParsedFunctionName, InferredType, VariableId}; use bincode::{Decode, Encode}; use combine::stream::position; use combine::EasyParser; @@ -30,7 +30,7 @@ use std::fmt::Display; use std::ops::Deref; use std::str::FromStr; -#[derive(Debug, Clone, PartialEq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] pub enum Expr { Let(VariableId, Option, Box, InferredType), SelectField(Box, String, InferredType), @@ -256,9 +256,9 @@ impl Expr { cond } - pub fn call(parsed_fn_name: ParsedFunctionName, args: Vec) -> Self { + pub fn call(dynamic_parsed_fn_name: DynamicParsedFunctionName, args: Vec) -> Self { Expr::Call( - CallType::Function(parsed_fn_name), + CallType::Function(dynamic_parsed_fn_name), args, InferredType::Unknown, ) @@ -692,7 +692,7 @@ impl Expr { } } -#[derive(Debug, Clone, PartialEq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] pub struct Number { pub value: f64, // Change to bigdecimal } @@ -721,7 +721,7 @@ impl Display for Number { } } -#[derive(Debug, Clone, PartialEq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] pub struct MatchArm { pub arm_pattern: ArmPattern, pub arm_resolution_expr: Box, @@ -735,7 +735,7 @@ impl MatchArm { } } } -#[derive(Debug, Clone, PartialEq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] pub enum ArmPattern { WildCard, As(String, Box), diff --git a/golem-rib/src/function_name.rs b/golem-rib/src/function_name.rs index 0b3f8af3d..95ee0dd83 100644 --- a/golem-rib/src/function_name.rs +++ b/golem-rib/src/function_name.rs @@ -12,13 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. +use crate::{text, CompilerOutput, Expr, Interpreter, RibInterpreterResult}; use bincode::{BorrowDecode, Decode, Encode}; use combine::stream::easy; use combine::EasyParser; use golem_wasm_ast::analysis::AnalysedType; +use golem_wasm_rpc::json::TypeAnnotatedValueJsonExtensions; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use golem_wasm_rpc::type_annotated_value_from_str; use golem_wasm_rpc::Value; +use poem_openapi::types::ToJSON; use semver::{BuildMetadata, Prerelease}; use serde::{Deserialize, Serialize}; use std::borrow::Cow; @@ -266,6 +269,122 @@ pub enum ParsedFunctionReference { }, } +#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] +pub(crate) enum DynamicParsedFunctionReference { + Function { + function: String, + }, + RawResourceConstructor { + resource: String, + }, + RawResourceDrop { + resource: String, + }, + RawResourceMethod { + resource: String, + method: String, + }, + RawResourceStaticMethod { + resource: String, + method: String, + }, + IndexedResourceConstructor { + resource: String, + resource_params: Vec, + }, + IndexedResourceMethod { + resource: String, + resource_params: Vec, + method: String, + }, + IndexedResourceStaticMethod { + resource: String, + resource_params: Vec, + method: String, + }, + IndexedResourceDrop { + resource: String, + resource_params: Vec, + }, +} + +impl DynamicParsedFunctionReference { + fn to_static(&self) -> ParsedFunctionReference { + match self { + Self::Function { function } => ParsedFunctionReference::Function { + function: function.clone(), + }, + Self::RawResourceConstructor { resource } => { + ParsedFunctionReference::RawResourceConstructor { + resource: resource.clone(), + } + } + Self::RawResourceDrop { resource } => ParsedFunctionReference::RawResourceDrop { + resource: resource.clone(), + }, + Self::RawResourceMethod { resource, method } => { + ParsedFunctionReference::RawResourceMethod { + resource: resource.clone(), + method: method.clone(), + } + } + Self::RawResourceStaticMethod { resource, method } => { + ParsedFunctionReference::RawResourceStaticMethod { + resource: resource.clone(), + method: method.clone(), + } + } + Self::IndexedResourceConstructor { + resource, + resource_params, + } => ParsedFunctionReference::IndexedResourceConstructor { + resource: resource.clone(), + resource_params: resource_params + .iter() + .map(|param| text::to_raw_string(¶m.0)) + .collect(), + }, + Self::IndexedResourceMethod { + resource, + resource_params, + method, + } => ParsedFunctionReference::IndexedResourceMethod { + resource: resource.clone(), + resource_params: resource_params + .iter() + .map(|param| text::to_raw_string(¶m.0)) + .collect(), + method: method.clone(), + }, + Self::IndexedResourceStaticMethod { + resource, + resource_params, + method, + } => ParsedFunctionReference::IndexedResourceStaticMethod { + resource: resource.clone(), + resource_params: resource_params + .iter() + .map(|param| text::to_raw_string(¶m.0)) + .collect(), + method: method.clone(), + }, + Self::IndexedResourceDrop { + resource, + resource_params, + } => ParsedFunctionReference::IndexedResourceDrop { + resource: resource.clone(), + resource_params: resource_params + .iter() + .map(|param| text::to_raw_string(¶m.0)) + .collect(), + }, + } + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] +pub struct ResourceParam(pub Expr); + impl Display for ParsedFunctionReference { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let function_name = match self { @@ -598,6 +717,51 @@ pub struct ParsedFunctionName { pub function: ParsedFunctionReference, } +#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] +pub(crate) struct DynamicParsedFunctionName { + pub site: ParsedFunctionSite, + pub function: DynamicParsedFunctionReference, +} + +impl TryFrom for ParsedFunctionName { + type Error = String; + + fn try_from(value: DynamicParsedFunctionName) -> Result { + Ok(ParsedFunctionName { + site: value.site, + function: value.function.try_into()?, + }) + } +} + +impl DynamicParsedFunctionName { + pub fn parse(name: impl AsRef) -> Result { + let name = name.as_ref(); + + let mut parser = crate::parser::call::function_name(); + + let result: Result<(DynamicParsedFunctionName, &str), easy::ParseError<&str>> = + parser.easy_parse(name); + + match result { + Ok((parsed, _)) => Ok(parsed), + Err(error) => { + let error_message = error + .map_position(|p| p.translate_position(name)) + .to_string(); + Err(error_message) + } + } + } + + fn to_static(&self) -> ParsedFunctionName { + ParsedFunctionName { + site: self.site.clone(), + function: self.function.to_static(), + } + } +} + impl Serialize for ParsedFunctionName { fn serialize(&self, serializer: S) -> Result { let function_name = self.to_string(); @@ -651,7 +815,7 @@ impl ParsedFunctionName { let mut parser = crate::parser::call::function_name(); - let result: Result<(ParsedFunctionName, &str), easy::ParseError<&str>> = + let result: Result<(DynamicParsedFunctionName, &str), easy::ParseError<&str>> = parser.easy_parse(name); match result { diff --git a/golem-rib/src/interpreter/env.rs b/golem-rib/src/interpreter/env.rs index 6a33817bf..3afe7ece6 100644 --- a/golem-rib/src/interpreter/env.rs +++ b/golem-rib/src/interpreter/env.rs @@ -27,7 +27,7 @@ pub struct InterpreterEnv { pub type RibFunctionInvoke = Arc< dyn Fn( - ParsedFunctionName, + String, Vec, ) -> Pin> + Send>> + Send @@ -56,7 +56,7 @@ impl InterpreterEnv { pub fn invoke_worker_function_async( &self, - function_name: ParsedFunctionName, + function_name: String, args: Vec, ) -> Pin> + Send>> { (self.call_worker_function_async)(function_name, args) diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index 90c38928c..2d1c185b1 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -135,8 +135,12 @@ impl Interpreter { internal::run_select_index_instruction(&mut self.stack, index)?; } - RibIR::InvokeFunction(parsed_function_name, arity, _) => { - internal::run_call_instruction(parsed_function_name, arity, self).await?; + RibIR::CreateFunctionName(site, function_type) => { + internal::run_create_function_name_instruction(site, function_type, self)?; + } + + RibIR::InvokeFunction(arity, _) => { + internal::run_call_instruction(arity, self).await?; } RibIR::PushVariant(variant_name, analysed_type) => { @@ -210,13 +214,16 @@ mod internal { use crate::interpreter::result::RibInterpreterResult; use crate::interpreter::stack::InterpreterStack; use crate::{ - GetLiteralValue, InstructionId, Interpreter, ParsedFunctionName, RibIR, VariableId, + FunctionReferenceType, GetLiteralValue, InstructionId, Interpreter, ParsedFunctionName, + ParsedFunctionReference, ParsedFunctionSite, RibIR, VariableId, }; use golem_wasm_ast::analysis::AnalysedType; use golem_wasm_ast::analysis::TypeResult; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use golem_wasm_rpc::protobuf::typed_result::ResultValue; use golem_wasm_rpc::protobuf::{NameValuePair, TypedRecord, TypedTuple}; + use golem_wasm_rpc::type_annotated_value_to_string; + use poem_openapi::types::ToJSON; use std::collections::VecDeque; use std::ops::Deref; @@ -559,9 +566,202 @@ mod internal { } } + pub(crate) fn run_create_function_name_instruction( + site: ParsedFunctionSite, + function_type: FunctionReferenceType, + interpreter: &mut Interpreter, + ) -> Result<(), String> { + match function_type { + FunctionReferenceType::Function(parsed_fn_name) => { + let parsed_function_name = ParsedFunctionName { + site, + function: ParsedFunctionReference::Function { + function: parsed_fn_name, + }, + }; + + interpreter + .stack + .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); + } + + FunctionReferenceType::RawResourceConstructor(resource) => { + let parsed_function_name = ParsedFunctionName { + site, + function: ParsedFunctionReference::RawResourceConstructor { resource }, + }; + + interpreter + .stack + .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); + } + FunctionReferenceType::RawResourceDrop(resource) => { + let parsed_function_name = ParsedFunctionName { + site, + function: ParsedFunctionReference::RawResourceDrop { resource }, + }; + + interpreter + .stack + .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); + } + FunctionReferenceType::RawResourceMethod(resource, meethod) => { + let parsed_function_name = ParsedFunctionName { + site, + function: ParsedFunctionReference::RawResourceMethod { resource, method }, + }; + + interpreter + .stack + .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); + } + FunctionReferenceType::RawResourceStaticMethod(resource, method) => { + let parsed_function_name = ParsedFunctionName { + site, + function: ParsedFunctionReference::RawResourceStaticMethod { resource, method }, + }; + + interpreter + .stack + .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); + } + FunctionReferenceType::IndexedResourceConstructor(resource, resource_params_size) => { + let last_n_elements = interpreter + .stack + .pop_n(resource_params_size) + .ok_or("Failed to get values from the stack".to_string())?; + + let type_anntoated_values = last_n_elements + .iter() + .map(|interpreter_result| { + interpreter_result + .get_val() + .ok_or("Failed to get value from the stack".to_string()) + }) + .collect::, String>>()?; + + let parsed_function_name = ParsedFunctionName { + site, + function: ParsedFunctionReference::IndexedResourceConstructor { + resource, + resource_params: type_anntoated_values + .iter() + .map(type_annotated_value_to_string) + .collect()?, + }, + }; + + interpreter + .stack + .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); + } + FunctionReferenceType::IndexedResourceMethod( + resource, + resource_params_size, + method, + ) => { + let last_n_elements = interpreter + .stack + .pop_n(resource_params_size) + .ok_or("Failed to get values from the stack".to_string())?; + + let type_anntoated_values = last_n_elements + .iter() + .map(|interpreter_result| { + interpreter_result + .get_val() + .ok_or("Failed to get value from the stack".to_string()) + }) + .collect::, String>>()?; + + let parsed_function_name = ParsedFunctionName { + site, + function: ParsedFunctionReference::IndexedResourceMethod { + resource, + resource_params: type_anntoated_values + .iter() + .map(type_annotated_value_to_string) + .collect()?, + method, + }, + }; + + interpreter + .stack + .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); + } + FunctionReferenceType::IndexedResourceStaticMethod( + resource, + resource_params_size, + method, + ) => { + let last_n_elements = interpreter + .stack + .pop_n(resource_params_size) + .ok_or("Failed to get values from the stack".to_string())?; + + let type_anntoated_values = last_n_elements + .iter() + .map(|interpreter_result| { + interpreter_result + .get_val() + .ok_or("Failed to get value from the stack".to_string()) + }) + .collect::, String>>()?; + + let parsed_function_name = ParsedFunctionName { + site, + function: ParsedFunctionReference::IndexedResourceStaticMethod { + resource, + resource_params: type_anntoated_values + .iter() + .map(type_annotated_value_to_string) + .collect()?, + method, + }, + }; + + interpreter + .stack + .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); + } + FunctionReferenceType::IndexedResourceDrop(resource, resource_params) => { + let last_n_elements = interpreter + .stack + .pop_n(resource_params) + .ok_or("Failed to get values from the stack".to_string())?; + + let type_anntoated_values = last_n_elements + .iter() + .map(|interpreter_result| { + interpreter_result + .get_val() + .ok_or("Failed to get value from the stack".to_string()) + }) + .collect::, String>>()?; + + let parsed_function_name = ParsedFunctionName { + site, + function: ParsedFunctionReference::IndexedResourceDrop { + resource, + resource_params: type_anntoated_values + .iter() + .map(type_annotated_value_to_string) + .collect()?, + }, + }; + + interpreter + .stack + .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); + } + } + + Ok(()) + } + // Separate variant pub(crate) async fn run_call_instruction( - parsed_function_name: ParsedFunctionName, argument_size: usize, interpreter: &mut Interpreter, ) -> Result<(), String> { @@ -579,9 +779,14 @@ mod internal { }) .collect::, String>>()?; + let function_name = interpreter + .stack + .pop_str() + .ok_or("Failed to get a function name from the stack".to_string())?; + let result = interpreter .env - .invoke_worker_function_async(parsed_function_name, type_anntoated_values) + .invoke_worker_function_async(function_name, type_anntoated_values) .await?; let interpreter_result = match result { diff --git a/golem-rib/src/interpreter/stack.rs b/golem-rib/src/interpreter/stack.rs index eda6ef4de..b42a5f59c 100644 --- a/golem-rib/src/interpreter/stack.rs +++ b/golem-rib/src/interpreter/stack.rs @@ -63,6 +63,13 @@ impl InterpreterStack { Some(results) } + pub fn pop_str(&mut self) -> Option { + self.pop_val().and_then(|v| match v { + TypeAnnotatedValue::Str(s) => Some(s), + _ => None, + }) + } + pub fn pop_val(&mut self) -> Option { self.stack.pop().and_then(|v| v.get_val()) } diff --git a/golem-rib/src/parser/call.rs b/golem-rib/src/parser/call.rs index d07c6e18b..2e2800d5d 100644 --- a/golem-rib/src/parser/call.rs +++ b/golem-rib/src/parser/call.rs @@ -12,12 +12,14 @@ // See the License for the specific language governing permissions and // limitations under the License. +use crate::{DynamicParsedFunctionName, DynamicParsedFunctionReference, ResourceParam}; use combine::error::Commit; use combine::parser::char::{alpha_num, string}; use combine::parser::char::{char, spaces}; use combine::parser::repeat::take_until; -use combine::sep_by; +use combine::stream::position; use combine::{any, attempt, between, choice, many1, optional, parser, token, ParseError, Parser}; +use combine::{sep_by, EasyParser}; use crate::expr::Expr; use crate::function_name::{ @@ -46,11 +48,7 @@ where .message("Invalid function call") } -// TODO; Reusing function_name between Rib and internals of GOLEM may be a surface level requirement -// as users can form function name in various other ways. -// Example: Arguments to a resource can be partial because they may come from request parameters -// and these are not represented using the current structure of ParsedFunctionName -pub fn function_name() -> impl Parser +pub fn function_name() -> impl Parser where Input: combine::Stream, RibParseError: Into< @@ -81,7 +79,11 @@ where nesting += 1; current_param.push(next_char); } else if next_char == ',' && nesting == 1 { - result.push(current_param.trim().to_string()); + let (expr, _) = rib_expr() + .easy_parse(position::Stream::new(current_param.trim())) + .into_result()?; + + result.push(expr); current_param.clear(); } else { current_param.push(next_char); @@ -94,7 +96,11 @@ where } if !current_param.is_empty() { - result.push(current_param.trim().to_string()); + let expr = rib_expr() + .easy_parse(position::Stream::new(¤t_param)) + .into_result()?; + + result.push(expr.0); } Ok((result, result_committed.unwrap())) @@ -112,44 +118,55 @@ where }) .message("version"); - let single_function = identifier().map(|id| ParsedFunctionReference::Function { function: id }); + let single_function = + identifier().map(|id| DynamicParsedFunctionReference::Function { function: id }); let indexed_resource_syntax = || (identifier(), token('(').with(capture_resource_params())); let indexed_constructor_syntax = (indexed_resource_syntax(), token('.'), string("new")).map( - |((resource, resource_params), _, _)| ParsedFunctionReference::IndexedResourceConstructor { - resource, - resource_params, + |((resource, resource_params), _, _)| { + DynamicParsedFunctionReference::IndexedResourceConstructor { + resource, + resource_params: resource_params.into_iter().map(ResourceParam).collect(), + } }, ); let indexed_drop_syntax = (indexed_resource_syntax(), token('.'), string("drop")).map( - |((resource, resource_params), _, _)| ParsedFunctionReference::IndexedResourceDrop { + |((resource, resource_params), _, _)| DynamicParsedFunctionReference::IndexedResourceDrop { resource, - resource_params, + resource_params: resource_params.into_iter().map(ResourceParam).collect(), }, ); let indexed_method_syntax = (indexed_resource_syntax(), token('.'), identifier()).map( - |((resource, resource_params), _, method)| ParsedFunctionReference::IndexedResourceMethod { - resource, - resource_params, - method, + |((resource, resource_params), _, method)| { + DynamicParsedFunctionReference::IndexedResourceMethod { + resource, + resource_params: resource_params.into_iter().map(ResourceParam).collect(), + method, + } }, ); let raw_constructor_syntax = (identifier(), token('.'), string("new")) - .map(|(resource, _, _)| ParsedFunctionReference::RawResourceConstructor { resource }) - .or((string("[constructor]"), identifier()) - .map(|(_, resource)| ParsedFunctionReference::RawResourceConstructor { resource })); + .map(|(resource, _, _)| DynamicParsedFunctionReference::RawResourceConstructor { resource }) + .or( + (string("[constructor]"), identifier()).map(|(_, resource)| { + DynamicParsedFunctionReference::RawResourceConstructor { resource } + }), + ); let raw_drop_syntax = (identifier(), token('.'), string("drop")) - .map(|(resource, _, _)| ParsedFunctionReference::RawResourceDrop { resource }) + .map(|(resource, _, _)| DynamicParsedFunctionReference::RawResourceDrop { resource }) .or((string("[drop]"), identifier()) - .map(|(_, resource)| ParsedFunctionReference::RawResourceDrop { resource })); + .map(|(_, resource)| DynamicParsedFunctionReference::RawResourceDrop { resource })); let raw_method_syntax = (identifier(), token('.'), identifier()) .map( - |(resource, _, method)| ParsedFunctionReference::RawResourceMethod { resource, method }, + |(resource, _, method)| DynamicParsedFunctionReference::RawResourceMethod { + resource, + method, + }, ) .or( (string("[method]"), identifier(), token('.'), identifier()).map( - |(_, resource, _, method)| ParsedFunctionReference::RawResourceMethod { + |(_, resource, _, method)| DynamicParsedFunctionReference::RawResourceMethod { resource, method, }, @@ -157,7 +174,7 @@ where ); let raw_static_method_syntax = (string("[static]"), identifier(), token('.'), identifier()) .map( - |(_, resource, _, method)| ParsedFunctionReference::RawResourceStaticMethod { + |(_, resource, _, method)| DynamicParsedFunctionReference::RawResourceStaticMethod { resource, method, }, @@ -194,17 +211,18 @@ where }, None => ParsedFunctionSite::Interface { name: iface }, }; - ParsedFunctionName { site, function } + DynamicParsedFunctionName { site, function } }), ) - .or(identifier().map(|id| ParsedFunctionName { + .or(identifier().map(|id| DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { function: id }, + function: DynamicParsedFunctionReference::Function { function: id }, })) } #[cfg(test)] mod function_call_tests { + use crate::{DynamicParsedFunctionName, DynamicParsedFunctionReference, ResourceParam}; use combine::EasyParser; use crate::expr::Expr; @@ -219,9 +237,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -240,9 +258,9 @@ mod function_call_tests { let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -259,9 +277,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -278,9 +296,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -301,9 +319,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -325,9 +343,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -350,9 +368,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -376,9 +394,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -398,9 +416,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -420,9 +438,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -442,9 +460,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -465,9 +483,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -487,9 +505,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -509,9 +527,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -531,9 +549,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -553,9 +571,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -575,9 +593,9 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }, @@ -594,11 +612,11 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::Interface { name: "interface".to_string(), }, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "fn1".to_string(), }, }, @@ -615,14 +633,14 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "fn1".to_string(), }, }, @@ -639,14 +657,14 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "wasi".to_string(), package: "cli".to_string(), interface: "run".to_string(), version: Some(SemVer(semver::Version::new(0, 2, 0))), }, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "run".to_string(), }, }, @@ -663,14 +681,14 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::RawResourceConstructor { + function: DynamicParsedFunctionReference::RawResourceConstructor { resource: "resource1".to_string(), }, }, @@ -687,14 +705,14 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::RawResourceConstructor { + function: DynamicParsedFunctionReference::RawResourceConstructor { resource: "resource1".to_string(), }, }, @@ -711,14 +729,14 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::IndexedResourceConstructor { + function: DynamicParsedFunctionReference::IndexedResourceConstructor { resource: "resource1".to_string(), resource_params: vec![], }, @@ -738,19 +756,19 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::IndexedResourceConstructor { + function: DynamicParsedFunctionReference::IndexedResourceConstructor { resource: "resource1".to_string(), resource_params: vec![ - "\"hello\"".to_string(), - "1".to_string(), - "true".to_string(), + ResourceParam(Expr::literal("hello")), + ResourceParam(Expr::number(1f64)), + ResourceParam(Expr::boolean(true)), ], }, }, @@ -768,18 +786,29 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::IndexedResourceConstructor { + function: DynamicParsedFunctionReference::IndexedResourceConstructor { resource: "resource1".to_string(), resource_params: vec![ - "\"hello\"".to_string(), - "{ field-a: some(1) }".to_string(), + ResourceParam(Expr::literal("hello")), + ResourceParam(Expr::record(vec![( + "field-a".to_string(), + Expr::call( + DynamicParsedFunctionName { + site: ParsedFunctionSite::Global, + function: DynamicParsedFunctionReference::Function { + function: "some".to_string(), + }, + }, + vec![Expr::number(1f64)], + ), + )])), ], }, }, @@ -795,14 +824,14 @@ mod function_call_tests { let input = "ns:name/interface.{resource1.do-something}({bar, baz})"; let result = Expr::from_text(input).unwrap(); let expected = Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::RawResourceMethod { + function: DynamicParsedFunctionReference::RawResourceMethod { resource: "resource1".to_string(), method: "do-something".to_string(), }, @@ -818,14 +847,14 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::RawResourceMethod { + function: DynamicParsedFunctionReference::RawResourceMethod { resource: "resource1".to_string(), method: "do-something".to_string(), }, @@ -844,14 +873,14 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::RawResourceMethod { + function: DynamicParsedFunctionReference::RawResourceMethod { resource: "resource1".to_string(), method: "do-something-static".to_string(), }, @@ -869,14 +898,14 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::RawResourceStaticMethod { + function: DynamicParsedFunctionReference::RawResourceStaticMethod { resource: "resource1".to_string(), method: "do-something-static".to_string(), }, @@ -894,14 +923,14 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::RawResourceDrop { + function: DynamicParsedFunctionReference::RawResourceDrop { resource: "resource1".to_string(), }, }, @@ -918,14 +947,14 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::IndexedResourceDrop { + function: DynamicParsedFunctionReference::IndexedResourceDrop { resource: "resource1".to_string(), resource_params: vec![], }, @@ -943,19 +972,19 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::IndexedResourceDrop { + function: DynamicParsedFunctionReference::IndexedResourceDrop { resource: "resource1".to_string(), resource_params: vec![ - "\"hello\"".to_string(), - "1".to_string(), - "true".to_string(), + ResourceParam(Expr::literal("hello")), + ResourceParam(Expr::number(1f64)), + ResourceParam(Expr::boolean(true)), ], }, }, @@ -973,18 +1002,29 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::IndexedResourceDrop { + function: DynamicParsedFunctionReference::IndexedResourceDrop { resource: "resource1".to_string(), resource_params: vec![ - "\"hello\"".to_string(), - "{ field-a: some(1) }".to_string(), + ResourceParam(Expr::literal("\"hello\"")), + ResourceParam(Expr::record(vec![( + "field-a".to_string(), + Expr::call( + DynamicParsedFunctionName { + site: ParsedFunctionSite::Global, + function: DynamicParsedFunctionReference::Function { + function: "some".to_string(), + }, + }, + vec![Expr::literal("1")], + ), + )])), ], }, }, @@ -1001,14 +1041,14 @@ mod function_call_tests { let result = rib_expr().easy_parse(input); let expected = Ok(( Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: ParsedFunctionSite::PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: ParsedFunctionReference::RawResourceDrop { + function: DynamicParsedFunctionReference::RawResourceDrop { resource: "resource1".to_string(), }, }, diff --git a/golem-rib/src/text/mod.rs b/golem-rib/src/text/mod.rs index 18565ce3b..99122b928 100644 --- a/golem-rib/src/text/mod.rs +++ b/golem-rib/src/text/mod.rs @@ -26,6 +26,14 @@ pub fn to_string(expr: &Expr) -> Result { writer::write_expr(expr) } +// Writes Expr without any outer interpolation in all cases +// TODO; Once we avoid interpolation support (other than for concatenations, we need just `to_string` +// and avoid distinguishing it with `to_string`. Currently `to_string` writes expressions wrapped with interpolation +// unless they are literals/text concatenated string +pub fn to_raw_string(expr: &Expr) -> String { + writer::write_expr(expr).unwrap() +} + #[cfg(test)] mod record_tests { use crate::expr::*; diff --git a/golem-rib/src/text/writer.rs b/golem-rib/src/text/writer.rs index 9db0afae2..0e61945f1 100644 --- a/golem-rib/src/text/writer.rs +++ b/golem-rib/src/text/writer.rs @@ -41,6 +41,15 @@ pub fn write_expr(expr: &Expr) -> Result { Ok(String::from_utf8(buf).unwrap_or_else(|err| panic!("invalid UTF-8: {err:?}"))) } +pub fn write_expr_without_interpolation(expr: &Expr) -> Result { + let mut buf = vec![]; + let mut writer = Writer::new(&mut buf); + + writer.write_expr(expr)?; + + Ok(String::from_utf8(buf).unwrap_or_else(|err| panic!("invalid UTF-8: {err:?}"))) +} + struct Writer { inner: W, } diff --git a/golem-worker-service-base/src/worker_bridge_execution/mod.rs b/golem-worker-service-base/src/worker_bridge_execution/mod.rs index 5d5d8c449..f1d40301e 100644 --- a/golem-worker-service-base/src/worker_bridge_execution/mod.rs +++ b/golem-worker-service-base/src/worker_bridge_execution/mod.rs @@ -11,7 +11,7 @@ pub use worker_request_executor::*; pub struct WorkerRequest { pub component_id: ComponentId, pub worker_name: String, - pub function_name: ParsedFunctionName, + pub function_name: String, pub function_params: Vec, pub idempotency_key: Option, } diff --git a/golem-worker-service/src/worker_bridge_request_executor.rs b/golem-worker-service/src/worker_bridge_request_executor.rs index a2ed73bb0..3f0e8b550 100644 --- a/golem-worker-service/src/worker_bridge_request_executor.rs +++ b/golem-worker-service/src/worker_bridge_request_executor.rs @@ -92,7 +92,7 @@ mod internal { .invoke_and_await_function_json( &worker_id, worker_request_params.idempotency_key, - worker_request_params.function_name.to_string(), + worker_request_params.function_name, invoke_parameters, None, empty_worker_metadata(), From ed7ebe7e43a6c2792ced7fe4e83e61e9b5281baa Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Mon, 23 Sep 2024 12:06:57 +1000 Subject: [PATCH 02/27] Bring grpc types --- golem-api-grpc/proto/golem/rib/expr.proto | 43 ++++++- .../proto/golem/rib/function_name.proto | 2 +- golem-rib/src/expr.rs | 4 +- golem-rib/src/function_name.rs | 118 ++++++++++++++++-- golem-rib/src/interpreter/rib_interpreter.rs | 10 +- golem-rib/src/parser/call.rs | 14 +-- golem-rib/src/text/mod.rs | 6 +- golem-rib/src/type_registry.rs | 6 +- 8 files changed, 169 insertions(+), 34 deletions(-) diff --git a/golem-api-grpc/proto/golem/rib/expr.proto b/golem-api-grpc/proto/golem/rib/expr.proto index fb5690c0d..c83c21e97 100644 --- a/golem-api-grpc/proto/golem/rib/expr.proto +++ b/golem-api-grpc/proto/golem/rib/expr.proto @@ -175,7 +175,7 @@ message CallExpr { message InvocationName { oneof name { - golem.rib.ParsedFunctionName parsed = 1; + golem.rib.DynamicParsedFunctionName parsed = 1; string variant_constructor = 2; string enum_constructor = 3; } @@ -217,3 +217,44 @@ message TupleConstructorArmPattern { message LiteralArmPattern { Expr expr = 1; } + +message DynamicParsedFunctionName { + golem.rib.ParsedFunctionSite site = 1; + DynamicParsedFunctionReference function = 2; +} + +message DynamicParsedFunctionReference { + oneof function_reference { + golem.rib.FunctionFunctionReference function = 1; + golem.rib.RawResourceConstructorFunctionReference raw_resource_constructor = 2; + golem.rib.RawResourceDropFunctionReference raw_resource_drop = 3; + golem.rib.RawResourceMethodFunctionReference raw_resource_method = 4; + golem.rib.RawResourceStaticMethodFunctionReference raw_resource_static_method = 5; + DynamicIndexedResourceConstructorFunctionReference indexed_resource_constructor = 6; + DynamicIndexedResourceMethodFunctionReference indexed_resource_method = 7; + DynamicIndexedResourceStaticMethodFunctionReference indexed_resource_static_method = 8; + DynamicIndexedResourceDropFunctionReference indexed_resource_drop = 9; + } +} + +message DynamicIndexedResourceConstructorFunctionReference { + string resource = 1; + repeated golem.rib.Expr resource_params = 2; +} + +message DynamicIndexedResourceMethodFunctionReference { + string resource = 1; + repeated golem.rib.Expr resource_params = 2; + string method = 3; +} + +message DynamicIndexedResourceStaticMethodFunctionReference { + string resource = 1; + repeated golem.rib.Expr resource_params = 2; + string method = 3; +} + +message DynamicIndexedResourceDropFunctionReference { + string resource = 1; + repeated golem.rib.Expr resource_params = 2; +} \ No newline at end of file diff --git a/golem-api-grpc/proto/golem/rib/function_name.proto b/golem-api-grpc/proto/golem/rib/function_name.proto index aa9dc5370..49cf695d7 100644 --- a/golem-api-grpc/proto/golem/rib/function_name.proto +++ b/golem-api-grpc/proto/golem/rib/function_name.proto @@ -94,4 +94,4 @@ message IndexedResourceStaticMethodFunctionReference { message IndexedResourceDropFunctionReference { string resource = 1; repeated string resource_params = 2; -} \ No newline at end of file +} diff --git a/golem-rib/src/expr.rs b/golem-rib/src/expr.rs index b65d5b9c7..d95ff1e3e 100644 --- a/golem-rib/src/expr.rs +++ b/golem-rib/src/expr.rs @@ -1058,10 +1058,10 @@ impl TryFrom for Expr { } golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor( name, - ) => Expr::call(ParsedFunctionName::parse(name)?, params), + ) => Expr::call(DynamicParsedFunctionName::parse(name)?, params), golem_api_grpc::proto::golem::rib::invocation_name::Name::EnumConstructor( name, - ) => Expr::call(ParsedFunctionName::parse(name)?, params), + ) => Expr::call(DynamicParsedFunctionName::parse(name)?, params), } } }; diff --git a/golem-rib/src/function_name.rs b/golem-rib/src/function_name.rs index 95ee0dd83..b0286e384 100644 --- a/golem-rib/src/function_name.rs +++ b/golem-rib/src/function_name.rs @@ -26,6 +26,7 @@ use semver::{BuildMetadata, Prerelease}; use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::fmt::Display; +use golem_api_grpc::proto::golem::rib::dynamic_parsed_function_reference::FunctionReference as ProtoDynamicFunctionReference; #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] pub enum ParsedFunctionSite { @@ -549,6 +550,85 @@ impl ParsedFunctionReference { } } +impl TryFrom for DynamicParsedFunctionReference { + type Error = String; + + fn try_from(value: golem_api_grpc::proto::golem::rib::DynamicParsedFunctionReference) -> Result { + let function = value + .function_reference + .ok_or("Missing function reference".to_string())?; + + match function { + ProtoDynamicFunctionReference::Function(golem_api_grpc::proto::golem::rib::FunctionFunctionReference { + function + }) => { + Ok(Self::Function { function }) + }, + ProtoDynamicFunctionReference::RawResourceConstructor(golem_api_grpc::proto::golem::rib::RawResourceConstructorFunctionReference { + resource + }) => { + Ok(Self::RawResourceConstructor { resource }) + }, + ProtoDynamicFunctionReference::RawResourceMethod(golem_api_grpc::proto::golem::rib::RawResourceMethodFunctionReference { + resource, + method + }) => { + Ok(Self::RawResourceMethod { resource, method }) + }, + ProtoDynamicFunctionReference::RawResourceStaticMethod(golem_api_grpc::proto::golem::rib::RawResourceStaticMethodFunctionReference { + resource, + method + }) => { + Ok(Self::RawResourceStaticMethod { resource, method }) + }, + ProtoDynamicFunctionReference::RawResourceDrop(golem_api_grpc::proto::golem::rib::RawResourceDropFunctionReference { + resource + }) => { + Ok(Self::RawResourceDrop { resource }) + }, + ProtoDynamicFunctionReference::IndexedResourceConstructor(golem_api_grpc::proto::golem::rib::DynamicIndexedResourceConstructorFunctionReference { + resource, + resource_params + }) => { + + let resource_params: Vec = + resource_params.into_iter().map(|x| Expr::try_from(x).map(ResourceParam)).collect::, String>>()?; + + Ok(Self::IndexedResourceConstructor { resource, resource_params }) + }, + ProtoDynamicFunctionReference::IndexedResourceMethod(golem_api_grpc::proto::golem::rib::DynamicIndexedResourceMethodFunctionReference { + resource, + resource_params, + method + }) => { + let resource_params: Vec = + resource_params.into_iter().map(|x| Expr::try_from(x).map(ResourceParam)).collect::, String>>()?; + + Ok(Self::IndexedResourceMethod { resource, resource_params, method }) + }, + ProtoDynamicFunctionReference::IndexedResourceStaticMethod(golem_api_grpc::proto::golem::rib::DynamicIndexedResourceStaticMethodFunctionReference { + resource, + resource_params, + method + }) => { + let resource_params: Vec = + resource_params.into_iter().map(|x| Expr::try_from(x).map(ResourceParam)).collect::, String>>()?; + + Ok(Self::IndexedResourceStaticMethod { resource, resource_params, method }) + }, + ProtoDynamicFunctionReference::IndexedResourceDrop(golem_api_grpc::proto::golem::rib::DynamicIndexedResourceDropFunctionReference { + resource, + resource_params + }) => { + let resource_params: Vec = + resource_params.into_iter().map(|x| Expr::try_from(x).map(ResourceParam)).collect::, String>>()?; + + Ok(Self::IndexedResourceDrop { resource, resource_params }) + }, + } + } +} + impl TryFrom for ParsedFunctionReference { @@ -723,17 +803,6 @@ pub(crate) struct DynamicParsedFunctionName { pub function: DynamicParsedFunctionReference, } -impl TryFrom for ParsedFunctionName { - type Error = String; - - fn try_from(value: DynamicParsedFunctionName) -> Result { - Ok(ParsedFunctionName { - site: value.site, - function: value.function.try_into()?, - }) - } -} - impl DynamicParsedFunctionName { pub fn parse(name: impl AsRef) -> Result { let name = name.as_ref(); @@ -754,6 +823,10 @@ impl DynamicParsedFunctionName { } } + pub fn function_name(&self) -> String { + self.to_static().function.function_name() + } + fn to_static(&self) -> ParsedFunctionName { ParsedFunctionName { site: self.site.clone(), @@ -762,6 +835,13 @@ impl DynamicParsedFunctionName { } } +impl Display for DynamicParsedFunctionName { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let function_name = self.to_static().to_string(); + write!(f, "{}", function_name) + } +} + impl Serialize for ParsedFunctionName { fn serialize(&self, serializer: S) -> Result { let function_name = self.to_string(); @@ -819,7 +899,7 @@ impl ParsedFunctionName { parser.easy_parse(name); match result { - Ok((parsed, _)) => Ok(parsed), + Ok((parsed, _)) => Ok(parsed.to_static()), Err(error) => { let error_message = error .map_position(|p| p.translate_position(name)) @@ -845,6 +925,20 @@ impl ParsedFunctionName { } } +impl TryFrom for DynamicParsedFunctionName { + type Error = String; + + fn try_from( + value: golem_api_grpc::proto::golem::rib::DynamicParsedFunctionName, + ) -> Result { + let site = ParsedFunctionSite::try_from(value.site.ok_or("Missing site".to_string())?)?; + let function = DynamicParsedFunctionReference::try_from( + value.function.ok_or("Missing function".to_string())?, + )?; + Ok(Self { site, function }) + } +} + impl TryFrom for ParsedFunctionName { type Error = String; diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index 2d1c185b1..e66b855a4 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -605,7 +605,7 @@ mod internal { .stack .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); } - FunctionReferenceType::RawResourceMethod(resource, meethod) => { + FunctionReferenceType::RawResourceMethod(resource, method) => { let parsed_function_name = ParsedFunctionName { site, function: ParsedFunctionReference::RawResourceMethod { resource, method }, @@ -647,7 +647,7 @@ mod internal { resource_params: type_anntoated_values .iter() .map(type_annotated_value_to_string) - .collect()?, + .collect::, String>>()?, }, }; @@ -681,7 +681,7 @@ mod internal { resource_params: type_anntoated_values .iter() .map(type_annotated_value_to_string) - .collect()?, + .collect::, String>>()?, method, }, }; @@ -716,7 +716,7 @@ mod internal { resource_params: type_anntoated_values .iter() .map(type_annotated_value_to_string) - .collect()?, + .collect::, String>>()?, method, }, }; @@ -747,7 +747,7 @@ mod internal { resource_params: type_anntoated_values .iter() .map(type_annotated_value_to_string) - .collect()?, + .collect::, String>>()?, }, }; diff --git a/golem-rib/src/parser/call.rs b/golem-rib/src/parser/call.rs index 2e2800d5d..854ba25cc 100644 --- a/golem-rib/src/parser/call.rs +++ b/golem-rib/src/parser/call.rs @@ -13,7 +13,7 @@ // limitations under the License. use crate::{DynamicParsedFunctionName, DynamicParsedFunctionReference, ResourceParam}; -use combine::error::Commit; +use combine::error::{Commit, Tracked}; use combine::parser::char::{alpha_num, string}; use combine::parser::char::{char, spaces}; use combine::parser::repeat::take_until; @@ -79,11 +79,11 @@ where nesting += 1; current_param.push(next_char); } else if next_char == ',' && nesting == 1 { - let (expr, _) = rib_expr() - .easy_parse(position::Stream::new(current_param.trim())) - .into_result()?; + let expr = rib_expr() + .easy_parse(current_param.trim()) + .map_err(|e| Commit::Commit(Tracked::from(RibParseError::Message(e.to_string()))))?; - result.push(expr); + result.push(expr.0); current_param.clear(); } else { current_param.push(next_char); @@ -97,8 +97,8 @@ where if !current_param.is_empty() { let expr = rib_expr() - .easy_parse(position::Stream::new(¤t_param)) - .into_result()?; + .easy_parse(current_param.trim()) + .map_err(|e| Commit::Commit(Tracked::from(RibParseError::Message(e.to_string()))))?; result.push(expr.0); } diff --git a/golem-rib/src/text/mod.rs b/golem-rib/src/text/mod.rs index 99122b928..e41da5ff7 100644 --- a/golem-rib/src/text/mod.rs +++ b/golem-rib/src/text/mod.rs @@ -26,9 +26,9 @@ pub fn to_string(expr: &Expr) -> Result { writer::write_expr(expr) } -// Writes Expr without any outer interpolation in all cases -// TODO; Once we avoid interpolation support (other than for concatenations, we need just `to_string` -// and avoid distinguishing it with `to_string`. Currently `to_string` writes expressions wrapped with interpolation +// TODO; Once we avoid interpolation support +// we can remove this function and use `to_string`. +// Currently `to_string` writes expressions wrapped with interpolation // unless they are literals/text concatenated string pub fn to_raw_string(expr: &Expr) -> String { writer::write_expr(expr).unwrap() diff --git a/golem-rib/src/type_registry.rs b/golem-rib/src/type_registry.rs index 0fccf8de3..cc1f85aa9 100644 --- a/golem-rib/src/type_registry.rs +++ b/golem-rib/src/type_registry.rs @@ -44,11 +44,11 @@ impl RegistryKey { RegistryKey::VariantName(variant_name.clone()) } CallType::EnumConstructor(enum_name) => RegistryKey::EnumName(enum_name.clone()), - CallType::Function(function_name) => match function_name.site().interface_name() { - None => RegistryKey::FunctionName(function_name.function().function_name()), + CallType::Function(function_name) => match function_name.site.interface_name() { + None => RegistryKey::FunctionName(function_name.function_name()), Some(interface_name) => RegistryKey::FunctionNameWithInterface { interface_name: interface_name.to_string(), - function_name: function_name.function().function_name(), + function_name: function_name.function_name(), }, }, } From a7e907cd0fc6dbcd180c32503bca84b2a2947a0e Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Mon, 23 Sep 2024 12:38:18 +1000 Subject: [PATCH 03/27] Add IR proto --- golem-api-grpc/proto/golem/rib/ir.proto | 68 ++++++++++++++++++++++++- golem-rib/src/compiler/ir.rs | 2 +- golem-rib/src/expr.rs | 4 +- 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/golem-api-grpc/proto/golem/rib/ir.proto b/golem-api-grpc/proto/golem/rib/ir.proto index 4225db472..f5f0d7f5a 100644 --- a/golem-api-grpc/proto/golem/rib/ir.proto +++ b/golem-api-grpc/proto/golem/rib/ir.proto @@ -6,6 +6,8 @@ import "wasm/ast/type.proto"; import "wasm/rpc/type_annotated_value.proto"; +import "golem/rib/function_name.proto"; + message RibIR { oneof instruction { wasm.rpc.TypeAnnotatedValue push_lit = 1; @@ -39,6 +41,7 @@ message RibIR { ConcatInstruction concat = 29; EnumConstructionInstruction enum_construction = 30; And and = 31; + CreateFunctionNameInstruction create_function_name = 32; } } @@ -83,7 +86,6 @@ message JumpInstruction { } message CallInstruction { - string function_name = 1; uint64 argument_count = 2; wasm.ast.Type return_type = 3; } @@ -98,6 +100,12 @@ message EnumConstructionInstruction { wasm.ast.Type return_type = 2; } +message CreateFunctionNameInstruction { + golem.rib.ParsedFunctionSite site = 1; + FunctionReferenceType function_reference_details = 2; +} + + message EqualTo {} message GreaterThan {} message LessThan {} @@ -106,3 +114,61 @@ message LessThanOrEqualTo {} message GetTag {} message Negate {} message And {} + +message FunctionReferenceType { + oneof type { + Function function = 1; + RawResourceConstructor raw_resource_constructor = 2; + RawResourceDrop raw_resource_drop = 3; + RawResourceMethod raw_resource_method = 4; + RawResourceStaticMethod raw_resource_static_method = 5; + IndexedResourceConstructor indexed_resource_constructor = 6; + IndexedResourceMethod indexed_resource_method = 7; + IndexedResourceStaticMethod indexed_resource_static_method = 8; + IndexedResourceDrop indexed_resource_drop = 9; + } +} + +message Function { + string name = 1; +} + +message RawResourceConstructor { + string resource_name = 1; +} + +message RawResourceDrop { + string resource_name = 1; +} + +message RawResourceMethod { + string resource_name = 1; + string method_name = 2; +} + +message RawResourceStaticMethod { + string resource_name = 1; + string method_name = 2; +} + +message IndexedResourceConstructor { + string resource_name = 1; + uint32 arg_size = 2; +} + +message IndexedResourceMethod { + string resource_name = 1; + uint32 arg_size = 2; + string method_name = 3; +} + +message IndexedResourceStaticMethod { + string resource_name = 1; + uint32 arg_size = 2; + string method_name = 3; +} + +message IndexedResourceDrop { + string resource_name = 1; + uint32 arg_size = 2; +} diff --git a/golem-rib/src/compiler/ir.rs b/golem-rib/src/compiler/ir.rs index 5c4d73f82..56c91efff 100644 --- a/golem-rib/src/compiler/ir.rs +++ b/golem-rib/src/compiler/ir.rs @@ -307,7 +307,7 @@ impl From for ProtoRibIR { instruction_id: value.index as u64, }), RibIR::Deconstruct => Instruction::Deconstruct((&AnalysedType::Str(TypeStr)).into()), //TODO; remove type in deconstruct from protobuf - RibIR::InvokeFunction(name, arg_count, return_type) => { + RibIR::InvokeFunction(arg_count, return_type) => { let typ = match return_type { AnalysedTypeWithUnit::Unit => None, AnalysedTypeWithUnit::Type(analysed_type) => { diff --git a/golem-rib/src/expr.rs b/golem-rib/src/expr.rs index d95ff1e3e..07fded282 100644 --- a/golem-rib/src/expr.rs +++ b/golem-rib/src/expr.rs @@ -692,11 +692,13 @@ impl Expr { } } -#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Encode, Decode)] pub struct Number { pub value: f64, // Change to bigdecimal } +impl Eq for Number {} + impl Number { pub fn to_val(&self, analysed_type: &AnalysedType) -> Option { match analysed_type { From 385bec758cd801b71afbbe95f0985759ccd2dbe6 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Mon, 23 Sep 2024 12:52:48 +1000 Subject: [PATCH 04/27] Add more rib --- golem-rib/src/compiler/ir.rs | 128 ++++++++++++++++++++++++++++++++--- 1 file changed, 120 insertions(+), 8 deletions(-) diff --git a/golem-rib/src/compiler/ir.rs b/golem-rib/src/compiler/ir.rs index 56c91efff..239ce5d79 100644 --- a/golem-rib/src/compiler/ir.rs +++ b/golem-rib/src/compiler/ir.rs @@ -15,11 +15,7 @@ use crate::{AnalysedTypeWithUnit, ParsedFunctionName, ParsedFunctionSite, VariableId}; use bincode::{Decode, Encode}; use golem_api_grpc::proto::golem::rib::rib_ir::Instruction; -use golem_api_grpc::proto::golem::rib::{ - And, CallInstruction, ConcatInstruction, EqualTo, GetTag, GreaterThan, GreaterThanOrEqualTo, - JumpInstruction, LessThan, LessThanOrEqualTo, Negate, PushListInstruction, PushNoneInstruction, - PushTupleInstruction, RibIr as ProtoRibIR, -}; +use golem_api_grpc::proto::golem::rib::{And, CallInstruction, ConcatInstruction, CreateFunctionNameInstruction, EqualTo, GetTag, GreaterThan, GreaterThanOrEqualTo, JumpInstruction, LessThan, LessThanOrEqualTo, Negate, PushListInstruction, PushNoneInstruction, PushTupleInstruction, RibIr as ProtoRibIR}; use golem_wasm_ast::analysis::{AnalysedType, TypeStr}; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use serde::{Deserialize, Serialize}; @@ -74,6 +70,110 @@ pub enum FunctionReferenceType { IndexedResourceDrop(String, usize), } +impl From for FunctionReferenceType { + fn from(value: golem_api_grpc::proto::golem::rib::FunctionReferenceType) -> Self { + let value = value.r#type.ok_or("Missing type".to_string())?; + match value { + golem_api_grpc::proto::golem::rib::function_reference_type::Type::Function(name) => FunctionReferenceType::Function(name.name), + golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceConstructor(name) => FunctionReferenceType::RawResourceConstructor(name.resource_name), + golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceDrop(name) => FunctionReferenceType::RawResourceDrop(name.resource_name), + golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceMethod(raw_resource_method) =>{ + let name = raw_resource_method.resource_name; + let method = raw_resource_method.method_name; + FunctionReferenceType::RawResourceMethod(name, method) + } + golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceStaticMethod(raw_resource_static_method) => { + let name = raw_resource_static_method.resource_name; + let method = raw_resource_static_method.method_name; + FunctionReferenceType::RawResourceStaticMethod(name, method) + } + golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceConstructor(indexed_resource_constructor) => { + let name = indexed_resource_constructor.resource_name; + let index = indexed_resource_constructor.arg_size; + FunctionReferenceType::IndexedResourceConstructor(name, index as usize) + } + golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceMethod(indexed_resource_method) => { + let name = indexed_resource_method.resource_name; + let index = indexed_resource_method.arg_size; + let method = indexed_resource_method.method_name; + FunctionReferenceType::IndexedResourceMethod(name, index as usize, method) + } + golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceStaticMethod(indexed_resource_static_method) => { + let name = indexed_resource_static_method.resource_name; + let index = indexed_resource_static_method.arg_size; + let method = indexed_resource_static_method.method_name; + FunctionReferenceType::IndexedResourceStaticMethod(name, index as usize, method) + } + golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceDrop(indexed_resource_drop) => { + let name = indexed_resource_drop.resource_name; + let index = indexed_resource_drop.arg_size; + FunctionReferenceType::IndexedResourceDrop(name, index as usize) + } + } + } +} + +impl From for golem_api_grpc::proto::golem::rib::FunctionReferenceType { + fn from(value: FunctionReferenceType) -> Self { + match value { + FunctionReferenceType::Function(name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::Function(golem_api_grpc::proto::golem::rib::Function { + name + })) + }, + FunctionReferenceType::RawResourceConstructor(resource_name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceConstructor(golem_api_grpc::proto::golem::rib::RawResourceConstructor { + resource_name + })) + }, + FunctionReferenceType::RawResourceDrop(resource_name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceDrop(golem_api_grpc::proto::golem::rib::RawResourceDrop { + resource_name + })) + }, + FunctionReferenceType::RawResourceMethod(resource_name, method_name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceMethod(golem_api_grpc::proto::golem::rib::RawResourceMethod { + resource_name, + method_name + })) + }, + FunctionReferenceType::RawResourceStaticMethod(resource_name, method_name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceStaticMethod(golem_api_grpc::proto::golem::rib::RawResourceStaticMethod { + resource_name, + method_name + })) + }, + FunctionReferenceType::IndexedResourceConstructor(resource_name, arg_size) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceConstructor(golem_api_grpc::proto::golem::rib::IndexedResourceConstructor { + resource_name, + arg_size: arg_size as u32 + })) + }, + FunctionReferenceType::IndexedResourceMethod(resource_name, arg_size, method_name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceMethod(golem_api_grpc::proto::golem::rib::IndexedResourceMethod { + resource_name, + arg_size: arg_size as u32, + method_name + })) + }, + FunctionReferenceType::IndexedResourceStaticMethod(resource_name, arg_size, method_name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceStaticMethod(golem_api_grpc::proto::golem::rib::IndexedResourceStaticMethod { + resource_name, + arg_size: arg_size as u32, + method_name + })) + }, + FunctionReferenceType::IndexedResourceDrop(resource_name, arg_size) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceDrop(golem_api_grpc::proto::golem::rib::IndexedResourceDrop { + resource_name, + arg_size: arg_size as u32 + })) + } + + } + } +} + // Every instruction can have a unique ID, and the compiler // can assign this and label the start and end of byte code blocks. // This is more efficient than assigning index to every instruction and incrementing it @@ -200,8 +300,6 @@ impl TryFrom for RibIR { }; Ok(RibIR::InvokeFunction( - ParsedFunctionName::parse(call_instruction.function_name) - .map_err(|_| "Failed to convert ParsedFunctionName".to_string())?, call_instruction.argument_count as usize, return_type, )) @@ -258,6 +356,15 @@ impl TryFrom for RibIR { Instruction::Concat(concat_instruction) => { Ok(RibIR::Concat(concat_instruction.arg_size as usize)) } + Instruction::CreateFunctionName(instruction) => { + let parsed_site = instruction.site.ok_or("Missing site".to_string())?; + let parsed_function_site = ParsedFunctionSite::try_from(parsed_site)?; + + let reference_type = instruction.function_reference_details.ok_or("Missing reference_type".to_string())?; + let function_reference_type = reference_type.into(); + + Ok(RibIR::CreateFunctionName(parsed_function_site, function_reference_type)) + } } } } @@ -317,7 +424,6 @@ impl From for ProtoRibIR { }; Instruction::Call(CallInstruction { - function_name: name.to_string(), argument_count: arg_count as u64, return_type: typ, }) @@ -361,6 +467,12 @@ impl From for ProtoRibIR { arg_size: concat as u64, }), RibIR::Negate => Instruction::Negate(Negate {}), + RibIR::CreateFunctionName(site, reference_type) => { + Instruction::CreateFunctionName(CreateFunctionNameInstruction { + site: Some(site.into()), + function_reference_details: Some(reference_type.into()), + }) + } }; ProtoRibIR { From caadf4c370afbe5b5cd7743747d85947fe36a4c6 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Mon, 23 Sep 2024 12:55:34 +1000 Subject: [PATCH 05/27] Add type --- golem-rib/src/compiler/ir.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/golem-rib/src/compiler/ir.rs b/golem-rib/src/compiler/ir.rs index 239ce5d79..8c7bb483d 100644 --- a/golem-rib/src/compiler/ir.rs +++ b/golem-rib/src/compiler/ir.rs @@ -70,10 +70,11 @@ pub enum FunctionReferenceType { IndexedResourceDrop(String, usize), } -impl From for FunctionReferenceType { - fn from(value: golem_api_grpc::proto::golem::rib::FunctionReferenceType) -> Self { +impl TryFrom for FunctionReferenceType { + type Error =String; + fn try_from(value: golem_api_grpc::proto::golem::rib::FunctionReferenceType) -> Result { let value = value.r#type.ok_or("Missing type".to_string())?; - match value { + let function_reference_type = match value { golem_api_grpc::proto::golem::rib::function_reference_type::Type::Function(name) => FunctionReferenceType::Function(name.name), golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceConstructor(name) => FunctionReferenceType::RawResourceConstructor(name.resource_name), golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceDrop(name) => FunctionReferenceType::RawResourceDrop(name.resource_name), @@ -109,7 +110,8 @@ impl From for Function let index = indexed_resource_drop.arg_size; FunctionReferenceType::IndexedResourceDrop(name, index as usize) } - } + }; + Ok(function_reference_type) } } @@ -361,7 +363,7 @@ impl TryFrom for RibIR { let parsed_function_site = ParsedFunctionSite::try_from(parsed_site)?; let reference_type = instruction.function_reference_details.ok_or("Missing reference_type".to_string())?; - let function_reference_type = reference_type.into(); + let function_reference_type = reference_type.try_into()?; Ok(RibIR::CreateFunctionName(parsed_function_site, function_reference_type)) } From 2ff41244151328134529b91a9c95c8fe8111e0ad Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Mon, 23 Sep 2024 13:06:25 +1000 Subject: [PATCH 06/27] Add Expr --- golem-rib/src/call_type.rs | 2 +- golem-rib/src/function_name.rs | 90 ++++++++++++++++++++++++++++++++-- 2 files changed, 88 insertions(+), 4 deletions(-) diff --git a/golem-rib/src/call_type.rs b/golem-rib/src/call_type.rs index 7bae88a88..6390e7c1a 100644 --- a/golem-rib/src/call_type.rs +++ b/golem-rib/src/call_type.rs @@ -42,7 +42,7 @@ impl TryFrom for CallType { let invocation = value.name.ok_or("Missing name of invocation")?; match invocation { golem_api_grpc::proto::golem::rib::invocation_name::Name::Parsed(name) => { - Ok(CallType::Function(ParsedFunctionName::try_from(name)?)) + Ok(CallType::Function(DynamicParsedFunctionName::try_from(name)?)) } golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor(name) => { Ok(CallType::VariantConstructor(name)) diff --git a/golem-rib/src/function_name.rs b/golem-rib/src/function_name.rs index b0286e384..44c2c00b1 100644 --- a/golem-rib/src/function_name.rs +++ b/golem-rib/src/function_name.rs @@ -22,13 +22,13 @@ use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use golem_wasm_rpc::type_annotated_value_from_str; use golem_wasm_rpc::Value; use poem_openapi::types::ToJSON; -use semver::{BuildMetadata, Prerelease}; -use serde::{Deserialize, Serialize}; +use semver::{BuildMetadata, Prerelease, Version}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::borrow::Cow; use std::fmt::Display; use golem_api_grpc::proto::golem::rib::dynamic_parsed_function_reference::FunctionReference as ProtoDynamicFunctionReference; -#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Encode, Decode)] pub enum ParsedFunctionSite { Global, Interface { @@ -45,6 +45,29 @@ pub enum ParsedFunctionSite { #[derive(PartialEq, Eq, Clone)] pub struct SemVer(pub semver::Version); + +impl Serialize for SemVer { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { + // Serialize the SemVer as its string representation. + serializer.serialize_str(&self.0.to_string()) + } +} + +impl<'de> Deserialize<'de> for SemVer { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + // Deserialize a string and attempt to parse it into a semver::Version. + let s = String::deserialize(deserializer)?; + let version = Version::parse(&s).map_err(serde::de::Error::custom)?; + Ok(SemVer(version)) + } +} + impl std::fmt::Debug for SemVer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) @@ -550,6 +573,58 @@ impl ParsedFunctionReference { } } +impl From for golem_api_grpc::proto::golem::rib::DynamicParsedFunctionReference { + fn from(value: DynamicParsedFunctionReference) -> Self { + let function = match value { + DynamicParsedFunctionReference::Function { function } => ProtoDynamicFunctionReference::Function( + golem_api_grpc::proto::golem::rib::FunctionFunctionReference { function }, + ), + DynamicParsedFunctionReference::RawResourceConstructor { resource } => ProtoDynamicFunctionReference::RawResourceConstructor( + golem_api_grpc::proto::golem::rib::RawResourceConstructorFunctionReference { resource }, + ), + DynamicParsedFunctionReference::RawResourceMethod { resource, method } => ProtoDynamicFunctionReference::RawResourceMethod( + golem_api_grpc::proto::golem::rib::RawResourceMethodFunctionReference { resource, method }, + ), + DynamicParsedFunctionReference::RawResourceStaticMethod { resource, method } => ProtoDynamicFunctionReference::RawResourceStaticMethod( + golem_api_grpc::proto::golem::rib::RawResourceStaticMethodFunctionReference { resource, method }, + ), + DynamicParsedFunctionReference::RawResourceDrop { resource } => ProtoDynamicFunctionReference::RawResourceDrop( + golem_api_grpc::proto::golem::rib::RawResourceDropFunctionReference { resource }, + ), + DynamicParsedFunctionReference::IndexedResourceConstructor { resource, resource_params } => ProtoDynamicFunctionReference::IndexedResourceConstructor( + golem_api_grpc::proto::golem::rib::DynamicIndexedResourceConstructorFunctionReference { + resource, + resource_params: resource_params.into_iter().map(|x| x.0.into()).collect(), + }, + ), + DynamicParsedFunctionReference::IndexedResourceMethod { resource, resource_params, method } => ProtoDynamicFunctionReference::IndexedResourceMethod( + golem_api_grpc::proto::golem::rib::DynamicIndexedResourceMethodFunctionReference { + resource, + resource_params: resource_params.into_iter().map(|x| x.0.into()).collect(), + method, + }, + ), + DynamicParsedFunctionReference::IndexedResourceStaticMethod { resource, resource_params, method } => ProtoDynamicFunctionReference::IndexedResourceStaticMethod( + golem_api_grpc::proto::golem::rib::DynamicIndexedResourceStaticMethodFunctionReference { + resource, + resource_params: resource_params.into_iter().map(|x| x.0.into()).collect(), + method, + }, + ), + DynamicParsedFunctionReference::IndexedResourceDrop { resource, resource_params } => ProtoDynamicFunctionReference::IndexedResourceDrop( + golem_api_grpc::proto::golem::rib::DynamicIndexedResourceDropFunctionReference { + resource, + resource_params: resource_params.into_iter().map(|x| x.0.into()).collect(), + }, + ), + }; + + golem_api_grpc::proto::golem::rib::DynamicParsedFunctionReference { + function_reference: Some(function), + } + } +} + impl TryFrom for DynamicParsedFunctionReference { type Error = String; @@ -939,6 +1014,15 @@ impl TryFrom for D } } +impl From for golem_api_grpc::proto::golem::rib::DynamicParsedFunctionName { + fn from(value: DynamicParsedFunctionName) -> Self { + golem_api_grpc::proto::golem::rib::DynamicParsedFunctionName { + site: Some(value.site.into()), + function: Some(value.function.into()), + } + } +} + impl TryFrom for ParsedFunctionName { type Error = String; From 4bf530a459116e49e5df03d9e56eeb1571ff16e0 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Mon, 23 Sep 2024 15:35:49 +1000 Subject: [PATCH 07/27] Add Expr --- golem-rib/src/parser/call.rs | 32 ++++++------------- golem-rib/src/parser/errors.rs | 2 ++ golem-rib/src/parser/multi_line_code_block.rs | 17 +++++----- golem-rib/src/parser/rib_expr.rs | 6 ++-- golem-rib/src/text/mod.rs | 2 +- .../type_inference/function_type_inference.rs | 5 +-- golem-rib/src/type_inference/mod.rs | 31 ++++++++++-------- golem-rib/src/type_inference/name_binding.rs | 21 ++++++------ golem-rib/src/type_inference/type_pull_up.rs | 3 +- 9 files changed, 58 insertions(+), 61 deletions(-) diff --git a/golem-rib/src/parser/call.rs b/golem-rib/src/parser/call.rs index 854ba25cc..e13be5f29 100644 --- a/golem-rib/src/parser/call.rs +++ b/golem-rib/src/parser/call.rs @@ -17,8 +17,8 @@ use combine::error::{Commit, Tracked}; use combine::parser::char::{alpha_num, string}; use combine::parser::char::{char, spaces}; use combine::parser::repeat::take_until; -use combine::stream::position; -use combine::{any, attempt, between, choice, many1, optional, parser, token, ParseError, Parser}; +use combine::stream::{PointerOffset, position}; +use combine::{any, attempt, between, choice, many1, optional, parser, token, ParseError, Parser, StreamOnce, Positioned}; use combine::{sep_by, EasyParser}; use crate::expr::Expr; @@ -79,11 +79,10 @@ where nesting += 1; current_param.push(next_char); } else if next_char == ',' && nesting == 1 { - let expr = rib_expr() - .easy_parse(current_param.trim()) - .map_err(|e| Commit::Commit(Tracked::from(RibParseError::Message(e.to_string()))))?; + let expr = + Expr::from_text(current_param.trim()).expect("Failed to parse expression"); - result.push(expr.0); + result.push(expr); current_param.clear(); } else { current_param.push(next_char); @@ -96,11 +95,9 @@ where } if !current_param.is_empty() { - let expr = rib_expr() - .easy_parse(current_param.trim()) - .map_err(|e| Commit::Commit(Tracked::from(RibParseError::Message(e.to_string()))))?; - - result.push(expr.0); + let expr = + Expr::from_text(current_param.trim()).expect("Failed to parse expression"); + result.push(expr); } Ok((result, result_committed.unwrap())) @@ -219,7 +216,6 @@ where function: DynamicParsedFunctionReference::Function { function: id }, })) } - #[cfg(test)] mod function_call_tests { use crate::{DynamicParsedFunctionName, DynamicParsedFunctionReference, ResourceParam}; @@ -1012,18 +1008,10 @@ mod function_call_tests { function: DynamicParsedFunctionReference::IndexedResourceDrop { resource: "resource1".to_string(), resource_params: vec![ - ResourceParam(Expr::literal("\"hello\"")), + ResourceParam(Expr::literal("hello")), ResourceParam(Expr::record(vec![( "field-a".to_string(), - Expr::call( - DynamicParsedFunctionName { - site: ParsedFunctionSite::Global, - function: DynamicParsedFunctionReference::Function { - function: "some".to_string(), - }, - }, - vec![Expr::literal("1")], - ), + Expr::option(Some(Expr::number(1f64))), )])), ], }, diff --git a/golem-rib/src/parser/errors.rs b/golem-rib/src/parser/errors.rs index 53ed19a24..c75612058 100644 --- a/golem-rib/src/parser/errors.rs +++ b/golem-rib/src/parser/errors.rs @@ -1,4 +1,5 @@ use std::fmt::Display; +use combine::{ParseError, StreamOnce}; use serde::de::StdError; @@ -25,6 +26,7 @@ impl StdError for RibParseError { } } + // A curated list of most common syntax errors, with the intent // to not regress user-facing error messages with changing parsing logic #[cfg(test)] diff --git a/golem-rib/src/parser/multi_line_code_block.rs b/golem-rib/src/parser/multi_line_code_block.rs index 07b7dca8d..26a899ae3 100644 --- a/golem-rib/src/parser/multi_line_code_block.rs +++ b/golem-rib/src/parser/multi_line_code_block.rs @@ -68,6 +68,7 @@ mod internal { mod tests { use crate::expr::Expr; use crate::{ArmPattern, MatchArm, ParsedFunctionName}; + use crate::function_name::DynamicParsedFunctionName; #[test] fn test_block_parse() { @@ -86,11 +87,11 @@ mod tests { Expr::let_binding("x", Expr::number(1f64)), Expr::let_binding("y", Expr::number(2f64)), Expr::call( - ParsedFunctionName::parse("foo").unwrap(), + DynamicParsedFunctionName::parse("foo").unwrap(), vec![Expr::identifier("x")], ), Expr::call( - ParsedFunctionName::parse("foo").unwrap(), + DynamicParsedFunctionName::parse("foo").unwrap(), vec![Expr::identifier("y")], ), ]); @@ -117,11 +118,11 @@ mod tests { Expr::let_binding("x", Expr::number(1f64)), Expr::let_binding("y", Expr::number(2f64)), Expr::call( - ParsedFunctionName::parse("foo").unwrap(), + DynamicParsedFunctionName::parse("foo").unwrap(), vec![Expr::identifier("x")], ), Expr::call( - ParsedFunctionName::parse("foo").unwrap(), + DynamicParsedFunctionName::parse("foo").unwrap(), vec![Expr::identifier("y")], ), ]), @@ -154,11 +155,11 @@ mod tests { Expr::let_binding("x", Expr::number(1f64)), Expr::let_binding("y", Expr::number(2f64)), Expr::call( - ParsedFunctionName::parse("foo").unwrap(), + DynamicParsedFunctionName::parse("foo").unwrap(), vec![Expr::identifier("x")], ), Expr::call( - ParsedFunctionName::parse("foo").unwrap(), + DynamicParsedFunctionName::parse("foo").unwrap(), vec![Expr::identifier("y")], ), ]), @@ -194,11 +195,11 @@ mod tests { Expr::let_binding("x", Expr::number(1f64)), Expr::let_binding("y", Expr::number(2f64)), Expr::call( - ParsedFunctionName::parse("foo").unwrap(), + DynamicParsedFunctionName::parse("foo").unwrap(), vec![Expr::identifier("x")], ), Expr::call( - ParsedFunctionName::parse("foo").unwrap(), + DynamicParsedFunctionName::parse("foo").unwrap(), vec![Expr::identifier("y")], ), ]), diff --git a/golem-rib/src/parser/rib_expr.rs b/golem-rib/src/parser/rib_expr.rs index 8d1f8b2f9..608599acb 100644 --- a/golem-rib/src/parser/rib_expr.rs +++ b/golem-rib/src/parser/rib_expr.rs @@ -187,7 +187,7 @@ mod tests { use crate::expr::ArmPattern; use crate::expr::MatchArm; - use crate::function_name::ParsedFunctionName; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference, ParsedFunctionName}; use crate::function_name::ParsedFunctionReference::RawResourceStaticMethod; use crate::function_name::ParsedFunctionSite::PackagedInterface; @@ -265,14 +265,14 @@ mod tests { Expr::let_binding( "result", Expr::call( - ParsedFunctionName { + DynamicParsedFunctionName { site: PackagedInterface { namespace: "ns".to_string(), package: "name".to_string(), interface: "interface".to_string(), version: None, }, - function: RawResourceStaticMethod { + function: DynamicParsedFunctionReference::RawResourceStaticMethod { resource: "resource1".to_string(), method: "do-something-static".to_string(), }, diff --git a/golem-rib/src/text/mod.rs b/golem-rib/src/text/mod.rs index e41da5ff7..0c0055039 100644 --- a/golem-rib/src/text/mod.rs +++ b/golem-rib/src/text/mod.rs @@ -31,7 +31,7 @@ pub fn to_string(expr: &Expr) -> Result { // Currently `to_string` writes expressions wrapped with interpolation // unless they are literals/text concatenated string pub fn to_raw_string(expr: &Expr) -> String { - writer::write_expr(expr).unwrap() + writer::write_expr_without_interpolation(expr).unwrap() } #[cfg(test)] diff --git a/golem-rib/src/type_inference/function_type_inference.rs b/golem-rib/src/type_inference/function_type_inference.rs index 364501eab..8e4404283 100644 --- a/golem-rib/src/type_inference/function_type_inference.rs +++ b/golem-rib/src/type_inference/function_type_inference.rs @@ -257,6 +257,7 @@ mod function_parameters_inference_tests { use golem_wasm_ast::analysis::{ AnalysedExport, AnalysedFunction, AnalysedFunctionParameter, AnalysedType, TypeU32, TypeU64, }; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; fn get_function_type_registry() -> FunctionTypeRegistry { let metadata = vec![ @@ -295,9 +296,9 @@ mod function_parameters_inference_tests { let let_binding = Expr::let_binding("x", Expr::number(1f64)); let call_expr = Expr::Call( - CallType::Function(ParsedFunctionName { + CallType::Function(DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }), diff --git a/golem-rib/src/type_inference/mod.rs b/golem-rib/src/type_inference/mod.rs index c5b8f5b6a..ecd259c44 100644 --- a/golem-rib/src/type_inference/mod.rs +++ b/golem-rib/src/type_inference/mod.rs @@ -57,6 +57,7 @@ mod type_inference_tests { Expr, InferredType, Number, ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, VariableId, }; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; #[test] fn test_simple_let_binding_type_inference() { @@ -83,9 +84,9 @@ mod type_inference_tests { ); let call_expr = Expr::Call( - CallType::Function(ParsedFunctionName { + CallType::Function(DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }), @@ -140,9 +141,9 @@ mod type_inference_tests { ); let call_expr1 = Expr::Call( - CallType::Function(ParsedFunctionName { + CallType::Function(DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }), @@ -154,9 +155,9 @@ mod type_inference_tests { ); let call_expr2 = Expr::Call( - CallType::Function(ParsedFunctionName { + CallType::Function(DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "baz".to_string(), }, }), @@ -1025,6 +1026,7 @@ mod type_inference_tests { ArmPattern, Expr, FunctionTypeRegistry, InferredType, MatchArm, Number, ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, VariableId, }; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; #[test] fn test_simple_pattern_match_type_inference() { @@ -1076,9 +1078,9 @@ mod type_inference_tests { InferredType::U64, ))), Expr::Call( - CallType::Function(ParsedFunctionName { + CallType::Function(DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }), @@ -1096,9 +1098,9 @@ mod type_inference_tests { InferredType::U64, // because predicate is u64 ))), Expr::Call( - CallType::Function(ParsedFunctionName { + CallType::Function(DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "baz".to_string(), }, }), @@ -1898,6 +1900,7 @@ mod type_inference_tests { }; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use golem_wasm_rpc::protobuf::TypedOption; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; pub(crate) fn get_function_type_registry() -> FunctionTypeRegistry { let metadata = vec![ @@ -2063,9 +2066,9 @@ mod type_inference_tests { VariableId::local("result", 0), None, Box::new(Expr::Call( - CallType::Function(ParsedFunctionName { + CallType::Function(DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "process".to_string(), }, }), @@ -2546,9 +2549,9 @@ mod type_inference_tests { VariableId::local("result", 0), None, Box::new(Expr::Call( - CallType::Function(ParsedFunctionName { + CallType::Function(DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }), diff --git a/golem-rib/src/type_inference/name_binding.rs b/golem-rib/src/type_inference/name_binding.rs index 08613afbb..1aa77a61d 100644 --- a/golem-rib/src/type_inference/name_binding.rs +++ b/golem-rib/src/type_inference/name_binding.rs @@ -78,6 +78,7 @@ mod name_binding_tests { Expr, InferredType, ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, VariableId, }; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; #[test] fn test_name_binding_simple() { @@ -99,9 +100,9 @@ mod name_binding_tests { ); let call_expr = Expr::Call( - CallType::Function(ParsedFunctionName { + CallType::Function(DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }), @@ -146,9 +147,9 @@ mod name_binding_tests { ); let call_expr1 = Expr::Call( - CallType::Function(ParsedFunctionName { + CallType::Function(DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }), @@ -160,9 +161,9 @@ mod name_binding_tests { ); let call_expr2 = Expr::Call( - CallType::Function(ParsedFunctionName { + CallType::Function(DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }), @@ -207,9 +208,9 @@ mod name_binding_tests { ); let call_expr1 = Expr::Call( - CallType::Function(ParsedFunctionName { + CallType::Function(DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }), @@ -221,9 +222,9 @@ mod name_binding_tests { ); let call_expr2 = Expr::Call( - CallType::Function(ParsedFunctionName { + CallType::Function(DynamicParsedFunctionName { site: ParsedFunctionSite::Global, - function: ParsedFunctionReference::Function { + function: DynamicParsedFunctionReference::Function { function: "foo".to_string(), }, }), diff --git a/golem-rib/src/type_inference/type_pull_up.rs b/golem-rib/src/type_inference/type_pull_up.rs index 54331fbdc..cef7be3d7 100644 --- a/golem-rib/src/type_inference/type_pull_up.rs +++ b/golem-rib/src/type_inference/type_pull_up.rs @@ -247,6 +247,7 @@ mod internal { #[cfg(test)] mod type_pull_up_tests { use crate::{ArmPattern, Expr, InferredType, Number, ParsedFunctionName}; + use crate::function_name::DynamicParsedFunctionName; #[test] pub fn test_pull_up_identifier() { @@ -403,7 +404,7 @@ mod type_pull_up_tests { #[test] pub fn test_pull_up_for_call() { let mut expr = Expr::call( - ParsedFunctionName::parse("global_fn").unwrap(), + DynamicParsedFunctionName::parse("global_fn").unwrap(), vec![Expr::number(1f64)], ); expr.pull_types_up().unwrap(); From 486d07e134a9d2faf78902f5cba872fdbc8ac543 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Mon, 23 Sep 2024 15:40:02 +1000 Subject: [PATCH 08/27] Fix test cases --- golem-rib/src/call_type.rs | 6 +-- golem-rib/src/compiler/ir.rs | 21 +++++++--- golem-rib/src/function_name.rs | 39 ++++++++++++------- golem-rib/src/parser/call.rs | 17 +++----- golem-rib/src/parser/errors.rs | 3 +- golem-rib/src/parser/multi_line_code_block.rs | 2 +- golem-rib/src/parser/rib_expr.rs | 4 +- .../type_inference/function_type_inference.rs | 2 +- golem-rib/src/type_inference/mod.rs | 6 +-- golem-rib/src/type_inference/name_binding.rs | 2 +- golem-rib/src/type_inference/type_pull_up.rs | 2 +- 11 files changed, 60 insertions(+), 44 deletions(-) diff --git a/golem-rib/src/call_type.rs b/golem-rib/src/call_type.rs index 6390e7c1a..635014859 100644 --- a/golem-rib/src/call_type.rs +++ b/golem-rib/src/call_type.rs @@ -41,9 +41,9 @@ impl TryFrom for CallType { ) -> Result { let invocation = value.name.ok_or("Missing name of invocation")?; match invocation { - golem_api_grpc::proto::golem::rib::invocation_name::Name::Parsed(name) => { - Ok(CallType::Function(DynamicParsedFunctionName::try_from(name)?)) - } + golem_api_grpc::proto::golem::rib::invocation_name::Name::Parsed(name) => Ok( + CallType::Function(DynamicParsedFunctionName::try_from(name)?), + ), golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor(name) => { Ok(CallType::VariantConstructor(name)) } diff --git a/golem-rib/src/compiler/ir.rs b/golem-rib/src/compiler/ir.rs index 8c7bb483d..7f2d72b4d 100644 --- a/golem-rib/src/compiler/ir.rs +++ b/golem-rib/src/compiler/ir.rs @@ -15,7 +15,11 @@ use crate::{AnalysedTypeWithUnit, ParsedFunctionName, ParsedFunctionSite, VariableId}; use bincode::{Decode, Encode}; use golem_api_grpc::proto::golem::rib::rib_ir::Instruction; -use golem_api_grpc::proto::golem::rib::{And, CallInstruction, ConcatInstruction, CreateFunctionNameInstruction, EqualTo, GetTag, GreaterThan, GreaterThanOrEqualTo, JumpInstruction, LessThan, LessThanOrEqualTo, Negate, PushListInstruction, PushNoneInstruction, PushTupleInstruction, RibIr as ProtoRibIR}; +use golem_api_grpc::proto::golem::rib::{ + And, CallInstruction, ConcatInstruction, CreateFunctionNameInstruction, EqualTo, GetTag, + GreaterThan, GreaterThanOrEqualTo, JumpInstruction, LessThan, LessThanOrEqualTo, Negate, + PushListInstruction, PushNoneInstruction, PushTupleInstruction, RibIr as ProtoRibIR, +}; use golem_wasm_ast::analysis::{AnalysedType, TypeStr}; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use serde::{Deserialize, Serialize}; @@ -71,8 +75,10 @@ pub enum FunctionReferenceType { } impl TryFrom for FunctionReferenceType { - type Error =String; - fn try_from(value: golem_api_grpc::proto::golem::rib::FunctionReferenceType) -> Result { + type Error = String; + fn try_from( + value: golem_api_grpc::proto::golem::rib::FunctionReferenceType, + ) -> Result { let value = value.r#type.ok_or("Missing type".to_string())?; let function_reference_type = match value { golem_api_grpc::proto::golem::rib::function_reference_type::Type::Function(name) => FunctionReferenceType::Function(name.name), @@ -362,10 +368,15 @@ impl TryFrom for RibIR { let parsed_site = instruction.site.ok_or("Missing site".to_string())?; let parsed_function_site = ParsedFunctionSite::try_from(parsed_site)?; - let reference_type = instruction.function_reference_details.ok_or("Missing reference_type".to_string())?; + let reference_type = instruction + .function_reference_details + .ok_or("Missing reference_type".to_string())?; let function_reference_type = reference_type.try_into()?; - Ok(RibIR::CreateFunctionName(parsed_function_site, function_reference_type)) + Ok(RibIR::CreateFunctionName( + parsed_function_site, + function_reference_type, + )) } } } diff --git a/golem-rib/src/function_name.rs b/golem-rib/src/function_name.rs index 44c2c00b1..f2083a701 100644 --- a/golem-rib/src/function_name.rs +++ b/golem-rib/src/function_name.rs @@ -16,6 +16,7 @@ use crate::{text, CompilerOutput, Expr, Interpreter, RibInterpreterResult}; use bincode::{BorrowDecode, Decode, Encode}; use combine::stream::easy; use combine::EasyParser; +use golem_api_grpc::proto::golem::rib::dynamic_parsed_function_reference::FunctionReference as ProtoDynamicFunctionReference; use golem_wasm_ast::analysis::AnalysedType; use golem_wasm_rpc::json::TypeAnnotatedValueJsonExtensions; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; @@ -26,7 +27,6 @@ use semver::{BuildMetadata, Prerelease, Version}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::borrow::Cow; use std::fmt::Display; -use golem_api_grpc::proto::golem::rib::dynamic_parsed_function_reference::FunctionReference as ProtoDynamicFunctionReference; #[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Encode, Decode)] pub enum ParsedFunctionSite { @@ -45,11 +45,10 @@ pub enum ParsedFunctionSite { #[derive(PartialEq, Eq, Clone)] pub struct SemVer(pub semver::Version); - impl Serialize for SemVer { fn serialize(&self, serializer: S) -> Result - where - S: Serializer, + where + S: Serializer, { // Serialize the SemVer as its string representation. serializer.serialize_str(&self.0.to_string()) @@ -58,8 +57,8 @@ impl Serialize for SemVer { impl<'de> Deserialize<'de> for SemVer { fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, + where + D: Deserializer<'de>, { // Deserialize a string and attempt to parse it into a semver::Version. let s = String::deserialize(deserializer)?; @@ -573,7 +572,9 @@ impl ParsedFunctionReference { } } -impl From for golem_api_grpc::proto::golem::rib::DynamicParsedFunctionReference { +impl From + for golem_api_grpc::proto::golem::rib::DynamicParsedFunctionReference +{ fn from(value: DynamicParsedFunctionReference) -> Self { let function = match value { DynamicParsedFunctionReference::Function { function } => ProtoDynamicFunctionReference::Function( @@ -625,10 +626,14 @@ impl From for golem_api_grpc::proto::golem::rib: } } -impl TryFrom for DynamicParsedFunctionReference { +impl TryFrom + for DynamicParsedFunctionReference +{ type Error = String; - fn try_from(value: golem_api_grpc::proto::golem::rib::DynamicParsedFunctionReference) -> Result { + fn try_from( + value: golem_api_grpc::proto::golem::rib::DynamicParsedFunctionReference, + ) -> Result { let function = value .function_reference .ok_or("Missing function reference".to_string())?; @@ -1000,7 +1005,9 @@ impl ParsedFunctionName { } } -impl TryFrom for DynamicParsedFunctionName { +impl TryFrom + for DynamicParsedFunctionName +{ type Error = String; fn try_from( @@ -1014,7 +1021,9 @@ impl TryFrom for D } } -impl From for golem_api_grpc::proto::golem::rib::DynamicParsedFunctionName { +impl From + for golem_api_grpc::proto::golem::rib::DynamicParsedFunctionName +{ fn from(value: DynamicParsedFunctionName) -> Self { golem_api_grpc::proto::golem::rib::DynamicParsedFunctionName { site: Some(value.site.into()), @@ -1285,7 +1294,7 @@ mod function_name_tests { parsed.function().raw_resource_params(), Some(&vec![ "\"hello\"".to_string(), - "{ field-a: some(1) }".to_string(), + "{field-a: some(1)}".to_string(), ]) ); assert_eq!( @@ -1301,7 +1310,7 @@ mod function_name_tests { resource: "resource1".to_string(), resource_params: vec![ "\"hello\"".to_string(), - "{ field-a: some(1) }".to_string(), + "{field-a: some(1)}".to_string(), ], }, }, @@ -1551,7 +1560,7 @@ mod function_name_tests { parsed.function().raw_resource_params(), Some(&vec![ "\"hello\"".to_string(), - "{ field-a: some(1) }".to_string(), + "{field-a: some(1)}".to_string(), ]) ); assert_eq!( @@ -1567,7 +1576,7 @@ mod function_name_tests { resource: "resource1".to_string(), resource_params: vec![ "\"hello\"".to_string(), - "{ field-a: some(1) }".to_string(), + "{field-a: some(1)}".to_string(), ], }, }, diff --git a/golem-rib/src/parser/call.rs b/golem-rib/src/parser/call.rs index e13be5f29..c5f4bab92 100644 --- a/golem-rib/src/parser/call.rs +++ b/golem-rib/src/parser/call.rs @@ -17,8 +17,11 @@ use combine::error::{Commit, Tracked}; use combine::parser::char::{alpha_num, string}; use combine::parser::char::{char, spaces}; use combine::parser::repeat::take_until; -use combine::stream::{PointerOffset, position}; -use combine::{any, attempt, between, choice, many1, optional, parser, token, ParseError, Parser, StreamOnce, Positioned}; +use combine::stream::{position, PointerOffset}; +use combine::{ + any, attempt, between, choice, many1, optional, parser, token, ParseError, Parser, Positioned, + StreamOnce, +}; use combine::{sep_by, EasyParser}; use crate::expr::Expr; @@ -795,15 +798,7 @@ mod function_call_tests { ResourceParam(Expr::literal("hello")), ResourceParam(Expr::record(vec![( "field-a".to_string(), - Expr::call( - DynamicParsedFunctionName { - site: ParsedFunctionSite::Global, - function: DynamicParsedFunctionReference::Function { - function: "some".to_string(), - }, - }, - vec![Expr::number(1f64)], - ), + Expr::option(Some(Expr::number(1f64))), )])), ], }, diff --git a/golem-rib/src/parser/errors.rs b/golem-rib/src/parser/errors.rs index c75612058..e15e0a5df 100644 --- a/golem-rib/src/parser/errors.rs +++ b/golem-rib/src/parser/errors.rs @@ -1,5 +1,5 @@ -use std::fmt::Display; use combine::{ParseError, StreamOnce}; +use std::fmt::Display; use serde::de::StdError; @@ -26,7 +26,6 @@ impl StdError for RibParseError { } } - // A curated list of most common syntax errors, with the intent // to not regress user-facing error messages with changing parsing logic #[cfg(test)] diff --git a/golem-rib/src/parser/multi_line_code_block.rs b/golem-rib/src/parser/multi_line_code_block.rs index 26a899ae3..95d2d8e4b 100644 --- a/golem-rib/src/parser/multi_line_code_block.rs +++ b/golem-rib/src/parser/multi_line_code_block.rs @@ -67,8 +67,8 @@ mod internal { #[cfg(test)] mod tests { use crate::expr::Expr; - use crate::{ArmPattern, MatchArm, ParsedFunctionName}; use crate::function_name::DynamicParsedFunctionName; + use crate::{ArmPattern, MatchArm, ParsedFunctionName}; #[test] fn test_block_parse() { diff --git a/golem-rib/src/parser/rib_expr.rs b/golem-rib/src/parser/rib_expr.rs index 608599acb..70c8771af 100644 --- a/golem-rib/src/parser/rib_expr.rs +++ b/golem-rib/src/parser/rib_expr.rs @@ -187,9 +187,11 @@ mod tests { use crate::expr::ArmPattern; use crate::expr::MatchArm; - use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference, ParsedFunctionName}; use crate::function_name::ParsedFunctionReference::RawResourceStaticMethod; use crate::function_name::ParsedFunctionSite::PackagedInterface; + use crate::function_name::{ + DynamicParsedFunctionName, DynamicParsedFunctionReference, ParsedFunctionName, + }; use super::*; diff --git a/golem-rib/src/type_inference/function_type_inference.rs b/golem-rib/src/type_inference/function_type_inference.rs index 8e4404283..ab53cf7bd 100644 --- a/golem-rib/src/type_inference/function_type_inference.rs +++ b/golem-rib/src/type_inference/function_type_inference.rs @@ -249,6 +249,7 @@ mod internal { #[cfg(test)] mod function_parameters_inference_tests { use crate::call_type::CallType; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; use crate::type_registry::FunctionTypeRegistry; use crate::{ Expr, InferredType, ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, @@ -257,7 +258,6 @@ mod function_parameters_inference_tests { use golem_wasm_ast::analysis::{ AnalysedExport, AnalysedFunction, AnalysedFunctionParameter, AnalysedType, TypeU32, TypeU64, }; - use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; fn get_function_type_registry() -> FunctionTypeRegistry { let metadata = vec![ diff --git a/golem-rib/src/type_inference/mod.rs b/golem-rib/src/type_inference/mod.rs index ecd259c44..1cb72671b 100644 --- a/golem-rib/src/type_inference/mod.rs +++ b/golem-rib/src/type_inference/mod.rs @@ -52,12 +52,12 @@ mod type_inference_tests { mod let_binding_tests { use crate::call_type::CallType; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; use crate::type_inference::type_inference_tests::internal; use crate::{ Expr, InferredType, Number, ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, VariableId, }; - use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; #[test] fn test_simple_let_binding_type_inference() { @@ -1020,13 +1020,13 @@ mod type_inference_tests { } mod pattern_match_tests { use crate::call_type::CallType; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; use crate::parser::type_name::TypeName; use crate::type_inference::type_inference_tests::internal; use crate::{ ArmPattern, Expr, FunctionTypeRegistry, InferredType, MatchArm, Number, ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, VariableId, }; - use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; #[test] fn test_simple_pattern_match_type_inference() { @@ -1888,6 +1888,7 @@ mod type_inference_tests { } mod internal { use crate::call_type::CallType; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; use crate::parser::type_name::TypeName; use crate::{ ArmPattern, Expr, FunctionTypeRegistry, InferredType, MatchArm, MatchIdentifier, @@ -1900,7 +1901,6 @@ mod type_inference_tests { }; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use golem_wasm_rpc::protobuf::TypedOption; - use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; pub(crate) fn get_function_type_registry() -> FunctionTypeRegistry { let metadata = vec![ diff --git a/golem-rib/src/type_inference/name_binding.rs b/golem-rib/src/type_inference/name_binding.rs index 1aa77a61d..5bb05881f 100644 --- a/golem-rib/src/type_inference/name_binding.rs +++ b/golem-rib/src/type_inference/name_binding.rs @@ -74,11 +74,11 @@ mod internal { #[cfg(test)] mod name_binding_tests { use crate::call_type::CallType; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; use crate::{ Expr, InferredType, ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, VariableId, }; - use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; #[test] fn test_name_binding_simple() { diff --git a/golem-rib/src/type_inference/type_pull_up.rs b/golem-rib/src/type_inference/type_pull_up.rs index cef7be3d7..12e68402d 100644 --- a/golem-rib/src/type_inference/type_pull_up.rs +++ b/golem-rib/src/type_inference/type_pull_up.rs @@ -246,8 +246,8 @@ mod internal { #[cfg(test)] mod type_pull_up_tests { - use crate::{ArmPattern, Expr, InferredType, Number, ParsedFunctionName}; use crate::function_name::DynamicParsedFunctionName; + use crate::{ArmPattern, Expr, InferredType, Number, ParsedFunctionName}; #[test] pub fn test_pull_up_identifier() { From 318b48ad4ad29cfc279c17e03533007e009d873a Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Mon, 23 Sep 2024 17:35:12 +1000 Subject: [PATCH 09/27] Try to fix function name --- golem-rib/src/compiler/byte_code.rs | 13 +++++++------ golem-rib/src/interpreter/rib_interpreter.rs | 11 +++++++---- golem-rib/src/interpreter/stack.rs | 2 +- .../src/worker_service_rib_interpreter/mod.rs | 2 +- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/golem-rib/src/compiler/byte_code.rs b/golem-rib/src/compiler/byte_code.rs index 7e7112dac..9fa117ce8 100644 --- a/golem-rib/src/compiler/byte_code.rs +++ b/golem-rib/src/compiler/byte_code.rs @@ -240,6 +240,7 @@ mod internal { Expr::Call(invocation_name, arguments, inferred_type) => match invocation_name { CallType::Function(parsed_function_name) => { + let function_result_type = if inferred_type.is_unit() { AnalysedTypeWithUnit::Unit } else { @@ -249,6 +250,12 @@ mod internal { )?) }; + for expr in arguments.iter().rev() { + stack.push(ExprState::from_expr(expr)); + } + + instructions.push(RibIR::InvokeFunction(arguments.len(), function_result_type)); + let site = parsed_function_name.site.clone(); match &parsed_function_name.function { @@ -355,12 +362,6 @@ mod internal { )) } } - - for expr in arguments.iter().rev() { - stack.push(ExprState::from_expr(expr)); - } - - instructions.push(RibIR::InvokeFunction(arguments.len(), function_result_type)); } CallType::VariantConstructor(variant_name) => { diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index e66b855a4..4436dce7f 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -63,6 +63,7 @@ impl Interpreter { // O(1) to do this let mut instructions = VecDeque::from(instructions0.instructions); + while let Some(instruction) = instructions.pop_front() { match instruction { RibIR::PushLit(val) => { @@ -357,6 +358,7 @@ mod internal { match analysed_type { AnalysedType::Tuple(inner_type) => { // Last updated value in stack should be a list to update the list + let last_list = interpreter_stack .pop_n(list_size) .ok_or(format!("Expected {} value on the stack", list_size))?; @@ -765,6 +767,11 @@ mod internal { argument_size: usize, interpreter: &mut Interpreter, ) -> Result<(), String> { + let function_name = interpreter + .stack + .pop_str() + .ok_or("Failed to get a function name from the stack".to_string())?; + let last_n_elements = interpreter .stack .pop_n(argument_size) @@ -779,10 +786,6 @@ mod internal { }) .collect::, String>>()?; - let function_name = interpreter - .stack - .pop_str() - .ok_or("Failed to get a function name from the stack".to_string())?; let result = interpreter .env diff --git a/golem-rib/src/interpreter/stack.rs b/golem-rib/src/interpreter/stack.rs index b42a5f59c..385ba0246 100644 --- a/golem-rib/src/interpreter/stack.rs +++ b/golem-rib/src/interpreter/stack.rs @@ -20,7 +20,7 @@ use golem_wasm_rpc::protobuf::{ TypedEnum, TypedList, TypedOption, TypedRecord, TypedTuple, TypedVariant, }; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct InterpreterStack { pub stack: Vec, } diff --git a/golem-worker-service-base/src/worker_service_rib_interpreter/mod.rs b/golem-worker-service-base/src/worker_service_rib_interpreter/mod.rs index ae71b6d66..b817251a6 100644 --- a/golem-worker-service-base/src/worker_service_rib_interpreter/mod.rs +++ b/golem-worker-service-base/src/worker_service_rib_interpreter/mod.rs @@ -86,7 +86,7 @@ impl WorkerServiceRibInterpreter for DefaultEvaluator { let idempotency_key = idempotency_key.clone(); let worker_invoke_function: RibFunctionInvoke = Arc::new( - move |function_name: ParsedFunctionName, parameters: Vec| { + move |function_name: String, parameters: Vec| { let worker_name = worker_name.to_string(); let component_id = component_id.clone(); let worker_name = worker_name.clone(); From 632e910fbcb669384f11411068dbfe779ae75126 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Mon, 23 Sep 2024 19:19:23 +1000 Subject: [PATCH 10/27] Fix tests --- golem-rib/src/compiler/byte_code.rs | 251 ++++++++++--------- golem-rib/src/interpreter/rib_interpreter.rs | 5 +- 2 files changed, 130 insertions(+), 126 deletions(-) diff --git a/golem-rib/src/compiler/byte_code.rs b/golem-rib/src/compiler/byte_code.rs index 9fa117ce8..cb6451bb9 100644 --- a/golem-rib/src/compiler/byte_code.rs +++ b/golem-rib/src/compiler/byte_code.rs @@ -238,145 +238,146 @@ mod internal { )?)); } - Expr::Call(invocation_name, arguments, inferred_type) => match invocation_name { - CallType::Function(parsed_function_name) => { - - let function_result_type = if inferred_type.is_unit() { - AnalysedTypeWithUnit::Unit - } else { - AnalysedTypeWithUnit::Type(convert_to_analysed_type_for( - expr, - inferred_type, - )?) - }; - - for expr in arguments.iter().rev() { - stack.push(ExprState::from_expr(expr)); - } - - instructions.push(RibIR::InvokeFunction(arguments.len(), function_result_type)); - - let site = parsed_function_name.site.clone(); + Expr::Call(invocation_name, arguments, inferred_type) => { + for expr in arguments.iter().rev() { + stack.push(ExprState::from_expr(expr)); + } - match &parsed_function_name.function { - DynamicParsedFunctionReference::Function { function } => { - instructions.push(RibIR::CreateFunctionName( - site, - FunctionReferenceType::Function(function.clone()), - )) - } + match invocation_name { + CallType::Function(parsed_function_name) => { + let function_result_type = if inferred_type.is_unit() { + AnalysedTypeWithUnit::Unit + } else { + AnalysedTypeWithUnit::Type(convert_to_analysed_type_for( + expr, + inferred_type, + )?) + }; + + instructions.push(RibIR::InvokeFunction(arguments.len(), function_result_type)); + + let site = parsed_function_name.site.clone(); + + match &parsed_function_name.function { + DynamicParsedFunctionReference::Function { function } => { + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::Function(function.clone()), + )) + } - DynamicParsedFunctionReference::RawResourceConstructor { resource } => { - instructions.push(RibIR::CreateFunctionName( - site, - FunctionReferenceType::RawResourceConstructor(resource.clone()), - )) - } - DynamicParsedFunctionReference::RawResourceDrop { resource } => { - instructions.push(RibIR::CreateFunctionName( - site, - FunctionReferenceType::RawResourceDrop(resource.clone()), - )) - } - DynamicParsedFunctionReference::RawResourceMethod { resource, method } => { - instructions.push(RibIR::CreateFunctionName( - site, - FunctionReferenceType::RawResourceMethod( - resource.clone(), - method.clone(), - ), - )) - } - DynamicParsedFunctionReference::RawResourceStaticMethod { - resource, - method, - } => instructions.push(RibIR::CreateFunctionName( - site, - FunctionReferenceType::RawResourceStaticMethod( - resource.clone(), - method.clone(), - ), - )), - DynamicParsedFunctionReference::IndexedResourceConstructor { - resource, - resource_params, - } => { - for param in resource_params { - stack.push(ExprState::from_expr(¶m.0)); + DynamicParsedFunctionReference::RawResourceConstructor { resource } => { + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::RawResourceConstructor(resource.clone()), + )) } - instructions.push(RibIR::CreateFunctionName( - site, - FunctionReferenceType::IndexedResourceConstructor( - resource.clone(), - resource_params.len(), - ), - )) - } - DynamicParsedFunctionReference::IndexedResourceMethod { - resource, - resource_params, - method, - } => { - for param in resource_params { - stack.push(ExprState::from_expr(¶m.0)); + DynamicParsedFunctionReference::RawResourceDrop { resource } => { + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::RawResourceDrop(resource.clone()), + )) } - instructions.push(RibIR::CreateFunctionName( - site, - FunctionReferenceType::IndexedResourceMethod( - resource.clone(), - resource_params.len(), - method.clone(), - ), - )) - } - DynamicParsedFunctionReference::IndexedResourceStaticMethod { - resource, - resource_params, - method, - } => { - for param in resource_params { - stack.push(ExprState::from_expr(¶m.0)); + DynamicParsedFunctionReference::RawResourceMethod { resource, method } => { + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::RawResourceMethod( + resource.clone(), + method.clone(), + ), + )) } - instructions.push(RibIR::CreateFunctionName( + DynamicParsedFunctionReference::RawResourceStaticMethod { + resource, + method, + } => instructions.push(RibIR::CreateFunctionName( site, - FunctionReferenceType::IndexedResourceStaticMethod( + FunctionReferenceType::RawResourceStaticMethod( resource.clone(), - resource_params.len(), method.clone(), ), - )) - } - DynamicParsedFunctionReference::IndexedResourceDrop { - resource, - resource_params, - } => { - for param in resource_params { - stack.push(ExprState::from_expr(¶m.0)); + )), + DynamicParsedFunctionReference::IndexedResourceConstructor { + resource, + resource_params, + } => { + for param in resource_params { + stack.push(ExprState::from_expr(¶m.0)); + } + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::IndexedResourceConstructor( + resource.clone(), + resource_params.len(), + ), + )) + } + DynamicParsedFunctionReference::IndexedResourceMethod { + resource, + resource_params, + method, + } => { + for param in resource_params { + stack.push(ExprState::from_expr(¶m.0)); + } + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::IndexedResourceMethod( + resource.clone(), + resource_params.len(), + method.clone(), + ), + )) + } + DynamicParsedFunctionReference::IndexedResourceStaticMethod { + resource, + resource_params, + method, + } => { + for param in resource_params { + stack.push(ExprState::from_expr(¶m.0)); + } + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::IndexedResourceStaticMethod( + resource.clone(), + resource_params.len(), + method.clone(), + ), + )) + } + DynamicParsedFunctionReference::IndexedResourceDrop { + resource, + resource_params, + } => { + for param in resource_params { + stack.push(ExprState::from_expr(¶m.0)); + } + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::IndexedResourceDrop( + resource.clone(), + resource_params.len(), + ), + )) } - instructions.push(RibIR::CreateFunctionName( - site, - FunctionReferenceType::IndexedResourceDrop( - resource.clone(), - resource_params.len(), - ), - )) } } - } - CallType::VariantConstructor(variant_name) => { - instructions.push(RibIR::PushVariant( - variant_name.clone(), - convert_to_analysed_type_for(expr, inferred_type)?, - )); - } - CallType::EnumConstructor(enmum_name) => { - instructions.push(RibIR::PushEnum( - enmum_name.clone(), - convert_to_analysed_type_for(expr, inferred_type)?, - )); + CallType::VariantConstructor(variant_name) => { + instructions.push(RibIR::PushVariant( + variant_name.clone(), + convert_to_analysed_type_for(expr, inferred_type)?, + )); + } + CallType::EnumConstructor(enmum_name) => { + instructions.push(RibIR::PushEnum( + enmum_name.clone(), + convert_to_analysed_type_for(expr, inferred_type)?, + )); + } } - }, + } Expr::Flags(flag_values, inferred_type) => match inferred_type { InferredType::Flags(all_flags) => { diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index 4436dce7f..ad9e27976 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -63,6 +63,8 @@ impl Interpreter { // O(1) to do this let mut instructions = VecDeque::from(instructions0.instructions); + dbg!(instructions.clone()); + while let Some(instruction) = instructions.pop_front() { match instruction { @@ -548,7 +550,7 @@ mod internal { interpreter .stack .pop_val() - .ok_or("Failed to get a value from the stack".to_string())?, + .ok_or("Failed to get the variant argument from the stack".to_string())?, ), None => None, }; @@ -767,6 +769,7 @@ mod internal { argument_size: usize, interpreter: &mut Interpreter, ) -> Result<(), String> { + dbg!("is this executed?"); let function_name = interpreter .stack .pop_str() From a538b652bf936a9d53bb4fa754e8e9d65ff3477a Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Mon, 23 Sep 2024 19:21:05 +1000 Subject: [PATCH 11/27] Reformat --- golem-rib/src/compiler/byte_code.rs | 29 ++++++++++---------- golem-rib/src/interpreter/rib_interpreter.rs | 18 +++++------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/golem-rib/src/compiler/byte_code.rs b/golem-rib/src/compiler/byte_code.rs index cb6451bb9..71b863b36 100644 --- a/golem-rib/src/compiler/byte_code.rs +++ b/golem-rib/src/compiler/byte_code.rs @@ -254,17 +254,17 @@ mod internal { )?) }; - instructions.push(RibIR::InvokeFunction(arguments.len(), function_result_type)); + instructions + .push(RibIR::InvokeFunction(arguments.len(), function_result_type)); let site = parsed_function_name.site.clone(); match &parsed_function_name.function { - DynamicParsedFunctionReference::Function { function } => { - instructions.push(RibIR::CreateFunctionName( + DynamicParsedFunctionReference::Function { function } => instructions + .push(RibIR::CreateFunctionName( site, FunctionReferenceType::Function(function.clone()), - )) - } + )), DynamicParsedFunctionReference::RawResourceConstructor { resource } => { instructions.push(RibIR::CreateFunctionName( @@ -278,15 +278,16 @@ mod internal { FunctionReferenceType::RawResourceDrop(resource.clone()), )) } - DynamicParsedFunctionReference::RawResourceMethod { resource, method } => { - instructions.push(RibIR::CreateFunctionName( - site, - FunctionReferenceType::RawResourceMethod( - resource.clone(), - method.clone(), - ), - )) - } + DynamicParsedFunctionReference::RawResourceMethod { + resource, + method, + } => instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::RawResourceMethod( + resource.clone(), + method.clone(), + ), + )), DynamicParsedFunctionReference::RawResourceStaticMethod { resource, method, diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index ad9e27976..95f527941 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -65,7 +65,6 @@ impl Interpreter { dbg!(instructions.clone()); - while let Some(instruction) = instructions.pop_front() { match instruction { RibIR::PushLit(val) => { @@ -545,15 +544,13 @@ mod internal { let variant_arg_typ = variant.typ.clone(); - let arg_value = match variant_arg_typ { - Some(_) => Some( - interpreter - .stack - .pop_val() - .ok_or("Failed to get the variant argument from the stack".to_string())?, - ), - None => None, - }; + let arg_value = + match variant_arg_typ { + Some(_) => Some(interpreter.stack.pop_val().ok_or( + "Failed to get the variant argument from the stack".to_string(), + )?), + None => None, + }; interpreter.stack.push_variant( variant_name.clone(), @@ -789,7 +786,6 @@ mod internal { }) .collect::, String>>()?; - let result = interpreter .env .invoke_worker_function_async(function_name, type_anntoated_values) From 1fc4453449fb1bdafd453244fddc8aa5ea828ce5 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Mon, 23 Sep 2024 19:22:53 +1000 Subject: [PATCH 12/27] Fix clippy --- golem-rib/src/call_type.rs | 2 +- golem-rib/src/compiler/byte_code.rs | 2 +- golem-rib/src/compiler/ir.rs | 2 +- golem-rib/src/expr.rs | 1 - golem-rib/src/function_name.rs | 6 ++---- golem-rib/src/interpreter/env.rs | 2 +- golem-rib/src/interpreter/rib_interpreter.rs | 2 +- golem-rib/src/parser/call.rs | 10 ++++------ golem-rib/src/parser/errors.rs | 1 - 9 files changed, 11 insertions(+), 17 deletions(-) diff --git a/golem-rib/src/call_type.rs b/golem-rib/src/call_type.rs index 635014859..37afc3864 100644 --- a/golem-rib/src/call_type.rs +++ b/golem-rib/src/call_type.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{DynamicParsedFunctionName, ParsedFunctionName}; +use crate::DynamicParsedFunctionName; use bincode::{Decode, Encode}; use std::convert::TryFrom; use std::fmt::Display; diff --git a/golem-rib/src/compiler/byte_code.rs b/golem-rib/src/compiler/byte_code.rs index 71b863b36..580724b13 100644 --- a/golem-rib/src/compiler/byte_code.rs +++ b/golem-rib/src/compiler/byte_code.rs @@ -86,7 +86,7 @@ mod internal { use crate::compiler::desugar::desugar_pattern_match; use crate::{ AnalysedTypeWithUnit, DynamicParsedFunctionReference, Expr, FunctionReferenceType, - InferredType, InstructionId, ParsedFunctionName, ParsedFunctionReference, RibIR, + InferredType, InstructionId, RibIR, }; use golem_wasm_ast::analysis::AnalysedType; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; diff --git a/golem-rib/src/compiler/ir.rs b/golem-rib/src/compiler/ir.rs index 7f2d72b4d..eb78ad64e 100644 --- a/golem-rib/src/compiler/ir.rs +++ b/golem-rib/src/compiler/ir.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{AnalysedTypeWithUnit, ParsedFunctionName, ParsedFunctionSite, VariableId}; +use crate::{AnalysedTypeWithUnit, ParsedFunctionSite, VariableId}; use bincode::{Decode, Encode}; use golem_api_grpc::proto::golem::rib::rib_ir::Instruction; use golem_api_grpc::proto::golem::rib::{ diff --git a/golem-rib/src/expr.rs b/golem-rib/src/expr.rs index 07fded282..7b7e5b4ac 100644 --- a/golem-rib/src/expr.rs +++ b/golem-rib/src/expr.rs @@ -13,7 +13,6 @@ // limitations under the License. use crate::call_type::CallType; -use crate::function_name::ParsedFunctionName; use crate::parser::rib_expr::rib_program; use crate::parser::type_name::TypeName; use crate::type_registry::FunctionTypeRegistry; diff --git a/golem-rib/src/function_name.rs b/golem-rib/src/function_name.rs index f2083a701..7e4320dd1 100644 --- a/golem-rib/src/function_name.rs +++ b/golem-rib/src/function_name.rs @@ -12,17 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{text, CompilerOutput, Expr, Interpreter, RibInterpreterResult}; +use crate::{text, Expr}; use bincode::{BorrowDecode, Decode, Encode}; use combine::stream::easy; use combine::EasyParser; use golem_api_grpc::proto::golem::rib::dynamic_parsed_function_reference::FunctionReference as ProtoDynamicFunctionReference; use golem_wasm_ast::analysis::AnalysedType; -use golem_wasm_rpc::json::TypeAnnotatedValueJsonExtensions; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use golem_wasm_rpc::type_annotated_value_from_str; use golem_wasm_rpc::Value; -use poem_openapi::types::ToJSON; use semver::{BuildMetadata, Prerelease, Version}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::borrow::Cow; @@ -878,7 +876,7 @@ pub struct ParsedFunctionName { } #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] -pub(crate) struct DynamicParsedFunctionName { +pub struct DynamicParsedFunctionName { pub site: ParsedFunctionSite, pub function: DynamicParsedFunctionReference, } diff --git a/golem-rib/src/interpreter/env.rs b/golem-rib/src/interpreter/env.rs index 3afe7ece6..0428ecbaf 100644 --- a/golem-rib/src/interpreter/env.rs +++ b/golem-rib/src/interpreter/env.rs @@ -13,7 +13,7 @@ // limitations under the License. use crate::interpreter::result::RibInterpreterResult; -use crate::{ParsedFunctionName, VariableId}; +use crate::VariableId; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use std::collections::HashMap; use std::future::Future; diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index 95f527941..4843167a6 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -225,7 +225,7 @@ mod internal { use golem_wasm_rpc::protobuf::typed_result::ResultValue; use golem_wasm_rpc::protobuf::{NameValuePair, TypedRecord, TypedTuple}; use golem_wasm_rpc::type_annotated_value_to_string; - use poem_openapi::types::ToJSON; + use std::collections::VecDeque; use std::ops::Deref; diff --git a/golem-rib/src/parser/call.rs b/golem-rib/src/parser/call.rs index c5f4bab92..a9089147c 100644 --- a/golem-rib/src/parser/call.rs +++ b/golem-rib/src/parser/call.rs @@ -13,20 +13,18 @@ // limitations under the License. use crate::{DynamicParsedFunctionName, DynamicParsedFunctionReference, ResourceParam}; -use combine::error::{Commit, Tracked}; +use combine::error::Commit; use combine::parser::char::{alpha_num, string}; use combine::parser::char::{char, spaces}; use combine::parser::repeat::take_until; -use combine::stream::{position, PointerOffset}; use combine::{ - any, attempt, between, choice, many1, optional, parser, token, ParseError, Parser, Positioned, - StreamOnce, + any, attempt, between, choice, many1, optional, parser, token, ParseError, Parser, }; -use combine::{sep_by, EasyParser}; +use combine::sep_by; use crate::expr::Expr; use crate::function_name::{ - ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, SemVer, + ParsedFunctionSite, SemVer, }; use crate::parser::errors::RibParseError; use crate::parser::rib_expr::rib_expr; diff --git a/golem-rib/src/parser/errors.rs b/golem-rib/src/parser/errors.rs index e15e0a5df..53ed19a24 100644 --- a/golem-rib/src/parser/errors.rs +++ b/golem-rib/src/parser/errors.rs @@ -1,4 +1,3 @@ -use combine::{ParseError, StreamOnce}; use std::fmt::Display; use serde::de::StdError; From 9d14333583adc4bb38c0a03fa23c10f7f2c9c16d Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Mon, 23 Sep 2024 20:36:44 +1000 Subject: [PATCH 13/27] Refactor --- golem-rib/src/function_name.rs | 2 +- golem-rib/src/interpreter/rib_interpreter.rs | 2 +- golem-rib/src/parser/call.rs | 12 +++--------- golem-rib/src/parser/multi_line_code_block.rs | 2 +- golem-rib/src/parser/rib_expr.rs | 5 +---- .../src/type_inference/function_type_inference.rs | 5 +---- golem-rib/src/type_inference/mod.rs | 9 +++------ golem-rib/src/type_inference/name_binding.rs | 5 +---- golem-rib/src/type_inference/type_pull_up.rs | 2 +- .../src/worker_bridge_execution/mod.rs | 1 - .../src/worker_service_rib_interpreter/mod.rs | 2 +- 11 files changed, 14 insertions(+), 33 deletions(-) diff --git a/golem-rib/src/function_name.rs b/golem-rib/src/function_name.rs index 7e4320dd1..a833285ae 100644 --- a/golem-rib/src/function_name.rs +++ b/golem-rib/src/function_name.rs @@ -291,7 +291,7 @@ pub enum ParsedFunctionReference { } #[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] -pub(crate) enum DynamicParsedFunctionReference { +pub enum DynamicParsedFunctionReference { Function { function: String, }, diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index 4843167a6..8e0a73d8a 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -225,7 +225,7 @@ mod internal { use golem_wasm_rpc::protobuf::typed_result::ResultValue; use golem_wasm_rpc::protobuf::{NameValuePair, TypedRecord, TypedTuple}; use golem_wasm_rpc::type_annotated_value_to_string; - + use std::collections::VecDeque; use std::ops::Deref; diff --git a/golem-rib/src/parser/call.rs b/golem-rib/src/parser/call.rs index a9089147c..a3a71c241 100644 --- a/golem-rib/src/parser/call.rs +++ b/golem-rib/src/parser/call.rs @@ -17,15 +17,11 @@ use combine::error::Commit; use combine::parser::char::{alpha_num, string}; use combine::parser::char::{char, spaces}; use combine::parser::repeat::take_until; -use combine::{ - any, attempt, between, choice, many1, optional, parser, token, ParseError, Parser, -}; use combine::sep_by; +use combine::{any, attempt, between, choice, many1, optional, parser, token, ParseError, Parser}; use crate::expr::Expr; -use crate::function_name::{ - ParsedFunctionSite, SemVer, -}; +use crate::function_name::{ParsedFunctionSite, SemVer}; use crate::parser::errors::RibParseError; use crate::parser::rib_expr::rib_expr; @@ -223,9 +219,7 @@ mod function_call_tests { use combine::EasyParser; use crate::expr::Expr; - use crate::function_name::{ - ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, SemVer, - }; + use crate::function_name::{ParsedFunctionSite, SemVer}; use crate::parser::rib_expr::rib_expr; #[test] diff --git a/golem-rib/src/parser/multi_line_code_block.rs b/golem-rib/src/parser/multi_line_code_block.rs index 95d2d8e4b..11cf77527 100644 --- a/golem-rib/src/parser/multi_line_code_block.rs +++ b/golem-rib/src/parser/multi_line_code_block.rs @@ -68,7 +68,7 @@ mod internal { mod tests { use crate::expr::Expr; use crate::function_name::DynamicParsedFunctionName; - use crate::{ArmPattern, MatchArm, ParsedFunctionName}; + use crate::{ArmPattern, MatchArm}; #[test] fn test_block_parse() { diff --git a/golem-rib/src/parser/rib_expr.rs b/golem-rib/src/parser/rib_expr.rs index 70c8771af..6221c3a3d 100644 --- a/golem-rib/src/parser/rib_expr.rs +++ b/golem-rib/src/parser/rib_expr.rs @@ -187,11 +187,8 @@ mod tests { use crate::expr::ArmPattern; use crate::expr::MatchArm; - use crate::function_name::ParsedFunctionReference::RawResourceStaticMethod; use crate::function_name::ParsedFunctionSite::PackagedInterface; - use crate::function_name::{ - DynamicParsedFunctionName, DynamicParsedFunctionReference, ParsedFunctionName, - }; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; use super::*; diff --git a/golem-rib/src/type_inference/function_type_inference.rs b/golem-rib/src/type_inference/function_type_inference.rs index ab53cf7bd..bef3fdd5f 100644 --- a/golem-rib/src/type_inference/function_type_inference.rs +++ b/golem-rib/src/type_inference/function_type_inference.rs @@ -251,10 +251,7 @@ mod function_parameters_inference_tests { use crate::call_type::CallType; use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; use crate::type_registry::FunctionTypeRegistry; - use crate::{ - Expr, InferredType, ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, - VariableId, - }; + use crate::{Expr, InferredType, ParsedFunctionSite, VariableId}; use golem_wasm_ast::analysis::{ AnalysedExport, AnalysedFunction, AnalysedFunctionParameter, AnalysedType, TypeU32, TypeU64, }; diff --git a/golem-rib/src/type_inference/mod.rs b/golem-rib/src/type_inference/mod.rs index 1cb72671b..38cd59b85 100644 --- a/golem-rib/src/type_inference/mod.rs +++ b/golem-rib/src/type_inference/mod.rs @@ -54,10 +54,7 @@ mod type_inference_tests { use crate::call_type::CallType; use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; use crate::type_inference::type_inference_tests::internal; - use crate::{ - Expr, InferredType, Number, ParsedFunctionName, ParsedFunctionReference, - ParsedFunctionSite, VariableId, - }; + use crate::{Expr, InferredType, Number, ParsedFunctionSite, VariableId}; #[test] fn test_simple_let_binding_type_inference() { @@ -1025,7 +1022,7 @@ mod type_inference_tests { use crate::type_inference::type_inference_tests::internal; use crate::{ ArmPattern, Expr, FunctionTypeRegistry, InferredType, MatchArm, Number, - ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, VariableId, + ParsedFunctionSite, VariableId, }; #[test] @@ -1892,7 +1889,7 @@ mod type_inference_tests { use crate::parser::type_name::TypeName; use crate::{ ArmPattern, Expr, FunctionTypeRegistry, InferredType, MatchArm, MatchIdentifier, - ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, VariableId, + ParsedFunctionSite, VariableId, }; use golem_wasm_ast::analysis::TypeVariant; use golem_wasm_ast::analysis::{ diff --git a/golem-rib/src/type_inference/name_binding.rs b/golem-rib/src/type_inference/name_binding.rs index 5bb05881f..e8cc50ef9 100644 --- a/golem-rib/src/type_inference/name_binding.rs +++ b/golem-rib/src/type_inference/name_binding.rs @@ -75,10 +75,7 @@ mod internal { mod name_binding_tests { use crate::call_type::CallType; use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; - use crate::{ - Expr, InferredType, ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, - VariableId, - }; + use crate::{Expr, InferredType, ParsedFunctionSite, VariableId}; #[test] fn test_name_binding_simple() { diff --git a/golem-rib/src/type_inference/type_pull_up.rs b/golem-rib/src/type_inference/type_pull_up.rs index 12e68402d..2fc0ebb79 100644 --- a/golem-rib/src/type_inference/type_pull_up.rs +++ b/golem-rib/src/type_inference/type_pull_up.rs @@ -247,7 +247,7 @@ mod internal { #[cfg(test)] mod type_pull_up_tests { use crate::function_name::DynamicParsedFunctionName; - use crate::{ArmPattern, Expr, InferredType, Number, ParsedFunctionName}; + use crate::{ArmPattern, Expr, InferredType, Number}; #[test] pub fn test_pull_up_identifier() { diff --git a/golem-worker-service-base/src/worker_bridge_execution/mod.rs b/golem-worker-service-base/src/worker_bridge_execution/mod.rs index f1d40301e..3e35427c5 100644 --- a/golem-worker-service-base/src/worker_bridge_execution/mod.rs +++ b/golem-worker-service-base/src/worker_bridge_execution/mod.rs @@ -4,7 +4,6 @@ use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; mod content_type_mapper; pub mod to_response; mod worker_request_executor; -use rib::ParsedFunctionName; pub use worker_request_executor::*; #[derive(PartialEq, Debug, Clone)] diff --git a/golem-worker-service-base/src/worker_service_rib_interpreter/mod.rs b/golem-worker-service-base/src/worker_service_rib_interpreter/mod.rs index b817251a6..e19d8d9b6 100644 --- a/golem-worker-service-base/src/worker_service_rib_interpreter/mod.rs +++ b/golem-worker-service-base/src/worker_service_rib_interpreter/mod.rs @@ -8,7 +8,7 @@ use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use golem_common::model::{ComponentId, IdempotencyKey}; use crate::worker_binding::RibInputValue; -use rib::{ParsedFunctionName, RibByteCode, RibFunctionInvoke, RibInterpreterResult}; +use rib::{RibByteCode, RibFunctionInvoke, RibInterpreterResult}; use crate::worker_bridge_execution::{ NoopWorkerRequestExecutor, WorkerRequest, WorkerRequestExecutor, From ae3058bd2bd82d775b988a2344a41d6be2d785f1 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Tue, 24 Sep 2024 12:28:20 +1000 Subject: [PATCH 14/27] Use function name --- golem-rib/src/compiler/byte_code.rs | 8 +- golem-rib/src/function_name.rs | 57 +++++---- golem-rib/src/interpreter/rib_interpreter.rs | 31 ++++- golem-rib/src/parser/call.rs | 34 ++--- .../type_inference/function_type_inference.rs | 116 ++++++++++++------ golem-rib/src/type_registry.rs | 21 ++-- 6 files changed, 177 insertions(+), 90 deletions(-) diff --git a/golem-rib/src/compiler/byte_code.rs b/golem-rib/src/compiler/byte_code.rs index 580724b13..278119c5d 100644 --- a/golem-rib/src/compiler/byte_code.rs +++ b/golem-rib/src/compiler/byte_code.rs @@ -303,7 +303,7 @@ mod internal { resource_params, } => { for param in resource_params { - stack.push(ExprState::from_expr(¶m.0)); + stack.push(ExprState::from_expr(¶m)); } instructions.push(RibIR::CreateFunctionName( site, @@ -319,7 +319,7 @@ mod internal { method, } => { for param in resource_params { - stack.push(ExprState::from_expr(¶m.0)); + stack.push(ExprState::from_expr(param)); } instructions.push(RibIR::CreateFunctionName( site, @@ -336,7 +336,7 @@ mod internal { method, } => { for param in resource_params { - stack.push(ExprState::from_expr(¶m.0)); + stack.push(ExprState::from_expr(param)); } instructions.push(RibIR::CreateFunctionName( site, @@ -352,7 +352,7 @@ mod internal { resource_params, } => { for param in resource_params { - stack.push(ExprState::from_expr(¶m.0)); + stack.push(ExprState::from_expr(param)); } instructions.push(RibIR::CreateFunctionName( site, diff --git a/golem-rib/src/function_name.rs b/golem-rib/src/function_name.rs index a833285ae..77e566cd3 100644 --- a/golem-rib/src/function_name.rs +++ b/golem-rib/src/function_name.rs @@ -311,21 +311,21 @@ pub enum DynamicParsedFunctionReference { }, IndexedResourceConstructor { resource: String, - resource_params: Vec, + resource_params: Vec, }, IndexedResourceMethod { resource: String, - resource_params: Vec, + resource_params: Vec, method: String, }, IndexedResourceStaticMethod { resource: String, - resource_params: Vec, + resource_params: Vec, method: String, }, IndexedResourceDrop { resource: String, - resource_params: Vec, + resource_params: Vec, }, } @@ -362,7 +362,7 @@ impl DynamicParsedFunctionReference { resource: resource.clone(), resource_params: resource_params .iter() - .map(|param| text::to_raw_string(¶m.0)) + .map(|param| text::to_raw_string(¶m)) .collect(), }, Self::IndexedResourceMethod { @@ -373,7 +373,7 @@ impl DynamicParsedFunctionReference { resource: resource.clone(), resource_params: resource_params .iter() - .map(|param| text::to_raw_string(¶m.0)) + .map(|param| text::to_raw_string(¶m)) .collect(), method: method.clone(), }, @@ -385,7 +385,7 @@ impl DynamicParsedFunctionReference { resource: resource.clone(), resource_params: resource_params .iter() - .map(|param| text::to_raw_string(¶m.0)) + .map(|param| text::to_raw_string(¶m)) .collect(), method: method.clone(), }, @@ -396,15 +396,25 @@ impl DynamicParsedFunctionReference { resource: resource.clone(), resource_params: resource_params .iter() - .map(|param| text::to_raw_string(¶m.0)) + .map(|param| text::to_raw_string(¶m)) .collect(), }, } } + + pub fn raw_resource_params(&mut self) -> Option<&mut Vec> { + match self { + Self::IndexedResourceConstructor { resource_params, .. } + | Self::IndexedResourceMethod { resource_params, .. } + | Self::IndexedResourceStaticMethod { resource_params, .. } + | Self::IndexedResourceDrop { resource_params, .. } => { + Some(resource_params) + } + _ => None + } + } } -#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] -pub struct ResourceParam(pub Expr); impl Display for ParsedFunctionReference { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -593,27 +603,27 @@ impl From DynamicParsedFunctionReference::IndexedResourceConstructor { resource, resource_params } => ProtoDynamicFunctionReference::IndexedResourceConstructor( golem_api_grpc::proto::golem::rib::DynamicIndexedResourceConstructorFunctionReference { resource, - resource_params: resource_params.into_iter().map(|x| x.0.into()).collect(), + resource_params: resource_params.into_iter().map(|x| x.into()).collect(), }, ), DynamicParsedFunctionReference::IndexedResourceMethod { resource, resource_params, method } => ProtoDynamicFunctionReference::IndexedResourceMethod( golem_api_grpc::proto::golem::rib::DynamicIndexedResourceMethodFunctionReference { resource, - resource_params: resource_params.into_iter().map(|x| x.0.into()).collect(), + resource_params: resource_params.into_iter().map(|x| x.into()).collect(), method, }, ), DynamicParsedFunctionReference::IndexedResourceStaticMethod { resource, resource_params, method } => ProtoDynamicFunctionReference::IndexedResourceStaticMethod( golem_api_grpc::proto::golem::rib::DynamicIndexedResourceStaticMethodFunctionReference { resource, - resource_params: resource_params.into_iter().map(|x| x.0.into()).collect(), + resource_params: resource_params.into_iter().map(|x| x.into()).collect(), method, }, ), DynamicParsedFunctionReference::IndexedResourceDrop { resource, resource_params } => ProtoDynamicFunctionReference::IndexedResourceDrop( golem_api_grpc::proto::golem::rib::DynamicIndexedResourceDropFunctionReference { resource, - resource_params: resource_params.into_iter().map(|x| x.0.into()).collect(), + resource_params: resource_params.into_iter().map(|x| x.into()).collect(), }, ), }; @@ -669,8 +679,8 @@ impl TryFrom resource_params }) => { - let resource_params: Vec = - resource_params.into_iter().map(|x| Expr::try_from(x).map(ResourceParam)).collect::, String>>()?; + let resource_params: Vec = + resource_params.into_iter().map(|x| Expr::try_from(x)).collect::, String>>()?; Ok(Self::IndexedResourceConstructor { resource, resource_params }) }, @@ -679,8 +689,8 @@ impl TryFrom resource_params, method }) => { - let resource_params: Vec = - resource_params.into_iter().map(|x| Expr::try_from(x).map(ResourceParam)).collect::, String>>()?; + let resource_params: Vec = + resource_params.into_iter().map(|x| Expr::try_from(x)).collect::, String>>()?; Ok(Self::IndexedResourceMethod { resource, resource_params, method }) }, @@ -689,8 +699,8 @@ impl TryFrom resource_params, method }) => { - let resource_params: Vec = - resource_params.into_iter().map(|x| Expr::try_from(x).map(ResourceParam)).collect::, String>>()?; + let resource_params: Vec = + resource_params.into_iter().map(|x| Expr::try_from(x)).collect::, String>>()?; Ok(Self::IndexedResourceStaticMethod { resource, resource_params, method }) }, @@ -698,8 +708,8 @@ impl TryFrom resource, resource_params }) => { - let resource_params: Vec = - resource_params.into_iter().map(|x| Expr::try_from(x).map(ResourceParam)).collect::, String>>()?; + let resource_params: Vec = + resource_params.into_iter().map(|x| Expr::try_from(x)).collect::, String>>()?; Ok(Self::IndexedResourceDrop { resource, resource_params }) }, @@ -905,7 +915,8 @@ impl DynamicParsedFunctionName { self.to_static().function.function_name() } - fn to_static(&self) -> ParsedFunctionName { + // + pub fn to_static(&self) -> ParsedFunctionName { ParsedFunctionName { site: self.site.clone(), function: self.function.to_static(), diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index 8e0a73d8a..43ea92e20 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -63,8 +63,6 @@ impl Interpreter { // O(1) to do this let mut instructions = VecDeque::from(instructions0.instructions); - dbg!(instructions.clone()); - while let Some(instruction) = instructions.pop_front() { match instruction { RibIR::PushLit(val) => { @@ -766,7 +764,6 @@ mod internal { argument_size: usize, interpreter: &mut Interpreter, ) -> Result<(), String> { - dbg!("is this executed?"); let function_name = interpreter .stack .pop_str() @@ -1365,6 +1362,34 @@ mod interpreter_tests { ); } + #[tokio::test] + async fn test_interpreter_for_dynamic_resource_parameters() { + let mut interpreter = Interpreter::default(); + + let input = internal::get_analysed_typ_str(); + + let analysed_exports = + internal::get_component_metadata("ns:name/interface.{resource1(\"hello\").new}", vec![input], AnalysedType::Str(TypeStr)); + + let expr = r#" + + let hello = "hello"; + let result = ns:name/interface.{resource1(hello).new}(hello); + result + + "#; + + let expr = Expr::from_text(expr).unwrap(); + let mut expr2 = expr.clone(); + let compiled = compiler::compile(&expr, &analysed_exports).unwrap(); + let result = interpreter.run(compiled.byte_code).await.unwrap(); + + assert_eq!( + result.get_val().unwrap(), + TypeAnnotatedValue::Str("foo 100 1 bar jak validate prod dev test".to_string()) + ); + } + #[tokio::test] async fn test_interpreter_for_pattern_match_on_tuple_with_all_types() { let mut interpreter = Interpreter::default(); diff --git a/golem-rib/src/parser/call.rs b/golem-rib/src/parser/call.rs index a3a71c241..5fd4127a4 100644 --- a/golem-rib/src/parser/call.rs +++ b/golem-rib/src/parser/call.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{DynamicParsedFunctionName, DynamicParsedFunctionReference, ResourceParam}; +use crate::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; use combine::error::Commit; use combine::parser::char::{alpha_num, string}; use combine::parser::char::{char, spaces}; @@ -120,21 +120,21 @@ where |((resource, resource_params), _, _)| { DynamicParsedFunctionReference::IndexedResourceConstructor { resource, - resource_params: resource_params.into_iter().map(ResourceParam).collect(), + resource_params } }, ); let indexed_drop_syntax = (indexed_resource_syntax(), token('.'), string("drop")).map( |((resource, resource_params), _, _)| DynamicParsedFunctionReference::IndexedResourceDrop { resource, - resource_params: resource_params.into_iter().map(ResourceParam).collect(), + resource_params }, ); let indexed_method_syntax = (indexed_resource_syntax(), token('.'), identifier()).map( |((resource, resource_params), _, method)| { DynamicParsedFunctionReference::IndexedResourceMethod { resource, - resource_params: resource_params.into_iter().map(ResourceParam).collect(), + resource_params, method, } }, @@ -215,7 +215,7 @@ where } #[cfg(test)] mod function_call_tests { - use crate::{DynamicParsedFunctionName, DynamicParsedFunctionReference, ResourceParam}; + use crate::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; use combine::EasyParser; use crate::expr::Expr; @@ -757,9 +757,9 @@ mod function_call_tests { function: DynamicParsedFunctionReference::IndexedResourceConstructor { resource: "resource1".to_string(), resource_params: vec![ - ResourceParam(Expr::literal("hello")), - ResourceParam(Expr::number(1f64)), - ResourceParam(Expr::boolean(true)), + Expr::literal("hello"), + Expr::number(1f64), + Expr::boolean(true), ], }, }, @@ -787,11 +787,11 @@ mod function_call_tests { function: DynamicParsedFunctionReference::IndexedResourceConstructor { resource: "resource1".to_string(), resource_params: vec![ - ResourceParam(Expr::literal("hello")), - ResourceParam(Expr::record(vec![( + Expr::literal("hello"), + Expr::record(vec![( "field-a".to_string(), Expr::option(Some(Expr::number(1f64))), - )])), + )]), ], }, }, @@ -965,9 +965,9 @@ mod function_call_tests { function: DynamicParsedFunctionReference::IndexedResourceDrop { resource: "resource1".to_string(), resource_params: vec![ - ResourceParam(Expr::literal("hello")), - ResourceParam(Expr::number(1f64)), - ResourceParam(Expr::boolean(true)), + Expr::literal("hello"), + Expr::number(1f64), + Expr::boolean(true), ], }, }, @@ -995,11 +995,11 @@ mod function_call_tests { function: DynamicParsedFunctionReference::IndexedResourceDrop { resource: "resource1".to_string(), resource_params: vec![ - ResourceParam(Expr::literal("hello")), - ResourceParam(Expr::record(vec![( + Expr::literal("hello"), + Expr::record(vec![( "field-a".to_string(), Expr::option(Some(Expr::number(1f64))), - )])), + )]), ], }, }, diff --git a/golem-rib/src/type_inference/function_type_inference.rs b/golem-rib/src/type_inference/function_type_inference.rs index bef3fdd5f..caf3eb14d 100644 --- a/golem-rib/src/type_inference/function_type_inference.rs +++ b/golem-rib/src/type_inference/function_type_inference.rs @@ -15,6 +15,7 @@ use crate::type_registry::{FunctionTypeRegistry, RegistryKey, RegistryValue}; use crate::{Expr, InferredType}; use std::collections::VecDeque; +use crate::call_type::CallType; pub fn infer_function_types( expr: &mut Expr, @@ -25,40 +26,7 @@ pub fn infer_function_types( while let Some(expr) = queue.pop_back() { match expr { Expr::Call(parsed_fn_name, args, inferred_type) => { - let key = RegistryKey::from_invocation_name(parsed_fn_name); - if let Some(value) = function_type_registry.types.get(&key) { - match value { - RegistryValue::Value(_) => {} - RegistryValue::Function { - parameter_types, - return_types, - } => { - if parameter_types.len() == args.len() { - for (arg, param_type) in args.iter_mut().zip(parameter_types) { - internal::check_function_arguments(param_type, arg)?; - arg.add_infer_type_mut(param_type.clone().into()); - arg.push_types_down()? - } - *inferred_type = { - if return_types.len() == 1 { - return_types[0].clone().into() - } else { - InferredType::Sequence( - return_types.iter().map(|t| t.clone().into()).collect(), - ) - } - } - } else { - return Err(format!( - "Function {} expects {} arguments, but {} were provided", - parsed_fn_name, - parameter_types.len(), - args.len() - )); - } - } - } - } + internal::resolve_call_expressions(parsed_fn_name, function_type_registry, args, inferred_type)?; } _ => expr.visit_children_mut_bottom_up(&mut queue), } @@ -68,8 +36,86 @@ pub fn infer_function_types( } mod internal { - use crate::Expr; + use crate::{DynamicParsedFunctionName, Expr, FunctionTypeRegistry, InferredType, RegistryKey, RegistryValue}; use golem_wasm_ast::analysis::AnalysedType; + use crate::call_type::CallType; + + pub(crate) fn resolve_call_expressions(call_type: &mut CallType, function_type_registry: &FunctionTypeRegistry, args: &mut Vec, inferred_type: &mut InferredType) -> Result<(), String>{ + match call_type { + CallType::Function(dynamic_parsed_function_name) => { + let function = dynamic_parsed_function_name.clone().to_static().function; + let indexed_resource = function.is_indexed_resource(); + + if indexed_resource { + // Inferring th types of the resource parameters + let constructor = + function.resource_name().ok_or("Resource name not found")?; + + let mut constructor_params = + dynamic_parsed_function_name + .function + .raw_resource_params().ok_or("Resource params not found")?; + + let registry_key = RegistryKey::FunctionName(constructor.clone()); + infer_types(constructor.as_str(), function_type_registry, registry_key, &mut constructor_params, inferred_type)?; + + // Inferring the types of the final method in the resource + let resource_method_name = function.function_name(); + let registry_key = RegistryKey::FunctionName(resource_method_name.clone()); + infer_types(resource_method_name.as_str(), function_type_registry, registry_key, args, inferred_type) + } + + else { + let registry_key = RegistryKey::from_invocation_name(call_type); + + infer_types(function.function_name().as_str(), function_type_registry, registry_key, args, inferred_type) + } + } + + // This will never happen unless variant identification phase happens before functions identification phase + _ => panic!("Enum constructor not supported"), + } + } + + pub(crate) fn infer_types(function_name: &str, function_type_registry: &FunctionTypeRegistry, key: RegistryKey, args: &mut Vec, inferred_type: &mut InferredType) -> Result<(), String> { + if let Some(value) = function_type_registry.types.get(&key) { + match value { + RegistryValue::Value(_) => {} + RegistryValue::Function { + parameter_types, + return_types, + } => { + if parameter_types.len() == args.len() { + for (arg, param_type) in args.iter_mut().zip(parameter_types) { + check_function_arguments(param_type, arg)?; + arg.add_infer_type_mut(param_type.clone().into()); + arg.push_types_down()? + } + + *inferred_type = { + if return_types.len() == 1 { + return_types[0].clone().into() + } else { + InferredType::Sequence( + return_types.iter().map(|t| t.clone().into()).collect(), + ) + } + } + + } else { + return Err(format!( + "Function {} expects {} arguments, but {} were provided", + function_name, + parameter_types.len(), + args.len() + )); + } + } + } + } + + Ok(()) + } // A preliminary check of the arguments passed before typ inference pub(crate) fn check_function_arguments( diff --git a/golem-rib/src/type_registry.rs b/golem-rib/src/type_registry.rs index cc1f85aa9..85ef4cce6 100644 --- a/golem-rib/src/type_registry.rs +++ b/golem-rib/src/type_registry.rs @@ -16,6 +16,7 @@ use crate::call_type::CallType; use golem_wasm_ast::analysis::AnalysedExport; use golem_wasm_ast::analysis::AnalysedType; use std::collections::{HashMap, HashSet}; +use crate::{ParsedFunctionName, ParsedFunctionReference}; // A type-registry is a mapping from a function name (global or part of an interface in WIT) // to the registry value that represents the type of the name. @@ -43,13 +44,17 @@ impl RegistryKey { CallType::VariantConstructor(variant_name) => { RegistryKey::VariantName(variant_name.clone()) } - CallType::EnumConstructor(enum_name) => RegistryKey::EnumName(enum_name.clone()), - CallType::Function(function_name) => match function_name.site.interface_name() { - None => RegistryKey::FunctionName(function_name.function_name()), - Some(interface_name) => RegistryKey::FunctionNameWithInterface { - interface_name: interface_name.to_string(), - function_name: function_name.function_name(), - }, + CallType::EnumConstructor(enum_name) => { + RegistryKey::EnumName(enum_name.clone()) + }, + CallType::Function(function_name) => { + match function_name.site.interface_name() { + None => RegistryKey::FunctionName(function_name.function_name()), + Some(interface_name) => RegistryKey::FunctionNameWithInterface { + interface_name: interface_name.to_string(), + function_name: function_name.function_name(), + }, + } }, } } @@ -64,7 +69,7 @@ pub enum RegistryValue { }, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct FunctionTypeRegistry { pub types: HashMap, } From 74d89450970a276635a9b46335e5ebe1c30fe0b3 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Tue, 24 Sep 2024 13:58:29 +1000 Subject: [PATCH 15/27] Write test for indexed function --- golem-rib/src/interpreter/rib_interpreter.rs | 267 ++++++++++++++++-- .../type_inference/function_type_inference.rs | 32 ++- golem-rib/src/type_registry.rs | 12 +- 3 files changed, 272 insertions(+), 39 deletions(-) diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index 43ea92e20..5d6ebcf5a 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -1362,34 +1362,6 @@ mod interpreter_tests { ); } - #[tokio::test] - async fn test_interpreter_for_dynamic_resource_parameters() { - let mut interpreter = Interpreter::default(); - - let input = internal::get_analysed_typ_str(); - - let analysed_exports = - internal::get_component_metadata("ns:name/interface.{resource1(\"hello\").new}", vec![input], AnalysedType::Str(TypeStr)); - - let expr = r#" - - let hello = "hello"; - let result = ns:name/interface.{resource1(hello).new}(hello); - result - - "#; - - let expr = Expr::from_text(expr).unwrap(); - let mut expr2 = expr.clone(); - let compiled = compiler::compile(&expr, &analysed_exports).unwrap(); - let result = interpreter.run(compiled.byte_code).await.unwrap(); - - assert_eq!( - result.get_val().unwrap(), - TypeAnnotatedValue::Str("foo 100 1 bar jak validate prod dev test".to_string()) - ); - } - #[tokio::test] async fn test_interpreter_for_pattern_match_on_tuple_with_all_types() { let mut interpreter = Interpreter::default(); @@ -1454,6 +1426,31 @@ mod interpreter_tests { ); } + #[tokio::test] + async fn test_interpreter_with_indexed_resource() { + let mut interpreter = Interpreter::default(); + + let input = internal::get_analysed_typ_str(); + + let analysed_exports = + internal::get_component_metadata_with_indexed_resource(); + + let expr = r#" + golem:it/api.{cart("hello").checkout}(); + "success" + "#; + + let expr = Expr::from_text(expr).unwrap(); + let mut expr2 = expr.clone(); + let compiled = compiler::compile(&expr, &analysed_exports).unwrap(); + let result = interpreter.run(compiled.byte_code).await.unwrap(); + + assert_eq!( + result.get_val().unwrap(), + TypeAnnotatedValue::Str("success".to_string()) + ); + } + mod internal { use golem_wasm_ast::analysis::*; @@ -1564,5 +1561,219 @@ mod interpreter_tests { }], })] } + + + pub(crate) fn get_component_metadata_with_indexed_resource() -> Vec { + + let instance = AnalysedExport::Instance( + AnalysedInstance { + name: "golem:it/api".to_string(), + functions: vec![ + AnalysedFunction { + name: "[constructor]cart".to_string(), + parameters: vec![ + AnalysedFunctionParameter { + name: "user-id".to_string(), + typ: AnalysedType::Str(TypeStr) + } + ], + results: vec![ + AnalysedFunctionResult { + name: None, + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Owned + }) + } + ] + }, + AnalysedFunction { + name: "[method]cart.add-item".to_string(), + parameters: vec![ + AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed + }) + }, + AnalysedFunctionParameter { + name: "item".to_string(), + typ: AnalysedType::Record(TypeRecord { + fields: vec![ + NameTypePair { + name: "product-id".to_string(), + typ: AnalysedType::Str(TypeStr) + }, + NameTypePair { + name: "name".to_string(), + typ: AnalysedType::Str(TypeStr) + }, + NameTypePair { + name: "price".to_string(), + typ: AnalysedType::F32(TypeF32) + }, + NameTypePair { + name: "quantity".to_string(), + typ: AnalysedType::U32(TypeU32) + } + ] + }) + } + ], + results: vec![] + }, + AnalysedFunction { + name: "[method]cart.remove-item".to_string(), + parameters: vec![ + AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed + }) + }, + AnalysedFunctionParameter { + name: "product-id".to_string(), + typ: AnalysedType::Str(TypeStr) + } + ], + results: vec![] + }, + AnalysedFunction { + name: "[method]cart.update-item-quantity".to_string(), + parameters: vec![ + AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed + }) + }, + AnalysedFunctionParameter { + name: "product-id".to_string(), + typ: AnalysedType::Str(TypeStr) + }, + AnalysedFunctionParameter { + name: "quantity".to_string(), + typ: AnalysedType::U32(TypeU32) + } + ], + results: vec![] + }, + AnalysedFunction { + name: "[method]cart.checkout".to_string(), + parameters: vec![ + AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed + }) + } + ], + results: vec![ + AnalysedFunctionResult { + name: None, + typ: AnalysedType::Variant(TypeVariant { + cases: vec![ + NameOptionTypePair { + name: "error".to_string(), + typ: Some(AnalysedType::Str(TypeStr)) + }, + NameOptionTypePair { + name: "success".to_string(), + typ: Some(AnalysedType::Record(TypeRecord { + fields: vec![ + NameTypePair { + name: "order-id".to_string(), + typ: AnalysedType::Str(TypeStr) + } + ] + })) + } + ] + }) + } + ] + }, + AnalysedFunction { + name: "[method]cart.get-cart-contents".to_string(), + parameters: vec![ + AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed + }) + } + ], + results: vec![ + AnalysedFunctionResult { + name: None, + typ: AnalysedType::List(TypeList { + inner: Box::new(AnalysedType::Record(TypeRecord { + fields: vec![ + NameTypePair { + name: "product-id".to_string(), + typ: AnalysedType::Str(TypeStr) + }, + NameTypePair { + name: "name".to_string(), + typ: AnalysedType::Str(TypeStr) + }, + NameTypePair { + name: "price".to_string(), + typ: AnalysedType::F32(TypeF32) + }, + NameTypePair { + name: "quantity".to_string(), + typ: AnalysedType::U32(TypeU32) + } + ] + })) + }) + } + ] + }, + AnalysedFunction { + name: "[method]cart.merge-with".to_string(), + parameters: vec![ + AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed + }) + }, + AnalysedFunctionParameter { + name: "other-cart".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed + }) + } + ], + results: vec![] + }, + AnalysedFunction { + name: "[drop]cart".to_string(), + parameters: vec![ + AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Owned + }) + } + ], + results: vec![] + } + ] + } + ); + + vec![instance] + } } } diff --git a/golem-rib/src/type_inference/function_type_inference.rs b/golem-rib/src/type_inference/function_type_inference.rs index caf3eb14d..ff76f7888 100644 --- a/golem-rib/src/type_inference/function_type_inference.rs +++ b/golem-rib/src/type_inference/function_type_inference.rs @@ -43,32 +43,37 @@ mod internal { pub(crate) fn resolve_call_expressions(call_type: &mut CallType, function_type_registry: &FunctionTypeRegistry, args: &mut Vec, inferred_type: &mut InferredType) -> Result<(), String>{ match call_type { CallType::Function(dynamic_parsed_function_name) => { - let function = dynamic_parsed_function_name.clone().to_static().function; + let parsed_function_static = dynamic_parsed_function_name.clone().to_static(); + let function = parsed_function_static.function; let indexed_resource = function.is_indexed_resource(); if indexed_resource { // Inferring th types of the resource parameters - let constructor = - function.resource_name().ok_or("Resource name not found")?; + let constructor = { + let raw_str = function.resource_name().ok_or("Resource name not found")?; + format!["[constructor]{}", raw_str] + }; let mut constructor_params = dynamic_parsed_function_name .function .raw_resource_params().ok_or("Resource params not found")?; - let registry_key = RegistryKey::FunctionName(constructor.clone()); - infer_types(constructor.as_str(), function_type_registry, registry_key, &mut constructor_params, inferred_type)?; + let registry_key = RegistryKey::from_function_name(&parsed_function_static.site, constructor.as_str()); + + infer_types(constructor.as_str(), function_type_registry, registry_key, &mut constructor_params, inferred_type, false)?; // Inferring the types of the final method in the resource let resource_method_name = function.function_name(); - let registry_key = RegistryKey::FunctionName(resource_method_name.clone()); - infer_types(resource_method_name.as_str(), function_type_registry, registry_key, args, inferred_type) + let registry_key = RegistryKey::from_function_name(&parsed_function_static.site, resource_method_name.as_str()); + + infer_types(resource_method_name.as_str(), function_type_registry, registry_key, args, inferred_type, true) } else { let registry_key = RegistryKey::from_invocation_name(call_type); - infer_types(function.function_name().as_str(), function_type_registry, registry_key, args, inferred_type) + infer_types(function.function_name().as_str(), function_type_registry, registry_key, args, inferred_type, false) } } @@ -77,7 +82,7 @@ mod internal { } } - pub(crate) fn infer_types(function_name: &str, function_type_registry: &FunctionTypeRegistry, key: RegistryKey, args: &mut Vec, inferred_type: &mut InferredType) -> Result<(), String> { + pub(crate) fn infer_types(function_name: &str, function_type_registry: &FunctionTypeRegistry, key: RegistryKey, args: &mut Vec, inferred_type: &mut InferredType, is_resource_method: bool) -> Result<(), String> { if let Some(value) = function_type_registry.types.get(&key) { match value { RegistryValue::Value(_) => {} @@ -85,9 +90,16 @@ mod internal { parameter_types, return_types, } => { + let mut parameter_types = parameter_types.clone(); + if is_resource_method { + parameter_types = parameter_types.iter().filter(|t| match t { + AnalysedType::Handle(_) => false, + _ => true, + }).cloned().collect(); + } if parameter_types.len() == args.len() { for (arg, param_type) in args.iter_mut().zip(parameter_types) { - check_function_arguments(param_type, arg)?; + check_function_arguments(¶m_type, arg)?; arg.add_infer_type_mut(param_type.clone().into()); arg.push_types_down()? } diff --git a/golem-rib/src/type_registry.rs b/golem-rib/src/type_registry.rs index 85ef4cce6..459a8ffc5 100644 --- a/golem-rib/src/type_registry.rs +++ b/golem-rib/src/type_registry.rs @@ -16,7 +16,7 @@ use crate::call_type::CallType; use golem_wasm_ast::analysis::AnalysedExport; use golem_wasm_ast::analysis::AnalysedType; use std::collections::{HashMap, HashSet}; -use crate::{ParsedFunctionName, ParsedFunctionReference}; +use crate::{ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite}; // A type-registry is a mapping from a function name (global or part of an interface in WIT) // to the registry value that represents the type of the name. @@ -39,6 +39,16 @@ pub enum RegistryKey { } impl RegistryKey { + + pub fn from_function_name(site: &ParsedFunctionSite, function_name: &str) -> RegistryKey { + match site.interface_name() { + None => RegistryKey::FunctionName(function_name.to_string()), + Some(name) => RegistryKey::FunctionNameWithInterface { + interface_name: name.to_string(), + function_name: function_name.to_string(), + }, + } + } pub fn from_invocation_name(invocation_name: &CallType) -> RegistryKey { match invocation_name { CallType::VariantConstructor(variant_name) => { From 5f69c0c9e1a325f6b9fb0101c017c714e30bd949 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Tue, 24 Sep 2024 15:07:42 +1000 Subject: [PATCH 16/27] Make sure resource params are created --- golem-rib/src/compiler/byte_code.rs | 2 +- golem-rib/src/function_name.rs | 67 +-- golem-rib/src/interpreter/env.rs | 9 + golem-rib/src/interpreter/rib_interpreter.rs | 414 +++++++++--------- golem-rib/src/parser/call.rs | 10 +- golem-rib/src/type_inference/expr_visitor.rs | 43 +- .../type_inference/function_type_inference.rs | 103 +++-- golem-rib/src/type_registry.rs | 21 +- 8 files changed, 371 insertions(+), 298 deletions(-) diff --git a/golem-rib/src/compiler/byte_code.rs b/golem-rib/src/compiler/byte_code.rs index 278119c5d..8894f604b 100644 --- a/golem-rib/src/compiler/byte_code.rs +++ b/golem-rib/src/compiler/byte_code.rs @@ -303,7 +303,7 @@ mod internal { resource_params, } => { for param in resource_params { - stack.push(ExprState::from_expr(¶m)); + stack.push(ExprState::from_expr(param)); } instructions.push(RibIR::CreateFunctionName( site, diff --git a/golem-rib/src/function_name.rs b/golem-rib/src/function_name.rs index 77e566cd3..8233f0696 100644 --- a/golem-rib/src/function_name.rs +++ b/golem-rib/src/function_name.rs @@ -360,10 +360,7 @@ impl DynamicParsedFunctionReference { resource_params, } => ParsedFunctionReference::IndexedResourceConstructor { resource: resource.clone(), - resource_params: resource_params - .iter() - .map(|param| text::to_raw_string(¶m)) - .collect(), + resource_params: resource_params.iter().map(text::to_raw_string).collect(), }, Self::IndexedResourceMethod { resource, @@ -371,10 +368,7 @@ impl DynamicParsedFunctionReference { method, } => ParsedFunctionReference::IndexedResourceMethod { resource: resource.clone(), - resource_params: resource_params - .iter() - .map(|param| text::to_raw_string(¶m)) - .collect(), + resource_params: resource_params.iter().map(text::to_raw_string).collect(), method: method.clone(), }, Self::IndexedResourceStaticMethod { @@ -383,10 +377,7 @@ impl DynamicParsedFunctionReference { method, } => ParsedFunctionReference::IndexedResourceStaticMethod { resource: resource.clone(), - resource_params: resource_params - .iter() - .map(|param| text::to_raw_string(¶m)) - .collect(), + resource_params: resource_params.iter().map(text::to_raw_string).collect(), method: method.clone(), }, Self::IndexedResourceDrop { @@ -394,27 +385,47 @@ impl DynamicParsedFunctionReference { resource_params, } => ParsedFunctionReference::IndexedResourceDrop { resource: resource.clone(), - resource_params: resource_params - .iter() - .map(|param| text::to_raw_string(¶m)) - .collect(), + resource_params: resource_params.iter().map(text::to_raw_string).collect(), }, } } - pub fn raw_resource_params(&mut self) -> Option<&mut Vec> { + pub fn raw_resource_params_mut(&mut self) -> Option<&mut Vec> { match self { - Self::IndexedResourceConstructor { resource_params, .. } - | Self::IndexedResourceMethod { resource_params, .. } - | Self::IndexedResourceStaticMethod { resource_params, .. } - | Self::IndexedResourceDrop { resource_params, .. } => { - Some(resource_params) + Self::IndexedResourceConstructor { + resource_params, .. + } + | Self::IndexedResourceMethod { + resource_params, .. + } + | Self::IndexedResourceStaticMethod { + resource_params, .. } - _ => None + | Self::IndexedResourceDrop { + resource_params, .. + } => Some(resource_params), + _ => None, } } -} + pub fn raw_resource_params(&self) -> Option<&Vec> { + match self { + Self::IndexedResourceConstructor { + resource_params, .. + } + | Self::IndexedResourceMethod { + resource_params, .. + } + | Self::IndexedResourceStaticMethod { + resource_params, .. + } + | Self::IndexedResourceDrop { + resource_params, .. + } => Some(resource_params), + _ => None, + } + } +} impl Display for ParsedFunctionReference { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -680,7 +691,7 @@ impl TryFrom }) => { let resource_params: Vec = - resource_params.into_iter().map(|x| Expr::try_from(x)).collect::, String>>()?; + resource_params.into_iter().map(Expr::try_from).collect::, String>>()?; Ok(Self::IndexedResourceConstructor { resource, resource_params }) }, @@ -690,7 +701,7 @@ impl TryFrom method }) => { let resource_params: Vec = - resource_params.into_iter().map(|x| Expr::try_from(x)).collect::, String>>()?; + resource_params.into_iter().map(Expr::try_from).collect::, String>>()?; Ok(Self::IndexedResourceMethod { resource, resource_params, method }) }, @@ -700,7 +711,7 @@ impl TryFrom method }) => { let resource_params: Vec = - resource_params.into_iter().map(|x| Expr::try_from(x)).collect::, String>>()?; + resource_params.into_iter().map(Expr::try_from).collect::, String>>()?; Ok(Self::IndexedResourceStaticMethod { resource, resource_params, method }) }, @@ -709,7 +720,7 @@ impl TryFrom resource_params }) => { let resource_params: Vec = - resource_params.into_iter().map(|x| Expr::try_from(x)).collect::, String>>()?; + resource_params.into_iter().map(Expr::try_from).collect::, String>>()?; Ok(Self::IndexedResourceDrop { resource, resource_params }) }, diff --git a/golem-rib/src/interpreter/env.rs b/golem-rib/src/interpreter/env.rs index 0428ecbaf..834088725 100644 --- a/golem-rib/src/interpreter/env.rs +++ b/golem-rib/src/interpreter/env.rs @@ -16,6 +16,7 @@ use crate::interpreter::result::RibInterpreterResult; use crate::VariableId; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use std::collections::HashMap; +use std::fmt::Debug; use std::future::Future; use std::pin::Pin; use std::sync::Arc; @@ -25,6 +26,14 @@ pub struct InterpreterEnv { pub call_worker_function_async: RibFunctionInvoke, } +impl Debug for InterpreterEnv { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.debug_struct("InterpreterEnv") + .field("env", &self.env) + .finish() + } +} + pub type RibFunctionInvoke = Arc< dyn Fn( String, diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index 5d6ebcf5a..bd006ed36 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -19,6 +19,7 @@ use crate::{RibByteCode, RibIR}; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use std::collections::{HashMap, VecDeque}; +#[derive(Debug)] pub struct Interpreter { pub stack: InterpreterStack, pub env: InterpreterEnv, @@ -63,6 +64,8 @@ impl Interpreter { // O(1) to do this let mut instructions = VecDeque::from(instructions0.instructions); + dbg!(instructions.clone()); + while let Some(instruction) = instructions.pop_front() { match instruction { RibIR::PushLit(val) => { @@ -116,6 +119,7 @@ impl Interpreter { } RibIR::LoadVar(variable_id) => { + dbg!("here?? {}", self.stack.clone(), &self.env); internal::run_load_var_instruction(variable_id, self)?; } @@ -625,6 +629,7 @@ mod internal { .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); } FunctionReferenceType::IndexedResourceConstructor(resource, resource_params_size) => { + dbg!("here??"); let last_n_elements = interpreter .stack .pop_n(resource_params_size) @@ -769,6 +774,8 @@ mod internal { .pop_str() .ok_or("Failed to get a function name from the stack".to_string())?; + dbg!(function_name.clone()); + let last_n_elements = interpreter .stack .pop_n(argument_size) @@ -1430,18 +1437,15 @@ mod interpreter_tests { async fn test_interpreter_with_indexed_resource() { let mut interpreter = Interpreter::default(); - let input = internal::get_analysed_typ_str(); - - let analysed_exports = - internal::get_component_metadata_with_indexed_resource(); + let analysed_exports = internal::get_component_metadata_with_indexed_resource(); let expr = r#" - golem:it/api.{cart("hello").checkout}(); + let x = "user"; + golem:it/api.{cart(x).checkout}(); "success" "#; let expr = Expr::from_text(expr).unwrap(); - let mut expr2 = expr.clone(); let compiled = compiler::compile(&expr, &analysed_exports).unwrap(); let result = interpreter.run(compiled.byte_code).await.unwrap(); @@ -1562,216 +1566,196 @@ mod interpreter_tests { })] } - pub(crate) fn get_component_metadata_with_indexed_resource() -> Vec { - - let instance = AnalysedExport::Instance( - AnalysedInstance { - name: "golem:it/api".to_string(), - functions: vec![ - AnalysedFunction { - name: "[constructor]cart".to_string(), - parameters: vec![ - AnalysedFunctionParameter { - name: "user-id".to_string(), - typ: AnalysedType::Str(TypeStr) - } - ], - results: vec![ - AnalysedFunctionResult { - name: None, - typ: AnalysedType::Handle(TypeHandle { - resource_id: AnalysedResourceId(0), - mode: AnalysedResourceMode::Owned - }) - } - ] - }, - AnalysedFunction { - name: "[method]cart.add-item".to_string(), - parameters: vec![ - AnalysedFunctionParameter { - name: "self".to_string(), - typ: AnalysedType::Handle(TypeHandle { - resource_id: AnalysedResourceId(0), - mode: AnalysedResourceMode::Borrowed - }) - }, - AnalysedFunctionParameter { - name: "item".to_string(), - typ: AnalysedType::Record(TypeRecord { - fields: vec![ - NameTypePair { - name: "product-id".to_string(), - typ: AnalysedType::Str(TypeStr) - }, - NameTypePair { - name: "name".to_string(), - typ: AnalysedType::Str(TypeStr) - }, - NameTypePair { - name: "price".to_string(), - typ: AnalysedType::F32(TypeF32) - }, - NameTypePair { - name: "quantity".to_string(), - typ: AnalysedType::U32(TypeU32) - } - ] - }) - } - ], - results: vec![] - }, - AnalysedFunction { - name: "[method]cart.remove-item".to_string(), - parameters: vec![ - AnalysedFunctionParameter { - name: "self".to_string(), - typ: AnalysedType::Handle(TypeHandle { - resource_id: AnalysedResourceId(0), - mode: AnalysedResourceMode::Borrowed - }) - }, - AnalysedFunctionParameter { - name: "product-id".to_string(), - typ: AnalysedType::Str(TypeStr) - } - ], - results: vec![] - }, - AnalysedFunction { - name: "[method]cart.update-item-quantity".to_string(), - parameters: vec![ - AnalysedFunctionParameter { - name: "self".to_string(), - typ: AnalysedType::Handle(TypeHandle { - resource_id: AnalysedResourceId(0), - mode: AnalysedResourceMode::Borrowed - }) - }, - AnalysedFunctionParameter { - name: "product-id".to_string(), - typ: AnalysedType::Str(TypeStr) - }, - AnalysedFunctionParameter { - name: "quantity".to_string(), - typ: AnalysedType::U32(TypeU32) - } - ], - results: vec![] - }, - AnalysedFunction { - name: "[method]cart.checkout".to_string(), - parameters: vec![ - AnalysedFunctionParameter { - name: "self".to_string(), - typ: AnalysedType::Handle(TypeHandle { - resource_id: AnalysedResourceId(0), - mode: AnalysedResourceMode::Borrowed - }) - } - ], - results: vec![ - AnalysedFunctionResult { - name: None, - typ: AnalysedType::Variant(TypeVariant { - cases: vec![ - NameOptionTypePair { - name: "error".to_string(), - typ: Some(AnalysedType::Str(TypeStr)) - }, - NameOptionTypePair { - name: "success".to_string(), - typ: Some(AnalysedType::Record(TypeRecord { - fields: vec![ - NameTypePair { - name: "order-id".to_string(), - typ: AnalysedType::Str(TypeStr) - } - ] - })) - } - ] - }) - } - ] - }, - AnalysedFunction { - name: "[method]cart.get-cart-contents".to_string(), - parameters: vec![ - AnalysedFunctionParameter { - name: "self".to_string(), - typ: AnalysedType::Handle(TypeHandle { - resource_id: AnalysedResourceId(0), - mode: AnalysedResourceMode::Borrowed - }) - } - ], - results: vec![ - AnalysedFunctionResult { - name: None, - typ: AnalysedType::List(TypeList { - inner: Box::new(AnalysedType::Record(TypeRecord { - fields: vec![ - NameTypePair { - name: "product-id".to_string(), - typ: AnalysedType::Str(TypeStr) - }, - NameTypePair { - name: "name".to_string(), - typ: AnalysedType::Str(TypeStr) - }, - NameTypePair { - name: "price".to_string(), - typ: AnalysedType::F32(TypeF32) - }, - NameTypePair { - name: "quantity".to_string(), - typ: AnalysedType::U32(TypeU32) - } - ] - })) - }) - } - ] - }, - AnalysedFunction { - name: "[method]cart.merge-with".to_string(), - parameters: vec![ - AnalysedFunctionParameter { - name: "self".to_string(), - typ: AnalysedType::Handle(TypeHandle { - resource_id: AnalysedResourceId(0), - mode: AnalysedResourceMode::Borrowed - }) - }, - AnalysedFunctionParameter { - name: "other-cart".to_string(), - typ: AnalysedType::Handle(TypeHandle { - resource_id: AnalysedResourceId(0), - mode: AnalysedResourceMode::Borrowed - }) - } - ], - results: vec![] - }, - AnalysedFunction { - name: "[drop]cart".to_string(), - parameters: vec![ - AnalysedFunctionParameter { - name: "self".to_string(), - typ: AnalysedType::Handle(TypeHandle { - resource_id: AnalysedResourceId(0), - mode: AnalysedResourceMode::Owned - }) - } - ], - results: vec![] - } - ] - } - ); + let instance = AnalysedExport::Instance(AnalysedInstance { + name: "golem:it/api".to_string(), + functions: vec![ + AnalysedFunction { + name: "[constructor]cart".to_string(), + parameters: vec![AnalysedFunctionParameter { + name: "user-id".to_string(), + typ: AnalysedType::Str(TypeStr), + }], + results: vec![AnalysedFunctionResult { + name: None, + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Owned, + }), + }], + }, + AnalysedFunction { + name: "[method]cart.add-item".to_string(), + parameters: vec![ + AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed, + }), + }, + AnalysedFunctionParameter { + name: "item".to_string(), + typ: AnalysedType::Record(TypeRecord { + fields: vec![ + NameTypePair { + name: "product-id".to_string(), + typ: AnalysedType::Str(TypeStr), + }, + NameTypePair { + name: "name".to_string(), + typ: AnalysedType::Str(TypeStr), + }, + NameTypePair { + name: "price".to_string(), + typ: AnalysedType::F32(TypeF32), + }, + NameTypePair { + name: "quantity".to_string(), + typ: AnalysedType::U32(TypeU32), + }, + ], + }), + }, + ], + results: vec![], + }, + AnalysedFunction { + name: "[method]cart.remove-item".to_string(), + parameters: vec![ + AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed, + }), + }, + AnalysedFunctionParameter { + name: "product-id".to_string(), + typ: AnalysedType::Str(TypeStr), + }, + ], + results: vec![], + }, + AnalysedFunction { + name: "[method]cart.update-item-quantity".to_string(), + parameters: vec![ + AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed, + }), + }, + AnalysedFunctionParameter { + name: "product-id".to_string(), + typ: AnalysedType::Str(TypeStr), + }, + AnalysedFunctionParameter { + name: "quantity".to_string(), + typ: AnalysedType::U32(TypeU32), + }, + ], + results: vec![], + }, + AnalysedFunction { + name: "[method]cart.checkout".to_string(), + parameters: vec![AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed, + }), + }], + results: vec![AnalysedFunctionResult { + name: None, + typ: AnalysedType::Variant(TypeVariant { + cases: vec![ + NameOptionTypePair { + name: "error".to_string(), + typ: Some(AnalysedType::Str(TypeStr)), + }, + NameOptionTypePair { + name: "success".to_string(), + typ: Some(AnalysedType::Record(TypeRecord { + fields: vec![NameTypePair { + name: "order-id".to_string(), + typ: AnalysedType::Str(TypeStr), + }], + })), + }, + ], + }), + }], + }, + AnalysedFunction { + name: "[method]cart.get-cart-contents".to_string(), + parameters: vec![AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed, + }), + }], + results: vec![AnalysedFunctionResult { + name: None, + typ: AnalysedType::List(TypeList { + inner: Box::new(AnalysedType::Record(TypeRecord { + fields: vec![ + NameTypePair { + name: "product-id".to_string(), + typ: AnalysedType::Str(TypeStr), + }, + NameTypePair { + name: "name".to_string(), + typ: AnalysedType::Str(TypeStr), + }, + NameTypePair { + name: "price".to_string(), + typ: AnalysedType::F32(TypeF32), + }, + NameTypePair { + name: "quantity".to_string(), + typ: AnalysedType::U32(TypeU32), + }, + ], + })), + }), + }], + }, + AnalysedFunction { + name: "[method]cart.merge-with".to_string(), + parameters: vec![ + AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed, + }), + }, + AnalysedFunctionParameter { + name: "other-cart".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Borrowed, + }), + }, + ], + results: vec![], + }, + AnalysedFunction { + name: "[drop]cart".to_string(), + parameters: vec![AnalysedFunctionParameter { + name: "self".to_string(), + typ: AnalysedType::Handle(TypeHandle { + resource_id: AnalysedResourceId(0), + mode: AnalysedResourceMode::Owned, + }), + }], + results: vec![], + }, + ], + }); vec![instance] } diff --git a/golem-rib/src/parser/call.rs b/golem-rib/src/parser/call.rs index 5fd4127a4..b29012c38 100644 --- a/golem-rib/src/parser/call.rs +++ b/golem-rib/src/parser/call.rs @@ -120,14 +120,14 @@ where |((resource, resource_params), _, _)| { DynamicParsedFunctionReference::IndexedResourceConstructor { resource, - resource_params + resource_params, } }, ); let indexed_drop_syntax = (indexed_resource_syntax(), token('.'), string("drop")).map( |((resource, resource_params), _, _)| DynamicParsedFunctionReference::IndexedResourceDrop { resource, - resource_params + resource_params, }, ); let indexed_method_syntax = (indexed_resource_syntax(), token('.'), identifier()).map( @@ -757,9 +757,9 @@ mod function_call_tests { function: DynamicParsedFunctionReference::IndexedResourceConstructor { resource: "resource1".to_string(), resource_params: vec![ - Expr::literal("hello"), - Expr::number(1f64), - Expr::boolean(true), + Expr::literal("hello"), + Expr::number(1f64), + Expr::boolean(true), ], }, }, diff --git a/golem-rib/src/type_inference/expr_visitor.rs b/golem-rib/src/type_inference/expr_visitor.rs index 5750f16c1..0f7ea5d14 100644 --- a/golem-rib/src/type_inference/expr_visitor.rs +++ b/golem-rib/src/type_inference/expr_visitor.rs @@ -1,3 +1,4 @@ +use crate::call_type::CallType; use crate::Expr; use std::collections::VecDeque; use std::ops::Deref; @@ -50,7 +51,13 @@ pub fn visit_children_bottom_up_mut<'a>(expr: &'a mut Expr, queue: &mut VecDeque Expr::Option(Some(expr), _) => queue.push_back(&mut *expr), Expr::Result(Ok(expr), _) => queue.push_back(&mut *expr), Expr::Result(Err(expr), _) => queue.push_back(&mut *expr), - Expr::Call(_, expressions, _) => queue.extend(expressions.iter_mut()), + Expr::Call(call_type, arguments, _) => { + if let Some(exprs) = internal::get_expressions_in_call_mut(call_type) { + queue.extend(exprs.iter_mut()) + } + + queue.extend(arguments.iter_mut()) + } Expr::Unwrap(expr, _) => queue.push_back(&mut *expr), // not yet needed Expr::And(expr1, expr2, _) => { queue.push_back(&mut *expr1); @@ -114,7 +121,14 @@ pub fn visit_children_bottom_up<'a>(expr: &'a Expr, queue: &mut VecDeque<&'a Exp Expr::Option(Some(expr), _) => queue.push_back(expr), Expr::Result(Ok(expr), _) => queue.push_back(expr), Expr::Result(Err(expr), _) => queue.push_back(expr), - Expr::Call(_, expressions, _) => queue.extend(expressions.iter()), + Expr::Call(call_type, arguments, _) => { + if let CallType::Function(dynamic) = call_type { + if let Some(params) = dynamic.function.raw_resource_params() { + queue.extend(params.iter()) + } + } + queue.extend(arguments.iter()) + } Expr::Unwrap(expr, _) => queue.push_back(expr), Expr::And(expr1, expr2, _) => { queue.push_back(expr1); @@ -203,8 +217,14 @@ pub fn visit_children_mut_top_down<'a>(expr: &'a mut Expr, queue: &mut VecDeque< Expr::Option(Some(expr), _) => queue.push_front(&mut *expr), Expr::Result(Ok(expr), _) => queue.push_front(&mut *expr), Expr::Result(Err(expr), _) => queue.push_front(&mut *expr), - Expr::Call(_, expressions, _) => { - for expr in expressions.iter_mut() { + Expr::Call(call_type, arguments, _) => { + if let Some(exprs) = internal::get_expressions_in_call_mut(call_type) { + for expr in exprs.iter_mut() { + queue.push_front(expr); + } + } + + for expr in arguments.iter_mut() { queue.push_front(expr); } } @@ -219,3 +239,18 @@ pub fn visit_children_mut_top_down<'a>(expr: &'a mut Expr, queue: &mut VecDeque< Expr::GetTag(_, _) => {} } } + +mod internal { + use crate::call_type::CallType; + use crate::Expr; + + pub(crate) fn get_expressions_in_call_mut(call_type: &mut CallType) -> Option<&mut Vec> { + match call_type { + CallType::Function(dynamic_parsed_function_name) => dynamic_parsed_function_name + .function + .raw_resource_params_mut(), + + _ => None, + } + } +} diff --git a/golem-rib/src/type_inference/function_type_inference.rs b/golem-rib/src/type_inference/function_type_inference.rs index ff76f7888..079a22726 100644 --- a/golem-rib/src/type_inference/function_type_inference.rs +++ b/golem-rib/src/type_inference/function_type_inference.rs @@ -12,10 +12,9 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::type_registry::{FunctionTypeRegistry, RegistryKey, RegistryValue}; -use crate::{Expr, InferredType}; +use crate::type_registry::FunctionTypeRegistry; +use crate::Expr; use std::collections::VecDeque; -use crate::call_type::CallType; pub fn infer_function_types( expr: &mut Expr, @@ -26,7 +25,12 @@ pub fn infer_function_types( while let Some(expr) = queue.pop_back() { match expr { Expr::Call(parsed_fn_name, args, inferred_type) => { - internal::resolve_call_expressions(parsed_fn_name, function_type_registry, args, inferred_type)?; + internal::resolve_call_expressions( + parsed_fn_name, + function_type_registry, + args, + inferred_type, + )?; } _ => expr.visit_children_mut_bottom_up(&mut queue), } @@ -36,11 +40,16 @@ pub fn infer_function_types( } mod internal { - use crate::{DynamicParsedFunctionName, Expr, FunctionTypeRegistry, InferredType, RegistryKey, RegistryValue}; - use golem_wasm_ast::analysis::AnalysedType; use crate::call_type::CallType; + use crate::{Expr, FunctionTypeRegistry, InferredType, RegistryKey, RegistryValue}; + use golem_wasm_ast::analysis::AnalysedType; - pub(crate) fn resolve_call_expressions(call_type: &mut CallType, function_type_registry: &FunctionTypeRegistry, args: &mut Vec, inferred_type: &mut InferredType) -> Result<(), String>{ + pub(crate) fn resolve_call_expressions( + call_type: &mut CallType, + function_type_registry: &FunctionTypeRegistry, + args: &mut [Expr], + inferred_type: &mut InferredType, + ) -> Result<(), String> { match call_type { CallType::Function(dynamic_parsed_function_name) => { let parsed_function_static = dynamic_parsed_function_name.clone().to_static(); @@ -48,41 +57,70 @@ mod internal { let indexed_resource = function.is_indexed_resource(); if indexed_resource { - // Inferring th types of the resource parameters let constructor = { let raw_str = function.resource_name().ok_or("Resource name not found")?; format!["[constructor]{}", raw_str] }; - let mut constructor_params = - dynamic_parsed_function_name - .function - .raw_resource_params().ok_or("Resource params not found")?; - - let registry_key = RegistryKey::from_function_name(&parsed_function_static.site, constructor.as_str()); - - infer_types(constructor.as_str(), function_type_registry, registry_key, &mut constructor_params, inferred_type, false)?; + let constructor_params = dynamic_parsed_function_name + .function + .raw_resource_params_mut() + .ok_or("Resource params not found")?; + + let registry_key = RegistryKey::from_function_name( + &parsed_function_static.site, + constructor.as_str(), + ); + + infer_types( + constructor.as_str(), + function_type_registry, + registry_key, + constructor_params, + inferred_type, + false, + )?; // Inferring the types of the final method in the resource let resource_method_name = function.function_name(); - let registry_key = RegistryKey::from_function_name(&parsed_function_static.site, resource_method_name.as_str()); - - infer_types(resource_method_name.as_str(), function_type_registry, registry_key, args, inferred_type, true) - } - - else { + let registry_key = RegistryKey::from_function_name( + &parsed_function_static.site, + resource_method_name.as_str(), + ); + + infer_types( + resource_method_name.as_str(), + function_type_registry, + registry_key, + args, + inferred_type, + true, + ) + } else { let registry_key = RegistryKey::from_invocation_name(call_type); - - infer_types(function.function_name().as_str(), function_type_registry, registry_key, args, inferred_type, false) + infer_types( + function.function_name().as_str(), + function_type_registry, + registry_key, + args, + inferred_type, + false, + ) } } - // This will never happen unless variant identification phase happens before functions identification phase - _ => panic!("Enum constructor not supported"), + _ => Ok(()), } } - pub(crate) fn infer_types(function_name: &str, function_type_registry: &FunctionTypeRegistry, key: RegistryKey, args: &mut Vec, inferred_type: &mut InferredType, is_resource_method: bool) -> Result<(), String> { + pub(crate) fn infer_types( + function_name: &str, + function_type_registry: &FunctionTypeRegistry, + key: RegistryKey, + args: &mut [Expr], + inferred_type: &mut InferredType, + is_resource_method: bool, + ) -> Result<(), String> { if let Some(value) = function_type_registry.types.get(&key) { match value { RegistryValue::Value(_) => {} @@ -92,11 +130,13 @@ mod internal { } => { let mut parameter_types = parameter_types.clone(); if is_resource_method { - parameter_types = parameter_types.iter().filter(|t| match t { - AnalysedType::Handle(_) => false, - _ => true, - }).cloned().collect(); + parameter_types = parameter_types + .iter() + .filter(|t| !matches!(t, AnalysedType::Handle(_))) + .cloned() + .collect(); } + if parameter_types.len() == args.len() { for (arg, param_type) in args.iter_mut().zip(parameter_types) { check_function_arguments(¶m_type, arg)?; @@ -113,7 +153,6 @@ mod internal { ) } } - } else { return Err(format!( "Function {} expects {} arguments, but {} were provided", diff --git a/golem-rib/src/type_registry.rs b/golem-rib/src/type_registry.rs index 459a8ffc5..dad0f6a04 100644 --- a/golem-rib/src/type_registry.rs +++ b/golem-rib/src/type_registry.rs @@ -13,10 +13,10 @@ // limitations under the License. use crate::call_type::CallType; +use crate::ParsedFunctionSite; use golem_wasm_ast::analysis::AnalysedExport; use golem_wasm_ast::analysis::AnalysedType; use std::collections::{HashMap, HashSet}; -use crate::{ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite}; // A type-registry is a mapping from a function name (global or part of an interface in WIT) // to the registry value that represents the type of the name. @@ -39,7 +39,6 @@ pub enum RegistryKey { } impl RegistryKey { - pub fn from_function_name(site: &ParsedFunctionSite, function_name: &str) -> RegistryKey { match site.interface_name() { None => RegistryKey::FunctionName(function_name.to_string()), @@ -54,17 +53,13 @@ impl RegistryKey { CallType::VariantConstructor(variant_name) => { RegistryKey::VariantName(variant_name.clone()) } - CallType::EnumConstructor(enum_name) => { - RegistryKey::EnumName(enum_name.clone()) - }, - CallType::Function(function_name) => { - match function_name.site.interface_name() { - None => RegistryKey::FunctionName(function_name.function_name()), - Some(interface_name) => RegistryKey::FunctionNameWithInterface { - interface_name: interface_name.to_string(), - function_name: function_name.function_name(), - }, - } + CallType::EnumConstructor(enum_name) => RegistryKey::EnumName(enum_name.clone()), + CallType::Function(function_name) => match function_name.site.interface_name() { + None => RegistryKey::FunctionName(function_name.function_name()), + Some(interface_name) => RegistryKey::FunctionNameWithInterface { + interface_name: interface_name.to_string(), + function_name: function_name.function_name(), + }, }, } } From d91f000b53cfec02787f8e8b8b7627567767b12d Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Tue, 24 Sep 2024 15:09:12 +1000 Subject: [PATCH 17/27] Delete comments --- golem-rib/src/function_name.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/golem-rib/src/function_name.rs b/golem-rib/src/function_name.rs index 8233f0696..504bbd705 100644 --- a/golem-rib/src/function_name.rs +++ b/golem-rib/src/function_name.rs @@ -48,7 +48,6 @@ impl Serialize for SemVer { where S: Serializer, { - // Serialize the SemVer as its string representation. serializer.serialize_str(&self.0.to_string()) } } @@ -58,7 +57,6 @@ impl<'de> Deserialize<'de> for SemVer { where D: Deserializer<'de>, { - // Deserialize a string and attempt to parse it into a semver::Version. let s = String::deserialize(deserializer)?; let version = Version::parse(&s).map_err(serde::de::Error::custom)?; Ok(SemVer(version)) From 44d13a44d6fdbe5616a2d59e0c9d6d9df2900693 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Tue, 24 Sep 2024 15:11:33 +1000 Subject: [PATCH 18/27] Remove clone --- golem-rib/src/interpreter/rib_interpreter.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index bd006ed36..007e5992d 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -64,8 +64,6 @@ impl Interpreter { // O(1) to do this let mut instructions = VecDeque::from(instructions0.instructions); - dbg!(instructions.clone()); - while let Some(instruction) = instructions.pop_front() { match instruction { RibIR::PushLit(val) => { @@ -119,7 +117,6 @@ impl Interpreter { } RibIR::LoadVar(variable_id) => { - dbg!("here?? {}", self.stack.clone(), &self.env); internal::run_load_var_instruction(variable_id, self)?; } @@ -629,7 +626,6 @@ mod internal { .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); } FunctionReferenceType::IndexedResourceConstructor(resource, resource_params_size) => { - dbg!("here??"); let last_n_elements = interpreter .stack .pop_n(resource_params_size) @@ -773,9 +769,7 @@ mod internal { .stack .pop_str() .ok_or("Failed to get a function name from the stack".to_string())?; - - dbg!(function_name.clone()); - + let last_n_elements = interpreter .stack .pop_n(argument_size) From f10154ffe3785ed999f3f7fe840caaf1c889d016 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Tue, 24 Sep 2024 17:02:31 +1000 Subject: [PATCH 19/27] Reformat code --- golem-rib/src/interpreter/rib_interpreter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index 007e5992d..bc202ccb8 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -769,7 +769,7 @@ mod internal { .stack .pop_str() .ok_or("Failed to get a function name from the stack".to_string())?; - + let last_n_elements = interpreter .stack .pop_n(argument_size) From 07bbf7e355ce2532623da10bbc4e2e2afc8bf21d Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Tue, 24 Sep 2024 18:01:02 +1000 Subject: [PATCH 20/27] Add more tests --- golem-rib/src/interpreter/rib_interpreter.rs | 180 ++++++++++++++++++- 1 file changed, 174 insertions(+), 6 deletions(-) diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index bc202ccb8..d51491325 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -984,7 +984,8 @@ mod interpreter_tests { use super::*; use crate::{compiler, Expr, FunctionTypeRegistry, InstructionId, VariableId}; use golem_wasm_ast::analysis::{ - AnalysedType, NameTypePair, TypeList, TypeRecord, TypeS32, TypeStr, + AnalysedType, NameOptionTypePair, NameTypePair, TypeList, TypeRecord, TypeS32, TypeStr, + TypeVariant, }; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use golem_wasm_rpc::protobuf::{NameValuePair, TypedList, TypedRecord}; @@ -1428,14 +1429,14 @@ mod interpreter_tests { } #[tokio::test] - async fn test_interpreter_with_indexed_resource() { + async fn test_interpreter_with_indexed_resource_drop() { let mut interpreter = Interpreter::default(); - let analysed_exports = internal::get_component_metadata_with_indexed_resource(); + let analysed_exports = internal::get_shopping_cart_metadata_with_cart_resource(); let expr = r#" - let x = "user"; - golem:it/api.{cart(x).checkout}(); + let user_id = "user"; + golem:it/api.{cart(user_id).drop}(); "success" "#; @@ -1449,8 +1450,127 @@ mod interpreter_tests { ); } + #[tokio::test] + async fn test_interpreter_with_indexed_resource_checkout() { + let result_type = AnalysedType::Variant(TypeVariant { + cases: vec![ + NameOptionTypePair { + name: "error".to_string(), + typ: Some(AnalysedType::Str(TypeStr)), + }, + NameOptionTypePair { + name: "success".to_string(), + typ: Some(AnalysedType::Record(TypeRecord { + fields: vec![NameTypePair { + name: "order-id".to_string(), + typ: AnalysedType::Str(TypeStr), + }], + })), + }, + ], + }); + + let result_value = internal::type_annotated_value_result( + &result_type, + r#" + success({order-id: "foo"}) + "#, + ); + + let analysed_exports = internal::get_shopping_cart_metadata_with_cart_resource(); + + let mut interpreter = internal::test_interpreter(&result_type, &result_value); + + let expr = r#" + let user_id = "foo"; + let result = golem:it/api.{cart(user_id).checkout}(); + result + "#; + + let expr = Expr::from_text(expr).unwrap(); + let compiled = compiler::compile(&expr, &analysed_exports).unwrap(); + let result = interpreter.run(compiled.byte_code).await.unwrap(); + + assert_eq!(result.get_val().unwrap(), result_value); + } + + #[tokio::test] + async fn test_interpreter_with_indexed_resource_get_cart_contents() { + let analysed_exports = internal::get_shopping_cart_metadata_with_cart_resource(); + + let result_type = AnalysedType::Variant(TypeVariant { + cases: vec![ + NameOptionTypePair { + name: "error".to_string(), + typ: Some(AnalysedType::Str(TypeStr)), + }, + NameOptionTypePair { + name: "success".to_string(), + typ: Some(AnalysedType::Record(TypeRecord { + fields: vec![NameTypePair { + name: "order-id".to_string(), + typ: AnalysedType::Str(TypeStr), + }], + })), + }, + ], + }); + + let result_value = internal::type_annotated_value_result( + &result_type, + r#" + success({order-id: "foo"}) + "#, + ); + + let mut interpreter = internal::test_interpreter(&result_type, &result_value); + + let expr = r#" + let user_id = "bar"; + let result = golem:it/api.{cart(user_id).get-cart-contents}(); + result + "#; + + let expr = Expr::from_text(expr).unwrap(); + let compiled = compiler::compile(&expr, &analysed_exports).unwrap(); + let result = interpreter.run(compiled.byte_code).await.unwrap(); + + assert_eq!(result.get_val().unwrap(), result_value); + } + + #[tokio::test] + async fn test_interpreter_with_indexed_resource_update_item_quantity() { + let mut interpreter = Interpreter::default(); + + let analysed_exports = internal::get_shopping_cart_metadata_with_cart_resource(); + + let expr = r#" + let user_id = "jon"; + let product_id = "mac"; + let quantity = 1032; + golem:it/api.{cart(user_id).update-item-quantity}(product_id, quantity); + "successfully updated" + "#; + + let expr = Expr::from_text(expr).unwrap(); + let compiled = compiler::compile(&expr, &analysed_exports).unwrap(); + let result = interpreter.run(compiled.byte_code).await.unwrap(); + + assert_eq!( + result.get_val().unwrap(), + TypeAnnotatedValue::Str("successfully updated".to_string()) + ); + } + mod internal { + use crate::interpreter::env::InterpreterEnv; + use crate::interpreter::stack::InterpreterStack; + use crate::{Interpreter, RibFunctionInvoke}; use golem_wasm_ast::analysis::*; + use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; + use golem_wasm_rpc::protobuf::TypedTuple; + use std::collections::HashMap; + use std::sync::Arc; pub(crate) fn get_analysed_type_variant() -> AnalysedType { AnalysedType::Variant(TypeVariant { @@ -1560,7 +1680,7 @@ mod interpreter_tests { })] } - pub(crate) fn get_component_metadata_with_indexed_resource() -> Vec { + pub(crate) fn get_shopping_cart_metadata_with_cart_resource() -> Vec { let instance = AnalysedExport::Instance(AnalysedInstance { name: "golem:it/api".to_string(), functions: vec![ @@ -1753,5 +1873,53 @@ mod interpreter_tests { vec![instance] } + + pub(crate) fn type_annotated_value_result( + analysed_type: &AnalysedType, + wasm_wave_str: &str, + ) -> TypeAnnotatedValue { + golem_wasm_rpc::type_annotated_value_from_str(analysed_type, wasm_wave_str).unwrap() + } + + pub(crate) fn test_interpreter( + result_type: &AnalysedType, + result_value: &TypeAnnotatedValue, + ) -> Interpreter { + Interpreter { + stack: InterpreterStack::default(), + env: InterpreterEnv { + env: HashMap::new(), + call_worker_function_async: static_worker_invoke(result_type, result_value), + }, + } + } + + fn static_worker_invoke( + result_type: &AnalysedType, + value: &TypeAnnotatedValue, + ) -> RibFunctionInvoke { + let analysed_type = result_type.clone(); + let value = value.clone(); + + Arc::new(move |_, _| { + Box::pin({ + let analysed_type = analysed_type.clone(); + let value = value.clone(); + + async move { + let analysed_type = analysed_type.clone(); + let value = value.clone(); + Ok(TypeAnnotatedValue::Tuple(TypedTuple { + typ: vec![golem_wasm_ast::analysis::protobuf::Type::from( + &analysed_type, + )], + value: vec![golem_wasm_rpc::protobuf::TypeAnnotatedValue { + type_annotated_value: Some(value.clone()), + }], + })) + } + }) + }) + } } } From 2ffcfff2d3aa8f4c150e6ec0fb045f778ac05964 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Tue, 24 Sep 2024 19:26:04 +1000 Subject: [PATCH 21/27] Add more tests --- golem-rib/src/inferred_type.rs | 2 +- golem-rib/src/interpreter/rib_interpreter.rs | 150 +++++++++++------- .../type_inference/function_type_inference.rs | 70 +++++--- 3 files changed, 141 insertions(+), 81 deletions(-) diff --git a/golem-rib/src/inferred_type.rs b/golem-rib/src/inferred_type.rs index eba310a53..17188b3b7 100644 --- a/golem-rib/src/inferred_type.rs +++ b/golem-rib/src/inferred_type.rs @@ -793,7 +793,7 @@ impl InferredType { (InferredType::OneOf(types), inferred_type) => { let mut unified = None; for typ in types { - match typ.unify_with_required(inferred_type) { + match typ.unify_with_alternative(inferred_type) { Ok(result) => { unified = Some(result); break; diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index d51491325..bf0541c3b 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -984,8 +984,8 @@ mod interpreter_tests { use super::*; use crate::{compiler, Expr, FunctionTypeRegistry, InstructionId, VariableId}; use golem_wasm_ast::analysis::{ - AnalysedType, NameOptionTypePair, NameTypePair, TypeList, TypeRecord, TypeS32, TypeStr, - TypeVariant, + AnalysedType, NameOptionTypePair, NameTypePair, TypeF32, TypeList, TypeRecord, TypeS32, + TypeStr, TypeU32, TypeVariant, }; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use golem_wasm_rpc::protobuf::{NameValuePair, TypedList, TypedRecord}; @@ -1430,19 +1430,18 @@ mod interpreter_tests { #[tokio::test] async fn test_interpreter_with_indexed_resource_drop() { - let mut interpreter = Interpreter::default(); - - let analysed_exports = internal::get_shopping_cart_metadata_with_cart_resource(); - let expr = r#" let user_id = "user"; golem:it/api.{cart(user_id).drop}(); "success" "#; - let expr = Expr::from_text(expr).unwrap(); - let compiled = compiler::compile(&expr, &analysed_exports).unwrap(); - let result = interpreter.run(compiled.byte_code).await.unwrap(); + let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource(); + + let compiled = compiler::compile(&expr, &component_metadata).unwrap(); + + let mut rib_interpreter = Interpreter::default(); + let result = rib_interpreter.run(compiled.byte_code).await.unwrap(); assert_eq!( result.get_val().unwrap(), @@ -1452,6 +1451,14 @@ mod interpreter_tests { #[tokio::test] async fn test_interpreter_with_indexed_resource_checkout() { + let expr = r#" + let user_id = "foo"; + let result = golem:it/api.{cart(user_id).checkout}(); + result + "#; + + let expr = Expr::from_text(expr).unwrap(); + let result_type = AnalysedType::Variant(TypeVariant { cases: vec![ NameOptionTypePair { @@ -1477,73 +1484,69 @@ mod interpreter_tests { "#, ); - let analysed_exports = internal::get_shopping_cart_metadata_with_cart_resource(); - - let mut interpreter = internal::test_interpreter(&result_type, &result_value); + let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource(); + let compiled = compiler::compile(&expr, &component_metadata).unwrap(); - let expr = r#" - let user_id = "foo"; - let result = golem:it/api.{cart(user_id).checkout}(); - result - "#; - - let expr = Expr::from_text(expr).unwrap(); - let compiled = compiler::compile(&expr, &analysed_exports).unwrap(); - let result = interpreter.run(compiled.byte_code).await.unwrap(); + let mut rib_executor = internal::test_executor(&result_type, &result_value); + let result = rib_executor.run(compiled.byte_code).await.unwrap(); assert_eq!(result.get_val().unwrap(), result_value); } #[tokio::test] async fn test_interpreter_with_indexed_resource_get_cart_contents() { - let analysed_exports = internal::get_shopping_cart_metadata_with_cart_resource(); + let expr = r#" + let user_id = "bar"; + let result = golem:it/api.{cart(user_id).get-cart-contents}(); + result[0].product-id + "#; - let result_type = AnalysedType::Variant(TypeVariant { - cases: vec![ - NameOptionTypePair { - name: "error".to_string(), - typ: Some(AnalysedType::Str(TypeStr)), - }, - NameOptionTypePair { - name: "success".to_string(), - typ: Some(AnalysedType::Record(TypeRecord { - fields: vec![NameTypePair { - name: "order-id".to_string(), - typ: AnalysedType::Str(TypeStr), - }], - })), - }, - ], + let expr = Expr::from_text(expr).unwrap(); + + let result_type = AnalysedType::List(TypeList { + inner: Box::new(AnalysedType::Record(TypeRecord { + fields: vec![ + NameTypePair { + name: "product-id".to_string(), + typ: AnalysedType::Str(TypeStr), + }, + NameTypePair { + name: "name".to_string(), + typ: AnalysedType::Str(TypeStr), + }, + NameTypePair { + name: "price".to_string(), + typ: AnalysedType::F32(TypeF32), + }, + NameTypePair { + name: "quantity".to_string(), + typ: AnalysedType::U32(TypeU32), + }, + ], + })), }); let result_value = internal::type_annotated_value_result( &result_type, r#" - success({order-id: "foo"}) + [{product-id: "foo", name: "bar", price: 100.0, quantity: 1}, {product-id: "bar", name: "baz", price: 200.0, quantity: 2}] "#, ); - let mut interpreter = internal::test_interpreter(&result_type, &result_value); + let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource(); + let compiled = compiler::compile(&expr, &component_metadata).unwrap(); - let expr = r#" - let user_id = "bar"; - let result = golem:it/api.{cart(user_id).get-cart-contents}(); - result - "#; - - let expr = Expr::from_text(expr).unwrap(); - let compiled = compiler::compile(&expr, &analysed_exports).unwrap(); - let result = interpreter.run(compiled.byte_code).await.unwrap(); + let mut rib_executor = internal::test_executor(&result_type, &result_value); + let result = rib_executor.run(compiled.byte_code).await.unwrap(); - assert_eq!(result.get_val().unwrap(), result_value); + assert_eq!( + result.get_val().unwrap(), + TypeAnnotatedValue::Str("foo".to_string()) + ); } #[tokio::test] async fn test_interpreter_with_indexed_resource_update_item_quantity() { - let mut interpreter = Interpreter::default(); - - let analysed_exports = internal::get_shopping_cart_metadata_with_cart_resource(); - let expr = r#" let user_id = "jon"; let product_id = "mac"; @@ -1551,10 +1554,15 @@ mod interpreter_tests { golem:it/api.{cart(user_id).update-item-quantity}(product_id, quantity); "successfully updated" "#; - let expr = Expr::from_text(expr).unwrap(); - let compiled = compiler::compile(&expr, &analysed_exports).unwrap(); - let result = interpreter.run(compiled.byte_code).await.unwrap(); + + let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource(); + + let compiled = compiler::compile(&expr, &component_metadata).unwrap(); + + let mut rib_executor = Interpreter::default(); + + let result = rib_executor.run(compiled.byte_code).await.unwrap(); assert_eq!( result.get_val().unwrap(), @@ -1562,6 +1570,32 @@ mod interpreter_tests { ); } + #[tokio::test] + async fn test_interpreter_with_indexed_resource_add_item() { + let expr = r#" + let user_id = "foo"; + let product = { product-id: "mac", name: "macbook", quantity: 1u32, price: 1f32 }; + golem:it/api.{cart(user_id).add-item}(product); + + "successfully added" + "#; + + let expr = Expr::from_text(expr).unwrap(); + + let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource(); + + let compiled = compiler::compile(&expr, &component_metadata).unwrap(); + + let mut rib_executor = Interpreter::default(); + + let result = rib_executor.run(compiled.byte_code).await.unwrap(); + + assert_eq!( + result.get_val().unwrap(), + TypeAnnotatedValue::Str("successfully added".to_string()) + ); + } + mod internal { use crate::interpreter::env::InterpreterEnv; use crate::interpreter::stack::InterpreterStack; @@ -1881,7 +1915,7 @@ mod interpreter_tests { golem_wasm_rpc::type_annotated_value_from_str(analysed_type, wasm_wave_str).unwrap() } - pub(crate) fn test_interpreter( + pub(crate) fn test_executor( result_type: &AnalysedType, result_value: &TypeAnnotatedValue, ) -> Interpreter { diff --git a/golem-rib/src/type_inference/function_type_inference.rs b/golem-rib/src/type_inference/function_type_inference.rs index 079a22726..971c2a150 100644 --- a/golem-rib/src/type_inference/function_type_inference.rs +++ b/golem-rib/src/type_inference/function_type_inference.rs @@ -41,8 +41,11 @@ pub fn infer_function_types( mod internal { use crate::call_type::CallType; - use crate::{Expr, FunctionTypeRegistry, InferredType, RegistryKey, RegistryValue}; + use crate::{ + Expr, FunctionTypeRegistry, InferredType, ParsedFunctionName, RegistryKey, RegistryValue, + }; use golem_wasm_ast::analysis::AnalysedType; + use std::fmt::Display; pub(crate) fn resolve_call_expressions( call_type: &mut CallType, @@ -53,35 +56,40 @@ mod internal { match call_type { CallType::Function(dynamic_parsed_function_name) => { let parsed_function_static = dynamic_parsed_function_name.clone().to_static(); - let function = parsed_function_static.function; + let function = parsed_function_static.clone().function; let indexed_resource = function.is_indexed_resource(); + // If indexed resource, first we need to fetch the parameter types of th constructor if indexed_resource { - let constructor = { + let constructor_name = { let raw_str = function.resource_name().ok_or("Resource name not found")?; format!["[constructor]{}", raw_str] }; - let constructor_params = dynamic_parsed_function_name + let mut constructor_params: &mut Vec = &mut vec![]; + + if let Some(resource_params) = dynamic_parsed_function_name .function .raw_resource_params_mut() - .ok_or("Resource params not found")?; + { + constructor_params = resource_params + } let registry_key = RegistryKey::from_function_name( &parsed_function_static.site, - constructor.as_str(), + constructor_name.as_str(), ); + // Infer the types of constructor parameter expressions infer_types( - constructor.as_str(), + &FunctionNameInternal::ResourceConstructorName(constructor_name), function_type_registry, registry_key, constructor_params, inferred_type, - false, )?; - // Inferring the types of the final method in the resource + // Infer the types of resource method parameters let resource_method_name = function.function_name(); let registry_key = RegistryKey::from_function_name( &parsed_function_static.site, @@ -89,22 +97,20 @@ mod internal { ); infer_types( - resource_method_name.as_str(), + &FunctionNameInternal::ResourceMethodName(resource_method_name), function_type_registry, registry_key, args, inferred_type, - true, ) } else { let registry_key = RegistryKey::from_invocation_name(call_type); infer_types( - function.function_name().as_str(), + &FunctionNameInternal::Fqn(parsed_function_static), function_type_registry, registry_key, args, inferred_type, - false, ) } } @@ -113,13 +119,12 @@ mod internal { } } - pub(crate) fn infer_types( - function_name: &str, + fn infer_types( + function_name: &FunctionNameInternal, function_type_registry: &FunctionTypeRegistry, key: RegistryKey, args: &mut [Expr], inferred_type: &mut InferredType, - is_resource_method: bool, ) -> Result<(), String> { if let Some(value) = function_type_registry.types.get(&key) { match value { @@ -129,12 +134,11 @@ mod internal { return_types, } => { let mut parameter_types = parameter_types.clone(); - if is_resource_method { - parameter_types = parameter_types - .iter() - .filter(|t| !matches!(t, AnalysedType::Handle(_))) - .cloned() - .collect(); + + if let FunctionNameInternal::ResourceMethodName(_) = function_name { + if let Some(AnalysedType::Handle(_)) = parameter_types.first() { + parameter_types.remove(0); + } } if parameter_types.len() == args.len() { @@ -168,6 +172,28 @@ mod internal { Ok(()) } + enum FunctionNameInternal { + ResourceConstructorName(String), + ResourceMethodName(String), + Fqn(ParsedFunctionName), + } + + impl Display for FunctionNameInternal { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + FunctionNameInternal::ResourceConstructorName(name) => { + write!(f, "{}", name) + } + FunctionNameInternal::ResourceMethodName(name) => { + write!(f, "{}", name) + } + FunctionNameInternal::Fqn(name) => { + write!(f, "{}", name) + } + } + } + } + // A preliminary check of the arguments passed before typ inference pub(crate) fn check_function_arguments( expected: &AnalysedType, From ab986308cf2ed2d41d97336d5f7196707854a5c4 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Tue, 24 Sep 2024 22:04:58 +1000 Subject: [PATCH 22/27] Remove the need of serde for RibByteCode --- golem-rib/src/compiler/byte_code.rs | 3 +- golem-rib/src/compiler/ir.rs | 2 +- golem-rib/src/function_name.rs | 26 ++------- golem-rib/src/interpreter/rib_interpreter.rs | 54 +++++++++++++++---- .../http/http_api_definition.rs | 6 +-- .../compiled_golem_worker_binding.rs | 9 ++-- 6 files changed, 55 insertions(+), 45 deletions(-) diff --git a/golem-rib/src/compiler/byte_code.rs b/golem-rib/src/compiler/byte_code.rs index 8894f604b..f1a170851 100644 --- a/golem-rib/src/compiler/byte_code.rs +++ b/golem-rib/src/compiler/byte_code.rs @@ -17,9 +17,8 @@ use crate::compiler::ir::RibIR; use crate::{Expr, InstructionId}; use bincode::{Decode, Encode}; use golem_api_grpc::proto::golem::rib::RibByteCode as ProtoRibByteCode; -use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Encode, Decode)] pub struct RibByteCode { pub instructions: Vec, } diff --git a/golem-rib/src/compiler/ir.rs b/golem-rib/src/compiler/ir.rs index eb78ad64e..442021a93 100644 --- a/golem-rib/src/compiler/ir.rs +++ b/golem-rib/src/compiler/ir.rs @@ -25,7 +25,7 @@ use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use serde::{Deserialize, Serialize}; // To create any type, example, CreateOption, you have to feed a fully formed AnalysedType -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Encode, Decode)] pub enum RibIR { PushLit(TypeAnnotatedValue), AssignVar(VariableId), diff --git a/golem-rib/src/function_name.rs b/golem-rib/src/function_name.rs index 504bbd705..ab7605211 100644 --- a/golem-rib/src/function_name.rs +++ b/golem-rib/src/function_name.rs @@ -21,12 +21,12 @@ use golem_wasm_ast::analysis::AnalysedType; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use golem_wasm_rpc::type_annotated_value_from_str; use golem_wasm_rpc::Value; -use semver::{BuildMetadata, Prerelease, Version}; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use semver::{BuildMetadata, Prerelease}; +use serde::{Deserialize, Serialize}; use std::borrow::Cow; use std::fmt::Display; -#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize, Encode, Decode)] +#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] pub enum ParsedFunctionSite { Global, Interface { @@ -43,26 +43,6 @@ pub enum ParsedFunctionSite { #[derive(PartialEq, Eq, Clone)] pub struct SemVer(pub semver::Version); -impl Serialize for SemVer { - fn serialize(&self, serializer: S) -> Result - where - S: Serializer, - { - serializer.serialize_str(&self.0.to_string()) - } -} - -impl<'de> Deserialize<'de> for SemVer { - fn deserialize(deserializer: D) -> Result - where - D: Deserializer<'de>, - { - let s = String::deserialize(deserializer)?; - let version = Version::parse(&s).map_err(serde::de::Error::custom)?; - Ok(SemVer(version)) - } -} - impl std::fmt::Debug for SemVer { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self.0) diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index bf0541c3b..2e7cd9217 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -1436,7 +1436,7 @@ mod interpreter_tests { "success" "#; let expr = Expr::from_text(expr).unwrap(); - let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource(); + let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); let compiled = compiler::compile(&expr, &component_metadata).unwrap(); @@ -1484,7 +1484,7 @@ mod interpreter_tests { "#, ); - let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource(); + let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); let compiled = compiler::compile(&expr, &component_metadata).unwrap(); let mut rib_executor = internal::test_executor(&result_type, &result_value); @@ -1533,7 +1533,7 @@ mod interpreter_tests { "#, ); - let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource(); + let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); let compiled = compiler::compile(&expr, &component_metadata).unwrap(); let mut rib_executor = internal::test_executor(&result_type, &result_value); @@ -1556,7 +1556,7 @@ mod interpreter_tests { "#; let expr = Expr::from_text(expr).unwrap(); - let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource(); + let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); let compiled = compiler::compile(&expr, &component_metadata).unwrap(); @@ -1582,7 +1582,33 @@ mod interpreter_tests { let expr = Expr::from_text(expr).unwrap(); - let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource(); + let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); + + let compiled = compiler::compile(&expr, &component_metadata).unwrap(); + + let mut rib_executor = Interpreter::default(); + + let result = rib_executor.run(compiled.byte_code).await.unwrap(); + + assert_eq!( + result.get_val().unwrap(), + TypeAnnotatedValue::Str("successfully added".to_string()) + ); + } + + #[tokio::test] + async fn test_interpreter_with_resource_add_item() { + let expr = r#" + let user_id = "foo"; + let product = { product-id: "mac", name: "macbook", quantity: 1u32, price: 1f32 }; + golem:it/api.{cart.add-item}(product); + + "successfully added" + "#; + + let expr = Expr::from_text(expr).unwrap(); + + let component_metadata = internal::get_shopping_cart_metadata_with_cart_raw_resource(); let compiled = compiler::compile(&expr, &component_metadata).unwrap(); @@ -1714,16 +1740,24 @@ mod interpreter_tests { })] } - pub(crate) fn get_shopping_cart_metadata_with_cart_resource() -> Vec { + pub(crate) fn get_shopping_cart_metadata_with_cart_resource_with_parameters() -> Vec { + get_shopping_cart_metadata_with_cart_resource(vec![AnalysedFunctionParameter { + name: "user-id".to_string(), + typ: AnalysedType::Str(TypeStr), + }]) + } + + pub(crate) fn get_shopping_cart_metadata_with_cart_raw_resource() -> Vec { + get_shopping_cart_metadata_with_cart_resource(vec![]) + } + + fn get_shopping_cart_metadata_with_cart_resource(constructor_parameters: Vec) -> Vec { let instance = AnalysedExport::Instance(AnalysedInstance { name: "golem:it/api".to_string(), functions: vec![ AnalysedFunction { name: "[constructor]cart".to_string(), - parameters: vec![AnalysedFunctionParameter { - name: "user-id".to_string(), - typ: AnalysedType::Str(TypeStr), - }], + parameters: constructor_parameters, results: vec![AnalysedFunctionResult { name: None, typ: AnalysedType::Handle(TypeHandle { diff --git a/golem-worker-service-base/src/api_definition/http/http_api_definition.rs b/golem-worker-service-base/src/api_definition/http/http_api_definition.rs index 753169b28..50cd8a067 100644 --- a/golem-worker-service-base/src/api_definition/http/http_api_definition.rs +++ b/golem-worker-service-base/src/api_definition/http/http_api_definition.rs @@ -80,13 +80,11 @@ impl From for HttpApiDefinition { } } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] +#[derive(Debug, Clone, PartialEq)] pub struct CompiledHttpApiDefinition { pub id: ApiDefinitionId, pub version: ApiVersion, pub routes: Vec, - #[serde(default)] pub draft: bool, pub created_at: chrono::DateTime, } @@ -350,7 +348,7 @@ pub struct Route { pub binding: GolemWorkerBinding, } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Encode, Decode)] pub struct CompiledRoute { pub method: MethodPattern, pub path: AllPathPatterns, diff --git a/golem-worker-service-base/src/worker_binding/compiled_golem_worker_binding.rs b/golem-worker-service-base/src/worker_binding/compiled_golem_worker_binding.rs index c524d1074..e2dbf4c28 100644 --- a/golem-worker-service-base/src/worker_binding/compiled_golem_worker_binding.rs +++ b/golem-worker-service-base/src/worker_binding/compiled_golem_worker_binding.rs @@ -3,9 +3,8 @@ use bincode::{Decode, Encode}; use golem_service_base::model::VersionedComponentId; use golem_wasm_ast::analysis::AnalysedExport; use rib::{Expr, RibByteCode, RibInputTypeInfo}; -use serde::{Deserialize, Serialize}; -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Encode, Decode)] pub struct CompiledGolemWorkerBinding { pub component_id: VersionedComponentId, pub worker_name_compiled: WorkerNameCompiled, @@ -43,7 +42,7 @@ impl CompiledGolemWorkerBinding { } } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Encode, Decode)] pub struct WorkerNameCompiled { pub worker_name: Expr, pub compiled_worker_name: RibByteCode, @@ -65,7 +64,7 @@ impl WorkerNameCompiled { } } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Encode, Decode)] pub struct IdempotencyKeyCompiled { pub idempotency_key: Expr, pub compiled_idempotency_key: RibByteCode, @@ -87,7 +86,7 @@ impl IdempotencyKeyCompiled { } } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Encode, Decode)] pub struct ResponseMappingCompiled { pub response_rib_expr: Expr, pub compiled_response: RibByteCode, From 6149dd4003784d8aa16aab062520079a431ae7f4 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Tue, 24 Sep 2024 22:22:03 +1000 Subject: [PATCH 23/27] Use field names in instruction set instead of anonymouse types --- golem-rib/src/compiler/byte_code.rs | 66 ++++----- golem-rib/src/compiler/ir.rs | 135 ++++++++++++------- golem-rib/src/interpreter/rib_interpreter.rs | 60 +++++---- 3 files changed, 153 insertions(+), 108 deletions(-) diff --git a/golem-rib/src/compiler/byte_code.rs b/golem-rib/src/compiler/byte_code.rs index f1a170851..86af7a7c1 100644 --- a/golem-rib/src/compiler/byte_code.rs +++ b/golem-rib/src/compiler/byte_code.rs @@ -18,7 +18,7 @@ use crate::{Expr, InstructionId}; use bincode::{Decode, Encode}; use golem_api_grpc::proto::golem::rib::RibByteCode as ProtoRibByteCode; -#[derive(Debug, Clone, PartialEq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Encode, Decode)] pub struct RibByteCode { pub instructions: Vec, } @@ -262,19 +262,25 @@ mod internal { DynamicParsedFunctionReference::Function { function } => instructions .push(RibIR::CreateFunctionName( site, - FunctionReferenceType::Function(function.clone()), + FunctionReferenceType::Function { + function: function.clone(), + }, )), DynamicParsedFunctionReference::RawResourceConstructor { resource } => { instructions.push(RibIR::CreateFunctionName( site, - FunctionReferenceType::RawResourceConstructor(resource.clone()), + FunctionReferenceType::RawResourceConstructor { + resource: resource.clone(), + }, )) } DynamicParsedFunctionReference::RawResourceDrop { resource } => { instructions.push(RibIR::CreateFunctionName( site, - FunctionReferenceType::RawResourceDrop(resource.clone()), + FunctionReferenceType::RawResourceDrop { + resource: resource.clone(), + }, )) } DynamicParsedFunctionReference::RawResourceMethod { @@ -282,20 +288,20 @@ mod internal { method, } => instructions.push(RibIR::CreateFunctionName( site, - FunctionReferenceType::RawResourceMethod( - resource.clone(), - method.clone(), - ), + FunctionReferenceType::RawResourceMethod { + resource: resource.clone(), + method: method.clone(), + }, )), DynamicParsedFunctionReference::RawResourceStaticMethod { resource, method, } => instructions.push(RibIR::CreateFunctionName( site, - FunctionReferenceType::RawResourceStaticMethod( - resource.clone(), - method.clone(), - ), + FunctionReferenceType::RawResourceStaticMethod { + resource: resource.clone(), + method: method.clone(), + }, )), DynamicParsedFunctionReference::IndexedResourceConstructor { resource, @@ -306,10 +312,10 @@ mod internal { } instructions.push(RibIR::CreateFunctionName( site, - FunctionReferenceType::IndexedResourceConstructor( - resource.clone(), - resource_params.len(), - ), + FunctionReferenceType::IndexedResourceConstructor { + resource: resource.clone(), + arg_size: resource_params.len(), + }, )) } DynamicParsedFunctionReference::IndexedResourceMethod { @@ -322,11 +328,11 @@ mod internal { } instructions.push(RibIR::CreateFunctionName( site, - FunctionReferenceType::IndexedResourceMethod( - resource.clone(), - resource_params.len(), - method.clone(), - ), + FunctionReferenceType::IndexedResourceMethod { + resource: resource.clone(), + arg_size: resource_params.len(), + method: method.clone(), + }, )) } DynamicParsedFunctionReference::IndexedResourceStaticMethod { @@ -339,11 +345,11 @@ mod internal { } instructions.push(RibIR::CreateFunctionName( site, - FunctionReferenceType::IndexedResourceStaticMethod( - resource.clone(), - resource_params.len(), - method.clone(), - ), + FunctionReferenceType::IndexedResourceStaticMethod { + resource: resource.clone(), + arg_size: resource_params.len(), + method: method.clone(), + }, )) } DynamicParsedFunctionReference::IndexedResourceDrop { @@ -355,10 +361,10 @@ mod internal { } instructions.push(RibIR::CreateFunctionName( site, - FunctionReferenceType::IndexedResourceDrop( - resource.clone(), - resource_params.len(), - ), + FunctionReferenceType::IndexedResourceDrop { + resource: resource.clone(), + arg_size: resource_params.len(), + }, )) } } diff --git a/golem-rib/src/compiler/ir.rs b/golem-rib/src/compiler/ir.rs index 442021a93..2d7722e30 100644 --- a/golem-rib/src/compiler/ir.rs +++ b/golem-rib/src/compiler/ir.rs @@ -25,7 +25,7 @@ use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use serde::{Deserialize, Serialize}; // To create any type, example, CreateOption, you have to feed a fully formed AnalysedType -#[derive(Debug, Clone, PartialEq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Encode, Decode)] pub enum RibIR { PushLit(TypeAnnotatedValue), AssignVar(VariableId), @@ -63,15 +63,41 @@ pub enum RibIR { #[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode)] pub enum FunctionReferenceType { - Function(String), - RawResourceConstructor(String), - RawResourceDrop(String), - RawResourceMethod(String, String), - RawResourceStaticMethod(String, String), - IndexedResourceConstructor(String, usize), - IndexedResourceMethod(String, usize, String), - IndexedResourceStaticMethod(String, usize, String), - IndexedResourceDrop(String, usize), + Function { + function: String, + }, + RawResourceConstructor { + resource: String, + }, + RawResourceDrop { + resource: String, + }, + RawResourceMethod { + resource: String, + method: String, + }, + RawResourceStaticMethod { + resource: String, + method: String, + }, + IndexedResourceConstructor { + resource: String, + arg_size: usize, + }, + IndexedResourceMethod { + resource: String, + arg_size: usize, + method: String, + }, + IndexedResourceStaticMethod { + resource: String, + arg_size: usize, + method: String, + }, + IndexedResourceDrop { + resource: String, + arg_size: usize, + }, } impl TryFrom for FunctionReferenceType { @@ -81,40 +107,47 @@ impl TryFrom for Funct ) -> Result { let value = value.r#type.ok_or("Missing type".to_string())?; let function_reference_type = match value { - golem_api_grpc::proto::golem::rib::function_reference_type::Type::Function(name) => FunctionReferenceType::Function(name.name), - golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceConstructor(name) => FunctionReferenceType::RawResourceConstructor(name.resource_name), - golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceDrop(name) => FunctionReferenceType::RawResourceDrop(name.resource_name), + golem_api_grpc::proto::golem::rib::function_reference_type::Type::Function(name) => FunctionReferenceType::Function { + function: name.name + }, + golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceConstructor(name) => + FunctionReferenceType::RawResourceConstructor { + resource: name.resource_name + }, + golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceDrop(name) => FunctionReferenceType::RawResourceDrop { + resource: name.resource_name + }, golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceMethod(raw_resource_method) =>{ - let name = raw_resource_method.resource_name; + let resource = raw_resource_method.resource_name; let method = raw_resource_method.method_name; - FunctionReferenceType::RawResourceMethod(name, method) + FunctionReferenceType::RawResourceMethod { resource, method } } golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceStaticMethod(raw_resource_static_method) => { - let name = raw_resource_static_method.resource_name; + let resource = raw_resource_static_method.resource_name; let method = raw_resource_static_method.method_name; - FunctionReferenceType::RawResourceStaticMethod(name, method) + FunctionReferenceType::RawResourceStaticMethod{ resource, method } } golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceConstructor(indexed_resource_constructor) => { - let name = indexed_resource_constructor.resource_name; - let index = indexed_resource_constructor.arg_size; - FunctionReferenceType::IndexedResourceConstructor(name, index as usize) + let resource = indexed_resource_constructor.resource_name; + let arg_size = indexed_resource_constructor.arg_size; + FunctionReferenceType::IndexedResourceConstructor { resource, arg_size: arg_size as usize } } golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceMethod(indexed_resource_method) => { - let name = indexed_resource_method.resource_name; - let index = indexed_resource_method.arg_size; + let resource = indexed_resource_method.resource_name; + let arg_size = indexed_resource_method.arg_size; let method = indexed_resource_method.method_name; - FunctionReferenceType::IndexedResourceMethod(name, index as usize, method) + FunctionReferenceType::IndexedResourceMethod { resource, arg_size: arg_size as usize, method } } golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceStaticMethod(indexed_resource_static_method) => { - let name = indexed_resource_static_method.resource_name; - let index = indexed_resource_static_method.arg_size; + let resource = indexed_resource_static_method.resource_name; + let arg_size = indexed_resource_static_method.arg_size; let method = indexed_resource_static_method.method_name; - FunctionReferenceType::IndexedResourceStaticMethod(name, index as usize, method) + FunctionReferenceType::IndexedResourceStaticMethod { resource, arg_size: arg_size as usize, method } } golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceDrop(indexed_resource_drop) => { - let name = indexed_resource_drop.resource_name; - let index = indexed_resource_drop.arg_size; - FunctionReferenceType::IndexedResourceDrop(name, index as usize) + let resource = indexed_resource_drop.resource_name; + let arg_size = indexed_resource_drop.arg_size; + FunctionReferenceType::IndexedResourceDrop { resource, arg_size: arg_size as usize } } }; Ok(function_reference_type) @@ -124,56 +157,56 @@ impl TryFrom for Funct impl From for golem_api_grpc::proto::golem::rib::FunctionReferenceType { fn from(value: FunctionReferenceType) -> Self { match value { - FunctionReferenceType::Function(name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + FunctionReferenceType::Function { function } => golem_api_grpc::proto::golem::rib::FunctionReferenceType { r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::Function(golem_api_grpc::proto::golem::rib::Function { - name + name: function })) }, - FunctionReferenceType::RawResourceConstructor(resource_name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + FunctionReferenceType::RawResourceConstructor{ resource } => golem_api_grpc::proto::golem::rib::FunctionReferenceType { r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceConstructor(golem_api_grpc::proto::golem::rib::RawResourceConstructor { - resource_name + resource_name: resource })) }, - FunctionReferenceType::RawResourceDrop(resource_name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + FunctionReferenceType::RawResourceDrop { resource } => golem_api_grpc::proto::golem::rib::FunctionReferenceType { r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceDrop(golem_api_grpc::proto::golem::rib::RawResourceDrop { - resource_name + resource_name: resource })) }, - FunctionReferenceType::RawResourceMethod(resource_name, method_name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + FunctionReferenceType::RawResourceMethod { resource, method } => golem_api_grpc::proto::golem::rib::FunctionReferenceType { r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceMethod(golem_api_grpc::proto::golem::rib::RawResourceMethod { - resource_name, - method_name + resource_name: resource, + method_name: method })) }, - FunctionReferenceType::RawResourceStaticMethod(resource_name, method_name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + FunctionReferenceType::RawResourceStaticMethod { resource, method } => golem_api_grpc::proto::golem::rib::FunctionReferenceType { r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceStaticMethod(golem_api_grpc::proto::golem::rib::RawResourceStaticMethod { - resource_name, - method_name + resource_name: resource, + method_name: method })) }, - FunctionReferenceType::IndexedResourceConstructor(resource_name, arg_size) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + FunctionReferenceType::IndexedResourceConstructor { resource, arg_size } => golem_api_grpc::proto::golem::rib::FunctionReferenceType { r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceConstructor(golem_api_grpc::proto::golem::rib::IndexedResourceConstructor { - resource_name, + resource_name: resource, arg_size: arg_size as u32 })) }, - FunctionReferenceType::IndexedResourceMethod(resource_name, arg_size, method_name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + FunctionReferenceType::IndexedResourceMethod { resource, arg_size, method } => golem_api_grpc::proto::golem::rib::FunctionReferenceType { r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceMethod(golem_api_grpc::proto::golem::rib::IndexedResourceMethod { - resource_name, + resource_name: resource, arg_size: arg_size as u32, - method_name + method_name: method })) }, - FunctionReferenceType::IndexedResourceStaticMethod(resource_name, arg_size, method_name) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + FunctionReferenceType::IndexedResourceStaticMethod { resource, arg_size, method } => golem_api_grpc::proto::golem::rib::FunctionReferenceType { r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceStaticMethod(golem_api_grpc::proto::golem::rib::IndexedResourceStaticMethod { - resource_name, + resource_name: resource, arg_size: arg_size as u32, - method_name + method_name: method })) }, - FunctionReferenceType::IndexedResourceDrop(resource_name, arg_size) => golem_api_grpc::proto::golem::rib::FunctionReferenceType { + FunctionReferenceType::IndexedResourceDrop { resource, arg_size } => golem_api_grpc::proto::golem::rib::FunctionReferenceType { r#type: Some(golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceDrop(golem_api_grpc::proto::golem::rib::IndexedResourceDrop { - resource_name, + resource_name: resource, arg_size: arg_size as u32 })) } diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index 2e7cd9217..ebbc3ca72 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -572,12 +572,10 @@ mod internal { interpreter: &mut Interpreter, ) -> Result<(), String> { match function_type { - FunctionReferenceType::Function(parsed_fn_name) => { + FunctionReferenceType::Function { function } => { let parsed_function_name = ParsedFunctionName { site, - function: ParsedFunctionReference::Function { - function: parsed_fn_name, - }, + function: ParsedFunctionReference::Function { function }, }; interpreter @@ -585,7 +583,7 @@ mod internal { .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); } - FunctionReferenceType::RawResourceConstructor(resource) => { + FunctionReferenceType::RawResourceConstructor { resource } => { let parsed_function_name = ParsedFunctionName { site, function: ParsedFunctionReference::RawResourceConstructor { resource }, @@ -595,7 +593,7 @@ mod internal { .stack .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); } - FunctionReferenceType::RawResourceDrop(resource) => { + FunctionReferenceType::RawResourceDrop { resource } => { let parsed_function_name = ParsedFunctionName { site, function: ParsedFunctionReference::RawResourceDrop { resource }, @@ -605,7 +603,7 @@ mod internal { .stack .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); } - FunctionReferenceType::RawResourceMethod(resource, method) => { + FunctionReferenceType::RawResourceMethod { resource, method } => { let parsed_function_name = ParsedFunctionName { site, function: ParsedFunctionReference::RawResourceMethod { resource, method }, @@ -615,7 +613,7 @@ mod internal { .stack .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); } - FunctionReferenceType::RawResourceStaticMethod(resource, method) => { + FunctionReferenceType::RawResourceStaticMethod { resource, method } => { let parsed_function_name = ParsedFunctionName { site, function: ParsedFunctionReference::RawResourceStaticMethod { resource, method }, @@ -625,10 +623,10 @@ mod internal { .stack .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); } - FunctionReferenceType::IndexedResourceConstructor(resource, resource_params_size) => { + FunctionReferenceType::IndexedResourceConstructor { resource, arg_size } => { let last_n_elements = interpreter .stack - .pop_n(resource_params_size) + .pop_n(arg_size) .ok_or("Failed to get values from the stack".to_string())?; let type_anntoated_values = last_n_elements @@ -655,14 +653,14 @@ mod internal { .stack .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); } - FunctionReferenceType::IndexedResourceMethod( + FunctionReferenceType::IndexedResourceMethod { resource, - resource_params_size, + arg_size, method, - ) => { + } => { let last_n_elements = interpreter .stack - .pop_n(resource_params_size) + .pop_n(arg_size) .ok_or("Failed to get values from the stack".to_string())?; let type_anntoated_values = last_n_elements @@ -690,14 +688,14 @@ mod internal { .stack .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); } - FunctionReferenceType::IndexedResourceStaticMethod( + FunctionReferenceType::IndexedResourceStaticMethod { resource, - resource_params_size, + arg_size, method, - ) => { + } => { let last_n_elements = interpreter .stack - .pop_n(resource_params_size) + .pop_n(arg_size) .ok_or("Failed to get values from the stack".to_string())?; let type_anntoated_values = last_n_elements @@ -725,10 +723,10 @@ mod internal { .stack .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); } - FunctionReferenceType::IndexedResourceDrop(resource, resource_params) => { + FunctionReferenceType::IndexedResourceDrop { resource, arg_size } => { let last_n_elements = interpreter .stack - .pop_n(resource_params) + .pop_n(arg_size) .ok_or("Failed to get values from the stack".to_string())?; let type_anntoated_values = last_n_elements @@ -1436,7 +1434,8 @@ mod interpreter_tests { "success" "#; let expr = Expr::from_text(expr).unwrap(); - let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); + let component_metadata = + internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); let compiled = compiler::compile(&expr, &component_metadata).unwrap(); @@ -1484,7 +1483,8 @@ mod interpreter_tests { "#, ); - let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); + let component_metadata = + internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); let compiled = compiler::compile(&expr, &component_metadata).unwrap(); let mut rib_executor = internal::test_executor(&result_type, &result_value); @@ -1533,7 +1533,8 @@ mod interpreter_tests { "#, ); - let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); + let component_metadata = + internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); let compiled = compiler::compile(&expr, &component_metadata).unwrap(); let mut rib_executor = internal::test_executor(&result_type, &result_value); @@ -1556,7 +1557,8 @@ mod interpreter_tests { "#; let expr = Expr::from_text(expr).unwrap(); - let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); + let component_metadata = + internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); let compiled = compiler::compile(&expr, &component_metadata).unwrap(); @@ -1582,7 +1584,8 @@ mod interpreter_tests { let expr = Expr::from_text(expr).unwrap(); - let component_metadata = internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); + let component_metadata = + internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); let compiled = compiler::compile(&expr, &component_metadata).unwrap(); @@ -1740,7 +1743,8 @@ mod interpreter_tests { })] } - pub(crate) fn get_shopping_cart_metadata_with_cart_resource_with_parameters() -> Vec { + pub(crate) fn get_shopping_cart_metadata_with_cart_resource_with_parameters( + ) -> Vec { get_shopping_cart_metadata_with_cart_resource(vec![AnalysedFunctionParameter { name: "user-id".to_string(), typ: AnalysedType::Str(TypeStr), @@ -1751,7 +1755,9 @@ mod interpreter_tests { get_shopping_cart_metadata_with_cart_resource(vec![]) } - fn get_shopping_cart_metadata_with_cart_resource(constructor_parameters: Vec) -> Vec { + fn get_shopping_cart_metadata_with_cart_resource( + constructor_parameters: Vec, + ) -> Vec { let instance = AnalysedExport::Instance(AnalysedInstance { name: "golem:it/api".to_string(), functions: vec![ From 170dbcfffed057fe38ebb5bb7ea753db00d8f4ac Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Tue, 24 Sep 2024 22:27:47 +1000 Subject: [PATCH 24/27] Check if its part of resource than indexed_resource --- golem-rib/src/type_inference/function_type_inference.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/golem-rib/src/type_inference/function_type_inference.rs b/golem-rib/src/type_inference/function_type_inference.rs index 971c2a150..8ecb22f6e 100644 --- a/golem-rib/src/type_inference/function_type_inference.rs +++ b/golem-rib/src/type_inference/function_type_inference.rs @@ -57,10 +57,8 @@ mod internal { CallType::Function(dynamic_parsed_function_name) => { let parsed_function_static = dynamic_parsed_function_name.clone().to_static(); let function = parsed_function_static.clone().function; - let indexed_resource = function.is_indexed_resource(); - // If indexed resource, first we need to fetch the parameter types of th constructor - if indexed_resource { + if let Some(_) = function.resource_name() { let constructor_name = { let raw_str = function.resource_name().ok_or("Resource name not found")?; format!["[constructor]{}", raw_str] From 528bb7932aca19b69b2f9b2a1a593fd5085cce60 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Tue, 24 Sep 2024 23:31:19 +1000 Subject: [PATCH 25/27] Make grpc types backward compatible --- golem-api-grpc/proto/golem/rib/expr.proto | 14 +++- golem-rib/src/call_type.rs | 72 ++++++++++++------- golem-rib/src/expr.rs | 54 ++++++++++---- .../type_inference/function_type_inference.rs | 3 +- 4 files changed, 99 insertions(+), 44 deletions(-) diff --git a/golem-api-grpc/proto/golem/rib/expr.proto b/golem-api-grpc/proto/golem/rib/expr.proto index c83c21e97..f9bc9eadd 100644 --- a/golem-api-grpc/proto/golem/rib/expr.proto +++ b/golem-api-grpc/proto/golem/rib/expr.proto @@ -169,13 +169,23 @@ message ResultExpr { } message CallExpr { - InvocationName name = 1; + optional InvocationName name = 1; repeated Expr params = 2; + optional CallType call_type = 3; } +message CallType { + oneof name { + golem.rib.DynamicParsedFunctionName parsed = 1; + string variant_constructor = 2; + string enum_constructor = 3; + } +} + +/** Legacy call-type that holds fully formed function names and not dynamic functions. This is kept for backward compatibility */ message InvocationName { oneof name { - golem.rib.DynamicParsedFunctionName parsed = 1; + golem.rib.ParsedFunctionName parsed = 1; string variant_constructor = 2; string enum_constructor = 3; } diff --git a/golem-rib/src/call_type.rs b/golem-rib/src/call_type.rs index 37afc3864..3f752f0f9 100644 --- a/golem-rib/src/call_type.rs +++ b/golem-rib/src/call_type.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::DynamicParsedFunctionName; +use crate::{DynamicParsedFunctionName, ParsedFunctionName}; use bincode::{Decode, Encode}; use std::convert::TryFrom; use std::fmt::Display; @@ -34,49 +34,67 @@ impl Display for CallType { } } -impl TryFrom for CallType { +impl TryFrom for CallType { type Error = String; - fn try_from( - value: golem_api_grpc::proto::golem::rib::InvocationName, - ) -> Result { + fn try_from(value: golem_api_grpc::proto::golem::rib::CallType) -> Result { let invocation = value.name.ok_or("Missing name of invocation")?; match invocation { - golem_api_grpc::proto::golem::rib::invocation_name::Name::Parsed(name) => Ok( + golem_api_grpc::proto::golem::rib::call_type::Name::Parsed(name) => Ok( CallType::Function(DynamicParsedFunctionName::try_from(name)?), ), - golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor(name) => { + golem_api_grpc::proto::golem::rib::call_type::Name::VariantConstructor(name) => { Ok(CallType::VariantConstructor(name)) } - golem_api_grpc::proto::golem::rib::invocation_name::Name::EnumConstructor(name) => { + golem_api_grpc::proto::golem::rib::call_type::Name::EnumConstructor(name) => { Ok(CallType::EnumConstructor(name)) } } } } -impl From for golem_api_grpc::proto::golem::rib::InvocationName { +impl From for golem_api_grpc::proto::golem::rib::CallType { fn from(value: CallType) -> Self { match value { - CallType::Function(parsed_name) => { - golem_api_grpc::proto::golem::rib::InvocationName { - name: Some(golem_api_grpc::proto::golem::rib::invocation_name::Name::Parsed( - parsed_name.into(), - )), - } + CallType::Function(parsed_name) => golem_api_grpc::proto::golem::rib::CallType { + name: Some(golem_api_grpc::proto::golem::rib::call_type::Name::Parsed( + parsed_name.into(), + )), + }, + CallType::VariantConstructor(name) => golem_api_grpc::proto::golem::rib::CallType { + name: Some( + golem_api_grpc::proto::golem::rib::call_type::Name::VariantConstructor(name), + ), + }, + CallType::EnumConstructor(name) => golem_api_grpc::proto::golem::rib::CallType { + name: Some( + golem_api_grpc::proto::golem::rib::call_type::Name::EnumConstructor(name), + ), + }, + } + } +} + +// InvocationName is a legacy structure to keep the backward compatibility. +// InvocationName is corresponding to the new CallType and the difference here is, +// InvocationName::Function will always hold a static function name and not a dynamic one +// with Expr representing resource construction parameters +impl TryFrom for CallType { + type Error = String; + fn try_from( + value: golem_api_grpc::proto::golem::rib::InvocationName, + ) -> Result { + let invocation = value.name.ok_or("Missing name of invocation")?; + match invocation { + golem_api_grpc::proto::golem::rib::invocation_name::Name::Parsed(name) => { + Ok(CallType::Function(DynamicParsedFunctionName::parse( + ParsedFunctionName::try_from(name)?.to_string(), + )?)) } - CallType::VariantConstructor(name) => { - golem_api_grpc::proto::golem::rib::InvocationName { - name: Some(golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor( - name, - )), - } + golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor(name) => { + Ok(CallType::VariantConstructor(name)) } - CallType::EnumConstructor(name) => { - golem_api_grpc::proto::golem::rib::InvocationName { - name: Some(golem_api_grpc::proto::golem::rib::invocation_name::Name::EnumConstructor( - name, - )), - } + golem_api_grpc::proto::golem::rib::invocation_name::Name::EnumConstructor(name) => { + Ok(CallType::EnumConstructor(name)) } } } diff --git a/golem-rib/src/expr.rs b/golem-rib/src/expr.rs index 7b7e5b4ac..a6686229e 100644 --- a/golem-rib/src/expr.rs +++ b/golem-rib/src/expr.rs @@ -16,7 +16,9 @@ use crate::call_type::CallType; use crate::parser::rib_expr::rib_program; use crate::parser::type_name::TypeName; use crate::type_registry::FunctionTypeRegistry; -use crate::{text, type_inference, DynamicParsedFunctionName, InferredType, VariableId}; +use crate::{ + text, type_inference, DynamicParsedFunctionName, InferredType, ParsedFunctionName, VariableId, +}; use bincode::{Decode, Encode}; use combine::stream::position; use combine::EasyParser; @@ -1051,18 +1053,43 @@ impl TryFrom for Expr { .into_iter() .map(|expr| expr.try_into()) .collect::, _>>()?; - let invocation_name = expr.name.ok_or("Missing invocation name")?; - let name = invocation_name.name.ok_or("Missing function call name")?; - match name { - golem_api_grpc::proto::golem::rib::invocation_name::Name::Parsed(name) => { - Expr::call(name.try_into()?, params) + // This is not required and kept for backward compatibility + let legacy_invocation_name = expr.name; + let call_type = expr.call_type; + + match (legacy_invocation_name, call_type) { + (Some(legacy), None) => { + let name = legacy.name.ok_or("Missing function call name")?; + match name { + golem_api_grpc::proto::golem::rib::invocation_name::Name::Parsed(name) => { + // Reading the previous parsed-function-name in persistent store as a dynamic-parsed-function-name + Expr::call(DynamicParsedFunctionName::parse( + ParsedFunctionName::try_from(name)?.to_string() + )?, params) + } + golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor( + name, + ) => Expr::call(DynamicParsedFunctionName::parse(name)?, params), + golem_api_grpc::proto::golem::rib::invocation_name::Name::EnumConstructor( + name, + ) => Expr::call(DynamicParsedFunctionName::parse(name)?, params), + } } - golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor( - name, - ) => Expr::call(DynamicParsedFunctionName::parse(name)?, params), - golem_api_grpc::proto::golem::rib::invocation_name::Name::EnumConstructor( - name, - ) => Expr::call(DynamicParsedFunctionName::parse(name)?, params), + (_, Some(call_type)) => { + let name = call_type.name.ok_or("Missing function call name")?; + match name { + golem_api_grpc::proto::golem::rib::call_type::Name::Parsed(name) => { + Expr::call(name.try_into()?, params) + } + golem_api_grpc::proto::golem::rib::call_type::Name::VariantConstructor( + name, + ) => Expr::call(DynamicParsedFunctionName::parse(name)?, params), + golem_api_grpc::proto::golem::rib::call_type::Name::EnumConstructor( + name, + ) => Expr::call(DynamicParsedFunctionName::parse(name)?, params), + } + } + (_, _) => Err("Missing both call type (and legacy invocation type)")?, } } }; @@ -1249,8 +1276,9 @@ impl From for golem_api_grpc::proto::golem::rib::Expr { Expr::Call(function_name, args, _) => { Some(golem_api_grpc::proto::golem::rib::expr::Expr::Call( golem_api_grpc::proto::golem::rib::CallExpr { - name: Some(function_name.into()), + name: None, params: args.into_iter().map(|expr| expr.into()).collect(), + call_type: Some(function_name.into()), }, )) } diff --git a/golem-rib/src/type_inference/function_type_inference.rs b/golem-rib/src/type_inference/function_type_inference.rs index 8ecb22f6e..484d195ec 100644 --- a/golem-rib/src/type_inference/function_type_inference.rs +++ b/golem-rib/src/type_inference/function_type_inference.rs @@ -57,8 +57,7 @@ mod internal { CallType::Function(dynamic_parsed_function_name) => { let parsed_function_static = dynamic_parsed_function_name.clone().to_static(); let function = parsed_function_static.clone().function; - // If indexed resource, first we need to fetch the parameter types of th constructor - if let Some(_) = function.resource_name() { + if function.resource_name().is_some() { let constructor_name = { let raw_str = function.resource_name().ok_or("Resource name not found")?; format!["[constructor]{}", raw_str] From 61d3b824dfc5ca24151fe22a24b0cd1c0b845269 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Wed, 25 Sep 2024 00:00:32 +1000 Subject: [PATCH 26/27] Reformat code --- .../src/worker_binding/compiled_golem_worker_binding.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/golem-worker-service-base/src/worker_binding/compiled_golem_worker_binding.rs b/golem-worker-service-base/src/worker_binding/compiled_golem_worker_binding.rs index e2dbf4c28..ea45a8e8d 100644 --- a/golem-worker-service-base/src/worker_binding/compiled_golem_worker_binding.rs +++ b/golem-worker-service-base/src/worker_binding/compiled_golem_worker_binding.rs @@ -4,7 +4,7 @@ use golem_service_base::model::VersionedComponentId; use golem_wasm_ast::analysis::AnalysedExport; use rib::{Expr, RibByteCode, RibInputTypeInfo}; -#[derive(Debug, Clone, PartialEq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Encode, Decode)] pub struct CompiledGolemWorkerBinding { pub component_id: VersionedComponentId, pub worker_name_compiled: WorkerNameCompiled, From eb2f113d162d1d4a3a4de805216fd13e91ef3fb4 Mon Sep 17 00:00:00 2001 From: Afsal Thaj Date: Wed, 25 Sep 2024 00:08:57 +1000 Subject: [PATCH 27/27] Add tests --- golem-rib/src/interpreter/rib_interpreter.rs | 138 +++++++++++++++++++ 1 file changed, 138 insertions(+) diff --git a/golem-rib/src/interpreter/rib_interpreter.rs b/golem-rib/src/interpreter/rib_interpreter.rs index ebbc3ca72..0ab9b769c 100644 --- a/golem-rib/src/interpreter/rib_interpreter.rs +++ b/golem-rib/src/interpreter/rib_interpreter.rs @@ -1625,6 +1625,144 @@ mod interpreter_tests { ); } + #[tokio::test] + async fn test_interpreter_with_resource_get_cart_contents() { + let expr = r#" + let result = golem:it/api.{cart.get-cart-contents}(); + result[0].product-id + "#; + + let expr = Expr::from_text(expr).unwrap(); + + let result_type = AnalysedType::List(TypeList { + inner: Box::new(AnalysedType::Record(TypeRecord { + fields: vec![ + NameTypePair { + name: "product-id".to_string(), + typ: AnalysedType::Str(TypeStr), + }, + NameTypePair { + name: "name".to_string(), + typ: AnalysedType::Str(TypeStr), + }, + NameTypePair { + name: "price".to_string(), + typ: AnalysedType::F32(TypeF32), + }, + NameTypePair { + name: "quantity".to_string(), + typ: AnalysedType::U32(TypeU32), + }, + ], + })), + }); + + let result_value = internal::type_annotated_value_result( + &result_type, + r#" + [{product-id: "foo", name: "bar", price: 100.0, quantity: 1}, {product-id: "bar", name: "baz", price: 200.0, quantity: 2}] + "#, + ); + + let component_metadata = internal::get_shopping_cart_metadata_with_cart_raw_resource(); + let compiled = compiler::compile(&expr, &component_metadata).unwrap(); + + let mut rib_executor = internal::test_executor(&result_type, &result_value); + let result = rib_executor.run(compiled.byte_code).await.unwrap(); + + assert_eq!( + result.get_val().unwrap(), + TypeAnnotatedValue::Str("foo".to_string()) + ); + } + + #[tokio::test] + async fn test_interpreter_with_resource_update_item() { + let expr = r#" + let product_id = "mac"; + let quantity = 1032; + golem:it/api.{cart.update-item-quantity}(product_id, quantity); + "successfully updated" + "#; + let expr = Expr::from_text(expr).unwrap(); + + let component_metadata = internal::get_shopping_cart_metadata_with_cart_raw_resource(); + + let compiled = compiler::compile(&expr, &component_metadata).unwrap(); + + let mut rib_executor = Interpreter::default(); + + let result = rib_executor.run(compiled.byte_code).await.unwrap(); + + assert_eq!( + result.get_val().unwrap(), + TypeAnnotatedValue::Str("successfully updated".to_string()) + ); + } + + #[tokio::test] + async fn test_interpreter_with_resource_checkout() { + let expr = r#" + let result = golem:it/api.{cart.checkout}(); + result + "#; + + let expr = Expr::from_text(expr).unwrap(); + + let result_type = AnalysedType::Variant(TypeVariant { + cases: vec![ + NameOptionTypePair { + name: "error".to_string(), + typ: Some(AnalysedType::Str(TypeStr)), + }, + NameOptionTypePair { + name: "success".to_string(), + typ: Some(AnalysedType::Record(TypeRecord { + fields: vec![NameTypePair { + name: "order-id".to_string(), + typ: AnalysedType::Str(TypeStr), + }], + })), + }, + ], + }); + + let result_value = internal::type_annotated_value_result( + &result_type, + r#" + success({order-id: "foo"}) + "#, + ); + + let component_metadata = internal::get_shopping_cart_metadata_with_cart_raw_resource(); + let compiled = compiler::compile(&expr, &component_metadata).unwrap(); + + let mut rib_executor = internal::test_executor(&result_type, &result_value); + let result = rib_executor.run(compiled.byte_code).await.unwrap(); + + assert_eq!(result.get_val().unwrap(), result_value); + } + + #[tokio::test] + async fn test_interpreter_with_resource_drop() { + let expr = r#" + golem:it/api.{cart.drop}(); + "success" + "#; + let expr = Expr::from_text(expr).unwrap(); + let component_metadata = internal::get_shopping_cart_metadata_with_cart_raw_resource(); + + let compiled = compiler::compile(&expr, &component_metadata).unwrap(); + + let mut rib_interpreter = Interpreter::default(); + let result = rib_interpreter.run(compiled.byte_code).await.unwrap(); + + assert_eq!( + result.get_val().unwrap(), + TypeAnnotatedValue::Str("success".to_string()) + ); + } + mod internal { use crate::interpreter::env::InterpreterEnv; use crate::interpreter::stack::InterpreterStack;