// Build an interface method declaration. public static void BuildInterfaceMethod(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { var method = new MethodDeclaration(parentExpression, currentNode.Token.Convert()); parentExpression.ChildExpressions.Add(method); // Build the return type of the interface method. method.ReturnTypeName = parser.CheckAlias(currentNode.ChildNodes[0].ChildNodes[0].FindTokenAndGetText()); // The name of the interface method. method.Name = currentNode.ChildNodes[0].ChildNodes[1].FindTokenAndGetText(); // Build the list of generic type names. if (currentNode.ChildNodes[1].ChildNodes.Count > 0) { var generics = currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[1]; foreach (string s in IronyParser.InterpretList(generics)) method.GenericTypeNames.Add(parser.CheckAlias(s)); } // Build the arguments of the method if (currentNode.ChildNodes[2].ChildNodes.Count > 0) { foreach (var n in currentNode.ChildNodes[2].ChildNodes) { MethodDeclarationBuilder.BuildArgument(parser, method, n.ChildNodes[0]); } } }
// Build the arguments for the method: check if it's directioned, array, generic, or simple public static void BuildArgument(IronyParser parser, MethodDeclaration method, ParseTreeNode node) { if (node.Term.ToString() == "out_parameter") { var a = new DirectionedParameter(null, node.FindToken().Convert()); switch(node.ChildNodes[0].ChildNodes[0].Term.ToString()) { case "ref": a.Direction = ParameterDirection.Ref; break; case "out": a.Direction = ParameterDirection.Out; break; } a.TypeName = parser.CheckAlias(node.ChildNodes[1].FindTokenAndGetText()); a.Name = node.ChildNodes[2].FindTokenAndGetText(); method.Parameters.Add(a); } else if(node.Term.ToString() == "array_parameter") { var a = new SimpleParameter(null, node.FindToken().Convert()); a.TypeName = parser.CheckAlias(node.ChildNodes[0].FindTokenAndGetText()) + "[]"; a.Name = node.ChildNodes[3].FindTokenAndGetText(); method.Parameters.Add(a); } else if(node.Term.ToString() == "generic_parameter") { var a = new SimpleParameter(null, node.FindToken().Convert()); a.TypeName = node.ChildNodes[0].ChildNodes[0].FindTokenAndGetText()+"<"; for(int i = 0; i < node.ChildNodes[0].ChildNodes[2].ChildNodes.Count; i++) { a.TypeName += parser.CheckAlias(node.ChildNodes[0].ChildNodes[2].ChildNodes[i].FindTokenAndGetText()); if (i < node.ChildNodes[0].ChildNodes[2].ChildNodes.Count - 1) a.TypeName += ","; } a.TypeName += ">"; a.Name = node.ChildNodes[1].FindTokenAndGetText(); method.Parameters.Add(a); } else { var a = new SimpleParameter(null, node.FindToken().Convert()); a.TypeName = parser.CheckAlias(node.ChildNodes[0].FindTokenAndGetText()); a.Name = node.ChildNodes[1].FindTokenAndGetText(); method.Parameters.Add(a); } }
// 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)); }
// Build a method declaration expression public static void BuildMethodDeclaration(IronyParser parser, Root root, Expression parentExpression, ParseTreeNode currentNode) { MethodDeclaration e = new MethodDeclaration(parentExpression, currentNode.FindToken().Convert()); parentExpression.ChildExpressions.Add(e); int i = 0; // Set default modifiers var c = parentExpression as Class; if(c.IsModule) // If the parent is a module, set the method to shared. { e.IsShared = true; } // Interpret the modifiers for the method declaration InterpretModifiers(root, e, currentNode.ChildNodes[0].ChildNodes[0]); if(e.IsShared && (e.IsFinal || e.IsOverride)) root.CompilerErrors.Add(new IncompatibleModifiersCompilerError("", currentNode.FindToken().Location.Line, currentNode.FindToken().Location.Position)); i+=1; // skip the def // Interpret the return type name: check if it's an array, generic, or simple type name if (currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[0].Term.ToString() == "array") { e.Name = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText(); e.ReturnTypeName = parser.CheckAlias(currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[0].FindTokenAndGetText()) + "[]"; } else if (currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[0].Term.ToString() == "generic_identifier") { var genericNode = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].ChildNodes[0]; e.Name = parser.CheckAlias(currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText()); e.ReturnTypeName = parser.CheckAlias(genericNode.ChildNodes[0].FindTokenAndGetText()) + "<"; for(int n = 0; n < genericNode.ChildNodes[2].ChildNodes.Count; n++) { e.ReturnTypeName += parser.CheckAlias(genericNode.ChildNodes[2].ChildNodes[n].FindTokenAndGetText()); if(n < genericNode.ChildNodes[2].ChildNodes.Count - 1) e.ReturnTypeName += ","; } e.ReturnTypeName += ">"; } else { e.Name = currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[1].FindTokenAndGetText(); e.ReturnTypeName = parser.CheckAlias(currentNode.ChildNodes[0].ChildNodes[1].ChildNodes[0].FindTokenAndGetText()); } i++; i++; // Add the generic type names for the method declaration if (currentNode.ChildNodes[1].ChildNodes.Count > 0) { var generics = currentNode.ChildNodes[1].ChildNodes[0].ChildNodes[1]; foreach (string s in IronyParser.InterpretList(generics)) e.GenericTypeNames.Add(s); } i+=1; // add the arguments for the method declaration if (currentNode.ChildNodes[2].ChildNodes.Count > 0) { foreach (var n in currentNode.ChildNodes[2].ChildNodes) { BuildArgument(parser, e, n.ChildNodes[0]); } } // Build the body of statements in the method declaration parser.ConsumeParseTree(root, e, currentNode.ChildNodes[3]); }
// Interpret the modifiers for the method declaration static void InterpretModifiers(Root root, MethodDeclaration c, ParseTreeNode node) { bool foundPublic = false; bool foundInternal = false; bool foundFinal = false; bool foundShared = false; bool foundAbstract = false; bool foundPrivate = false; bool foundProtected = false; bool foundOverride = false; bool foundVirtual = false; foreach (var modifierNode in node.ChildNodes) { string text = modifierNode.FindTokenAndGetText(); if (text == "public") { if (foundPublic || foundInternal || foundPrivate || foundProtected) { root.CompilerErrors.Add(new MultipleAccessModifiersCompilerError("", modifierNode.FindToken().Location.Line, modifierNode.FindToken().Location.Position)); } else { c.Accessibility = Accessibility.Public; foundPublic = true; } } if (text == "internal") { if (foundInternal || foundPublic || foundPrivate || foundProtected) { root.CompilerErrors.Add(new MultipleAccessModifiersCompilerError("", modifierNode.FindToken().Location.Line, modifierNode.FindToken().Location.Position)); } else { c.Accessibility = Accessibility.Internal; foundInternal = true; } } if (text == "protected") { if (foundInternal || foundPublic || foundPrivate || foundProtected) { root.CompilerErrors.Add(new MultipleAccessModifiersCompilerError("", modifierNode.FindToken().Location.Line, modifierNode.FindToken().Location.Position)); } else { c.Accessibility = Accessibility.Protected; foundProtected = true; } } if (text == "private") { if (foundInternal || foundPublic || foundPrivate || foundProtected) { root.CompilerErrors.Add(new MultipleAccessModifiersCompilerError("", modifierNode.FindToken().Location.Line, modifierNode.FindToken().Location.Position)); } else { c.Accessibility = Accessibility.Private; foundPrivate = true; } } if (text == "final") { if (foundFinal) { root.CompilerErrors.Add(new DuplicateModifiersCompilerError("", modifierNode.FindToken().Location.Line, modifierNode.FindToken().Location.Position)); } else { c.IsFinal = true; foundFinal = true; } } if (text == "abstract") { if (foundAbstract) { root.CompilerErrors.Add(new DuplicateModifiersCompilerError("", modifierNode.FindToken().Location.Line, modifierNode.FindToken().Location.Position)); } else { c.IsAbstract = true; foundAbstract = true; } } if (text == "shared") { if (foundShared) { root.CompilerErrors.Add(new DuplicateModifiersCompilerError("", modifierNode.FindToken().Location.Line, modifierNode.FindToken().Location.Position)); } else { c.IsShared = true; foundShared = true; } } if (text == "virtual") { if (foundVirtual) { root.CompilerErrors.Add(new DuplicateModifiersCompilerError("", modifierNode.FindToken().Location.Line, modifierNode.FindToken().Location.Position)); } else { c.IsVirtual = true; foundVirtual = true; } } if (text == "override") { if (foundOverride) { root.CompilerErrors.Add(new DuplicateModifiersCompilerError("", modifierNode.FindToken().Location.Line, modifierNode.FindToken().Location.Position)); } else { c.IsOverride = true; foundOverride = true; } } } }