aboutsummaryrefslogtreecommitdiff
path: root/src/ARMeilleure/CodeGen/Linking/Symbol.cs
blob: 5559afe094cc3bc889bc4ead5b7ab5419f2d0d73 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
using System;

namespace ARMeilleure.CodeGen.Linking
{
    /// <summary>
    /// Represents a symbol.
    /// </summary>
    readonly struct Symbol
    {
        private readonly ulong _value;

        /// <summary>
        /// Gets the <see cref="SymbolType"/> of the <see cref="Symbol"/>.
        /// </summary>
        public SymbolType Type { get; }

        /// <summary>
        /// Gets the value of the <see cref="Symbol"/>.
        /// </summary>
        /// <exception cref="InvalidOperationException"><see cref="Type"/> is <see cref="SymbolType.None"/></exception>
        public ulong Value
        {
            get
            {
                if (Type == SymbolType.None)
                {
                    ThrowSymbolNone();
                }

                return _value;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Symbol"/> structure with the specified <see cref="SymbolType"/> and value.
        /// </summary>
        /// <param name="type">Type of symbol</param>
        /// <param name="value">Value of symbol</param>
        public Symbol(SymbolType type, ulong value)
        {
            (Type, _value) = (type, value);
        }

        /// <summary>
        /// Determines if the specified <see cref="Symbol"/> instances are equal.
        /// </summary>
        /// <param name="a">First instance</param>
        /// <param name="b">Second instance</param>
        /// <returns><see langword="true"/> if equal; otherwise <see langword="false"/></returns>
        public static bool operator ==(Symbol a, Symbol b)
        {
            return a.Equals(b);
        }

        /// <summary>
        /// Determines if the specified <see cref="Symbol"/> instances are not equal.
        /// </summary>
        /// <param name="a">First instance</param>
        /// <param name="b">Second instance</param>
        /// <returns><see langword="true"/> if not equal; otherwise <see langword="false"/></returns>
        public static bool operator !=(Symbol a, Symbol b)
        {
            return !(a == b);
        }

        /// <summary>
        /// Determines if the specified <see cref="Symbol"/> is equal to this <see cref="Symbol"/> instance.
        /// </summary>
        /// <param name="other">Other <see cref="Symbol"/> instance</param>
        /// <returns><see langword="true"/> if equal; otherwise <see langword="false"/></returns>
        public bool Equals(Symbol other)
        {
            return other.Type == Type && other._value == _value;
        }

        /// <inheritdoc/>
        public override bool Equals(object obj)
        {
            return obj is Symbol sym && Equals(sym);
        }

        /// <inheritdoc/>
        public override int GetHashCode()
        {
            return HashCode.Combine(Type, _value);
        }

        /// <inheritdoc/>
        public override string ToString()
        {
            return $"{Type}:{_value}";
        }

        private static void ThrowSymbolNone()
        {
            throw new InvalidOperationException("Symbol refers to nothing.");
        }
    }
}