Skip to content

Instantly share code, notes, and snippets.

@cdiggins
Created October 16, 2022 19:28
Show Gist options
  • Save cdiggins/6d6481e8bbb9044cd06d879d1a7cf467 to your computer and use it in GitHub Desktop.
Save cdiggins/6d6481e8bbb9044cd06d879d1a7cf467 to your computer and use it in GitHub Desktop.
Example of Plato code, and generated backing C# code, for a Vector3 class.
/*
* This is a sample of the auto-generated code currently produced by Plato
* along with the code it was generated from.
* Plato and the generated code is compatible with .NET Standard 2.0 and C# 8.0
*/
using System;
namespace Plato2
{
/// <summary>
/// As a programmer I can write the following code, and the generated code is shown below
/// </summary>
public readonly partial struct Vector3 :
INumber,
IVector<float>
{
public float X { get; }
public float Y { get; }
public float Z { get; }
}
}
// These are predefined Plato library interfaces
namespace Plato2
{
/// <summary>
/// Any class or struct implementing this interfaces is considered to be numeric.
/// It must contain only fields that are primitive numbers or that is also considered numeric.
/// Plato will automatically generate implementations of the following functions, fields, operators:
/// - arithmetical operators: +, - (binary and unary), *, /
/// - equality operators ==, !=
/// - GetHashCode and Equals overrides
/// - Deconstruct function
/// - ToString override, that produces a JSON formatted object
/// - value tuple implicit conversion to/from
/// - static fields for "One", "Zero", "Default", "MinValue", "MaxValue"
/// - WithX functions for each field, that create a copy with a field changed
/// </summary>
public interface INumber { }
/// <summary>
/// Classes implementing this interface are expected to provide O(1) implementation
/// of Count and the random element operation.
/// There is an extensive library of LINQ style extensions functions available.
/// </summary>
public interface IArray<T>
{
int Count { get; }
T this[int index] { get; }
}
/// <summary>
/// Any class or struct declaring to implement the IVector interface, will have
/// a default implementation provided automatically by Plato.
/// Plato will also provide operators to multiply and divide by the scalar.
/// </summary>
public interface IVector<T> : IArray<T>, INumber
{
}
}
// This is auto-generated code.
namespace Plato2
{
public static partial class Intrinsics
{
public static float Add(this float a, float b) => a + b;
public static float Subtract(this float a, float b) => a - b;
public static float Multiply(this float a, float b) => a * b;
public static float Divide(this float a, float b) => a / b;
public static float Negate(this float a) => -a;
public static bool Equals(this float a, float b) => a == b;
public static bool NotEquals(this float a, float b) => a != b;
public static float Default(this float _) => default(float);
public static float Zero(this float _) => (float)0;
public static float One(this float _) => (float)1;
public static float MinValue(this float _) => float.MinValue;
public static float MaxValue(this float _) => float.MaxValue;
}
public static partial class Intrinsics
{
public static double Add(this double a, double b) => a + b;
public static double Subtract(this double a, double b) => a - b;
public static double Multiply(this double a, double b) => a * b;
public static double Divide(this double a, double b) => a / b;
public static double Negate(this double a) => -a;
public static bool Equals(this double a, double b) => a == b;
public static bool NotEquals(this double a, double b) => a != b;
public static double Default(this double _) => default(double);
public static double Zero(this double _) => (double)0;
public static double One(this double _) => (double)1;
public static double MinValue(this double _) => double.MinValue;
public static double MaxValue(this double _) => double.MaxValue;
}
public static partial class Intrinsics
{
public static int Add(this int a, int b) => a + b;
public static int Subtract(this int a, int b) => a - b;
public static int Multiply(this int a, int b) => a * b;
public static int Divide(this int a, int b) => a / b;
public static int Negate(this int a) => -a;
public static bool Equals(this int a, int b) => a == b;
public static bool NotEquals(this int a, int b) => a != b;
public static int Default(this int _) => default(int);
public static int Zero(this int _) => (int)0;
public static int One(this int _) => (int)1;
public static int MinValue(this int _) => int.MinValue;
public static int MaxValue(this int _) => int.MaxValue;
}
public static partial class Intrinsics
{
public static long Add(this long a, long b) => a + b;
public static long Subtract(this long a, long b) => a - b;
public static long Multiply(this long a, long b) => a * b;
public static long Divide(this long a, long b) => a / b;
public static long Negate(this long a) => -a;
public static bool Equals(this long a, long b) => a == b;
public static bool NotEquals(this long a, long b) => a != b;
public static long Default(this long _) => default(long);
public static long Zero(this long _) => (long)0;
public static long One(this long _) => (long)1;
public static long MinValue(this long _) => long.MinValue;
public static long MaxValue(this long _) => long.MaxValue;
}
public static partial class Intrinsics
{
public static decimal Add(this decimal a, decimal b) => a + b;
public static decimal Subtract(this decimal a, decimal b) => a - b;
public static decimal Multiply(this decimal a, decimal b) => a * b;
public static decimal Divide(this decimal a, decimal b) => a / b;
public static decimal Negate(this decimal a) => -a;
public static bool Equals(this decimal a, decimal b) => a == b;
public static bool NotEquals(this decimal a, decimal b) => a != b;
public static decimal Default(this decimal _) => default(decimal);
public static decimal Zero(this decimal _) => (decimal)0;
public static decimal One(this decimal _) => (decimal)1;
public static decimal MinValue(this decimal _) => decimal.MinValue;
public static decimal MaxValue(this decimal _) => decimal.MaxValue;
}
public partial struct Vector3
{
public Vector3(Single x, Single y, Single z) => (X, Y, Z) = (x, y, z);
public static implicit operator Vector3((Single X, Single Y, Single Z) tuple) =>
new Vector3(tuple.X, tuple.Y, tuple.Z);
public static implicit operator (Single X, Single Y, Single Z)(Vector3 self) => (self.X, self.Y, self.Z);
public void Deconstruct(out Single x, out Single y, out Single z) => (x, y, z) = (X, Y, Z);
public override string ToString() => $"{{ \"X\" : {X}, \"Y\" : {Y}, \"Z\" : {Z} }}";
public override bool Equals(object other) => other is Vector3 typedOther && this == typedOther;
public override int GetHashCode() => (X, Y, Z).GetHashCode();
public static readonly Vector3 Default = default;
public static Vector3 Zero = new Vector3(Default.X.Zero(), Default.Y.Zero(), Default.Z.Zero());
public static Vector3 One = new Vector3(Default.X.One(), Default.Y.One(), Default.Z.One());
public static Vector3 MinValue = new Vector3(Default.X.MinValue(), Default.Y.MinValue(), Default.Z.MinValue());
public static Vector3 MaxValue = new Vector3(Default.X.MaxValue(), Default.Y.MaxValue(), Default.Z.MaxValue());
public Vector3 WithX(Single value) => new Vector3(value, Y, Z);
public Vector3 WithY(Single value) => new Vector3(X, value, Z);
public Vector3 WithZ(Single value) => new Vector3(X, Y, value);
public static Vector3 operator +(Vector3 a, Vector3 b) => new Vector3(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
public static Vector3 operator -(Vector3 a, Vector3 b) => new Vector3(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
public static Vector3 operator *(Vector3 a, Vector3 b) => new Vector3(a.X * b.X, a.Y * b.Y, a.Z * b.Z);
public static Vector3 operator /(Vector3 a, Vector3 b) => new Vector3(a.X / b.X, a.Y / b.Y, a.Z / b.Z);
public static Vector3 operator -(Vector3 a) => new Vector3(-a.X, -a.Y, -a.Z);
public static bool operator ==(Vector3 a, Vector3 b) => (a.X == b.X) && (a.Y == b.Y) && (a.Z == b.Z);
public static bool operator !=(Vector3 a, Vector3 b) => (a.X != b.X) || (a.Y != b.Y) || (a.Z != b.Z);
public static Vector3 operator *(Vector3 self, Single scalar) =>
new Vector3(self.X * scalar, self.Y * scalar, self.Z * scalar);
public static Vector3 operator /(Vector3 self, Single scalar) =>
new Vector3(self.X / scalar, self.Y / scalar, self.Z / scalar);
public int Count => 3;
public Single this[int index]
{
get
{
switch (index)
{
case 0: return X;
case 1: return Y;
case 2: return Z;
default: throw new System.ArgumentOutOfRangeException(nameof(index));
}
}
}
}
public static partial class Intrinsics
{
public static Vector3 Add(this Vector3 a, Vector3 b) => a + b;
public static Vector3 Subtract(this Vector3 a, Vector3 b) => a - b;
public static Vector3 Multiply(this Vector3 a, Vector3 b) => a * b;
public static Vector3 Divide(this Vector3 a, Vector3 b) => a / b;
public static Vector3 Negate(this Vector3 a) => -a;
public static bool Equals(this Vector3 a, Vector3 b) => a == b;
public static bool NotEquals(this Vector3 a, Vector3 b) => a != b;
public static Vector3 Default(this Vector3 _) => default(Vector3);
public static Vector3 Zero(this Vector3 _) => Vector3.Zero;
public static Vector3 One(this Vector3 _) => Vector3.One;
public static Vector3 MinValue(this Vector3 _) => Vector3.MinValue;
public static Vector3 MaxValue(this Vector3 _) => Vector3.MaxValue;
}
} // End namespace
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment