Skip to content

Commit

Permalink
Bugfixes and improvements for the previous commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
Uralstech committed Nov 3, 2024
1 parent 0394832 commit 5ed4199
Show file tree
Hide file tree
Showing 16 changed files with 128 additions and 88 deletions.
7 changes: 6 additions & 1 deletion src/Executor/CodeExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ public static class CodeExecutor
/// </summary>
public static readonly Interpreter Interpreter = new();

/// <summary>
/// The static <see cref="Runtime.RuntimeResult"/> of <see cref="Interpreter"/>.
/// </summary>
public static RuntimeResult RuntimeResult => Interpreter.RuntimeResult;

/// <summary>
/// The runtime context, may be <see langword="null"/>.
/// </summary>
Expand All @@ -40,7 +45,7 @@ public static void CreateRuntimeContext(string filePath)
/// Use <see cref="CreateRuntimeContext(string)"/> to initialize the runtime context.
/// </exception>
/// <param name="excludeIO">Exclude built-in I/O functions like <see cref="EzrBuiltinFunctions.Show(Runtime.WrapperAttributes.SharpMethodParameters)"/>?</param>
public static void PopulateRuntimeContext(bool excludeIO=false)
public static void PopulateRuntimeContext(bool excludeIO = false)
{
if (RuntimeContext is null)
throw new NullReferenceException($"{nameof(RuntimeContext)} is null! Call {nameof(CreateRuntimeContext)} to create it!");
Expand Down
1 change: 1 addition & 0 deletions src/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
[assembly: SuppressMessage("Style", "IDE0078:Use pattern matching", Justification = "Recommended fix breaks code.", Scope = "member", Target = "~M:EzrSquared.Runtime.Types.Core.Text.EzrCharacterList.Multiplication(EzrSquared.Runtime.Types.IEzrObject,EzrSquared.Runtime.RuntimeResult)")]
[assembly: SuppressMessage("Style", "IDE0078:Use pattern matching", Justification = "Recommended fix breaks code.", Scope = "member", Target = "~M:EzrSquared.Runtime.Types.Collections.EzrList.Multiplication(EzrSquared.Runtime.Types.IEzrObject,EzrSquared.Runtime.RuntimeResult)")]
[assembly: SuppressMessage("Style", "IDE0078:Use pattern matching", Justification = "Recommended fix breaks code.", Scope = "member", Target = "~M:EzrSquared.Runtime.Types.Core.Text.EzrString.Multiplication(EzrSquared.Runtime.Types.IEzrObject,EzrSquared.Runtime.RuntimeResult)")]
[assembly: SuppressMessage("Style", "IDE0046:Convert to conditional expression", Justification = "That's too many ternary operations.", Scope = "member", Target = "~M:EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.EzrSharpCompatibilityWrapper.Validate~System.Boolean")]
4 changes: 2 additions & 2 deletions src/Runtime/Collections/RuntimeEzrObjectDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public class RuntimeEzrObjectDictionary : IMutable<RuntimeEzrObjectDictionary>
/// <summary>
/// The number of <see cref="IEzrObject"/>s in the <see cref="RuntimeEzrObjectDictionary"/>.
/// </summary>
[SharpAutoWrapper(IsReadOnly = true)]
[SharpAutoWrapper(isReadOnly: true)]
public int Length => _items.Count;

/// <summary>
Expand Down Expand Up @@ -103,7 +103,7 @@ public bool Remove(IEzrObject key, RuntimeResult result)
/// </remarks>
/// <param name="key">The key (hash) to be removed.</param>
/// <returns><see langword="true"/> if the operation was successful, <see langword="false"/> if not.</returns>
[SharpAutoWrapper(Name = "remove_by_hash")]
[SharpAutoWrapper("remove_by_hash")]
public bool RemoveHash(int key)
{
return _items.Remove(key);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers;
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers.Executables;
using EzrSquared.Runtime.WrapperAttributes;
using EzrSquared.Util;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -29,7 +30,6 @@ public class EzrSharpCompatibilityObjectInstance : EzrSharpCompatibilityWrapper
/// </summary>
/// <param name="instance">The object to wrap.</param>
/// <param name="instanceType">The C# object's type.</param>
/// <param name="result">Runtime result for carrying any errors.</param>
/// <param name="parentContext">The context in which this object was created.</param>
/// <param name="startPosition">The starting position of the object.</param>
/// <param name="endPosition">The ending position of the object.</param>
Expand All @@ -45,20 +45,24 @@ public EzrSharpCompatibilityObjectInstance(
| DynamicallyAccessedMemberTypes.NonPublicFields)]
Type instanceType,

RuntimeResult result, Context parentContext, Position startPosition, Position endPosition) : base(instanceType, parentContext, startPosition, endPosition)
Context parentContext, Position startPosition, Position endPosition) : base(instanceType, parentContext, startPosition, endPosition)
{
Instance = instance;
Tag = $"{Tag}.{SharpMemberName}.{Utils.GetNextUniqueId()}";

MethodInfo[] publicMethods = instanceType.GetMethods(BindingFlags.Public | BindingFlags.Instance);
Dictionary<string, int> duplicateNames = new(publicMethods.Length);
for (int i = 0; i < publicMethods.Length; i++)
MethodInfo[] allMethods = instanceType.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
Dictionary<string, int> duplicateNames = new(allMethods.Length);
for (int i = 0; i < allMethods.Length; i++)
{
MethodInfo method = publicMethods[i];
if (method.IsAbstract)
MethodInfo method = allMethods[i];
if (method.IsAbstract || (!method.IsPublic && method.GetCustomAttribute<SharpAutoWrapperAttribute>() is null))
continue;

string methodObjectName = Utils.PascalToSnakeCase(method.Name);
EzrSharpCompatibilityFunction methodObject = new(method, Instance, Context, StartPosition, EndPosition, skipValidation: true);
if (!methodObject.Validate())
continue;

string methodObjectName = methodObject.SharpMemberName;
if (duplicateNames.TryGetValue(method.Name, out int duplicates))
{
methodObjectName += $"_{duplicates}";
Expand All @@ -67,31 +71,35 @@ public EzrSharpCompatibilityObjectInstance(
else
duplicateNames.Add(method.Name, 1);

EzrSharpCompatibilityFunction methodObject = new(method, Instance, Context, StartPosition, EndPosition);
if (methodObject.Validate(result))
return;

Context.Set(null, methodObjectName, ReferencePool.Get(methodObject, AccessMod.Constant));
}

PropertyInfo[] publicProperties = instanceType.GetProperties(BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < publicProperties.Length; i++)
PropertyInfo[] allProperties = instanceType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
for (int i = 0; i < allProperties.Length; i++)
{
EzrSharpCompatibilityProperty property = new(publicProperties[i], Instance, Context, StartPosition, EndPosition);
if (property.Validate(result))
return;
PropertyInfo property = allProperties[i];
if (property.GetMethod?.IsPublic != true && property.SetMethod?.IsPublic != true && property.GetCustomAttribute<SharpAutoWrapperAttribute>() is null)
continue;

Context.Set(null, property.SharpMemberName, ReferencePool.Get(property, AccessMod.Constant));
EzrSharpCompatibilityProperty propertyObject = new(property, Instance, Context, StartPosition, EndPosition, skipValidation: true);
if (!propertyObject.Validate())
continue;

Context.Set(null, propertyObject.SharpMemberName, ReferencePool.Get(propertyObject, AccessMod.Constant));
}

FieldInfo[] publicFields = instanceType.GetFields(BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < publicFields.Length; i++)
FieldInfo[] allFields = instanceType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
for (int i = 0; i < allFields.Length; i++)
{
EzrSharpCompatibilityField field = new(publicFields[i], Instance, Context, StartPosition, EndPosition);
if (field.Validate(result))
return;
FieldInfo field = allFields[i];
if (!field.IsPublic && field.GetCustomAttribute<SharpAutoWrapperAttribute>() is null)
continue;

EzrSharpCompatibilityField fieldObject = new(field, Instance, Context, StartPosition, EndPosition, skipValidation: true);
if (!fieldObject.Validate())
continue;

Context.Set(null, field.SharpMemberName, ReferencePool.Get(field, AccessMod.Constant));
Context.Set(null, fieldObject.SharpMemberName, ReferencePool.Get(fieldObject, AccessMod.Constant));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,11 @@ public EzrSharpCompatibilityType(
if (method.IsAbstract || (!method.IsPublic && method.GetCustomAttribute<SharpAutoWrapperAttribute>() is null))
continue;

string methodObjectName = Utils.PascalToSnakeCase(method.Name);
EzrSharpCompatibilityFunction methodObject = new(method, null, Context, StartPosition, EndPosition, skipValidation: true);
if (!methodObject.Validate())
continue;

string methodObjectName = methodObject.SharpMemberName;
if (duplicateNames.TryGetValue(method.Name, out int duplicates))
{
methodObjectName += $"_{duplicates}";
Expand All @@ -83,10 +87,6 @@ public EzrSharpCompatibilityType(
else
duplicateNames.Add(method.Name, 1);

EzrSharpCompatibilityFunction methodObject = new(method, null, Context, StartPosition, EndPosition);
if (!methodObject.Validate(result))
return;

Context.Set(null, methodObjectName, ReferencePool.Get(methodObject, AccessMod.Constant));
}

Expand All @@ -97,9 +97,9 @@ public EzrSharpCompatibilityType(
if (property.GetMethod?.IsPublic != true && property.SetMethod?.IsPublic != true && property.GetCustomAttribute<SharpAutoWrapperAttribute>() is null)
continue;

EzrSharpCompatibilityProperty propertyObject = new(property, null, Context, StartPosition, EndPosition);
if (!propertyObject.Validate(result))
return;
EzrSharpCompatibilityProperty propertyObject = new(property, null, Context, StartPosition, EndPosition, skipValidation: true);
if (!propertyObject.Validate())
continue;

Context.Set(null, propertyObject.SharpMemberName, ReferencePool.Get(propertyObject, AccessMod.Constant));
}
Expand All @@ -111,9 +111,9 @@ public EzrSharpCompatibilityType(
if (!field.IsPublic && field.GetCustomAttribute<SharpAutoWrapperAttribute>() is null)
continue;

EzrSharpCompatibilityField fieldObject = new(field, null, Context, StartPosition, EndPosition);
if (!fieldObject.Validate(result))
return;
EzrSharpCompatibilityField fieldObject = new(field, null, Context, StartPosition, EndPosition, skipValidation: true);
if (!fieldObject.Validate())
continue;

Context.Set(null, fieldObject.SharpMemberName, ReferencePool.Get(fieldObject, AccessMod.Constant));
}
Expand All @@ -122,12 +122,12 @@ public EzrSharpCompatibilityType(
for (int i = 0; i < publicConstructors.Length; i++)
{
ConstructorInfo constructor = publicConstructors[i];
if (!constructor.IsPublic)
if (!constructor.IsPublic && constructor.GetCustomAttribute<SharpAutoWrapperAttribute>() is null)
continue;

EzrSharpCompatibilityConstructor constructorObject = new(this, constructor, Context, StartPosition, EndPosition);
if (constructorObject.Validate(result))
return;
EzrSharpCompatibilityConstructor constructorObject = new(this, constructor, Context, StartPosition, EndPosition, skipValidation: true);
if (!constructorObject.Validate())
continue;

Context.Set(null, $"make_{i}", ReferencePool.Get(constructorObject, AccessMod.Constant));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers;
Expand Down Expand Up @@ -48,25 +49,42 @@ public EzrSharpCompatibilityWrapper(MemberInfo wrappedMember, Context parentCont
{
SharpMember = wrappedMember;
AutoWrapperAttribute = wrappedMember.GetCustomAttribute<SharpAutoWrapperAttribute>();
SharpMemberName = !string.IsNullOrEmpty(AutoWrapperAttribute?.Name) ? AutoWrapperAttribute.Name : Utils.PascalToSnakeCase(wrappedMember.Name);
SharpMemberName = !string.IsNullOrEmpty(AutoWrapperAttribute?.Name) ? AutoWrapperAttribute.Name : PascalToSnakeCase(wrappedMember.Name);
}

/// <summary>
/// Validates the the current object for wrapping.
/// </summary>
/// <param name="result">Optional runtime result for carrying runtime errors.</param>
/// <returns><see langword="true"/> if the member can be wrapped, <see langword="false"/> otherwise.</returns>
public bool Validate(RuntimeResult? result=null)
public bool Validate()
{
Exception? validationException = SharpAutoWrapperAttribute.Validate(SharpMember);
if (validationException is null)
return true;

if (AutoWrapperAttribute is not null)
throw validationException;
return AutoWrapperAttribute is not null ? throw validationException : false;
}

/// <summary>
/// Converts a string from PascalCase to snake_case.
/// </summary>
/// <param name="text">The text to convert in PascalCase.</param>
/// <returns>The converted text in snake_case.</returns>
internal protected static string PascalToSnakeCase(string text)
{
StringBuilder result = new();
result.Append(char.ToLowerInvariant(text[0]));

for (int i = 1; i < text.Length; ++i)
{
char c = text[i];
if (char.IsUpper(c))
result.Append('_').Append(char.ToLowerInvariant(c));
else
result.Append(c);
}

result?.Failure(new EzrUnsupportedWrappingError($"C# type member \"{SharpMemberName}\" cannot be wrapped into an ezr² type!", Context, StartPosition, EndPosition));
return false;
return result.ToString();
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers.E
/// <param name="startPosition">The starting position of the object.</param>
/// <param name="endPosition">The ending position of the object.</param>
/// <param name="skipValidation">Skip method signature validation?</param>
public class EzrSharpCompatibilityConstructor(EzrSharpCompatibilityType constructingTypeWrapper, ConstructorInfo sharpConstructor, Context parentContext, Position startPosition, Position endPosition, bool skipValidation=false) : EzrSharpCompatibilityExecutable(sharpConstructor, null, parentContext, startPosition, endPosition, skipValidation)
public class EzrSharpCompatibilityConstructor(EzrSharpCompatibilityType constructingTypeWrapper, ConstructorInfo sharpConstructor, Context parentContext, Position startPosition, Position endPosition, bool skipValidation = false) : EzrSharpCompatibilityExecutable(sharpConstructor, null, parentContext, startPosition, endPosition, skipValidation)
{
/// <summary>
/// The wrapper for this C# constructor's class.
Expand All @@ -40,7 +40,7 @@ public override void Execute(Reference[] arguments, Interpreter interpreter, Run
result.Success(NewNothingConstant());
else
{
IEzrObject wrapper = new EzrSharpCompatibilityObjectInstance(output, ConstructingTypeWrapper.SharpType, result, _executionContext, StartPosition, EndPosition);
IEzrObject wrapper = new EzrSharpCompatibilityObjectInstance(output, ConstructingTypeWrapper.SharpType, _executionContext, StartPosition, EndPosition);
if (result.ShouldReturn)
return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,13 @@ public EzrSharpCompatibilityExecutable(MethodBase sharpMember, object? instance,

Executable = sharpMember;
Parameters = Executable.GetParameters();
ParameterNames = Array.ConvertAll(Parameters, p => Utils.PascalToSnakeCase(p.Name ?? string.Empty));

ParameterNames = Array.ConvertAll(Parameters, p =>
{
string? definedName = p.GetCustomAttribute<SharpAutoWrapperAttribute>()?.Name;
return string.IsNullOrEmpty(definedName) ? PascalToSnakeCase(p.Name ?? string.Empty) : definedName;
});

Instance = instance;

if (!skipValidation)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers.E
/// <param name="startPosition">The starting position of the object.</param>
/// <param name="endPosition">The ending position of the object.</param>
/// <param name="skipValidation">Skip method signature validation?</param>
public class EzrSharpCompatibilityFunction(MethodInfo sharpFunction, object? instance, Context parentContext, Position startPosition, Position endPosition, bool skipValidation=false) : EzrSharpCompatibilityExecutable(sharpFunction, instance, parentContext, startPosition, endPosition, skipValidation)
public class EzrSharpCompatibilityFunction(MethodInfo sharpFunction, object? instance, Context parentContext, Position startPosition, Position endPosition, bool skipValidation = false) : EzrSharpCompatibilityExecutable(sharpFunction, instance, parentContext, startPosition, endPosition, skipValidation)
{
/// <inheritdoc/>
public override string TypeName { get; protected internal set; } = "csharp function";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using EzrSquared.Runtime.Types.Core.Errors;
using EzrSquared.Runtime.WrapperAttributes;
using EzrSquared.Util;
using System;
using System.Reflection;
Expand Down Expand Up @@ -36,7 +35,7 @@ public class EzrSharpCompatibilityField : EzrSharpCompatibilityWrapper
/// <param name="startPosition">The starting position of the object.</param>
/// <param name="endPosition">The ending position of the object.</param>
/// <param name="skipValidation">Skip field type validation?</param>
public EzrSharpCompatibilityField(FieldInfo sharpField, object? instance, Context parentContext, Position startPosition, Position endPosition, bool skipValidation=false) : base(sharpField, parentContext, startPosition, endPosition)
public EzrSharpCompatibilityField(FieldInfo sharpField, object? instance, Context parentContext, Position startPosition, Position endPosition, bool skipValidation = false) : base(sharpField, parentContext, startPosition, endPosition)
{
SharpField = sharpField;
Instance = instance;
Expand Down Expand Up @@ -85,7 +84,7 @@ public override void Execute(Reference[] arguments, Interpreter interpreter, Run
result.Failure(new EzrIllegalOperationError($"Cannot get value from CSharp field wrapper \"{SharpMemberName}\" as it is write-only!", Context, StartPosition, EndPosition));
break;
}

object? value = SharpField.GetValue(Instance);
CSharpToEzrObject(value, result);
break;
Expand Down
Loading

0 comments on commit 5ed4199

Please sign in to comment.