2025-07-29 14:25:31 +08:00
|
|
|
|
using Serein.Library.Utils;
|
|
|
|
|
|
using Serein.Script.Node;
|
2025-07-23 15:57:57 +08:00
|
|
|
|
using Serein.Script.Node.FlowControl;
|
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
|
|
namespace Serein.Script
|
|
|
|
|
|
{
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 将 Serein 脚本转换为 C# 脚本的类
|
|
|
|
|
|
/// </summary>
|
2025-07-26 19:36:54 +08:00
|
|
|
|
public class SereinScriptToCsharpScript
|
2025-07-23 15:57:57 +08:00
|
|
|
|
{
|
2025-07-26 19:36:54 +08:00
|
|
|
|
public const string ClassName = nameof(SereinScriptToCsharpScript);
|
|
|
|
|
|
|
2025-07-31 15:45:02 +08:00
|
|
|
|
public SereinScriptMethodInfo sereinScriptMethodInfo;
|
2025-07-26 19:36:54 +08:00
|
|
|
|
|
2025-07-23 15:57:57 +08:00
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 符号表
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private readonly Dictionary<ASTNode, Type> _symbolInfos;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 记录方法节点是否需要异步调用
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private readonly Dictionary<ASTNode, bool> _asyncMethods;
|
|
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
|
/// 临时变量表
|
|
|
|
|
|
/// </summary>
|
|
|
|
|
|
private readonly Dictionary<string, Type> _local = [];
|
|
|
|
|
|
|
|
|
|
|
|
private bool _isTaskMain = false;
|
|
|
|
|
|
|
|
|
|
|
|
public SereinScriptToCsharpScript(SereinScriptTypeAnalysis analysis)
|
|
|
|
|
|
{
|
|
|
|
|
|
_symbolInfos = analysis.NodeSymbolInfos;
|
|
|
|
|
|
_asyncMethods = analysis.AsyncMethods;
|
|
|
|
|
|
_isTaskMain = _asyncMethods.Any(kvp => kvp.Value);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private readonly StringBuilder _codeBuilder = new StringBuilder();
|
|
|
|
|
|
private int _indentLevel = 0;
|
|
|
|
|
|
|
|
|
|
|
|
private void AppendLine(string code)
|
|
|
|
|
|
{
|
|
|
|
|
|
_codeBuilder.AppendLine(new string(' ', _indentLevel * 4) + code);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void Append(string code)
|
|
|
|
|
|
{
|
|
|
|
|
|
_codeBuilder.Append(code);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-31 15:45:02 +08:00
|
|
|
|
private void CompleteCurrentStatement()
|
|
|
|
|
|
{
|
|
|
|
|
|
_codeBuilder.Append($";{Environment.NewLine}");
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
private string Tab => new string (' ', _indentLevel* 4);
|
|
|
|
|
|
|
2025-07-23 15:57:57 +08:00
|
|
|
|
private void Indent() => _indentLevel++;
|
|
|
|
|
|
private void Unindent() => _indentLevel--;
|
|
|
|
|
|
|
|
|
|
|
|
private List<Action<StringBuilder>> _classDefinitions = new List<Action<StringBuilder>>();
|
|
|
|
|
|
|
2025-07-26 19:36:54 +08:00
|
|
|
|
public SereinScriptMethodInfo CompileToCSharp(string mehtodName, ProgramNode programNode, Dictionary<string, Type>? param)
|
2025-07-23 15:57:57 +08:00
|
|
|
|
{
|
|
|
|
|
|
_codeBuilder.Clear();
|
2025-07-26 19:36:54 +08:00
|
|
|
|
sereinScriptMethodInfo = new SereinScriptMethodInfo()
|
|
|
|
|
|
{
|
|
|
|
|
|
ClassName = ClassName,
|
|
|
|
|
|
ParamInfos = new List<SereinScriptMethodInfo.SereinScriptParamInfo>(),
|
|
|
|
|
|
MethodName = mehtodName,
|
|
|
|
|
|
};
|
2025-07-23 15:57:57 +08:00
|
|
|
|
var sb = _codeBuilder;
|
|
|
|
|
|
var methodResultType = _symbolInfos[programNode];
|
2025-07-31 15:45:02 +08:00
|
|
|
|
if (methodResultType == typeof(void))
|
2025-07-23 15:57:57 +08:00
|
|
|
|
{
|
|
|
|
|
|
methodResultType = typeof(object);
|
|
|
|
|
|
}
|
2025-07-26 19:36:54 +08:00
|
|
|
|
var taskFullName = typeof(Task).FullName;
|
|
|
|
|
|
string? returnContent;
|
|
|
|
|
|
if (_isTaskMain)
|
|
|
|
|
|
{
|
|
|
|
|
|
returnContent = $"global::{taskFullName}<global::{methodResultType.FullName}>";
|
|
|
|
|
|
sereinScriptMethodInfo.IsAsync = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
returnContent = $"global::{methodResultType.FullName}";
|
|
|
|
|
|
sereinScriptMethodInfo.IsAsync = false;
|
|
|
|
|
|
}
|
2025-07-23 15:57:57 +08:00
|
|
|
|
|
2025-07-26 19:36:54 +08:00
|
|
|
|
AppendLine($"public partial class {ClassName}");
|
2025-07-31 15:45:02 +08:00
|
|
|
|
AppendLine("{");
|
2025-07-23 15:57:57 +08:00
|
|
|
|
Indent();
|
2025-07-31 15:45:02 +08:00
|
|
|
|
if (param is null || param.Count == 0)
|
2025-07-23 15:57:57 +08:00
|
|
|
|
{
|
2025-07-29 14:25:31 +08:00
|
|
|
|
// 生成方法签名
|
2025-07-23 15:57:57 +08:00
|
|
|
|
AppendLine($"public static {returnContent} {mehtodName}()");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-07-29 14:25:31 +08:00
|
|
|
|
// 生成方法签名
|
2025-07-23 15:57:57 +08:00
|
|
|
|
AppendLine($"public static {returnContent} {mehtodName}({GetMethodParamster(param)})");
|
|
|
|
|
|
}
|
2025-07-31 15:45:02 +08:00
|
|
|
|
AppendLine("{");
|
2025-07-23 15:57:57 +08:00
|
|
|
|
Indent();
|
2025-07-29 14:25:31 +08:00
|
|
|
|
// 生成变量节点
|
|
|
|
|
|
var idfNodesTemp = _symbolInfos.Keys.Where(key => key is IdentifierNode)
|
2025-07-31 15:45:02 +08:00
|
|
|
|
.OfType<IdentifierNode>().ToList();
|
2025-07-29 14:25:31 +08:00
|
|
|
|
var idfNodes = (param is null) switch
|
2025-07-23 15:57:57 +08:00
|
|
|
|
{
|
2025-07-29 14:25:31 +08:00
|
|
|
|
true => idfNodesTemp.DistinctBy(n => n.Name).ToList(),
|
2025-07-31 15:45:02 +08:00
|
|
|
|
false => idfNodesTemp.DistinctBy(n => n.Name).DistinctByCondition(n => !param.ContainsKey(n.Name)).ToList(),
|
2025-07-29 14:25:31 +08:00
|
|
|
|
};
|
|
|
|
|
|
foreach (var idf in idfNodes)
|
|
|
|
|
|
{
|
|
|
|
|
|
var varName = idf.Name;
|
|
|
|
|
|
var varType = _symbolInfos[idf];
|
|
|
|
|
|
AppendLine($"global::{varType.FullName} {varName} = default; // 变量");
|
2025-07-23 15:57:57 +08:00
|
|
|
|
}
|
2025-07-29 14:25:31 +08:00
|
|
|
|
AppendLine("");
|
2025-07-26 19:36:54 +08:00
|
|
|
|
|
2025-07-29 14:25:31 +08:00
|
|
|
|
// 递归遍历节点生成代码
|
2025-07-31 15:45:02 +08:00
|
|
|
|
foreach (var stmt in programNode.Statements)
|
2025-07-29 14:25:31 +08:00
|
|
|
|
{
|
|
|
|
|
|
ConvertCode(stmt);
|
2025-07-31 15:45:02 +08:00
|
|
|
|
if (stmt is not (IfNode or WhileNode))
|
|
|
|
|
|
{
|
|
|
|
|
|
CompleteCurrentStatement();
|
|
|
|
|
|
}
|
2025-07-29 14:25:31 +08:00
|
|
|
|
}
|
2025-07-26 19:36:54 +08:00
|
|
|
|
if (_symbolInfos[programNode] == typeof(void))
|
2025-07-23 15:57:57 +08:00
|
|
|
|
{
|
2025-07-26 19:36:54 +08:00
|
|
|
|
AppendLine("");
|
2025-07-23 15:57:57 +08:00
|
|
|
|
AppendLine("return null;");
|
|
|
|
|
|
}
|
2025-07-26 19:36:54 +08:00
|
|
|
|
|
2025-07-23 15:57:57 +08:00
|
|
|
|
Unindent();
|
|
|
|
|
|
AppendLine("}");
|
|
|
|
|
|
Unindent();
|
|
|
|
|
|
AppendLine("}");
|
|
|
|
|
|
|
|
|
|
|
|
foreach (var cd in _classDefinitions)
|
|
|
|
|
|
{
|
|
|
|
|
|
cd.Invoke(sb);
|
|
|
|
|
|
}
|
2025-07-26 19:36:54 +08:00
|
|
|
|
sereinScriptMethodInfo.CsharpCode = sb.ToString();
|
|
|
|
|
|
sereinScriptMethodInfo.ReturnType = methodResultType;
|
|
|
|
|
|
return sereinScriptMethodInfo;
|
2025-07-23 15:57:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private string GetMethodParamster(Dictionary<string, Type> param)
|
|
|
|
|
|
{
|
|
|
|
|
|
var values = param.Select(kvp =>
|
|
|
|
|
|
{
|
2025-07-26 19:36:54 +08:00
|
|
|
|
var paramName = kvp.Key;
|
|
|
|
|
|
var type = kvp.Value;
|
|
|
|
|
|
_local[paramName] = type;
|
|
|
|
|
|
sereinScriptMethodInfo.ParamInfos.Add(new SereinScriptMethodInfo.SereinScriptParamInfo
|
|
|
|
|
|
{
|
|
|
|
|
|
ParameterType = type,
|
|
|
|
|
|
ParamName = paramName,
|
|
|
|
|
|
});
|
|
|
|
|
|
return $"global::{type.FullName} {paramName}";
|
2025-07-23 15:57:57 +08:00
|
|
|
|
});
|
|
|
|
|
|
return string.Join(',', values);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-31 15:45:02 +08:00
|
|
|
|
private void ConvertCode(ASTNode node)
|
2025-07-23 15:57:57 +08:00
|
|
|
|
{
|
|
|
|
|
|
switch (node)
|
|
|
|
|
|
{
|
|
|
|
|
|
case ProgramNode programNode: // 程序开始节点
|
|
|
|
|
|
break;
|
|
|
|
|
|
case ReturnNode returnNode: // 程序退出节点
|
|
|
|
|
|
void ConvertCodeOfReturnNode(ReturnNode returnNode)
|
|
|
|
|
|
{
|
2025-07-31 15:45:02 +08:00
|
|
|
|
|
|
|
|
|
|
Append(Tab);
|
2025-07-23 15:57:57 +08:00
|
|
|
|
if (returnNode.Value is not null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Append($"return ");
|
|
|
|
|
|
ConvertCode(returnNode.Value);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
2025-07-31 15:45:02 +08:00
|
|
|
|
AppendLine("return defult");
|
2025-07-23 15:57:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
ConvertCodeOfReturnNode(returnNode);
|
|
|
|
|
|
break;
|
|
|
|
|
|
#region 字面量解析
|
|
|
|
|
|
case NullNode nullNode: // null
|
|
|
|
|
|
Append("null");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CharNode charNode: // char字面量
|
|
|
|
|
|
Append($"'{charNode.Value}'");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case StringNode stringNode: // 字符串字面量
|
|
|
|
|
|
Append($"\"{stringNode.Value}\"");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case BooleanNode booleanNode: // 布尔值字面量
|
|
|
|
|
|
Append($"{(booleanNode.Value ? "true" : "false")}");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NumberIntNode numberIntNode: // int整型数值字面量
|
|
|
|
|
|
Append($"{numberIntNode.Value}");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NumberLongNode numberLongNode: // long整型数值字面量
|
|
|
|
|
|
Append($"{numberLongNode.Value}");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NumberFloatNode numberFloatNode: // float浮点数值字面量
|
|
|
|
|
|
Append($"{numberFloatNode.Value}f");
|
|
|
|
|
|
break;
|
|
|
|
|
|
case NumberDoubleNode numberDoubleNode: // double浮点数值字面量
|
|
|
|
|
|
Append($"{numberDoubleNode.Value}d");
|
2025-07-31 15:45:02 +08:00
|
|
|
|
break;
|
2025-07-23 15:57:57 +08:00
|
|
|
|
#endregion
|
|
|
|
|
|
case IdentifierNode identifierNode: // 变量定义
|
|
|
|
|
|
void ConvertCodeOfIdentifierNode(IdentifierNode identifierNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
var varName = identifierNode.Name;
|
2025-07-29 14:25:31 +08:00
|
|
|
|
Append(varName);
|
2025-07-23 15:57:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
ConvertCodeOfIdentifierNode(identifierNode);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case IfNode ifNode: // if语句结构
|
|
|
|
|
|
void ConvertCodeOfIfNode(IfNode ifNOde)
|
|
|
|
|
|
{
|
2025-07-31 15:45:02 +08:00
|
|
|
|
|
|
|
|
|
|
Append($"{Tab}if(");
|
2025-07-23 15:57:57 +08:00
|
|
|
|
ConvertCode(ifNOde.Condition); // 解析条件
|
2025-07-31 15:45:02 +08:00
|
|
|
|
Append($" == true){Environment.NewLine}");
|
2025-07-23 15:57:57 +08:00
|
|
|
|
AppendLine("{");
|
|
|
|
|
|
Indent();
|
2025-07-31 15:45:02 +08:00
|
|
|
|
foreach (var item in ifNOde.TrueBranch)
|
2025-07-23 15:57:57 +08:00
|
|
|
|
{
|
|
|
|
|
|
ConvertCode(item);
|
2025-07-31 15:45:02 +08:00
|
|
|
|
CompleteCurrentStatement();
|
|
|
|
|
|
}
|
2025-07-23 15:57:57 +08:00
|
|
|
|
Unindent();
|
|
|
|
|
|
AppendLine("}");
|
|
|
|
|
|
AppendLine("else");
|
|
|
|
|
|
AppendLine("{");
|
|
|
|
|
|
Indent();
|
2025-07-29 14:25:31 +08:00
|
|
|
|
foreach (var item in ifNOde.FalseBranch)
|
2025-07-23 15:57:57 +08:00
|
|
|
|
{
|
|
|
|
|
|
ConvertCode(item);
|
2025-07-31 15:45:02 +08:00
|
|
|
|
CompleteCurrentStatement();
|
2025-07-23 15:57:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
Unindent();
|
|
|
|
|
|
AppendLine("}");
|
|
|
|
|
|
}
|
|
|
|
|
|
ConvertCodeOfIfNode(ifNode);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case WhileNode whileNode: // while语句结构
|
|
|
|
|
|
void ConvertCodeOfWhileNode(WhileNode whileNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
AppendLine("");
|
|
|
|
|
|
Append($"while(");
|
|
|
|
|
|
ConvertCode(whileNode.Condition); // 解析条件
|
|
|
|
|
|
Append($" == {true})");
|
|
|
|
|
|
AppendLine("{");
|
|
|
|
|
|
Indent();
|
|
|
|
|
|
foreach (var item in whileNode.Body)
|
|
|
|
|
|
{
|
|
|
|
|
|
ConvertCode(item);
|
2025-07-31 15:45:02 +08:00
|
|
|
|
CompleteCurrentStatement();
|
2025-07-23 15:57:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
Unindent();
|
|
|
|
|
|
AppendLine("}");
|
|
|
|
|
|
}
|
|
|
|
|
|
ConvertCodeOfWhileNode(whileNode);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case AssignmentNode assignmentNode: // 变量赋值语句
|
|
|
|
|
|
void ConvertCodeOfAssignmentNode(AssignmentNode assignmentNode)
|
|
|
|
|
|
{
|
2025-07-31 15:45:02 +08:00
|
|
|
|
|
|
|
|
|
|
Append(Tab);
|
2025-07-23 15:57:57 +08:00
|
|
|
|
ConvertCode(assignmentNode.Target);
|
|
|
|
|
|
Append(" = ");
|
|
|
|
|
|
if (assignmentNode.Value is null)
|
|
|
|
|
|
{
|
|
|
|
|
|
Append("null");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ConvertCode(assignmentNode.Value);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
ConvertCodeOfAssignmentNode(assignmentNode);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case BinaryOperationNode binaryOperationNode: // 二元运算操作
|
|
|
|
|
|
void ConvertCodeOfBinaryOperationNode(BinaryOperationNode binaryOperationNode)
|
|
|
|
|
|
{
|
2025-07-31 15:45:02 +08:00
|
|
|
|
Append("(");
|
2025-07-23 15:57:57 +08:00
|
|
|
|
ConvertCode(binaryOperationNode.Left); // 左操作数
|
|
|
|
|
|
Append(binaryOperationNode.Operator); // 操作符
|
|
|
|
|
|
ConvertCode(binaryOperationNode.Right); // 左操作数
|
2025-07-31 15:45:02 +08:00
|
|
|
|
Append(")");
|
2025-07-23 15:57:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
ConvertCodeOfBinaryOperationNode(binaryOperationNode);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CollectionAssignmentNode collectionAssignmentNode:
|
|
|
|
|
|
void ConvertCodeOfCollectionAssignmentNode(CollectionAssignmentNode collectionAssignmentNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
ConvertCode(collectionAssignmentNode.Collection);
|
|
|
|
|
|
Append(" = ");
|
|
|
|
|
|
ConvertCode(collectionAssignmentNode.Value);
|
|
|
|
|
|
AppendLine(string.Empty);
|
|
|
|
|
|
}
|
|
|
|
|
|
ConvertCodeOfCollectionAssignmentNode(collectionAssignmentNode);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CollectionIndexNode collectionIndexNode: // 集合类型操作
|
|
|
|
|
|
void ConvertCodeOfCollectionIndexNode(CollectionIndexNode collectionIndexNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
ConvertCode(collectionIndexNode.Collection);
|
|
|
|
|
|
Append("[");
|
|
|
|
|
|
ConvertCode(collectionIndexNode.Index);
|
|
|
|
|
|
Append("]");
|
|
|
|
|
|
}
|
|
|
|
|
|
ConvertCodeOfCollectionIndexNode(collectionIndexNode);
|
|
|
|
|
|
break;
|
2025-07-31 15:45:02 +08:00
|
|
|
|
case ArrayDefintionNode arrayDefintionNode:
|
|
|
|
|
|
void ConvertCodeOfArrayDefintionNode(ArrayDefintionNode arrayDefintionNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
var arrType = this._symbolInfos[arrayDefintionNode];
|
|
|
|
|
|
var tab = new string(' ', (_indentLevel + 1) * 4);
|
|
|
|
|
|
Append($"new global::{arrType.FullName}{{{Environment.NewLine}");
|
|
|
|
|
|
for (int index = 0; index < arrayDefintionNode.Elements.Count; index++)
|
|
|
|
|
|
{
|
|
|
|
|
|
ASTNode? e = arrayDefintionNode.Elements[index];
|
|
|
|
|
|
Append(tab + " ");
|
|
|
|
|
|
ConvertCode(e);
|
|
|
|
|
|
if (index < arrayDefintionNode.Elements.Count - 1)
|
|
|
|
|
|
Append($", {Environment.NewLine}");
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
Append($"{Environment.NewLine}{tab}}}");
|
|
|
|
|
|
}
|
|
|
|
|
|
ConvertCodeOfArrayDefintionNode(arrayDefintionNode);
|
|
|
|
|
|
break;
|
2025-07-23 15:57:57 +08:00
|
|
|
|
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
|
|
|
|
|
|
void ConvertCodeOfClassTypeDefinitionNode(ClassTypeDefinitionNode classTypeDefinitionNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
_classDefinitions.Add((sb) =>
|
|
|
|
|
|
{
|
|
|
|
|
|
var type = _symbolInfos[classTypeDefinitionNode.ClassType];
|
|
|
|
|
|
AppendLine($"public class {type.FullName}");
|
|
|
|
|
|
AppendLine("{");
|
|
|
|
|
|
Indent();
|
|
|
|
|
|
foreach (var property in classTypeDefinitionNode.Propertys)
|
|
|
|
|
|
{
|
|
|
|
|
|
var propertyName = property.Key;
|
|
|
|
|
|
var propertyType = _symbolInfos[property.Value];
|
|
|
|
|
|
AppendLine($"public global::{propertyType.FullName} {propertyName} {{ get; set; }}");
|
|
|
|
|
|
}
|
|
|
|
|
|
Unindent();
|
|
|
|
|
|
AppendLine("}");
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
ConvertCodeOfClassTypeDefinitionNode(classTypeDefinitionNode);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case TypeNode typeNode: // 类型
|
|
|
|
|
|
break;
|
|
|
|
|
|
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
|
|
|
|
|
|
void ConvertCodeOfObjectInstantiationNode(ObjectInstantiationNode objectInstantiationNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
var type = _symbolInfos[objectInstantiationNode.Type];
|
|
|
|
|
|
Append($"new global::{type}");
|
|
|
|
|
|
if (objectInstantiationNode.Arguments.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
Append("(");
|
|
|
|
|
|
for (int i = 0; i < objectInstantiationNode.Arguments.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
ConvertCode(objectInstantiationNode.Arguments[i]);
|
|
|
|
|
|
if (i < objectInstantiationNode.Arguments.Count - 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
Append(", ");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Append(")");
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
Append("()");
|
|
|
|
|
|
}
|
|
|
|
|
|
if (objectInstantiationNode.CtorAssignments.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
AppendLine("{");
|
|
|
|
|
|
Indent();
|
|
|
|
|
|
foreach (var assignment in objectInstantiationNode.CtorAssignments)
|
|
|
|
|
|
{
|
|
|
|
|
|
ConvertCode(assignment);
|
|
|
|
|
|
}
|
|
|
|
|
|
Unindent();
|
|
|
|
|
|
AppendLine("}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
ConvertCodeOfObjectInstantiationNode(objectInstantiationNode);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case CtorAssignmentNode ctorAssignmentNode: // 构造器赋值
|
|
|
|
|
|
void ConvertCodeOfCtorAssignmentNode(CtorAssignmentNode ctorAssignmentNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
var propertyName = ctorAssignmentNode.MemberName;
|
|
|
|
|
|
var value = ctorAssignmentNode.Value;
|
|
|
|
|
|
Append($"{propertyName} = ");
|
|
|
|
|
|
ConvertCode(value);
|
|
|
|
|
|
AppendLine(",");
|
|
|
|
|
|
}
|
|
|
|
|
|
ConvertCodeOfCtorAssignmentNode(ctorAssignmentNode);
|
|
|
|
|
|
break;
|
|
|
|
|
|
case MemberAccessNode memberAccessNode: // 对象成员访问
|
|
|
|
|
|
void ConvertCodeOfMemberAccessNode(MemberAccessNode memberAccessNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
ConvertCode(memberAccessNode.Object);
|
|
|
|
|
|
Append($".{memberAccessNode.MemberName}");
|
|
|
|
|
|
}
|
2025-07-31 15:45:02 +08:00
|
|
|
|
ConvertCodeOfMemberAccessNode(memberAccessNode);
|
2025-07-23 15:57:57 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case MemberAssignmentNode memberAssignmentNode: // 对象成员赋值
|
|
|
|
|
|
void ConvertCodeOfMemberAssignmentNode(MemberAssignmentNode memberAssignmentNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
ConvertCode(memberAssignmentNode.Object);
|
|
|
|
|
|
Append($".{memberAssignmentNode.MemberName} = ");
|
|
|
|
|
|
ConvertCode(memberAssignmentNode.Value);
|
|
|
|
|
|
}
|
2025-07-31 15:45:02 +08:00
|
|
|
|
ConvertCodeOfMemberAssignmentNode(memberAssignmentNode);
|
2025-07-23 15:57:57 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
|
|
|
|
|
|
void ConvertCodeOfMemberFunctionCallNode(MemberFunctionCallNode memberFunctionCallNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
var isAsync = _asyncMethods.TryGetValue(memberFunctionCallNode, out var isAsyncValue) && isAsyncValue;
|
|
|
|
|
|
if (isAsync)
|
|
|
|
|
|
{
|
|
|
|
|
|
Append($"(await ");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ConvertCode(memberFunctionCallNode.Object);
|
|
|
|
|
|
Append($".{memberFunctionCallNode.FunctionName}(");
|
|
|
|
|
|
for (int i = 0; i < memberFunctionCallNode.Arguments.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
ASTNode? argNode = memberFunctionCallNode.Arguments[i];
|
|
|
|
|
|
ConvertCode(argNode);
|
|
|
|
|
|
if (i < memberFunctionCallNode.Arguments.Count - 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
Append(", ");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Append($")");
|
|
|
|
|
|
if (isAsync)
|
|
|
|
|
|
{
|
|
|
|
|
|
Append($")");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
2025-07-31 15:45:02 +08:00
|
|
|
|
ConvertCodeOfMemberFunctionCallNode(memberFunctionCallNode);
|
2025-07-23 15:57:57 +08:00
|
|
|
|
break;
|
|
|
|
|
|
case FunctionCallNode functionCallNode: // 外部挂载的函数调用
|
|
|
|
|
|
void ConvertCodeOfFunctionCallNode(FunctionCallNode functionCallNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
var isAsync = _asyncMethods.TryGetValue(functionCallNode, out var isAsyncValue) && isAsyncValue;
|
|
|
|
|
|
if (isAsync)
|
|
|
|
|
|
{
|
|
|
|
|
|
Append($"(await ");
|
|
|
|
|
|
}
|
|
|
|
|
|
var funcName = functionCallNode.FunctionName switch
|
|
|
|
|
|
{
|
2025-07-31 15:45:02 +08:00
|
|
|
|
"int" => "@int",
|
|
|
|
|
|
"bool" => "@bool",
|
|
|
|
|
|
"double" => "@double",
|
|
|
|
|
|
"long" => "@long",
|
|
|
|
|
|
"decimal" => "@decimal",
|
|
|
|
|
|
"float" => "@float",
|
|
|
|
|
|
"byte" => "@byte",
|
2025-07-23 15:57:57 +08:00
|
|
|
|
|
|
|
|
|
|
_ => functionCallNode.FunctionName,
|
|
|
|
|
|
};
|
|
|
|
|
|
Append($"global::Serein.Library.ScriptBaseFunc.{funcName}(");
|
|
|
|
|
|
for (int i = 0; i < functionCallNode.Arguments.Count; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
ASTNode? argNode = functionCallNode.Arguments[i];
|
|
|
|
|
|
ConvertCode(argNode);
|
|
|
|
|
|
if (i < functionCallNode.Arguments.Count - 1)
|
|
|
|
|
|
{
|
|
|
|
|
|
Append(", ");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Append($")");
|
|
|
|
|
|
if (isAsync)
|
|
|
|
|
|
{
|
|
|
|
|
|
Append($")");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
ConvertCodeOfFunctionCallNode(functionCallNode);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default: // 未定义的节点类型
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-07-31 15:45:02 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-07-23 15:57:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|