Ejemplo n.º 1
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
                }
            }
        }
Ejemplo n.º 2
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);
            }
        }
Ejemplo n.º 3
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;
            }));
        }
Ejemplo n.º 4
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);
        }