Пример #1
0
        private static IEnumerable <MemberDeclarationSyntax> createRemoteConstructors(ClassDeclarationSyntax @class, string typeName)
        {
            var constructor = @class
                              .ChildNodes()
                              .OfType <ConstructorDeclarationSyntax>()
                              .OrderBy(ctor => ctor.ParameterList.Parameters.Count)
                              .FirstOrDefault();

            var result = CSharp.ConstructorDeclaration(typeName)
                         .AddParameterListParameters(CSharp
                                                     .Parameter(CSharp.Identifier("id")).WithType(CSharp.ParseTypeName("Guid")))
                         .WithBody(CSharp.Block(Templates.RemoteIdAssign))
                         .WithModifiers(Roslyn.@public);

            if (constructor != null)
            {
                result = result.WithInitializer(CSharp.ConstructorInitializer(
                                                    SyntaxKind.BaseConstructorInitializer,
                                                    CSharp.ArgumentList(CSharp.SeparatedList(
                                                                            constructor
                                                                            .ParameterList
                                                                            .Parameters
                                                                            .Select(parameter => CSharp.Argument(
                                                                                        CSharp.DefaultExpression(parameter.Type)))))));
            }

            return(new MemberDeclarationSyntax[]
            {
                result
            });
        }
Пример #2
0
        private static SyntaxNode Compound(RParser.CompoundContext compound, Func <ParserRuleContext, Scope, SyntaxNode> transform, Scope scope)
        {
            //create a new context for the block
            var inner = new Scope(scope);

            inner.InitR();

            var pre        = inner.PreStatements();
            var statements = new List <StatementSyntax>();
            var exprlist   = compound.exprlist();

            if (exprlist is RParser.ExpressionListContext)
            {
                var list = exprlist as RParser.ExpressionListContext;
                foreach (var expr in list.expr_or_assign())
                {
                    pre.Clear();
                    var statement = transform(expr, inner) as StatementSyntax;
                    Debug.Assert(statement != null);


                    statements.AddRange(pre);
                    statements.Add(statement);
                }
            }

            return(CSharp.Block(statements));
        }
Пример #3
0
        private static SyntaxNode ProcessContract(SyntaxNode node, Scope scope, SyntacticalExtension <SyntaxNode> extension)
        {
            if (extension.Kind == ExtensionKind.Code)
            {
                var block = extension.Body as BlockSyntax;
                Debug.Assert(block != null);

                List <StatementSyntax> checks = new List <StatementSyntax>();
                foreach (var st in block.Statements)
                {
                    var stExpression = st as ExpressionStatementSyntax;
                    if (stExpression == null)
                    {
                        scope.AddError("contract01", "contracts only support boolean expressions", st);
                        continue;
                    }

                    var contractCheck = ContractCheck
                                        .ReplaceNodes(ContractCheck
                                                      .DescendantNodes()
                                                      .OfType <ExpressionSyntax>()
                                                      .Where(expr => expr.ToString() == "__condition"),

                                                      (oldNode, newNode) =>
                                                      stExpression.Expression);

                    checks.Add(contractCheck);
                }

                return(CSharp.Block(checks));
            }

            scope.AddError("contract02", "contract cannot return a value", node);
            return(node);
        }
Пример #4
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));
        }
Пример #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)));
        }
Пример #6
0
        private static SyntaxNode addConstructor(SyntaxNode node)
        {
            var classDeclaration = node as ClassDeclarationSyntax;

            Assert.IsTrue(classDeclaration != null);

            return(classDeclaration
                   .AddMembers(CSharp.ConstructorDeclaration(classDeclaration.Identifier)
                               .WithBody(CSharp.Block())));
        }
Пример #7
0
 private static SyntaxNode MoveToRun(SyntaxNode root, IEnumerable <SyntaxNode> statements, Scope scope)
 {
     return(_app
            .ReplaceNodes(_app
                          .DescendantNodes()
                          .OfType <MethodDeclarationSyntax>()
                          .Where(m => m.Identifier.ToString() == "run"),
                          (on, nn) => nn.WithBody(CSharp.Block(
                                                      statements.Select(sn => (StatementSyntax)sn)))));
 }
