Exemple #1
0
        private static CommonSyntaxNode TransformRootVisualBasic(Roslyn.Compilers.VisualBasic.SyntaxNode originalRoot)
        {
            var comments = originalRoot.DescendantTrivia().Where(t => t.Kind == Roslyn.Compilers.VisualBasic.SyntaxKind.CommentTrivia);
            var newRoot = originalRoot.ReplaceTrivia(comments, (t1, t2) => Roslyn.Compilers.VisualBasic.SyntaxTriviaList.Empty);

            return newRoot;
        }
Exemple #2
0
        public override SyntaxNode VisitLocalDeclarationStatement(LocalDeclarationStatementSyntax node)
        {
            var awaitExpr      = null as ExpressionSyntax;
            var extraStatement = null as StatementSyntax;

            if (node.Declaration.Variables.Count == 1)
            {
                var variable = node
                               .Declaration
                               .Variables[0];

                var value = variable
                            ?.Initializer
                            ?.Value;

                if (node.Declaration.Type.ToString() == "await")
                {
                    //case: await signal;
                    awaitExpr = CSharp.IdentifierName(variable.Identifier);
                }
                else if (value != null && value is AwaitExpressionSyntax)
                {
                    //case: var a = await b();
                    extraStatement = CSharp
                                     .LocalDeclarationStatement(CSharp.VariableDeclaration(
                                                                    node.Declaration.Type, CSharp.SeparatedList(new[] {
                        CSharp.VariableDeclarator(variable.Identifier)
                    })));

                    awaitExpr = CSharp.AssignmentExpression(
                        SyntaxKind.SimpleAssignmentExpression,
                        CSharp.IdentifierName(variable.Identifier),
                        (value as AwaitExpressionSyntax)
                        .Expression);
                }
            }

            if (awaitExpr != null)
            {
                var result = VisitExpressionStatement(Templates
                                                      .AwaitExpr
                                                      .Get <ExpressionStatementSyntax>(awaitExpr))
                             as StatementSyntax;

                if (extraStatement != null)
                {
                    var block = Roslyn.TrackNode(CSharp.Block(
                                                     extraStatement,
                                                     result));

                    var document = _scope.GetDocument();
                    document.change(node.Parent, Roslyn.ExplodeBlock(block));
                    return(block);
                }

                return(result);
            }

            return(base.VisitLocalDeclarationStatement(node));
        }
Exemple #3
0
        private static MethodDeclarationSyntax createRemoteMethod(MethodDeclarationSyntax method)
        {
            var original = method;

            var args = CSharp
                       .AnonymousObjectCreationExpression(CSharp.SeparatedList(method
                                                                               .ParameterList
                                                                               .Parameters
                                                                               .Select(parameter =>
            {
                var identifierName = CSharp.IdentifierName(parameter.Identifier);
                return(CSharp.AnonymousObjectMemberDeclarator(
                           CSharp.NameEquals(identifierName),
                           identifierName));
            })));

            var value = original
                        .ReturnType.ToString() == "void"
                ? Roslyn.@null
                : Templates
                        .RemoteResult
                        .Get <ExpressionSyntax>(original.ReturnType);

            return(method
                   .WithModifiers(CSharp.TokenList())
                   .AddModifiers(
                       CSharp.Token(SyntaxKind.ProtectedKeyword),
                       CSharp.Token(SyntaxKind.OverrideKeyword))
                   .WithBody(Templates
                             .RemoteInternalMethod
                             .Get <BlockSyntax>(
                                 Roslyn.Quoted(original.Identifier.ToString()),
                                 args,
                                 value)));
        }
Exemple #4
0
        public Signal AddSignal()
        {
            var signal = AddSignal(Roslyn.uniqueId(), false);

            signal.Internal = true;
            return(signal);
        }
Exemple #5
0
        private StatementSyntax LinkAssignment(AssignmentExpressionSyntax assignment, InvocationExpressionSyntax success, InvocationExpressionSyntax failure, Dictionary <string, TypeSyntax> assignments)
        {
            var leftString = assignment.Left.ToString();
            var leftType   = Roslyn.SymbolTypeSyntax(_model, assignment.Left);

            Debug.Assert(assignment.Left is IdentifierNameSyntax);
            Debug.Assert(!assignments.ContainsKey(leftString));
            Debug.Assert(leftType != null); //td: error

            assignments[leftString] = leftType;

            var emptyAssignments = new Dictionary <string, TypeSyntax>();
            var right            = LinkOperand(assignment.Right, success, failure, emptyAssignments);

            Debug.Assert(right != null);
            Debug.Assert(!emptyAssignments.Any());

            //there are 2 scenarios, first, the right operand was a concurrent expression
            //in which case it would have a success function
            var successFunc = right
                              .DescendantNodes()
                              .OfType <ParenthesizedLambdaExpressionSyntax>()
                              .Where(fn => fn
                                     .ParameterList
                                     .Parameters
                                     .Any(p => p.Identifier.ToString() == "__res"))
                              .SingleOrDefault();

            if (successFunc != null)
            {
                return(right.ReplaceNode(successFunc, successFunc
                                         .WithBody(CSharp.Block(new[] {
                    Templates
                    .ExpressionAssigment
                    .Get <StatementSyntax>(assignment.Left, leftType)
                }
                                                                .Union(successFunc.Body is BlockSyntax
                            ? (successFunc.Body as BlockSyntax)
                                                                       .Statements
                                                                       .AsEnumerable()
                            : new[] { successFunc.Body as StatementSyntax })
                                                                .ToArray()))));
            }

            //else, we need to substitute the actual Right expr by
            //an assignment.
            var rightString = assignment.Right.ToString();

            return(right.ReplaceNodes(right.
                                      DescendantNodes()
                                      .OfType <ExpressionSyntax>()
                                      .Where(node => node.ToString().Equals(rightString)),
                                      (on, nn) => CSharp.AssignmentExpression(
                                          assignment.Kind(),
                                          Templates
                                          .ExpressionProperty
                                          .Get <ExpressionSyntax>(assignment.Left),
                                          nn)));
        }
