public SymbolDefinition CreateReflectionSymbol(string name, System.Type type, object value)
        {
            if (value != null && !type.IsAssignableFrom(value.GetType()))
            {
                throw new ArgumentException($"Non-compatible value given for type {type.FullName}");
            }

            SymbolDefinition symbolDefinition = GetReflectionSymbol(name, type);

            if (symbolDefinition == null)
            {
                symbolDefinition = CreateNamedSymbol(name, type, SymbolDeclTypeFlags.Internal | SymbolDeclTypeFlags.Constant | SymbolDeclTypeFlags.Reflection);
                symbolDefinition.symbolDefaultValue = value;
            }

            return(symbolDefinition);
        }
예제 #2
0
            public void MarkDirty()
            {
                if (referenceCount == 0)
                {
                    isDirty = true;
                    symbol  = null;
                    return;
                }

                if (!isDirty)
                {
                    SymbolDefinition temporary = visitorContext.topTable.CreateUnnamedSymbol(symbol.internalType, SymbolDeclTypeFlags.Internal | SymbolDeclTypeFlags.Local);
                    visitorContext.uasmBuilder.AddCopy(temporary, symbol, " Copy-on-write symbol value dirtied");
                    symbol  = temporary;
                    isDirty = true;
                }
            }
        public SymbolDefinition GetReflectionSymbol(string name, System.Type type)
        {
            SymbolDefinition symbolDefinition = null;

            SymbolTable globalSymbols = GetGlobalSymbolTable();

            foreach (SymbolDefinition currentSymbol in globalSymbols.symbolDefinitions)
            {
                if (currentSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Reflection) &&
                    currentSymbol.symbolOriginalName == name &&
                    currentSymbol.symbolCsType == type)
                {
                    symbolDefinition = currentSymbol;
                    break;
                }
            }

            return(symbolDefinition);
        }
예제 #4
0
        public override void VisitFieldDeclaration(FieldDeclarationSyntax node)
        {
            bool isPublic = node.Modifiers.HasModifier("public");

            System.Type fieldType = null;

            using (ExpressionCaptureScope fieldTypeCapture = new ExpressionCaptureScope(visitorContext, null))
            {
                Visit(node.Declaration.Type);

                fieldType = fieldTypeCapture.captureType;
            }

            foreach (VariableDeclaratorSyntax variableDeclarator in node.Declaration.Variables)
            {
                SymbolDefinition newSymbol = visitorContext.topTable.CreateNamedSymbol(variableDeclarator.Identifier.ValueText, fieldType, isPublic ? SymbolDeclTypeFlags.Public : SymbolDeclTypeFlags.Private);

                classDefinition.fieldDefinitions.Add(new FieldDefinition(newSymbol));
            }
        }
예제 #5
0
        /// <summary>
        /// Tries to find a global constant that already has a given constant value to avoid duplication
        /// </summary>
        /// <param name="type"></param>
        /// <param name="value"></param>
        /// <param name="foundSymbol"></param>
        /// <returns></returns>
        public bool TryGetGlobalConstSymbol(System.Type type, object value, out SymbolDefinition foundSymbol)
        {
            SymbolTable globalSymTable = GetGlobalSymbolTable();

            foreach (SymbolDefinition definition in globalSymTable.symbolDefinitions)
            {
                if (definition.declarationType.HasFlag(SymbolDeclTypeFlags.Constant) &&
                    definition.declarationType.HasFlag(SymbolDeclTypeFlags.Internal) &&
                    definition.symbolCsType == type &&
                    ((value == null && definition.symbolDefaultValue == null) ||
                     (definition.symbolDefaultValue != null && definition.symbolDefaultValue.Equals(value))))
                {
                    foundSymbol = definition;
                    return(true);
                }
            }

            foundSymbol = null;
            return(false);
        }
        /// <summary>
        /// Tries to find a global constant that already has a given constant value to avoid duplication
        /// </summary>
        /// <param name="type"></param>
        /// <param name="value"></param>
        /// <param name="foundSymbol"></param>
        /// <returns></returns>
        public bool TryGetGlobalSymbol(System.Type type, object value, out SymbolDefinition foundSymbol, SymbolDeclTypeFlags flags)
        {
            SymbolTable globalSymTable = GetGlobalSymbolTable();

            foreach (SymbolDefinition definition in globalSymTable.symbolDefinitions)
            {
                bool hasFlags = ((int)flags & (int)definition.declarationType) == (int)flags;

                if (hasFlags &&
                    definition.symbolCsType == type &&
                    ((value == null && definition.symbolDefaultValue == null) ||
                     (definition.symbolDefaultValue != null && definition.symbolDefaultValue.Equals(value))))
                {
                    foundSymbol = definition;
                    return(true);
                }
            }

            foundSymbol = null;
            return(false);
        }