Пример #8
0
        private static StatementSyntax caseStatement(SyntaxList <StatementSyntax> statements)
        {
            Debug.Assert(statements.Any());

            if (statements.Count == 1)
            {
                return(statements.First());
            }

            return(CSharp.Block(statements));
        }
Пример #9
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);
        }
Пример #10
0
        public override SyntaxNode VisitExpressionStatement(ExpressionStatementSyntax statement)
        {
            var result = null as SyntaxNode;

            if (statement.Expression is BinaryExpressionSyntax)
            {
                result = Parse(statement.Expression as BinaryExpressionSyntax);

                HasConcurrent = HasConcurrent || result != statement.Expression;
            }
            else if (statement.Expression is AwaitExpressionSyntax)
            {
                HasConcurrent = true;
                var expr = (statement.Expression as AwaitExpressionSyntax)
                           .Expression;

                Debug.Assert(expr != null); //td: error
                result = VisitExpressionStatement(Templates
                                                  .AwaitExpr
                                                  .Get <ExpressionStatementSyntax>(expr));
            }
            else if (statement.Expression is InvocationExpressionSyntax)
            {
                var queueStatement = null as StatementSyntax;
                if (_class.isQueueInvocation(
                        statement.Expression as InvocationExpressionSyntax,
                        false, //synch call
                        null,
                        out queueStatement))
                {
                    return(queueStatement);
                }
            }

            if (result == null)
            {
                result = base.VisitExpressionStatement(statement);
            }

            if (statement.Parent is BlockSyntax)
            {
                return(result);
            }

            //in cases such as if (x) y;
            //we standarize the blocks, if (x) {y;}
            return(CSharp.Block((StatementSyntax)result));
        }
Пример #11
0
 private MethodDeclarationSyntax OverrideMethod(MethodDeclarationSyntax method)
 {
     return(method
            .WithModifiers(CSharp.TokenList(method
                                            .Modifiers
                                            .Where(modifier => modifier.Kind() != SyntaxKind.VirtualKeyword)
                                            .Union(new[] { CSharp.Token(SyntaxKind.OverrideKeyword) })
                                            .ToArray()))
            .WithBody(CSharp.Block()
                      .WithStatements(CSharp.List(new[] {
         contextCall.Get <StatementSyntax>(method
                                           .ParameterList
                                           .Parameters
                                           .First()
                                           .Type)
     }))));
 }
Пример #12
0
        private static SyntaxNode ParseContract(BlockSyntax block, Scope scope)
        {
            List <StatementSyntax> checks = new List <StatementSyntax>();

            foreach (var st in block.Statements)
            {
                var stExpression = st as ExpressionStatementSyntax;
                if (stExpression == null)
                {
                    scope.AddError("contract01", "contracts only support boolean expressions", st);
                    continue;
                }

                var expr = stExpression.Expression as BinaryExpressionSyntax;
                if (expr != null && expr.OperatorToken.IsKind(SyntaxKind.GreaterThanGreaterThanToken))
                {
                    var exprAssign = expr.Right as InvocationExpressionSyntax;
                    if (exprAssign == null)
                    {
                        scope.AddError("contract02", "contracts only invocations on the right side of >>", st);
                        continue;
                    }

                    var throwExpr = ContractCheckWithException
                                    .Get <StatementSyntax>(
                        expr.Left,
                        exprAssign.Expression);

                    var newExpr = throwExpr
                                  .DescendantNodes()
                                  .OfType <ObjectCreationExpressionSyntax>()
                                  .Single();

                    checks.Add(throwExpr.ReplaceNode(newExpr,
                                                     newExpr.WithArgumentList(exprAssign.ArgumentList)));
                }
                else
                {
                    checks.Add(ContractCheck
                               .Get <StatementSyntax>(stExpression.Expression));
                }
            }

            return(CSharp.Block(checks));
        }