Exemple #6
0
        private static IEnumerable <StatementSyntax> ProcessScopeStatements(SyntaxList <StatementSyntax> statements)
        {
            yield return(Templates.NewScope);

            foreach (var statement in statements)
            {
                if (statement is LocalDeclarationStatementSyntax)
                {
                    //changes to the scope, again expressed as variables
                    var localDeclaration = statement as LocalDeclarationStatementSyntax;
                    var type             = localDeclaration.Declaration.Type;

                    Debug.Assert(localDeclaration.Declaration.Variables.Count == 1); //td: for now
                    var variable = localDeclaration.Declaration.Variables.Single();
                    if (variable.Initializer != null)
                    {
                        yield return(statement);

                        yield return(Templates.AddToNewScope
                                     .Get <StatementSyntax>(
                                         Roslyn.Quoted(variable.Identifier.ToString()),
                                         CSharp.IdentifierName(variable.Identifier)));
                    }
                    else
                    {
                        //td: error, should set values
                    }
                }
                else if (statement is ExpressionStatementSyntax)
                {
                    //invocations to happen on a different context
                    var invocation = (statement as ExpressionStatementSyntax)
                                     .Expression as InvocationExpressionSyntax;

                    if (invocation != null)
                    {
                        if (invocation.Expression is MemberAccessExpressionSyntax)
                        {
                            //td: error, only namspace function calls?
                        }
                        else
                        {
                            yield return(statement.ReplaceNode(invocation, invocation
                                                               .AddArgumentListArguments(CSharp.Argument(Templates
                                                                                                         .NewScopeValue))));
                        }
                    }
                    else
                    {
                        //td: error, bad invocation
                    }
                }
                else
                {
                    //td: error, only variables and invocations
                }
            }
        }
Exemple #7
0
 private static Func <SyntaxNode, Scope, SyntaxNode> AddFunctionClass(ClassDeclarationSyntax @class)
 {
     return((node, scope) =>
     {
         var document = scope.GetDocument();
         @class = (ClassDeclarationSyntax)document.change(@class, CompileFunctionClass);
         return Roslyn.AddMember(@class)(node, scope);
     });
 }
Exemple #8
0
        public override SyntaxNode VisitMethodDeclaration(MethodDeclarationSyntax node)
        {
            if (_class.IsSignal(node))
            {
                _isStatic = Roslyn.IsStatic(node);
                return(base.VisitMethodDeclaration(node));
            }

            return(node);
        }
Exemple #9
0
        public static void Visit(ClassDeclarationSyntax @class,
                                 Action <SyntaxToken, TypeSyntax, IEnumerable <ParameterSyntax> > methods = null,
                                 Action <SyntaxToken, TypeSyntax, ExpressionSyntax> fields = null,
                                 Action <IEnumerable <ParameterSyntax> > constructors      = null)
        {
            var publicMembers = @class
                                .DescendantNodes()
                                .OfType <MemberDeclarationSyntax>()
                                .Where(member => Roslyn.IsVisible(member));

            foreach (var member in publicMembers)
            {
                if (member is MethodDeclarationSyntax && methods != null)
                {
                    var method = member as MethodDeclarationSyntax;

                    //since we generate multiple methods
                    if (methods != null &&
                        method
                        .AttributeLists
                        .Any(attrList => attrList
                             .Attributes
                             .Any(attr => attr.Name.ToString() == "Concurrent")))
                    {
                        methods(method.Identifier, method.ReturnType, method.ParameterList.Parameters);
                    }
                }
                else if (member is FieldDeclarationSyntax && fields != null)
                {
                    var declaration = (member as FieldDeclarationSyntax)
                                      .Declaration;

                    var variable = declaration
                                   .Variables
                                   .Single();

                    fields(variable.Identifier, declaration.Type, variable.Initializer.Value);
                }
                else if (member is PropertyDeclarationSyntax && fields != null)
                {
                    var property = member as PropertyDeclarationSyntax;
                    fields(property.Identifier, property.Type, null);
                }
                else if (member is ConstructorDeclarationSyntax)
                {
                    constructors?.Invoke((member as ConstructorDeclarationSyntax)
                                         .ParameterList
                                         .Parameters);
                }
                else
                {
                    //td: review other member types
                }
            }
        }
