public override Value EmitSet(EmitContext context, BoundExpression valueExpression)
            {
                Value.CowValue sourceValue = null;

                if (!Field.IsStatic)
                {
                    sourceValue = GetInstanceValue(context);
                }

                Value expressionResult = context.EmitValue(valueExpression);

                if (sourceValue != null)
                {
                    context.Module.AddPush(sourceValue.Value);
                }

                context.Module.AddPush(expressionResult);

                context.Module.AddExternSet(Field);

                if (sourceValue != null)
                {
                    if (SourceExpression.ValueType.IsValueType &&
                        SourceExpression is BoundAccessExpression sourceAccessExpression)
                    {
                        context.EmitSet(sourceAccessExpression, BindAccess(sourceValue.Value));
                    }
                }

                return(expressionResult);
            }
Ejemplo n.º 2
0
        protected Value[] GetParameterValues(EmitContext context)
        {
            Value.CowValue[] parameterCows = context.GetExpressionCowValues(this, "parameters");

            if (parameterCows != null)
            {
                return(parameterCows.Select(e => e.Value).ToArray());
            }

            parameterCows = new Value.CowValue[ParameterExpressions.Length];

            using (context.InterruptAssignmentScope())
            {
                for (int i = 0; i < parameterCows.Length; ++i)
                {
                    parameterCows[i] = context.EmitValueWithDeferredRelease(ParameterExpressions[i])
                                       .GetCowValue(context);
                }
            }

            context.RegisterCowValues(parameterCows, this, "parameters");

            Value[] parameterValues = new Value[ParameterExpressions.Length];

            for (int i = 0; i < parameterValues.Length; ++i)
            {
                parameterValues[i] = parameterCows[i].Value;
            }

            return(parameterValues);
        }
        private BoundExpression[] GetParameters(EmitContext context, BoundExpression valueExpression = null)
        {
            using (context.InterruptAssignmentScope())
            {
                Value.CowValue[] propertyParams = context.GetExpressionCowValues(this, "propertyParams");

                if (propertyParams == null)
                {
                    if (ParameterExpressions != null)
                    {
                        propertyParams = new Value.CowValue[ParameterExpressions.Length];

                        for (int i = 0; i < propertyParams.Length; ++i)
                        {
                            propertyParams[i] = context.EmitValue(ParameterExpressions[i]).GetCowValue(context);
                        }
                    }
                    else
                    {
                        propertyParams = Array.Empty <Value.CowValue>();
                    }

                    context.RegisterCowValues(propertyParams, this, "propertyParams");
                }

                List <BoundExpression> expressions = new List <BoundExpression>();
                expressions.AddRange(propertyParams.Select(BindAccess));
                if (valueExpression != null)
                {
                    expressions.Add(valueExpression);
                }

                return(expressions.ToArray());
            }
        }
            public override Value EmitValue(EmitContext context)
            {
                Value returnValue = context.GetReturnValue(Field.Type);

                Value.CowValue sourceValue = null;

                if (!Field.IsStatic)
                {
                    sourceValue = GetInstanceValue(context);
                }

                if (sourceValue != null)
                {
                    context.Module.AddPush(sourceValue.Value);
                }

                context.Module.AddPush(returnValue);

                context.Module.AddExternGet(Field);

                return(returnValue);
            }
Ejemplo n.º 5
0
 public static BoundAccessExpression BindAccess(Value.CowValue value)
 {
     return(new BoundCowValueAccessExpression(value));
 }
Ejemplo n.º 6
0
 public BoundCowValueAccessExpression(Value.CowValue value)
     : base(null, null)
 {
     AccessValue = value;
     ValueType   = value.Value.UserType;
 }