예제 #7
0
        public SymbolDefinition FindUserDefinedSymbol(string symbolName)
        {
            SymbolTable currentTable = this;

            while (currentTable != null)
            {
                //foreach (SymbolDefinition symbolDefinition in currentTable.symbolDefinitions)
                for (int i = currentTable.symbolDefinitions.Count - 1; i >= 0; --i)
                {
                    SymbolDefinition symbolDefinition = currentTable.symbolDefinitions[i];

                    if (!symbolDefinition.declarationType.HasFlag(SymbolDeclTypeFlags.Internal) &&
                        symbolDefinition.symbolOriginalName == symbolName)
                    {
                        return(symbolDefinition);
                    }
                }

                currentTable = currentTable.parentSymbolTable;
            }

            // Found nothing, return null
            return(null);
        }
 public void AddCopy(SymbolDefinition target, SymbolDefinition source, string comment = "")
 {
     AddPush(source);
     AddPush(target);
     AddCopy(comment);
 }
 public void AddReturnSequence(SymbolDefinition returnTrampolineSymbol, string comment = "")
 {
     AddPush(returnTrampolineSymbol, comment);
     AddCopy();
     AddJumpIndirect(returnTrampolineSymbol);
 }
 public void AddJumpIndirect(SymbolDefinition addressSymbol, string comment = "")
 {
     AppendCommentedLine($"JUMP_INDIRECT, {addressSymbol.symbolUniqueName}", comment);
     programCounter += UdonSharpUtils.GetUdonInstructionSize("JUMP_INDIRECT");
 }
 public void AddJumpIfFalse(JumpLabel jumpTarget, SymbolDefinition conditionSymbol, string comment = "")
 {
     AddPush(conditionSymbol);
     AddJumpIfFalse(jumpTarget, comment);
 }
 public void AddPush(SymbolDefinition heapAddressSymbol, string comment = "")
 {
     AddPush(heapAddressSymbol.symbolUniqueName, comment);
 }
