private static ClassDeclarationSyntax LinkNode(ServerInstance instance, out StatementSyntax appStatement) { appStatement = Templates.CallStartNode.Get <StatementSyntax>(instance.Id); //td: var statements = new List <StatementSyntax>(); var only = Templates .StringArray .Get <ArrayCreationExpressionSyntax>() .WithInitializer(StringArrayInitializer(instance.HostedClasses)); statements.Add(Templates .StartNetMQServer .Get <StatementSyntax>( Roslyn.Quoted(instance.Host.Address), Roslyn.Quoted(instance.Parent.Identity), Roslyn.Constant(instance.Threads), only, instance.Id)); var result = Templates .ServerInstance .Get <ClassDeclarationSyntax>(instance.Id, Roslyn.Quoted(instance.Id)); var start = result .DescendantNodes() .OfType <MethodDeclarationSyntax>() .Where(method => method.Identifier.ToString() == "Run" && method.ParameterList.Parameters.Count == 3) .Single(); return(result .ReplaceNode(start, start .AddBodyStatements(statements.ToArray()))); }
public static InitializerExpressionSyntax StringArrayInitializer(IEnumerable <string> values) { return(CSharp.InitializerExpression( SyntaxKind.ArrayInitializerExpression, CSharp.SeparatedList(values .Select(value => Roslyn.Quoted(value))))); }
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))); }
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 } } }
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); }
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 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()))); }
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); }