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); }
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); }
public static BoundAccessExpression BindAccess(Value.CowValue value) { return(new BoundCowValueAccessExpression(value)); }
public BoundCowValueAccessExpression(Value.CowValue value) : base(null, null) { AccessValue = value; ValueType = value.Value.UserType; }
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); }
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); }