예제 #13
0
        /// <summary>
        /// Create a symbol given a name. At the moment assumes that only internal symbols get incremented, this means there's no masking at the moment for local variables.
        /// </summary>
        /// <param name="symbolName"></param>
        /// <param name="resolvedSymbolType"></param>
        /// <param name="declType"></param>
        /// <param name="appendType">Used to disable redundant type append from unnamed variable allocations</param>
        /// <returns></returns>
        private SymbolDefinition CreateNamedSymbolInternal(string symbolName, System.Type resolvedSymbolType, SymbolDeclTypeFlags declType, bool appendType = true)
        {
            if (resolvedSymbolType == null || symbolName == null)
            {
                throw new System.ArgumentNullException();
            }

            if (!declType.HasFlag(SymbolDeclTypeFlags.Internal) && symbolName.StartsWith("__"))
            {
                throw new System.ArgumentException($"Symbol {symbolName} cannot have name starting with \"__\", this naming is reserved for internal variables.");
            }

            string uniqueSymbolName = symbolName;

            bool hasGlobalDeclaration = false;

            if (declType.HasFlag(SymbolDeclTypeFlags.Internal))
            {
                uniqueSymbolName = $"intnl_{uniqueSymbolName}";
            }
            if (declType.HasFlag(SymbolDeclTypeFlags.Constant))
            {
                uniqueSymbolName     = $"const_{uniqueSymbolName}";
                hasGlobalDeclaration = true;
            }
            if (declType.HasFlag(SymbolDeclTypeFlags.This))
            {
                uniqueSymbolName     = $"this_{uniqueSymbolName}";
                hasGlobalDeclaration = true;
            }

            if (!declType.HasFlag(SymbolDeclTypeFlags.Public) && !declType.HasFlag(SymbolDeclTypeFlags.Private))
            {
                if (appendType)
                {
                    string sanitizedName = resolver.SanitizeTypeName(resolvedSymbolType.Name);
                    uniqueSymbolName += $"_{sanitizedName}";
                }

                if (hasGlobalDeclaration)
                {
                    uniqueSymbolName = $"__{IncrementGlobalNameCounter(uniqueSymbolName)}_{uniqueSymbolName}";
                }
                else
                {
                    uniqueSymbolName = $"__{IncrementUniqueNameCounter(uniqueSymbolName)}_{uniqueSymbolName}";
                }
            }

            System.Type typeForName = resolvedSymbolType;
            if (resolvedSymbolType == typeof(UdonSharpBehaviour) || resolvedSymbolType.IsSubclassOf(typeof(UdonSharpBehaviour)))
            {
                typeForName = typeof(VRC.Udon.UdonBehaviour);
            }
            else if (resolvedSymbolType.IsArray && (resolvedSymbolType.GetElementType() == typeof(UdonSharpBehaviour) || resolvedSymbolType.GetElementType().IsSubclassOf(typeof(UdonSharpBehaviour))))
            {
                typeForName = typeof(Component[]); // Hack because VRC doesn't expose UdonBehaviour array type
            }
            string udonTypeName = resolver.GetUdonTypeName(typeForName);

            if (udonTypeName == null)
            {
                throw new System.ArgumentException($"Could not locate Udon type for system type {resolvedSymbolType.FullName}");
            }

            udonTypeName = udonTypeName.Replace("VRCUdonCommonInterfacesIUdonEventReceiver", "VRCUdonUdonBehaviour");

            SymbolDefinition symbolDefinition = new SymbolDefinition();

            symbolDefinition.declarationType        = declType;
            symbolDefinition.symbolCsType           = resolvedSymbolType;
            symbolDefinition.symbolOriginalName     = symbolName;
            symbolDefinition.symbolResolvedTypeName = udonTypeName;
            symbolDefinition.symbolUniqueName       = uniqueSymbolName;

            if (hasGlobalDeclaration)
            {
                GetGlobalSymbolTable().symbolDefinitions.Add(symbolDefinition);
            }
            else
            {
                symbolDefinitions.Add(symbolDefinition);
            }

            return(symbolDefinition);
        }
예제 #14
0
 public FieldDefinition(SymbolDefinition symbol)
 {
     fieldSymbol     = symbol;
     fieldAttributes = new List <System.Attribute>();
 }
예제 #15
0
 public void AddJumpIndirect(SymbolDefinition addressSymbol, string comment = "")
 {
     //throw new System.NotImplementedException("Jump indirect instruction is not implemented in UdonSharp yet."); // I'm not sure why JUMP_INDIRECT both takes an address and pops an address from the stack
     AppendCommentedLine($"JUMP_INDIRECT, {addressSymbol.symbolUniqueName}", comment);
     programCounter += UdonSharpUtils.GetUdonInstructionSize("JUMP_INDIRECT");
 }