Exemple #10
0
        private static MethodDeclarationSyntax concurrentMethod(Class ctx, MethodDeclarationSyntax method, bool forever = false)
        {
            var name = method.Identifier.ToString();

            var body             = method.Body;
            var returnStatements = body
                                   .DescendantNodes()
                                   .OfType <ReturnStatementSyntax>();

            var lastReturn = body.Statements.LastOrDefault() as ReturnStatementSyntax;

            if (returnStatements.Any())
            {
                body = body
                       .ReplaceNodes(returnStatements,
                                     (on, nn) => Templates
                                     .ExpressionReturn
                                     .Get <StatementSyntax>(nn.Expression == null || nn.Expression.IsMissing
                            ? Roslyn.@null
                            : nn.Expression,
                                                            Roslyn.Quoted(method.Identifier.ToString())));
            }

            if (forever)
            {
                body = CSharp.Block(
                    CSharp.ForStatement(body));
            }
            else if (lastReturn == null)
            {
                body = body.AddStatements(Templates
                                          .ExpressionReturn
                                          .Get <StatementSyntax>(
                                              Roslyn.@null,
                                              Roslyn.Quoted(method.Identifier.ToString())));
            }

            var result = Templates
                         .ConcurrentMethod
                         .Get <MethodDeclarationSyntax>("__concurrent" + name);

            result = result
                     .WithParameterList(method
                                        .ParameterList
                                        .AddParameters(result
                                                       .ParameterList
                                                       .Parameters
                                                       .ToArray()))
                     .WithBody(body);

            ctx.AddMember(result);
            return(result);
        }
Exemple #11
0
        private StatementSyntax LinkSignal(IdentifierNameSyntax name, InvocationExpressionSyntax success, InvocationExpressionSyntax failure)
        {
            var signalName = name.ToString();
            var signal     = _class.GetSignal(signalName);

            Debug.Assert(signal != null);

            return(Templates
                   .SignalListener
                   .Get <StatementSyntax>(
                       Roslyn.Quoted(signalName),
                       WrapInLambda(success)));
        }
        private void AddNodeToTree(Roslyn.Compilers.VisualBasic.SyntaxNode codeNode, ItemsControl parent)
        {
            var newNode = new TreeViewItem();

            newNode.Header = codeNode.GetType().Name;
            newNode.ToolTip = codeNode.ToFullString();

            parent.Items.Add(newNode);

            foreach (var childCodeName in codeNode.ChildNodes())
            {
                AddNodeToTree(childCodeName, newNode);
            }
        }
Exemple #13
0
        private static void compileProperty(PropertyDeclarationSyntax property, Class ctx, Scope scope)
        {
            if (!Roslyn.IsVisible(property))
            {
                return;
            }

            var @get = null as AccessorDeclarationSyntax;
            var @set = null as AccessorDeclarationSyntax;

            foreach (var accesor in property.AccessorList.Accessors)
            {
                switch (accesor.Keyword.Kind())
                {
                case SyntaxKind.GetKeyword:
                    @get = accesor;
                    break;

                case SyntaxKind.SetKeyword:
                    @set = accesor;
                    break;

                default:
                    throw new NotImplementedException();
                }
            }

            bool hasCustomGet = @get != null && @get.Body != null && @get.Body.Statements.Count > 0;

            if (hasCustomGet && @get.Body.Statements.Count == 1)
            {
                hasCustomGet = !(@get.Body.Statements[0] is ReturnStatementSyntax);
            }

            bool hasCustomSet = @set != null && @set.Body != null && @set.Body.Statements.Count > 0;

            if (hasCustomSet && @set.Body.Statements.Count == 1)
            {
                hasCustomSet = !(@set.Body.Statements[0] is ExpressionStatementSyntax) ||
                               (@set.Body.Statements[0] as ExpressionStatementSyntax)
                               .Expression.Kind() != SyntaxKind.SimpleAssignmentExpression;
            }

            if (hasCustomGet || hasCustomSet)
            {
                scope.AddError("concurrent00", "invalid concurrent property, custom accessors are not allowed", property);
            }
        }
Exemple #14
0
        private static SyntaxNode Transform(SyntaxNode oldNode, SyntaxNode newNode, Scope scope, LexicalExtension <SyntaxToken> extension)
        {
            Debug.Assert(newNode is AnonymousObjectCreationExpressionSyntax);
            var result = createJson.Get(newNode);

            var isAssignment = false;

            result = Roslyn.ReplaceAssignment(oldNode, result, out isAssignment);
            if (!isAssignment)
            {
                scope.AddError("json01", "json expects to be assigned", oldNode);
                return(newNode);
            }

            return(result);
        }
Exemple #15
0
        private static MethodDeclarationSyntax MemberFunctionModifiers(MethodDeclarationSyntax method)
        {
            var modifiers = method.Modifiers;

            if (!modifiers.Any(m => m.IsKind(SyntaxKind.StaticKeyword)))
            {
                method = method.AddModifiers(CSharp.Token(SyntaxKind.StaticKeyword));
            }

            if (!Roslyn.HasVisibilityModifier(method.Modifiers))
            {
                method = method.AddModifiers(CSharp.Token(SyntaxKind.PublicKeyword));
            }

            return(method);
        }
Exemple #16
0
        private static IEnumerable <MemberDeclarationSyntax> getConcurrentInterface(ClassDeclarationSyntax @class)
        {
            return(@class
                   .ChildNodes()
                   .OfType <MemberDeclarationSyntax>()
                   .Where(member =>
            {
                if (member is MethodDeclarationSyntax && Roslyn.IsVisible(member))
                {
                    return !(member as MethodDeclarationSyntax)
                    .Modifiers
                    .Any(modifier => modifier.Kind() == SyntaxKind.StaticKeyword);
                }

                return false;
            }));
        }
