Skip to content
← Back

src/ir/values/sequence_equality.ghul

1
namespace IR.Values is
2
use System.Reflection.Metadata.ILOpCode
3
4
use Semantic.Types.Type
5
6
// `a =~ b` where both operands are a sequence - an array, or a
7
// list - compared by count and then element by element.
8
//
9
// The element comparison arrives already built against a load of
10
// the index local this node declares, so what the element type's
11
// equality is has been decided by the caller in the same way as for
12
// any other operand; this node only supplies the loop around it.
13
// Both counts are read twice, so they arrive as repeatable loads.
14
//
15
// <left count>
16
// <right count>
17
// ceq
18
// brfalse <unequal>
19
// ldc.i4.0
20
// stloc i
21
// <loop>:
22
// ldloc i
23
// <left count>
24
// bge <equal> // every element compared equal
25
// <element comparison> // reads a[i] and b[i] through the local
26
// brfalse <unequal>
27
// ldloc i
28
// ldc.i4.1
29
// add
30
// stloc i
31
// br <loop>
32
// <equal>:
33
// ldc.i4.1
34
// br <end>
35
// <unequal>:
36
// ldc.i4.0
37
// <end>:
38
class SEQUENCE_EQUALITY: Value is
39
left_count: Value
40
right_count: Value
41
index_name: string
42
index_type: Type
43
element_equals: Value
44
_result_type: Type
45
46
type: Type => _result_type
47
is_lightweight_pure: bool => false
48
49
init(
50
left_count: Value,
51
right_count: Value,
52
index_name: string,
53
index_type: Type,
54
element_equals: Value,
55
result_type: Type
56
) is
57
super.init()
58
59
self.left_count = left_count
60
self.right_count = right_count
61
self.index_name = index_name
62
self.index_type = index_type
63
self.element_equals = element_equals
64
self._result_type = result_type
65
si
66
67
gen(context: IR.CONTEXT) is
68
let loop_label = IR.LABEL()
69
let equal_label = IR.LABEL()
70
let unequal_label = IR.LABEL()
71
let end_label = IR.LABEL()
72
73
let body = context.current_srm_body_emitter!
74
75
body.declare_local(index_name, index_type)
76
77
gen(left_count, context)
78
gen(right_count, context)
79
body.op(ILOpCode.CEQ)
80
body.branch(ILOpCode.BRFALSE, unequal_label)
81
82
body.ldc_i4(0)
83
body.stloc(index_name)
84
85
body.mark_label(loop_label)
86
body.ldloc(index_name)
87
gen(left_count, context)
88
body.branch(ILOpCode.BGE, equal_label)
89
90
gen(element_equals, context)
91
body.branch(ILOpCode.BRFALSE, unequal_label)
92
93
body.ldloc(index_name)
94
body.ldc_i4(1)
95
body.op(ILOpCode.ADD)
96
body.stloc(index_name)
97
body.branch(ILOpCode.BR, loop_label)
98
99
body.mark_label(equal_label)
100
body.ldc_i4(1)
101
body.branch(ILOpCode.BR, end_label)
102
103
body.mark_label(unequal_label)
104
body.ldc_i4(0)
105
106
body.mark_label(end_label)
107
si
108
109
to_string() -> string =>
110
"sequence-equality:[{type}]({left_count},{right_count},{index_name},{element_equals})"
111
si
112
113
// `a =~ b` on two references of a class declaring neither `=~` nor
114
// `<>`: the same thing as `a == b`, reached from a synthesized
115
// comparison where the operator could not have been written.
116
class REFERENCE_EQUALITY: Value is
117
left: Value
118
right: Value
119
_result_type: Type
120
121
type: Type => _result_type
122
is_lightweight_pure: bool => false
123
124
init(left: Value, right: Value, result_type: Type) is
125
super.init()
126
127
self.left = left
128
self.right = right
129
self._result_type = result_type
130
si
131
132
gen(context: IR.CONTEXT) is
133
gen(left, context)
134
gen(right, context)
135
136
context.current_srm_body_emitter!.op(ILOpCode.CEQ)
137
si
138
139
to_string() -> string => "reference-equality:[{type}]({left},{right})"
140
si
141
si