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; }
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); }
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 Typedef(SyntaxNode node, Scope scope) { var field = node .AncestorsAndSelf() .OfType <FieldDeclarationSyntax>() .FirstOrDefault(); if (field == null) { scope.AddError("xs01", "malformed typedef", node); //td: error, malformed typedef return(node); } if (field.Declaration.Variables.Count != 1) { scope.AddError("xs01", "malformed typedef", node); return(node); } var variable = field .Declaration .Variables[0]; Debug.Assert(variable.Initializer == null || variable.Initializer.IsMissing); var type = RoslynCompiler.UnMark(field.Declaration.Type); var identifier = variable.Identifier; var parentScope = scope.CreateScope <SyntaxToken, SyntaxNode, SemanticModel>(field.Parent); Debug.Assert(parentScope != null); parentScope.set("__tdef" + identifier.ToString(), type); //schedule deletion var document = scope.GetDocument <SyntaxToken, SyntaxNode, SemanticModel>(); document.change(field.Parent, RoslynCompiler.RemoveMember(field)); //return intact return(node); }
private static SyntaxNode ProcessMatch(SyntaxNode node, Scope scope) { var switchExpr = node as SwitchStatementSyntax; if (switchExpr == null) { scope.AddError("match01", "malformed match", node); return(node); } //store items to simplify var cases = new List <ExpressionSyntax>(); var statements = new List <StatementSyntax>(); var defaultStatement = null as StatementSyntax; foreach (var section in switchExpr.Sections) { bool isDefault; var expr = caseExpression(section.Labels, switchExpr.Expression, out isDefault); StatementSyntax statement = caseStatement(section.Statements); if (isDefault && section.Labels.Count == 1) { defaultStatement = statement; } else { cases.Add(expr); statements.Add(statement); if (isDefault) { defaultStatement = statement; } } } //convert cases to ifs Debug.Assert(cases.Count == statements.Count); var last = cases.Count - 1; IfStatementSyntax result = CSharp.IfStatement(cases[last], statements[last]); if (defaultStatement != null) { result = result.WithElse(CSharp.ElseClause(defaultStatement)); } for (int i = last - 1; i >= 0; i--) { result = CSharp.IfStatement(cases[i], statements[i]) .WithElse(CSharp.ElseClause(result)); } return(result); }
private static SyntaxNode TransformFoo(string id, object value, IEnumerable <InstanceConnection <SyntaxNode> > connections, Scope scope) { var decl = instanceCreation.Get(id, "RuntimeFoo"); scope.AddInstanceDeclaration(decl .ReplaceNodes(decl .DescendantNodes() .OfType <ParameterListSyntax>(), (on, nn) => { var values = (value as InstanceFoo).Values; return(nn .WithParameters(CSharp.SeparatedList( values.Select(val => CSharp.Parameter(CSharp.Literal(val)))))); })); foreach (var connection in connections) { if (connection.Input == null) { scope.AddError("test01", "unregistered connection", connection.OutputModelNode); continue; } if (connection.Output == null) { scope.AddError("test01", "unregistered connection", connection.InputModelNode); continue; } if (connection.Source == id) { connection.OutputNode = CSharp.ParseExpression(id + "." + connection.Output.Id); } else { Assert.IsTrue(connection.Target == id); connection.InputNode = CSharp.ParseExpression(id + "." + connection.Input.Id); } } return(null); }
private static SyntaxNode ProcessSynch(SyntaxNode node, Scope scope, SyntacticalExtension <SyntaxNode> extension) { if (extension.Kind == ExtensionKind.Code) { //td: verify it's inside an asynch return(SynchTemplate .ReplaceNodes(SynchTemplate .DescendantNodes() .OfType <BlockSyntax>(), (oldNode, newNode) => extension.Body)); } scope.AddError("synch01", "synch does not return a value", node); return(node); }
private static SyntaxNode ProcessSynch(SyntaxNode node, Scope scope, SyntacticalExtension<SyntaxNode> extension) { if (extension.Kind == ExtensionKind.Code) { //td: verify it's inside an asynch return SynchTemplate .ReplaceNodes(SynchTemplate .DescendantNodes() .OfType<BlockSyntax>(), (oldNode, newNode) => extension.Body); } scope.AddError("synch01", "synch does not return a value", node); return node; }
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); } }
private static SyntaxNode Transform(SyntaxNode oldNode, SyntaxNode newNode, Scope scope, LexicalExtension <SyntaxToken> extension) { Debug.Assert(newNode is AnonymousObjectCreationExpressionSyntax); var result = createJson.Get(newNode); var isAssignment = false; result = Roslyn.ReplaceAssignment(oldNode, result, out isAssignment); if (!isAssignment) { scope.AddError("json01", "json expects to be assigned", oldNode); return(newNode); } return(result); }
private static SyntaxNode ProcessAsynch(SyntaxNode node, Scope scope, SyntacticalExtension <SyntaxNode> extension) { if (extension.Kind == ExtensionKind.Code) { var result = AsynchTemplate .ReplaceNodes(AsynchTemplate .DescendantNodes() .OfType <BlockSyntax>(), (oldNode, newNode) => extension.Body); var document = scope.GetDocument <SyntaxToken, SyntaxNode, SemanticModel>(); document.change(node.Parent, RoslynCompiler.AddStatement(ContextVariable, before: node)); return(result); } scope.AddError("asynch01", "asynch does not return a value", node); return(node); }
private static SyntaxNode ProcessAsynch(SyntaxNode node, Scope scope, SyntacticalExtension<SyntaxNode> extension) { if (extension.Kind == ExtensionKind.Code) { var result = AsynchTemplate .ReplaceNodes(AsynchTemplate .DescendantNodes() .OfType<BlockSyntax>(), (oldNode, newNode) => extension.Body); var document = scope.GetDocument<SyntaxToken, SyntaxNode, SemanticModel>(); document.change(node.Parent, RoslynCompiler.AddStatement(ContextVariable, before: node)); return result; } scope.AddError("asynch01", "asynch does not return a value", node); return node; }
private static SyntaxNode Typedef(SyntaxNode node, Scope scope) { var field = node .AncestorsAndSelf() .OfType<FieldDeclarationSyntax>() .FirstOrDefault(); if (field == null) { scope.AddError("xs01", "malformed typedef", node); //td: error, malformed typedef return node; } if (field.Declaration.Variables.Count != 1) { scope.AddError("xs01", "malformed typedef", node); return node; } var variable = field .Declaration .Variables[0]; Debug.Assert(variable.Initializer == null || variable.Initializer.IsMissing); var type = RoslynCompiler.UnMark(field.Declaration.Type); var identifier = variable.Identifier; var parentScope = scope.CreateScope<SyntaxToken, SyntaxNode, SemanticModel>(field.Parent); Debug.Assert(parentScope != null); parentScope.set("__tdef" + identifier.ToString(), type); //schedule deletion var document = scope.GetDocument<SyntaxToken, SyntaxNode, SemanticModel>(); document.change(field.Parent, RoslynCompiler.RemoveMember(field)); //return intact return node; }
private static SyntaxNode Transform(SyntaxNode oldNode, SyntaxNode newNode, Scope scope, LexicalExtension <SyntaxToken> extension) { Debug.Assert(newNode is BlockSyntax); var isAssignment = oldNode is LocalDeclarationStatementSyntax; if (!isAssignment && oldNode is BinaryExpressionSyntax) { var expr = oldNode as BinaryExpressionSyntax; isAssignment = expr.Kind() == SyntaxKind.SimpleAssignmentExpression; } if (isAssignment) { scope.AddError("r01", "R does not return", oldNode); return(newNode); } var document = scope.GetDocument <SyntaxToken, SyntaxNode, SemanticModel>(); document.change(oldNode.Parent, RoslynCompiler.ExplodeBlock(newNode)); return(newNode); }
private static SyntaxNode TransformFoo(string id, object value, IEnumerable<InstanceConnection<SyntaxNode>> connections, Scope scope) { var decl = instanceCreation.Get(id, "RuntimeFoo"); scope.AddInstanceDeclaration(decl .ReplaceNodes(decl .DescendantNodes() .OfType<ParameterListSyntax>(), (on, nn) => { var values = (value as InstanceFoo).Values; return nn .WithParameters(CSharp.SeparatedList( values.Select(val => CSharp.Parameter(CSharp.Literal(val))))); })); foreach (var connection in connections) { if (connection.Input == null) { scope.AddError("test01", "unregistered connection", connection.OutputModelNode); continue; } if (connection.Output == null) { scope.AddError("test01", "unregistered connection", connection.InputModelNode); continue; } if (connection.Source == id) connection.OutputNode = CSharp.ParseExpression(id + "." + connection.Output.Id); else { Assert.IsTrue(connection.Target == id); connection.InputNode = CSharp.ParseExpression(id + "." + connection.Input.Id); } } return null; }
private static SyntaxNode ProcessMatch(SyntaxNode node, Scope scope) { var switchExpr = node as SwitchStatementSyntax; if (switchExpr == null) { scope.AddError("match01", "malformed match", node); return node; } //store items to simplify var cases = new List<ExpressionSyntax>(); var statements = new List<StatementSyntax>(); var defaultStatement = null as StatementSyntax; foreach (var section in switchExpr.Sections) { bool isDefault; var expr = caseExpression(section.Labels, switchExpr.Expression, out isDefault); StatementSyntax statement = caseStatement(section.Statements); if (isDefault && section.Labels.Count == 1) { defaultStatement = statement; } else { cases.Add(expr); statements.Add(statement); if (isDefault) defaultStatement = statement; } } //convert cases to ifs Debug.Assert(cases.Count == statements.Count); var last = cases.Count - 1; IfStatementSyntax result = CSharp.IfStatement(cases[last], statements[last]); if (defaultStatement != null) result = result.WithElse(CSharp.ElseClause(defaultStatement)); for (int i = last - 1; i >= 0; i--) { result = CSharp.IfStatement(cases[i], statements[i]) .WithElse(CSharp.ElseClause(result)); } return result; }
private static SyntaxNode Transform(SyntaxNode oldNode, SyntaxNode newNode, Scope scope, LexicalExtension<SyntaxToken> extension) { Debug.Assert(newNode is BlockSyntax); var isAssignment = oldNode is LocalDeclarationStatementSyntax; if (!isAssignment && oldNode is BinaryExpressionSyntax) { var expr = oldNode as BinaryExpressionSyntax; isAssignment = expr.Kind() == SyntaxKind.SimpleAssignmentExpression; } if (isAssignment) { scope.AddError("r01", "R does not return", oldNode); return newNode; } var document = scope.GetDocument<SyntaxToken, SyntaxNode, SemanticModel>(); document.change(oldNode.Parent, RoslynCompiler.ExplodeBlock(newNode)); return newNode; }
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); }
public void SyntaxError(IRecognizer recognizer, TToken offendingSymbol, int line, int charPositionInLine, string msg, RecognitionException e) { _scope.AddError("grammar syntax error", msg, _offset + offendingSymbol.StartIndex, offendingSymbol.StopIndex - offendingSymbol.StartIndex); }