Compare commits
6 Commits
58f3d1067c
...
29dd4f5d96
| Author | SHA1 | Date | |
|---|---|---|---|
| 29dd4f5d96 | |||
| 971baf8c9e | |||
| 104a80e527 | |||
| b7ccc387fc | |||
| 4860aa251e | |||
| 7eb53fc3c5 |
@@ -1,5 +1,6 @@
|
||||
using Convention.RScript.Parser;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Convention.RScript.Runner
|
||||
@@ -8,28 +9,38 @@ namespace Convention.RScript.Runner
|
||||
{
|
||||
protected static void DoJumpRuntimePointer(ExpressionParser parser, int target, RScriptContext context)
|
||||
{
|
||||
Tuple<int, int> enterKey = Tuple.Create(context.CurrentRuntimePointer, target);
|
||||
int currentPointer = context.CurrentRuntimePointer;
|
||||
bool isForwardMove = target > context.CurrentRuntimePointer;
|
||||
int step = isForwardMove ? 1 : -1;
|
||||
int depth = 0;
|
||||
int lastLayer = 0;
|
||||
for (; context.CurrentRuntimePointer != target; context.CurrentRuntimePointer += step)
|
||||
if (context.JumpPointerCache.TryGetValue(enterKey, out var jumpResult))
|
||||
{
|
||||
if (context.CurrentSentence.mode == RScriptSentence.Mode.ExitNamespace)
|
||||
depth = jumpResult.Item1;
|
||||
lastLayer = jumpResult.Item2;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool isForwardMove = target > context.CurrentRuntimePointer;
|
||||
int step = isForwardMove ? 1 : -1;
|
||||
for (; context.CurrentRuntimePointer != target; context.CurrentRuntimePointer += step)
|
||||
{
|
||||
if (isForwardMove)
|
||||
lastLayer--;
|
||||
else
|
||||
lastLayer++;
|
||||
if (context.CurrentSentence.mode == RScriptSentence.Mode.ExitNamespace)
|
||||
{
|
||||
if (isForwardMove)
|
||||
lastLayer--;
|
||||
else
|
||||
lastLayer++;
|
||||
}
|
||||
else if (context.CurrentSentence.mode == RScriptSentence.Mode.EnterNamespace)
|
||||
{
|
||||
if (isForwardMove)
|
||||
lastLayer++;
|
||||
else
|
||||
lastLayer--;
|
||||
}
|
||||
depth = lastLayer < depth ? lastLayer : depth;
|
||||
}
|
||||
else if (context.CurrentSentence.mode == RScriptSentence.Mode.EnterNamespace)
|
||||
{
|
||||
if (isForwardMove)
|
||||
lastLayer++;
|
||||
else
|
||||
lastLayer--;
|
||||
}
|
||||
depth = lastLayer < depth ? lastLayer : depth;
|
||||
context.JumpPointerCache.Add(enterKey, Tuple.Create(depth, lastLayer));
|
||||
}
|
||||
// 对上层的最深影响
|
||||
for (; depth < 0; depth++)
|
||||
|
||||
@@ -95,6 +95,8 @@ namespace Convention.RScript.Parser
|
||||
public ExpressionParser(ExpressionContext context)
|
||||
{
|
||||
this.context = context;
|
||||
// 默认启用未定义标识符作为字符串的功能
|
||||
this.context.Options.UndefinedIdentifiersAsStrings = true;
|
||||
}
|
||||
|
||||
private readonly Dictionary<string, Type> CompileGenericExpressionTypen = new();
|
||||
|
||||
113
PublicTypes/InjectVariable/CStyle.cs
Normal file
113
PublicTypes/InjectVariable/CStyle.cs
Normal file
@@ -0,0 +1,113 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Convention.RScript.Variable.CStyle
|
||||
{
|
||||
public class CScriptRScriptVariableGenerater : RScriptInjectVariableGenerater
|
||||
{
|
||||
public static string GetTypename(Type type)
|
||||
{
|
||||
var name = type.Name.Replace('`', '_');
|
||||
return name;
|
||||
}
|
||||
|
||||
private int m_layer = 0;
|
||||
private int layer
|
||||
{
|
||||
get=>m_layer;
|
||||
set
|
||||
{
|
||||
m_layer = value;
|
||||
Prefix = new('\t', layer);
|
||||
}
|
||||
}
|
||||
private string Prefix = "";
|
||||
|
||||
public CScriptRScriptVariableGenerater(Type targetType, Generater generater, Destorier destorier, string name) : base(targetType, generater, destorier, name)
|
||||
{
|
||||
}
|
||||
|
||||
protected override string WriteClassBodyEnter(Type currentType)
|
||||
{
|
||||
string result = $"{Prefix}{"{"}\n{Prefix}public:";
|
||||
layer++;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override string WriteClassBodyExit(Type currentType)
|
||||
{
|
||||
layer--;
|
||||
return $"{Prefix}{"};"}";
|
||||
}
|
||||
|
||||
protected override string WriteClassHead(Type currentType)
|
||||
{
|
||||
string description = string.IsNullOrEmpty(this.description) ? "" : string.Join("", from item in this.description.Split('\n') where string.IsNullOrEmpty(item) == false select $"{Prefix}{item}\n");
|
||||
string suffix = currentType.BaseType == typeof(object) ? string.Empty : $" : public {GetTypename(currentType.BaseType)}";
|
||||
string result = $"{Prefix}\\*{description}*\\\n{Prefix}{Prefix}class {GetTypename(currentType)}{suffix}";
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override string WriteClassMethod(Type returnType, string methodName, string[] parameterNames, Type[] parameterTypes)
|
||||
{
|
||||
List<string> parameters = new();
|
||||
for (int i = 0, e = parameterNames.Length; i < e; i++)
|
||||
{
|
||||
parameters.Add($"{GetTypename(parameterTypes[i])} {parameterNames[i]}");
|
||||
}
|
||||
return $"{Prefix}{GetTypename(returnType)} {methodName}({string.Join(", ", parameters)});";
|
||||
}
|
||||
|
||||
protected override string WriteClassTail(Type currentType)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
protected override string WriteEnumBodyEnter(Type currentType)
|
||||
{
|
||||
string result = $"{Prefix}{"{"}";
|
||||
layer++;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected override string WriteEnumBodyExit(Type currentType)
|
||||
{
|
||||
layer--;
|
||||
return $"{Prefix}{"};"}";
|
||||
}
|
||||
|
||||
protected override string WriteEnumHead(Type currentEnum)
|
||||
{
|
||||
return $"{Prefix}enum {GetTypename(currentEnum)}";
|
||||
}
|
||||
|
||||
protected override string WriteEnumName(string enumName)
|
||||
{
|
||||
return $"{Prefix}{enumName},";
|
||||
}
|
||||
|
||||
protected override string WriteEnumTail(Type currentType)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
protected override string WritePageEnd(Type currentType)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
protected override string WritePageHead(Type currentType)
|
||||
{
|
||||
return $"#include\"{GetFilename(currentType)}\"";
|
||||
}
|
||||
|
||||
public override string GetFilename(Type currentType)
|
||||
{
|
||||
return GetTypename(currentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
224
PublicTypes/RScriptInjectVariableGenerater.cs
Normal file
224
PublicTypes/RScriptInjectVariableGenerater.cs
Normal file
@@ -0,0 +1,224 @@
|
||||
using Flee.InternalTypes;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Convention.RScript.Variable
|
||||
{
|
||||
namespace Attr
|
||||
{
|
||||
|
||||
[AttributeUsage(AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
|
||||
public sealed class MethodAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Enum, Inherited = true, AllowMultiple = false)]
|
||||
public sealed class EnumAttribute : Attribute
|
||||
{
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class|AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
|
||||
public sealed class DefaultAttribute : Attribute
|
||||
{
|
||||
public string defaultScript;
|
||||
public DefaultAttribute(string defaultScript)
|
||||
{
|
||||
this.defaultScript = defaultScript;
|
||||
}
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, Inherited = false, AllowMultiple = false)]
|
||||
public sealed class DescriptionAttribute : Attribute
|
||||
{
|
||||
public string description;
|
||||
public DescriptionAttribute(string description)
|
||||
{
|
||||
this.description = description;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract class RScriptInjectVariableGenerater
|
||||
{
|
||||
public string RScriptString { get; private set; }
|
||||
|
||||
public abstract string GetFilename(Type currentType);
|
||||
|
||||
protected abstract string WritePageHead(Type currentType);
|
||||
|
||||
#region Enum
|
||||
|
||||
protected abstract string WriteEnumHead(Type currentEnum);
|
||||
protected abstract string WriteEnumBodyEnter(Type currentType);
|
||||
protected abstract string WriteEnumName(string enumName);
|
||||
protected abstract string WriteEnumBodyExit(Type currentType);
|
||||
protected abstract string WriteEnumTail(Type currentType);
|
||||
|
||||
#endregion
|
||||
|
||||
#region Class
|
||||
|
||||
protected abstract string WriteClassHead(Type currentType);
|
||||
protected abstract string WriteClassBodyEnter(Type currentType);
|
||||
protected abstract string WriteClassMethod(Type returnType, string methodName, string[] parameterNames, Type[] parameterTypes);
|
||||
protected abstract string WriteClassBodyExit(Type currentType);
|
||||
protected abstract string WriteClassTail(Type currentType);
|
||||
|
||||
#endregion
|
||||
|
||||
protected abstract string WritePageEnd(Type currentType);
|
||||
|
||||
/// <summary>
|
||||
/// 生成targetType类型的实体
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public delegate object Generater();
|
||||
|
||||
public delegate void Destorier(object o);
|
||||
|
||||
private readonly Generater MyGenerater;
|
||||
private readonly Destorier MyDestorier;
|
||||
private readonly HashSet<object> GenerateObjects = new();
|
||||
|
||||
public readonly static Dictionary<string, RScriptInjectVariableGenerater> AllRScriptInjectVariables = new();
|
||||
|
||||
public readonly Type targetType;
|
||||
public readonly string name;
|
||||
public readonly string scriptIndicator;
|
||||
public readonly string defaultScript;
|
||||
public readonly string description;
|
||||
|
||||
public object Generate()
|
||||
{
|
||||
return MyGenerater();
|
||||
}
|
||||
|
||||
public RScriptInjectVariableGenerater(Type targetType, [MaybeNull] Generater generater, [MaybeNull] Destorier destorier, string name)
|
||||
{
|
||||
if (AllRScriptInjectVariables.TryGetValue(name, out var exist_var))
|
||||
{
|
||||
throw new InvalidOperationException($"{name} is been used");
|
||||
}
|
||||
|
||||
this.targetType = targetType;
|
||||
this.MyGenerater = generater;
|
||||
this.MyDestorier = destorier;
|
||||
this.name = name;
|
||||
var defaultAttr = targetType.GetCustomAttribute<Attr.DefaultAttribute>();
|
||||
this.defaultScript = defaultAttr?.defaultScript ?? "";
|
||||
var descriptionAttr = targetType.GetCustomAttribute<Attr.DescriptionAttribute>();
|
||||
this.description = descriptionAttr?.description ?? "";
|
||||
|
||||
StringBuilder builder = new();
|
||||
builder.AppendLine(this.WritePageHead(targetType));
|
||||
builder.AppendLine(this.WriteClassHead(targetType));
|
||||
builder.AppendLine(this.WriteClassBodyEnter(targetType));
|
||||
// 绘制枚举
|
||||
{
|
||||
var scriptEnums = from enumItem in targetType.GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Public)
|
||||
where enumItem.GetCustomAttribute<Attr.EnumAttribute>() != null
|
||||
select enumItem;
|
||||
foreach (var enumItem in scriptEnums)
|
||||
{
|
||||
var attr = enumItem.GetCustomAttribute<Attr.EnumAttribute>();
|
||||
this.WriteEnumHead(targetType);
|
||||
this.WriteEnumBodyEnter(targetType);
|
||||
foreach (var enumName in enumItem.GetEnumNames())
|
||||
{
|
||||
this.WriteEnumName(enumName);
|
||||
}
|
||||
this.WriteEnumBodyExit(targetType);
|
||||
this.WriteEnumTail(targetType);
|
||||
}
|
||||
}
|
||||
// 绘制方法
|
||||
{
|
||||
var scriptMethods = from method in targetType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
|
||||
where method.GetCustomAttribute<Attr.MethodAttribute>() != null
|
||||
select method;
|
||||
foreach (var method in scriptMethods)
|
||||
{
|
||||
var attr = method.GetCustomAttribute<Attr.MethodAttribute>();
|
||||
var returnType = method.ReturnType;
|
||||
var methodName = method.Name;
|
||||
var parameters = method.GetParameters();
|
||||
var parameterNames = from item in parameters select item.Name;
|
||||
var parameterTypes = from item in parameters select item.ParameterType;
|
||||
builder.AppendLine(this.WriteClassMethod(returnType, methodName, parameterNames.ToArray(), parameterTypes.ToArray()));
|
||||
}
|
||||
}
|
||||
builder.AppendLine(this.WriteClassBodyExit(targetType));
|
||||
builder.AppendLine(this.WriteClassTail(targetType));
|
||||
builder.AppendLine(this.WritePageEnd(targetType));
|
||||
this.scriptIndicator = builder.ToString();
|
||||
}
|
||||
|
||||
public void Register()
|
||||
{
|
||||
AllRScriptInjectVariables.Add(name, this);
|
||||
}
|
||||
|
||||
public bool Unregister()
|
||||
{
|
||||
if (MyDestorier != null)
|
||||
foreach (var item in GenerateObjects)
|
||||
{
|
||||
MyDestorier(item);
|
||||
}
|
||||
this.GenerateObjects.Clear();
|
||||
return AllRScriptInjectVariables.Remove(name);
|
||||
}
|
||||
|
||||
public static object GenerateRScriptVariable(string name)
|
||||
{
|
||||
if (AllRScriptInjectVariables.TryGetValue(name, out var variable))
|
||||
{
|
||||
if (variable.MyGenerater != null)
|
||||
{
|
||||
var result = variable.Generate();
|
||||
if (result.GetType().IsSubclassOf(variable.targetType) || result.GetType() == variable.targetType)
|
||||
{
|
||||
variable.GenerateObjects.Add(result);
|
||||
return result;
|
||||
}
|
||||
else
|
||||
throw new InvalidOperationException($"{name} target is not sub-class of it's target type");
|
||||
}
|
||||
}
|
||||
throw new InvalidOperationException($"{name} target is not exist or abstract");
|
||||
}
|
||||
|
||||
public static string DestoryRScriptVariable(object o)
|
||||
{
|
||||
if (o == null)
|
||||
return string.Empty;
|
||||
foreach (var (name,variable) in AllRScriptInjectVariables)
|
||||
{
|
||||
variable.GenerateObjects.RemoveWhere(x => x == null);
|
||||
if(variable.GenerateObjects.Remove(o))
|
||||
{
|
||||
variable.MyDestorier(o);
|
||||
return variable.name;
|
||||
}
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
public static class RScriptVariableGenerater
|
||||
{
|
||||
public static object New(string name)
|
||||
{
|
||||
return RScriptInjectVariableGenerater.GenerateRScriptVariable(name);
|
||||
}
|
||||
|
||||
public static string Delete(object o)
|
||||
{
|
||||
return RScriptInjectVariableGenerater.DestoryRScriptVariable(o);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,6 +92,7 @@ namespace Convention.RScript
|
||||
void Run(ExpressionParser parser);
|
||||
IEnumerator RunAsync(ExpressionParser parser);
|
||||
SerializableClass Compile(ExpressionParser parser);
|
||||
SerializableClass CompileFromCurrent(ExpressionParser parser);
|
||||
}
|
||||
|
||||
public partial class RScriptContext : IBasicRScriptContext
|
||||
@@ -111,6 +112,7 @@ namespace Convention.RScript
|
||||
public Tuple<int, int>[] NamespaceLayer;
|
||||
public Tuple<string, int>[] NamespaceLabels;
|
||||
public ExpressionParser.SerializableParser CompileParser;
|
||||
public Tuple<Tuple<int, int>, Tuple<int, int>>[] JumpPointerCache;
|
||||
}
|
||||
|
||||
public List<IRSentenceMatcher> SentenceParser = new()
|
||||
@@ -250,9 +252,14 @@ namespace Convention.RScript
|
||||
this.Variables.Add("context", new(typeof(object), new BuildInContext(this)));
|
||||
|
||||
this.Sentences = data.Sentences;
|
||||
this.Labels = (from item in data.Labels select item).ToDictionary(t => t.Item1, t => t.Item2);
|
||||
this.NamespaceLayer = (from item in data.NamespaceLayer select item).ToDictionary(t => t.Item1, t => t.Item2);
|
||||
this.NamespaceLabels = (from item in data.NamespaceLabels select item).ToDictionary(t => t.Item1, t => t.Item2);
|
||||
if (data.Labels != null)
|
||||
this.Labels = (from item in data.Labels select item).ToDictionary(t => t.Item1, t => t.Item2);
|
||||
if (data.NamespaceLayer != null)
|
||||
this.NamespaceLayer = (from item in data.NamespaceLayer select item).ToDictionary(t => t.Item1, t => t.Item2);
|
||||
if (data.NamespaceLabels != null)
|
||||
this.NamespaceLabels = (from item in data.NamespaceLabels select item).ToDictionary(t => t.Item1, t => t.Item2);
|
||||
if (data.JumpPointerCache != null)
|
||||
this.JumpPointerCache = (from item in data.JumpPointerCache select item).ToDictionary(t => t.Item1, t => t.Item2);
|
||||
}
|
||||
|
||||
public RScriptSentence CurrentSentence => Sentences[CurrentRuntimePointer];
|
||||
@@ -279,6 +286,7 @@ namespace Convention.RScript
|
||||
|
||||
internal readonly Stack<int> RuntimePointerStack = new();
|
||||
internal readonly Stack<int> GotoPointerStack = new();
|
||||
internal readonly Dictionary<Tuple<int, int>, Tuple<int, int>> JumpPointerCache = new();
|
||||
public int CurrentRuntimePointer { get; internal set; } = 0;
|
||||
internal readonly Stack<HashSet<string>> CurrentLocalSpaceVariableNames = new();
|
||||
|
||||
@@ -300,6 +308,8 @@ namespace Convention.RScript
|
||||
GotoPointerStack.Clear();
|
||||
CurrentLocalSpaceVariableNames.Clear();
|
||||
CurrentLocalSpaceVariableNames.Push(new());
|
||||
JumpPointerCache.Clear();
|
||||
parser.context.Imports.AddType(typeof(Variable.RScriptVariableGenerater));
|
||||
foreach (var staticType in Import)
|
||||
{
|
||||
parser.context.Imports.AddType(staticType);
|
||||
@@ -359,6 +369,19 @@ namespace Convention.RScript
|
||||
NamespaceLayer = (from item in NamespaceLayer select Tuple.Create(item.Key, item.Value)).ToArray(),
|
||||
NamespaceLabels = (from item in NamespaceLabels select Tuple.Create(item.Key, item.Value)).ToArray(),
|
||||
Sentences = Sentences,
|
||||
JumpPointerCache = (from item in JumpPointerCache select Tuple.Create(item.Key, item.Value)).ToArray(),
|
||||
};
|
||||
}
|
||||
public SerializableClass CompileFromCurrent(ExpressionParser parser)
|
||||
{
|
||||
return new SerializableClass()
|
||||
{
|
||||
CompileParser = parser.Serialize(),
|
||||
Labels = (from item in Labels select Tuple.Create(item.Key, item.Value)).ToArray(),
|
||||
NamespaceLayer = (from item in NamespaceLayer select Tuple.Create(item.Key, item.Value)).ToArray(),
|
||||
NamespaceLabels = (from item in NamespaceLabels select Tuple.Create(item.Key, item.Value)).ToArray(),
|
||||
Sentences = Sentences,
|
||||
JumpPointerCache = (from item in JumpPointerCache select Tuple.Create(item.Key, item.Value)).ToArray(),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ namespace Convention.RScript
|
||||
Dictionary<string, RScriptVariableEntry> Run(string script, RScriptImportClass import = null, RScriptVariables variables = null);
|
||||
IEnumerator RunAsync(string script, RScriptImportClass import = null, RScriptVariables variables = null);
|
||||
SerializableClass Compile(string script, RScriptImportClass import = null, RScriptVariables variables = null);
|
||||
SerializableClass GetCompileResultFromCurrent();
|
||||
Dictionary<string, RScriptVariableEntry> Run(SerializableClass data, RScriptImportClass import = null, RScriptVariables variables = null);
|
||||
IEnumerator RunAsync(SerializableClass data, RScriptImportClass import = null, RScriptVariables variables = null);
|
||||
}
|
||||
@@ -151,6 +152,10 @@ namespace Convention.RScript
|
||||
context = CreateContext(SplitScript(script).ToArray(), import, variables);
|
||||
return context.Compile(parser);
|
||||
}
|
||||
public SerializableClass GetCompileResultFromCurrent()
|
||||
{
|
||||
return context.CompileFromCurrent(parser);
|
||||
}
|
||||
|
||||
public Dictionary<string, RScriptVariableEntry> Run(SerializableClass data, RScriptImportClass import = null, RScriptVariables variables = null)
|
||||
{
|
||||
|
||||
@@ -63,8 +63,18 @@ namespace Convention.RScript
|
||||
}
|
||||
}
|
||||
|
||||
// 这里需要根据 ExpressionParser.SerializableParser 的结构来序列化
|
||||
// writer.Write(...); // CompileParser 的序列化
|
||||
// 序列化 JumpPointerCache 数组
|
||||
writer.Write(data.JumpPointerCache?.Length ?? 0);
|
||||
if (data.JumpPointerCache != null)
|
||||
{
|
||||
foreach (var jpItem in data.JumpPointerCache)
|
||||
{
|
||||
writer.Write(jpItem.Item1.Item1);
|
||||
writer.Write(jpItem.Item1.Item2);
|
||||
writer.Write(jpItem.Item2.Item1);
|
||||
writer.Write(jpItem.Item2.Item2);
|
||||
}
|
||||
}
|
||||
|
||||
return stream.ToArray();
|
||||
}
|
||||
@@ -141,8 +151,20 @@ namespace Convention.RScript
|
||||
}
|
||||
}
|
||||
|
||||
// 反序列化 CompileParser
|
||||
// result.CompileParser = ...; // 根据具体结构实现
|
||||
// 反序列化 JumpPointerCache 数组
|
||||
int jumpPointerCacheLength = reader.ReadInt32();
|
||||
if (jumpPointerCacheLength > 0)
|
||||
{
|
||||
result.JumpPointerCache = new Tuple<Tuple<int, int>, Tuple<int, int>>[jumpPointerCacheLength];
|
||||
for(int i=0;i<jumpPointerCacheLength;i++)
|
||||
{
|
||||
int x= reader.ReadInt32();
|
||||
int y= reader.ReadInt32();
|
||||
int z= reader.ReadInt32();
|
||||
int w= reader.ReadInt32();
|
||||
result.JumpPointerCache[i] = Tuple.Create(Tuple.Create(x, y), Tuple.Create(z, w));
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user