diff --git a/DoRunner/DefineVariableRunner.cs b/DoRunner/DefineVariableRunner.cs index 54e92a9..15d10b4 100644 --- a/DoRunner/DefineVariableRunner.cs +++ b/DoRunner/DefineVariableRunner.cs @@ -79,7 +79,7 @@ namespace Convention.RScript.Runner if (varTypeName == "string") { varType = typeof(string); - varDefaultValue = varInitExpression == null ? string.Empty : varInitExpression; + varDefaultValue = varInitExpression == null ? string.Empty : varInitExpression.Trim('\"'); } else if (varTypeName == "int") { diff --git a/DoRunner/ExitNamespaceRunner.cs b/DoRunner/ExitNamespaceRunner.cs index 5303372..bb1e3ec 100644 --- a/DoRunner/ExitNamespaceRunner.cs +++ b/DoRunner/ExitNamespaceRunner.cs @@ -22,7 +22,14 @@ namespace Convention.RScript.Runner // 还原上层命名空间的变量 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(); // 弹栈 diff --git a/Parser/ExpressionParser.cs b/Parser/ExpressionParser.cs index 393f390..4e717fa 100644 --- a/Parser/ExpressionParser.cs +++ b/Parser/ExpressionParser.cs @@ -97,6 +97,14 @@ namespace Convention.RScript.Parser this.context = context; // 默认启用未定义标识符作为字符串的功能 this.context.Options.UndefinedIdentifiersAsStrings = true; + // 启用大小写敏感 + this.context.Options.CaseSensitive = true; + // 启用溢出检查 + this.context.Options.Checked = true; +#if UNITY_EDITOR + // 浮点数使用float而非double(Unity性能优化) + this.context.Options.RealLiteralDataType = RealLiteralDataType.Single; +#endif } private readonly Dictionary CompileGenericExpressionTypen = new(); diff --git a/PublicTypes/InjectVariable/CStyle.cs b/PublicTypes/InjectVariable/CStyle.cs index ac35096..5989ceb 100644 --- a/PublicTypes/InjectVariable/CStyle.cs +++ b/PublicTypes/InjectVariable/CStyle.cs @@ -11,6 +11,20 @@ namespace Convention.RScript.Variable.CStyle { 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('`', '_'); return name; } @@ -102,7 +116,7 @@ namespace Convention.RScript.Variable.CStyle protected override string WritePageHead(Type currentType) { - return $"#include\"{GetFilename(currentType)}\""; + return $"#include\"{GetFilename(currentType.BaseType)}\""; } public override string GetFilename(Type currentType) diff --git a/PublicTypes/RScriptInjectVariableGenerater.cs b/PublicTypes/RScriptInjectVariableGenerater.cs index f1f23d1..7d0e349 100644 --- a/PublicTypes/RScriptInjectVariableGenerater.cs +++ b/PublicTypes/RScriptInjectVariableGenerater.cs @@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Reflection; using System.Text; +using UnityEditor; namespace Convention.RScript.Variable { @@ -115,44 +116,59 @@ namespace Convention.RScript.Variable StringBuilder builder = new(); builder.AppendLine(this.WritePageHead(targetType)); - builder.AppendLine(this.WriteClassHead(targetType)); - builder.AppendLine(this.WriteClassBodyEnter(targetType)); - // 绘制枚举 + if (targetType.IsEnum) { - var scriptEnums = from enumItem in targetType.GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Public) - where enumItem.GetCustomAttribute() != null - select enumItem; - foreach (var enumItem in scriptEnums) + // 绘制枚举 + builder.AppendLine(this.WriteEnumHead(targetType)); + builder.AppendLine(this.WriteEnumBodyEnter(targetType)); + foreach (var enumName in targetType.GetEnumNames()) { - var attr = enumItem.GetCustomAttribute(); - this.WriteEnumHead(targetType); - this.WriteEnumBodyEnter(targetType); - foreach (var enumName in enumItem.GetEnumNames()) + builder.AppendLine(this.WriteEnumName(enumName)); + } + builder.AppendLine(this.WriteEnumBodyExit(targetType)); + 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() != null + select enumItem; + foreach (var enumItem in scriptEnums) { - this.WriteEnumName(enumName); + var attr = enumItem.GetCustomAttribute(); + 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() != null - select method; - foreach (var method in scriptMethods) + // 绘制方法 { - var attr = method.GetCustomAttribute(); - 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())); + var scriptMethods = from method in targetType.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly) + where method.GetCustomAttribute() != null + select method; + foreach (var method in scriptMethods) + { + var attr = method.GetCustomAttribute(); + 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)); this.scriptIndicator = builder.ToString(); } @@ -173,20 +189,54 @@ namespace Convention.RScript.Variable 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) { if (AllRScriptInjectVariables.TryGetValue(name, out var variable)) { - if (variable.MyGenerater != null) + if (variable.targetType.IsEnum) { - var result = variable.Generate(); - if (result.GetType().IsSubclassOf(variable.targetType) || result.GetType() == variable.targetType) + if (variable.MyGenerater != null) { - variable.GenerateObjects.Add(result); - return result; + 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"); } 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"); diff --git a/PublicTypes/RScriptVariables.cs b/PublicTypes/RScriptVariables.cs index a585855..bcf3555 100644 --- a/PublicTypes/RScriptVariables.cs +++ b/PublicTypes/RScriptVariables.cs @@ -32,7 +32,7 @@ namespace Convention.RScript else internalData = Activator.CreateInstance(type); } - else if (type == typeof(object) || type == value.GetType()) + else if (type == typeof(object) || type.IsAssignableFrom(value.GetType())) internalData = value; else internalData = Convert.ChangeType(value, type); diff --git a/RScriptContext.cs b/RScriptContext.cs index b90ea34..78429a9 100644 --- a/RScriptContext.cs +++ b/RScriptContext.cs @@ -6,6 +6,7 @@ using System.Collections; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.Linq; +using UnityEngine; using static Convention.RScript.RScriptContext; namespace Convention.RScript @@ -283,10 +284,12 @@ namespace Convention.RScript } catch (RScriptException) { + Debug.LogError($"current sentence: {sentence}"); throw; } catch (Exception ex) { + Debug.LogError($"current sentence: {sentence}"); throw new RScriptRuntimeException($"Runtime error: {ex.Message}", CurrentRuntimePointer, ex); } }