public COWValueInternal(ASTVisitorContext visitorContext, SymbolDefinition symbol)
            {
                this.symbol         = this.originalSymbol = symbol;
                this.visitorContext = visitorContext;

                tableCreationScope = visitorContext.topTable;

                tableCreationScope.AddSymbolCOW(this);
            }
Exemple #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;
                }
            }
Exemple #3
0
        // Where we handle creating constants and such
        public override void VisitLiteralExpression(LiteralExpressionSyntax node)
        {
            UpdateSyntaxNode(node);

            SymbolDefinition expressionConstant = null;

            switch (node.Kind())
            {
            case SyntaxKind.NumericLiteralExpression:
                // The Roslyn AST figures out the type automagically for you based on how the token is declared :D
                // Can probably flatten out the other ones into this too
                expressionConstant = visitorContext.topTable.CreateConstSymbol(node.Token.Value.GetType(), node.Token.Value);
                break;

            case SyntaxKind.StringLiteralExpression:
                expressionConstant = visitorContext.topTable.CreateConstSymbol(typeof(string), node.Token.Value);
                break;

            case SyntaxKind.CharacterLiteralExpression:
                expressionConstant = visitorContext.topTable.CreateConstSymbol(typeof(char), node.Token.Value);
                break;

            case SyntaxKind.TrueLiteralExpression:
                expressionConstant = visitorContext.topTable.CreateConstSymbol(typeof(bool), true);
                break;

            case SyntaxKind.FalseLiteralExpression:
                expressionConstant = visitorContext.topTable.CreateConstSymbol(typeof(bool), false);
                break;

            case SyntaxKind.NullLiteralExpression:
                expressionConstant = visitorContext.topTable.CreateConstSymbol(typeof(object), null);
                break;

            default:
                base.VisitLiteralExpression(node);
                return;
            }

            if (expressionConstant != null && visitorContext.topCaptureScope != null)
            {
                visitorContext.topCaptureScope.SetToLocalSymbol(expressionConstant);
            }
        }
Exemple #4
0
        protected List <SymbolDefinition> HandleVariableDeclaration(VariableDeclarationSyntax node, SymbolDeclTypeFlags symbolType, UdonSyncMode syncMode)
        {
            UpdateSyntaxNode(node);

            bool isVar = node.Type.IsVar;

            System.Type variableType = null;

            if (!isVar)
            {
                using (ExpressionCaptureScope typeCapture = new ExpressionCaptureScope(visitorContext, null))
                {
                    Visit(node.Type);

                    if (!typeCapture.IsType())
                    {
                        throw new System.Exception($"The type or namespace name '{typeCapture.unresolvedAccessChain}' could not be found (are you missing a using directive?)");
                    }

                    variableType = typeCapture.captureType;
                }
            }

            List <SymbolDefinition> newSymbols = new List <SymbolDefinition>();

            foreach (VariableDeclaratorSyntax variableDeclarator in node.Variables)
            {
                SymbolDefinition newSymbol = null;

                string variableName = variableDeclarator.Identifier.ValueText;

                using (ExpressionCaptureScope symbolCreationScope = new ExpressionCaptureScope(visitorContext, null))
                {
                    if (!isVar)
                    {
                        newSymbol = visitorContext.topTable.CreateNamedSymbol(variableDeclarator.Identifier.ValueText, variableType, symbolType);
                    }

                    // Run the initializer if it exists
                    // Todo: Run the set on the new symbol scope from within the initializer scope for direct setting
                    if (variableDeclarator.Initializer != null && symbolType.HasFlag(SymbolDeclTypeFlags.Local))
                    {
                        using (ExpressionCaptureScope initializerCapture = new ExpressionCaptureScope(visitorContext, null, newSymbol))
                        {
                            Visit(variableDeclarator.Initializer);

                            if (newSymbol == null)
                            {
                                // TODO: Find a way to determine the return type before generating initializer code, to avoid a copy on 'var' local initializers
                                variableType = initializerCapture.GetReturnType(true);
                                newSymbol    = visitorContext.topTable.CreateNamedSymbol(variableDeclarator.Identifier.ValueText, variableType, symbolType);
                            }

                            symbolCreationScope.SetToLocalSymbol(newSymbol);
                            symbolCreationScope.ExecuteSet(initializerCapture.ExecuteGet());
                        }
                    }

                    newSymbol.syncMode = syncMode;
                }

                VerifySyncValidForType(newSymbol.symbolCsType, syncMode);
                newSymbols.Add(newSymbol);
            }

            if (!visitorContext.resolverContext.IsValidUdonType(variableType))
            {
                throw new System.NotSupportedException($"Udon does not support variables of type '{variableType.Name}' yet");
            }

            return(newSymbols);
        }
