diff --git a/golem-api-grpc/proto/golem/rib/expr.proto b/golem-api-grpc/proto/golem/rib/expr.proto index fb5690c0d7..f9bc9eadde 100644 --- a/golem-api-grpc/proto/golem/rib/expr.proto +++ b/golem-api-grpc/proto/golem/rib/expr.proto @@ -169,10 +169,20 @@ 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.ParsedFunctionName parsed = 1; @@ -217,3 +227,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 aa9dc5370e..49cf695d7d 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-api-grpc/proto/golem/rib/ir.proto b/golem-api-grpc/proto/golem/rib/ir.proto index 4225db4728..f5f0d7f5a7 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/call_type.rs b/golem-rib/src/call_type.rs index f0ef76e7d4..3f752f0f95 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), } @@ -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(CallType::Function(ParsedFunctionName::try_from(name)?)) - } - golem_api_grpc::proto::golem::rib::invocation_name::Name::VariantConstructor(name) => { + golem_api_grpc::proto::golem::rib::call_type::Name::Parsed(name) => Ok( + CallType::Function(DynamicParsedFunctionName::try_from(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/compiler/byte_code.rs b/golem-rib/src/compiler/byte_code.rs index 8b970b9872..86af7a7c13 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, } @@ -84,7 +83,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, RibIR, + }; use golem_wasm_ast::analysis::AnalysedType; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; @@ -251,11 +253,121 @@ mod internal { )?) }; - instructions.push(RibIR::InvokeFunction( - parsed_function_name.clone(), - 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( + site, + FunctionReferenceType::Function { + function: function.clone(), + }, + )), + + DynamicParsedFunctionReference::RawResourceConstructor { resource } => { + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::RawResourceConstructor { + resource: resource.clone(), + }, + )) + } + DynamicParsedFunctionReference::RawResourceDrop { resource } => { + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::RawResourceDrop { + resource: resource.clone(), + }, + )) + } + DynamicParsedFunctionReference::RawResourceMethod { + resource, + method, + } => instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::RawResourceMethod { + resource: resource.clone(), + method: method.clone(), + }, + )), + DynamicParsedFunctionReference::RawResourceStaticMethod { + resource, + method, + } => instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::RawResourceStaticMethod { + resource: resource.clone(), + method: method.clone(), + }, + )), + DynamicParsedFunctionReference::IndexedResourceConstructor { + resource, + resource_params, + } => { + for param in resource_params { + stack.push(ExprState::from_expr(param)); + } + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::IndexedResourceConstructor { + resource: resource.clone(), + arg_size: resource_params.len(), + }, + )) + } + DynamicParsedFunctionReference::IndexedResourceMethod { + resource, + resource_params, + method, + } => { + for param in resource_params { + stack.push(ExprState::from_expr(param)); + } + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::IndexedResourceMethod { + resource: resource.clone(), + arg_size: resource_params.len(), + method: method.clone(), + }, + )) + } + DynamicParsedFunctionReference::IndexedResourceStaticMethod { + resource, + resource_params, + method, + } => { + for param in resource_params { + stack.push(ExprState::from_expr(param)); + } + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::IndexedResourceStaticMethod { + resource: resource.clone(), + arg_size: resource_params.len(), + method: method.clone(), + }, + )) + } + DynamicParsedFunctionReference::IndexedResourceDrop { + resource, + resource_params, + } => { + for param in resource_params { + stack.push(ExprState::from_expr(param)); + } + instructions.push(RibIR::CreateFunctionName( + site, + FunctionReferenceType::IndexedResourceDrop { + resource: resource.clone(), + arg_size: resource_params.len(), + }, + )) + } + } } CallType::VariantConstructor(variant_name) => { @@ -380,6 +492,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 efb7c0d5c3..2d7722e30b 100644 --- a/golem-rib/src/compiler/ir.rs +++ b/golem-rib/src/compiler/ir.rs @@ -12,20 +12,20 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{AnalysedTypeWithUnit, ParsedFunctionName, 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::{ - And, CallInstruction, ConcatInstruction, EqualTo, GetTag, GreaterThan, GreaterThanOrEqualTo, - JumpInstruction, LessThan, LessThanOrEqualTo, Negate, PushListInstruction, PushNoneInstruction, - PushTupleInstruction, RibIr as ProtoRibIR, + 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}; // 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), @@ -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,160 @@ pub enum RibIR { Negate, } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Encode, Decode)] +pub enum FunctionReferenceType { + 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 { + 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 { + 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 resource = raw_resource_method.resource_name; + let method = raw_resource_method.method_name; + FunctionReferenceType::RawResourceMethod { resource, method } + } + golem_api_grpc::proto::golem::rib::function_reference_type::Type::RawResourceStaticMethod(raw_resource_static_method) => { + let resource = raw_resource_static_method.resource_name; + let method = raw_resource_static_method.method_name; + FunctionReferenceType::RawResourceStaticMethod{ resource, method } + } + golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceConstructor(indexed_resource_constructor) => { + 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 resource = indexed_resource_method.resource_name; + let arg_size = indexed_resource_method.arg_size; + let method = indexed_resource_method.method_name; + 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 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 { resource, arg_size: arg_size as usize, method } + } + golem_api_grpc::proto::golem::rib::function_reference_type::Type::IndexedResourceDrop(indexed_resource_drop) => { + 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) + } +} + +impl From for golem_api_grpc::proto::golem::rib::FunctionReferenceType { + fn from(value: FunctionReferenceType) -> Self { + match value { + 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: function + })) + }, + 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 + })) + }, + 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 + })) + }, + 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: resource, + method_name: method + })) + }, + 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: resource, + method_name: method + })) + }, + 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, + arg_size: arg_size as u32 + })) + }, + 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, + arg_size: arg_size as u32, + method_name: method + })) + }, + 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, + arg_size: arg_size as u32, + method_name: method + })) + }, + 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, + 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 @@ -186,8 +341,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, )) @@ -244,6 +397,20 @@ 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.try_into()?; + + Ok(RibIR::CreateFunctionName( + parsed_function_site, + function_reference_type, + )) + } } } } @@ -293,7 +460,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) => { @@ -303,7 +470,6 @@ impl From for ProtoRibIR { }; Instruction::Call(CallInstruction { - function_name: name.to_string(), argument_count: arg_count as u64, return_type: typ, }) @@ -347,6 +513,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 { diff --git a/golem-rib/src/expr.rs b/golem-rib/src/expr.rs index 3b7d6cf08d..a6686229ea 100644 --- a/golem-rib/src/expr.rs +++ b/golem-rib/src/expr.rs @@ -13,11 +13,12 @@ // 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; -use crate::{text, type_inference, InferredType, VariableId}; +use crate::{ + text, type_inference, DynamicParsedFunctionName, InferredType, ParsedFunctionName, VariableId, +}; use bincode::{Decode, Encode}; use combine::stream::position; use combine::EasyParser; @@ -30,7 +31,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 +257,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, ) @@ -697,6 +698,8 @@ 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 { @@ -721,7 +724,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 +738,7 @@ impl MatchArm { } } } -#[derive(Debug, Clone, PartialEq, Encode, Decode)] +#[derive(Debug, Clone, PartialEq, Eq, Encode, Decode)] pub enum ArmPattern { WildCard, As(String, Box), @@ -1050,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(ParsedFunctionName::parse(name)?, params), - golem_api_grpc::proto::golem::rib::invocation_name::Name::EnumConstructor( - name, - ) => Expr::call(ParsedFunctionName::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)")?, } } }; @@ -1248,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/function_name.rs b/golem-rib/src/function_name.rs index 0b3f8af3dd..ab76052110 100644 --- a/golem-rib/src/function_name.rs +++ b/golem-rib/src/function_name.rs @@ -12,9 +12,11 @@ // See the License for the specific language governing permissions and // limitations under the License. +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::protobuf::type_annotated_value::TypeAnnotatedValue; use golem_wasm_rpc::type_annotated_value_from_str; @@ -266,6 +268,143 @@ pub enum ParsedFunctionReference { }, } +#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] +pub 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(text::to_raw_string).collect(), + }, + Self::IndexedResourceMethod { + resource, + resource_params, + method, + } => ParsedFunctionReference::IndexedResourceMethod { + resource: resource.clone(), + resource_params: resource_params.iter().map(text::to_raw_string).collect(), + method: method.clone(), + }, + Self::IndexedResourceStaticMethod { + resource, + resource_params, + method, + } => ParsedFunctionReference::IndexedResourceStaticMethod { + resource: resource.clone(), + resource_params: resource_params.iter().map(text::to_raw_string).collect(), + method: method.clone(), + }, + Self::IndexedResourceDrop { + resource, + resource_params, + } => ParsedFunctionReference::IndexedResourceDrop { + resource: resource.clone(), + resource_params: resource_params.iter().map(text::to_raw_string).collect(), + }, + } + } + + 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), + _ => 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 { let function_name = match self { @@ -430,6 +569,143 @@ 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.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.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.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.into()).collect(), + }, + ), + }; + + golem_api_grpc::proto::golem::rib::DynamicParsedFunctionReference { + function_reference: Some(function), + } + } +} + +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(Expr::try_from).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(Expr::try_from).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(Expr::try_from).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(Expr::try_from).collect::, String>>()?; + + Ok(Self::IndexedResourceDrop { resource, resource_params }) + }, + } + } +} + impl TryFrom for ParsedFunctionReference { @@ -598,6 +874,52 @@ pub struct ParsedFunctionName { pub function: ParsedFunctionReference, } +#[derive(Debug, PartialEq, Eq, Clone, Encode, Decode)] +pub struct DynamicParsedFunctionName { + pub site: ParsedFunctionSite, + pub function: DynamicParsedFunctionReference, +} + +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) + } + } + } + + pub fn function_name(&self) -> String { + self.to_static().function.function_name() + } + + // + pub fn to_static(&self) -> ParsedFunctionName { + ParsedFunctionName { + site: self.site.clone(), + function: self.function.to_static(), + } + } +} + +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(); @@ -651,11 +973,11 @@ 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 { - Ok((parsed, _)) => Ok(parsed), + Ok((parsed, _)) => Ok(parsed.to_static()), Err(error) => { let error_message = error .map_position(|p| p.translate_position(name)) @@ -681,6 +1003,33 @@ 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 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; @@ -943,7 +1292,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!( @@ -959,7 +1308,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(), ], }, }, @@ -1209,7 +1558,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!( @@ -1225,7 +1574,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/inferred_type.rs b/golem-rib/src/inferred_type.rs index eba310a539..17188b3b74 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/env.rs b/golem-rib/src/interpreter/env.rs index 6a33817bf3..8340887253 100644 --- a/golem-rib/src/interpreter/env.rs +++ b/golem-rib/src/interpreter/env.rs @@ -13,9 +13,10 @@ // 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::fmt::Debug; use std::future::Future; use std::pin::Pin; use std::sync::Arc; @@ -25,9 +26,17 @@ 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( - ParsedFunctionName, + String, Vec, ) -> Pin> + Send>> + Send @@ -56,7 +65,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 90c38928c6..0ab9b769ce 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, @@ -135,8 +136,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 +215,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 std::collections::VecDeque; use std::ops::Deref; @@ -350,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))?; @@ -534,15 +543,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 a value 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(), @@ -559,12 +566,208 @@ 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 { function } => { + let parsed_function_name = ParsedFunctionName { + site, + function: ParsedFunctionReference::Function { function }, + }; + + 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, method } => { + 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, arg_size } => { + let last_n_elements = interpreter + .stack + .pop_n(arg_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::, String>>()?, + }, + }; + + interpreter + .stack + .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); + } + FunctionReferenceType::IndexedResourceMethod { + resource, + arg_size, + method, + } => { + let last_n_elements = interpreter + .stack + .pop_n(arg_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::, String>>()?, + method, + }, + }; + + interpreter + .stack + .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); + } + FunctionReferenceType::IndexedResourceStaticMethod { + resource, + arg_size, + method, + } => { + let last_n_elements = interpreter + .stack + .pop_n(arg_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::, String>>()?, + method, + }, + }; + + interpreter + .stack + .push_val(TypeAnnotatedValue::Str(parsed_function_name.to_string())); + } + FunctionReferenceType::IndexedResourceDrop { resource, arg_size } => { + let last_n_elements = interpreter + .stack + .pop_n(arg_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::IndexedResourceDrop { + resource, + resource_params: type_anntoated_values + .iter() + .map(type_annotated_value_to_string) + .collect::, String>>()?, + }, + }; + + 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> { + 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) @@ -581,7 +784,7 @@ mod internal { 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 { @@ -779,7 +982,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, TypeF32, TypeList, TypeRecord, TypeS32, + TypeStr, TypeU32, TypeVariant, }; use golem_wasm_rpc::protobuf::type_annotated_value::TypeAnnotatedValue; use golem_wasm_rpc::protobuf::{NameValuePair, TypedList, TypedRecord}; @@ -1222,8 +1426,352 @@ mod interpreter_tests { ); } + #[tokio::test] + async fn test_interpreter_with_indexed_resource_drop() { + let expr = r#" + let user_id = "user"; + golem:it/api.{cart(user_id).drop}(); + "success" + "#; + let expr = Expr::from_text(expr).unwrap(); + let component_metadata = + internal::get_shopping_cart_metadata_with_cart_resource_with_parameters(); + + 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()) + ); + } + + #[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 { + 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_resource_with_parameters(); + 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_indexed_resource_get_cart_contents() { + let expr = r#" + let user_id = "bar"; + let result = golem:it/api.{cart(user_id).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_resource_with_parameters(); + 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_indexed_resource_update_item_quantity() { + 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 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 updated".to_string()) + ); + } + + #[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_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(); + + 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_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; + 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 { @@ -1332,5 +1880,258 @@ mod interpreter_tests { }], })] } + + 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: constructor_parameters, + 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] + } + + 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_executor( + 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()), + }], + })) + } + }) + }) + } } } diff --git a/golem-rib/src/interpreter/stack.rs b/golem-rib/src/interpreter/stack.rs index eda6ef4de9..385ba0246e 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, } @@ -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 d07c6e18b8..b29012c38d 100644 --- a/golem-rib/src/parser/call.rs +++ b/golem-rib/src/parser/call.rs @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +use crate::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; use combine::error::Commit; use combine::parser::char::{alpha_num, string}; use combine::parser::char::{char, spaces}; @@ -20,9 +21,7 @@ use combine::sep_by; use combine::{any, attempt, between, choice, many1, optional, parser, token, ParseError, Parser}; use crate::expr::Expr; -use crate::function_name::{ - ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, SemVer, -}; +use crate::function_name::{ParsedFunctionSite, SemVer}; use crate::parser::errors::RibParseError; use crate::parser::rib_expr::rib_expr; @@ -46,11 +45,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 +76,10 @@ where nesting += 1; current_param.push(next_char); } else if next_char == ',' && nesting == 1 { - result.push(current_param.trim().to_string()); + let expr = + Expr::from_text(current_param.trim()).expect("Failed to parse expression"); + + result.push(expr); current_param.clear(); } else { current_param.push(next_char); @@ -94,7 +92,9 @@ where } if !current_param.is_empty() { - result.push(current_param.trim().to_string()); + let expr = + Expr::from_text(current_param.trim()).expect("Failed to parse expression"); + result.push(expr); } Ok((result, result_committed.unwrap())) @@ -112,44 +112,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, + } }, ); let indexed_drop_syntax = (indexed_resource_syntax(), token('.'), string("drop")).map( - |((resource, resource_params), _, _)| ParsedFunctionReference::IndexedResourceDrop { + |((resource, resource_params), _, _)| DynamicParsedFunctionReference::IndexedResourceDrop { resource, resource_params, }, ); 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, + 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 +168,7 @@ where ); let raw_static_method_syntax = (string("[static]"), identifier(), token('.'), identifier()) .map( - |(_, resource, _, method)| ParsedFunctionReference::RawResourceStaticMethod { + |(_, resource, _, method)| DynamicParsedFunctionReference::RawResourceStaticMethod { resource, method, }, @@ -194,23 +205,21 @@ 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}; 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] @@ -219,9 +228,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 +249,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 +268,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 +287,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 +310,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 +334,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 +359,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 +385,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 +407,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 +429,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 +451,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 +474,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 +496,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 +518,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 +540,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 +562,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 +584,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 +603,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 +624,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 +648,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 +672,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 +696,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 +720,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 +747,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(), + Expr::literal("hello"), + Expr::number(1f64), + Expr::boolean(true), ], }, }, @@ -768,18 +777,21 @@ 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(), + Expr::literal("hello"), + Expr::record(vec![( + "field-a".to_string(), + Expr::option(Some(Expr::number(1f64))), + )]), ], }, }, @@ -795,14 +807,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 +830,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 +856,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 +881,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 +906,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 +930,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 +955,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(), + Expr::literal("hello"), + Expr::number(1f64), + Expr::boolean(true), ], }, }, @@ -973,18 +985,21 @@ 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(), + Expr::literal("hello"), + Expr::record(vec![( + "field-a".to_string(), + Expr::option(Some(Expr::number(1f64))), + )]), ], }, }, @@ -1001,14 +1016,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/parser/multi_line_code_block.rs b/golem-rib/src/parser/multi_line_code_block.rs index 07b7dca8d9..11cf775271 100644 --- a/golem-rib/src/parser/multi_line_code_block.rs +++ b/golem-rib/src/parser/multi_line_code_block.rs @@ -67,7 +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}; #[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 8d1f8b2f9f..6221c3a3de 100644 --- a/golem-rib/src/parser/rib_expr.rs +++ b/golem-rib/src/parser/rib_expr.rs @@ -187,9 +187,8 @@ mod tests { use crate::expr::ArmPattern; use crate::expr::MatchArm; - use crate::function_name::ParsedFunctionName; - use crate::function_name::ParsedFunctionReference::RawResourceStaticMethod; use crate::function_name::ParsedFunctionSite::PackagedInterface; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; use super::*; @@ -265,14 +264,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 18565ce3b7..0c00550393 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) } +// 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_without_interpolation(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 9db0afae23..0e61945f1c 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-rib/src/type_inference/expr_visitor.rs b/golem-rib/src/type_inference/expr_visitor.rs index 5750f16c10..0f7ea5d142 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 364501eab1..484d195eca 100644 --- a/golem-rib/src/type_inference/function_type_inference.rs +++ b/golem-rib/src/type_inference/function_type_inference.rs @@ -12,8 +12,8 @@ // 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; pub fn infer_function_types( @@ -25,40 +25,12 @@ 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 +40,156 @@ pub fn infer_function_types( } mod internal { - use crate::Expr; + use crate::call_type::CallType; + 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, + 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(); + let function = parsed_function_static.clone().function; + 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] + }; + + let mut constructor_params: &mut Vec = &mut vec![]; + + if let Some(resource_params) = dynamic_parsed_function_name + .function + .raw_resource_params_mut() + { + constructor_params = resource_params + } + + let registry_key = RegistryKey::from_function_name( + &parsed_function_static.site, + constructor_name.as_str(), + ); + + // Infer the types of constructor parameter expressions + infer_types( + &FunctionNameInternal::ResourceConstructorName(constructor_name), + function_type_registry, + registry_key, + constructor_params, + inferred_type, + )?; + + // 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, + resource_method_name.as_str(), + ); + + infer_types( + &FunctionNameInternal::ResourceMethodName(resource_method_name), + function_type_registry, + registry_key, + args, + inferred_type, + ) + } else { + let registry_key = RegistryKey::from_invocation_name(call_type); + infer_types( + &FunctionNameInternal::Fqn(parsed_function_static), + function_type_registry, + registry_key, + args, + inferred_type, + ) + } + } + + _ => Ok(()), + } + } + + fn infer_types( + function_name: &FunctionNameInternal, + function_type_registry: &FunctionTypeRegistry, + key: RegistryKey, + args: &mut [Expr], + 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, + } => { + let mut parameter_types = parameter_types.clone(); + + if let FunctionNameInternal::ResourceMethodName(_) = function_name { + if let Some(AnalysedType::Handle(_)) = parameter_types.first() { + parameter_types.remove(0); + } + } + + if parameter_types.len() == args.len() { + for (arg, param_type) in args.iter_mut().zip(parameter_types) { + check_function_arguments(¶m_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(()) + } + + 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( @@ -249,11 +369,9 @@ 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, - VariableId, - }; + use crate::{Expr, InferredType, ParsedFunctionSite, VariableId}; use golem_wasm_ast::analysis::{ AnalysedExport, AnalysedFunction, AnalysedFunctionParameter, AnalysedType, TypeU32, TypeU64, }; @@ -295,9 +413,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 c5b8f5b6a9..38cd59b858 100644 --- a/golem-rib/src/type_inference/mod.rs +++ b/golem-rib/src/type_inference/mod.rs @@ -52,11 +52,9 @@ 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::{Expr, InferredType, Number, ParsedFunctionSite, VariableId}; #[test] fn test_simple_let_binding_type_inference() { @@ -83,9 +81,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 +138,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 +152,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(), }, }), @@ -1019,11 +1017,12 @@ 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, + ParsedFunctionSite, VariableId, }; #[test] @@ -1076,9 +1075,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 +1095,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(), }, }), @@ -1886,10 +1885,11 @@ 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, - ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, VariableId, + ParsedFunctionSite, VariableId, }; use golem_wasm_ast::analysis::TypeVariant; use golem_wasm_ast::analysis::{ @@ -2063,9 +2063,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 +2546,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 08613afbbe..e8cc50ef94 100644 --- a/golem-rib/src/type_inference/name_binding.rs +++ b/golem-rib/src/type_inference/name_binding.rs @@ -74,10 +74,8 @@ mod internal { #[cfg(test)] mod name_binding_tests { use crate::call_type::CallType; - use crate::{ - Expr, InferredType, ParsedFunctionName, ParsedFunctionReference, ParsedFunctionSite, - VariableId, - }; + use crate::function_name::{DynamicParsedFunctionName, DynamicParsedFunctionReference}; + use crate::{Expr, InferredType, ParsedFunctionSite, VariableId}; #[test] fn test_name_binding_simple() { @@ -99,9 +97,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 +144,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 +158,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 +205,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 +219,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 54331fbdca..2fc0ebb79c 100644 --- a/golem-rib/src/type_inference/type_pull_up.rs +++ b/golem-rib/src/type_inference/type_pull_up.rs @@ -246,7 +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}; #[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(); diff --git a/golem-rib/src/type_registry.rs b/golem-rib/src/type_registry.rs index 0fccf8de31..dad0f6a04f 100644 --- a/golem-rib/src/type_registry.rs +++ b/golem-rib/src/type_registry.rs @@ -13,6 +13,7 @@ // 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}; @@ -38,17 +39,26 @@ 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) => { 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(), }, }, } @@ -64,7 +74,7 @@ pub enum RegistryValue { }, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct FunctionTypeRegistry { pub types: HashMap, } 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 753169b289..50cd8a067b 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 c524d10740..ea45a8e8d1 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, 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 5d5d8c4496..3e35427c53 100644 --- a/golem-worker-service-base/src/worker_bridge_execution/mod.rs +++ b/golem-worker-service-base/src/worker_bridge_execution/mod.rs @@ -4,14 +4,13 @@ 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)] 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-base/src/worker_service_rib_interpreter/mod.rs b/golem-worker-service-base/src/worker_service_rib_interpreter/mod.rs index ae71b6d666..e19d8d9b66 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, @@ -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(); diff --git a/golem-worker-service/src/worker_bridge_request_executor.rs b/golem-worker-service/src/worker_bridge_request_executor.rs index 0ed9af9b8f..fb44ae78ca 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.into_target_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(),