Ejemplo n.º 7
0
        public override Value EmitValue(EmitContext context)
        {
            // Make base calls to UdonSharpBehaviour events a noop
            if (IsBaseCall)
            {
                if (Method.ContainingType == context.GetTypeSymbol(typeof(UdonSharpBehaviour)))
                {
                    if (Method.Name == "OnOwnershipRequest")
                    {
                        return(context.GetConstantValue(context.GetTypeSymbol(SpecialType.System_Boolean), true));
                    }

                    return(null);
                }
            }

            if (SourceExpression == null || SourceExpression.IsThis)
            {
                return(base.EmitValue(context));
            }

            // Calls across UdonBehaviours
            CompilationContext.MethodExportLayout layout =
                context.CompileContext.GetUsbMethodLayout(Method, context);

            Value.CowValue        instanceCowValue = GetInstanceValue(context);
            Value                 instanceValue    = instanceCowValue.Value;
            BoundAccessExpression instanceAccess   = BoundAccessExpression.BindAccess(instanceValue);

            TypeSymbol stringType = context.GetTypeSymbol(SpecialType.System_String);

            Value[] recursiveValues   = null;
            Value   stackSizeCheckVal = null;
            bool    isRecursiveCall   = context.IsRecursiveMethodEmit;

            if (isRecursiveCall)
            {
                stackSizeCheckVal = context.CreateGlobalInternalValue(context.GetTypeSymbol(SpecialType.System_Int32));
            }

            if (Method.Parameters.Length > 0)
            {
                MethodSymbol setProgramVariableMethod = context.GetTypeSymbol(typeof(UdonSharpBehaviour))
                                                        .GetMembers <MethodSymbol>("SetProgramVariable", context)
                                                        .First(e => e.Parameters.Length == 2 &&
                                                               e.Parameters[0].Type == stringType);

                Value[] parameterValues = GetParameterValues(context);
                instanceValue  = instanceCowValue.Value;
                instanceAccess = BoundAccessExpression.BindAccess(instanceValue); // Re-bind here since the parameters may have changed the cowvalue

                if (isRecursiveCall)
                {
                    EmitContext.MethodLinkage selfLinkage = context.GetMethodLinkage(context.CurrentEmitMethod, false);
                    recursiveValues = selfLinkage.ParameterValues;

                    CheckStackSize(stackSizeCheckVal, context);
                    PushRecursiveValues(recursiveValues, context);

                    for (int i = 0; i < parameterValues.Length; ++i)
                    {
                        Value paramIntermediate = context.CreateInternalValue(parameterValues[i].UserType);
                        context.Module.AddCopy(parameterValues[i], paramIntermediate);
                        parameterValues[i] = paramIntermediate;
                    }
                }
                else
                {
                    instanceCowValue.Dispose();
                }

                context.TopTable.DirtyAllValues();

                for (int i = 0; i < Method.Parameters.Length; ++i)
                {
                    context.Emit(CreateBoundInvocation(context, SyntaxNode, setProgramVariableMethod, instanceAccess,
                                                       new BoundExpression[]
                    {
                        BoundAccessExpression.BindAccess(context.GetConstantValue(stringType, layout.ParameterExportNames[i])),
                        BoundAccessExpression.BindAccess(parameterValues[i])
                    }));
                }
            }

            if (isRecursiveCall)
            {
                if (recursiveValues == null)
                {
                    recursiveValues = Array.Empty <Value>();
                }

                Value[] scopeValues = context.CollectRecursiveValues();

                PushRecursiveValues(scopeValues, context);

                recursiveValues = recursiveValues.Concat(scopeValues).ToArray();

                stackSizeCheckVal.DefaultValue = recursiveValues.Length;
                context.UpdateRecursiveStackMaxSize(recursiveValues.Length);
            }

            MethodSymbol sendCustomEventMethod = context.GetTypeSymbol(typeof(UdonSharpBehaviour)).GetMember <MethodSymbol>("SendCustomEvent", context);

            context.Emit(CreateBoundInvocation(context, SyntaxNode, sendCustomEventMethod, BoundAccessExpression.BindAccess(instanceValue),
                                               new BoundExpression[]
            {
                BoundAccessExpression.BindAccess(context.GetConstantValue(stringType, layout.ExportMethodName))
            }));

            if (isRecursiveCall)
            {
                PopRecursiveValues(recursiveValues, context);
            }

            if (Method.Parameters.Length > 0 &&
                Method.Parameters.Any(e => e.IsOut))
            {
                if (isRecursiveCall)
                {
                    throw new CompilerException("U# does not yet support calling user methods with ref/out parameters from methods marked with RecursiveMethod");
                }

                MethodSymbol getProgramVariableMethod = context.GetTypeSymbol(typeof(UdonSharpBehaviour))
                                                        .GetMembers <MethodSymbol>("GetProgramVariable", context)
                                                        .First(e => e.Parameters.Length == 1 &&
                                                               e.Parameters[0].Type == stringType);

                // Copy out/ref parameters back
                for (int i = 0; i < Method.Parameters.Length; ++i)
                {
                    ParameterSymbol parameterSymbol = Method.Parameters[i];

                    if (parameterSymbol.IsOut)
                    {
                        BoundAccessExpression currentAccessExpression = (BoundAccessExpression)ParameterExpressions[i];

                        currentAccessExpression.EmitSet(context, CreateBoundInvocation(context, SyntaxNode,
                                                                                       getProgramVariableMethod, instanceAccess, new[]
                        {
                            BoundAccessExpression.BindAccess(context.GetConstantValue(stringType,
                                                                                      layout.ParameterExportNames[i]))
                        }));
                    }
                }
            }

            if (IsPropertySetter)
            {
                return(GetParameterValues(context).Last());
            }

            if (Method.ReturnType != null)
            {
                MethodSymbol getProgramVariableMethod = context.GetTypeSymbol(typeof(UdonSharpBehaviour))
                                                        .GetMembers <MethodSymbol>("GetProgramVariable", context)
                                                        .First(e => e.Parameters.Length == 1 &&
                                                               e.Parameters[0].Type == stringType);

                Value returnVal = context.CreateInternalValue(Method.ReturnType);

                BoundInvocationExpression boundGetReturn = CreateBoundInvocation(context, SyntaxNode,
                                                                                 getProgramVariableMethod, instanceAccess,
                                                                                 new BoundExpression[]
                {
                    BoundAccessExpression.BindAccess(context.GetConstantValue(stringType,
                                                                              layout.ReturnExportName))
                });

                context.EmitValueAssignment(returnVal, boundGetReturn);

                return(returnVal);
            }

            return(null);
        }
