Exemple #1
0
        public override ExpressionSyntax GenerateExpression(VisualScriptCompilerContext context)
        {
            var expression = ParseExpression(Expression);

            // Forward diagnostics to log
            foreach (var diagnostic in expression.GetDiagnostics())
            {
                LogMessageType logType;
                switch (diagnostic.Severity)
                {
                case DiagnosticSeverity.Info:
                    logType = LogMessageType.Info;
                    break;

                case DiagnosticSeverity.Warning:
                    logType = LogMessageType.Warning;
                    break;

                case DiagnosticSeverity.Error:
                    logType = LogMessageType.Error;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                context.Log.Log(new LogMessage(nameof(CustomExpression), logType, diagnostic.GetMessage()));
            }

            return(expression);
        }
Exemple #2
0
 public ExpressionSyntax GenerateExpression(VisualScriptCompilerContext context, Slot slot)
 {
     // TODO: Out/ref
     // Other cases should have been handled by context.RegisterLocalVariable during code generation
     // It's also possible that this block is actually not executed and used as input, so we issue a warning anyway
     context.Log.Error($"No value found for slot {slot}. Note that out/ref slots are not implemented yet.", CallerInfo.Get());
     return(null);
 }
Exemple #3
0
        public override ExpressionSyntax GenerateExpression(VisualScriptCompilerContext context)
        {
            if (Name == null)
            {
                return(IdentifierName("variable_not_set"));
            }

            return(IdentifierName(Name));
        }
Exemple #4
0
        public override void GenerateCode(VisualScriptCompilerContext context)
        {
            var arguments           = new List <SyntaxNodeOrToken>();
            var memberCallProcessed = false;

            var invocationTarget = MethodName;

            for (int index = 0; index < Slots.Count; index++)
            {
                var slot = Slots[index];
                if (slot.Direction == SlotDirection.Input && slot.Kind == SlotKind.Value)
                {
                    var argument = context.GenerateExpression(slot);

                    if (IsMemberCall && !memberCallProcessed)
                    {
                        // this parameter (non-static or extension method)
                        memberCallProcessed = true;
                        invocationTarget    = argument.ToFullString() + "." + invocationTarget;
                        continue;
                    }

                    if (arguments.Count > 0)
                    {
                        arguments.Add(Token(SyntaxKind.CommaToken));
                    }

                    arguments.Add(Argument(argument));
                }
            }

            var expression = InvocationExpression(ParseExpression(invocationTarget), ArgumentList(SeparatedList <ArgumentSyntax>(arguments)));
            var statement  = (StatementSyntax)ExpressionStatement(expression);

            // Only store return variable if somebody is using it
            if (ReturnSlot != null && context.FindOutputLinks(ReturnSlot).Any())
            {
                var localVariableName = context.GenerateLocalVariableName();

                // Store return value in a local variable
                statement =
                    LocalDeclarationStatement(
                        VariableDeclaration(
                            IdentifierName("var"))
                        .WithVariables(
                            SingletonSeparatedList <VariableDeclaratorSyntax>(
                                VariableDeclarator(
                                    Identifier(localVariableName))
                                .WithInitializer(
                                    EqualsValueClause(expression)))));

                context.RegisterLocalVariable(ReturnSlot, localVariableName);
            }

            context.AddStatement(statement);
        }
Exemple #5
0
        //[DataMemberIgnore]
        //public Slot OutputSlot => FindSlot(SlotDirection.Output, SlotKind.Value, null);

        public override void GenerateCode(VisualScriptCompilerContext context)
        {
            if (Name == null)
            {
                return;
            }

            // Evaluate value
            var newValue = context.GenerateExpression(InputSlot);

            // Generate assignment statement
            context.AddStatement(ExpressionStatement(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(Name), newValue)));
        }
Exemple #6
0
        public override void GenerateCode(VisualScriptCompilerContext context)
        {
            // Create local variable that will store the item
            var itemVariableName = context.GenerateLocalVariableName("item");

            context.RegisterLocalVariable(ItemSlot, itemVariableName);

            // Switch to "continue" instead of "return" in case there is no next node
            var wasInsideLoop = context.IsInsideLoop;

            context.IsInsideLoop = true;

            var innerBlockStatements = context.ProcessInnerLoop(LoopSlot);

            context.IsInsideLoop = wasInsideLoop;

            context.AddStatement(ForEachStatement(IdentifierName("var"), itemVariableName, context.GenerateExpression(CollectionSlot), Block(innerBlockStatements)));
        }
