修复了脚本语言中构造器赋值的 bug

This commit is contained in:
fengjiayi
2025-07-16 16:16:19 +08:00
parent 01ab905155
commit 88a82046b8
16 changed files with 825 additions and 1376 deletions

View File

@@ -15,41 +15,40 @@ namespace Serein.Script.Node
public bool IsOverlay { get; set; }
/// <summary>
/// 类名称
/// 类名称
/// </summary>
public string ClassName { get; }
public TypeNode ClassType { get; }
/// <summary>
/// 字段名称及字段类型
/// 类型中的属性
/// </summary>
[Obsolete("此属性已经过时,将会改为Dictionary<string, string>", false)]
public Dictionary<string, Type> Fields { get; }
/// <summary>
/// 字段名称及字段类型(Kvp[fididName:fidleTypeName])
/// </summary>
public Dictionary<string, string> FieldInfos { get; }
public Dictionary<string, TypeNode> Propertys { get; }
public ClassTypeDefinitionNode(Dictionary<string, string> fields, string className)
public ClassTypeDefinitionNode(Dictionary<string, TypeNode> propertys, TypeNode className)
{
this.FieldInfos = fields;
this.ClassName = className;
this.Propertys = propertys;
this.ClassType = className;
}
[Obsolete("此构造方法已经过时,可能在下一个版本中移除", false)]
public ClassTypeDefinitionNode(Dictionary<string, Type> fields, string className)
{
this.Fields = fields;
this.ClassName = className;
}
[Obsolete("此构造方法已经过时,可能在下一个版本中移除", false)]
public ClassTypeDefinitionNode(Dictionary<string, Type> fields, string className, bool isOverlay)
{
this.Fields = fields;
this.ClassName = className;
IsOverlay = isOverlay;
}
/* /// <summary>
/// 字段名称及字段类型
/// </summary>
[Obsolete("此属性已经过时将会改为Dictionary<string, string>", false)]
public Dictionary<TypeNode, Type> Fields { get; }
*/
/* /// <summary>
/// 字段名称及字段类型(Kvp[fididName:fidleTypeName])
/// </summary>
public Dictionary<TypeNode, string> FieldInfos { get; }
*/
//[Obsolete("此构造方法已经过时,可能在下一个版本中移除", false)]
}
}

View File

@@ -0,0 +1,46 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.Script.Node
{
/// <summary>
/// 构造器对对象成员赋值
/// </summary>
public class CtorAssignmentNode : ASTNode
{
/// <summary>
/// 成员来源类型
/// </summary>
public TypeNode Class { get; }
/// <summary>
/// 成员名称
/// </summary>
public string MemberName { get; }
/// <summary>
/// 值来源
/// </summary>
public ASTNode Value { get; }
/// <summary>
/// 构造器赋值
/// </summary>
/// <param name="typeNode">成员来源类型</param>
/// <param name="memberName">成员名称</param>
/// <param name="value">成员值来源</param>
public CtorAssignmentNode(TypeNode typeNode, string memberName, ASTNode value)
{
Class = typeNode;
MemberName = memberName;
Value = value;
}
}
}

View File

@@ -12,19 +12,31 @@ namespace Serein.Script.Node
public class ObjectInstantiationNode : ASTNode
{
/// <summary>
/// 类型名称
/// 类型来源
/// </summary>
public string TypeName { get; }
public TypeNode Type { get; }
/// <summary>
/// 构造方法的参数来源
/// </summary>
public List<ASTNode> Arguments { get; }
public ObjectInstantiationNode(string typeName, List<ASTNode> arguments)
/// <summary>
/// 构造器赋值
/// </summary>
public List<CtorAssignmentNode> CtorAssignments { get; private set; } = [];
public ObjectInstantiationNode(TypeNode type, List<ASTNode> arguments)
{
this.TypeName = typeName;
this.Type = type;
this.Arguments = arguments;
}
public ObjectInstantiationNode SetCtorAssignments(List<CtorAssignmentNode> ctorAssignments)
{
CtorAssignments = ctorAssignments;
return this;
}
}
}

View File

@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Serein.Script.Node
{
/// <summary>
/// 类型节点
/// </summary>
public class TypeNode : ASTNode
{
public string TypeName { get; }
public TypeNode(string typeName)
{
TypeName = typeName;
}
}
}

View File

