Skip to content
← Back

src/semantic/symbols/method_override_class.ghul

1
namespace Semantic is
2
use IO.Std
3
4
use System.Text.StringBuilder
5
6
use Collections.Iterable
7
use Collections.Iterator
8
use Collections.List
9
use Collections.LIST
10
use Collections.MAP
11
use Collections.SET
12
13
use Symbols.Function
14
15
use Types.Type
16
17
use Ghul.Pipes
18
19
class METHOD_OVERRIDE_CLASS is
20
arguments: List[Type]
21
// Number of generic arguments. Functions only override / count as
22
// duplicates of siblings with the same generic-argument count;
23
// `foo()` and `foo[T]()` are distinct sibling functions, not one
24
// overriding the other and not a duplicate.
25
generic_arguments_count: int
26
27
// The method's own type parameters, in declaration order. Two
28
// declarations of the same generic method have parameters that
29
// are different symbols, so one side's arguments are read in
30
// the other's terms before they are compared.
31
generic_arguments: List[Type]
32
33
init(arguments: List[Type]) is
34
init(arguments, LIST[Type]())
35
si
36
37
init(arguments: List[Type], generic_arguments: List[Type]) is
38
assert arguments |> all(a => a?) else "override class arguments list contains null elements"
39
40
self.arguments = arguments
41
self.generic_arguments = generic_arguments
42
self.generic_arguments_count = generic_arguments.count
43
si
44
45
// Declared: the loop over each argument's `matches` is
46
// genuinely store-free, but the store-free walk disqualifies
47
// any function containing a `for` loop unconditionally rather
48
// than reasoning about the loop body.
49
=~(other: METHOD_OVERRIDE_CLASS) -> bool pure is
50
if other.generic_arguments_count != generic_arguments_count then
51
return false
52
fi
53
54
if other.arguments.count != arguments.count then
55
return false
56
fi
57
58
let theirs = _in_our_terms(other)
59
60
for i in 0..arguments.count do
61
if !arguments[i].matches(theirs[i]) then
62
return false
63
fi
64
od
65
66
return true
67
si
68
69
// `other`'s arguments with its own type parameters replaced by
70
// ours at the same position, so `describe[T](tag: T)` declared
71
// twice compares equal although each `T` is its own symbol.
72
_in_our_terms(other: METHOD_OVERRIDE_CLASS) -> List[Type] pure =>
73
Symbols.GENERIC_PARAMETER_ALIGNMENT.rewrite_all(
74
other.arguments, generic_arguments, other.generic_arguments)
75
76
equals(other: object?) -> bool is
77
if !other? then
78
return false
79
fi
80
81
if !isa METHOD_OVERRIDE_CLASS(other) then
82
return false
83
fi
84
85
return self =~ other
86
si
87
88
get_hash_code() -> int is
89
let result mut = generic_arguments_count
90
91
// A generic method's argument types mention its own type
92
// parameters, which are a different symbol in every
93
// declaration, so only the shape can contribute: two that
94
// compare equal have to hash equal.
95
if generic_arguments_count > 0 then
96
return result + arguments.count
97
fi
98
99
for a in arguments do
100
result = result + a.get_hash_code()
101
od
102
103
return result
104
si
105
106
to_string() -> string => "({arguments |> join(", ")})"
107
si
108
si