예제 #16
0
        public SymbolDefinition Invoke(SymbolDefinition[] invokeParams)
        {
            SymbolDefinition methodResult = null;

            System.Type resultSymbolType = null;
            string      lookupSymbolName = null;

            switch (captureFunc)
            {
            case InternalFunc.TypeIDInstance:
            case InternalFunc.TypeIDGeneric:
                resultSymbolType = typeof(long);
                lookupSymbolName = "udonTypeID";
                break;

            case InternalFunc.TypeNameInstance:
            case InternalFunc.TypeNameGeneric:
                resultSymbolType = typeof(string);
                lookupSymbolName = "udonTypeName";
                break;

            default:
                throw new System.ArgumentException("Invalid internal method invocation");
            }

            methodResult = visitorContext.topTable.CreateUnnamedSymbol(resultSymbolType, SymbolDeclTypeFlags.Internal);

            if (captureFunc == InternalFunc.TypeIDInstance ||
                captureFunc == InternalFunc.TypeNameInstance)
            {
                SymbolDefinition invokeSymbol = captureScope.accessSymbol;

                using (ExpressionCaptureScope resultSetterScope = new ExpressionCaptureScope(visitorContext, null))
                {
                    resultSetterScope.SetToLocalSymbol(methodResult);

                    using (ExpressionCaptureScope getInvokeScope = new ExpressionCaptureScope(visitorContext, null))
                    {
                        getInvokeScope.SetToLocalSymbol(invokeSymbol);
                        getInvokeScope.ResolveAccessToken(nameof(VRC.Udon.UdonBehaviour.GetProgramVariable));

                        string symbolName = visitorContext.topTable.GetReflectionSymbol(lookupSymbolName, resultSymbolType).symbolUniqueName;

                        SymbolDefinition invokeResult = getInvokeScope.Invoke(new SymbolDefinition[] { visitorContext.topTable.CreateConstSymbol(typeof(string), symbolName) });

                        JumpLabel exitBranchJump = visitorContext.labelTable.GetNewJumpLabel("exitUdonTypeIdLoc");
                        JumpLabel falseBranchLoc = visitorContext.labelTable.GetNewJumpLabel("falseUdonTypeIdLoc");

                        SymbolDefinition nullCheckSymbol = null;

                        using (ExpressionCaptureScope nullCheckCondition = new ExpressionCaptureScope(visitorContext, null))
                        {
                            nullCheckCondition.SetToMethods(UdonSharpUtils.GetOperators(typeof(object), BuiltinOperatorType.Inequality));
                            nullCheckSymbol = nullCheckCondition.Invoke(new SymbolDefinition[] { invokeResult, visitorContext.topTable.CreateConstSymbol(typeof(object), null) });
                        }

                        visitorContext.uasmBuilder.AddJumpIfFalse(falseBranchLoc, nullCheckSymbol);

                        resultSetterScope.ExecuteSet(captureScope.CastSymbolToType(invokeResult, resultSymbolType, true));
                        visitorContext.uasmBuilder.AddJump(exitBranchJump);

                        // If the value is null
                        visitorContext.uasmBuilder.AddJumpLabel(falseBranchLoc);

                        if (captureFunc == InternalFunc.TypeIDInstance)
                        {
                            resultSetterScope.ExecuteSet(visitorContext.topTable.CreateConstSymbol(typeof(long), 0L));
                        }
                        else
                        {
                            resultSetterScope.ExecuteSet(visitorContext.topTable.CreateConstSymbol(typeof(string), "UnknownType"));
                        }

                        visitorContext.uasmBuilder.AddJumpLabel(exitBranchJump);
                    }
                }
            }
            else
            {
                object resultSymbolValue = null;

                if (captureFunc == InternalFunc.TypeIDGeneric)
                {
                    resultSymbolValue = Internal.UdonSharpInternalUtility.GetTypeID(genericType);
                }
                else if (captureFunc == InternalFunc.TypeNameGeneric)
                {
                    resultSymbolValue = Internal.UdonSharpInternalUtility.GetTypeName(genericType);
                }

                methodResult = visitorContext.topTable.CreateConstSymbol(resultSymbolType, resultSymbolValue);
            }

            using (ExpressionCaptureScope propagateScope = new ExpressionCaptureScope(visitorContext, visitorContext.topCaptureScope))
            {
                propagateScope.SetToLocalSymbol(methodResult);
            }

            return(methodResult);
        }