Skip to content
← Back

src/ir/values/literal/number.ghul

1
namespace IR.Values.Literal is
2
use System.Reflection.Metadata.ILOpCode
3
use TypeTyped = Semantic.Types.Typed
4
use Semantic.Types.Type
5
6
// The constant a numeric literal loads, at the width it is loaded at.
7
//
8
// An integer is held at the width its load asks for rather than as a
9
// magnitude, because the two are not the same: `0xFF00FF00` is a
10
// `uint` in range, and the constant `ldc.i4` takes is the 32-bit
11
// pattern, which read as a magnitude is negative.
12
union CONSTANT is
13
I4(value: int)
14
I8(value: long)
15
R4(value: single)
16
R8(value: double)
17
si
18
19
// A numeric constant, held as the value rather than as the way it was
20
// written down. A source literal can be written in any radix and with
21
// any suffix, so the spelling and the value are not the same thing,
22
// and reading that spelling back is not something emission should
23
// have to do.
24
class NUMBER: Value, TypeTyped is
25
constant: CONSTANT
26
type: Type
27
28
// Narrows the loaded constant to the literal's declared type,
29
// where the width it is loaded at is wider than that type.
30
conv: ILOpCode?
31
32
is_lightweight_pure: bool => true
33
34
is_real: bool =>
35
case constant
36
when _: CONSTANT.R4 then true
37
when _: CONSTANT.R8 then true
38
else false
39
esac
40
41
// The constant written out, used to render an attribute
42
// argument and as a key for comparing case-arm constants.
43
rendered: string =>
44
case constant
45
when i4: CONSTANT.I4 then "{i4.value}"
46
when i8: CONSTANT.I8 then "{i8.value}"
47
when r4: CONSTANT.R4 then "{r4.value}"
48
when r8: CONSTANT.R8 then "{r8.value}"
49
esac
50
51
init(constant: CONSTANT, type: Type, conv: ILOpCode?) is
52
super.init()
53
54
self.constant = constant
55
self.type = type
56
self.conv = conv
57
si
58
59
init(constant: CONSTANT, type: Type) is
60
self.init(constant, type, null)
61
si
62
63
init(value: int, type: Type) is
64
self.init(CONSTANT.I4(value), type, null)
65
si
66
67
init(value: long, type: Type) is
68
self.init(CONSTANT.I8(value), type, null)
69
si
70
71
init(value: single, type: Type) is
72
self.init(CONSTANT.R4(value), type, null)
73
si
74
75
init(value: double, type: Type) is
76
self.init(CONSTANT.R8(value), type, null)
77
si
78
79
gen(context: IR.CONTEXT) is
80
let body = context.current_srm_body_emitter!
81
82
case constant
83
when i4: CONSTANT.I4 then body.ldc_i4(i4.value)
84
when i8: CONSTANT.I8 then body.ldc_i8(i8.value)
85
when r4: CONSTANT.R4 then body.ldc_r4(r4.value)
86
when r8: CONSTANT.R8 then body.ldc_r8(r8.value)
87
esac
88
89
if let narrowing = conv then
90
body.op(narrowing)
91
fi
92
si
93
94
to_string() -> string =>
95
"literal:[{type}]({constant})"
96
si
97
si