Пример #13
0
        private static SyntaxNode CompileFunction(SyntaxNode node, Scope scope)
        {
            var method          = (MethodDeclarationSyntax)node;
            var concurrentClass = method.Identifier.ToString() + "__concurrent";

            //create a concurrent class with the method
            var @class = CSharp.ClassDeclaration(concurrentClass)
                         .AddMembers(method);

            //add it to the parent
            var document = scope.GetDocument();

            document.change(node.Parent, AddFunctionClass(@class));

            //create a substitute call
            var invocation = Templates.FunctionInvocation
                             .Get <ExpressionStatementSyntax>(
                concurrentClass,
                method.Identifier);

            if (method.ParameterList.Parameters.Count > 0)
            {
                var invoke    = (InvocationExpressionSyntax)invocation.Expression;
                var arguments = method.ParameterList
                                .Parameters
                                .Select(parameter => CSharp.Argument(CSharp.IdentifierName(
                                                                         parameter.Identifier)))
                                .Union(invoke.ArgumentList.Arguments);

                invocation = invocation
                             .WithExpression(invoke
                                             .WithArgumentList(CSharp.ArgumentList(CSharp.SeparatedList(
                                                                                       arguments))));
            }

            return(method
                   .AddAttributeLists(CSharp.AttributeList(CSharp.SeparatedList <AttributeSyntax>(new[] {
                CSharp.Attribute(CSharp.ParseName("Concurrent"))
            })))
                   .AddParameterListParameters(Templates
                                               .FunctionParameters
                                               .Parameters
                                               .ToArray())
                   .WithBody(CSharp.Block(invocation)));
        }
Пример #14
0
        private static SyntaxNode GenerateCode(IDictionary <string, Tuple <object, SyntaxNode> > instances, Scope scope)
        {
            var graph      = scope.get <IExcessGraph>();
            var parameters = graph.Root
                             .Where(node => node.Owner is Parameter)
                             .Select(node => node.Owner as Parameter);

            var method = FormulaClass
                         .DescendantNodes()
                         .OfType <MethodDeclarationSyntax>()
                         .Single();

            return(FormulaClass.ReplaceNode(method, method
                                            .WithParameterList(CSharp.ParameterList(CSharp.SeparatedList(
                                                                                        parameters.Select(parameter => CSharp.Parameter(CSharp.ParseToken(parameter.Name))
                                                                                                          .WithType(DoubleType)))))
                                            .WithBody(CSharp.Block(
                                                          graph.RenderNodes(graph.Root)))));
        }
Пример #15
0
        private static BlockSyntax parseBlock(RParser.ExprContext expr, Func <ParserRuleContext, Scope, SyntaxNode> transform, Scope scope)
        {
            var node = transform(expr, scope);

            if (expr is RParser.CompoundContext)
            {
                return((BlockSyntax)node);
            }

            if (node is ExpressionSyntax)
            {
                node = CSharp.ExpressionStatement(node as ExpressionSyntax);
            }

            return(CSharp
                   .Block()
                   .WithStatements(CSharp.List(new StatementSyntax[] {
                (StatementSyntax)node
            })));
        }
Пример #16
0
        private static MethodDeclarationSyntax singletonPublicSignal(MethodDeclarationSyntax method, out MethodDeclarationSyntax result)
        {
            result = method.WithIdentifier(CSharp.ParseToken("__" + method.Identifier.ToString()));

            var sCall = method.ReturnType.ToString() == "void"
                ? Templates.SingletonCall
                        .Get <StatementSyntax>(result.Identifier.ToString())
                : Templates.SingletonReturnCall
                        .Get <StatementSyntax>(result.Identifier.ToString());

            return(method
                   .AddModifiers([email protected]())
                   .WithBody(CSharp.Block(sCall
                                          .ReplaceNodes(sCall
                                                        .DescendantNodes()
                                                        .OfType <ArgumentListSyntax>(),
                                                        (on, nn) => nn.WithArguments(CSharp.SeparatedList(method
                                                                                                          .ParameterList
                                                                                                          .Parameters
                                                                                                          .Select(parameter => CSharp.Argument(CSharp.IdentifierName(parameter.Identifier)))))))));
        }