Exemple #7
0
        public override void GenerateCode(VisualScriptCompilerContext context)
        {
            // Generate false then true block (false block will be reached if the previous condition failed), then true block (reached by goto)
            var falseBlock = context.GetOrCreateBasicBlockFromSlot(FalseSlot);
            var trueBlock  = context.GetOrCreateBasicBlockFromSlot(TrueSlot);

            // Generate condition
            var condition = context.GenerateExpression(ConditionSlot);

            // if (condition) goto trueBlock;
            if (trueBlock != null)
            {
                context.AddStatement(IfStatement(condition, context.CreateGotoStatement(trueBlock)));
            }

            // Execution continue in false block
            context.CurrentBasicBlock.NextBlock = falseBlock;
        }
Exemple #8
0
 public override void GenerateCode(VisualScriptCompilerContext context)
 {
     // Nothing to do (since we have autoflow on Start slot)
 }
Exemple #9
0
 public abstract ExpressionSyntax GenerateExpression(VisualScriptCompilerContext context);
Exemple #10
0
 ExpressionSyntax IExpressionBlock.GenerateExpression(VisualScriptCompilerContext context, Slot slot)
 {
     return(GenerateExpression(context));
 }
Exemple #11
0
 public abstract void GenerateCode(VisualScriptCompilerContext context);
