// Build an assembly from a list of source strings. public override CompilerResults CompileAssemblyFromSource(CompilerParameters options, params string[] sources) { var root = new Root(); foreach(string code in sources) parser.Parse(root, code); if(root.CompilerErrors.Count > 0) { var results = new CompilerResults(null); foreach(var e in root.CompilerErrors) results.Errors.Add(e); return results; } validator.Validate(options, root); if (root.CompilerErrors.Count > 0) { var results = new CompilerResults(null); foreach (var e in root.CompilerErrors) results.Errors.Add(e); return results; } var codeDomEmitter = new CodeDomEmitter(); return codeDomEmitter.Emit(options, root); }
// Emits the codedom statement for an if conditional block. public static CodeStatement Emit(IfBlock ifBlock) { // Create the codedom if statement. var i = new CodeConditionStatement(); // Emit the conditional statements for the if block. i.Condition = CodeDomEmitter.EmitCodeExpression(ifBlock.Conditional.ChildExpressions[0]); // Emit the lists of statements for the true and false bodies of the if block. // Comments need to be added in case the bodies are empty: these two properties // of the CodeConditionStatement can't be null. i.FalseStatements.Add(new CodeCommentStatement("If condition is false, execute these statements.")); i.TrueStatements.Add(new CodeCommentStatement("If condition is true, execute these statements.")); // Emit the statements for the true block foreach (var e in ifBlock.TrueBlock.ChildExpressions) { i.TrueStatements.Add(CodeDomEmitter.EmitCodeStatement(e)); } // Emit the statements for the false block. foreach (var e in ifBlock.FalseBlock.ChildExpressions) { i.FalseStatements.Add(CodeDomEmitter.EmitCodeStatement(e)); } return(i); }
// Generates a codedom instantiation expression: new foo() or new foo[x]. public static CodeExpression Emit(Instantiation instantiation) { // Array instantiation needs a different treatment. if (instantiation.IsArray) { var c = new CodeArrayCreateExpression(); c.CreateType = new CodeTypeReference(instantiation.Name); c.SizeExpression = CodeDomEmitter.EmitCodeExpression(instantiation.Parameters.ChildExpressions[0]); return(c); } else // Non-array instantiation { var c = new CodeObjectCreateExpression(); // The type that is being created var createType = new CodeTypeReference(instantiation.Name); // Apply the generic type names, if any. foreach (var g in instantiation.GenericTypes) { createType.TypeArguments.Add(new CodeTypeReference(g)); } c.CreateType = createType; // Translate the instantiation parameters. foreach (var a in instantiation.Parameters.ChildExpressions) { c.Parameters.Add(CodeDomEmitter.EmitCodeExpression(a)); } return(c); } }
// Generate a codedom throw statement public static CodeStatement Emit(Throw th) { var codeThrow = new CodeThrowExceptionStatement(); codeThrow.ToThrow = CodeDomEmitter.EmitCodeExpression(th.ChildExpressions[0]); return(codeThrow); }
// Generate a codedom return statement. public static CodeStatement Emit(Return r) { var codeMethodReturnStatement = new CodeMethodReturnStatement(); // Attach the expression to return, if any. if (r.ChildExpressions.Count > 0) { codeMethodReturnStatement.Expression = CodeDomEmitter.EmitCodeExpression(r.ChildExpressions[0]); } return(codeMethodReturnStatement); }
// Generates a codedom indexed identifier: one that is an identifier followed by an indexer: ex foo[1]. public static CodeExpression Emit(IndexedIdentifier indexedIdentifier) { // Create the codedom indexer expression var codeIndex = new CodeIndexerExpression(); // Set the object that is being indexed. codeIndex.TargetObject = new CodeVariableReferenceExpression(indexedIdentifier.Name); // Set the expression that is generating the index. codeIndex.Indices.Add(CodeDomEmitter.EmitCodeExpression(indexedIdentifier.ChildExpressions[0])); return(codeIndex); }
// Emit a codedome expression representing a while loop. public static CodeStatement Emit(WhileLoop loop) { // A while loop is a for loop with no initializer or incrementor, only a condition. var i = new CodeIterationStatement(new CodeSnippetStatement(""), CodeDomEmitter.EmitCodeExpression(loop.Condition.ChildExpressions[0]), new CodeSnippetStatement("")); // Emit the statements found in the body of the while loop. foreach (var e in loop.ChildExpressions) { i.Statements.Add(CodeDomEmitter.EmitCodeStatement(e)); } return(i); }
// Generate a series of codedom if statements representing a switch block. // (Codedom doesn't support switch) public static CodeStatement Emit(SwitchBlock switchBlock) { // Create the expression for whatever we're switching on. var codeVar = CodeDomEmitter.EmitCodeExpression(switchBlock.Variable.ChildExpressions[0]); // Store the first and previous if statements here, since it's needed on future loops. CodeConditionStatement codeIf = null; CodeConditionStatement lastIf = null; foreach (var e in switchBlock.ChildExpressions) { // Get the value being compared to: the right operand. var right = CodeDomEmitter.EmitCodeExpression((e as CaseBlock).Variable.ChildExpressions[0]); // Create the next if statement. var nestedIf = new CodeConditionStatement(); // Each case block will compare codeVar (left) to the right operand. nestedIf.Condition = new CodeBinaryOperatorExpression(codeVar, CodeBinaryOperatorType.ValueEquality, right); nestedIf.TrueStatements.Add(new CodeCommentStatement("If condition is true, execute these statements.")); foreach (var s in e.ChildExpressions) { nestedIf.TrueStatements.Add(CodeDomEmitter.EmitCodeStatement(s)); } nestedIf.FalseStatements.Add(new CodeCommentStatement("If condition is false, execute these statements.")); // if codeIf is null, this is the first if statement. if (codeIf == null) { codeIf = nestedIf; } else // It's not the first if statement, so attach it to the previous one. { lastIf.FalseStatements.Add(nestedIf); } // Store the last if block for the next iteration. lastIf = nestedIf; } return(codeIf); }
// Generate the codedom expression for a method invocation. public static CodeExpression Emit(MethodInvocation methodInvocation) { CodeTypeReferenceExpression t = null; // Check if it's a method owned by a variable. if (methodInvocation.Prefix != "") { t = new CodeTypeReferenceExpression(methodInvocation.Prefix); } // Create the codedom method invcation. var mi = new CodeMethodInvokeExpression(new CodeMethodReferenceExpression(t, methodInvocation.Name)); // Add the parameters of the method invocation. foreach (var a in methodInvocation.Parameters.ChildExpressions) { mi.Parameters.Add(CodeDomEmitter.EmitCodeExpression(a)); } return(mi); }
// Generate a codedom exception handler statement public static CodeStatement Emit(ExceptionHandler ex) { // Create the codedom exception handler statement var codeTry = new CodeTryCatchFinallyStatement(); // Add the statements in the try block foreach (var e in ex.Try.ChildExpressions) { codeTry.TryStatements.Add(CodeDomEmitter.EmitCodeStatement(e)); } // Add all the catch clauses. foreach (var c in ex.CatchClauses) { // Create the codedom catch statement. var catchClause = new CodeCatchClause(); // To do: replace with non-test code catchClause.CatchExceptionType = new CodeTypeReference("System.Exception"); catchClause.LocalName = "ex"; codeTry.CatchClauses.Add(catchClause); // Add the statemnts in the catch block foreach (var e in c.ChildExpressions) { catchClause.Statements.Add(CodeDomEmitter.EmitCodeStatement(e)); } } // Add the statements in the finally block. foreach (var e in ex.Finally.ChildExpressions) { codeTry.FinallyStatements.Add(CodeDomEmitter.EmitCodeStatement(e)); } return(codeTry); }
// Generate a codedom method declaration and attach it to the given codedom type. public static void Emit(CodeTypeDeclaration codeTypeDeclaration, MethodDeclaration methodDeclaration) { // Create the codedom member method and attach it to the codedom type. var codeMemberMethod = new CodeMemberMethod(); codeTypeDeclaration.Members.Add(codeMemberMethod); // Assign the method name codeMemberMethod.Name = methodDeclaration.Name; // Assign the return type: make sure to check for null. if (methodDeclaration.ReturnTypeName == "void") { codeMemberMethod.ReturnType = null; } else { codeMemberMethod.ReturnType = new CodeTypeReference(methodDeclaration.ReturnTypeName); } // Translate the method parameters. foreach (Expression p in methodDeclaration.Parameters) { if (p is SimpleParameter) // For example "int i" { codeMemberMethod.Parameters.Add(new CodeParameterDeclarationExpression((p as SimpleParameter).TypeName, (p as SimpleParameter).Name)); } if (p is DirectionedParameter) // For example "ref int i" { var codeParameter = new CodeParameterDeclarationExpression((p as DirectionedParameter).TypeName, (p as DirectionedParameter).Name); switch ((p as DirectionedParameter).Direction) { case ParameterDirection.Out: codeParameter.Direction = FieldDirection.Out; break; case ParameterDirection.Ref: codeParameter.Direction = FieldDirection.Ref; break; } codeMemberMethod.Parameters.Add(codeParameter); } } // Translate the method's accessibility MemberAttributes memberAttributes = MemberAttributes.Public; switch (methodDeclaration.Accessibility) { case Accessibility.Internal: memberAttributes = MemberAttributes.FamilyAndAssembly; break; case Accessibility.Private: memberAttributes = MemberAttributes.Private; break; case Accessibility.Protected: memberAttributes = MemberAttributes.Family; break; case Accessibility.Public: memberAttributes = MemberAttributes.Public; break; } // Shared = static if (methodDeclaration.IsShared) { memberAttributes |= MemberAttributes.Static; } if (methodDeclaration.IsAbstract) { memberAttributes |= MemberAttributes.Abstract; } if (!methodDeclaration.IsVirtual && !methodDeclaration.IsAbstract) { if (methodDeclaration.IsOverride) { memberAttributes |= MemberAttributes.Override; } else { memberAttributes |= MemberAttributes.Final; } } codeMemberMethod.Attributes = memberAttributes; // Add the statements found in the method body. foreach (var e in methodDeclaration.ChildExpressions) { codeMemberMethod.Statements.Add(CodeDomEmitter.EmitCodeStatement(e)); } }
// Emit a codedom binary operation expression public static CodeExpression Emit(BinaryOperator op) { // Translate the operator type to a codedom one. CodeBinaryOperatorType opType = CodeBinaryOperatorType.Add; switch (op.OperatorType) { case BinaryOperatorType.Subtract: opType = CodeBinaryOperatorType.Subtract; break; case BinaryOperatorType.Divide: opType = CodeBinaryOperatorType.Divide; break; case BinaryOperatorType.Multiply: opType = CodeBinaryOperatorType.Multiply; break; case BinaryOperatorType.Less: opType = CodeBinaryOperatorType.LessThan; break; case BinaryOperatorType.LessOrEqual: opType = CodeBinaryOperatorType.LessThanOrEqual; break; case BinaryOperatorType.Equal: opType = CodeBinaryOperatorType.IdentityEquality; break; case BinaryOperatorType.NotEqual: opType = CodeBinaryOperatorType.IdentityInequality; break; case BinaryOperatorType.Greater: opType = CodeBinaryOperatorType.GreaterThan; break; case BinaryOperatorType.GreaterOrEqual: opType = CodeBinaryOperatorType.GreaterThanOrEqual; break; case BinaryOperatorType.BitwiseAnd: opType = CodeBinaryOperatorType.BitwiseAnd; break; case BinaryOperatorType.BitwiseOr: opType = CodeBinaryOperatorType.BitwiseOr; break; case BinaryOperatorType.Modulo: opType = CodeBinaryOperatorType.Modulus; break; case BinaryOperatorType.LogicalAnd: opType = CodeBinaryOperatorType.BooleanAnd; break; case BinaryOperatorType.LogicalOr: opType = CodeBinaryOperatorType.BooleanOr; break; case BinaryOperatorType.As: // Casting requires a different set of codedom expressions. var cast = new CodeCastExpression(); cast.TargetType = new CodeTypeReference((op.ChildExpressions[1] as VariableReference).Name); cast.Expression = CodeDomEmitter.EmitCodeExpression(op.ChildExpressions[0]); return(cast); } var o = new CodeBinaryOperatorExpression(CodeDomEmitter.EmitCodeExpression(op.ChildExpressions[0]), // left operand opType, // operator CodeDomEmitter.EmitCodeExpression(op.ChildExpressions[1])); // right operand return(o); }
// Emit a codedome expression representing a for loop. public static CodeStatement Emit(ForLoop loop) { // The expression describing how the for loop starts. CodeExpression startEx = null; // The expression describing how the for loop ends. CodeExpression endEx = null; // The for loop has both a start and end defined. For example: for int i in 0 to 10 if (loop.Condition.ChildExpressions.Count > 1) { startEx = CodeDomEmitter.EmitCodeExpression(loop.Condition.ChildExpressions[0]); endEx = CodeDomEmitter.EmitCodeExpression(loop.Condition.ChildExpressions[1]); } else // The for loop has only the end defined. For examle: for int i in 10 { startEx = new CodePrimitiveExpression(0); endEx = CodeDomEmitter.EmitCodeExpression(loop.Condition.ChildExpressions[0]); } // The statement that initializes the for loop (int i, i, etc). CodeStatement varInit = null; // The variable reference from the initialization: we need this when the initialization is "int i". // The variable reference is "i". CodeExpression varRef = null; // An intializer that is an explicit variable declaration must be handled differently. if (loop.Initialization.ChildExpressions[0] is ExplicitVariableDeclaration) { // Get the explicit variable declaration var explicitVariable = loop.Initialization.ChildExpressions[0] as ExplicitVariableDeclaration; varInit = new CodeVariableDeclarationStatement(explicitVariable.TypeName, explicitVariable.Name, // The declaration startEx); // The assignment varRef = new CodeVariableReferenceExpression((loop.Initialization.ChildExpressions[0] as ExplicitVariableDeclaration).Name); } else // It's a variable reference { // Get the variable reference. var variable = loop.Initialization.ChildExpressions[0] as VariableReference; varRef = new CodeVariableReferenceExpression((loop.Initialization.ChildExpressions[0] as VariableReference).Name); varInit = new CodeAssignStatement(varRef, // Left operand startEx); } // Pie's for loop is limited to less than or equal conditional. var op = new CodeBinaryOperatorExpression(varRef, CodeBinaryOperatorType.LessThanOrEqual, endEx); // The step: the amount incremented or decremented. CodeStatement stepSt = null; if (loop.Step.ChildExpressions[0] is Literal) { var literal = loop.Step.ChildExpressions[0] as Literal; stepSt = new CodeAssignStatement(varRef, new CodeBinaryOperatorExpression( varRef, CodeBinaryOperatorType.Add, new CodePrimitiveExpression(literal.Value))); } var i = new CodeIterationStatement(varInit, op, stepSt); // Emit the statements found in the body of the while loop. foreach (var e in loop.ChildExpressions) { i.Statements.Add(CodeDomEmitter.EmitCodeStatement(e)); } return(i); }
// Generate a codedom property expression and attach it to the codedom type. public static void Emit(CodeTypeDeclaration codeTypeDeclaration, Property property) { // Create the codedom property and attach it to the codedom type. var codeProperty = new CodeMemberProperty(); codeTypeDeclaration.Members.Add(codeProperty); // Assign the name. codeProperty.Name = property.Name; // Assign the return type, making sure to check for null. if (property.TypeName == "void") { codeProperty.Type = null; } else { codeProperty.Type = new CodeTypeReference(property.TypeName); } // Translate the accessibility. MemberAttributes memberAttributes = MemberAttributes.Public; switch (property.Accessibility) { case Accessibility.Internal: memberAttributes = MemberAttributes.FamilyAndAssembly; break; case Accessibility.Private: memberAttributes = MemberAttributes.Private; break; case Accessibility.Protected: memberAttributes = MemberAttributes.Family; break; case Accessibility.Public: memberAttributes = MemberAttributes.Public; break; } // Shared = static if (property.IsShared) { memberAttributes |= MemberAttributes.Static; } if (property.IsAbstract) { memberAttributes |= MemberAttributes.Abstract; } if (property.IsOverride) { memberAttributes |= MemberAttributes.Override; } codeProperty.Attributes = memberAttributes; // Add the statements for the get block. if (property.GetBlock.ChildExpressions.Count > 0) { foreach (var e in property.GetBlock.ChildExpressions) { codeProperty.GetStatements.Add(CodeDomEmitter.EmitCodeStatement(e)); } } else { codeProperty.GetStatements.Add(new CodeCommentStatement("Placeholder statement")); } // Add the statements for the set block. if (property.SetBlock.ChildExpressions.Count > 0) { foreach (var e in property.SetBlock.ChildExpressions) { codeProperty.SetStatements.Add(CodeDomEmitter.EmitCodeStatement(e)); } } else { codeProperty.SetStatements.Add(new CodeCommentStatement("Placeholder statement")); } }
/* Returns a CodeDOM statement representing an Assignment expression. */ public static CodeStatement Emit(Assignment assignment) { // The expression that is being assigned. var assignedExpression = CodeDomEmitter.EmitCodeExpression(assignment.ChildExpressions[1]); // Translate the assignment type to a CodeDOM one. var codeOperator = CodeBinaryOperatorType.Add; switch (assignment.AssignmentType) { case AssignmentType.Add: codeOperator = CodeBinaryOperatorType.Add; break; case AssignmentType.And: codeOperator = CodeBinaryOperatorType.BitwiseAnd; break; case AssignmentType.Or: codeOperator = CodeBinaryOperatorType.BitwiseOr; break; case AssignmentType.Divide: codeOperator = CodeBinaryOperatorType.Divide; break; case AssignmentType.Multiply: codeOperator = CodeBinaryOperatorType.Multiply; break; case AssignmentType.Subtract: codeOperator = CodeBinaryOperatorType.Subtract; break; } /* Variables that are immediately assigned a value upon explicit declaration such as: * int i = 10 * require a different CodeDOM statement than the normal assignment statement. */ if (assignment.ChildExpressions[0] is ExplicitVariableDeclaration) { var variable = assignment.ChildExpressions[0] as ExplicitVariableDeclaration; var codeType = new CodeTypeReference(); codeType.BaseType = variable.TypeName; foreach (String e in variable.GenericTypes) { codeType.TypeArguments.Add(new CodeTypeReference(e)); } if (assignment.AssignmentType == AssignmentType.Equal) { return(new CodeVariableDeclarationStatement(codeType, variable.Name, // The declaration assignedExpression)); // The assignment } else { // If we got this far, the validator missed that int i += x is not valid. // Since this should have been caught prior to reaching the generator, this is a failure state. throw new NotImplementedException(); } } else // Normal assignment (ex i = 1) { var left = CodeDomEmitter.EmitCodeExpression(assignment.ChildExpressions[0]); if (assignment.AssignmentType == AssignmentType.Equal) { // A simple assignment: left = assignedExpression return(new CodeAssignStatement(left, // Left operand assignedExpression)); // Right operand } else { // Some other type of assignment, such as left += assignedExpression // We need to create the appropriate codedom binary expression first. var addOp = new CodeBinaryOperatorExpression(); addOp.Left = left; addOp.Right = assignedExpression; addOp.Operator = codeOperator; return(new CodeAssignStatement(left, addOp)); } } }
// Generates a codedom constructor expression and attaches it to the given type. public static void Emit(CodeTypeDeclaration codeTypeDeclaration, Constructor ctor) { // Create the codedom constructor var codeCtor = new CodeConstructor(); codeTypeDeclaration.Members.Add(codeCtor); // Translate accessibility of the constructor MemberAttributes memberAttributes = MemberAttributes.Public; switch (ctor.Accessibility) { case Accessibility.Internal: memberAttributes |= MemberAttributes.FamilyAndAssembly; break; case Accessibility.Private: memberAttributes |= MemberAttributes.Private; break; case Accessibility.Protected: memberAttributes |= MemberAttributes.Family; break; case Accessibility.Public: memberAttributes |= MemberAttributes.Public; break; } codeCtor.Attributes = memberAttributes; // Translate the parameters of the constructor foreach (Expression p in ctor.Parameters) { if (p is SimpleParameter) // ex "int i" { codeCtor.Parameters.Add(new CodeParameterDeclarationExpression((p as SimpleParameter).TypeName, (p as SimpleParameter).Name)); } if (p is DirectionedParameter) // ex "ref int i" { var codeParameter = new CodeParameterDeclarationExpression((p as DirectionedParameter).TypeName, (p as DirectionedParameter).Name); switch ((p as DirectionedParameter).Direction) { case ParameterDirection.Out: codeParameter.Direction = FieldDirection.Out; break; case ParameterDirection.Ref: codeParameter.Direction = FieldDirection.Ref; break; } codeCtor.Parameters.Add(codeParameter); } } // Add call to a constructor of the base class or another in the same class. foreach (var a in ctor.SubParameters.ChildExpressions) { if (ctor.Sub) { codeCtor.ChainedConstructorArgs.Add(CodeDomEmitter.EmitCodeExpression(a)); } else { codeCtor.BaseConstructorArgs.Add(CodeDomEmitter.EmitCodeExpression(a)); } } // Add all the statements in the body of the constructor foreach (var e in ctor.ChildExpressions) { codeCtor.Statements.Add(CodeDomEmitter.EmitCodeStatement(e)); } }