[Runtime] Float:ToDebugString() is not an override

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//
USING System
USING System.Runtime.InteropServices
USING System.Runtime.CompilerServices
USING System.Runtime.Serialization
USING System.Diagnostics

BEGIN NAMESPACE XSharp
    // use explicit layout so we can compact the size into 12 bytes
    // Type is Immutable, so no settable properties
    /// Internal type that implements the VO Compatible FLOAT type.
    /// This type has many operators and implicit converters that normally are never directly called from user code.
    ///
    /// <seealso cref="IFloat"/>
    /// <seealso cref="RDD.DbFloat"/>
    [DebuggerDisplay("{ToDebugString(),nq}", Type := "FLOAT" )];
    [StructLayout(LayoutKind.Explicit, Pack := 4)];
    [Serializable];
    PUBLIC STRUCTURE __Float IMPLEMENTS IFloat, ;
        IConvertible,;
        IFormattable, ;
        IComparable<__Float>, ;
        IEquatable<__Float>, ;
        IComparable,            ;
        ISerializable

        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
        [FieldOffset(0)]  PRIVATE INITONLY _value AS REAL8
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
        [FieldOffset(8)]  PRIVATE INITONLY _length AS SHORTINT
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
        [FieldOffset(10)] PRIVATE INITONLY _decimals AS SHORTINT

        #region constructors
        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        /// <param name="r8">Real8 value to convert to a FLOAT</param>
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (r8 AS REAL8)
            SELF:_value    := r8
            SELF:_length   := 0
            SELF:_decimals := -1

        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (r8 AS REAL8, decimals AS INT)
            SELF:_value    := r8
            SELF:_length   := 0
            SELF:_decimals := (SHORTINT) decimals

        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (r8 AS REAL8, decimals AS DWORD)
            SELF:_value    := r8
            SELF:_length   := 0
            SELF:_decimals := (SHORTINT) decimals

        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (r8 AS REAL8, length AS DWORD, decimals AS DWORD)
            SELF:_value    := r8
            SELF:_length   := (SHORTINT) length
            SELF:_decimals := (SHORTINT) decimals

        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (r8 AS REAL8, length AS INT, decimals AS INT )
            SELF:_value    := r8
            SELF:_length   := (SHORTINT) length
            SELF:_decimals := (SHORTINT) decimals

        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (@@Value AS IFloat)
            SELF:_value		:= @@Value:Value
            SELF:_length	:= (SHORT)  @@Value:Digits
            SELF:_decimals	:= (SHORT)  @@Value:Decimals
        #endregion
        #region Properties
        /// REAL8 (System.Double) value
        PROPERTY @@Value    AS REAL8	GET _value
        /// Width
        PROPERTY Digits   AS INT	GET _length
        /// Number of decimals
        PROPERTY Decimals AS INT	GET _decimals
        #endregion

        #region Equality Operators
        /// <inheritdoc />
        OVERRIDE METHOD Equals(rhs AS OBJECT  ) AS LOGIC
            LOCAL result AS LOGIC
            IF rhs != NULL .AND. rhs IS FLOAT
                result := SELF:Equals( (FLOAT) rhs)
            ELSE
                result := FALSE
            ENDIF
            RETURN result

        /// <inheritdoc />
        METHOD Equals(rhs AS FLOAT ) AS LOGIC
            LOCAL delta AS REAL8
            LOCAL diff  AS REAL8
            LOCAL equal AS LOGIC

            IF Double.IsNaN(rhs:_value) .or. Double.IsNaN(SELF:_value)
            	RETURN Double.IsNaN(rhs:_value) .and. Double.IsNaN(SELF:_value)
            ELSEIF rhs:_value == Double.PositiveInfinity .or. SELF:_value == Double.PositiveInfinity
            	RETURN rhs:_value == SELF:_value
            ELSEIF rhs:_value == Double.NegativeInfinity .or. SELF:_value == Double.NegativeInfinity
            	RETURN rhs:_value == SELF:_value
            END IF

            delta := RuntimeState.FloatDelta
            diff := _value - rhs:_value
            IF delta == 0.0
                equal :=  diff == 0.0
            ELSEIF diff < 0.0
                equal :=  Math.Abs(diff) < delta
            ELSE
                equal := diff < delta
            ENDIF
            RETURN equal

            /// <inheritdoc />
        OVERRIDE METHOD GetHashCode() AS INT
            RETURN SELF:_value:GetHashCode()

            /// <exclude />
        METHOD GetTypeCode() AS TypeCode
            RETURN TypeCode.Double

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR ==(lhs AS FLOAT, rhs AS FLOAT) AS LOGIC
            RETURN lhs:Equals(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR !=(lhs AS FLOAT, rhs AS FLOAT) AS LOGIC
            RETURN ! lhs:Equals(rhs)
            #endregion

        #region Comparison Operators
        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR >(lhs AS FLOAT, rhs AS FLOAT) AS LOGIC
            LOCAL delta AS REAL8
            LOCAL diff  AS REAL8
            delta := RuntimeState.FloatDelta
            diff := lhs:_value - rhs:_value
            IF (delta == 0.0)
                RETURN diff > 0.0
            ENDIF
            RETURN diff > delta

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR <(lhs AS FLOAT, rhs AS FLOAT) AS LOGIC
            LOCAL delta AS REAL8
            LOCAL diff  AS REAL8
            delta := RuntimeState.FloatDelta
            diff := lhs:_value - rhs:_value
            IF (delta == 0.0)
                RETURN diff < 0.0
            ENDIF
            RETURN diff < -delta

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR >=(lhs AS FLOAT, rhs AS FLOAT) AS LOGIC
            // call other operator methods for simplicity
            // we may want to optimize this later
            RETURN lhs > rhs .OR. lhs == rhs

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR <=(lhs AS FLOAT, rhs AS FLOAT) AS LOGIC
            // call other operator methods for simplicity
            // we may want to optimize this later
            RETURN lhs < rhs .OR. lhs == rhs

            #endregion

        #region Implicit Converters
        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(b AS BYTE) AS FLOAT
            RETURN FLOAT{b, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(sb AS SByte) AS FLOAT
            RETURN FLOAT{sb, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(si AS SHORT) AS FLOAT
            RETURN FLOAT{si, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(w AS WORD) AS FLOAT
            RETURN FLOAT{w, 0}
            /// <include file="RTComments.xml" path="Comments/Converter/*" />

        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(i AS INT) AS FLOAT
            RETURN FLOAT{i, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(dw AS DWORD) AS FLOAT
            RETURN FLOAT{dw, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(i64 AS INT64) AS FLOAT
            RETURN FLOAT{i64, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(ui64 AS UINT64) AS FLOAT
            RETURN FLOAT{ui64, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(r4 AS REAL4) AS FLOAT
            RETURN FLOAT{r4, RuntimeState.Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(r8 AS REAL8) AS FLOAT
            RETURN FLOAT{r8, RuntimeState.Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(val AS System.Decimal) AS FLOAT
            RETURN FLOAT{ (REAL8) val, RuntimeState.Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(fl  AS FLOAT) AS REAL8
            RETURN fl:_value

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(fl  AS FLOAT) AS REAL4
            RETURN (REAL4) fl:_value

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(fl  AS FLOAT) AS System.Decimal
            RETURN (System.Decimal) fl:_value

        #endregion
        #region Explicit Converters
        /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS BYTE
            IF RuntimeState.CompilerOptionVO11
                RETURN Convert.ToByte(fl:_value)
            ENDIF
            RETURN (BYTE) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl AS FLOAT) AS SByte
            RETURN (SByte) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS SHORT
            IF RuntimeState.CompilerOptionVO11
                RETURN Convert.ToInt16(fl:_value)
            ENDIF
            RETURN (SHORT) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS WORD
            RETURN (WORD) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS LONG
            IF RuntimeState.CompilerOptionVO11
                RETURN Convert.ToInt32(fl:_value)
            ENDIF
            RETURN (LONG) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS DWORD
            RETURN (DWORD) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS INT64
            IF RuntimeState.CompilerOptionVO11
                RETURN Convert.ToInt64(fl:_value)
            ENDIF
            RETURN (INT64) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS UINT64
            RETURN (UINT64) fl:_value

            #endregion

        #region Numeric Operators
        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR +(fl  AS FLOAT) AS FLOAT
            RETURN fl

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR -(fl  AS FLOAT) AS FLOAT
            RETURN FLOAT{- fl:_value, fl:Digits, fl:Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR+(lhs AS FLOAT, rhs AS FLOAT) AS FLOAT
            RETURN lhs:Add(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR+(lhs AS FLOAT, rhs AS USUAL) AS FLOAT
            RETURN lhs:Add(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR+(lhs AS USUAL, rhs AS FLOAT) AS FLOAT
            RETURN rhs:Add(lhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR-(lhs AS FLOAT, rhs AS FLOAT) AS FLOAT
            RETURN lhs:Subtract(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR-(lhs AS FLOAT, rhs AS USUAL) AS FLOAT
            RETURN lhs:Subtract(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR-(lhs AS USUAL, rhs AS FLOAT) AS FLOAT
            // set decimals for LHS to 0, so max decmals is decimals right
            RETURN FLOAT{lhs, 0}:Subtract(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR*(lhs AS FLOAT, rhs AS FLOAT) AS FLOAT
            RETURN FLOAT{ lhs:_value * rhs:_value, lhs:Decimals + rhs:Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        //[DebuggerStepThroughAttribute];
        OPERATOR/(lhs AS FLOAT, rhs AS FLOAT) AS FLOAT
            VAR tmp := lhs:_value / rhs:_value
            IF System.Double.IsNaN(tmp) .or. System.Double.IsInfinity(tmp)
                THROW DivideByZeroException{}
            ENDIF
            RETURN FLOAT{ tmp, RuntimeState.Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR%(lhs AS FLOAT, rhs AS FLOAT) AS FLOAT
            RETURN FLOAT{ lhs:_value % rhs:_value, RuntimeState.Decimals}

            #endregion
        #region Unary Operators
        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR ++ (fl  AS FLOAT) AS FLOAT
            RETURN FLOAT{fl:_value+1, fl:Digits, fl:Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR -- (fl  AS FLOAT) AS FLOAT
            RETURN FLOAT{fl:_value-1, fl:Digits, fl:Decimals}
            #endregion

        #region Explicit casts. Used inside Transform
        /// <exclude />
        [DebuggerStepThroughAttribute];
        METHOD CastToInt() AS INT
            RETURN (INT)(SELF:_value)

            /// <exclude />
        [DebuggerStepThroughAttribute];
        METHOD CastToInt64() AS INT64
            RETURN (INT64)(SELF:_value)

            #endregion
        #region Add and Subtract
        /// <exclude />
        [DebuggerStepThroughAttribute];
        METHOD Add(rhs AS FLOAT) AS FLOAT
            RETURN FLOAT{ SELF:_value + rhs:_value, Math.Max(SELF:_decimals, rhs:_decimals)}

            /// <exclude />
        [DebuggerStepThroughAttribute];
        METHOD Add(rhs AS USUAL) AS FLOAT
            LOCAL result AS FLOAT
            IF rhs:IsFloat
                result := SELF:Add ( (FLOAT) rhs)
            ELSEIF rhs:IsDecimal .OR. rhs:IsCurrency
                result := SELF:Add ( (System.Decimal) rhs)
            ELSEIF  rhs:IsLong
                result := FLOAT{ SELF:_value + (LONG) rhs, SELF:Digits, SELF:Decimals}
            ELSE
                THROW Error.ArgumentError(__ENTITY__,Nameof(rhs), "Argument is not numeric")
            ENDIF
            RETURN result

            /// <exclude />
        [DebuggerStepThroughAttribute];
        METHOD Subtract(rhs AS FLOAT) AS FLOAT
            RETURN FLOAT{ SELF:_value - rhs:_value, Math.Max(SELF:_decimals, rhs:_decimals)}

            /// <exclude />
        [DebuggerStepThroughAttribute];
        METHOD Subtract(rhs AS USUAL) AS FLOAT
            LOCAL result AS FLOAT
            IF rhs:IsFloat
                result := SELF:Subtract( (FLOAT) rhs)
            ELSEIF rhs:IsDecimal .OR. rhs:IsCurrency
                result := SELF:Subtract( (System.Decimal) rhs)
            ELSEIF  rhs:IsLong
                result := FLOAT{ SELF:_value - (LONG) rhs, SELF:Digits, SELF:Decimals}
            ELSE
                THROW Error.ArgumentError(__ENTITY__,Nameof(rhs), "Argument is not numeric")
            ENDIF
            RETURN result

            #endregion

        #region IConvertable
        /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToBoolean(provider AS System.IFormatProvider) AS LOGIC
            RETURN _value ==  0.0

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToByte(provider AS System.IFormatProvider) AS BYTE
            RETURN ((IConvertible) _value):ToByte(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToChar(provider AS System.IFormatProvider) AS CHAR
            RETURN ((IConvertible) _value):ToChar(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToDateTime(provider AS System.IFormatProvider) AS System.DateTime
            RETURN ((IConvertible) _value):ToDateTime(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToDecimal(provider AS System.IFormatProvider) AS Decimal
            RETURN ((IConvertible) _value):ToDecimal(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToDouble(provider AS System.IFormatProvider) AS REAL8
            RETURN ((IConvertible) _value):ToDouble(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToInt16(provider AS System.IFormatProvider) AS SHORT
            RETURN ((IConvertible) _value):ToInt16(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToInt32(provider AS System.IFormatProvider) AS LONG
            RETURN ((IConvertible) _value):ToInt32(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToInt64(provider AS System.IFormatProvider) AS INT64
            RETURN ((IConvertible) _value):ToInt64(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToSByte(provider AS System.IFormatProvider) AS SByte
            RETURN ((IConvertible) _value):ToSByte(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToSingle(provider AS System.IFormatProvider) AS REAL4
            RETURN ((IConvertible) _value):ToSingle(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToType(conversionType AS System.Type, provider AS System.IFormatProvider) AS OBJECT
            RETURN ((IConvertible) _value):ToType(conversionType, provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToUInt16(provider AS System.IFormatProvider) AS WORD
            RETURN ((IConvertible) _value):ToUInt16(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToUInt32(provider AS System.IFormatProvider) AS DWORD
            RETURN ((IConvertible) _value):ToUInt32(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToUInt64(provider AS System.IFormatProvider) AS UINT64
            RETURN ((IConvertible) _value):ToUInt64(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToString(provider AS System.IFormatProvider) AS STRING
            RETURN ((IConvertible) _value):ToString(provider)
            #endregion
        #region IFormattable
        /// <inheritdoc />
        PUBLIC OVERRIDE METHOD ToString() AS STRING
            RETURN Str1(SELF)

        /// <inheritdoc cref="System.Double.ToString(System.String)"/>
        PUBLIC METHOD ToString(sFormat AS STRING) AS STRING
            RETURN _value:ToString(sFormat)

            /// <inheritdoc />
        PUBLIC METHOD ToString(format AS STRING, provider AS System.IFormatProvider) AS STRING
            RETURN ((IFormattable) _value):ToString(format, provider)
            #endregion
        #region IComparable
        /// <inheritdoc />
        PUBLIC METHOD CompareTo(rhs AS FLOAT) AS INT
            RETURN _value:CompareTo( rhs:_value)

            /// <inheritdoc />
        PUBLIC METHOD CompareTo(rhs AS OBJECT) AS INT
            RETURN SELF:CompareTo( (FLOAT) rhs)
            #endregion

        #region ISerializable
        /// <inheritdoc/>
        PUBLIC METHOD GetObjectData(info AS SerializationInfo, context AS StreamingContext) AS VOID
            IF info == NULL
                THROW System.ArgumentException{"info"}
            ENDIF
            info:AddValue("Value", SELF:_value)
            info:AddValue("Length", SELF:_length)
            info:AddValue("Decimals", SELF:_decimals)
            RETURN

        /// <include file="RTComments.xml" path="Comments/SerializeConstructor/*" />
        CONSTRUCTOR (info AS SerializationInfo, context AS StreamingContext)
            IF info == NULL
                THROW System.ArgumentException{"info"}
            ENDIF
            SELF:_value     := info:GetDouble("Value")
            SELF:_length    := info:GetInt16("Length")
            SELF:_decimals  := info:GetInt16("Decimals")
        #endregion

        PUBLIC METHOD ToDebugString() AS STRING
            RETURN SELF:Value:ToString()

    END STRUCTURE

END NAMESPACE

//
// Copyright (c) XSharp B.V.  All Rights Reserved.
// Licensed under the Apache License, Version 2.0.
// See License.txt in the project root for license information.
//
USING System
USING System.Runtime.InteropServices
USING System.Runtime.CompilerServices
USING System.Runtime.Serialization
USING System.Diagnostics

BEGIN NAMESPACE XSharp
    // use explicit layout so we can compact the size into 12 bytes
    // Type is Immutable, so no settable properties
    /// Internal type that implements the VO Compatible FLOAT type.
    /// This type has many operators and implicit converters that normally are never directly called from user code.
    ///
    /// <seealso cref="IFloat"/>
    /// <seealso cref="RDD.DbFloat"/>
    [DebuggerDisplay("{ToDebugString(),nq}", Type := "FLOAT" )];
    [StructLayout(LayoutKind.Explicit, Pack := 4)];
    [Serializable];
    PUBLIC STRUCTURE __Float IMPLEMENTS IFloat, ;
        IConvertible,;
        IFormattable, ;
        IComparable<__Float>, ;
        IEquatable<__Float>, ;
        IComparable,            ;
        ISerializable

        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
        [FieldOffset(0)]  PRIVATE INITONLY _value AS REAL8
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
        [FieldOffset(8)]  PRIVATE INITONLY _length AS SHORTINT
        [DebuggerBrowsable(DebuggerBrowsableState.Never)];
        [FieldOffset(10)] PRIVATE INITONLY _decimals AS SHORTINT

        #region constructors
        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        /// <param name="r8">Real8 value to convert to a FLOAT</param>
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (r8 AS REAL8)
            SELF:_value    := r8
            SELF:_length   := 0
            SELF:_decimals := -1

        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (r8 AS REAL8, decimals AS INT)
            SELF:_value    := r8
            SELF:_length   := 0
            SELF:_decimals := (SHORTINT) decimals

        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (r8 AS REAL8, decimals AS DWORD)
            SELF:_value    := r8
            SELF:_length   := 0
            SELF:_decimals := (SHORTINT) decimals

        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (r8 AS REAL8, length AS DWORD, decimals AS DWORD)
            SELF:_value    := r8
            SELF:_length   := (SHORTINT) length
            SELF:_decimals := (SHORTINT) decimals

        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (r8 AS REAL8, length AS INT, decimals AS INT )
            SELF:_value    := r8
            SELF:_length   := (SHORTINT) length
            SELF:_decimals := (SHORTINT) decimals

        /// <include file="RTComments.xml" path="Comments/Constructor/*" />
        [DebuggerStepThroughAttribute] [MethodImpl(MethodImplOptions.AggressiveInlining)];
        CONSTRUCTOR (@@Value AS IFloat)
            SELF:_value		:= @@Value:Value
            SELF:_length	:= (SHORT)  @@Value:Digits
            SELF:_decimals	:= (SHORT)  @@Value:Decimals
        #endregion
        #region Properties
        /// REAL8 (System.Double) value
        PROPERTY @@Value    AS REAL8	GET _value
        /// Width
        PROPERTY Digits   AS INT	GET _length
        /// Number of decimals
        PROPERTY Decimals AS INT	GET _decimals
        #endregion

        #region Equality Operators
        /// <inheritdoc />
        OVERRIDE METHOD Equals(rhs AS OBJECT  ) AS LOGIC
            LOCAL result AS LOGIC
            IF rhs != NULL .AND. rhs IS FLOAT
                result := SELF:Equals( (FLOAT) rhs)
            ELSE
                result := FALSE
            ENDIF
            RETURN result

        /// <inheritdoc />
        METHOD Equals(rhs AS FLOAT ) AS LOGIC
            LOCAL delta AS REAL8
            LOCAL diff  AS REAL8
            LOCAL equal AS LOGIC

            IF Double.IsNaN(rhs:_value) .or. Double.IsNaN(SELF:_value)
            	RETURN Double.IsNaN(rhs:_value) .and. Double.IsNaN(SELF:_value)
            ELSEIF rhs:_value == Double.PositiveInfinity .or. SELF:_value == Double.PositiveInfinity
            	RETURN rhs:_value == SELF:_value
            ELSEIF rhs:_value == Double.NegativeInfinity .or. SELF:_value == Double.NegativeInfinity
            	RETURN rhs:_value == SELF:_value
            END IF

            delta := RuntimeState.FloatDelta
            diff := _value - rhs:_value
            IF delta == 0.0
                equal :=  diff == 0.0
            ELSEIF diff < 0.0
                equal :=  Math.Abs(diff) < delta
            ELSE
                equal := diff < delta
            ENDIF
            RETURN equal

            /// <inheritdoc />
        OVERRIDE METHOD GetHashCode() AS INT
            RETURN SELF:_value:GetHashCode()

            /// <exclude />
        METHOD GetTypeCode() AS TypeCode
            RETURN TypeCode.Double

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR ==(lhs AS FLOAT, rhs AS FLOAT) AS LOGIC
            RETURN lhs:Equals(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR !=(lhs AS FLOAT, rhs AS FLOAT) AS LOGIC
            RETURN ! lhs:Equals(rhs)
            #endregion

        #region Comparison Operators
        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR >(lhs AS FLOAT, rhs AS FLOAT) AS LOGIC
            LOCAL delta AS REAL8
            LOCAL diff  AS REAL8
            delta := RuntimeState.FloatDelta
            diff := lhs:_value - rhs:_value
            IF (delta == 0.0)
                RETURN diff > 0.0
            ENDIF
            RETURN diff > delta

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR <(lhs AS FLOAT, rhs AS FLOAT) AS LOGIC
            LOCAL delta AS REAL8
            LOCAL diff  AS REAL8
            delta := RuntimeState.FloatDelta
            diff := lhs:_value - rhs:_value
            IF (delta == 0.0)
                RETURN diff < 0.0
            ENDIF
            RETURN diff < -delta

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR >=(lhs AS FLOAT, rhs AS FLOAT) AS LOGIC
            // call other operator methods for simplicity
            // we may want to optimize this later
            RETURN lhs > rhs .OR. lhs == rhs

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR <=(lhs AS FLOAT, rhs AS FLOAT) AS LOGIC
            // call other operator methods for simplicity
            // we may want to optimize this later
            RETURN lhs < rhs .OR. lhs == rhs

            #endregion

        #region Implicit Converters
        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(b AS BYTE) AS FLOAT
            RETURN FLOAT{b, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(sb AS SByte) AS FLOAT
            RETURN FLOAT{sb, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(si AS SHORT) AS FLOAT
            RETURN FLOAT{si, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(w AS WORD) AS FLOAT
            RETURN FLOAT{w, 0}
            /// <include file="RTComments.xml" path="Comments/Converter/*" />

        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(i AS INT) AS FLOAT
            RETURN FLOAT{i, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(dw AS DWORD) AS FLOAT
            RETURN FLOAT{dw, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(i64 AS INT64) AS FLOAT
            RETURN FLOAT{i64, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(ui64 AS UINT64) AS FLOAT
            RETURN FLOAT{ui64, 0}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(r4 AS REAL4) AS FLOAT
            RETURN FLOAT{r4, RuntimeState.Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(r8 AS REAL8) AS FLOAT
            RETURN FLOAT{r8, RuntimeState.Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(val AS System.Decimal) AS FLOAT
            RETURN FLOAT{ (REAL8) val, RuntimeState.Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(fl  AS FLOAT) AS REAL8
            RETURN fl:_value

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(fl  AS FLOAT) AS REAL4
            RETURN (REAL4) fl:_value

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR IMPLICIT(fl  AS FLOAT) AS System.Decimal
            RETURN (System.Decimal) fl:_value

        #endregion
        #region Explicit Converters
        /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS BYTE
            IF RuntimeState.CompilerOptionVO11
                RETURN Convert.ToByte(fl:_value)
            ENDIF
            RETURN (BYTE) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl AS FLOAT) AS SByte
            RETURN (SByte) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS SHORT
            IF RuntimeState.CompilerOptionVO11
                RETURN Convert.ToInt16(fl:_value)
            ENDIF
            RETURN (SHORT) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS WORD
            RETURN (WORD) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS LONG
            IF RuntimeState.CompilerOptionVO11
                RETURN Convert.ToInt32(fl:_value)
            ENDIF
            RETURN (LONG) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS DWORD
            RETURN (DWORD) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS INT64
            IF RuntimeState.CompilerOptionVO11
                RETURN Convert.ToInt64(fl:_value)
            ENDIF
            RETURN (INT64) fl:_value
            /// <include file="RTComments.xml" path="Comments/Converter/*" />
        [DebuggerStepThroughAttribute];
        STATIC OPERATOR EXPLICIT(fl  AS FLOAT) AS UINT64
            RETURN (UINT64) fl:_value

            #endregion

        #region Numeric Operators
        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR +(fl  AS FLOAT) AS FLOAT
            RETURN fl

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR -(fl  AS FLOAT) AS FLOAT
            RETURN FLOAT{- fl:_value, fl:Digits, fl:Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR+(lhs AS FLOAT, rhs AS FLOAT) AS FLOAT
            RETURN lhs:Add(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR+(lhs AS FLOAT, rhs AS USUAL) AS FLOAT
            RETURN lhs:Add(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR+(lhs AS USUAL, rhs AS FLOAT) AS FLOAT
            RETURN rhs:Add(lhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR-(lhs AS FLOAT, rhs AS FLOAT) AS FLOAT
            RETURN lhs:Subtract(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR-(lhs AS FLOAT, rhs AS USUAL) AS FLOAT
            RETURN lhs:Subtract(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR-(lhs AS USUAL, rhs AS FLOAT) AS FLOAT
            // set decimals for LHS to 0, so max decmals is decimals right
            RETURN FLOAT{lhs, 0}:Subtract(rhs)

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR*(lhs AS FLOAT, rhs AS FLOAT) AS FLOAT
            RETURN FLOAT{ lhs:_value * rhs:_value, lhs:Decimals + rhs:Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        //[DebuggerStepThroughAttribute];
        OPERATOR/(lhs AS FLOAT, rhs AS FLOAT) AS FLOAT
            VAR tmp := lhs:_value / rhs:_value
            IF System.Double.IsNaN(tmp) .or. System.Double.IsInfinity(tmp)
                THROW DivideByZeroException{}
            ENDIF
            RETURN FLOAT{ tmp, RuntimeState.Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR%(lhs AS FLOAT, rhs AS FLOAT) AS FLOAT
            RETURN FLOAT{ lhs:_value % rhs:_value, RuntimeState.Decimals}

            #endregion
        #region Unary Operators
        /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR ++ (fl  AS FLOAT) AS FLOAT
            RETURN FLOAT{fl:_value+1, fl:Digits, fl:Decimals}

            /// <include file="RTComments.xml" path="Comments/Operator/*" />
        [DebuggerStepThroughAttribute];
        OPERATOR -- (fl  AS FLOAT) AS FLOAT
            RETURN FLOAT{fl:_value-1, fl:Digits, fl:Decimals}
            #endregion

        #region Explicit casts. Used inside Transform
        /// <exclude />
        [DebuggerStepThroughAttribute];
        METHOD CastToInt() AS INT
            RETURN (INT)(SELF:_value)

            /// <exclude />
        [DebuggerStepThroughAttribute];
        METHOD CastToInt64() AS INT64
            RETURN (INT64)(SELF:_value)

            #endregion
        #region Add and Subtract
        /// <exclude />
        [DebuggerStepThroughAttribute];
        METHOD Add(rhs AS FLOAT) AS FLOAT
            RETURN FLOAT{ SELF:_value + rhs:_value, Math.Max(SELF:_decimals, rhs:_decimals)}

            /// <exclude />
        [DebuggerStepThroughAttribute];
        METHOD Add(rhs AS USUAL) AS FLOAT
            LOCAL result AS FLOAT
            IF rhs:IsFloat
                result := SELF:Add ( (FLOAT) rhs)
            ELSEIF rhs:IsDecimal .OR. rhs:IsCurrency
                result := SELF:Add ( (System.Decimal) rhs)
            ELSEIF  rhs:IsLong
                result := FLOAT{ SELF:_value + (LONG) rhs, SELF:Digits, SELF:Decimals}
            ELSE
                THROW Error.ArgumentError(__ENTITY__,Nameof(rhs), "Argument is not numeric")
            ENDIF
            RETURN result

            /// <exclude />
        [DebuggerStepThroughAttribute];
        METHOD Subtract(rhs AS FLOAT) AS FLOAT
            RETURN FLOAT{ SELF:_value - rhs:_value, Math.Max(SELF:_decimals, rhs:_decimals)}

            /// <exclude />
        [DebuggerStepThroughAttribute];
        METHOD Subtract(rhs AS USUAL) AS FLOAT
            LOCAL result AS FLOAT
            IF rhs:IsFloat
                result := SELF:Subtract( (FLOAT) rhs)
            ELSEIF rhs:IsDecimal .OR. rhs:IsCurrency
                result := SELF:Subtract( (System.Decimal) rhs)
            ELSEIF  rhs:IsLong
                result := FLOAT{ SELF:_value - (LONG) rhs, SELF:Digits, SELF:Decimals}
            ELSE
                THROW Error.ArgumentError(__ENTITY__,Nameof(rhs), "Argument is not numeric")
            ENDIF
            RETURN result

            #endregion

        #region IConvertable
        /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToBoolean(provider AS System.IFormatProvider) AS LOGIC
            RETURN _value ==  0.0

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToByte(provider AS System.IFormatProvider) AS BYTE
            RETURN ((IConvertible) _value):ToByte(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToChar(provider AS System.IFormatProvider) AS CHAR
            RETURN ((IConvertible) _value):ToChar(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToDateTime(provider AS System.IFormatProvider) AS System.DateTime
            RETURN ((IConvertible) _value):ToDateTime(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToDecimal(provider AS System.IFormatProvider) AS Decimal
            RETURN ((IConvertible) _value):ToDecimal(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToDouble(provider AS System.IFormatProvider) AS REAL8
            RETURN ((IConvertible) _value):ToDouble(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToInt16(provider AS System.IFormatProvider) AS SHORT
            RETURN ((IConvertible) _value):ToInt16(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToInt32(provider AS System.IFormatProvider) AS LONG
            RETURN ((IConvertible) _value):ToInt32(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToInt64(provider AS System.IFormatProvider) AS INT64
            RETURN ((IConvertible) _value):ToInt64(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToSByte(provider AS System.IFormatProvider) AS SByte
            RETURN ((IConvertible) _value):ToSByte(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToSingle(provider AS System.IFormatProvider) AS REAL4
            RETURN ((IConvertible) _value):ToSingle(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToType(conversionType AS System.Type, provider AS System.IFormatProvider) AS OBJECT
            RETURN ((IConvertible) _value):ToType(conversionType, provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToUInt16(provider AS System.IFormatProvider) AS WORD
            RETURN ((IConvertible) _value):ToUInt16(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToUInt32(provider AS System.IFormatProvider) AS DWORD
            RETURN ((IConvertible) _value):ToUInt32(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToUInt64(provider AS System.IFormatProvider) AS UINT64
            RETURN ((IConvertible) _value):ToUInt64(provider)

            /// <inheritdoc />
        PUBLIC METHOD IConvertible.ToString(provider AS System.IFormatProvider) AS STRING
            RETURN ((IConvertible) _value):ToString(provider)
            #endregion
        #region IFormattable
        /// <inheritdoc />
        PUBLIC OVERRIDE METHOD ToString() AS STRING
            RETURN Str1(SELF)

        /// <inheritdoc cref="System.Double.ToString(System.String)"/>
        PUBLIC METHOD ToString(sFormat AS STRING) AS STRING
            RETURN _value:ToString(sFormat)

            /// <inheritdoc />
        PUBLIC METHOD ToString(format AS STRING, provider AS System.IFormatProvider) AS STRING
            RETURN ((IFormattable) _value):ToString(format, provider)
            #endregion
        #region IComparable
        /// <inheritdoc />
        PUBLIC METHOD CompareTo(rhs AS FLOAT) AS INT
            RETURN _value:CompareTo( rhs:_value)

            /// <inheritdoc />
        PUBLIC METHOD CompareTo(rhs AS OBJECT) AS INT
            RETURN SELF:CompareTo( (FLOAT) rhs)
            #endregion

        #region ISerializable
        /// <inheritdoc/>
        PUBLIC METHOD GetObjectData(info AS SerializationInfo, context AS StreamingContext) AS VOID
            IF info == NULL
                THROW System.ArgumentException{"info"}
            ENDIF
            info:AddValue("Value", SELF:_value)
            info:AddValue("Length", SELF:_length)
            info:AddValue("Decimals", SELF:_decimals)
            RETURN

        /// <include file="RTComments.xml" path="Comments/SerializeConstructor/*" />
        CONSTRUCTOR (info AS SerializationInfo, context AS StreamingContext)
            IF info == NULL
                THROW System.ArgumentException{"info"}
            ENDIF
            SELF:_value     := info:GetDouble("Value")
            SELF:_length    := info:GetInt16("Length")
            SELF:_decimals  := info:GetInt16("Decimals")
        #endregion

        PUBLIC OVERRIDE METHOD ToDebugString() AS STRING
            RETURN SELF:Value:ToString()

    END STRUCTURE

END NAMESPACE


codegen/QtTest: updated

codegen/QtTest: updated

Modified:
codegen/QtTest/QTestEventList.prg

%%
%% Qt4xHb - Bindings libraries for Harbour/xHarbour and Qt Framework 4
%%
%% Copyright (C) 2018 Marcos Antonio Gambeta <marcosgambeta AT outlook DOT com>
%%

$header

#include "hbclass.ch"

$addRequests

$beginClass

   METHOD new
   METHOD delete
   METHOD addDelay
   METHOD addKeyClick1
   METHOD addKeyClick2
   METHOD addKeyClick
   METHOD addKeyClicks
   METHOD addKeyPress1
   METHOD addKeyPress2
   METHOD addKeyPress
   METHOD addKeyRelease1
   METHOD addKeyRelease2
   METHOD addKeyRelease
   METHOD addMouseClick
   METHOD addMouseDClick
   METHOD addMouseMove
   METHOD addMousePress
   METHOD addMouseRelease
   METHOD clear
   METHOD simulate

$endClass

$destructor

#pragma BEGINDUMP

$includes

$prototype=QTestEventList ()
$internalConstructor=|new1|

$prototype=QTestEventList ( const QTestEventList & other )
$internalConstructor=|new2|const QTestEventList &

//[1]QTestEventList ()
//[2]QTestEventList ( const QTestEventList & other )

HB_FUNC_STATIC( QTESTEVENTLIST_NEW )
{
  if( ISNUMPAR(0) )
  {
    QTestEventList_new1();
  }
  else if( ISNUMPAR(1) && ISQTESTEVENTLIST(1) )
  {
    QTestEventList_new2();
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$deleteMethod

$prototype=void addDelay ( int msecs )
$method=|void|addDelay|int

$prototype=void addKeyClick ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClick,addKeyClick1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyClick ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClick,addKeyClick2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

//[1]void addKeyClick ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
//[2]void addKeyClick ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYCLICK )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYCLICK1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYCLICK2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$prototype=void addKeyClicks ( const QString & keys, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClicks|const QString &,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyPress ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyPress,addKeyPress1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyPress ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyPress,addKeyPress2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

//[1]void addKeyPress ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
//[2]void addKeyPress ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYPRESS )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYPRESS1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYPRESS2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$prototype=void addKeyRelease ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyRelease,addKeyRelease1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyRelease ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyRelease,addKeyRelease2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

//[1]void addKeyRelease ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
//[2]void addKeyRelease ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYRELEASE )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYRELEASE1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYRELEASE2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$prototype=void addMouseClick ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseClick|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseDClick ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseDClick|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseMove ( QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseMove|QPoint=QPoint(),int=-1

$prototype=void addMousePress ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMousePress|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseRelease ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseRelease|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void clear ()
$method=|void|clear|

$prototype=void simulate ( QWidget * w )
$method=|void|simulate|QWidget *

$extraMethods

#pragma ENDDUMP

%%
%% Qt4xHb - Bindings libraries for Harbour/xHarbour and Qt Framework 4
%%
%% Copyright (C) 2018 Marcos Antonio Gambeta <marcosgambeta AT outlook DOT com>
%%

$header

#include "hbclass.ch"

$beginClass

   METHOD new
   METHOD delete
   METHOD addDelay
   METHOD addKeyClick1
   METHOD addKeyClick2
   METHOD addKeyClick
   METHOD addKeyClicks
   METHOD addKeyPress1
   METHOD addKeyPress2
   METHOD addKeyPress
   METHOD addKeyRelease1
   METHOD addKeyRelease2
   METHOD addKeyRelease
   METHOD addMouseClick
   METHOD addMouseDClick
   METHOD addMouseMove
   METHOD addMousePress
   METHOD addMouseRelease
   METHOD clear
   METHOD simulate

$endClass

$destructor

#pragma BEGINDUMP

$includes

$prototype=QTestEventList ()
$internalConstructor=|new1|

$prototype=QTestEventList ( const QTestEventList & other )
$internalConstructor=|new2|const QTestEventList &

//[1]QTestEventList ()
//[2]QTestEventList ( const QTestEventList & other )

HB_FUNC_STATIC( QTESTEVENTLIST_NEW )
{
  if( ISNUMPAR(0) )
  {
    QTestEventList_new1();
  }
  else if( ISNUMPAR(1) && ISQTESTEVENTLIST(1) )
  {
    QTestEventList_new2();
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$deleteMethod

$prototype=void addDelay ( int msecs )
$method=|void|addDelay|int

$prototype=void addKeyClick ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClick,addKeyClick1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyClick ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClick,addKeyClick2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

//[1]void addKeyClick ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
//[2]void addKeyClick ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYCLICK )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYCLICK1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYCLICK2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$prototype=void addKeyClicks ( const QString & keys, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyClicks|const QString &,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyPress ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyPress,addKeyPress1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyPress ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyPress,addKeyPress2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

//[1]void addKeyPress ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
//[2]void addKeyPress ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYPRESS )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYPRESS1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYPRESS2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$prototype=void addKeyRelease ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyRelease,addKeyRelease1|Qt::Key,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

$prototype=void addKeyRelease ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
$method=|void|addKeyRelease,addKeyRelease2|char,Qt::KeyboardModifiers=Qt::NoModifier,int=-1

//[1]void addKeyRelease ( Qt::Key qtKey, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )
//[2]void addKeyRelease ( char ascii, Qt::KeyboardModifiers modifiers = Qt::NoModifier, int msecs = -1 )

HB_FUNC_STATIC( QTESTEVENTLIST_ADDKEYRELEASE )
{
  if( ISBETWEEN(1,3) && ISNUM(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYRELEASE1 );
  }
  else if( ISBETWEEN(1,3) && ISCHAR(1) && (ISNUM(2)||ISNIL(2)) && (ISNUM(3)||ISNIL(3)) )
  {
    HB_FUNC_EXEC( QTESTEVENTLIST_ADDKEYRELEASE2 );
  }
  else
  {
    hb_errRT_BASE( EG_ARG, 3012, NULL, HB_ERR_FUNCNAME, HB_ERR_ARGS_BASEPARAMS );
  }
}

$prototype=void addMouseClick ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseClick|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseDClick ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseDClick|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseMove ( QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseMove|QPoint=QPoint(),int=-1

$prototype=void addMousePress ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMousePress|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void addMouseRelease ( Qt::MouseButton button, Qt::KeyboardModifiers modifiers = 0, QPoint pos = QPoint(), int delay = -1 )
$method=|void|addMouseRelease|Qt::MouseButton,Qt::KeyboardModifiers=0,QPoint=QPoint(),int=-1

$prototype=void clear ()
$method=|void|clear|

$prototype=void simulate ( QWidget * w )
$method=|void|simulate|QWidget *

$extraMethods

#pragma ENDDUMP


this is gone by renaming

this is gone by renaming

-- implement the idea described in
-- https://code.google.com/p/omega/wiki/IcebergTypes
--

import "../src/LangPrelude.prg" (maybeM)

data Thrist :: (l ~> l ~> *) ~> l ~> l ~> * where
  Nil :: Thrist k a a
  Cons :: k a b -> Thrist k b c -> Thrist k a c
 deriving List(t)

data Multiplicity :: *2 where
  Mono :: Multiplicity
  Poly :: Multiplicity

data Lev :: Multiplicity ~> *1 where
  ValueLevel :: Lev Mono
  LevelUp :: Lev m ~> Lev m
  PolyLevel :: Lev Poly -- level n .
 deriving syntax (lev) Nat(ValueLevel, LevelUp)

data Level :: Lev n ~> * where
  ValueLevel :: Level ValueLevel
  LevelUp :: Level l -> Level (LevelUp l)
  PolyLevel :: Level PolyLevel
 deriving syntax (l) Nat(ValueLevel, LevelUp)

data Signature :: * where
  Sig :: Signature -- some signature (for now)
  SigCtor :: Label t -> Signature
  SigFun :: Label t -> Signature
  SigVar :: Label t -> Signature
  SigApp :: Signature -> Signature -> Signature

data Iceberg :: * ~> * ~> * where
  Constructor :: Label t -> Level l -> Signature -> Iceberg () ()

data Icename :: Tag ~> Tag ~> * where -- entities with certain name
  NamedConstructor :: Label t -> Level l -> Signature -> Icename t t

data Icelevel :: Lev n ~> Lev n ~> * where -- entities with certain level
  LevelConstructor :: LevelFits l' l => Label t -> Level l -> Signature -> Icelevel l' l'

data TagLev :: Multiplicity ~> *1 where
  TL :: Tag ~> Lev m ~> TagLev m

data Icenamelevel :: TagLev n ~> TagLev n ~> * where -- entities with certain level and name
  NamedLevelConstructor :: LevelFits l' l => Label t -> Level l -> Signature -> Icenamelevel (TL t l') (TL t l')

builtIns :: Thrist Iceberg () ()
builtIns = [ Constructor `Z 0l $ SigApp natPrimeCtor (SigCtor `Z)
           , Constructor `S 0l $ SigApp (SigApp varrowCtor (SigApp natPrimeCtor $ SigVar `a)) (SigApp natPrimeCtor $ (SigApp (SigCtor `S) $ SigVar `a))
           , Constructor natPrime 0l $ SigApp (SigApp karrowCtor natCtor) starCtor
           , Constructor `Z 1l $ natCtor
           , Constructor `S 1l $ SigApp (SigApp karrowCtor natCtor) natCtor
           , Constructor `Nat 2l Sig
           , Constructor starN (LevelUp (LevelUp PolyLevel)) Sig
           , Constructor constraintN (LevelUp (LevelUp PolyLevel)) Sig
           , Constructor varrow 1l Sig
           , Constructor `MultValueAndUp PolyLevel Sig]t
  where HideLabel natPrime = newLabel "Nat'"
        HideLabel starN = newLabel "*n"
        HideLabel constraintN = newLabel "#n"
        HideLabel varrow = newLabel "->"
        HideLabel karrow = newLabel "~>"
        starCtor = SigCtor starN
        natPrimeCtor = SigCtor natPrime
        varrowCtor = SigCtor varrow
        karrowCtor = SigCtor karrow
        natCtor = SigCtor `Nat

projectName :: Label l -> Thrist Iceberg () () -> Thrist Icename l l
projectName _ []t = []t
projectName l [Constructor l' lev sig; rest]t = case l `sameLabel` l' of
                                                L Eq -> [NamedConstructor l' lev sig; projectName l rest]t
                                                _ -> projectName l rest

projectName' :: Label t -> Thrist Icelevel l l -> Thrist Icenamelevel (TL t l) (TL t l)
projectName' _ []t = []t
projectName' t [LevelConstructor t' lev sig; rest]t = case t `sameLabel` t' of
                                                      L Eq -> [NamedLevelConstructor t' lev sig; projectName' t rest]t
                                                      _ -> projectName' t rest

-- inclusion relation on levels
--
prop LevelFits :: Lev n ~> Lev n' ~> * where
  BothValue :: LevelFits ValueLevel ValueLevel
  InPoly :: LevelFits k PolyLevel
  BothUp :: LevelFits k k' -> LevelFits (LevelUp k) (LevelUp k')

-- runtime compute level inclusion
--
fits :: Level l -> Level l' -> Maybe (LevelFits l l')
fits ValueLevel ValueLevel = Just BothValue
fits (LevelUp l) (LevelUp l') = do ev <- fits l l'
                                   return $ BothUp ev
                                 where monad maybeM
fits _ PolyLevel = Just InPoly
fits _ _ = Nothing

multiplicity :: Multiplicity ~> Multiplicity ~> Multiplicity
{multiplicity Mono b} = Mono
{multiplicity Poly b} = b

unilev :: Lev a ~> Lev b ~> Lev {multiplicity a b}
{unilev ValueLevel ValueLevel} = ValueLevel
{unilev ValueLevel PolyLevel} = ValueLevel
{unilev (LevelUp a) (LevelUp b)} = LevelUp {unilev a b}
{unilev (LevelUp a) PolyLevel} = LevelUp {unilev a PolyLevel}
{unilev PolyLevel ValueLevel} = ValueLevel
{unilev PolyLevel (LevelUp b)} = LevelUp {unilev PolyLevel b}
{unilev PolyLevel PolyLevel} = PolyLevel

-- prove commutativity
--
unifyCommutes :: Level k -> Level l -> Equal {unilev k l} {unilev l k}
unifyCommutes ValueLevel ValueLevel = Eq
unifyCommutes ValueLevel PolyLevel = Eq
unifyCommutes (LevelUp a) (LevelUp b) = Eq where theorem hyp = unifyCommutes a b
unifyCommutes (LevelUp a) PolyLevel = Eq where theorem hyp = unifyCommutes a PolyLevel
unifyCommutes PolyLevel ValueLevel = Eq
unifyCommutes PolyLevel (LevelUp b) = Eq where theorem hyp = unifyCommutes PolyLevel b
unifyCommutes PolyLevel PolyLevel = Eq

unifyLevels :: Level k -> Level l -> Maybe (Level {unilev k l})
unifyLevels ValueLevel (LevelUp b) = Nothing
unifyLevels ValueLevel ValueLevel = Just ValueLevel
unifyLevels ValueLevel PolyLevel = Just ValueLevel
unifyLevels (LevelUp a) (LevelUp b) = do yes <- unifyLevels a b
                                         return $ LevelUp yes
                                       where monad maybeM
unifyLevels (LevelUp a) ValueLevel = Nothing
unifyLevels (LevelUp a) PolyLevel = do yes <- unifyLevels a PolyLevel
                                       return $ LevelUp yes
                                     where monad maybeM
unifyLevels PolyLevel ValueLevel = unifyLevels ValueLevel PolyLevel
unifyLevels PolyLevel (LevelUp b) = unifyLevels (LevelUp b) PolyLevel
  where theorem comm = unifyCommutes PolyLevel b
unifyLevels PolyLevel PolyLevel = Just PolyLevel

projectLevel :: Level l -> Thrist Iceberg () () -> Thrist Icelevel l l
projectLevel _ []t = []t
projectLevel l [Constructor t l' sig; rest]t = case l `fits` l' of
                                               Just BothValue -> [LevelConstructor t l' sig; projectLevel l rest]t
                                               Just InPoly -> [LevelConstructor t l' sig; projectLevel l rest]t
                                               Just (BothUp below) -> [LevelConstructor t l' sig; projectLevel l rest]t
                                               _ -> projectLevel l rest

projectLevel' :: Level l -> Thrist Icename t t -> Thrist Icenamelevel (TL t l) (TL t l)
projectLevel' _ []t = []t
projectLevel' l [NamedConstructor t l' sig; rest]t = case l `fits` l' of
                                                     Just BothValue -> [NamedLevelConstructor t l' sig; projectLevel' l rest]t
                                                     Just InPoly -> [NamedLevelConstructor t l' sig; projectLevel' l rest]t
                                                     Just (BothUp below) -> [NamedLevelConstructor t l' sig; projectLevel' l rest]t
                                                     _ -> projectLevel' l rest

data Levels :: Lev m ~> Lev m ~> * where
  InLevel :: Thrist Icelevel l l -> Levels l (1+l)l

t3 :: Thrist Levels 0l 2l
t3 = [InLevel $ projectLevel 0l builtIns, InLevel $ projectLevel 1l builtIns]t

fibrateLevels :: Level l -> Thrist Iceberg () () -> Thrist Levels l a
fibrateLevels l berg = [InLevel $ projectLevel l berg; lazy (fibrateLevels (1+l)l berg)]t

[t30, t31, t32, t33; t34]t = fibrateLevels 0l builtIns
[t40, t41, t42, t43; t44]t = fibrateLevels PolyLevel builtIns