Exemple #12
0
        public override void GenerateCode(VisualScriptCompilerContext context)
        {
            var blockStatement = ParseStatement($"{{ {Code} }}");

            // Forward diagnostics to log
            foreach (var diagnostic in blockStatement.GetDiagnostics())
            {
                LogMessageType logType;
                switch (diagnostic.Severity)
                {
                case DiagnosticSeverity.Info:
                    logType = LogMessageType.Info;
                    break;

                case DiagnosticSeverity.Warning:
                    logType = LogMessageType.Warning;
                    break;

                case DiagnosticSeverity.Error:
                    logType = LogMessageType.Error;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                context.Log.Log(new LogMessage(nameof(CustomCodeBlock), logType, diagnostic.GetMessage()));
            }

            var block = blockStatement as BlockSyntax;

            if (block != null)
            {
                RoslynHelper.CreateCompilationUnitFromBlock(ref block);

                foreach (var slot in Slots.Where(x => x.Kind == SlotKind.Value))
                {
                    var symbolsToReplace = block.DescendantNodes()
                                           .OfType <IdentifierNameSyntax>()
                                           .Where(x => x.Identifier.Text == slot.Name)
                                           .Where(x =>
                    {
                        // We can never be on the right side of a member access
                        var memberAccess = (x.Parent as MemberAccessExpressionSyntax);
                        return(memberAccess == null || memberAccess.Expression == x);
                    })
                                           .ToArray();

                    if (slot.Direction == SlotDirection.Input)
                    {
                        // Input
                        // Find expression
                        var expression = context.GenerateExpression(slot);
                        block = block.ReplaceNodes(symbolsToReplace, (x1, x2) => expression);
                    }
                    else
                    {
                        // Output

                        // Replace every reference of slot.Name into generated slotName
                        var slotName = context.GenerateLocalVariableName(slot.Name);
                        block = block.ReplaceNodes(symbolsToReplace, (x1, x2) => x1.WithIdentifier(Identifier(slotName)));

                        // Register a local var with generated name
                        context.RegisterLocalVariable(slot, slotName);
                    }
                }

                foreach (var statement in block.Statements)
                {
                    context.AddStatement(statement);
                }
            }
        }
Exemple #13
0
        public static VisualScriptCompilerResult Generate(VisualScriptAsset visualScriptAsset, VisualScriptCompilerOptions options)
        {
            var result = new VisualScriptCompilerResult();

            var members   = new List <MemberDeclarationSyntax>();
            var className = options.Class;

            // Generate variables
            foreach (var variable in visualScriptAsset.Properties)
            {
                var variableType = variable.Type;
                if (variableType == null)
                {
                    result.Error($"Variable {variable.Name} has no type, using \"object\" instead.");
                    variableType = "object";
                }

                var field =
                    FieldDeclaration(
                        VariableDeclaration(
                            ParseTypeName(variableType))
                        .WithVariables(
                            SingletonSeparatedList(
                                VariableDeclarator(
                                    Identifier(variable.Name)))))
                    .WithModifiers(
                        TokenList(
                            Token(SyntaxKind.PublicKeyword)));

                members.Add(field);
            }

            // Process each function
            foreach (var method in visualScriptAsset.Methods)
            {
                var functionStartBlock = method.Blocks.Values.OfType <FunctionStartBlock>().FirstOrDefault();
                if (functionStartBlock == null)
                {
                    continue;
                }

                var context = new VisualScriptCompilerContext(visualScriptAsset, method, result);

                context.ProcessEntryBlock(functionStartBlock);

                var methodModifiers = new SyntaxTokenList();
                methodModifiers = ConvertAccessibility(methodModifiers, method.Accessibility);
                methodModifiers = ConvertVirtualModifier(methodModifiers, method.VirtualModifier);
                if (method.IsStatic)
                {
                    methodModifiers = methodModifiers.Add(Token(SyntaxKind.StaticKeyword));
                }

                var parameters = new List <SyntaxNodeOrToken>();
                foreach (var parameter in method.Parameters)
                {
                    if (parameters.Count > 0)
                    {
                        parameters.Add(Token(SyntaxKind.CommaToken));
                    }

                    parameters.Add(
                        Parameter(Identifier(parameter.Name))
                        .WithModifiers(ConvertRefKind(parameter.RefKind))
                        .WithType(ParseTypeName(parameter.Type)));
                }

                // Generate method
                var methodDeclaration =
                    MethodDeclaration(
                        method.ReturnType == "void" ? PredefinedType(Token(SyntaxKind.VoidKeyword)) : ParseTypeName(method.ReturnType),
                        Identifier(method.Name))
                    .WithModifiers(methodModifiers)
                    .WithParameterList(ParameterList(
                                           SeparatedList <ParameterSyntax>(parameters)))
                    .WithBody(
                        Block(context.Blocks.SelectMany(x => x.Statements)))
                    .WithAdditionalAnnotations(GenerateAnnotation(method));

                members.Add(methodDeclaration);
            }

            // Generate class
            var classModifiers = new SyntaxTokenList();

            classModifiers = ConvertAccessibility(classModifiers, visualScriptAsset.Accessibility).Add(Token(SyntaxKind.PartialKeyword));
            if (visualScriptAsset.IsStatic)
            {
                classModifiers = classModifiers.Add(Token(SyntaxKind.StaticKeyword));
            }

            var @class =
                ClassDeclaration(className)
                .WithMembers(List(members))
                .WithModifiers(classModifiers);

            if (visualScriptAsset.BaseType != null)
            {
                @class = @class.WithBaseList(BaseList(SingletonSeparatedList <BaseTypeSyntax>(SimpleBaseType(IdentifierName(visualScriptAsset.BaseType)))));
            }

            // Generate namespace around class (if any)
            MemberDeclarationSyntax namespaceOrClass = @class;
            var @namespace = !string.IsNullOrEmpty(visualScriptAsset.Namespace) ? visualScriptAsset.Namespace : options.DefaultNamespace;

            if (@namespace != null)
            {
                namespaceOrClass =
                    NamespaceDeclaration(
                        IdentifierName(@namespace))
                    .WithMembers(
                        SingletonList <MemberDeclarationSyntax>(@class));
            }

            // Generate compilation unit
            var compilationUnit =
                CompilationUnit()
                .WithUsings(
                    List(visualScriptAsset.UsingDirectives.Select(x =>
                                                                  UsingDirective(
                                                                      IdentifierName(x)))))
                .WithMembers(
                    SingletonList(namespaceOrClass))
                .NormalizeWhitespace();

            // Generate actual source code
            result.GeneratedSource = compilationUnit.ToFullString();
            result.SyntaxTree      = SyntaxTree(compilationUnit, path: options.FilePath ?? string.Empty);

            return(result);
        }