Exemple #17
0
 private static IEnumerable <StatementSyntax> FunctionInjectionStatements(BlockSyntax block, SyntaxNode toReplace, IEnumerable <StatementSyntax> toReplaceWith)
 {
     foreach (var statement in block.Statements)
     {
         if (Roslyn.SameNode(statement, toReplace))
         {
             foreach (var newStatement in toReplaceWith)
             {
                 yield return(newStatement);
             }
         }
         else
         {
             yield return(statement);
         }
     }
 }
Exemple #18
0
        public static dynamic Compile(CotMethod cotMethod, CancellationToken token = default)
        {
            var rndClass   = CodeSnippet.RandomString();
            var pageOfCode = CodeSnippet.GeneratePage(rndClass, new[] { cotMethod.ToString() }, out var refs);

            var errors = Roslyn.Compile(pageOfCode, refs, out var asm, token);

            if (errors.Length == 0)
            {
                var t = asm.GetType(rndClass);
                try
                {
                    var mn = cotMethod.Info.Name.ValueText;
                    var d  = RuntimeDelegateFactory.StaticMethod(t, mn);
                    return(d);
                }
                catch (ArgumentException)
                {
                    throw;
                }
            }
            throw new CompilationException(errors);
        }
Exemple #19
0
        public static DelegateWrapper <T> Compile <T>(CotMethod cotMethod, CancellationToken token = default)
            where T : Delegate
        {
            var rndClass   = CodeSnippet.RandomString();
            var pageOfCode = CodeSnippet.GeneratePage(rndClass, new[] { cotMethod.ToString() }, out var refs);

            var errors = Roslyn.Compile(pageOfCode, refs, out var asm, token);

            if (errors.Length == 0)
            {
                var t = asm.GetType(rndClass);
                try
                {
                    var mn = cotMethod.Info.Name.ValueText;
                    var d  = Delegate.CreateDelegate(typeof(T), t, mn, false, true) as T;
                    return(new DelegateWrapper <T>(d, mn));
                }
                catch (ArgumentException)
                {
                    throw;
                }
            }
            throw new CompilationException(errors);
        }
 public DefaultCaseCodeAction(IDocument document, Roslyn.Compilers.CSharp.SwitchStatementSyntax switchNode)
 {
     this.document = document;
     this.switchNode = switchNode;
 }
 private void AddAlignmentBlockOperationRelativeToFirstTokenOnBaseTokenLine(List<IndentBlockOperation> list, Roslyn.Utilities.ValueTuple<SyntaxToken, SyntaxToken> bracePair)
 {
     var option = IndentBlockOption.RelativeToFirstTokenOnBaseTokenLine;
     SetAlignmentBlockOperation(list, bracePair.Item1, bracePair.Item1.GetNextToken(includeZeroWidth: true), bracePair.Item2, option);
 }
Exemple #22
0
        private static SyntaxNode LinkServerInstance(ServerInstance app, Func <ServerModel, Scope, SyntaxNode> transform, Scope scope)
        {
            //a list of statements and types to be added
            var statements = new List <StatementSyntax>();

            foreach (var node in app.Nodes)
            {
                var appStatement = default(StatementSyntax);
                scope.AddType(LinkNode(node, out appStatement));

                if (appStatement != null)
                {
                    statements.Add(appStatement);
                }
            }

            //create the http start
            //
            var except = Templates
                         .StringArray
                         .Get <ArrayCreationExpressionSyntax>()
                         .WithInitializer(StringArrayInitializer(app
                                                                 .Nodes
                                                                 .SelectMany(node => node.HostedClasses)));

            //find functional filters
            var filters = new List <ExpressionSyntax>();

            if (app.SQL != null)
            {
                var connectionString = default(ExpressionSyntax);
                if (app.SQL.ConnectionString != null)
                {
                    Debug.Assert(app.SQL.ConnectionId == null);
                    connectionString = Roslyn.Quoted(app.SQL.ConnectionString);
                }
                else
                {
                    Debug.Assert(app.SQL.ConnectionId != null);
                    connectionString = Templates
                                       .SqlConnectionStringFromConfig
                                       .Get <ExpressionSyntax>(
                        Roslyn.Quoted(app.SQL.ConnectionId));
                }

                var connectionClass = app.SQL.ConnectionInstantiator ?? "SqlConnection";
                filters.Add(Templates
                            .SqlFilter
                            .Get <ExpressionSyntax>(
                                connectionString,
                                CSharp.IdentifierName(connectionClass)));
            }

            filters.Add(Templates.UserFilter);

            //start the server
            statements.Add(Templates
                           .StartHttpServer
                           .Get <StatementSyntax>(
                               Roslyn.Quoted(app.Host.Address),
                               Roslyn.Quoted(app.Identity),
                               Roslyn.Quoted(app.StaticFiles, escaped: true),
                               Roslyn.Constant(app.Threads),
                               except,
                               Roslyn.Constant(app.Nodes.Count),
                               app.Id,
                               Templates
                               .EmptyArray
                               .WithInitializer(CSharp.InitializerExpression(
                                                    SyntaxKind.ArrayInitializerExpression, CSharp.SeparatedList(
                                                        filters)))));

            //generate configuration class
            var result = Templates
                         .ServerInstance
                         .Get <ClassDeclarationSyntax>(app.Id, Roslyn.Quoted(app.Id));

            var runMethods = result
                             .DescendantNodes()
                             .OfType <MethodDeclarationSyntax>()
                             .Where(method => method.Identifier.ToString() == "Run");

            return(result.ReplaceNodes(runMethods,
                                       (on, nn) => nn.AddBodyStatements(statements.ToArray())));
        }
