This commit is contained in:
2025-11-28 15:24:25 +08:00
7 changed files with 122 additions and 40 deletions

View File

@@ -79,7 +79,7 @@ namespace Convention.RScript.Runner
if (varTypeName == "string") if (varTypeName == "string")
{ {
varType = typeof(string); varType = typeof(string);
varDefaultValue = varInitExpression == null ? string.Empty : varInitExpression; varDefaultValue = varInitExpression == null ? string.Empty : varInitExpression.Trim('\"');
} }
else if (varTypeName == "int") else if (varTypeName == "int")
{ {

View File

@@ -22,7 +22,14 @@ namespace Convention.RScript.Runner
// 还原上层命名空间的变量 // 还原上层命名空间的变量
foreach (var local in context.CurrentLocalSpaceVariableNames.Peek()) foreach (var local in context.CurrentLocalSpaceVariableNames.Peek())
{ {
parser.context.Variables[local] = context.Variables[local].data; if (context.Variables.ContainsKey(local))
{
parser.context.Variables[local] = context.Variables[local].data;
}
else
{
parser.context.Variables.Remove(local);
}
} }
context.CurrentLocalSpaceVariableNames.Pop(); context.CurrentLocalSpaceVariableNames.Pop();
// 弹栈 // 弹栈

View File

@@ -97,6 +97,14 @@ namespace Convention.RScript.Parser
this.context = context; this.context = context;
// 默认启用未定义标识符作为字符串的功能 // 默认启用未定义标识符作为字符串的功能
this.context.Options.UndefinedIdentifiersAsStrings = true; this.context.Options.UndefinedIdentifiersAsStrings = true;
// 启用大小写敏感
this.context.Options.CaseSensitive = true;
// 启用溢出检查
this.context.Options.Checked = true;
#if UNITY_EDITOR
// 浮点数使用float而非doubleUnity性能优化
this.context.Options.RealLiteralDataType = RealLiteralDataType.Single;
#endif
} }
private readonly Dictionary<string, Type> CompileGenericExpressionTypen = new(); private readonly Dictionary<string, Type> CompileGenericExpressionTypen = new();

View File

