新增UndefinedIdentifiersAsStrings选项并完善变量控制器

This commit is contained in:
2025-10-27 10:50:36 +08:00
parent 971baf8c9e
commit 29dd4f5d96
4 changed files with 129 additions and 68 deletions

View File

@@ -95,6 +95,8 @@ namespace Convention.RScript.Parser
public ExpressionParser(ExpressionContext context) public ExpressionParser(ExpressionContext context)
{ {
this.context = context; this.context = context;
// 默认启用未定义标识符作为字符串的功能
this.context.Options.UndefinedIdentifiersAsStrings = true;
} }
private readonly Dictionary<string, Type> CompileGenericExpressionTypen = new(); private readonly Dictionary<string, Type> CompileGenericExpressionTypen = new();

View File

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace Convention.RScript.Variable.CStyle namespace Convention.RScript.Variable.CStyle
{ {
public class RScriptVariableGenerater : RScriptInjectVariableGenerater public class CScriptRScriptVariableGenerater : RScriptInjectVariableGenerater
{ {
public static string GetTypename(Type type) public static string GetTypename(Type type)
{ {
@@ -15,16 +15,25 @@ namespace Convention.RScript.Variable.CStyle
return name; return name;
} }
private int layer = 0; private int m_layer = 0;
private string Prefix => new('\t', layer); private int layer
{
get=>m_layer;
set
{
m_layer = value;
Prefix = new('\t', layer);
}
}
private string Prefix = "";
public RScriptVariableGenerater(Type targetType, [MaybeNull] Generater generater, string name) : base(targetType, generater, name) public CScriptRScriptVariableGenerater(Type targetType, Generater generater, Destorier destorier, string name) : base(targetType, generater, destorier, name)
{ {
} }
protected override string WriteClassBodyEnter(Type currentType) protected override string WriteClassBodyEnter(Type currentType)
{ {
string result = $"{Prefix}{"{public:"}"; string result = $"{Prefix}{"{"}\n{Prefix}public:";
layer++; layer++;
return result; return result;
} }
@@ -32,21 +41,21 @@ namespace Convention.RScript.Variable.CStyle
protected override string WriteClassBodyExit(Type currentType) protected override string WriteClassBodyExit(Type currentType)
{ {
layer--; layer--;
return $"{Prefix}{"{"}"; return $"{Prefix}{"};"}";
} }
protected override string WriteClassHead(Type currentType) 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 suffix = currentType.BaseType == typeof(object) ? string.Empty : $" : public {GetTypename(currentType.BaseType)}";
string result = $"{Prefix}class {GetTypename(currentType)}{suffix}"; string result = $"{Prefix}\\*{description}*\\\n{Prefix}{Prefix}class {GetTypename(currentType)}{suffix}";
layer++;
return result; return result;
} }
protected override string WriteClassMethod(Type returnType, string methodName, string[] parameterNames, Type[] parameterTypes) protected override string WriteClassMethod(Type returnType, string methodName, string[] parameterNames, Type[] parameterTypes)
{ {
List<string> parameters = new(); List<string> parameters = new();
for(int i=0,e=parameterNames.Length;i<e;i++) for (int i = 0, e = parameterNames.Length; i < e; i++)
{ {
parameters.Add($"{GetTypename(parameterTypes[i])} {parameterNames[i]}"); parameters.Add($"{GetTypename(parameterTypes[i])} {parameterNames[i]}");
} }
@@ -68,7 +77,7 @@ namespace Convention.RScript.Variable.CStyle
protected override string WriteEnumBodyExit(Type currentType) protected override string WriteEnumBodyExit(Type currentType)
{ {
layer--; layer--;
return $"{Prefix}{"{"}"; return $"{Prefix}{"};"}";
} }
protected override string WriteEnumHead(Type currentEnum) protected override string WriteEnumHead(Type currentEnum)

View File

@@ -1,4 +1,5 @@
using System; using Flee.InternalTypes;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
@@ -29,6 +30,16 @@ namespace Convention.RScript.Variable
this.defaultScript = 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 abstract class RScriptInjectVariableGenerater
@@ -67,7 +78,11 @@ namespace Convention.RScript.Variable
/// <returns></returns> /// <returns></returns>
public delegate object Generater(); public delegate object Generater();
private Generater MyGenerater; 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 static Dictionary<string, RScriptInjectVariableGenerater> AllRScriptInjectVariables = new();
@@ -75,77 +90,87 @@ namespace Convention.RScript.Variable
public readonly string name; public readonly string name;
public readonly string scriptIndicator; public readonly string scriptIndicator;
public readonly string defaultScript; public readonly string defaultScript;
public readonly string description;
public object Generate() public object Generate()
{ {
return MyGenerater(); return MyGenerater();
} }
public RScriptInjectVariableGenerater(Type targetType, [MaybeNull] Generater generater, string name) public RScriptInjectVariableGenerater(Type targetType, [MaybeNull] Generater generater, [MaybeNull] Destorier destorier, string name)
{ {
if (AllRScriptInjectVariables.TryGetValue(name, out var exist_var)) if (AllRScriptInjectVariables.TryGetValue(name, out var exist_var))
{ {
if (exist_var.MyGenerater != generater || exist_var.targetType != targetType) throw new InvalidOperationException($"{name} is been used");
{
throw new InvalidOperationException($"{name} is been used");
}
this.targetType = exist_var.targetType;
this.name = exist_var.name;
this.scriptIndicator = exist_var.scriptIndicator;
this.defaultScript = exist_var.defaultScript;
}
else
{
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();
} }
this.targetType = targetType; this.targetType = targetType;
this.MyGenerater = generater; this.MyGenerater = generater;
this.MyDestorier = destorier;
this.name = name; this.name = name;
var defaultAttr = targetType.GetCustomAttribute<Attr.DefaultAttribute>(); var defaultAttr = targetType.GetCustomAttribute<Attr.DefaultAttribute>();
this.defaultScript = defaultAttr?.defaultScript; 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) public static object GenerateRScriptVariable(string name)
@@ -156,13 +181,32 @@ namespace Convention.RScript.Variable
{ {
var result = variable.Generate(); var result = variable.Generate();
if (result.GetType().IsSubclassOf(variable.targetType) || result.GetType() == variable.targetType) if (result.GetType().IsSubclassOf(variable.targetType) || result.GetType() == variable.targetType)
{
variable.GenerateObjects.Add(result);
return result; return result;
}
else else
throw new InvalidOperationException($"{name} target is not sub-class of it's target type"); throw new InvalidOperationException($"{name} target is not sub-class of it's target type");
} }
} }
throw new InvalidOperationException($"{name} target is not exist or abstract"); 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 class RScriptVariableGenerater
@@ -171,5 +215,10 @@ namespace Convention.RScript.Variable
{ {
return RScriptInjectVariableGenerater.GenerateRScriptVariable(name); return RScriptInjectVariableGenerater.GenerateRScriptVariable(name);
} }
public static string Delete(object o)
{
return RScriptInjectVariableGenerater.DestoryRScriptVariable(o);
}
} }
} }

View File

@@ -309,6 +309,7 @@ namespace Convention.RScript
CurrentLocalSpaceVariableNames.Clear(); CurrentLocalSpaceVariableNames.Clear();
CurrentLocalSpaceVariableNames.Push(new()); CurrentLocalSpaceVariableNames.Push(new());
JumpPointerCache.Clear(); JumpPointerCache.Clear();
parser.context.Imports.AddType(typeof(Variable.RScriptVariableGenerater));
foreach (var staticType in Import) foreach (var staticType in Import)
{ {
parser.context.Imports.AddType(staticType); parser.context.Imports.AddType(staticType);