private static ArgumentListSyntax Arguments(ParserRuleContext node) { var expr = null as ExpressionSyntax; var args = null as ArgumentListSyntax; if (node.ChildCount == 1) { expr = visitNode(node.GetRuleContext <ParserRuleContext>(0)); } else { Debug.Assert(node.ChildCount == 2); expr = visitNode(node.GetRuleContext <ParserRuleContext>(1)); args = Arguments(node.GetRuleContext <ParserRuleContext>(0)); } var arg = CSharp.Argument(expr); if (args != null) { return(args.AddArguments(arg)); } return(CSharp .ArgumentList(CSharp .SeparatedList(new[] { arg }))); }
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 }); }
private static string argumentsFromParameters(IEnumerable <ParameterSyntax> parameters) { return(CSharp .ArgumentList(CSharp.SeparatedList( parameters .Select(parameter => CSharp.Argument(CSharp. IdentifierName(parameter.Identifier))))) .ToString()); }
private static MethodDeclarationSyntax createPublicSignals(Class ctx, MethodDeclarationSyntax method, Signal signal, bool isSingleton) { var returnType = method.ReturnType.ToString() != "void" ? method.ReturnType : Roslyn.@object; var internalMethod = method.Identifier.ToString(); if (!internalMethod.StartsWith("__concurrent")) { internalMethod = "__concurrent" + internalMethod; } var internalCall = Templates.InternalCall .Get <ExpressionSyntax>(internalMethod); internalCall = internalCall .ReplaceNodes(internalCall .DescendantNodes() .OfType <InvocationExpressionSyntax>() .Where(i => i.ArgumentList.Arguments.Count == 3), (on, nn) => nn .WithArgumentList(CSharp.ArgumentList(CSharp.SeparatedList( method.ParameterList.Parameters .Select(param => CSharp.Argument(CSharp.IdentifierName( param.Identifier))) .Union(on.ArgumentList.Arguments))))); var ps1 = publicSignal( method.ParameterList, Templates.TaskPublicMethod .Get <MethodDeclarationSyntax>( method.Identifier.ToString(), returnType, internalCall)); var ps2 = publicSignal( method.ParameterList, Templates.TaskCallbackMethod .Get <MethodDeclarationSyntax>( method.Identifier.ToString(), internalCall)); if (isSingleton) { ctx.AddMember(singletonPublicSignal(ps1, out ps1)); ctx.AddMember(singletonPublicSignal(ps2, out ps2)); ctx.AddMember(singletonPublicSignal(method, out method)); } ctx.AddMember(ps1); ctx.AddMember(ps2); return(method); }
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))); }
private static ExpressionSyntax Call(ParserRuleContext node) { if (node.ChildCount == 1) { return(Expression(node.GetRuleContext <ParserRuleContext>(0))); } var expr = visitNode(node.GetRuleContext <ParserRuleContext>(0)); var args = null as ArgumentListSyntax; if (node.ChildCount == 4) { args = Arguments(node.GetRuleContext <ParserRuleContext>(2)); } else { args = CSharp.ArgumentList(); } return(CSharp.InvocationExpression(expr, args)); }
private ExpressionSyntax CreateCallback(bool success, bool leftOfParent, SyntaxToken token) { var arg1 = leftOfParent ? success ? Roslyn.@true : Roslyn.@false : Roslyn.@null; var arg2 = leftOfParent ? Roslyn.@null : success ? Roslyn.@true : Roslyn.@false; var ex = success ? Roslyn.@null : Templates.FailureParameter; return(CSharp .InvocationExpression(CSharp.IdentifierName(token)) .WithArgumentList(CSharp.ArgumentList(CSharp.SeparatedList(new[] { CSharp.Argument(arg1), CSharp.Argument(arg2), CSharp.Argument(ex) })))); }
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); }
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)); }
private static SyntaxNode ArgumentList(RParser.SublistContext args, Func <ParserRuleContext, Scope, SyntaxNode> transform, Scope scope) { var nodes = new List <ArgumentSyntax>(); foreach (var arg in args.sub()) { var argName = null as string; var value = null as ExpressionSyntax; if (arg is RParser.SubExpressionContext) { value = (ExpressionSyntax)transform((arg as RParser.SubExpressionContext).expr(), scope); } else if (arg is RParser.SubAssignmentContext) { var paramName = (arg as RParser.SubAssignmentContext); argName = paramName.ID().ToString(); value = (ExpressionSyntax)transform(paramName.expr(), scope); } else if (arg is RParser.SubStringAssignmentContext) { var paramName = (arg as RParser.SubStringAssignmentContext); argName = paramName.STRING().ToString(); value = (ExpressionSyntax)transform(paramName.expr(), scope); } else if (arg is RParser.SubIncompleteNullContext || arg is RParser.SubNullAssignmentContext) { throw new NotImplementedException(); } else if (arg is RParser.SubEllipsisContext) { throw new NotImplementedException(); } else if (arg is RParser.SubIncompleteAssignmentContext || arg is RParser.SubIncompleteStringContext || arg is RParser.SubIncompleteStringContext) { throw new NotImplementedException(); } else if (arg is RParser.SubEmptyContext) { continue; } else { Debug.Assert(false); } Debug.Assert(value != null); var result = CSharp.Argument(value); if (argName != null) { result = result .WithNameColon(CSharp .NameColon(argName)); } nodes.Add(result); } return(CSharp .ArgumentList() .WithArguments(CSharp .SeparatedList(nodes))); }