@@ -11,6 +11,20 @@ namespace Convention.RScript.Variable.CStyle
{ {
public static string GetTypename(Type type) public static string GetTypename(Type type)
{ {
if (type == typeof(int))
return "int";
if (type == typeof(float))
return "float";
if (type == typeof(double))
return "double";
if (type == typeof(bool))
return "bool";
if (type == typeof(void))
return "void";
if (type.IsEnum)
return type.FullName.Replace('`', '_');
if (type.IsClass)
return type.FullName.Replace('`', '_');
var name = type.Name.Replace('`', '_'); var name = type.Name.Replace('`', '_');
return name; return name;
} }
@@ -102,7 +116,7 @@ namespace Convention.RScript.Variable.CStyle
protected override string WritePageHead(Type currentType) protected override string WritePageHead(Type currentType)
{ {
return $"#include\"{GetFilename(currentType)}\""; return $"#include\"{GetFilename(currentType.BaseType)}\"";
} }
public override string GetFilename(Type currentType) public override string GetFilename(Type currentType)

View File

@@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using UnityEditor;
namespace Convention.RScript.Variable namespace Convention.RScript.Variable
{ {
@@ -115,44 +116,59 @@ namespace Convention.RScript.Variable
StringBuilder builder = new(); StringBuilder builder = new();
builder.AppendLine(this.WritePageHead(targetType)); builder.AppendLine(this.WritePageHead(targetType));
builder.AppendLine(this.WriteClassHead(targetType)); if (targetType.IsEnum)
builder.AppendLine(this.WriteClassBodyEnter(targetType));
// 绘制枚举
{ {
var scriptEnums = from enumItem in targetType.GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Public) // 绘制枚举
where enumItem.GetCustomAttribute<Attr.EnumAttribute>() != null builder.AppendLine(this.WriteEnumHead(targetType));
select enumItem; builder.AppendLine(this.WriteEnumBodyEnter(targetType));
foreach (var enumItem in scriptEnums) foreach (var enumName in targetType.GetEnumNames())
{ {
var attr = enumItem.GetCustomAttribute<Attr.EnumAttribute>(); builder.AppendLine(this.WriteEnumName(enumName));
this.WriteEnumHead(targetType); }
this.WriteEnumBodyEnter(targetType); builder.AppendLine(this.WriteEnumBodyExit(targetType));
foreach (var enumName in enumItem.GetEnumNames()) builder.AppendLine(this.WriteEnumTail(targetType));
}
else
{
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)
{ {
this.WriteEnumName(enumName); 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);
} }
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 scriptMethods = from method in targetType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly)
var returnType = method.ReturnType; where method.GetCustomAttribute<Attr.MethodAttribute>() != null
var methodName = method.Name; select method;
var parameters = method.GetParameters(); foreach (var method in scriptMethods)
var parameterNames = from item in parameters select item.Name; {
var parameterTypes = from item in parameters select item.ParameterType; var attr = method.GetCustomAttribute<Attr.MethodAttribute>();
builder.AppendLine(this.WriteClassMethod(returnType, methodName, parameterNames.ToArray(), parameterTypes.ToArray())); 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.WriteClassBodyExit(targetType));
builder.AppendLine(this.WriteClassTail(targetType));
builder.AppendLine(this.WritePageEnd(targetType)); builder.AppendLine(this.WritePageEnd(targetType));
this.scriptIndicator = builder.ToString(); this.scriptIndicator = builder.ToString();
} }
@@ -173,20 +189,54 @@ namespace Convention.RScript.Variable
return AllRScriptInjectVariables.Remove(name); return AllRScriptInjectVariables.Remove(name);
} }
public class EnumGetter
{
public Type enumType;
public EnumGetter(Type enumType)
{
this.enumType = enumType;
}
public object Get(string name)
{
return Enum.Parse(enumType, name);
}
}
public static object GenerateRScriptVariable(string name) public static object GenerateRScriptVariable(string name)
{ {
if (AllRScriptInjectVariables.TryGetValue(name, out var variable)) if (AllRScriptInjectVariables.TryGetValue(name, out var variable))
{ {
if (variable.MyGenerater != null) if (variable.targetType.IsEnum)
{ {
var result = variable.Generate(); if (variable.MyGenerater != null)
if (result.GetType().IsSubclassOf(variable.targetType) || result.GetType() == variable.targetType)
{ {
variable.GenerateObjects.Add(result); var result = variable.Generate();
return result; 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");
} }
else else
throw new InvalidOperationException($"{name} target is not sub-class of it's target type"); {
return variable.targetType;
}
}
else
{
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"); throw new InvalidOperationException($"{name} target is not exist or abstract");

View File

@@ -32,7 +32,7 @@ namespace Convention.RScript
else else
internalData = Activator.CreateInstance(type); internalData = Activator.CreateInstance(type);
} }
else if (type == typeof(object) || type == value.GetType()) else if (type == typeof(object) || type.IsAssignableFrom(value.GetType()))
internalData = value; internalData = value;
else else
internalData = Convert.ChangeType(value, type); internalData = Convert.ChangeType(value, type);

View File

@@ -6,6 +6,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using UnityEngine;
using static Convention.RScript.RScriptContext; using static Convention.RScript.RScriptContext;
namespace Convention.RScript namespace Convention.RScript
@@ -283,10 +284,12 @@ namespace Convention.RScript
} }
catch (RScriptException) catch (RScriptException)
{ {
Debug.LogError($"current sentence: {sentence}");
throw; throw;
} }
catch (Exception ex) catch (Exception ex)
{ {
Debug.LogError($"current sentence: {sentence}");
throw new RScriptRuntimeException($"Runtime error: {ex.Message}", CurrentRuntimePointer, ex); throw new RScriptRuntimeException($"Runtime error: {ex.Message}", CurrentRuntimePointer, ex);
} }
} }