Exemple #5
0
        private List <System.Attribute> GetFieldAttributes(FieldDeclarationSyntax node)
        {
            List <System.Attribute> attributes = new List <System.Attribute>();

            if (node.AttributeLists != null)
            {
                foreach (AttributeListSyntax attributeList in node.AttributeLists)
                {
                    UpdateSyntaxNode(attributeList);

                    foreach (AttributeSyntax attribute in attributeList.Attributes)
                    {
                        using (ExpressionCaptureScope attributeTypeCapture = new ExpressionCaptureScope(visitorContext, null))
                        {
                            attributeTypeCapture.isAttributeCaptureScope = true;
                            Visit(attribute.Name);

                            System.Type captureType = attributeTypeCapture.captureType;

                            if (captureType == typeof(UdonSyncedAttribute))
                            {
                                UdonSyncMode syncMode = UdonSyncMode.NotSynced;

                                if (attribute.ArgumentList == null ||
                                    attribute.ArgumentList.Arguments == null ||
                                    attribute.ArgumentList.Arguments.Count == 0)
                                {
                                    syncMode = UdonSyncMode.None;
                                }
                                else
                                {
                                    using (ExpressionCaptureScope attributeCaptureScope = new ExpressionCaptureScope(visitorContext, null))
                                    {
                                        Visit(attribute.ArgumentList.Arguments[0].Expression);

                                        if (!attributeCaptureScope.IsEnum())
                                        {
                                            throw new System.Exception("Invalid attribute argument provided for sync");
                                        }

                                        syncMode = (UdonSyncMode)attributeCaptureScope.GetEnumValue();
                                    }
                                }
                                attributes.Add(new UdonSyncedAttribute(syncMode));
                            }
                            else if (captureType != null)
                            {
                                try
                                {
                                    object attributeObject = null;

                                    if (attribute.ArgumentList == null ||
                                        attribute.ArgumentList.Arguments == null ||
                                        attribute.ArgumentList.Arguments.Count == 0)
                                    {
                                        attributeObject = System.Activator.CreateInstance(captureType);
                                    }
                                    else
                                    {
                                        // todo: requires constant folding to support decently
                                        object[] attributeArgs = new object[attribute.ArgumentList.Arguments.Count];

                                        for (int i = 0; i < attributeArgs.Length; ++i)
                                        {
                                            AttributeArgumentSyntax attributeArg = attribute.ArgumentList.Arguments[i];

                                            using (ExpressionCaptureScope attributeCapture = new ExpressionCaptureScope(visitorContext, null))
                                            {
                                                Visit(attributeArg);

                                                SymbolDefinition attrSymbol = attributeCapture.ExecuteGet();

                                                if (!attrSymbol.declarationType.HasFlag(SymbolDeclTypeFlags.Constant))
                                                {
                                                    throw new System.ArgumentException("Attributes do not support non-constant expressions");
                                                }

                                                attributeArgs[i] = attrSymbol.symbolDefaultValue;
                                            }
                                        }

                                        attributeObject = System.Activator.CreateInstance(captureType, attributeArgs);
                                    }

                                    if (attributeObject != null)
                                    {
                                        attributes.Add((System.Attribute)attributeObject);
                                    }
                                }
                                catch (System.Reflection.TargetInvocationException constructionException)
                                {
                                    throw constructionException.InnerException;
                                }
                            }
                        }
                    }
                }
            }

            return(attributes);
        }
 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);
 }
        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);
        }
Exemple #12
0
 public FieldDefinition(SymbolDefinition symbol)
 {
     fieldSymbol     = symbol;
     fieldAttributes = new List <System.Attribute>();
 }