private void BuildMethod(FunctionImplementation implementation) { string name = VMTranslations.RemovePrefixes(pluginNameVar, implementation.Name.Identifier, false); string retType = VMTranslations.RemovePrefixes(pluginNameVar, implementation.ReturnType.Declaration); List <string> funcParams = new List <string>(); foreach (FunctionParameter param in implementation.Parameters) { string paramType = VMTranslations.RemovePrefixes(pluginNameVar, param.m_Type.Declaration); string paramName = Output_CSharp.GetSafeVariableName(param.m_Lvalue.Identifier); string paramStr = paramType + " " + paramName; if (param is FunctionParameterWithDefault def) { string defaultAsStr = Output_CSharp.GetValueAsString(def.m_Default, true); paramStr += " = " + defaultAsStr; } funcParams.Add(paramStr); } string parameters = funcParams.Count == 0 ? "" : funcParams.Aggregate((a, b) => a + ", " + b); stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}public static {retType} {name}({parameters})"); stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}{{"); BuildImplementation(implementation); stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}}}"); stringBuilder.AppendLine(); }
private void ProcessImplementationNode(FunctionImplementation implementation, List <string> vectorDecls, NSSNode node, int depth) { string expression; switch (node) { case LvalueDeclSingleWithAssignment declAssignment: expression = VMTranslations.TryTranslate(pluginNameVar, declAssignment.m_Expression.m_Expression); if (declAssignment.m_Lvalue.Identifier == "sFunc") { stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}const {declAssignment.m_Type.Declaration} {declAssignment.m_Lvalue.Identifier} = {expression};"); stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}VM.NWNX.SetFunction({pluginNameVar}, sFunc);"); break; } stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{declAssignment.m_Type.Declaration} {declAssignment.m_Lvalue.Identifier} = {expression};"); break; case LvalueAssignment assignment: string[] identifier = assignment.m_Lvalue.Identifier.Split('.', 2); if (identifier.Length > 1 && vectorDecls.Contains(identifier[0])) { identifier[1] = identifier[1].ToUpper(); } expression = VMTranslations.TryTranslate(pluginNameVar, assignment.m_Expression.m_Expression); stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{string.Join('.', identifier)} = {expression};"); break; case LvalueDeclSingle declaration: if (declaration.m_Type.GetType() == typeof(StringType)) { stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{VMTranslations.RemovePrefixes(pluginNameVar, declaration.m_Type.Declaration)} {declaration.m_Lvalue.Identifier} = \"\";"); } else if (declaration.m_Type is StructType) { stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{VMTranslations.RemovePrefixes(pluginNameVar, declaration.m_Type.Declaration)} {declaration.m_Lvalue.Identifier} = default;"); } else if (declaration.m_Type is VectorType) { stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{VMTranslations.RemovePrefixes(pluginNameVar, declaration.m_Type.Declaration)} {declaration.m_Lvalue.Identifier} = default;"); vectorDecls.Add(declaration.m_Lvalue.Identifier); } else { stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{VMTranslations.RemovePrefixes(pluginNameVar, declaration.m_Type.Declaration)} {declaration.m_Lvalue.Identifier};"); } break; case FunctionCall functionCall: expression = VMTranslations.TranslateCall(pluginNameVar, functionCall.m_Name.Identifier, functionCall.m_Arguments); stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{expression};"); break; case ReturnStatement returnStatement: if (implementation.ReturnType is StructType || implementation.ReturnType is VectorType) { stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}return {returnStatement.m_Expression.m_Expression};"); break; } stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}return {implementation.ReturnType.NWNXPopFormat};"); break; case IfStatement ifStatement: expression = VMTranslations.TryTranslate(pluginNameVar, ifStatement.m_Expression.m_Expression); if (!expression.Contains("==") && !expression.Contains("!=") && !expression.Contains("<") && !expression.Contains(">")) { if (expression.StartsWith("!")) { expression = $"{expression.Substring(1)} == FALSE"; } else { expression = $"{expression} == TRUE"; } } stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}if ({expression})"); ProcessImplementationNode(implementation, vectorDecls, ifStatement.m_Action, depth); break; case ElseStatement elseStatement: stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}else"); ProcessImplementationNode(implementation, vectorDecls, elseStatement.m_Action, depth); break; case ForLoop forLoop: stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}for ({forLoop.m_Pre.m_Expression}; {forLoop.m_Condition.m_Expression}; {forLoop.m_Post.m_Expression})"); ProcessImplementationNode(implementation, vectorDecls, forLoop.m_Action, depth); break; case Block block: stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}{{"); foreach (NSSNode childNode in block.m_Nodes) { ProcessImplementationNode(implementation, vectorDecls, childNode, depth + 1); } stringBuilder.AppendLine($"{Output_CSharp.GetIndent(depth)}}}"); break; } }
public int GetFromCU(CompilationUnit cu, string className, out string data) { stringBuilder.Clear(); pluginNameVar = null; stringBuilder.AppendLine("using static NWN.Core.NWScript;"); stringBuilder.AppendLine(); stringBuilder.AppendLine("namespace NWN.Core.NWNX"); stringBuilder.AppendLine("{"); int attributePos = stringBuilder.Length; stringBuilder.AppendLine(); stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}public class {className}"); stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}{{"); HashSet <FunctionImplementation> implementedMethods = new HashSet <FunctionImplementation>(); for (int index = 0; index < cu.m_Nodes.Count; index++) { NSSNode node = cu.m_Nodes[index]; if (node is LineComment lineComment) { string xmlEscapedComment = lineComment.Comment .Replace("&", "&") .Replace("\"", """) .Replace("'", "'") .Replace("<", "<") .Replace(">", ">") .Replace("/ @}", " @}"); if (xmlEscapedComment.Contains("@param")) { string paramName = xmlEscapedComment.Split(' ')[2]; stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}//{xmlEscapedComment.Replace($"@param {paramName} ", $"<param name=\"{paramName}\">").Replace($"@param {paramName}", $"<param name=\"{paramName}\">")}</param>"); } else if (xmlEscapedComment.Contains("@return")) { stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}//{xmlEscapedComment.Replace("@return ", $"<returns>").Replace("@return", $"<returns>")}</returns>"); } else { stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}//" + xmlEscapedComment.Replace("@brief ", "")); } } if (node is BlockComment blockComment) { stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}/*"); foreach (string line in blockComment.CommentLines) { stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}" + line); } stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}*/"); } if (node is LvalueDeclSingleWithAssignment lvalueDecl) { // First entry is always the plugin name. if (pluginNameVar == null) { if (lvalueDecl.m_Type.GetType() != typeof(StringType)) { data = null; return(-1); } pluginNameVar = lvalueDecl.m_Lvalue.Identifier; } string type = lvalueDecl.m_Type.Declaration; string name = lvalueDecl.m_Lvalue.Identifier; string value = lvalueDecl.m_Expression.m_Expression; stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}public const {type} {name} = {value}{(lvalueDecl.m_Type.GetType() == typeof(FloatType) && !value.EndsWith("f") ? "f" : "")};"); if (cu.m_Nodes.Count > index + 2 && !(cu.m_Nodes[index + 1] is LvalueDeclSingleWithAssignment)) { stringBuilder.AppendLine(); } } if (pluginNameVar == null) { continue; } if (node is FunctionDeclaration funcDecl) { FunctionImplementation funcImpl = GetFunction(cu, funcDecl); if (implementedMethods.Contains(funcImpl)) { continue; } BuildMethod(funcImpl); implementedMethods.Add(funcImpl); } if (node is FunctionImplementation func) { if (implementedMethods.Contains(func)) { continue; } BuildMethod(func); implementedMethods.Add(func); } } stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}}}"); // Structures foreach (StructDeclaration structDeclaration in cu.m_Nodes.OfType <StructDeclaration>()) { stringBuilder.AppendLine(); stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}public struct {VMTranslations.RemovePrefixes(pluginNameVar, structDeclaration.m_Name.Identifier)}"); stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}{{"); foreach (LvalueDeclSingle dec in structDeclaration.m_Members.OfType <LvalueDeclSingle>()) { string type = dec.m_Type.Declaration; string name = dec.m_Lvalue.Identifier; stringBuilder.AppendLine($"{Output_CSharp.GetIndent(2)}public {type} {name};"); } stringBuilder.AppendLine($"{Output_CSharp.GetIndent(1)}}}"); } stringBuilder.Append("}"); stringBuilder.AppendLine(); if (pluginNameVar == null) { data = null; return(-1); } stringBuilder.Insert(attributePos, $"{Output_CSharp.GetIndent(1)}[NWNXPlugin({pluginNameVar})]"); data = stringBuilder.ToString(); return(0); }