Пример #17
0
        private static SyntaxNode Program(RParser.ProgContext prog, Func <ParserRuleContext, Scope, SyntaxNode> transform, Scope scope)
        {
            var statements = new List <StatementSyntax>();
            var inner      = new Scope(scope);

            inner.InitR();
            var pre = inner.PreStatements();

            foreach (var expr in prog.expr_or_assign())
            {
                pre.Clear();

                var statement = transform(expr, inner) as StatementSyntax;
                Debug.Assert(statement != null);

                statements.AddRange(pre);
                statements.Add(statement);
            }

            return(CSharp.Block(statements));
        }
Пример #18
0
        private SyntaxNode LinkTryStatements(List <StatementSyntax> statements, string variable)
        {
            var newStatements = new List <StatementSyntax>();
            var firstTry      = _trysInStack == 1;

            if (firstTry)
            {
                foreach (var v in _tryVariables)
                {
                    newStatements.Add(Templates
                                      .TryVariable
                                      .Get <StatementSyntax>(v));
                }

                _tryConcurrent = false;
                _tryVariables.Clear();
            }

            return(CSharp.Block(
                       newStatements.Union(
                           CreateTrySplit(statements, 0, variable))));
        }
Пример #19
0
        private IEnumerable <StatementSyntax> CreateTrySplit(List <StatementSyntax> statements, int index, string variable)
        {
            bool foundTry = false;

            for (int i = index; i < statements.Count; i++, index++)
            {
                if (foundTry)
                {
                    yield return(CSharp.IfStatement(
                                     Templates.Negation.Get <ExpressionSyntax>(CSharp.IdentifierName(variable)),
                                     CSharp.Block(CreateTrySplit(statements, index, variable))));

                    yield break;
                }

                var statement = statements[i];
                if (statement is TryStatementSyntax)
                {
                    foundTry = true;
                    var @try = statement as TryStatementSyntax;
                    yield return(@try
                                 .WithCatches(CSharp.List(
                                                  @try
                                                  .Catches
                                                  .Select(c => c.WithBlock(CSharp.Block(new [] {
                        Templates
                        .SetTryVariable
                        .Get <StatementSyntax>(variable)
                    }.Union(
                                                                                            c.Block.Statements)))))));
                }
                else
                {
                    yield return(statement);
                }
            }
        }
Пример #20
0
        private static SyntaxNode TransformHeaderModel(RootModel root, Func <MockIdentGrammarModel, Scope, SyntaxNode> parse, Scope scope)
        {
            var statements = new List <StatementSyntax>();

            foreach (var header in root.Headers)
            {
                foreach (var value in header.Values)
                {
                    statements.Add(HeaderValue.Get <StatementSyntax>(
                                       RoslynCompiler.Quoted(header.Name),
                                       RoslynCompiler.Quoted(value.Left.ToString()),
                                       value.Right));
                }

                foreach (var contact in header.Contacts)
                {
                    statements.Add(Contact.Get <StatementSyntax>(
                                       RoslynCompiler.Quoted(header.Name),
                                       RoslynCompiler.Quoted(contact.Name),
                                       RoslynCompiler.Quoted(contact.Telephone)));

                    foreach (var phone in contact.OtherNumbers)
                    {
                        statements.Add(OtherNumber.Get <StatementSyntax>(
                                           RoslynCompiler.Quoted(header.Name),
                                           RoslynCompiler.Quoted(contact.Name),
                                           CSharp.LiteralExpression(
                                               SyntaxKind.NumericLiteralExpression,
                                               CSharp.Literal(phone.AreaCode)),
                                           CSharp.LiteralExpression(
                                               SyntaxKind.NumericLiteralExpression,
                                               CSharp.Literal(phone.FirstThree)),
                                           CSharp.LiteralExpression(
                                               SyntaxKind.NumericLiteralExpression,
                                               CSharp.Literal(phone.LastFour))));
                    }
                }

                if (header.Location != null)
                {
                    statements.Add(Location.Get <StatementSyntax>(
                                       RoslynCompiler.Quoted(header.Name),
                                       RoslynCompiler.Quoted(header.Location.Place ?? ""),
                                       RoslynCompiler.Quoted(header.Location.City ?? "")));
                }
            }

            foreach (var forStatement in root.Statements)
            {
                statements.Add(CSharp
                               .ForEachStatement(
                                   CSharp.ParseTypeName("var"),
                                   forStatement.Iterator,
                                   CSharp.ParseExpression(forStatement.Iterable),
                                   CSharp.Block(forStatement
                                                .Statements
                                                .ToArray())));
            }

            return(CSharp.Block(statements.ToArray()));
        }
