Skip to content
← Back

src/syntax/process/compile-expressions/compile_literals.ghul

1
namespace Syntax.Process is
2
use Logging
3
4
use Semantic.Lookups.InnateSymbolLookup
5
use Semantic.Types.Type
6
7
use IR.Values
8
9
// Lowers literal and `_` (default-value) expressions to IR values.
10
// Split out of COMPILE_EXPRESSIONS, which delegates each
11
// visit(<literal>) here.
12
class COMPILE_LITERALS is
13
_logger: Logger
14
_innate_symbol_lookup: InnateSymbolLookup
15
_numeric_literal_classifier: NUMERIC_LITERAL_CLASSIFIER
16
_symbol_use_locations: Semantic.SYMBOL_USE_LOCATIONS
17
18
init(
19
logger: Logger,
20
innate_symbol_lookup: InnateSymbolLookup,
21
numeric_literal_classifier: NUMERIC_LITERAL_CLASSIFIER,
22
symbol_use_locations: Semantic.SYMBOL_USE_LOCATIONS
23
) is
24
super.init()
25
26
_logger = logger
27
_innate_symbol_lookup = innate_symbol_lookup
28
_numeric_literal_classifier = numeric_literal_classifier
29
_symbol_use_locations = symbol_use_locations
30
si
31
32
visit_integer(integer: Trees.Expressions.Literals.INTEGER) is
33
let value = _numeric_literal_classifier.classify(integer.location, integer.value_string)
34
35
if !value? then
36
integer.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), integer.location)
37
return
38
fi
39
40
integer.compile_expressions_state.value = value
41
si
42
43
visit_float(float: Trees.Expressions.Literals.FLOAT) is
44
let value_string = float.value_string
45
let kind = FLOAT_LITERAL_SUFFIX.kind(value_string)
46
let stripped = FLOAT_LITERAL_SUFFIX.strip(value_string)
47
48
if kind == FloatLiteralKind.DECIMAL then
49
if stripped.contains('e') \/ stripped.contains('E') then
50
_logger.error(float.location, "exponent notation not supported in decimal literal")
51
float.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), float.location)
52
return
53
fi
54
55
let decomp = Literal.DECIMAL.decompose(stripped)
56
57
if decomp.error? then
58
_logger.error(float.location, decomp.error!)
59
float.compile_expressions_state.value = DUMMY(Semantic.Types.ERROR(), float.location)
60
return
61
fi
62
63
float.compile_expressions_state.value = Literal.DECIMAL(
64
stripped,
65
_innate_symbol_lookup.get_decimal_type(),
66
decomp.lo,
67
decomp.mid,
68
decomp.hi,
69
decomp.scale
70
)
71
return
72
fi
73
74
let is_single = kind == FloatLiteralKind.SINGLE
75
76
let type =
77
if is_single then
78
_innate_symbol_lookup.get_single_type()
79
else
80
_innate_symbol_lookup.get_double_type()
81
fi
82
83
let parsed: double mut = _
84
85
if !double.try_parse(stripped, parsed ref) then
86
_logger.error(float.location, "invalid floating-point literal {stripped}")
87
return
88
fi
89
90
float.compile_expressions_state.value =
91
Literal.NUMBER(
92
if is_single then
93
Literal.CONSTANT.R4(cast single(parsed))
94
else
95
Literal.CONSTANT.R8(parsed)
96
fi,
97
type
98
)
99
si
100
101
visit_interpolation(interpolation: Trees.Expressions.STRING_INTERPOLATION) is
102
interpolation.compile_expressions_state.value = IR.Values.BLOCK(_innate_symbol_lookup.get_string_type())
103
si
104
105
visit_string(`string: Trees.Expressions.Literals.STRING) is
106
`string.compile_expressions_state.value = Literal.STRING(
107
`string.value_string,
108
_innate_symbol_lookup.get_string_type()
109
)
110
si
111
112
visit_character(character: Trees.Expressions.Literals.CHARACTER) is
113
let value_string = character.value_string
114
let c: int mut = 0
115
116
if value_string.length < 1 \/ value_string.length > 1 then
117
_logger.error(character.location, "invalid character literal")
118
else
119
c = cast int(value_string[0])
120
fi
121
122
character.compile_expressions_state.value = Literal.NUMBER(
123
c,
124
_innate_symbol_lookup.get_char_type()
125
)
126
si
127
128
visit_boolean(boolean: Trees.Expressions.Literals.BOOLEAN) is
129
let value_string = boolean.value_string
130
131
let value: int mut
132
133
if value_string =~ "true" then
134
value = 1
135
elif value_string =~ "false" then
136
value = 0
137
else
138
throw System.Exception("invalid value for boolean literal: {value_string}")
139
fi
140
141
boolean.compile_expressions_state.value = Literal.NUMBER(
142
value,
143
_innate_symbol_lookup.get_bool_type()
144
)
145
si
146
147
visit_default(`default: Trees.Expressions.DEFAULT) is
148
// `_[T]` pins the type explicitly; a bare `_` takes the
149
// type pushed in by the parent context (assignment RHS,
150
// return position, typed `let` initializer, call
151
// argument) via set_constraint.
152
let type: Semantic.Types.Type? mut = _
153
154
if `default.type_expression? then
155
type = `default.type_expression.type
156
elif `default.expected_type? then
157
type = `default.expected_type
158
fi
159
160
if !type? then
161
_logger.error(`default.location, "cannot infer type of default here")
162
`default.compile_expressions_state.value = IR.Values.DUMMY(Semantic.Types.ERROR(), `default.location)
163
return
164
fi
165
166
if type.is_error then
167
`default.compile_expressions_state.value = IR.Values.DUMMY(type, `default.location)
168
return
169
fi
170
171
// A bare `_` never names its type, so hover over it is the
172
// only place the reader can see what the context settled
173
// on. `_[T]` says it already.
174
if !`default.type_expression? then
175
_symbol_use_locations.add_inferred_type_hover(`default.location, type)
176
fi
177
178
// A `_` for a `T ref` slot discards what the callee writes: it
179
// is the address of a fresh local holding the default of `T`,
180
// never a null reference the callee would write through.
181
if let reference: Semantic.Types.REFERENCE = type then
182
`default.compile_expressions_state.value = IR.Values.ADDRESS(IR.Values.DEFAULT(reference.arguments[0]), type)
183
return
184
fi
185
186
`default.compile_expressions_state.value = IR.Values.DEFAULT(type)
187
si
188
si
189
si