Exemple #23
0
        private static bool compileMethod(MethodDeclarationSyntax methodDeclaration, Class ctx, Scope scope, Options options, bool isSingleton)
        {
            var method = methodDeclaration;
            var name   = method.Identifier.ToString();
            var isMain = name == "main";

            var isProtected = method
                              .Modifiers
                              .Where(m => m.Kind() == SyntaxKind.ProtectedKeyword)
                              .Any();

            var isVisible = isProtected || Roslyn.IsVisible(method);
            var isStatic  = Roslyn.IsStatic(method);

            var hasReturnType = method.ReturnType.ToString() != "void";
            var returnType    = hasReturnType
                ? method.ReturnType
                : Roslyn.boolean;

            var isEmptySignal = method.Body == null ||
                                method.Body.IsMissing;

            if (isEmptySignal)
            {
                if (method.ParameterList.Parameters.Count > 0)
                {
                    scope.AddError("concurrent03", "empty signals cannot contain parameters", method);
                }

                if (method.ReturnType.ToString() != "void")
                {
                    scope.AddError("concurrent04", "empty signals cannot return values", method);
                }

                method = method
                         .WithSemicolonToken(CSharp.MissingToken(SyntaxKind.SemicolonToken))
                         .WithBody(CSharp.Block());
            }

            var cc = parseConcurrentBlock(ctx, method.Body, scope, isStatic);

            if (cc != null)
            {
                method = method.WithBody(cc);
            }

            //remove attributes, until needed
            method = method.WithAttributeLists(CSharp.List <AttributeListSyntax>());

            if (isMain)
            {
                if (ctx.HasMain)
                {
                    scope.AddError("concurrent06", "multiple main methods", method);
                    return(false);
                }

                ctx.HasMain = true;

                var statements  = method.Body.Statements;
                var isContinued = (cc == null) && checkContinued(statements);
                if (isContinued)
                {
                    method = method
                             .WithBody(CSharp.Block(statements
                                                    .Take(statements.Count - 1)));
                }

                var mainMethod = concurrentMethod(ctx, method);

                //hook up our start method
                int currentIndex = 0;
                ctx.Replace(methodDeclaration, Templates
                            .StartObject
                            .Get <MethodDeclarationSyntax>(Templates
                                                           .ConcurrentMain
                                                           .Get <InvocationExpressionSyntax>()
                                                           .WithArgumentList(CSharp.ArgumentList(CSharp.SeparatedList(
                                                                                                     mainMethod
                                                                                                     .ParameterList
                                                                                                     .Parameters
                                                                                                     .Where(param => param.Identifier.ToString() != "__cancellation" &&
                                                                                                            param.Identifier.ToString() != "__success" &&
                                                                                                            param.Identifier.ToString() != "__failure")
                                                                                                     .Select(param => CSharp.Argument(Templates
                                                                                                                                      .StartObjectArgument
                                                                                                                                      .Get <ExpressionSyntax>(
                                                                                                                                          param.Type,
                                                                                                                                          currentIndex++)))
                                                                                                     .Union(new[] {
                    CSharp.Argument(Templates.NullCancelationToken),
                    CSharp.Argument(Roslyn.@null),
                    CSharp.Argument(Roslyn.@null),
                }))))));

                return(false);
            }

            if (isVisible)
            {
                if (isEmptySignal)
                {
                    Debug.Assert(!isStatic); //td: error
                    ctx.AddMember(Templates
                                  .EmptySignalMethod
                                  .Get <MethodDeclarationSyntax>(
                                      "__concurrent" + name,
                                      Roslyn.Quoted(name),
                                      isProtected ? Roslyn.@true : Roslyn.@false));
                }
                else
                {
                    concurrentMethod(ctx, method, asVirtual: options.GenerateRemote);
                }
            }
            else if (cc != null)
            {
                concurrentMethod(ctx, method);
            }
            else if (isEmptySignal)
            {
                ctx.AddMember(Templates
                              .EmptySignalMethod
                              .Get <MethodDeclarationSyntax>(
                                  "__concurrent" + name,
                                  Roslyn.Quoted(name),
                                  isProtected? Roslyn.@true : Roslyn.@false));
            }
            else
            {
                return(false);
            }

            var signal = ctx.AddSignal(name, returnType, isVisible, isStatic);

            if (isVisible)
            {
                method = createPublicSignals(ctx, method, signal, isSingleton);
                if (isSingleton)
                {
                    ctx.Replace(methodDeclaration, method);
                }
            }
            else
            {
                ctx.Replace(methodDeclaration, method
                            .WithBody(CSharp.Block()
                                      .WithStatements(CSharp.List(new[] {
                    isEmptySignal
                                ? Templates.SignalDispatcher.Get <StatementSyntax>(Roslyn.Quoted(method.Identifier.ToString()))
                                : Templates.PrivateSignal
                }))));
                return(false);
            }

            return(true);
        }