Пример #21
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);
        }
Пример #22
0
        private static SyntaxNode Compile(SyntaxNode node, Scope scope, bool isSingleton, Options options)
        {
            Debug.Assert(node is ClassDeclarationSyntax);
            var @class = (node as ClassDeclarationSyntax)
                         .AddBaseListTypes(
                CSharp.SimpleBaseType(CSharp.ParseTypeName(
                                          "ConcurrentObject")));

            if (options.GenerateInterface)
            {
                @class = @class.AddBaseListTypes(
                    CSharp.SimpleBaseType(CSharp.ParseTypeName(
                                              "I" + (node as ClassDeclarationSyntax).Identifier.ToString())));
            }

            var className = @class.Identifier.ToString();

            var ctx = new Class(className, scope, isSingleton);

            scope.set <Class>(ctx);

            foreach (var member in @class.Members)
            {
                if (member is PropertyDeclarationSyntax)
                {
                    compileProperty(member as PropertyDeclarationSyntax, ctx, scope);
                }
                else if (member is MethodDeclarationSyntax)
                {
                    var method = member as MethodDeclarationSyntax;
                    if (compileMethod(method, ctx, scope, options, isSingleton))
                    {
                        var isVoid   = method.ReturnType.ToString() == "void";
                        var taskArgs = isVoid
                            ? new[]
                        {
                            CSharp.Argument(Templates.NullCancelationToken),
                            CSharp.Argument(Roslyn.@null),
                            CSharp.Argument(Roslyn.@null)
                        }
                            : new[]
                        {
                            CSharp.Argument(Templates.NullCancelationToken)
                        };

                        var taskCall = CSharp
                                       .InvocationExpression(
                            CSharp.IdentifierName(method.Identifier),
                            CSharp.ArgumentList(CSharp.SeparatedList(
                                                    method
                                                    .ParameterList
                                                    .Parameters
                                                    .Select(parameter => CSharp
                                                            .Argument(CSharp.IdentifierName(parameter.Identifier)))
                                                    .Union(
                                                        taskArgs))));

                        var newMethod = method
                                        .AddAttributeLists(CSharp.AttributeList(CSharp.SeparatedList(new[] { CSharp
                                                                                                             .Attribute(CSharp
                                                                                                                        .ParseName("Concurrent")) })))
                                        .WithBody(CSharp.Block()
                                                  .WithStatements(CSharp.List(new[] {
                            isVoid
                                        ? Templates
                            .SynchVoidMethod
                            .Get <StatementSyntax>(taskCall)
                                        : Templates
                            .SynchReturnMethod
                            .Get <StatementSyntax>(taskCall)
                        })));

                        if (isSingleton && ctx.willReplace(method))
                        {
                            //singleton methods must change into __methodName
                            var fs = (newMethod
                                      .Body
                                      .Statements
                                      .First() as ExpressionStatementSyntax)
                                     .Expression as InvocationExpressionSyntax;

                            var newId = "__" + method.Identifier.ToString();
                            newMethod = newMethod
                                        .ReplaceNode(fs, fs.WithExpression(CSharp.IdentifierName(newId)))
                                        .WithIdentifier(CSharp.ParseToken(newId));
                        }

                        ctx.Replace(method, newMethod);
                    }
                }
            }

            //all concurrent compilation has been done, produce
            @class = ctx.Update(@class);

            if (isSingleton)
            {
                @class = @class.AddMembers(
                    Templates.SingletonField
                    .Get <MemberDeclarationSyntax>(@class.Identifier),
                    Templates.SingletonInit
                    .Get <MemberDeclarationSyntax>(@class.Identifier));
            }

            //generate the interface
            if (options.GenerateInterface)
            {
                scope.AddType(CreateInterface(@class));
            }

            if (options.GenerateRemote)
            {
                //add a remote type, to be used with an identity server
                var remoteMethod = null as MethodDeclarationSyntax;
                createRemoteType(@class, scope, out remoteMethod);
                @class = @class.AddMembers(remoteMethod);
            }

            if (options.GenerateID)
            {
                @class = @class.AddMembers(Templates
                                           .ObjectId
                                           .Get <MemberDeclarationSyntax>());
            }

            //schedule linking
            var document = scope.GetDocument();

            return(document.change(@class, Link(ctx), null));
        }
