Skip to content

Commit

Permalink
Merge pull request #267 from wledfor2/caseoptions
Browse files Browse the repository at this point in the history
Added Options to control "fuzzy" matching of userdata methods, etc
  • Loading branch information
LimpingNinja committed Jan 15, 2020
2 parents af8b2a7 + c2ed234 commit 4e748a7
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 32 deletions.
Expand Up @@ -233,18 +233,18 @@ public virtual DynValue Index(Script script, object obj, DynValue index, bool is
return null;

DynValue v = TryIndex(script, obj, index.String);
if (v == null) v = TryIndex(script, obj, UpperFirstLetter(index.String));
if (v == null) v = TryIndex(script, obj, Camelify(index.String));
if (v == null) v = TryIndex(script, obj, UpperFirstLetter(Camelify(index.String)));
if (v == null && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.UpperFirstLetter) == FuzzySymbolMatchingBehavior.UpperFirstLetter) v = TryIndex(script, obj, UpperFirstLetter(index.String));
if (v == null && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.Camelify) == FuzzySymbolMatchingBehavior.Camelify) v = TryIndex(script, obj, Camelify(index.String));
if (v == null && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.PascalCase) == FuzzySymbolMatchingBehavior.PascalCase) v = TryIndex(script, obj, UpperFirstLetter(Camelify(index.String)));

if (v == null && m_ExtMethodsVersion < UserData.GetExtensionMethodsChangeVersion())
{
m_ExtMethodsVersion = UserData.GetExtensionMethodsChangeVersion();

v = TryIndexOnExtMethod(script, obj, index.String);
if (v == null) v = TryIndexOnExtMethod(script, obj, UpperFirstLetter(index.String));
if (v == null) v = TryIndexOnExtMethod(script, obj, Camelify(index.String));
if (v == null) v = TryIndexOnExtMethod(script, obj, UpperFirstLetter(Camelify(index.String)));
if (v == null && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.UpperFirstLetter) == FuzzySymbolMatchingBehavior.UpperFirstLetter) v = TryIndexOnExtMethod(script, obj, UpperFirstLetter(index.String));
if (v == null && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.Camelify) == FuzzySymbolMatchingBehavior.Camelify) v = TryIndexOnExtMethod(script, obj, Camelify(index.String));
if (v == null && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.PascalCase) == FuzzySymbolMatchingBehavior.PascalCase) v = TryIndexOnExtMethod(script, obj, UpperFirstLetter(Camelify(index.String)));
}

return v;
Expand Down Expand Up @@ -344,9 +344,9 @@ public virtual bool SetIndex(Script script, object obj, DynValue index, DynValue
return false;

bool v = TrySetIndex(script, obj, index.String, value);
if (!v) v = TrySetIndex(script, obj, UpperFirstLetter(index.String), value);
if (!v) v = TrySetIndex(script, obj, Camelify(index.String), value);
if (!v) v = TrySetIndex(script, obj, UpperFirstLetter(Camelify(index.String)), value);
if (!v && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.UpperFirstLetter) == FuzzySymbolMatchingBehavior.UpperFirstLetter) v = TrySetIndex(script, obj, UpperFirstLetter(index.String), value);
if (!v && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.Camelify) == FuzzySymbolMatchingBehavior.Camelify) v = TrySetIndex(script, obj, Camelify(index.String), value);
if (!v && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.PascalCase) == FuzzySymbolMatchingBehavior.PascalCase) v = TrySetIndex(script, obj, UpperFirstLetter(Camelify(index.String)), value);