@@ -0,0 +1,131 @@
using Serein.Library;
using Serein.Script.Node;
using Serein.Script.Node.FlowControl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace Serein.Script
{
public class SereinScript
{
/// <summary>
/// 类型分析
/// </summary>
public SereinScriptTypeAnalysis TypeAnalysis { get; set; } = new SereinScriptTypeAnalysis();
private ProgramNode? programNode;
public Type ParserScript(Dictionary<string, Type> argTypes, string script)
{
SereinScriptParser parser = new SereinScriptParser();
var programNode = parser.Parse(script);
TypeAnalysis.NodeSymbolInfos.Clear(); // 清空符号表
TypeAnalysis.LoadSymbol(argTypes); // 提前加载脚本节点定义的符号
TypeAnalysis.Analysis(programNode); // 分析节点类型
var returnType = TypeAnalysis.NodeSymbolInfos[programNode]; // 获取返回类型
this.programNode = programNode;
return returnType; // 脚本返回类型
}
public async Task<object?> InterpreterAsync(IScriptInvokeContext context)
{
if(programNode is null)
{
throw new ArgumentNullException(nameof(programNode));
}
Dictionary<ASTNode, Type> symbolInfos = TypeAnalysis.NodeSymbolInfos.ToDictionary();
SereinScriptInterpreter Interpreter = new SereinScriptInterpreter(symbolInfos);
return await Interpreter.InterpretAsync(context, programNode);
}
/// <summary>
/// 挂载的函数
/// </summary>
public static Dictionary<string, DelegateDetails> FunctionDelegates { get; private set; } = [];
/// <summary>
/// 挂载方法的信息
/// </summary>
public static Dictionary<string, MethodInfo> FunctionInfos { get; private set; } = [];
/// <summary>
/// 挂载的类型
/// </summary>
public static Dictionary<string, Type> MountType = new Dictionary<string, Type>();
/// <summary>
/// 挂载的函数调用的对象(用于解决函数需要实例才能调用的场景)
/// </summary>
public static Dictionary<string, Func<object>> DelegateInstances = new Dictionary<string, Func<object>>();
/// <summary>
/// 挂载静态函数
/// </summary>
/// <param name="functionName"></param>
/// <param name="methodInfo"></param>
public static void AddStaticFunction(string functionName, MethodInfo methodInfo)
{
FunctionDelegates[functionName] = new DelegateDetails(methodInfo);
FunctionInfos[functionName] = methodInfo;
}
/// <summary>
/// 挂载函数
/// </summary>
/// <param name="functionName">函数名称</param>
/// <param name="methodInfo">方法信息</param>
public static void AddFunction(string functionName, MethodInfo methodInfo, Func<object>? callObj = null)
{
if (!methodInfo.IsStatic && callObj is null)
{
SereinEnv.WriteLine(InfoType.WARN, "函数挂载失败:试图挂载非静态的函数,但没有传入相应的获取实例的方法。");
return;
}
if (!methodInfo.IsStatic && callObj is not null && !DelegateInstances.ContainsKey(functionName))
{
// 非静态函数需要给定类型
DelegateInstances.Add(functionName, callObj);
}
if (!FunctionDelegates.ContainsKey(functionName))
{
FunctionDelegates[functionName] = new DelegateDetails(methodInfo);
}
}
/// <summary>
/// 挂载类型
/// </summary>
/// <param name="typeName">函数名称</param>
/// <param name="typeName">指定类型名称</param>
public static void AddClassType(Type type, string typeName = "")
{
if (string.IsNullOrEmpty(typeName))
{
typeName = type.Name;
}
if (!MountType.ContainsKey(typeName))
{
MountType[typeName] = type;
}
}
}
}

View File