Exemple #24
0
        private static Func <SyntaxNode, Scope, SyntaxNode> CompileApp(Options options)
        {
            var compileObject = CompileObject(options);

            return((node, scope) =>
            {
                var result = (node as ClassDeclarationSyntax)
                             .WithModifiers(CSharp.TokenList(
                                                CSharp.Token(SyntaxKind.PublicKeyword)));

                var main = result
                           .DescendantNodes()
                           .OfType <MethodDeclarationSyntax>()
                           .Where(method => method.Identifier.ToString() == "main")
                           .SingleOrDefault();

                if (main != null)
                {
                    result = result.ReplaceNode(main, CompileAppMain(main, options));
                }
                else
                {
                    Debug.Assert(false, "concurrent app must have main"); //td: error
                }
                if (options.GenerateAppProgram)
                {
                    scope.AddType(Templates.AppProgram.Get <ClassDeclarationSyntax>());
                }

                //convert to concurrent object
                result = (ClassDeclarationSyntax)compileObject(result, scope);

                //add a way for this app to run, stop and await completion
                var runner = null as Func <BlockSyntax, MemberDeclarationSyntax>;
                if (options.GenerateAppConstructor)
                {
                    runner = body => CSharp.ConstructorDeclaration("__app")
                             .WithModifiers(CSharp.TokenList(
                                                CSharp.Token(SyntaxKind.StaticKeyword)))
                             .WithBody(body);
                }
                else
                {
                    runner = body => Templates.AppRun.WithBody(options.GenerateAppProgram
                        ? CSharp.Block(new StatementSyntax[] { Templates.AppAssignArguments }
                                       .Union(body.Statements))
                        : body);
                }

                return result.AddMembers(
                    runner(Templates.AppThreaded
                           .Get <BlockSyntax>(
                               Roslyn.Constant(options.ThreadCount),
                               Roslyn.Constant(options.BlockUntilNextEvent),
                               options.AsFastAsPossible
                                ? Templates.HighPriority
                                : Templates.NormalPriority)),
                    Templates.AppArguments,
                    Templates.AppStop,
                    Templates.AppAwait);
            });
        }