Ejemplo n.º 8
0
        public override Value EmitValue(EmitContext context)
        {
            var module = context.Module;

            Value.CowValue instanceValue = null;

            using (context.InterruptAssignmentScope())
            {
                if (!Method.IsStatic && !Method.IsConstructor)
                {
                    instanceValue = GetInstanceValue(context);

                    // Prevent mutating a value constant if you call a method on the constant for some reason
                    // todo: fix for use with the cowvalues
                    // if (instanceValue.IsConstant && instanceValue.UserType.IsValueType &&
                    //     Method.Name != "ToString" && Method.Name != "Equals") // Common non-mutating methods
                    // {
                    //     Value proxyInstanceValue = context.CreateInternalValue(instanceValue.UserType);
                    //     module.AddCopy(instanceValue, proxyInstanceValue);
                    //     instanceValue = proxyInstanceValue;
                    // }
                }
            }

            Value[] parameterValues = GetParameterValues(context);

            if (instanceValue != null)
            {
                module.AddPush(instanceValue.Value);
            }

            Value[] recursiveValues = null;

            string methodName = Method.Name;

            if (methodName == "SendCustomEvent" ||
                methodName == "SendCustomNetworkEvent" ||
                methodName == "RunProgram")
            {
                if (context.IsRecursiveMethodEmit)
                {
                    recursiveValues = context.CollectRecursiveValues();
                    CheckStackSize(context.GetConstantValue(context.GetTypeSymbol(SpecialType.System_Int32), recursiveValues.Length), context);
                    PushRecursiveValues(recursiveValues, context);
                    context.UpdateRecursiveStackMaxSize(recursiveValues.Length);
                }
                else
                {
                    instanceValue?.Dispose();
                }

                context.TopTable.DirtyAllValues();
            }

            foreach (Value value in parameterValues)
            {
                module.AddPush(value);
            }

            Value returnValue = null;

            if (IsPropertySetter)
            {
                returnValue = parameterValues.Last();
            }

            if (Method.ReturnType != null)
            {
                returnValue = context.GetReturnValue(Method.ReturnType);
                if (returnValue.IsConstant)
                {
                    throw new InvalidOperationException("Cannot return to const value");
                }

                module.AddPush(returnValue);
            }

            module.AddExtern(externMethodSymbol);

            if (recursiveValues != null)
            {
                PopRecursiveValues(recursiveValues, context);
            }

            return(returnValue);
        }