return v;
}
Expand Down
6 changes: 3 additions & 3 deletions src/MoonSharp.Interpreter/Interop/PropertyTableAssigner.cs
Expand Up @@ -182,9 +182,9 @@ private bool TryAssignProperty(object obj, string name, DynValue value)
private void AssignProperty(object obj, string name, DynValue value)
{
if (TryAssignProperty(obj, name, value)) return;
if (TryAssignProperty(obj, DescriptorHelpers.UpperFirstLetter(name), value)) return;
if (TryAssignProperty(obj, DescriptorHelpers.Camelify(name), value)) return;
if (TryAssignProperty(obj, DescriptorHelpers.UpperFirstLetter(DescriptorHelpers.Camelify(name)), value)) return;
if ((Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.UpperFirstLetter) == FuzzySymbolMatchingBehavior.UpperFirstLetter && TryAssignProperty(obj, DescriptorHelpers.UpperFirstLetter(name), value)) return;
if ((Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.Camelify) == FuzzySymbolMatchingBehavior.Camelify && TryAssignProperty(obj, DescriptorHelpers.Camelify(name), value)) return;
if ((Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.PascalCase) == FuzzySymbolMatchingBehavior.PascalCase && TryAssignProperty(obj, DescriptorHelpers.UpperFirstLetter(DescriptorHelpers.Camelify(name)), value)) return;

throw new ScriptRuntimeException("Invalid property {0}", name);
}
Expand Down
Expand Up @@ -302,6 +302,7 @@
<Compile Include="Loaders\FileSystemScriptLoader.cs" />
<Compile Include="Loaders\InvalidScriptLoader.cs" />
<Compile Include="Options\ColonOperatorBehaviour.cs" />
<Compile Include="Options\FuzzySymbolMatchingBehavior.cs" />
<Compile Include="Platforms\DotNetCorePlatformAccessor.cs" />
<Compile Include="REPL\ReplHistoryNavigator.cs" />
<Compile Include="REPL\ReplInterpreterScriptLoader.cs" />
Expand Down
27 changes: 27 additions & 0 deletions src/MoonSharp.Interpreter/Options/FuzzySymbolMatchingBehavior.cs
@@ -0,0 +1,27 @@
using System;

namespace MoonSharp.Interpreter {

/// <summary>
/// A flag that controls if/how symbols (method, property, userdata) are fuzzily matched when they do not exist. Flags can be combined for multiple checks.
/// </summary>
[Flags]
public enum FuzzySymbolMatchingBehavior {

/// <summary>No fuzzy matching is performed.</summary>
None = 0,

/// <summary>The first letter of a symbol will be uppercased (to check for common C# naming conventions). For example, testMethod() becomes TestMethod()</summary>
UpperFirstLetter = 1,

/// <summary>Underscores in symbols are converted to camelcase. For example, test_method() becomes testMethod()</summary>
Camelify = 2,

/// <summary>
/// Converts a symbol to pascal case. For example, test_Method_two() becomes TestMethodTwo()
/// </summary>
PascalCase = 4

}

}
16 changes: 12 additions & 4 deletions src/MoonSharp.Interpreter/ScriptGlobalOptions.cs
@@ -1,18 +1,18 @@
using MoonSharp.Interpreter.Interop;
using MoonSharp.Interpreter.Platforms;
using MoonSharp.Interpreter;