Exemple #25
0
        /// <summary>
        /// Inspects the given code document to see if there's any need for immutable / mutable generation
        /// </summary>
        /// <param name="codeDocument"></param>
        /// <param name="text"></param>
        private void InspectAndUpdate(IDocument codeDocument, Roslyn.Compilers.Common.CommonCompilation commonCompilation)
        {
            // mild premature optimization
            var text = codeDocument.GetText().GetText();
            if (text.Contains("immutable_generated") && text.Contains("immutable_declarations"))
            {
                var updateRegions = new List<UpdateRegion>();

                // Compile
                var syntax = codeDocument.GetSyntaxTree();
                var root = syntax.GetRoot();

                // Filter down to classes
                foreach (var classDeclaration in root.DescendantNodes().OfType<ClassDeclarationSyntax>())
                {
                    var immutableGeneratedTrivia = this.GetRegion(classDeclaration, "immutable_generated");

                    if (null != immutableGeneratedTrivia)
                    {
                        var className = classDeclaration.Identifier.ValueText;
                        var classFullName = className;

                        var parent = classDeclaration.Parent;
                        while (null != parent)
                        {
                            if (parent is NamespaceDeclarationSyntax)
                                classFullName = ((NamespaceDeclarationSyntax)parent).Name.ToString().Trim() + "." + classFullName;

                            parent = parent.Parent;
                        }

                        var compiledClass = commonCompilation.GetTypeByMetadataName(classFullName);

                        var updateRegion = new UpdateRegion()
                        {
                            begin = immutableGeneratedTrivia.beginRegionTrivia.FullSpan.End,
                            end = immutableGeneratedTrivia.endRegionTrivia.FullSpan.Start
                        };

                        try
                        {
                            if (null != compiledClass)
                            {
                                Console.WriteLine("\t\t\t{0} is an immutable", classDeclaration.Identifier.GetText());

                                var immutableDeclarationsTrivia = this.GetRegion(classDeclaration, "immutable_declarations");

                                if (null != immutableDeclarationsTrivia)
                                {
                                    var fields = new List<IFieldSymbol>();

                                    // Iterate through all the tokens in the immutable_declarations to figure out the fields
                                    var token = immutableDeclarationsTrivia.beginRegionTrivia.Token;
                                    while (token != immutableDeclarationsTrivia.endRegionTrivia.Token)
                                    {
                                        if (token.Kind == SyntaxKind.IdentifierToken)
                                        {
                                            // Get the compiled version of the identifies
                                            var identifier = token.ValueText;
                                            var field = compiledClass.GetMembers(identifier)
                                                .FirstOrDefault() as IFieldSymbol;

                                            // Verify it
                                            if (null != field)
                                            {
                                                if (field.IsStatic)
                                                    throw new Exception(string.Format(
                                                        "Can not wrap static fields: {0}",
                                                        identifier));

                                                if (!field.IsReadOnly)
                                                    throw new Exception(string.Format(
                                                        "Exposed fields must be readonly: {0}",
                                                        identifier));

                                                if (field.HasConstantValue)
                                                    throw new Exception(string.Format(
                                                        "Exposed fields not be constant: {0}",
                                                        identifier));

                                                // TODO: Need to verify that the field is private

                                                fields.Add(field);
                                            }
                                        }

                                        token = token.GetNextToken();
                                    }

                                    var builder = new StringBuilder();
                                    builder.AppendLine();
                                    builder.Append(immutableGeneratedTrivia.whiteSpace);
                                    builder.AppendLine("// Generated code, do not edit unless you know what you're doing!");

                                    var propertyNames = new Dictionary<IFieldSymbol, string>();

                                    // Generate properties and set mutators
                                    foreach (var field in fields)
                                    {
                                        var type = field.Type.ToDisplayString();

                                        // Determine property name
                                        string propertyName;
                                        if (field.Name.StartsWith("_"))
                                            propertyName = field.Name.Substring(1);
                                        else
                                        {
                                            var firstChar = field.Name[0].ToString();
                                            var firstCharU = firstChar.ToUpperInvariant();
                                            var firstCharL = firstChar.ToLowerInvariant();

                                            if (firstCharL == firstCharU)
                                            {
                                                propertyName = field.Name.ToUpperInvariant();

                                                if (propertyName == field.Name)
                                                    propertyName = field.Name.ToLowerInvariant();

                                                if (propertyName == field.Name)
                                                    propertyName = field.Name + "_Property";
                                            }
                                            else
                                            {
                                                propertyName = field.Name.Substring(1);
                                                if (firstCharL == firstChar)
                                                    propertyName = firstCharU + propertyName;
                                                else
                                                    propertyName = firstCharL + propertyName;
                                            }
                                        }

                                        propertyNames[field] = propertyName;

                                        // Property
                                        builder.AppendFormat(
                                            "{0}public {1} {2} {{ get {{ return this.{3}; }}}}",
                                            immutableGeneratedTrivia.whiteSpace,
                                            type,
                                            propertyName,
                                            field.Name);

                                        builder.AppendLine();

                                        // Set Mutator
                                        builder.AppendFormat(
                                            "{0}public {1} Set{2}({3} {4}) {{ return new {1}(",
                                            immutableGeneratedTrivia.whiteSpace,
                                            className,
                                            propertyName,
                                            type,
                                            field.Name);

                                        var passes = new List<string>();
                                        foreach (var subField in fields)
                                        {
                                            if (subField == field)
                                                passes.Add(field.Name);
                                            else
                                                passes.Add("this." + subField.Name);
                                        }

                                        builder.Append(string.Join(", ", passes.ToArray()));
                                        builder.AppendLine("); }");

                                        builder.AppendLine();
                                    }

                                    builder.AppendLine();

                                    // Generate constructor
                                    builder.Append(immutableDeclarationsTrivia.whiteSpace);
                                    builder.AppendFormat("public {0}(", className);

                                    var argumentDeclarations = new List<string>();
                                    foreach (var field in fields)
                                    {
                                        argumentDeclarations.Add(string.Format(
                                            "{0} {1} = default({0})",
                                            field.Type.ToDisplayString(),
                                            field.Name));
                                    }

                                    builder.Append(string.Join(", ", argumentDeclarations.ToArray()));
                                    builder.Append(") { ");

                                    foreach (var field in fields)
                                    {
                                        var typeDisplayString = field.Type.ToDisplayString();
                                        if (this.IsIEnumerable(typeDisplayString))
                                        {
                                            builder.AppendFormat("if (default({1}) != {0}) this.{0} = {0}.ToArray().AsEnumerable(); ", field.Name, typeDisplayString);
                                        }
                                        else
                                        {
                                            builder.AppendFormat("this.{0} = {0}; ", field.Name);
                                        }
                                    }

                                    builder.AppendLine("}");
                                    builder.AppendLine();

                                    // Mutable class
                                    builder.Append(immutableGeneratedTrivia.whiteSpace);
                                    builder.Append("public class Mutable {");

                                    foreach (var field in fields)
                                    {
                                        var typeDisplayString = field.Type.ToDisplayString();
                                        if (this.IsIEnumerable(typeDisplayString))
                                        {
                                            typeDisplayString = typeDisplayString.Replace("IEnumerable", "IList");
                                        }

                                        builder.AppendFormat(
                                            " public {0} {1} {{ get; set; }}",
                                            typeDisplayString,
                                            propertyNames[field]);
                                    }

                                    // Generate immutable from mutable
                                    builder.AppendFormat(
                                        " public {0} ToImmutable() {{ return new {0}(",
                                        className);

                                    var assignments = new List<string>(fields.Count);
                                    foreach (var field in fields)
                                        assignments.Add(string.Format(
                                            "this.{0}",
                                            propertyNames[field]));

                                    builder.Append(string.Join(", ", assignments.ToArray()));
                                    builder.AppendLine(");} }");

                                    // GenerateMutable method
                                    builder.AppendFormat(
                                        "{0}public Mutable ToMutable() {{ return new Mutable() {{ ",
                                        immutableGeneratedTrivia.whiteSpace);

                                    assignments = new List<string>(fields.Count);
                                    foreach (var field in fields)
                                    {
                                        var copyMethod = String.Empty;
                                        var typeDisplayString = field.Type.ToDisplayString();
                                        if (this.IsIEnumerable(typeDisplayString))
                                        {
                                            copyMethod = ".ToList()";
                                        }

                                        assignments.Add(string.Format(
                                            "{0} = this.{1}{2}",
                                            propertyNames[field],
                                            field.Name,
                                            copyMethod));
                                    }

                                    builder.Append(string.Join(", ", assignments.ToArray()));
                                    builder.AppendLine("}; }");

                                    builder.AppendLine();

                                    // ==
                                    builder.AppendFormat(
                                        "{0}public static bool operator ==({1} lhs, {1} rhs) {{ return",
                                        immutableGeneratedTrivia.whiteSpace,
                                        className);

                                    var conditionBuilder = new List<string>(fields.Count);
                                    foreach (var field in fields)
                                    {
                                        var typeDisplayString = field.Type.ToDisplayString();
                                        if (this.IsIEnumerable(typeDisplayString))
                                        {
                                            conditionBuilder.Add(string.Format(
                                                " lhs.{0}.SequenceEqual(rhs.{0})",
                                                field.Name));
                                        }
                                        else
                                        {
                                            conditionBuilder.Add(string.Format(
                                                " lhs.{0} == rhs.{0} ",
                                                field.Name));
                                        }
                                    }

                                    builder.Append(string.Join("&&", conditionBuilder.ToArray()));
                                    builder.Append("; }");

                                    builder.AppendLine();

                                    // !=
                                    builder.AppendFormat(
                                        "{0}public static bool operator !=({1} lhs, {1} rhs) {{ return",
                                        immutableGeneratedTrivia.whiteSpace,
                                        className);

                                    conditionBuilder = new List<string>(fields.Count);
                                    foreach (var field in fields)
                                    {
                                        var typeDisplayString = field.Type.ToDisplayString();
                                        if (this.IsIEnumerable(typeDisplayString))
                                        {
                                            conditionBuilder.Add(string.Format(
                                                " (!lhs.{0}.SequenceEqual(rhs.{0}))",
                                                field.Name));
                                        }
                                        else
                                        {
                                            conditionBuilder.Add(string.Format(
                                                " lhs.{0} != rhs.{0} ",
                                                field.Name));
                                        }
                                    }

                                    builder.Append(string.Join("||", conditionBuilder.ToArray()));
                                    builder.Append("; }");

                                    builder.AppendLine();

                                    updateRegion.newText = builder.ToString();
                                }
                                else
                                {
                                    updateRegion.newText = immutableGeneratedTrivia.whiteSpace + "// Missing #region immutable_declarations\n\r";
                                }
                            }
                            else
                            {
                                updateRegion.newText = immutableGeneratedTrivia.whiteSpace + "// " + classFullName + " does not compile\n\r";
                            }
                        }
                        catch (Exception e)
                        {
                            updateRegion.newText = string.Format("/*{0}*/\r\n", e);
                        }

                        updateRegions.Add(updateRegion);
                    }
                }

                if (updateRegions.Count > 0)
                    this.Update(codeDocument, text, updateRegions);
            }
        }
