Skip to content

Commit

Permalink
Wrapper unification part 2.
Browse files Browse the repository at this point in the history
  • Loading branch information
Uralstech committed Dec 20, 2024
1 parent e3d629e commit c2b908a
Show file tree
Hide file tree
Showing 32 changed files with 307 additions and 999 deletions.
3 changes: 2 additions & 1 deletion src/GlobalSuppressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@
[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", "IDE0078:Use pattern matching", Justification = "Recommended fix breaks code.", Scope = "member", Target = "~M:EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.EzrSharpCompatibilityWrapper`1.EzrObjectToCSharp(EzrSquared.Runtime.Types.IEzrObject,System.Type,EzrSquared.Runtime.RuntimeResult)~System.Object")]
[assembly: SuppressMessage("Style", "IDE0046:Convert to conditional expression", Justification = "Too many ternary operators.", Scope = "member", Target = "~M:EzrSquared.Runtime.WrapperAttributes.SharpAutoWrapperAttribute.ValidateMethod(System.Reflection.MethodBase,System.Boolean)~System.Boolean")]
[assembly: SuppressMessage("Style", "IDE0046:Convert to conditional expression", Justification = "Too many ternary operators.", Scope = "member", Target = "~M:EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.Attributes.WrappedMemberAttribute.ValidateMethod(System.Reflection.MethodBase,System.Boolean)~System.Boolean")]
[assembly: SuppressMessage("Style", "IDE0046:Convert to conditional expression", Justification = "Too many ternary operators.", Scope = "member", Target = "~M:EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.Attributes.WrappedMemberAttribute.ValidateType(System.Type,System.Boolean)~System.Boolean")]
5 changes: 3 additions & 2 deletions src/Runtime/Collections/RuntimeEzrObjectDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using EzrSquared.Runtime.Types.Collections;
using EzrSquared.Runtime.Types.Core.Errors;
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.Attributes;
using EzrSquared.Runtime.WrapperAttributes;
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers.Executables.Attributes;
using System.Collections;
using System.Collections.Generic;

Expand Down Expand Up @@ -192,7 +192,8 @@ public Reference Get(IEzrObject key, RuntimeResult result)
/// <param name="key">The key to be checked.</param>
/// <param name="result">The <see cref="RuntimeResult"/> object for returning errors.</param>
/// <returns><see langword="true"/> if the key was found, <see langword="false"/> if any error occured or the key was not found.</returns>
public bool HasKey(IEzrObject key, RuntimeResult result)
[WrappedMember]
public bool HasKey(IEzrObject key, [Runtime(Feature.ResultRef)] RuntimeResult result)
{
int hash = key.ComputeHashCode(result);
return !result.ShouldReturn && _items.ContainsKey(hash);
Expand Down
6 changes: 3 additions & 3 deletions src/Runtime/Interpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
using EzrSquared.Runtime.Types.Core.Errors;
using EzrSquared.Runtime.Types.Core.Numerics;
using EzrSquared.Runtime.Types.Core.Text;
using EzrSquared.Runtime.Types.CSharpWrappers.SourceWrappers;
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers;
using EzrSquared.Runtime.Types.Executables;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -1174,13 +1174,13 @@ private void VisitTryNode(TryNode node, Context executionContext, Context callin
return;

IEzrObject targetObject = RuntimeResult.Reference.Object;
if (targetObject is not EzrSharpSourceTypeWrapper target || !typeof(IEzrRuntimeError).IsAssignableFrom(target.SharpType))
if (targetObject is not EzrSharpCompatibilityType target || !typeof(IEzrRuntimeError).IsAssignableFrom(target.SharpMember))
{
RuntimeResult.Failure(new EzrUnexpectedTypeError($"Expected error type, but got object of type \"{targetObject.TypeName}\"!", executionContext, errorType.StartPosition, errorType.EndPosition));
return;
}

if (target.SharpType.IsAssignableFrom(error.GetType()))
if (target.SharpMember.IsAssignableFrom(error.GetType()))
{
if (errorVariableNode is not null)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers;
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.Attributes;
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers.Executables.Attributes;
using EzrSquared.Runtime.WrapperAttributes;
using System;
using System.Collections.Generic;
using System.Text;
Expand Down
56 changes: 28 additions & 28 deletions src/Runtime/Types/CSharpWrappers/Builtins/EzrBuiltinsUtility.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using EzrSquared.Runtime.Types.Core;
using EzrSquared.Runtime.Types.Core.Errors;
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers;
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers.Executables;
using EzrSquared.Runtime.Types.CSharpWrappers.SourceWrappers;

namespace EzrSquared.Runtime.Types.CSharpWrappers.Builtins;

Expand Down Expand Up @@ -56,36 +56,36 @@ public static void AddBuiltinIOFunctions(Context context)
/// Adds all built-in types to the given context.
/// </summary>
/// <param name="context">The context to add to.</param>
public static void AddBuiltinTypes(Context context)
public static void AddBuiltinTypes(Context context )
{
EzrSharpSourceTypeWrapper runtimeError = new(typeof(EzrRuntimeError), context, Position.None, Position.None);
context.Set(null, runtimeError.SharpTypeName, ReferencePool.Get(runtimeError, AccessMod.Constant));
EzrSharpCompatibilityType runtimeError = new(typeof(EzrRuntimeError), context, Position.None, Position.None);
context.Set(null, runtimeError.SharpMemberName, ReferencePool.Get(runtimeError, AccessMod.Constant));

EzrSharpSourceTypeWrapper assertionError = new(typeof(EzrAssertionError), context, Position.None, Position.None);
EzrSharpSourceTypeWrapper illegalOperationError = new(typeof(EzrIllegalOperationError), context, Position.None, Position.None);
EzrSharpSourceTypeWrapper keyNotFoundError = new(typeof(EzrKeyNotFoundError), context, Position.None, Position.None);
EzrSharpSourceTypeWrapper mathError = new(typeof(EzrMathError), context, Position.None, Position.None);
EzrSharpSourceTypeWrapper missingRequiredArgumentError = new(typeof(EzrMissingRequiredArgumentError), context, Position.None, Position.None);
EzrSharpSourceTypeWrapper privateMemberOperationError = new(typeof(EzrPrivateMemberOperationError), context, Position.None, Position.None);
EzrSharpSourceTypeWrapper undefinedValueError = new(typeof(EzrUndefinedValueError), context, Position.None, Position.None);
EzrSharpSourceTypeWrapper unexpectedArgumentError = new(typeof(EzrUnexpectedArgumentError), context, Position.None, Position.None);
EzrSharpSourceTypeWrapper unexpectedTypeError = new(typeof(EzrUnexpectedTypeError), context, Position.None, Position.None);
EzrSharpSourceTypeWrapper unsupportedWrappingError = new(typeof(EzrUnsupportedWrappingError), context, Position.None, Position.None);
EzrSharpSourceTypeWrapper valueOutOfRangeError = new(typeof(EzrValueOutOfRangeError), context, Position.None, Position.None);
EzrSharpSourceTypeWrapper wrapperExecutionError = new(typeof(EzrWrapperExecutionError), context, Position.None, Position.None);
EzrSharpCompatibilityType assertionError = new(typeof(EzrAssertionError), context, Position.None, Position.None);
EzrSharpCompatibilityType illegalOperationError = new(typeof(EzrIllegalOperationError), context, Position.None, Position.None);
EzrSharpCompatibilityType keyNotFoundError = new(typeof(EzrKeyNotFoundError), context, Position.None, Position.None);
EzrSharpCompatibilityType mathError = new(typeof(EzrMathError), context, Position.None, Position.None);
EzrSharpCompatibilityType missingRequiredArgumentError = new(typeof(EzrMissingRequiredArgumentError), context, Position.None, Position.None);
EzrSharpCompatibilityType privateMemberOperationError = new(typeof(EzrPrivateMemberOperationError), context, Position.None, Position.None);
EzrSharpCompatibilityType undefinedValueError = new(typeof(EzrUndefinedValueError), context, Position.None, Position.None);
EzrSharpCompatibilityType unexpectedArgumentError = new(typeof(EzrUnexpectedArgumentError), context, Position.None, Position.None);
EzrSharpCompatibilityType unexpectedTypeError = new(typeof(EzrUnexpectedTypeError), context, Position.None, Position.None);
EzrSharpCompatibilityType unsupportedWrappingError = new(typeof(EzrUnsupportedWrappingError), context, Position.None, Position.None);
EzrSharpCompatibilityType valueOutOfRangeError = new(typeof(EzrValueOutOfRangeError), context, Position.None, Position.None);
EzrSharpCompatibilityType wrapperExecutionError = new(typeof(EzrWrapperExecutionError), context, Position.None, Position.None);

context.Set(null, assertionError.SharpTypeName, ReferencePool.Get(assertionError, AccessMod.Constant));
context.Set(null, illegalOperationError.SharpTypeName, ReferencePool.Get(illegalOperationError, AccessMod.Constant));
context.Set(null, keyNotFoundError.SharpTypeName, ReferencePool.Get(keyNotFoundError, AccessMod.Constant));
context.Set(null, mathError.SharpTypeName, ReferencePool.Get(mathError, AccessMod.Constant));
context.Set(null, missingRequiredArgumentError.SharpTypeName, ReferencePool.Get(missingRequiredArgumentError, AccessMod.Constant));
context.Set(null, privateMemberOperationError.SharpTypeName, ReferencePool.Get(privateMemberOperationError, AccessMod.Constant));
context.Set(null, undefinedValueError.SharpTypeName, ReferencePool.Get(undefinedValueError, AccessMod.Constant));
context.Set(null, unexpectedArgumentError.SharpTypeName, ReferencePool.Get(unexpectedArgumentError, AccessMod.Constant));
context.Set(null, unexpectedTypeError.SharpTypeName, ReferencePool.Get(unexpectedTypeError, AccessMod.Constant));
context.Set(null, unsupportedWrappingError.SharpTypeName, ReferencePool.Get(unsupportedWrappingError, AccessMod.Constant));
context.Set(null, valueOutOfRangeError.SharpTypeName, ReferencePool.Get(valueOutOfRangeError, AccessMod.Constant));
context.Set(null, wrapperExecutionError.SharpTypeName, ReferencePool.Get(wrapperExecutionError, AccessMod.Constant));
context.Set(null, assertionError.SharpMemberName, ReferencePool.Get(assertionError, AccessMod.Constant));
context.Set(null, illegalOperationError.SharpMemberName, ReferencePool.Get(illegalOperationError, AccessMod.Constant));
context.Set(null, keyNotFoundError.SharpMemberName, ReferencePool.Get(keyNotFoundError, AccessMod.Constant));
context.Set(null, mathError.SharpMemberName, ReferencePool.Get(mathError, AccessMod.Constant));
context.Set(null, missingRequiredArgumentError.SharpMemberName, ReferencePool.Get(missingRequiredArgumentError, AccessMod.Constant));
context.Set(null, privateMemberOperationError.SharpMemberName, ReferencePool.Get(privateMemberOperationError, AccessMod.Constant));
context.Set(null, undefinedValueError.SharpMemberName, ReferencePool.Get(undefinedValueError, AccessMod.Constant));
context.Set(null, unexpectedArgumentError.SharpMemberName, ReferencePool.Get(unexpectedArgumentError, AccessMod.Constant));
context.Set(null, unexpectedTypeError.SharpMemberName, ReferencePool.Get(unexpectedTypeError, AccessMod.Constant));
context.Set(null, unsupportedWrappingError.SharpMemberName, ReferencePool.Get(unsupportedWrappingError, AccessMod.Constant));
context.Set(null, valueOutOfRangeError.SharpMemberName, ReferencePool.Get(valueOutOfRangeError, AccessMod.Constant));
context.Set(null, wrapperExecutionError.SharpMemberName, ReferencePool.Get(wrapperExecutionError, AccessMod.Constant));
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.Attributes;
/// <summary>
/// Attribute for C# types and members to be automatically wrapped from C# types into ezr² types.
/// </summary>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = false, Inherited = false)]
public class WrappedMemberAttribute : Attribute
{
/// <summary>
Expand Down Expand Up @@ -50,6 +50,21 @@ public WrappedMemberAttribute(string name, bool isReadOnly = false, bool isWrite
Name = name;
}

/// <summary>
/// Checks if the given type has the supported signature for wrapping.
/// </summary>
/// <param name="type">The type.</param>
/// <param name="dontThrow">Disable exception throwing.</param>
/// <returns><see langword="true"/> if valid, an exception or <see langword="false"/> otherwise.</returns>
/// <exception cref="ArgumentException">Thrown if the type is generic or has generic parameters.</exception>
public static bool ValidateType(Type type, bool dontThrow = false)
{
if (type.IsAbstract || type.IsGenericTypeDefinition)
return dontThrow ? false : throw new ArgumentException($"The \"{nameof(WrappedMemberAttribute)}\" attribute does not support abstract/generic type \"{type.Name}\".", nameof(type));

return true;
}

/// <summary>
/// Checks if the given method has the supported signature for wrapping.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.Attributes;
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers;
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers.Executables;
using EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers.Executables.Attributes;
using EzrSquared.Util;
using System;
using System.Collections.Generic;
Expand All @@ -13,19 +14,23 @@ namespace EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers;
/// <summary>
/// Class to automatically wrap C# types so that they can be used in ezr².
/// </summary>
public class EzrSharpCompatibilityType : EzrSharpCompatibilityWrapper<Type>
public class EzrSharpCompatibilityType : EzrSharpCompatibilityWrapper<Type>, IEzrObject
{
/// <inheritdoc/>
public override string TypeName { get; protected internal set; } = "csharp type";

/// <inheritdoc/>
public override string Tag { get; protected internal set; } = "ezrSquared.CSharpType";

/// <summary>
/// The primary wrapped constructor for the type. May be <see langword="null"/>.
/// </summary>
public readonly EzrSharpCompatibilityConstructor? PrimaryConstructor;

/// <summary>
/// Creates a new <see cref="EzrSharpCompatibilityType"/>.
/// </summary>
/// <param name="sharpType">The type to wrap.</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 @@ -41,15 +46,10 @@ public EzrSharpCompatibilityType(
| DynamicallyAccessedMemberTypes.NonPublicConstructors)]
Type sharpType,

RuntimeResult result, Context parentContext, Position startPosition, Position endPosition) : base(sharpType, null, parentContext, startPosition, endPosition)
Context parentContext, Position startPosition, Position endPosition) : base(sharpType, null, parentContext, startPosition, endPosition)
{
Tag = $"{Tag}.{SharpMemberName}.{UIDProvider.Get()}";

if (sharpType.IsAbstract || sharpType.IsGenericTypeDefinition)
{
result.Failure(new EzrUnsupportedWrappingError($"Cannot wrap generic/abstract C# type \"{SharpMember.Name}\"!", Context, StartPosition, EndPosition));
return;
}
WrappedMemberAttribute.ValidateType(SharpMember, AutoWrapperAttribute is null);

MethodInfo[] allStaticMethods = sharpType.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
Dictionary<string, int> duplicateNames = new(allStaticMethods.Length);
Expand Down Expand Up @@ -109,9 +109,47 @@ public EzrSharpCompatibilityType(
if (!WrappedMemberAttribute.ValidateMethod(constructor, constructorObject.AutoWrapperAttribute is null))
continue;

Context.Set(null, definedConstructors == 0 ? "make" : $"make_{definedConstructors}", ReferencePool.Get(constructorObject, AccessMod.Constant));
definedConstructors++;
if (constructor.GetCustomAttribute<PrimaryConstructorAttribute>() is not null)
{
if (PrimaryConstructor is not null)
throw new ArgumentException($"Type \"{SharpMember.Name}\" cannot have multiple primary constructors!", nameof(sharpType));

PrimaryConstructor = constructorObject;
continue;
}

string name = definedConstructors == 0 ? "make" : $"make_{definedConstructors}";
if (constructorObject.AutoWrapperAttribute is not WrappedMemberAttribute attr || string.IsNullOrEmpty(attr.Name))
definedConstructors++;
else
{
if (Context.IsDefined(attr.Name))
throw new ArgumentException($"Wrapped member with name \"{attr.Name}\" is already defined for type \"{SharpMember.Name}\".", nameof(sharpType));

name = attr.Name;
}

Context.Set(null, name, ReferencePool.Get(constructorObject, AccessMod.Constant));
}
}

/// <inheritdoc/>
public new void Update(Context context, Position startPosition, Position endPosition)
{
base.Update(context, startPosition, endPosition);
PrimaryConstructor?.Update(Context, startPosition, endPosition);
}

/// <inheritdoc/>
public override void Execute(Reference[] arguments, Interpreter interpreter, RuntimeResult result)
{
if (PrimaryConstructor is null)
{
base.Execute(arguments, interpreter, result);
return;
}

PrimaryConstructor.Execute(arguments, interpreter, result);
}

/// <inheritdoc/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;

namespace EzrSquared.Runtime.Types.CSharpWrappers.CompatWrappers.ObjectMembers.Executables.Attributes;

/// <summary>
/// Attribute that declares a primary constructor.
/// </summary>
[AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false, Inherited = false)]
public class PrimaryConstructorAttribute : Attribute
{
}
Loading

0 comments on commit c2b908a

Please sign in to comment.