namespace MoonSharp.Interpreter
{
/// <summary>
/// Class containing script global options, that is options which cannot be customized per-script.
/// <see cref="Script.GlobalOptions"/>
/// </summary>
public class ScriptGlobalOptions
{
internal ScriptGlobalOptions()
{
public class ScriptGlobalOptions {
internal ScriptGlobalOptions() {
Platform = PlatformAutoDetector.GetDefaultPlatform();
CustomConverters = new CustomConvertersCollection();
FuzzySymbolMatching = FuzzySymbolMatchingBehavior.Camelify | FuzzySymbolMatchingBehavior.UpperFirstLetter | FuzzySymbolMatchingBehavior.PascalCase;
}

/// <summary>
Expand All @@ -33,5 +33,13 @@ internal ScriptGlobalOptions()
/// re-thrown as nested exceptions.
/// </summary>
public bool RethrowExceptionNested { get; set; }

/// <summary>
/// Gets or sets an enum that controls behaviour when a symbol (method, property, userdata) is not found in a userdata's descriptor. For instance,
/// when this value is <see cref="FuzzySymbolMatchingBehavior.UpperFirstLetter"/> and Lua code calls the non-existent method <c>someuserdata.someMethod()</c>,
/// <c>someuserdata.SomeMethod()</c> will also be tried.
/// </summary>
public FuzzySymbolMatchingBehavior FuzzySymbolMatching { get; set; }

}
}
Expand Up @@ -576,6 +576,9 @@
<Compile Include="..\..\Options\ColonOperatorBehaviour.cs">
<Link>ColonOperatorBehaviour.cs</Link>
</Compile>
<Compile Include="..\..\Options\FuzzySymbolMatchingBehavior.cs">
<Link>FuzzySymbolMatchingBehaviour.cs</Link>
</Compile>
<Compile Include="..\..\Platforms\DotNetCorePlatformAccessor.cs">
<Link>DotNetCorePlatformAccessor.cs</Link>
</Compile>
Expand Down
Expand Up @@ -233,18 +233,18 @@ public virtual DynValue Index(Script script, object obj, DynValue index, bool is
return null;

DynValue v = TryIndex(script, obj, index.String);
if (v == null) v = TryIndex(script, obj, UpperFirstLetter(index.String));
if (v == null) v = TryIndex(script, obj, Camelify(index.String));
if (v == null) v = TryIndex(script, obj, UpperFirstLetter(Camelify(index.String)));
if (v == null && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.UpperFirstLetter) == FuzzySymbolMatchingBehavior.UpperFirstLetter) v = TryIndex(script, obj, UpperFirstLetter(index.String));
if (v == null && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.Camelify) == FuzzySymbolMatchingBehavior.Camelify) v = TryIndex(script, obj, Camelify(index.String));
if (v == null && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.PascalCase) == FuzzySymbolMatchingBehavior.PascalCase) v = TryIndex(script, obj, UpperFirstLetter(Camelify(index.String)));

if (v == null && m_ExtMethodsVersion < UserData.GetExtensionMethodsChangeVersion())
{
m_ExtMethodsVersion = UserData.GetExtensionMethodsChangeVersion();

v = TryIndexOnExtMethod(script, obj, index.String);
if (v == null) v = TryIndexOnExtMethod(script, obj, UpperFirstLetter(index.String));
if (v == null) v = TryIndexOnExtMethod(script, obj, Camelify(index.String));
if (v == null) v = TryIndexOnExtMethod(script, obj, UpperFirstLetter(Camelify(index.String)));
if (v == null && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.UpperFirstLetter) == FuzzySymbolMatchingBehavior.UpperFirstLetter) v = TryIndexOnExtMethod(script, obj, UpperFirstLetter(index.String));
if (v == null && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.Camelify) == FuzzySymbolMatchingBehavior.Camelify) v = TryIndexOnExtMethod(script, obj, Camelify(index.String));
if (v == null && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.PascalCase) == FuzzySymbolMatchingBehavior.PascalCase) v = TryIndexOnExtMethod(script, obj, UpperFirstLetter(Camelify(index.String)));
}

return v;
Expand Down Expand Up @@ -344,9 +344,9 @@ public virtual bool SetIndex(Script script, object obj, DynValue index, DynValue
return false;

bool v = TrySetIndex(script, obj, index.String, value);
if (!v) v = TrySetIndex(script, obj, UpperFirstLetter(index.String), value);
if (!v) v = TrySetIndex(script, obj, Camelify(index.String), value);
if (!v) v = TrySetIndex(script, obj, UpperFirstLetter(Camelify(index.String)), value);
if (!v && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.UpperFirstLetter) == FuzzySymbolMatchingBehavior.UpperFirstLetter) v = TrySetIndex(script, obj, UpperFirstLetter(index.String), value);
if (!v && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.Camelify) == FuzzySymbolMatchingBehavior.Camelify) v = TrySetIndex(script, obj, Camelify(index.String), value);
if (!v && (Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.PascalCase) == FuzzySymbolMatchingBehavior.PascalCase) v = TrySetIndex(script, obj, UpperFirstLetter(Camelify(index.String)), value);