Пример #23
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);
            });
        }
Пример #24
0
        private static SyntaxNode ProcessInjection(SyntaxNode node, Scope scope)
        {
            var document = scope.GetDocument <SyntaxToken, SyntaxNode, SemanticModel>();
            var field    = node as FieldDeclarationSyntax;

            if (field == null)
            {
                //must be injecting on a function
                var toInject = (((node as LocalDeclarationStatementSyntax)
                                 ?.Declaration
                                 .Variables
                                 .SingleOrDefault()
                                 ?.Initializer
                                 ?.Value as SimpleLambdaExpressionSyntax)
                                ?.Body as BlockSyntax)
                               ?.Statements;

                if (toInject == null)
                {
                    //td: error
                    return(node);
                }

                document.change(node.Parent, FunctionInjection(node, toInject));
                return(node);
            }

            //otherwise, class injection
            var parentClass = null as ClassDeclarationSyntax;

            if (!ParseInjection(field, scope, out parentClass))
            {
                return(node);
            }

            var memberStatements = (((node as FieldDeclarationSyntax)
                                     ?.Declaration
                                     .Variables
                                     .SingleOrDefault()
                                     ?.Initializer
                                     ?.Value as SimpleLambdaExpressionSyntax)
                                    ?.Body as BlockSyntax)
                                   ?.Statements;

            if (memberStatements == null)
            {
                //td: error
                return(node);
            }

            var members = membersFromStatements(memberStatements);

            document.change(parentClass, AddFields(members));

            return(CSharp.ConstructorDeclaration(parentClass.Identifier)
                   .WithModifiers(RoslynCompiler.@public)
                   .WithParameterList(CSharp.ParameterList(CSharp.SeparatedList(
                                                               members
                                                               .Select(member => InjectionParameter(member)))))
                   .WithBody(CSharp.Block(
                                 members
                                 .Select(member => InjectionAssignment(member)))));
        }
Пример #25
0
 private static StatementSyntax caseStatement(SyntaxList <StatementSyntax> statements)
 {
     return(CSharp.Block(
                validCaseStatements(statements)));
 }
Пример #26
0
 private ParenthesizedLambdaExpressionSyntax WrapInLambda(IEnumerable <ExpressionSyntax> expressions)
 {
     return(CSharp.ParenthesizedLambdaExpression(
                CSharp.Block(expressions
                             .Select(e => CSharp.ExpressionStatement(e)))));
 }
Пример #27
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--;
            }
        }