@@ -18,98 +18,15 @@ namespace Serein.Script
/// </summary>
public class SereinScriptInterpreter
{
/// <summary>
/// 挂载的函数
/// </summary>
private static Dictionary<string, DelegateDetails> _functionTable = new Dictionary<string, DelegateDetails>();
private static Dictionary<string, MethodInfo> _functionInfoTable = new Dictionary<string, MethodInfo>();
private readonly Dictionary<ASTNode, Type> symbolInfos;
public static Dictionary<string, MethodInfo> FunctionInfoTable { get { return _functionInfoTable; } }
/// <summary>
/// 挂载的函数调用的对象(用于函数需要实例才能调用的场景)
/// </summary>
private Dictionary<string, Func<object>> _callFuncOfGetObjects = new Dictionary<string, Func<object>>();
/// <summary>
/// 定义的类型
/// </summary>
private Dictionary<string, Type> _classDefinition = new Dictionary<string, Type>();
/// <summary>
/// 类型分析器
/// </summary>
private SereinScriptTypeAnalysis typeAnalysis;
/// <summary>
/// 挂载静态函数
/// </summary>
/// <param name="functionName"></param>
/// <param name="methodInfo"></param>
public static void AddStaticFunction(string functionName, MethodInfo methodInfo)
public SereinScriptInterpreter(Dictionary<ASTNode, Type> symbolInfos)
{
_functionTable[functionName] = new DelegateDetails(methodInfo);
_functionInfoTable[functionName] = methodInfo;
this.symbolInfos = symbolInfos;
}
/// <summary>
/// 挂载函数
/// </summary>
/// <param name="functionName">函数名称</param>
/// <param name="methodInfo">方法信息</param>
public void AddFunction(string functionName, MethodInfo methodInfo, Func<object>? callObj = null)
{
//if (!_functionTable.ContainsKey(functionName))
//{
// _functionTable[functionName] = new DelegateDetails(methodInfo);
//}
if(!methodInfo.IsStatic && callObj is null)
{
SereinEnv.WriteLine(InfoType.WARN, "函数挂载失败:试图挂载非静态的函数,但没有传入相应的获取实例的方法。");
return;
}
if(!methodInfo.IsStatic && callObj is not null && !_callFuncOfGetObjects.ContainsKey(functionName))
{
// 静态函数不需要
_callFuncOfGetObjects.Add(functionName, callObj);
}
if (!_functionTable.ContainsKey(functionName))
{
_functionTable[functionName] = new DelegateDetails(methodInfo);
}
//_functionTable[functionName] = new DelegateDetails(methodInfo);
}
/// <summary>
/// 挂载类型
/// </summary>
/// <param name="typeName">函数名称</param>
/// <param name="type">方法信息</param>
public void AddClassType(Type type , string typeName = "")
{
if (string.IsNullOrEmpty(typeName))
{
typeName = type.Name;
}
if (!_classDefinition.ContainsKey(typeName))
{
_classDefinition[typeName] = type;
}
}
/// <summary>
/// 设置类型分析器
/// </summary>
/// <param name="typeAnalysis"></param>
public void SetTypeAnalysis(SereinScriptTypeAnalysis typeAnalysis)
{
this.typeAnalysis = typeAnalysis;
}
/// <summary>
/// 入口节点
@@ -159,17 +76,19 @@ namespace Serein.Script
/// <returns></returns>
private void ExecutionClassTypeDefinitionNode(ClassTypeDefinitionNode classTypeDefinitionNode)
{
if (_classDefinition.ContainsKey(classTypeDefinitionNode.ClassName) && !classTypeDefinitionNode.IsOverlay)
var className = classTypeDefinitionNode.ClassType.TypeName;
if (SereinScript.MountType.ContainsKey(className) && !classTypeDefinitionNode.IsOverlay)
{
//SereinEnv.WriteLine(InfoType.WARN, $"异常信息 : 类型重复定义,代码在第{classTypeDefinitionNode.Row}行: {classTypeDefinitionNode.Code.Trim()}");
return;
}
//var isOverlay = true; // classTypeDefinitionNode.IsOverlay;
var type = DynamicObjectHelper.CreateTypeWithProperties(classTypeDefinitionNode.Fields, classTypeDefinitionNode.ClassName); // 覆盖
//classTypeDefinitionNode.IsOverlay = false; // 已经加载过,则不再覆盖
_classDefinition[classTypeDefinitionNode.ClassName] = type; // 定义对象
if(DynamicObjectHelper.GetCacheType(className) == null)
{
var propertyTypes = classTypeDefinitionNode.Propertys.ToDictionary(p => p.Key, p => symbolInfos[p.Value]);
var type = DynamicObjectHelper.CreateTypeWithProperties(propertyTypes, className); // 覆盖
SereinScript.MountType[className] = type; // 定义对象
}
}
/// <summary>
@@ -305,11 +224,11 @@ namespace Serein.Script
// 查找并执行对应的函数
if (_functionTable.TryGetValue(funcName, out DelegateDetails? function))
if (SereinScript.FunctionDelegates .TryGetValue(funcName, out DelegateDetails? function))
{
if (!function.EmitMethodInfo.IsStatic)
{
if(_callFuncOfGetObjects.TryGetValue(funcName, out var action))
if(SereinScript.DelegateInstances.TryGetValue(funcName, out var action))
{
instance = action.Invoke();// 非静态的方法需要获取相应的实例
@@ -429,27 +348,34 @@ namespace Serein.Script
//if (right == null) throw new SereinSciptException(binOpNode.Right, "右值尝试使用计算 null");
return EvaluateBinaryOperation(left, binOpNode.Operator, right);
case ObjectInstantiationNode objectInstantiationNode: // 对象实例化
if (_classDefinition.TryGetValue(objectInstantiationNode.TypeName,out var type ))
if (!SereinScript.MountType.TryGetValue(objectInstantiationNode.Type.TypeName, out var type))
{
object?[] args = new object[objectInstantiationNode.Arguments.Count];
for (int i = 0; i < objectInstantiationNode.Arguments.Count; i++)
type = symbolInfos[objectInstantiationNode.Type];
if (type is null)
{
var argNode = objectInstantiationNode.Arguments[i];
args[i] = await EvaluateAsync(context, argNode);
throw new SereinSciptException(objectInstantiationNode, $"使用了未定义的类型\"{objectInstantiationNode.Type.TypeName}\"");
}
var obj = Activator.CreateInstance(type,args: args);// 创建对象
if (obj == null)
{
throw new SereinSciptException(objectInstantiationNode, $"类型创建失败\"{objectInstantiationNode.TypeName}\"");
}
return obj;
}
else
object?[] args = new object[objectInstantiationNode.Arguments.Count];
for (int i = 0; i < objectInstantiationNode.Arguments.Count; i++)
{
throw new SereinSciptException(objectInstantiationNode, $"使用了未定义的类型\"{objectInstantiationNode.TypeName}\"");
var argNode = objectInstantiationNode.Arguments[i];
args[i] = await EvaluateAsync(context, argNode);
}
var obj = Activator.CreateInstance(type, args: args);// 创建对象
if (obj == null)
{
throw new SereinSciptException(objectInstantiationNode, $"类型创建失败\"{objectInstantiationNode.Type.TypeName}\"");
}
for (int i = 0; i < objectInstantiationNode.CtorAssignments.Count; i++)
{
var ctorAssignmentNode = objectInstantiationNode.CtorAssignments[i];
var propertyName = ctorAssignmentNode.MemberName;
var value = await EvaluateAsync(context, ctorAssignmentNode.Value);
SetPropertyValue(obj, propertyName, value);
}
}
return obj;
case FunctionCallNode callNode: // 调用方法
return await InterpretFunctionCallAsync(context, callNode); // 调用方法返回函数的返回值
case MemberFunctionCallNode memberFunctionCallNode: // 对象方法调用
@@ -570,6 +496,48 @@ namespace Serein.Script
}
}
public void SetPropertyValue(object target, string memberName, object? value)
{
var targetType = target?.GetType();
if (targetType is null) return;
var propertyInfo = targetType.GetProperty(memberName);
if (propertyInfo is null)
{
var fieldInfo = target?.GetType().GetRuntimeField(memberName);
if (fieldInfo is null)
{
throw new Exception($"类型 {targetType} 对象没有成员\"{memberName}\"");
}
else
{
var convertedValue = Convert.ChangeType(value, fieldInfo.FieldType);
fieldInfo.SetValue(target, convertedValue);
}
}
else
{
if (value is null)
{
propertyInfo.SetValue(target, null);
return;
}
var valueTtpe = value.GetType();
if (propertyInfo.PropertyType.IsAssignableFrom(valueTtpe))
{
propertyInfo.SetValue(target, value);
}
else if (propertyInfo.PropertyType.FullName == valueTtpe.FullName)
{
propertyInfo.SetValue(target, value);
}
else
{
throw new Exception($"类型 {targetType} 对象成员\"{memberName}\" 赋值时异常");
}
//var convertedValue = Convert.ChangeType(value, );
}
}
/// <summary>
/// 获取对象成员
/// </summary>

View File

@@ -126,6 +126,11 @@ namespace Serein.Script
Type = type;
Value = value;
}
public override string ToString()
{
return $"token in {Row} row, type is \"{Type}\", value is \"{Value}\".";
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Reactive;
using System.Reflection;
using System.Reflection.Emit;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
@@ -26,11 +27,6 @@ namespace Serein.Script
/// </summary>
public Dictionary<ASTNode, Type> NodeSymbolInfos { get; } = new Dictionary<ASTNode, Type>();
public SereinScriptTypeAnalysis()
{
}
public void LoadSymbol(Dictionary<string,Type> identifierNodes)
{
foreach(var kvp in identifierNodes)
@@ -43,7 +39,7 @@ namespace Serein.Script
}
public void AnalysisProgramNode(ProgramNode astNode)
public void Analysis(ProgramNode astNode)
{
//NodeSymbolInfos.Clear();
for (int i = 0; i < astNode.Statements.Count; i++)
@@ -52,8 +48,8 @@ namespace Serein.Script
Analysis(node);
}
var returnNodes = astNode.Statements.Where(node => node is ReturnNode).ToArray();
var returnNodes = NodeSymbolInfos.Keys.Where(node => node is ReturnNode).ToArray();
if (returnNodes.Length == 0)
{
NodeSymbolInfos[astNode] = typeof(void); // 程序无返回值
@@ -66,7 +62,15 @@ namespace Serein.Script
}
else
{
var firstReturnType = NodeSymbolInfos[returnNodes[0]]; // 第一个返回值
foreach(var item in returnNodes)
{
if(NodeSymbolInfos[item] != firstReturnType)
{
throw new Exception("类型检查异常,存在不同分支返回值类型不一致");
}
}
NodeSymbolInfos[astNode] = NodeSymbolInfos[returnNodes[0]]; // 确定的返回值
}
}
@@ -235,32 +239,61 @@ namespace Serein.Script
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
Type AnalysisClassTypeDefinitionNode(ClassTypeDefinitionNode classTypeDefinitionNode)
{
var classType = DynamicObjectHelper.GetCacheType(classTypeDefinitionNode.ClassName);
if (classType is null)
classType = DynamicObjectHelper.CreateTypeWithProperties(classTypeDefinitionNode.Fields, classTypeDefinitionNode.ClassName);
var classType = Analysis(classTypeDefinitionNode.ClassType); // 查询类型
NodeSymbolInfos[classTypeDefinitionNode] = classType;
foreach (var kvp in classTypeDefinitionNode.Propertys)
{
TypeNode propertyNode = kvp.Value;
var propertyType = Analysis(propertyNode); // 查询属性类型
NodeSymbolInfos[propertyNode] = propertyType;
}
NodeSymbolInfos[classTypeDefinitionNode] = classType;
return classType;
}
return AnalysisClassTypeDefinitionNode(classTypeDefinitionNode);
case TypeNode typeNode:
Type AnalysisTypeNode(TypeNode typeNode)
{
// 类型搜寻优先级: 挂载类型 > 脚本中定义类型 > C#类型
Type resultType = GetTypeOfString(typeNode.TypeName); // 从自定义类型查询类型
NodeSymbolInfos[typeNode] = resultType;
return resultType;
}
return AnalysisTypeNode(typeNode);
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
Type AnalysisObjectInstantiationNode(ObjectInstantiationNode objectInstantiationNode)
{
Type? resultType = null;
try
Type resultType = Analysis(objectInstantiationNode.Type);
foreach(var item in objectInstantiationNode.CtorAssignments)
{
resultType = Type.GetType(objectInstantiationNode.TypeName); // 从命名空间查询类型
}
finally
{
if (resultType is null)
{
resultType = DynamicObjectHelper.GetCacheType(objectInstantiationNode.TypeName); // 从自定义类型查询类型
}
Analysis(item);
}
NodeSymbolInfos[objectInstantiationNode] = resultType;
return resultType;
}
return AnalysisObjectInstantiationNode(objectInstantiationNode);
case CtorAssignmentNode ctorAssignmentNode: // 构造器赋值
Type AnalysisCtorAssignmentNode(CtorAssignmentNode ctorAssignmentNode)
{
Type classType = Analysis(ctorAssignmentNode.Class);
Type valueType = Analysis(ctorAssignmentNode.Value);
//ctorAssignmentNode.MemberName
var property = classType.GetProperty(ctorAssignmentNode.MemberName);
if (property is null)
throw new Exception($"类型 {classType} 没有成员 {ctorAssignmentNode.MemberName}");
var propertyType = property.PropertyType;
if (!propertyType.IsAssignableFrom(valueType))
throw new Exception($"类型异常:构造器赋值需要 {propertyType},实际为 {valueType}");
NodeSymbolInfos[ctorAssignmentNode.Class] = classType;
NodeSymbolInfos[ctorAssignmentNode.Value] = valueType;
NodeSymbolInfos[ctorAssignmentNode] = propertyType;
return valueType;
}
return AnalysisCtorAssignmentNode(ctorAssignmentNode);
case ExpressionNode expressionNode: // 类型表达式(链式调用)
Type AnalysisObjectMemberExpressionNode(ExpressionNode expressionNode)
{
@@ -289,16 +322,33 @@ namespace Serein.Script
Type AnalysisMemberAssignmentNode(MemberAssignmentNode memberAssignmentNode)
{
var objectType = Analysis(memberAssignmentNode.Object);
var property = objectType.GetProperty(memberAssignmentNode.MemberName);
if(property is null)
throw new Exception($"类型异常:类型 {objectType} 没有成员 {memberAssignmentNode.MemberName}");
var propertyType = property.PropertyType;
var valueType = Analysis(memberAssignmentNode.Value);
if (!propertyType.IsAssignableFrom(valueType))
throw new Exception($"类型异常:赋值需要 {propertyType},实际为 {valueType}");
NodeSymbolInfos[memberAssignmentNode.Object] = propertyType;
NodeSymbolInfos[memberAssignmentNode.Value] = valueType;
NodeSymbolInfos[memberAssignmentNode] = typeof(void);
if(objectType == typeof(object))
{
/*var property = objectType.GetProperty(memberAssignmentNode.MemberName);
if (property is null)
throw new Exception($"类型异常:类型 {objectType} 没有成员 {memberAssignmentNode.MemberName}");
var propertyType = property.PropertyType;
var valueType = Analysis(memberAssignmentNode.Value);
if (!propertyType.IsAssignableFrom(valueType))
throw new Exception($"类型异常:赋值需要 {propertyType},实际为 {valueType}");*/
NodeSymbolInfos[memberAssignmentNode.Object] = typeof(object);
NodeSymbolInfos[memberAssignmentNode.Value] = typeof(object);
NodeSymbolInfos[memberAssignmentNode] = typeof(void);
}
else
{
var property = objectType.GetProperty(memberAssignmentNode.MemberName);
if (property is null)
throw new Exception($"类型异常:类型 {objectType} 没有成员 {memberAssignmentNode.MemberName}");
var propertyType = property.PropertyType;
var valueType = Analysis(memberAssignmentNode.Value);
if (!propertyType.IsAssignableFrom(valueType))
throw new Exception($"类型异常:赋值需要 {propertyType},实际为 {valueType}");
NodeSymbolInfos[memberAssignmentNode.Object] = propertyType;
NodeSymbolInfos[memberAssignmentNode.Value] = valueType;
NodeSymbolInfos[memberAssignmentNode] = typeof(void);
}
return typeof(void); // 对象成员赋值语句不产生类型
}
return AnalysisMemberAssignmentNode(memberAssignmentNode);
@@ -319,12 +369,14 @@ namespace Serein.Script
NodeSymbolInfos[memberFunctionCallNode.Object] = objectType;
NodeSymbolInfos[memberFunctionCallNode] = methodInfo.ReturnType;
return methodInfo.ReturnType;
}
return AnalysisMemberFunctionCallNode(memberFunctionCallNode);
case FunctionCallNode functionCallNode: // 外部挂载的函数调用
Type AnalysisFunctionCallNode(FunctionCallNode functionCallNode)
{
if(!SereinScriptInterpreter.FunctionInfoTable.TryGetValue(functionCallNode.FunctionName, out var methodInfo))
if(!SereinScript.FunctionInfos.TryGetValue(functionCallNode.FunctionName, out var methodInfo))
{
throw new Exception($"脚本没有挂载方法 {functionCallNode.FunctionName}");
}
@@ -486,6 +538,8 @@ namespace Serein.Script
break;
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
break;
case TypeNode typeNode: // 类型
break;
case ObjectInstantiationNode objectInstantiationNode: // 类型实例化
break;
case ExpressionNode expressionNode: // 类型表达式(链式调用)
@@ -504,6 +558,29 @@ namespace Serein.Script
}
public static Type GetTypeOfString(string typeName)
{
Type? resultType = null;
resultType = DynamicObjectHelper.GetCacheType(typeName); // 从自定义类型查询类型
if (resultType != null)
{
return resultType;
}
try
{
resultType = Type.GetType(typeName); // 从命名空间查询类型
if (resultType != null)
{
return resultType;
}
throw new InvalidOperationException($"无法匹配类型 {typeName}");
}
catch (Exception ex)
{
throw;
}
}