Exemple #26
0
        public override SyntaxNode VisitTryStatement(TryStatementSyntax node)
        {
            _trysInStack++;
            try
            {
                var newNode = (TryStatementSyntax)base.VisitTryStatement(node);

                if (_tryConcurrent)
                {
                    var variableName = "__try" + _trysInStack;
                    _tryVariables.Add(variableName);

                    //we can only split on expressions directly on the try level
                    //i.e. no try { if () { EXPRESSION }}
                    if (_trysInStack > 1 && !(newNode.Parent.Parent is TryStatementSyntax))
                    {
                        Debug.Assert(false); //td: error
                        return(newNode);
                    }

                    var statements    = new List <StatementSyntax>(newNode.Block.Statements);
                    var newStatements = new List <StatementSyntax>();
                    var currentIndex  = 0;

                    while (currentIndex < statements.Count)
                    {
                        var oldIndex = currentIndex;
                        for (int i = oldIndex; i < statements.Count; i++, currentIndex++)
                        {
                            var statement = statements[i];

                            if (statement is YieldStatementSyntax)
                            {
                                newStatements.Add(newNode
                                                  .WithBlock(CSharp.Block(
                                                                 statements
                                                                 .Skip(oldIndex)
                                                                 .Take(currentIndex - oldIndex - 1))));

                                //variable and return yield
                                //td: assert
                                newStatements.Add(statements[currentIndex - 1]);
                                newStatements.Add(statements[currentIndex++]);
                                break;
                            }

                            //must make variables available to later code, unless it precedes a yield
                            var yieldNext = statements.Count > i + 1 && statements[i + 1] is YieldStatementSyntax;
                            if (statement is LocalDeclarationStatementSyntax && !yieldNext)
                            {
                                var decl = statement as LocalDeclarationStatementSyntax;

                                var varType = decl.Declaration.Type;
                                if (varType == null || varType.Kind() == SyntaxKind.TypeVarKeyword)
                                {
                                    varType = Roslyn.SymbolTypeSyntax(_model, decl
                                                                      .Declaration
                                                                      .Variables[0]
                                                                      .Initializer
                                                                      .Value);
                                }

                                Debug.Assert(varType != null, "Untyped local variable on try fix");

                                var assignmentStatements = new List <StatementSyntax>();
                                newStatements.Add(decl
                                                  .WithDeclaration(decl.Declaration
                                                                   .WithType(varType)
                                                                   .WithVariables(CSharp.SeparatedList(
                                                                                      decl
                                                                                      .Declaration
                                                                                      .Variables
                                                                                      .Select(v =>
                                {
                                    assignmentStatements.Add(CSharp.ExpressionStatement(
                                                                 CSharp.AssignmentExpression(
                                                                     SyntaxKind.SimpleAssignmentExpression,
                                                                     CSharp.IdentifierName(v.Identifier),
                                                                     v.Initializer.Value)));

                                    return(v.WithInitializer(v
                                                             .Initializer
                                                             .WithValue(Templates
                                                                        .DefaultValue
                                                                        .Get <ExpressionSyntax>(varType))));
                                })))));

                                //once moved the variables "up" scope
                                //we must keep the assignments
                                Debug.Assert(assignmentStatements.Any());
                                statements.RemoveAt(i);
                                statements.InsertRange(i, assignmentStatements);
                            }
                        }
                    }

                    Debug.Assert(newStatements.Any());
                    return(LinkTryStatements(newStatements, variableName));
                }

                return(newNode);
            }
            finally
            {
                _trysInStack--;
            }
        }