return v;
}
Expand Down
Expand Up @@ -182,9 +182,9 @@ private bool TryAssignProperty(object obj, string name, DynValue value)
private void AssignProperty(object obj, string name, DynValue value)
{
if (TryAssignProperty(obj, name, value)) return;
if (TryAssignProperty(obj, DescriptorHelpers.UpperFirstLetter(name), value)) return;
if (TryAssignProperty(obj, DescriptorHelpers.Camelify(name), value)) return;
if (TryAssignProperty(obj, DescriptorHelpers.UpperFirstLetter(DescriptorHelpers.Camelify(name)), value)) return;
if ((Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.UpperFirstLetter) == FuzzySymbolMatchingBehavior.UpperFirstLetter && TryAssignProperty(obj, DescriptorHelpers.UpperFirstLetter(name), value)) return;
if ((Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.Camelify) == FuzzySymbolMatchingBehavior.Camelify && TryAssignProperty(obj, DescriptorHelpers.Camelify(name), value)) return;
if ((Script.GlobalOptions.FuzzySymbolMatching & FuzzySymbolMatchingBehavior.PascalCase) == FuzzySymbolMatchingBehavior.PascalCase && TryAssignProperty(obj, DescriptorHelpers.UpperFirstLetter(DescriptorHelpers.Camelify(name)), value)) return;

throw new ScriptRuntimeException("Invalid property {0}", name);
}
Expand Down
@@ -0,0 +1,27 @@
using System;

namespace MoonSharp.Interpreter {

/// <summary>
/// A flag that controls if/how symbols (method, property, userdata) are fuzzily matched when they do not exist. Flags can be combined for multiple checks.
/// </summary>
[Flags]
public enum FuzzySymbolMatchingBehavior {

/// <summary>No fuzzy matching is performed.</summary>
None = 0,

/// <summary>The first letter of a symbol will be uppercased (to check for common C# naming conventions). For example, testMethod() becomes TestMethod()</summary>
UpperFirstLetter = 1,

/// <summary>Underscores in symbols are converted to camelcase. For example, test_method() becomes testMethod()</summary>
Camelify = 2,

/// <summary>
/// Converts a symbol to pascal case. For example, test_Method_two() becomes TestMethodTwo()
/// </summary>
PascalCase = 4

}

}
@@ -1,18 +1,18 @@
using MoonSharp.Interpreter.Interop;
using MoonSharp.Interpreter.Platforms;
using MoonSharp.Interpreter;

namespace MoonSharp.Interpreter
{
/// <summary>
/// Class containing script global options, that is options which cannot be customized per-script.
/// <see cref="Script.GlobalOptions"/>
/// </summary>
public class ScriptGlobalOptions
{
internal ScriptGlobalOptions()
{
public class ScriptGlobalOptions {
internal ScriptGlobalOptions() {
Platform = PlatformAutoDetector.GetDefaultPlatform();
CustomConverters = new CustomConvertersCollection();
FuzzySymbolMatching = FuzzySymbolMatchingBehavior.Camelify | FuzzySymbolMatchingBehavior.UpperFirstLetter | FuzzySymbolMatchingBehavior.PascalCase;
}

/// <summary>
Expand All @@ -33,5 +33,13 @@ internal ScriptGlobalOptions()
/// re-thrown as nested exceptions.
/// </summary>
public bool RethrowExceptionNested { get; set; }

/// <summary>
/// Gets or sets an enum that controls behaviour when a symbol (method, property, userdata) is not found in a userdata's descriptor. For instance,
/// when this value is <see cref="FuzzySymbolMatchingBehavior.UpperFirstLetter"/> and Lua code calls the non-existent method <c>someuserdata.someMethod()</c>,
/// <c>someuserdata.SomeMethod()</c> will also be tried.
/// </summary>
public FuzzySymbolMatchingBehavior FuzzySymbolMatching { get; set; }

}
}
Expand Up @@ -573,6 +573,9 @@
<Compile Include="..\..\Options\ColonOperatorBehaviour.cs">
<Link>ColonOperatorBehaviour.cs</Link>
</Compile>
<Compile Include="..\..\Options\FuzzySymbolMatchingBehavior.cs">
<Link>FuzzySymbolMatchingBehavior.cs</Link>
</Compile>
<Compile Include="..\..\Platforms\DotNetCorePlatformAccessor.cs">
<Link>DotNetCorePlatformAccessor.cs</Link>
</Compile>
Expand Down

0 comments on commit 4e748a7

Please sign in to comment.