// generateMemberAssignment generates the expression source for a member assignment. func (eg *expressionGenerator) generateMemberAssignment(memberAssign *codedom.MemberAssignmentNode, context generationContext) esbuilder.ExpressionBuilder { basisNode := memberAssign.BasisNode() // If the target member is an operator, then we need to invoke it as a function call, with the first // argument being the argument to the child call, and the second argument being the assigned child // expression. if memberAssign.Target.IsOperator() { childCall := memberAssign.NameExpression.(*codedom.MemberCallNode) memberRef := childCall.ChildExpression.(*codedom.MemberReferenceNode) // If this is a native operator, change it into a native indexing and assignment. if memberAssign.Target.IsNative() { nativeAssign := codedom.NativeAssign( codedom.NativeIndexing(memberRef.ChildExpression, childCall.Arguments[0], basisNode), memberAssign.Value, basisNode) return eg.generateExpression(nativeAssign, context) } else { memberCall := codedom.MemberCall( codedom.NativeAccess(memberRef.ChildExpression, eg.pather.GetMemberName(memberAssign.Target), memberRef.BasisNode()), memberAssign.Target, []codedom.Expression{childCall.Arguments[0], memberAssign.Value}, basisNode) return eg.generateExpression(memberCall, context) } } // If the target member is implicitly called, then this is a property that needs to be assigned via a call. if memberAssign.Target.IsImplicitlyCalled() { memberRef := memberAssign.NameExpression.(*codedom.MemberReferenceNode) memberCall := codedom.MemberCall( codedom.NativeAccess(memberRef.ChildExpression, eg.pather.GetSetterName(memberRef.Member), memberRef.BasisNode()), memberAssign.Target, []codedom.Expression{memberAssign.Value}, basisNode) return eg.generateExpression(memberCall, context) } value := eg.generateExpression(memberAssign.Value, context) targetExpr := eg.generateExpression(memberAssign.NameExpression, context) return esbuilder.Assignment(targetExpr, value) }
// generateMemberCall generates the expression source for a call to a module or type member. func (eg *expressionGenerator) generateMemberCall(memberCall *codedom.MemberCallNode, context generationContext) esbuilder.ExpressionBuilder { if memberCall.Member.IsOperator() && memberCall.Member.IsNative() { // This is a call to a native operator. if memberCall.Member.Name() != "index" { panic("Native call to non-index operator") } refExpr := memberCall.ChildExpression.(*codedom.MemberReferenceNode).ChildExpression return eg.generateExpression(codedom.NativeIndexing(refExpr, memberCall.Arguments[0], memberCall.BasisNode()), context) } callPath := memberCall.ChildExpression arguments := memberCall.Arguments var functionCall = codedom.FunctionCall(callPath, arguments, memberCall.BasisNode()) if memberCall.Nullable { // Invoke the function with a specialized nullable-invoke. refExpr := callPath.(*codedom.DynamicAccessNode).ChildExpression var isPromising = "false" if memberCall.Member.IsPromising() { isPromising = "true" } localArguments := []codedom.Expression{ refExpr, codedom.LiteralValue("'"+memberCall.Member.Name()+"'", refExpr.BasisNode()), codedom.LiteralValue(isPromising, memberCall.BasisNode()), codedom.ArrayLiteral(arguments, memberCall.BasisNode()), } functionCall = codedom.RuntimeFunctionCall(codedom.NullableInvokeFunction, localArguments, memberCall.BasisNode()) } return eg.generateExpression(codedom.WrapIfPromising(functionCall, memberCall.Member, memberCall.BasisNode()), context) }