mirror of
https://gitee.com/langsisi_admin/serein-flow
synced 2026-03-03 00:00:49 +08:00
1. Script项目添加了数组表达式的支持
2. EmitHelper添加了数组创建委托的构建
This commit is contained in:
@@ -1,10 +1,6 @@
|
|||||||
using Serein.Library.Utils;
|
using Serein.Library.Utils;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using static Serein.Library.Utils.EmitHelper;
|
using static Serein.Library.Utils.EmitHelper;
|
||||||
|
|
||||||
@@ -54,7 +50,11 @@ namespace Serein.Library
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 集合赋值
|
/// 集合赋值
|
||||||
/// </summary>
|
/// </summary>
|
||||||
CollectionSetter
|
CollectionSetter,
|
||||||
|
/// <summary>
|
||||||
|
/// 数组创建
|
||||||
|
/// </summary>
|
||||||
|
ArrayCreate,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -172,6 +172,12 @@ namespace Serein.Library
|
|||||||
this.emitType = EmitType.CollectionGetter;
|
this.emitType = EmitType.CollectionGetter;
|
||||||
collectionGetter = EmitHelper.CreateCollectionGetter(type);
|
collectionGetter = EmitHelper.CreateCollectionGetter(type);
|
||||||
}
|
}
|
||||||
|
else if (emitType == EmitType.ArrayCreate)
|
||||||
|
{
|
||||||
|
Func<int, object> func = EmitHelper.CreateArrayFactory(type);
|
||||||
|
this.arrayCreatefunc = func;
|
||||||
|
this.emitType = EmitType.ArrayCreate;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throw new NotSupportedException("错误的构建类型");
|
throw new NotSupportedException("错误的构建类型");
|
||||||
@@ -179,8 +185,8 @@ namespace Serein.Library
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private Func<object,object, object> collectionGetter= null;
|
private Func<object,object, object> collectionGetter= null;
|
||||||
@@ -195,6 +201,8 @@ namespace Serein.Library
|
|||||||
private Func<object, object[], Task> methodTask = null;
|
private Func<object, object[], Task> methodTask = null;
|
||||||
private Func<object, object[], object> methodInvoke = null;
|
private Func<object, object[], object> methodInvoke = null;
|
||||||
|
|
||||||
|
private Func<int, object> arrayCreatefunc = null;
|
||||||
|
|
||||||
|
|
||||||
/*/// <summary>
|
/*/// <summary>
|
||||||
/// 更新委托方法
|
/// 更新委托方法
|
||||||
@@ -260,10 +268,17 @@ namespace Serein.Library
|
|||||||
collectionSetter(instance, args[0], args[1]);
|
collectionSetter(instance, args[0], args[1]);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
else
|
else if(emitType == EmitType.ArrayCreate)
|
||||||
{
|
{
|
||||||
throw new NotSupportedException("当前委托类型不支持 InvokeAsync 方法。请使用其他方法调用。");
|
if(args[0] is int count)
|
||||||
|
{
|
||||||
|
return arrayCreatefunc(count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
throw new NotSupportedException("当前委托类型不支持 InvokeAsync 方法。请使用其他方法调用。");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<object> MethodInvoke(object instance, object[] args)
|
private async Task<object> MethodInvoke(object instance, object[] args)
|
||||||
|
|||||||
@@ -226,10 +226,8 @@ namespace Serein.Library.Utils
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建字段 Getter 委托:Func<object, object>
|
/// 构建字段 Getter 委托:Func<object, object>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Func<object, object> CreateFieldGetter(FieldInfo fieldInfo)
|
public static Func<object, object> CreateFieldGetter(FieldInfo fieldInfo)
|
||||||
{
|
{
|
||||||
@@ -271,7 +269,7 @@ namespace Serein.Library.Utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建字段 Setter 委托:Action<object, object>
|
/// 构建字段 Setter 委托:Action<object, object>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Action<object, object> CreateFieldSetter(FieldInfo fieldInfo)
|
public static Action<object, object> CreateFieldSetter(FieldInfo fieldInfo)
|
||||||
{
|
{
|
||||||
@@ -315,7 +313,7 @@ namespace Serein.Library.Utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建属性 Getter 委托:Func<object, object>
|
/// 构建属性 Getter 委托:Func<object, object>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Func<object, object> CreatePropertyGetter(PropertyInfo propertyInfo)
|
public static Func<object, object> CreatePropertyGetter(PropertyInfo propertyInfo)
|
||||||
{
|
{
|
||||||
@@ -357,7 +355,7 @@ namespace Serein.Library.Utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建属性 Setter 委托:Action<object, object>
|
/// 构建属性 Setter 委托:Action<object, object>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static Action<object, object> CreatePropertySetter(PropertyInfo propertyInfo)
|
public static Action<object, object> CreatePropertySetter(PropertyInfo propertyInfo)
|
||||||
{
|
{
|
||||||
@@ -402,9 +400,40 @@ namespace Serein.Library.Utils
|
|||||||
return (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
|
return (Action<object, object>)method.CreateDelegate(typeof(Action<object, object>));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 构建数组创建委托:Func<int, object[]>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="elementType"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <exception cref="ArgumentNullException"></exception>
|
||||||
|
|
||||||
|
public static Func<int, object> CreateArrayFactory(Type elementType)
|
||||||
|
{
|
||||||
|
if (elementType == null) throw new ArgumentNullException(nameof(elementType));
|
||||||
|
|
||||||
|
var arrayType = elementType.MakeArrayType();
|
||||||
|
|
||||||
|
var dm = new DynamicMethod(
|
||||||
|
$"NewArray_{elementType.Name}",
|
||||||
|
typeof(object), // 返回 object
|
||||||
|
new[] { typeof(int) }, // 参数:length
|
||||||
|
typeof(EmitHelper).Module,
|
||||||
|
true);
|
||||||
|
|
||||||
|
var il = dm.GetILGenerator();
|
||||||
|
|
||||||
|
|
||||||
|
il.Emit(OpCodes.Ldarg_0); // length
|
||||||
|
il.Emit(OpCodes.Newarr, elementType); // new T[length]
|
||||||
|
il.Emit(OpCodes.Ret); // 返回 T[]
|
||||||
|
|
||||||
|
return (Func<int, object>)dm.CreateDelegate(typeof(Func<int, object>));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建集合赋值委托:Action<object, object, object>
|
/// 构建集合赋值委托:Action<object, object, object>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="collectionType"></param>
|
/// <param name="collectionType"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
@@ -474,9 +503,8 @@ namespace Serein.Library.Utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 创建集合获取委托:Func<object, object, object>
|
/// 构建集合获取委托:Func<object, object, object>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="collectionType"></param>
|
/// <param name="collectionType"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Serein.Library.Utils
|
namespace Serein.Library.Utils
|
||||||
@@ -173,8 +174,52 @@ namespace Serein.Library.Utils
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发掘类型中的基类
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="types"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static Type? FindCommonBaseType(Type[] types)
|
||||||
|
{
|
||||||
|
if (types.Length == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
Type? baseType = types[0];
|
||||||
|
|
||||||
|
foreach (var type in types.Skip(1))
|
||||||
|
{
|
||||||
|
baseType = FindCommonBaseType(baseType, type);
|
||||||
|
if (baseType == typeof(object))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return baseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查找父类
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="a"></param>
|
||||||
|
/// <param name="b"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
private static Type FindCommonBaseType(Type a, Type b)
|
||||||
|
{
|
||||||
|
// 如果相等,直接返回
|
||||||
|
if (a == b) return a;
|
||||||
|
|
||||||
|
// 向上查找父类链,找第一个 b.IsAssignableFrom(base)
|
||||||
|
var current = a;
|
||||||
|
while (current != null && current != typeof(object))
|
||||||
|
{
|
||||||
|
if (current.IsAssignableFrom(b))
|
||||||
|
return current;
|
||||||
|
|
||||||
|
current = current.BaseType!;
|
||||||
|
}
|
||||||
|
|
||||||
|
return typeof(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
27
Serein.Script/Node/ArrayDefintionNode.cs
Normal file
27
Serein.Script/Node/ArrayDefintionNode.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Serein.Script.Node
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 数组定义节点
|
||||||
|
/// <para>arr = [1, 2, 3, 4, 5];</para>
|
||||||
|
/// <para>arr = ["A","B","C"];</para>
|
||||||
|
/// </summary>
|
||||||
|
internal class ArrayDefintionNode : ASTNode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 数组子项
|
||||||
|
/// </summary>
|
||||||
|
public List<ASTNode> Elements { get; } = new List<ASTNode>();
|
||||||
|
|
||||||
|
public ArrayDefintionNode(List<ASTNode> elements)
|
||||||
|
{
|
||||||
|
Elements = elements;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -175,6 +175,39 @@ namespace Serein.Script
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
return await InterpreterCollectionIndexNodeAsync(context, collectionIndexNode);
|
return await InterpreterCollectionIndexNodeAsync(context, collectionIndexNode);
|
||||||
|
case ArrayDefintionNode arrayDefintionNode:
|
||||||
|
async Task<Array> InterpreterArrayDefintionNodeAsync(ArrayDefintionNode arrayDefintionNode)
|
||||||
|
{
|
||||||
|
var elementNodes = arrayDefintionNode.Elements;
|
||||||
|
var elementCount = elementNodes.Count;
|
||||||
|
if(elementCount == 0)
|
||||||
|
{
|
||||||
|
return Array.Empty<object>();
|
||||||
|
}
|
||||||
|
/*var arrayType = symbolInfos[arrayDefintionNode]; // 从 symbolInfos 中获取数组类型( T[])
|
||||||
|
var eleType = arrayType.MakeArrayType();*/
|
||||||
|
/*if (!ASTDelegateDetails.TryGetValue(arrayDefintionNode, out DelegateDetails? delegateDetails))
|
||||||
|
{
|
||||||
|
delegateDetails = new DelegateDetails(symbolInfos[elementNodes[0]], DelegateDetails.EmitType.ArrayCreate);
|
||||||
|
ASTDelegateDetails[arrayDefintionNode] = delegateDetails;
|
||||||
|
}*/
|
||||||
|
//var arrobj = await delegateDetails.InvokeAsync(null, [elementCount]);
|
||||||
|
|
||||||
|
var elementType1 = symbolInfos[elementNodes[0]];
|
||||||
|
var array = Array.CreateInstance(elementType1, elementCount);
|
||||||
|
for (int i = 0; i < elementNodes.Count; i++)
|
||||||
|
{
|
||||||
|
var elementNode = elementNodes[i];
|
||||||
|
var elementType = symbolInfos[elementNode];
|
||||||
|
var value = await InterpretAsync(context, elementNode);
|
||||||
|
var c = Convert.ChangeType(value, elementType);
|
||||||
|
array.SetValue(c, i);
|
||||||
|
//array[i] = value;
|
||||||
|
}
|
||||||
|
return array;
|
||||||
|
|
||||||
|
}
|
||||||
|
return await InterpreterArrayDefintionNodeAsync(arrayDefintionNode);
|
||||||
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
|
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
|
||||||
void InterpreterClassTypeDefinitionNode(IScriptInvokeContext context, ClassTypeDefinitionNode classTypeDefinitionNode)
|
void InterpreterClassTypeDefinitionNode(IScriptInvokeContext context, ClassTypeDefinitionNode classTypeDefinitionNode)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -123,7 +123,7 @@
|
|||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return $"token in {Row} row, type is \"{Type}\", value is \"{Value}\".";
|
return $"token in {Row} row, type is \"{Type}\", value is \"{Value}\"";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,18 +117,19 @@ namespace Serein.Script
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
#region 生成 ASTNode
|
|
||||||
|
#region 生成赋值语句/一般语句的ASTNode
|
||||||
if (isAssignment)
|
if (isAssignment)
|
||||||
{
|
{
|
||||||
// 以赋值语句的形式进行处理
|
// 以赋值语句的形式进行处理
|
||||||
var assignmentNode = ParseAssignmentNode();
|
var assignmentNode = ParseAssignmentNode(); // 解析复制表达式
|
||||||
NextToken();// 消耗 ";"
|
NextToken();// 消耗 ";"
|
||||||
return assignmentNode;
|
return assignmentNode;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 以一般语句的形式进行处理,可当作表达式进行解析
|
// 以一般语句的形式进行处理,可当作表达式进行解析
|
||||||
var targetNode = ParserExpression(); // 解析表达式
|
var targetNode = ParserExpression();
|
||||||
NextToken();// 消耗 ";"
|
NextToken();// 消耗 ";"
|
||||||
return targetNode;
|
return targetNode;
|
||||||
}
|
}
|
||||||
@@ -176,8 +177,8 @@ namespace Serein.Script
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ASTNode ParseAssignmentNode()
|
public ASTNode ParseAssignmentNode()
|
||||||
{
|
{
|
||||||
/*
|
/* 解析赋值语句
|
||||||
赋值语句:
|
赋值语句:
|
||||||
目标对象 表达式获取
|
目标对象 表达式获取
|
||||||
Target() | = | Expression() |
|
Target() | = | Expression() |
|
||||||
| = | variable; | (变量)
|
| = | variable; | (变量)
|
||||||
@@ -186,6 +187,7 @@ namespace Serein.Script
|
|||||||
| = | array[...]; | array为之前的上下文中出现过的变量。
|
| = | array[...]; | array为之前的上下文中出现过的变量。
|
||||||
| = | array[...].Value...; | array为之前的上下文中出现过的变量。调用表达式包含对象成员数组、方法
|
| = | array[...].Value...; | array为之前的上下文中出现过的变量。调用表达式包含对象成员数组、方法
|
||||||
| = | new Class(...); | 实例化类型,包含构造函数
|
| = | new Class(...); | 实例化类型,包含构造函数
|
||||||
|
| = | [v1, v2, v3]; | 定义数组
|
||||||
|
|
||||||
补充:Target() 可能的成员
|
补充:Target() 可能的成员
|
||||||
1. variable
|
1. variable
|
||||||
@@ -199,11 +201,12 @@ namespace Serein.Script
|
|||||||
如果是 "[" ,代表需要获取数组索引
|
如果是 "[" ,代表需要获取数组索引
|
||||||
如果是 "=" ,代表是变量赋值,退出循环
|
如果是 "=" ,代表是变量赋值,退出循环
|
||||||
*/
|
*/
|
||||||
/*
|
/* 获取成员的方式有三种:
|
||||||
1. 获取成员 => PeekToken.Type = TokenType.Dot
|
* 1. 获取成员 => PeekToken.Type = TokenType.Dot
|
||||||
2. 获取集合 => PeekToken.Type = TokenType.SquareBracketsLeft
|
* 2. 获取集合 => PeekToken.Type = TokenType.SquareBracketsLeft
|
||||||
3. 调用成员方法 => PeekToken.Type = TokenType.ParenthesisLeft
|
* 3. 调用成员方法 => PeekToken.Type = TokenType.ParenthesisLeft
|
||||||
*/
|
*
|
||||||
|
* */
|
||||||
//if (JudgmentOperator(_currentToken, "=")) break; // 退出
|
//if (JudgmentOperator(_currentToken, "=")) break; // 退出
|
||||||
//var tempPeekToken = _lexer.PeekToken();
|
//var tempPeekToken = _lexer.PeekToken();
|
||||||
var backupToken = _currentToken;
|
var backupToken = _currentToken;
|
||||||
@@ -211,14 +214,14 @@ namespace Serein.Script
|
|||||||
|
|
||||||
List<ASTNode> nodes = [targetNode];
|
List<ASTNode> nodes = [targetNode];
|
||||||
ASTNode? source;
|
ASTNode? source;
|
||||||
var peekToken2 = _lexer.PeekToken(); // 消耗 第一个标识符
|
var peekNextToken = _lexer.PeekToken(); // 预览下个标识符
|
||||||
if (JudgmentOperator(peekToken2, "="))
|
if (JudgmentOperator(peekNextToken, "="))
|
||||||
{
|
{
|
||||||
NextToken();
|
NextToken();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (peekToken2.Type == TokenType.ParenthesisLeft)
|
if (peekNextToken.Type == TokenType.ParenthesisLeft)
|
||||||
{
|
{
|
||||||
// 解析调用挂载方法
|
// 解析调用挂载方法
|
||||||
// ... = variable()()();
|
// ... = variable()()();
|
||||||
@@ -230,7 +233,7 @@ namespace Serein.Script
|
|||||||
}
|
}
|
||||||
targetNode = functionCallNode;
|
targetNode = functionCallNode;
|
||||||
}
|
}
|
||||||
else if (peekToken2.Type == TokenType.SquareBracketsLeft)
|
else if (peekNextToken.Type == TokenType.SquareBracketsLeft)
|
||||||
{
|
{
|
||||||
// 解析集合获取
|
// 解析集合获取
|
||||||
var collectionIndexNode = ParseCollectionIndexNode(targetNode);
|
var collectionIndexNode = ParseCollectionIndexNode(targetNode);
|
||||||
@@ -240,7 +243,7 @@ namespace Serein.Script
|
|||||||
}
|
}
|
||||||
targetNode = collectionIndexNode;
|
targetNode = collectionIndexNode;
|
||||||
}
|
}
|
||||||
else if (peekToken2.Type == TokenType.Dot)
|
else if (peekNextToken.Type == TokenType.Dot)
|
||||||
{
|
{
|
||||||
NextToken();
|
NextToken();
|
||||||
}
|
}
|
||||||
@@ -254,10 +257,11 @@ namespace Serein.Script
|
|||||||
source = nodes[^1]; // 重定向节点
|
source = nodes[^1]; // 重定向节点
|
||||||
if (peekToken.Type == TokenType.Dot) // 从对象获取
|
if (peekToken.Type == TokenType.Dot) // 从对象获取
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
1. 获取成员 => PeekToken.Type = TokenType.Dot
|
* 获取成员的方式有三种:
|
||||||
2. 获取集合 => PeekToken.Type = TokenType.SquareBracketsLeft
|
* 1. 获取成员 => PeekToken.Type = TokenType.Dot
|
||||||
3. 调用成员方法 => PeekToken.Type = TokenType.ParenthesisLeft
|
* 2. 获取集合 => PeekToken.Type = TokenType.SquareBracketsLeft
|
||||||
|
* 3. 调用成员方法 => PeekToken.Type = TokenType.ParenthesisLeft
|
||||||
*/
|
*/
|
||||||
NextToken(); // 消耗 "." 并获取下一个成员。
|
NextToken(); // 消耗 "." 并获取下一个成员。
|
||||||
var peekToken3 = _lexer.PeekToken();
|
var peekToken3 = _lexer.PeekToken();
|
||||||
@@ -292,21 +296,7 @@ namespace Serein.Script
|
|||||||
nodes.Add(collectionIndexNode);
|
nodes.Add(collectionIndexNode);
|
||||||
continue; // 结束当前轮次的token判断
|
continue; // 结束当前轮次的token判断
|
||||||
}
|
}
|
||||||
/*else if (peekToken.Type == TokenType.Semicolon)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (peekToken.Type == TokenType.ParenthesisRight // 可能解析完了方法参数
|
|
||||||
|| peekToken.Type == TokenType.Comma // 可能解析完了方法参数
|
|
||||||
|| peekToken.Type == TokenType.ParenthesisRight) // 可能解析完了下标索引
|
|
||||||
{
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
// 应该是异常,如果是其它符号,说明词法解析不符合预期
|
|
||||||
throw new Exception($"在 Expression().Factor() 遇到意外的 TokenType ,{_currentToken.Type} {_currentToken.Value} ");
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
targetNode = nodes[^1];
|
targetNode = nodes[^1];
|
||||||
@@ -437,14 +427,16 @@ namespace Serein.Script
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// (不处理分号,逗号,右括号)用于解析(...)中的参数部分。终止条件是 "," 参数分隔符 和 ")" 方法入参终止符
|
/// (不处理分号,逗号,右括号)用于解析(...) / [...] 中的参数部分。终止条件是 "," 参数分隔符 、")" 方法入参终止符、"]" 数组定义终止符
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ASTNode ParserArgNode()
|
public ASTNode ParserArgNode()
|
||||||
{
|
{
|
||||||
ASTNode node = ParserExpression(); // 解析参数
|
ASTNode node = ParserExpression(); // 解析参数
|
||||||
// ParserExpression 会完全解析当前表达式,自动移动到下一个Token,所以需要在这里判断是否符合期望的TokenType
|
// ParserExpression 会完全解析当前表达式,自动移动到下一个Token,所以需要在这里判断是否符合期望的TokenType
|
||||||
if(_currentToken.Type == TokenType.Comma || _currentToken.Type == TokenType.ParenthesisRight)
|
if(_currentToken.Type == TokenType.Comma
|
||||||
|
|| _currentToken.Type == TokenType.ParenthesisRight
|
||||||
|
|| _currentToken.Type == TokenType.SquareBracketsRight)
|
||||||
{
|
{
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
@@ -1016,6 +1008,24 @@ namespace Serein.Script
|
|||||||
NextToken(); // 消耗 ")"
|
NextToken(); // 消耗 ")"
|
||||||
return expNode;
|
return expNode;
|
||||||
}
|
}
|
||||||
|
else if (_currentToken.Type == TokenType.SquareBracketsLeft)
|
||||||
|
{
|
||||||
|
NextToken(); // 消耗 "["
|
||||||
|
List<ASTNode> elements = [];
|
||||||
|
while (_currentToken.Type != TokenType.SquareBracketsRight) // 遇到 "]" 时结束
|
||||||
|
{
|
||||||
|
var element = ParserArgNode();
|
||||||
|
elements.Add(element);
|
||||||
|
if (_currentToken.Type == TokenType.Comma)
|
||||||
|
{
|
||||||
|
NextToken(); // 消耗参数分隔符 ","
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NextToken(); // 消耗 "]"
|
||||||
|
|
||||||
|
ArrayDefintionNode arrayDefintionNode = new ArrayDefintionNode(elements);
|
||||||
|
return arrayDefintionNode.SetTokenInfo(_currentToken);
|
||||||
|
}
|
||||||
else if(_currentToken.Type == TokenType.Keyword && _currentToken.Value == "new") // 创建对象
|
else if(_currentToken.Type == TokenType.Keyword && _currentToken.Value == "new") // 创建对象
|
||||||
{
|
{
|
||||||
return ParseObjectInstantiationNode();
|
return ParseObjectInstantiationNode();
|
||||||
|
|||||||
@@ -248,6 +248,43 @@ namespace Serein.Script
|
|||||||
return typeof(void);
|
return typeof(void);
|
||||||
}
|
}
|
||||||
return AnalysisCollectionAssignmentNode(collectionAssignmentNode);
|
return AnalysisCollectionAssignmentNode(collectionAssignmentNode);
|
||||||
|
case ArrayDefintionNode arrayDefintionNode:
|
||||||
|
Type AnalysisArrayDefintionNode(ArrayDefintionNode arrayDefintionNode)
|
||||||
|
{
|
||||||
|
var elements = arrayDefintionNode.Elements;
|
||||||
|
if (elements.Count == 0)
|
||||||
|
{
|
||||||
|
return typeof(object[]);
|
||||||
|
}
|
||||||
|
|
||||||
|
Type[] types = new Type[elements.Count];
|
||||||
|
for (int i = 0; i < elements.Count; i++)
|
||||||
|
{
|
||||||
|
ASTNode? element = elements[i];
|
||||||
|
var elementType = Analysis(element); // 分析元素类型
|
||||||
|
types[i] = elementType;
|
||||||
|
NodeSymbolInfos[element] = elementType; // 添加到符号表
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 所有类型一致
|
||||||
|
if (types.All(t => t == types[0]))
|
||||||
|
{
|
||||||
|
var arrType = types[0].MakeArrayType();
|
||||||
|
NodeSymbolInfos[arrayDefintionNode] = arrType; // 添加到符号表
|
||||||
|
return arrType;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 尝试找公共基类
|
||||||
|
Type? commonType = TypeHelper.FindCommonBaseType(types) ?? typeof(object);
|
||||||
|
var arrType = commonType.MakeArrayType();
|
||||||
|
NodeSymbolInfos[arrayDefintionNode] = arrType; // 添加到符号表
|
||||||
|
return arrType;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return AnalysisArrayDefintionNode(arrayDefintionNode);
|
||||||
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
|
case ClassTypeDefinitionNode classTypeDefinitionNode: // 类型定义
|
||||||
Type AnalysisClassTypeDefinitionNode(ClassTypeDefinitionNode classTypeDefinitionNode)
|
Type AnalysisClassTypeDefinitionNode(ClassTypeDefinitionNode classTypeDefinitionNode)
|
||||||
{
|
{
|
||||||
@@ -412,7 +449,7 @@ namespace Serein.Script
|
|||||||
default: // 未定义的节点类型
|
default: // 未定义的节点类型
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException($"类型分析遇到未定义的节点 \"{node.GetType()}\", {node}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -422,7 +459,7 @@ namespace Serein.Script
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="node"></param>
|
/// <param name="node"></param>
|
||||||
/// <exception cref="NotImplementedException"></exception>
|
/// <exception cref="NotImplementedException"></exception>
|
||||||
private void Analysis1(ASTNode node)
|
private void Analysis11111111111(ASTNode node)
|
||||||
{
|
{
|
||||||
switch (node)
|
switch (node)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -47,55 +47,8 @@ namespace Serein.Workbench
|
|||||||
collection.AddViewModelServices();
|
collection.AddViewModelServices();
|
||||||
var services = collection.BuildServiceProvider(); // 绑定并返回获取实例的服务接口
|
var services = collection.BuildServiceProvider(); // 绑定并返回获取实例的服务接口
|
||||||
App.ServiceProvider = services;
|
App.ServiceProvider = services;
|
||||||
#if DEBUG
|
|
||||||
_ = this.LoadLocalProjectAsync();
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
|
|
||||||
// 这里是测试代码,可以删除
|
|
||||||
private async Task LoadLocalProjectAsync()
|
|
||||||
{
|
|
||||||
var script = """
|
|
||||||
x = 114514;
|
|
||||||
x = (x * 100000000000) + x;
|
|
||||||
value = "调用";
|
|
||||||
value = value + "委托";
|
|
||||||
return value + x;
|
|
||||||
""";
|
|
||||||
var result = await SereinScript.ExecuteAsync(script);
|
|
||||||
|
|
||||||
/* var properties = new Dictionary<string, Type>
|
|
||||||
{
|
|
||||||
{ "Id", typeof(int) },
|
|
||||||
{ "Name", typeof(string) },
|
|
||||||
{ "CreateTime", typeof(DateTime) }
|
|
||||||
};
|
|
||||||
|
|
||||||
var type = DynamicObjectHelper.CreateTypeWithINotifyPropertyChanged(properties, "MyDynamicClass");
|
|
||||||
dynamic? obj = Activator.CreateInstance(type);
|
|
||||||
if(obj is null) return;
|
|
||||||
if (obj is INotifyPropertyChanged npc)
|
|
||||||
{
|
|
||||||
npc.PropertyChanged += (s, e) => Debug.WriteLine($"属性改变: {e.PropertyName}");
|
|
||||||
}
|
|
||||||
obj.Name = "下北泽";
|
|
||||||
obj.Id = 114514;*/
|
|
||||||
|
|
||||||
|
|
||||||
#if false
|
|
||||||
var projectService = App.GetService<FlowProjectService>();
|
|
||||||
await Task.Delay(500);
|
|
||||||
string filePath;
|
|
||||||
filePath = @"F:\TempFile\flow\temp2\project.dnf";
|
|
||||||
projectService.LoadLocalProject(filePath);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
private void Application_Startup(object sender, StartupEventArgs e)
|
private void Application_Startup(object sender, StartupEventArgs e)
|
||||||
{
|
{
|
||||||
var projectService = App.GetService<FlowProjectService>();
|
var projectService = App.GetService<FlowProjectService>();
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Remove="Converters\TypeToColorConverter.cs" />
|
||||||
<Compile Remove="MainWindow.xaml.cs" />
|
<Compile Remove="MainWindow.xaml.cs" />
|
||||||
<Compile Remove="MainWindowViewModel.cs" />
|
<Compile Remove="MainWindowViewModel.cs" />
|
||||||
<Compile Remove="Node\FlipflopRegionControl.xaml.cs" />
|
<Compile Remove="Node\FlipflopRegionControl.xaml.cs" />
|
||||||
|
|||||||
Reference in New Issue
Block a user