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 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)); }
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); }
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)); }
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))); }
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()))); }
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))))); }
private static StatementSyntax caseStatement(SyntaxList <StatementSyntax> statements) { Debug.Assert(statements.Any()); if (statements.Count == 1) { return(statements.First()); } return(CSharp.Block(statements)); }
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); }
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)); }
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) })))); }
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)); }
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 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))))); }
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 }))); }
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))))))))); }
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)); }
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)))); }
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); } } }
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())); }
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 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); }); }
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))))); }
private static StatementSyntax caseStatement(SyntaxList <StatementSyntax> statements) { return(CSharp.Block( validCaseStatements(statements))); }
private ParenthesizedLambdaExpressionSyntax WrapInLambda(IEnumerable <ExpressionSyntax> expressions) { return(CSharp.ParenthesizedLambdaExpression( CSharp.Block(expressions .Select(e => CSharp.ExpressionStatement(e))))); }
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--; } }